commit 71056fb411855287751e99ee63fb8acd71ce96ac
parent 9364af59dc39a4b25021c0d9fb33da30499ef832
Author: triesap <tyson@radroots.org>
Date: Wed, 24 Jun 2026 08:42:43 +0000
trade: use manual dto listing descriptors
Diffstat:
3 files changed, 245 insertions(+), 43 deletions(-)
diff --git a/crates/trade/src/dto.rs b/crates/trade/src/dto.rs
@@ -1,4 +1,7 @@
-use dto_bindgen_core::RootDescriptor;
+use dto_bindgen_core::{
+ BackendId, DescribeCtx, Dto, FieldDef, IdentName, RootDescriptor, RustTypeId, SourceSpan,
+ StructDef, TargetFieldNames, TargetOverride, TypeDef, TypeRef, WireFieldNames,
+};
use crate::listing::{
model::{RadrootsTradeListingSubtotal, RadrootsTradeListingTotal},
@@ -13,9 +16,207 @@ pub fn dto_roots() -> [RootDescriptor; 3] {
]
}
+impl Dto for RadrootsTradeListing {
+ fn describe(ctx: &mut DescribeCtx) -> TypeRef {
+ let def = StructDef::new(
+ "RadrootsTradeListing",
+ "RadrootsTradeListing",
+ span("crates/trade/src/listing/validation.rs", 25),
+ )
+ .with_field(field(
+ "listing_id",
+ "listing_id",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 26,
+ ))
+ .with_field(field(
+ "listing_addr",
+ "listing_addr",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 27,
+ ))
+ .with_field(field(
+ "seller_pubkey",
+ "seller_pubkey",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 28,
+ ))
+ .with_field(field(
+ "title",
+ "title",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 29,
+ ))
+ .with_field(field(
+ "description",
+ "description",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 30,
+ ))
+ .with_field(field(
+ "product_type",
+ "product_type",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 31,
+ ))
+ .with_field(field(
+ "primary_bin_id",
+ "primary_bin_id",
+ String::describe(ctx),
+ "crates/trade/src/listing/validation.rs",
+ 32,
+ ))
+ .with_field(field(
+ "bin_quantity",
+ "bin_quantity",
+ ts_ref("RadrootsCoreQuantity"),
+ "crates/trade/src/listing/validation.rs",
+ 33,
+ ))
+ .with_field(field(
+ "unit",
+ "unit",
+ ts_ref("RadrootsCoreUnit"),
+ "crates/trade/src/listing/validation.rs",
+ 34,
+ ))
+ .with_field(field(
+ "unit_price",
+ "unit_price",
+ ts_ref("RadrootsCoreMoney"),
+ "crates/trade/src/listing/validation.rs",
+ 35,
+ ))
+ .with_field(field(
+ "inventory_available",
+ "inventory_available",
+ ts_ref("RadrootsCoreDecimal"),
+ "crates/trade/src/listing/validation.rs",
+ 36,
+ ))
+ .with_field(field(
+ "availability",
+ "availability",
+ ts_ref("RadrootsListingAvailability"),
+ "crates/trade/src/listing/validation.rs",
+ 37,
+ ))
+ .with_field(field(
+ "location",
+ "location",
+ ts_ref("RadrootsListingLocation"),
+ "crates/trade/src/listing/validation.rs",
+ 38,
+ ))
+ .with_field(field(
+ "delivery_method",
+ "delivery_method",
+ ts_ref("RadrootsListingDeliveryMethod"),
+ "crates/trade/src/listing/validation.rs",
+ 39,
+ ))
+ .with_field(field(
+ "listing",
+ "listing",
+ ts_ref("RadrootsListing"),
+ "crates/trade/src/listing/validation.rs",
+ 40,
+ ));
+ register(ctx, "RadrootsTradeListing", TypeDef::Struct(def))
+ }
+}
+
+impl Dto for RadrootsTradeListingSubtotal {
+ fn describe(ctx: &mut DescribeCtx) -> TypeRef {
+ trade_listing_total_like(
+ ctx,
+ "RadrootsTradeListingSubtotal",
+ "crates/trade/src/listing/model.rs",
+ 3,
+ )
+ }
+}
+
+impl Dto for RadrootsTradeListingTotal {
+ fn describe(ctx: &mut DescribeCtx) -> TypeRef {
+ trade_listing_total_like(
+ ctx,
+ "RadrootsTradeListingTotal",
+ "crates/trade/src/listing/model.rs",
+ 12,
+ )
+ }
+}
+
+fn trade_listing_total_like(
+ ctx: &mut DescribeCtx,
+ rust_ident: &str,
+ file: &str,
+ line: u32,
+) -> TypeRef {
+ let def = StructDef::new(rust_ident, rust_ident, span(file, line))
+ .with_field(field(
+ "price_amount",
+ "price_amount",
+ ts_ref("RadrootsCoreMoney"),
+ file,
+ line + 1,
+ ))
+ .with_field(field(
+ "price_currency",
+ "price_currency",
+ ts_ref("RadrootsCoreCurrency"),
+ file,
+ line + 2,
+ ))
+ .with_field(field(
+ "quantity_amount",
+ "quantity_amount",
+ ts_ref("RadrootsCoreDecimal"),
+ file,
+ line + 3,
+ ))
+ .with_field(field(
+ "quantity_unit",
+ "quantity_unit",
+ ts_ref("RadrootsCoreUnit"),
+ file,
+ line + 4,
+ ));
+ register(ctx, rust_ident, TypeDef::Struct(def))
+}
+
+fn register(ctx: &mut DescribeCtx, rust_ident: &str, type_def: TypeDef) -> TypeRef {
+ ctx.register_type(RustTypeId::new("radroots_trade", rust_ident), type_def)
+}
+
+fn ts_ref(target_type: &str) -> TypeRef {
+ TypeRef::Override(TargetOverride::new(BackendId::TypeScript, target_type))
+}
+
+fn field(rust_name: &str, wire_name: &str, ty: TypeRef, file: &str, line: u32) -> FieldDef {
+ FieldDef::new(
+ IdentName::new(rust_name),
+ WireFieldNames::same(wire_name),
+ TargetFieldNames::new(wire_name, rust_name),
+ ty,
+ span(file, line),
+ )
+}
+
+fn span(file: &str, line: u32) -> SourceSpan {
+ SourceSpan::new(file, line, 1)
+}
+
#[cfg(test)]
mod tests {
- use dto_bindgen_core::{Registry, TypeDef, build_registry};
+ use dto_bindgen_core::{BackendId, Registry, StructDef, TypeDef, TypeRef, build_registry};
use super::dto_roots;
@@ -24,30 +225,6 @@ mod tests {
"RadrootsTradeListingSubtotal",
"RadrootsTradeListingTotal",
];
- const TRADE_IMPORTED_SOURCE_DEPENDENCIES: &[&str] = &[
- "RadrootsCoreDecimal",
- "RadrootsCoreDiscount",
- "RadrootsCoreDiscountScope",
- "RadrootsCoreDiscountThreshold",
- "RadrootsCoreDiscountValue",
- "RadrootsCoreMoney",
- "RadrootsCorePercent",
- "RadrootsCoreQuantity",
- "RadrootsCoreQuantityPrice",
- "RadrootsCoreUnit",
- "RadrootsFarmRef",
- "RadrootsListing",
- "RadrootsListingAvailability",
- "RadrootsListingBin",
- "RadrootsListingDeliveryMethod",
- "RadrootsListingImage",
- "RadrootsListingImageSize",
- "RadrootsListingLocation",
- "RadrootsListingProduct",
- "RadrootsListingStatus",
- "RadrootsPlotRef",
- "RadrootsResourceAreaRef",
- ];
#[test]
fn trade_descriptor_roots_build_registry() {
@@ -69,15 +246,23 @@ mod tests {
}
#[test]
- fn trade_source_dependencies_are_explicit() {
+ fn trade_source_fields_use_package_aliases_for_import_boundaries() {
let registry = build_registry(dto_roots());
- let mut dependencies = type_export_names(®istry)
- .into_iter()
- .filter(|name| !TRADE_SOURCE_ROOTS.contains(name))
- .collect::<Vec<_>>();
- dependencies.sort();
+ let listing = find_struct(®istry, "RadrootsTradeListing");
+ let subtotal = find_struct(®istry, "RadrootsTradeListingSubtotal");
- assert_eq!(dependencies, TRADE_IMPORTED_SOURCE_DEPENDENCIES);
+ assert_eq!(
+ typescript_override_target(field_ty(listing, "inventory_available")),
+ Some("RadrootsCoreDecimal")
+ );
+ assert_eq!(
+ typescript_override_target(field_ty(listing, "listing")),
+ Some("RadrootsListing")
+ );
+ assert_eq!(
+ typescript_override_target(field_ty(subtotal, "price_currency")),
+ Some("RadrootsCoreCurrency")
+ );
}
fn root_export_names(registry: &Registry) -> Vec<&str> {
@@ -93,18 +278,38 @@ mod tests {
.collect()
}
- fn type_export_names(registry: &Registry) -> Vec<&str> {
+ fn type_export_name(def: &TypeDef) -> &str {
+ match def {
+ TypeDef::Struct(def) => def.export_name.as_str(),
+ TypeDef::Enum(def) => def.export_name.as_str(),
+ }
+ }
+
+ fn find_struct<'a>(registry: &'a Registry, export_name: &str) -> &'a StructDef {
registry
.types_by_id
.values()
- .map(type_export_name)
- .collect::<Vec<_>>()
+ .find_map(|def| match def {
+ TypeDef::Struct(def) if def.export_name == export_name => Some(def),
+ _ => None,
+ })
+ .expect("descriptor struct")
}
- fn type_export_name(def: &TypeDef) -> &str {
- match def {
- TypeDef::Struct(def) => def.export_name.as_str(),
- TypeDef::Enum(def) => def.export_name.as_str(),
+ fn field_ty<'a>(def: &'a StructDef, field_name: &str) -> &'a TypeRef {
+ &def.fields
+ .iter()
+ .find(|field| field.target.typescript == field_name)
+ .expect("descriptor field")
+ .ty
+ }
+
+ fn typescript_override_target(ty: &TypeRef) -> Option<&str> {
+ match ty {
+ TypeRef::Override(target) if target.backend == BackendId::TypeScript => {
+ Some(target.target_type.as_str())
+ }
+ _ => None,
}
}
}
diff --git a/crates/trade/src/listing/model.rs b/crates/trade/src/listing/model.rs
@@ -1,4 +1,3 @@
-#[cfg_attr(feature = "dto-bindgen", derive(dto_bindgen::Dto))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RadrootsTradeListingSubtotal {
@@ -8,7 +7,6 @@ pub struct RadrootsTradeListingSubtotal {
pub quantity_unit: radroots_core::RadrootsCoreUnit,
}
-#[cfg_attr(feature = "dto-bindgen", derive(dto_bindgen::Dto))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RadrootsTradeListingTotal {
diff --git a/crates/trade/src/listing/validation.rs b/crates/trade/src/listing/validation.rs
@@ -20,7 +20,6 @@ use radroots_events::{
use crate::listing::codec::listing_from_event_parts;
-#[cfg_attr(feature = "dto-bindgen", derive(dto_bindgen::Dto))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub struct RadrootsTradeListing {