sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

commit 2e11d8e70521579b908b500188f3cf3e208ec7e9
parent 8b066007fe786980863e1687763b42dc738f9c99
Author: triesap <tyson@radroots.org>
Date:   Wed, 24 Jun 2026 08:30:26 +0000

trade: inventory binding type surface

Diffstat:
Mcrates/trade_bindings/src/lib.rs | 327++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 326 insertions(+), 1 deletion(-)

diff --git a/crates/trade_bindings/src/lib.rs b/crates/trade_bindings/src/lib.rs @@ -4,9 +4,159 @@ mod model; pub use model::types_module; +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum TradeTypeDisposition { + SourceTradeRoot, + EventsBindingImport, + SdkLocalPackageShape, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct TradeTypeInventoryEntry { + pub export_name: &'static str, + pub disposition: TradeTypeDisposition, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum TradeLargeIntegerPolicy { + JsonNumberSafeCount, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct TradeLargeIntegerPolicyEntry { + pub type_name: &'static str, + pub field_name: &'static str, + pub policy: TradeLargeIntegerPolicy, +} + +pub const TRADE_TYPE_INVENTORY: &[TradeTypeInventoryEntry] = &[ + event_import("RadrootsFarmRef"), + event_import("RadrootsListing"), + event_import("RadrootsListingAvailability"), + event_import("RadrootsListingBin"), + event_import("RadrootsListingDeliveryMethod"), + event_import("RadrootsListingLocation"), + event_import("RadrootsListingProduct"), + event_import("RadrootsListingStatus"), + local_shape("RadrootsTradeFacetCount"), + source_root("RadrootsTradeListing"), + local_shape("RadrootsTradeListingBackofficeOverlay"), + local_shape("RadrootsTradeListingBackofficeQuery"), + local_shape("RadrootsTradeListingBackofficeView"), + local_shape("RadrootsTradeListingBinProjection"), + local_shape("RadrootsTradeListingFacets"), + local_shape("RadrootsTradeListingMarketStatus"), + local_shape("RadrootsTradeListingProjection"), + local_shape("RadrootsTradeListingQuery"), + local_shape("RadrootsTradeListingSort"), + local_shape("RadrootsTradeListingSortField"), + source_root("RadrootsTradeListingSubtotal"), + source_root("RadrootsTradeListingTotal"), + local_shape("RadrootsTradeMarketplaceListingSummary"), + local_shape("RadrootsTradeMarketplaceOrderSummary"), + event_import("RadrootsTradeMessageType"), + local_shape("RadrootsTradeModerationFlag"), + local_shape("RadrootsTradeModerationSeverity"), + local_shape("RadrootsTradeModerationStatus"), + local_shape("RadrootsTradeOrderBackofficeOverlay"), + local_shape("RadrootsTradeOrderBackofficeQuery"), + local_shape("RadrootsTradeOrderBackofficeView"), + local_shape("RadrootsTradeOrderFacets"), + local_shape("RadrootsTradeOrderQuery"), + local_shape("RadrootsTradeOrderSort"), + local_shape("RadrootsTradeOrderSortField"), + event_import("RadrootsTradeOrderStatus"), + local_shape("RadrootsTradeOrderWorkflowMessage"), + local_shape("RadrootsTradeOrderWorkflowProjection"), + local_shape("RadrootsTradeReviewPriority"), + local_shape("RadrootsTradeReviewQueueEntry"), + local_shape("RadrootsTradeReviewStatus"), + local_shape("RadrootsTradeSortDirection"), +]; + +pub const TRADE_LARGE_INTEGER_POLICIES: &[TradeLargeIntegerPolicyEntry] = &[ + json_number_safe_count("RadrootsTradeFacetCount", "count"), + json_number_safe_count( + "RadrootsTradeListingBackofficeView", + "open_moderation_flag_count", + ), + json_number_safe_count("RadrootsTradeListingProjection", "order_count"), + json_number_safe_count("RadrootsTradeListingProjection", "open_order_count"), + json_number_safe_count("RadrootsTradeListingProjection", "terminal_order_count"), + json_number_safe_count("RadrootsTradeMarketplaceListingSummary", "order_count"), + json_number_safe_count("RadrootsTradeMarketplaceListingSummary", "open_order_count"), + json_number_safe_count( + "RadrootsTradeMarketplaceListingSummary", + "terminal_order_count", + ), + json_number_safe_count("RadrootsTradeMarketplaceOrderSummary", "item_count"), + json_number_safe_count("RadrootsTradeMarketplaceOrderSummary", "total_bin_count"), + json_number_safe_count( + "RadrootsTradeOrderBackofficeView", + "open_moderation_flag_count", + ), + json_number_safe_count("RadrootsTradeOrderWorkflowProjection", "question_count"), + json_number_safe_count("RadrootsTradeOrderWorkflowProjection", "answer_count"), + json_number_safe_count("RadrootsTradeOrderWorkflowProjection", "revision_count"), + json_number_safe_count( + "RadrootsTradeOrderWorkflowProjection", + "discount_request_count", + ), + json_number_safe_count( + "RadrootsTradeOrderWorkflowProjection", + "discount_offer_count", + ), + json_number_safe_count( + "RadrootsTradeOrderWorkflowProjection", + "discount_accept_count", + ), + json_number_safe_count( + "RadrootsTradeOrderWorkflowProjection", + "discount_decline_count", + ), + json_number_safe_count("RadrootsTradeOrderWorkflowProjection", "cancellation_count"), +]; + +const fn source_root(export_name: &'static str) -> TradeTypeInventoryEntry { + TradeTypeInventoryEntry { + export_name, + disposition: TradeTypeDisposition::SourceTradeRoot, + } +} + +const fn event_import(export_name: &'static str) -> TradeTypeInventoryEntry { + TradeTypeInventoryEntry { + export_name, + disposition: TradeTypeDisposition::EventsBindingImport, + } +} + +const fn local_shape(export_name: &'static str) -> TradeTypeInventoryEntry { + TradeTypeInventoryEntry { + export_name, + disposition: TradeTypeDisposition::SdkLocalPackageShape, + } +} + +const fn json_number_safe_count( + type_name: &'static str, + field_name: &'static str, +) -> TradeLargeIntegerPolicyEntry { + TradeLargeIntegerPolicyEntry { + type_name, + field_name, + policy: TradeLargeIntegerPolicy::JsonNumberSafeCount, + } +} + #[cfg(test)] mod tests { - use super::types_module; + use super::{ + TRADE_LARGE_INTEGER_POLICIES, TRADE_TYPE_INVENTORY, TradeTypeDisposition, types_module, + }; + + const TRADE_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/trade-bindings/src/generated/types.ts"); #[test] fn preserves_trade_type_exports() { @@ -15,4 +165,179 @@ mod tests { assert!(rendered.contains("export type RadrootsTradeOrderWorkflowProjection")); assert!(rendered.contains("export type RadrootsTradeMarketplaceOrderSummary")); } + + #[test] + fn trade_type_inventory_matches_current_package_surface() { + let actual = type_inventory(TRADE_BINDINGS_TYPES_TS); + let expected = TRADE_TYPE_INVENTORY + .iter() + .map(|entry| entry.export_name) + .collect::<Vec<_>>(); + + assert_eq!(actual, expected); + } + + #[test] + fn source_owned_trade_support_types_are_marked_for_event_import() { + for export_name in [ + "RadrootsFarmRef", + "RadrootsListing", + "RadrootsListingAvailability", + "RadrootsListingBin", + "RadrootsListingDeliveryMethod", + "RadrootsListingLocation", + "RadrootsListingProduct", + "RadrootsListingStatus", + "RadrootsTradeMessageType", + "RadrootsTradeOrderStatus", + ] { + assert_eq!( + disposition(export_name), + TradeTypeDisposition::EventsBindingImport + ); + } + } + + #[test] + fn trade_source_roots_are_marked_for_source_registry() { + let source_roots = TRADE_TYPE_INVENTORY + .iter() + .filter(|entry| entry.disposition == TradeTypeDisposition::SourceTradeRoot) + .map(|entry| entry.export_name) + .collect::<Vec<_>>(); + + assert_eq!( + source_roots, + [ + "RadrootsTradeListing", + "RadrootsTradeListingSubtotal", + "RadrootsTradeListingTotal" + ] + ); + } + + #[test] + fn trade_large_integer_policy_covers_current_count_fields() { + let actual = TRADE_LARGE_INTEGER_POLICIES + .iter() + .map(|entry| (entry.type_name, entry.field_name, entry.policy)) + .collect::<Vec<_>>(); + + assert_eq!( + actual, + [ + ( + "RadrootsTradeFacetCount", + "count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeListingBackofficeView", + "open_moderation_flag_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeListingProjection", + "order_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeListingProjection", + "open_order_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeListingProjection", + "terminal_order_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeMarketplaceListingSummary", + "order_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeMarketplaceListingSummary", + "open_order_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeMarketplaceListingSummary", + "terminal_order_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeMarketplaceOrderSummary", + "item_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeMarketplaceOrderSummary", + "total_bin_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderBackofficeView", + "open_moderation_flag_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "question_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "answer_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "revision_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "discount_request_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "discount_offer_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "discount_accept_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "discount_decline_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ( + "RadrootsTradeOrderWorkflowProjection", + "cancellation_count", + super::TradeLargeIntegerPolicy::JsonNumberSafeCount + ), + ] + ); + } + + fn disposition(export_name: &str) -> TradeTypeDisposition { + TRADE_TYPE_INVENTORY + .iter() + .find(|entry| entry.export_name == export_name) + .map(|entry| entry.disposition) + .expect("inventory entry") + } + + fn type_inventory(types_ts: &str) -> Vec<&str> { + types_ts + .lines() + .filter_map(|line| line.strip_prefix("export type ")) + .map(|rest| rest.split([' ', '<']).next().expect("type name")) + .collect() + } }