use std::path::Path; use std::process::Command; use anyhow::{Context, Result, ensure}; pub fn check_public_types(manifest_dir: impl AsRef, declarations: &[&str]) -> Result<()> { let root = manifest_dir.as_ref(); check_types(root.join("tsconfig.json"))?; let directory = tempfile::tempdir()?; let mut files = Vec::new(); for (index, declaration) in declarations.iter().enumerate() { let path = directory.path().join(format!("module_{index}.d.ts")); std::fs::write(&path, declaration)?; files.push(path); } files.push(root.join("tests/public.ts")); let config = directory.path().join("tsconfig.json"); std::fs::write( &config, serde_json::to_vec_pretty(&serde_json::json!({ "extends": root.join("../../lib/ext_build/tsconfig.harness.json"), "files": files, }))?, )?; check_types(config) } /// Check an extension's tsconfig with the native TypeScript backend. /// Returns early when AVRIL_TEST_TYPESCRIPT is unset, like the backend test suite. pub fn check_types(config: impl AsRef) -> Result<()> { let Some(backend) = std::env::var_os("AVRIL_TEST_TYPESCRIPT").filter(|path| !path.is_empty()) else { eprintln!("skipping: AVRIL_TEST_TYPESCRIPT is not set"); return Ok(()); }; let config = config.as_ref(); let output = Command::new(&backend) .arg("--project") .arg(config) .args(["--noEmit", "--pretty", "false"]) .output() .with_context(|| format!("Type-checking {} with {backend:?}", config.display()))?; ensure!( output.status.success(), "{}:\n{}{}", config.display(), String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr), ); Ok(()) }