lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 2f542e0a48b6fafb35684db16416665367da6e32
parent 4550601711d55a03a7d8df0092bfd0a49ed27258
Author: triesap <tyson@radroots.org>
Date:   Fri, 20 Feb 2026 23:34:20 +0000

build: add ts model export command

Diffstat:
MCargo.lock | 8++++++++
Acrates/xtask/src/export_ts.rs | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/xtask/src/main.rs | 23+++++++++++++++++++++--
3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -5024,6 +5024,14 @@ dependencies = [ ] [[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "serde", + "toml 0.8.23", +] + +[[package]] name = "yaml-rust2" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/crates/xtask/src/export_ts.rs b/crates/xtask/src/export_ts.rs @@ -0,0 +1,52 @@ +#![forbid(unsafe_code)] + +use crate::contract; +use std::fs; +use std::path::{Path, PathBuf}; + +fn to_package_dir(base: &Path, package_name: &str) -> PathBuf { + let stripped = package_name.strip_prefix("@radroots/").unwrap_or(package_name); + base.join(stripped) +} + +fn copy_if_exists(src: &Path, dst: &Path) -> Result<bool, String> { + if !src.exists() { + return Ok(false); + } + if let Some(parent) = dst.parent() { + fs::create_dir_all(parent).map_err(|e| format!("create {}: {e}", parent.display()))?; + } + fs::copy(src, dst).map_err(|e| format!("copy {} -> {}: {e}", src.display(), dst.display()))?; + Ok(true) +} + +pub fn export_ts_models(workspace_root: &Path, out_dir: &Path) -> Result<(), String> { + let bundle = contract::load_contract_bundle(workspace_root)?; + contract::validate_contract_bundle(&bundle)?; + let ts_export = bundle + .exports + .iter() + .find(|mapping| mapping.language.id == "ts") + .ok_or_else(|| "missing ts export mapping".to_string())?; + let source_root = workspace_root.join("target").join("ts-rs"); + if !source_root.exists() { + return Err(format!("missing ts-rs source root {}", source_root.display())); + } + let ts_out_root = out_dir.join("ts").join("packages"); + let mut copied = 0usize; + for (crate_name, package_name) in &ts_export.packages { + let crate_dir = crate_name.strip_prefix("radroots-").unwrap_or(crate_name); + let src = source_root.join(crate_dir).join("types.ts"); + let dst = to_package_dir(&ts_out_root, package_name) + .join("src") + .join("generated") + .join("types.ts"); + if copy_if_exists(&src, &dst)? { + copied += 1; + } + } + if copied == 0 { + return Err("no ts model files were exported".to_string()); + } + Ok(()) +} diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs @@ -1,6 +1,7 @@ #![forbid(unsafe_code)] mod contract; +mod export_ts; use std::env; use std::path::{Path, PathBuf}; @@ -8,7 +9,7 @@ use std::process::ExitCode; fn usage() { eprintln!("usage:"); - eprintln!(" cargo xtask sdk export-ts [--out <dir>]"); + eprintln!(" cargo xtask sdk export-ts-models [--out <dir>]"); eprintln!(" cargo xtask sdk validate"); } @@ -23,6 +24,24 @@ fn workspace_root() -> Result<PathBuf, String> { Ok(root.to_path_buf()) } +fn parse_out_dir(args: &[String], workspace_root: &Path) -> Result<PathBuf, String> { + if args.is_empty() { + return Ok(workspace_root.join("target").join("sdk-export")); + } + if args.len() == 2 && args[0] == "--out" { + return Ok(PathBuf::from(&args[1])); + } + Err("invalid export args, expected --out <dir>".to_string()) +} + +fn export_ts_models(args: &[String]) -> Result<(), String> { + let root = workspace_root()?; + let out_dir = parse_out_dir(args, &root)?; + export_ts::export_ts_models(&root, &out_dir)?; + eprintln!("exported ts models to {}", out_dir.display()); + Ok(()) +} + fn validate_contract() -> Result<(), String> { let root = workspace_root()?; let bundle = contract::load_contract_bundle(&root)?; @@ -37,7 +56,7 @@ fn validate_contract() -> Result<(), String> { fn run_sdk(args: &[String]) -> Result<(), String> { match args.first().map(String::as_str) { - Some("export-ts") => Ok(()), + Some("export-ts-models") => export_ts_models(&args[1..]), Some("validate") => validate_contract(), _ => Err("unknown sdk subcommand".to_string()), }