commit 7840ad9ce4bf788a4b87b00611a50bbc5fe0d5c3
parent d85a5f64f1c25835b1ce46bf596dfece18dd18c0
Author: triesap <tyson@radroots.org>
Date: Sun, 4 Jan 2026 00:55:13 +0000
profile: add Any profile type and omit null relay fields
- Add radroots:type:any tag constant and RadrootsProfileType::Any variant
- Update tag parsing/mapping and emit/ingest handling for \"any\" profile type
- Extend codec tests to assert metadata reads Any profile type tag
- Skip serializing relay document optional fields when None
Diffstat:
7 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/events-codec/tests/profile.rs b/events-codec/tests/profile.rs
@@ -2,7 +2,12 @@
use radroots_events::{
kinds::KIND_POST,
- profile::{RadrootsProfileType, RADROOTS_PROFILE_TYPE_TAG_FARM, RADROOTS_PROFILE_TYPE_TAG_KEY},
+ profile::{
+ RadrootsProfileType,
+ RADROOTS_PROFILE_TYPE_TAG_ANY,
+ RADROOTS_PROFILE_TYPE_TAG_FARM,
+ RADROOTS_PROFILE_TYPE_TAG_KEY,
+ },
};
use radroots_events_codec::error::EventParseError;
use radroots_events_codec::profile::decode::profile_from_content;
@@ -76,3 +81,21 @@ fn profile_metadata_reads_profile_type_tag() {
assert_eq!(metadata.profile_type, Some(RadrootsProfileType::Farm));
}
+
+#[test]
+fn profile_metadata_reads_profile_type_any_tag() {
+ let metadata = radroots_events_codec::profile::decode::metadata_from_event(
+ "id".to_string(),
+ "author".to_string(),
+ 1,
+ 0,
+ "{\"name\":\"alice\"}".to_string(),
+ vec![vec![
+ RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
+ RADROOTS_PROFILE_TYPE_TAG_ANY.to_string(),
+ ]],
+ )
+ .expect("metadata");
+
+ assert_eq!(metadata.profile_type, Some(RadrootsProfileType::Any));
+}
diff --git a/events/bindings/ts/src/types.ts b/events/bindings/ts/src/types.ts
@@ -1,5 +1,3 @@
-import type { RadrootsCoreDecimal, RadrootsCoreDiscount, RadrootsCoreDiscountValue, RadrootsCoreMoney, RadrootsCorePercent, RadrootsCoreQuantity, RadrootsCoreQuantityPrice, RadrootsCoreUnit } from "@radroots/core-bindings";
-
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type JobFeedbackStatus = "payment_required" | "processing" | "error" | "success" | "partial";
@@ -176,7 +174,7 @@ export type RadrootsProfileEventIndex = { event: RadrootsNostrEvent, metadata: R
export type RadrootsProfileEventMetadata = { id: string, author: string, published_at: number, kind: number, profile_type?: RadrootsProfileType | null, profile: RadrootsProfile, };
-export type RadrootsProfileType = "individual" | "farm" | "coop";
+export type RadrootsProfileType = "individual" | "farm" | "coop" | "any";
export type RadrootsReaction = { root: RadrootsNostrEventRef, content: string, };
diff --git a/events/src/profile.rs b/events/src/profile.rs
@@ -9,6 +9,7 @@ pub const RADROOTS_PROFILE_TYPE_TAG_KEY: &str = "t";
pub const RADROOTS_PROFILE_TYPE_TAG_INDIVIDUAL: &str = "radroots:type:individual";
pub const RADROOTS_PROFILE_TYPE_TAG_FARM: &str = "radroots:type:farm";
pub const RADROOTS_PROFILE_TYPE_TAG_COOP: &str = "radroots:type:coop";
+pub const RADROOTS_PROFILE_TYPE_TAG_ANY: &str = "radroots:type:any";
#[cfg_attr(feature = "ts-rs", derive(TS))]
#[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))]
@@ -19,6 +20,7 @@ pub enum RadrootsProfileType {
Individual,
Farm,
Coop,
+ Any,
}
pub fn radroots_profile_type_tag_value(profile_type: RadrootsProfileType) -> &'static str {
@@ -26,6 +28,7 @@ pub fn radroots_profile_type_tag_value(profile_type: RadrootsProfileType) -> &'s
RadrootsProfileType::Individual => RADROOTS_PROFILE_TYPE_TAG_INDIVIDUAL,
RadrootsProfileType::Farm => RADROOTS_PROFILE_TYPE_TAG_FARM,
RadrootsProfileType::Coop => RADROOTS_PROFILE_TYPE_TAG_COOP,
+ RadrootsProfileType::Any => RADROOTS_PROFILE_TYPE_TAG_ANY,
}
}
@@ -34,6 +37,7 @@ pub fn radroots_profile_type_from_tag_value(value: &str) -> Option<RadrootsProfi
RADROOTS_PROFILE_TYPE_TAG_INDIVIDUAL => Some(RadrootsProfileType::Individual),
RADROOTS_PROFILE_TYPE_TAG_FARM => Some(RadrootsProfileType::Farm),
RADROOTS_PROFILE_TYPE_TAG_COOP => Some(RadrootsProfileType::Coop),
+ RADROOTS_PROFILE_TYPE_TAG_ANY => Some(RadrootsProfileType::Any),
_ => None,
}
}
diff --git a/events/src/relay_document.rs b/events/src/relay_document.rs
@@ -9,18 +9,25 @@ use alloc::{string::String, vec::Vec};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub struct RadrootsRelayDocument {
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub name: Option<String>,
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub description: Option<String>,
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub pubkey: Option<String>,
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub contact: Option<String>,
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "number[] | null"))]
pub supported_nips: Option<Vec<u16>>,
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub software: Option<String>,
+ #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub version: Option<String>,
}
diff --git a/tangle-events/src/emit.rs b/tangle-events/src/emit.rs
@@ -657,6 +657,7 @@ fn profile_event(
"individual" | "farmer" => Some(RadrootsProfileType::Individual),
"farm" => Some(RadrootsProfileType::Farm),
"coop" => Some(RadrootsProfileType::Coop),
+ "any" => Some(RadrootsProfileType::Any),
other => radroots_profile_type_from_tag_value(other),
};
let profile_event = RadrootsProfile {
diff --git a/tangle-events/src/ingest.rs b/tangle-events/src/ingest.rs
@@ -220,6 +220,7 @@ fn ingest_profile_event<E: SqlExecutor>(
radroots_events::profile::RadrootsProfileType::Individual => "individual",
radroots_events::profile::RadrootsProfileType::Farm => "farm",
radroots_events::profile::RadrootsProfileType::Coop => "coop",
+ radroots_events::profile::RadrootsProfileType::Any => "any",
};
let existing = nostr_profile::find_one(
diff --git a/trade/bindings/ts/src/types.ts b/trade/bindings/ts/src/types.ts
@@ -1,7 +1,3 @@
-import type { RadrootsListingImage, RadrootsNostrEventPtr, RadrootsPlotRef, RadrootsResourceAreaRef } from "@radroots/events-bindings";
-
-import type { RadrootsCoreCurrency, RadrootsCoreDecimal, RadrootsCoreDiscount, RadrootsCoreDiscountValue, RadrootsCoreMoney, RadrootsCoreQuantity, RadrootsCoreQuantityPrice, RadrootsCoreUnit } from "@radroots/core-bindings";
-
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type RadrootsListing = { d_tag: string, farm: RadrootsListingFarmRef, product: RadrootsListingProduct, primary_bin_id: string, bins: Array<RadrootsListingBin>, resource_area?: RadrootsResourceAreaRef | null, plot?: RadrootsPlotRef | null, discounts?: RadrootsCoreDiscount[] | null, inventory_available?: RadrootsCoreDecimal | null, availability?: RadrootsListingAvailability | null, delivery_method?: RadrootsListingDeliveryMethod | null, location?: RadrootsListingLocation | null, images?: RadrootsListingImage[] | null, };