sdk

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

commit 64dc049f7564df0346dfde99a64705ff383a600f
parent d2ab63b6b6927a3f32d6880238313ba2431a190a
Author: triesap <tyson@radroots.org>
Date:   Thu, 11 Jun 2026 14:19:26 -0700

test: align integration coverage

Diffstat:
Mcrates/xtask/src/check.rs | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/crates/xtask/src/check.rs b/crates/xtask/src/check.rs @@ -10,6 +10,7 @@ pub fn check() -> Result<(), String> { validate_package_matrix()?; let root = workspace_root()?; check_forbidden_packages(&root)?; + check_binding_crate_sources(&root)?; for spec in package_specs() { let package_dir = root.join(spec.package_dir); let package_json_path = package_dir.join("package.json"); @@ -34,6 +35,45 @@ pub fn check() -> Result<(), String> { Ok(()) } +fn check_binding_crate_sources(root: &Path) -> Result<(), String> { + for spec in package_specs() { + let crate_src_dir = root.join(spec.crate_dir).join("src"); + let typescript_dir = crate_src_dir.join("typescript"); + if typescript_dir.exists() { + return Err(format!( + "forbidden crate TypeScript source directory exists: {}", + typescript_dir.display() + )); + } + check_no_typescript_files(&crate_src_dir)?; + } + Ok(()) +} + +fn check_no_typescript_files(dir: &Path) -> Result<(), String> { + for entry in + fs::read_dir(dir).map_err(|error| format!("failed to read {}: {error}", dir.display()))? + { + let entry = + entry.map_err(|error| format!("failed to read {} entry: {error}", dir.display()))?; + let path = entry.path(); + let file_type = entry + .file_type() + .map_err(|error| format!("failed to inspect {}: {error}", path.display()))?; + if file_type.is_dir() { + check_no_typescript_files(&path)?; + } else if file_type.is_file() + && path.extension().and_then(|extension| extension.to_str()) == Some("ts") + { + return Err(format!( + "forbidden crate TypeScript source file exists: {}", + path.display() + )); + } + } + Ok(()) +} + fn check_forbidden_packages(root: &Path) -> Result<(), String> { for forbidden in FORBIDDEN_PACKAGE_NAMES { let package_leaf = forbidden.trim_start_matches("@radroots/").to_owned(); @@ -75,10 +115,60 @@ fn check_package_json(path: &Path, expected_name: &str) -> Result<(), String> { #[cfg(test)] mod tests { - use super::check; + use std::{ + fs, + path::PathBuf, + time::{SystemTime, UNIX_EPOCH}, + }; + + use super::{check, check_binding_crate_sources, check_no_typescript_files}; #[test] fn package_skeleton_is_valid() { check().expect("package skeleton validates"); } + + #[test] + fn rejects_crate_typescript_directories() { + let root = test_root("typescript_dir"); + let typescript_dir = root + .join("crates") + .join("core_bindings") + .join("src") + .join("typescript"); + fs::create_dir_all(&typescript_dir).expect("create forbidden directory"); + + let error = check_binding_crate_sources(&root).expect_err("forbidden directory rejected"); + + assert!(error.contains("forbidden crate TypeScript source directory")); + let _ = fs::remove_dir_all(root); + } + + #[test] + fn rejects_crate_typescript_files() { + let root = test_root("typescript_file"); + let src_dir = root.join("crates/core_bindings/src"); + fs::create_dir_all(&src_dir).expect("create crate source directory"); + fs::write(src_dir.join("types.ts"), "export type A = string;\n") + .expect("write forbidden file"); + + let error = check_no_typescript_files(&src_dir).expect_err("forbidden file rejected"); + + assert!(error.contains("forbidden crate TypeScript source file")); + let _ = fs::remove_dir_all(root); + } + + fn test_root(name: &str) -> PathBuf { + let stamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("system time after epoch") + .as_nanos(); + let root = std::env::temp_dir().join(format!( + "radroots_sdk_xtask_check_{name}_{}_{}", + std::process::id(), + stamp + )); + let _ = fs::remove_dir_all(&root); + root + } }