sdk

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

commit 67fc0bf8adf131904f70c6cd45e115b734bd9932
parent f54dd5d07226bfd8d704690df0d489103a036134
Author: triesap <tyson@radroots.org>
Date:   Wed, 24 Jun 2026 06:25:52 +0000

dto: add explicit source root sets

Diffstat:
MCargo.lock | 4++++
Mtools/xtask/Cargo.toml | 2++
Atools/xtask/src/dto_roots.rs | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools/xtask/src/main.rs | 2++
4 files changed, 173 insertions(+), 0 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1674,6 +1674,7 @@ dependencies = [ name = "radroots_core" version = "0.1.0-alpha.2" dependencies = [ + "dto_bindgen_core", "rust_decimal", "rust_decimal_macros", "serde", @@ -1703,6 +1704,7 @@ dependencies = [ name = "radroots_events" version = "0.1.0-alpha.2" dependencies = [ + "dto_bindgen_core", "hex", "radroots_core", "serde", @@ -2046,7 +2048,9 @@ name = "radroots_sdk_xtask" version = "0.1.0" dependencies = [ "dto_bindgen_core", + "radroots_core", "radroots_core_bindings", + "radroots_events", "radroots_events_bindings", "radroots_events_indexed_bindings", "radroots_identity_bindings", diff --git a/tools/xtask/Cargo.toml b/tools/xtask/Cargo.toml @@ -15,7 +15,9 @@ path = "src/main.rs" [dependencies] dto_bindgen_core = { workspace = true } radroots_sdk_binding_model = { path = "../../crates/binding_model" } +radroots_core = { workspace = true, features = ["dto-bindgen"] } radroots_core_bindings = { path = "../../crates/core_bindings" } +radroots_events = { workspace = true, features = ["dto-bindgen"] } radroots_events_bindings = { path = "../../crates/events_bindings" } radroots_events_indexed_bindings = { path = "../../crates/events_indexed_bindings" } radroots_identity_bindings = { path = "../../crates/identity_bindings" } diff --git a/tools/xtask/src/dto_roots.rs b/tools/xtask/src/dto_roots.rs @@ -0,0 +1,165 @@ +use dto_bindgen_core::{Registry, RootDescriptor, build_registry}; + +#[derive(Clone, Copy, Debug)] +pub struct DtoPackageRootSet { + pub package_key: &'static str, + roots: fn() -> Vec<RootDescriptor>, +} + +impl DtoPackageRootSet { + pub fn roots(&self) -> Vec<RootDescriptor> { + (self.roots)() + } + + pub fn registry(&self) -> Registry { + build_registry(self.roots()) + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ManualDescriptorFamily { + pub package_key: &'static str, + pub source_family: &'static str, + pub reason: &'static str, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct SdkLocalWrapperAllowance { + pub package_key: &'static str, + pub shape_family: &'static str, + pub reason: &'static str, +} + +pub const DTO_PACKAGE_ROOTS: &[DtoPackageRootSet] = &[ + DtoPackageRootSet { + package_key: "core", + roots: core_roots, + }, + DtoPackageRootSet { + package_key: "events", + roots: events_roots, + }, +]; + +pub const MANUAL_DESCRIPTOR_FAMILIES: &[ManualDescriptorFamily] = &[ + ManualDescriptorFamily { + package_key: "core", + source_family: "decimal, currency, money, quantity, percent, quantity price, unit, and discount value families", + reason: "custom serde, string-backed newtypes, aliases, and tagged enum wire forms require source-owned manual descriptors", + }, + ManualDescriptorFamily { + package_key: "events", + source_family: "event timestamps, counters, and optional metadata fields", + reason: "large integers and source-specific optional/null policy must be explicit", + }, + ManualDescriptorFamily { + package_key: "events", + source_family: "GeoJSON coordinate arrays", + reason: "fixed-size Rust arrays must preserve tuple semantics in TypeScript", + }, + ManualDescriptorFamily { + package_key: "events_indexed", + source_family: "checkpoint and index cursor fields", + reason: "custom deserialization and large integers require manual descriptor policy", + }, + ManualDescriptorFamily { + package_key: "replica_db_schema", + source_family: "untagged query wrappers and serde_json value fields", + reason: "schema query shapes are generated and not all source fields map to derive-supported DTOs", + }, + ManualDescriptorFamily { + package_key: "types", + source_family: "generic result wrapper types", + reason: "generic export instantiations must be explicit and package-scoped", + }, +]; + +pub const SDK_LOCAL_WRAPPER_ALLOWANCES: &[SdkLocalWrapperAllowance] = &[ + SdkLocalWrapperAllowance { + package_key: "core", + shape_family: "RadrootsCoreCurrency and RadrootsCoreDecimal package aliases", + reason: "source descriptors correctly describe fields as strings, while package roots still need stable named TypeScript aliases", + }, + SdkLocalWrapperAllowance { + package_key: "replica_db_schema", + shape_family: "generated query argument wrappers", + reason: "schema operation inputs are generated package shapes rather than source-owned public DTO structs", + }, + SdkLocalWrapperAllowance { + package_key: "types", + shape_family: "IResult, IResultList, and IResultPass generic envelopes", + reason: "generic helper envelopes are SDK package contracts used across generated schema packages", + }, + SdkLocalWrapperAllowance { + package_key: "events_indexed", + shape_family: "index query result helpers", + reason: "indexed package helpers represent SDK query projections rather than source-owned wire events", + }, +]; + +pub fn package_root_set(package_key: &str) -> Option<&'static DtoPackageRootSet> { + DTO_PACKAGE_ROOTS + .iter() + .find(|root_set| root_set.package_key == package_key) +} + +fn core_roots() -> Vec<RootDescriptor> { + radroots_core::dto::dto_roots().into_iter().collect() +} + +fn events_roots() -> Vec<RootDescriptor> { + radroots_events::dto::dto_roots().into_iter().collect() +} + +#[cfg(test)] +mod tests { + use super::{ + DTO_PACKAGE_ROOTS, MANUAL_DESCRIPTOR_FAMILIES, SDK_LOCAL_WRAPPER_ALLOWANCES, + package_root_set, + }; + + #[test] + fn approved_source_roots_build_registries() { + for root_set in DTO_PACKAGE_ROOTS { + let registry = root_set.registry(); + assert!( + !registry.has_errors(), + "registry for {} has diagnostics: {:?}", + root_set.package_key, + registry.diagnostics + ); + assert!(!registry.roots.is_empty()); + } + } + + #[test] + fn package_roots_are_explicit_not_discovered() { + assert!(package_root_set("core").is_some()); + assert!(package_root_set("events").is_some()); + assert!(package_root_set("trade").is_none()); + } + + #[test] + fn manual_descriptor_catalog_covers_known_review_families() { + assert!( + MANUAL_DESCRIPTOR_FAMILIES + .iter() + .any(|family| family.source_family.contains("GeoJSON")) + ); + assert!( + MANUAL_DESCRIPTOR_FAMILIES + .iter() + .any(|family| family.source_family.contains("generic result")) + ); + assert!( + SDK_LOCAL_WRAPPER_ALLOWANCES + .iter() + .any(|allowance| allowance.shape_family.contains("RadrootsCoreDecimal")) + ); + assert!( + SDK_LOCAL_WRAPPER_ALLOWANCES + .iter() + .any(|allowance| allowance.shape_family.contains("IResult")) + ); + } +} diff --git a/tools/xtask/src/main.rs b/tools/xtask/src/main.rs @@ -4,6 +4,8 @@ mod coverage; mod coverage_policy; #[allow(dead_code)] mod dto_render; +#[allow(dead_code)] +mod dto_roots; mod fs; mod generate; mod manifest;