diff --git a/adl/adlc/adlc/packaging.adl b/adl/adlc/adlc/packaging.adl index b4e3987a..8e830c28 100644 --- a/adl/adlc/adlc/packaging.adl +++ b/adl/adlc/adlc/packaging.adl @@ -32,10 +32,23 @@ struct Payload2 { struct AdlWorkspace<T> { String adlc; Vector<T> use; + StringMap<NamedOpts> named_options = {}; Vector<RuntimeOpts> runtimes = []; // Maybe<T> embedded_sys_loader; }; +struct NamedOpts { + TsNamedOpts ts_opts = {}; +}; + +struct TsNamedOpts { + Nullable<TsRuntimeOpt> runtime_opts = null; + Nullable<StringMap<String>> scripts = null; + Nullable<StringMap<String>> dependencies = null; + Nullable<StringMap<String>> dev_dependencies = null; + Nullable<TsConfig> tsconfig = null; +}; + union RuntimeOpts { TsWriteRuntime ts_runtime; }; @@ -77,6 +90,7 @@ union InjectAnnotation { struct AdlPackageRef { AdlPackageRefType ref; + Nullable<String> named_opts = null; Nullable<TypescriptGenOptions> ts_opts = null; }; @@ -106,6 +120,8 @@ struct TypescriptGenOptions { StringMap<VersionSpec> extra_dependencies = {}; StringMap<VersionSpec> extra_dev_dependencies = {}; Nullable<OutputOpts> outputs = null; + Nullable<TsConfig> tsconfig = null; + StringMap<String> scripts = {}; TsRuntimeOpt runtime_opts = {"package_ref": {"name": "@adl-lang/runtime", "version": "^1.0.0"}}; Bool generate_transitive = false; Bool include_resolver = false; @@ -222,15 +238,10 @@ struct NpmPackage { // the bits of tsconfig we need struct TsConfig { - String extends = "tsconfig/base.json"; - Vector<String> include = ["."]; - Vector<String> exclude = ["dist", "build", "node_modules"]; - TsCompilerOptions compilerOptions = { - "outDir": "dist", - "lib": [ - "es2020" - ] - }; + Nullable<String> extends; + Vector<String> include; + Vector<String> exclude; + TsCompilerOptions compilerOptions; }; struct TsCompilerOptions { diff --git a/rust/compiler/src/adlgen/adlc/packaging.rs b/rust/compiler/src/adlgen/adlc/packaging.rs index e9dcd47e..d5233c46 100644 --- a/rust/compiler/src/adlgen/adlc/packaging.rs +++ b/rust/compiler/src/adlgen/adlc/packaging.rs @@ -54,13 +54,16 @@ impl Payload2 { /** * Expected to live in a file named `adl.work.json` */ -#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] pub struct AdlWorkspace<T> { pub adlc: String, #[serde(rename="use")] pub r#use: Vec<T>, + #[serde(default="AdlWorkspace::<T>::def_named_options")] + pub named_options: std::collections::HashMap<String,NamedOpts>, + #[serde(default="AdlWorkspace::<T>::def_runtimes")] pub runtimes: Vec<RuntimeOpts>, } @@ -70,15 +73,88 @@ impl<T> AdlWorkspace<T> { AdlWorkspace { adlc: adlc, r#use: r#use, + named_options: AdlWorkspace::<T>::def_named_options(), runtimes: AdlWorkspace::<T>::def_runtimes(), } } + pub fn def_named_options() -> std::collections::HashMap<String,NamedOpts> { + [].iter().cloned().collect() + } + pub fn def_runtimes() -> Vec<RuntimeOpts> { vec![] } } +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct NamedOpts { + #[serde(default="NamedOpts::def_ts_opts")] + pub ts_opts: TsNamedOpts, +} + +impl NamedOpts { + pub fn new() -> NamedOpts { + NamedOpts { + ts_opts: NamedOpts::def_ts_opts(), + } + } + + pub fn def_ts_opts() -> TsNamedOpts { + TsNamedOpts{runtime_opts : None, scripts : None, dependencies : None, dev_dependencies : None, tsconfig : None} + } +} + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct TsNamedOpts { + #[serde(default="TsNamedOpts::def_runtime_opts")] + pub runtime_opts: Option<TsRuntimeOpt>, + + #[serde(default="TsNamedOpts::def_scripts")] + pub scripts: Option<std::collections::HashMap<String,String>>, + + #[serde(default="TsNamedOpts::def_dependencies")] + pub dependencies: Option<std::collections::HashMap<String,String>>, + + #[serde(default="TsNamedOpts::def_dev_dependencies")] + pub dev_dependencies: Option<std::collections::HashMap<String,String>>, + + #[serde(default="TsNamedOpts::def_tsconfig")] + pub tsconfig: Option<TsConfig>, +} + +impl TsNamedOpts { + pub fn new() -> TsNamedOpts { + TsNamedOpts { + runtime_opts: TsNamedOpts::def_runtime_opts(), + scripts: TsNamedOpts::def_scripts(), + dependencies: TsNamedOpts::def_dependencies(), + dev_dependencies: TsNamedOpts::def_dev_dependencies(), + tsconfig: TsNamedOpts::def_tsconfig(), + } + } + + pub fn def_runtime_opts() -> Option<TsRuntimeOpt> { + None + } + + pub fn def_scripts() -> Option<std::collections::HashMap<String,String>> { + None + } + + pub fn def_dependencies() -> Option<std::collections::HashMap<String,String>> { + None + } + + pub fn def_dev_dependencies() -> Option<std::collections::HashMap<String,String>> { + None + } + + pub fn def_tsconfig() -> Option<TsConfig> { + None + } +} + #[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum RuntimeOpts { #[serde(rename="ts_runtime")] @@ -211,6 +287,9 @@ pub struct AdlPackageRef { #[serde(rename="ref")] pub r#ref: AdlPackageRefType, + #[serde(default="AdlPackageRef::def_named_opts")] + pub named_opts: Option<String>, + #[serde(default="AdlPackageRef::def_ts_opts")] pub ts_opts: Option<TypescriptGenOptions>, } @@ -219,10 +298,15 @@ impl AdlPackageRef { pub fn new(r#ref: AdlPackageRefType) -> AdlPackageRef { AdlPackageRef { r#ref: r#ref, + named_opts: AdlPackageRef::def_named_opts(), ts_opts: AdlPackageRef::def_ts_opts(), } } + pub fn def_named_opts() -> Option<String> { + None + } + pub fn def_ts_opts() -> Option<TypescriptGenOptions> { None } @@ -291,6 +375,12 @@ pub struct TypescriptGenOptions { #[serde(default="TypescriptGenOptions::def_outputs")] pub outputs: Option<OutputOpts>, + #[serde(default="TypescriptGenOptions::def_tsconfig")] + pub tsconfig: Option<TsConfig>, + + #[serde(default="TypescriptGenOptions::def_scripts")] + pub scripts: std::collections::HashMap<String,String>, + #[serde(default="TypescriptGenOptions::def_runtime_opts")] pub runtime_opts: TsRuntimeOpt, @@ -321,6 +411,8 @@ impl TypescriptGenOptions { extra_dependencies: TypescriptGenOptions::def_extra_dependencies(), extra_dev_dependencies: TypescriptGenOptions::def_extra_dev_dependencies(), outputs: TypescriptGenOptions::def_outputs(), + tsconfig: TypescriptGenOptions::def_tsconfig(), + scripts: TypescriptGenOptions::def_scripts(), runtime_opts: TypescriptGenOptions::def_runtime_opts(), generate_transitive: TypescriptGenOptions::def_generate_transitive(), include_resolver: TypescriptGenOptions::def_include_resolver(), @@ -347,6 +439,14 @@ impl TypescriptGenOptions { None } + pub fn def_tsconfig() -> Option<TsConfig> { + None + } + + pub fn def_scripts() -> std::collections::HashMap<String,String> { + [].iter().cloned().collect() + } + pub fn def_runtime_opts() -> TsRuntimeOpt { TsRuntimeOpt::PackageRef(NpmPackageRef{name : "@adl-lang/runtime".to_string(), version : "^1.0.0".to_string()}) } @@ -685,45 +785,25 @@ impl NpmPackage { #[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct TsConfig { - #[serde(default="TsConfig::def_extends")] - pub extends: String, + pub extends: Option<String>, - #[serde(default="TsConfig::def_include")] pub include: Vec<String>, - #[serde(default="TsConfig::def_exclude")] pub exclude: Vec<String>, - #[serde(default="TsConfig::def_compiler_options")] #[serde(rename="compilerOptions")] pub compiler_options: TsCompilerOptions, } impl TsConfig { - pub fn new() -> TsConfig { + pub fn new(extends: Option<String>, include: Vec<String>, exclude: Vec<String>, compiler_options: TsCompilerOptions) -> TsConfig { TsConfig { - extends: TsConfig::def_extends(), - include: TsConfig::def_include(), - exclude: TsConfig::def_exclude(), - compiler_options: TsConfig::def_compiler_options(), + extends: extends, + include: include, + exclude: exclude, + compiler_options: compiler_options, } } - - pub fn def_extends() -> String { - "tsconfig/base.json".to_string() - } - - pub fn def_include() -> Vec<String> { - vec![".".to_string()] - } - - pub fn def_exclude() -> Vec<String> { - vec!["dist".to_string(), "build".to_string(), "node_modules".to_string()] - } - - pub fn def_compiler_options() -> TsCompilerOptions { - TsCompilerOptions{out_dir : "dist".to_string(), lib : vec!["es2020".to_string()]} - } } #[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] diff --git a/rust/compiler/src/cli/mod.rs b/rust/compiler/src/cli/mod.rs index 46eee69c..3b4ae9a9 100644 --- a/rust/compiler/src/cli/mod.rs +++ b/rust/compiler/src/cli/mod.rs @@ -82,6 +82,8 @@ pub fn run_cli() -> i32 { npm_version: TypescriptGenOptions::def_npm_version(), extra_dependencies: TypescriptGenOptions::def_extra_dependencies(), extra_dev_dependencies: TypescriptGenOptions::def_extra_dev_dependencies(), + tsconfig: TypescriptGenOptions::def_tsconfig(), + scripts: TypescriptGenOptions::def_scripts(), outputs: Some(crate::adlgen::adlc::packaging::OutputOpts::Gen(GenOutput { referenceable: ReferenceableScopeOption::Local, output_dir: opts.output.outputdir.to_str().unwrap().to_string(), diff --git a/rust/compiler/src/cli/tsgen/mod.rs b/rust/compiler/src/cli/tsgen/mod.rs index d70500d4..b0ede614 100644 --- a/rust/compiler/src/cli/tsgen/mod.rs +++ b/rust/compiler/src/cli/tsgen/mod.rs @@ -15,7 +15,7 @@ use genco::fmt::{self, Indentation}; use genco::prelude::*; use crate::adlgen::adlc::packaging::{ - AdlPackageRefType, AdlWorkspace, ModuleSrc, NpmPackage, Payload1, TsConfig, TsRuntimeOpt, + AdlPackageRefType, AdlWorkspace, ModuleSrc, NpmPackage, Payload1, TsRuntimeOpt, TsStyle, TsWriteRuntime, TypescriptGenOptions, }; use crate::adlgen::sys::adlast2::Module1; @@ -281,9 +281,9 @@ pub fn gen_npm_package(payload: &Payload1, wrk1: &AdlWorkspace<Payload1>) -> any } TsRuntimeOpt::Generate(_) => {} }; - npm_package - .scripts - .insert("tsc".to_string(), "tsc".to_string()); + for (k,v) in &opts.scripts { + npm_package.scripts.entry(k.clone()).or_insert(v.clone()); + } for d in &opts.extra_dependencies { npm_package.dependencies.insert(d.0.clone(), d.1.clone()); @@ -354,10 +354,11 @@ pub fn gen_npm_package(payload: &Payload1, wrk1: &AdlWorkspace<Payload1>) -> any writer.write(Path::new("package.json"), content)?; log::info!("generated {:?}", outputdir.clone().join("package.json")); - let ts_config = TsConfig::new(); - let content = serde_json::to_string_pretty(&ts_config)?; - writer.write(Path::new("tsconfig.json"), content)?; - log::info!("generated {:?}", outputdir.clone().join("tsconfig.json")); + if let Some(ts_config) = &opts.tsconfig { + let content = serde_json::to_string_pretty(ts_config)?; + writer.write(Path::new("tsconfig.json"), content)?; + log::info!("generated {:?}", outputdir.clone().join("tsconfig.json")); + } Ok(()) } diff --git a/rust/compiler/src/cli/workspace.rs b/rust/compiler/src/cli/workspace.rs index 7892d3cf..cad652a1 100644 --- a/rust/compiler/src/cli/workspace.rs +++ b/rust/compiler/src/cli/workspace.rs @@ -1,4 +1,5 @@ +use std::collections::HashMap; use std::path::PathBuf; use std::{env, fs}; @@ -8,7 +9,7 @@ use serde::Deserialize; use crate::adlgen::adlc::packaging::{ AdlPackage, AdlPackageRefType, AdlWorkspace0, AdlWorkspace1, DirLoaderRef, InjectAnnotation, - LoaderRef, LoaderRefType, LoaderWorkspace, Payload1, EmbeddedLoaderRef, EmbeddedPkg, AdlPackageRef, PkgRef, + LoaderRef, LoaderRefType, LoaderWorkspace, Payload1, EmbeddedLoaderRef, EmbeddedPkg, AdlPackageRef, PkgRef, TypescriptGenOptions, }; use crate::adlgen::sys::adlast2::ScopedName; use crate::adlrt::custom::sys::types::pair::Pair; @@ -63,6 +64,7 @@ fn wrk1_to_wld(wrk1: AdlWorkspace1) -> Result<LoaderWorkspace, anyhow::Error> { Ok(LoaderWorkspace { adlc: wrk1.adlc, r#use: u2, + named_options: HashMap::new(), runtimes: wrk1.runtimes, // embedded_sys_loader: Maybe(wrk1.embedded_sys_loader.0.as_ref().map(payload1_to_loader_ref)), }) @@ -119,6 +121,16 @@ fn payload1_to_loader_ref(payload1: &Payload1) -> Result<LoaderRef, anyhow::Erro Ok(loader_ref) } +fn aprt_to_name(a: &AdlPackageRefType) -> String { + match a { + AdlPackageRefType::Dir(d) => d.path.clone(), + AdlPackageRefType::Embedded(e) => match e.alias { + EmbeddedPkg::Sys => "sys".to_string(), + EmbeddedPkg::Adlc => "adlc".to_string(), + }, + } +} + fn collection_to_workspace( pkg_defs: Vec<(PkgDef, PathBuf, &str)>, ) -> Result<(PathBuf, AdlWorkspace1), anyhow::Error> { @@ -135,31 +147,56 @@ fn collection_to_workspace( PkgDef::Work => { let wrk0 = AdlWorkspace0::deserialize(&mut de) .map_err(|e| anyhow!("{:?}: {}", porw_path, e.to_string()))?; + let named_opts = wrk0.named_options; let mut wrk1 = AdlWorkspace1 { adlc: wrk0.adlc.clone(), runtimes: wrk0.runtimes, + named_options: HashMap::new(), r#use: vec![], - // embedded_sys_loader: Maybe(wrk0.embedded_sys_loader.0.map(|esl| Payload1 { - // p_ref: esl, - // pkg: AdlPackage { - // path: "github.com/adl-lang/adl/adl/stdlib/sys".to_string(), - // global_alias: Some("sys".to_string()), - // adlc: "0.0.0".to_string(), - // requires: vec![], - // excludes: vec![], - // replaces: vec![], - // retracts: vec![], - // }, - // })), }; for p in wrk0.r#use.iter() { let pkg = p.pkg_content(porw.1.clone())?; + let mut p2 = p.clone(); + if let Some(name) = &p.named_opts { + if let Some(opts) = named_opts.get(name) { + if let Some(tsopt) = &mut p2.ts_opts { + if let Some(rt) = &opts.ts_opts.runtime_opts { + if !tsopt.runtime_opts.eq(&TypescriptGenOptions::def_runtime_opts()) { + tsopt.runtime_opts = rt.to_owned(); + } + }; + if let Some(tsc) = &opts.ts_opts.tsconfig { + if tsopt.tsconfig == None { + tsopt.tsconfig = Some(tsc.to_owned()); + } + } + if let Some(hm) = &opts.ts_opts.dependencies { + for (k,v) in hm { + tsopt.extra_dependencies.entry(k.clone()).or_insert(v.clone()); + } + } + if let Some(hm) = &opts.ts_opts.dev_dependencies { + for (k,v) in hm { + tsopt.extra_dev_dependencies.entry(k.clone()).or_insert(v.clone()); + } + } + if let Some(hm) = &opts.ts_opts.scripts { + for (k,v) in hm { + tsopt.scripts.entry(k.clone()).or_insert(v.clone()); + } + } + p2.ts_opts = Some(tsopt.to_owned()); + } + } else { + log::warn!("Named option set specified but not found. Name: {} Package: {}", name, aprt_to_name(&p.r#ref)); + } + } // let p_path = porw.1.join(&p.path).join("adl.pkg.json"); // let content = fs::read_to_string(&p_path).map_err(|e| anyhow!("Can't read pkg specified in workspace.\n\tworkspace {:?}\n\t package {:?}\n\t error: {}", porw_path, p_path, e.to_string()))?; // let mut de = serde_json::Deserializer::from_str(&content); // let pkg = AdlPackage::deserialize(&mut de) // .map_err(|e| anyhow!("{:?}: {}", p_path, e.to_string()))?; - wrk1.r#use.push(Payload1::new(p.clone(), pkg)); + wrk1.r#use.push(Payload1::new(p2, pkg)); } return Ok((porw.1, wrk1)); } diff --git a/typescript/workspace/adl.work.json b/typescript/workspace/adl.work.json index 2c5a8fb1..06b02344 100644 --- a/typescript/workspace/adl.work.json +++ b/typescript/workspace/adl.work.json @@ -1,6 +1,39 @@ { "adlc": "0.0.0", - "use_embedded_sys_loader": true, + "named_options": { + "base": { + "ts_opts": { + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "scripts": { + "tsc": "tsc", + "clean": "rm -rf dist && rm -rf node_modules" + }, + "tsconfig": { + "extends": "tsconfig/base.json", + "include": [ + "." + ], + "exclude": [ + "dist", + "build", + "node_modules" + ], + "compilerOptions": { + "outDir": "dist", + "lib": [ + "es2020" + ] + } + } + } + } + }, "runtimes": [ { "ts_runtime": { @@ -11,6 +44,7 @@ ], "use": [ { + "named_opts": "base", "ref": { "embedded": { "alias": "sys" @@ -22,13 +56,6 @@ "extra_dependencies": { "base64-js": "^1.5.1" }, - "extra_dev_dependencies": { - "tsconfig": "workspace:*", - "typescript": "^4.9.3" - }, - "runtime_opts": { - "workspace_ref": "@adl-lang/runtime" - }, "outputs": { "gen": { "output_dir": "./generated/sys", @@ -40,6 +67,7 @@ } }, { + "named_opts": "base", "ref": { "dir": { "path": "./adl/lib" @@ -47,13 +75,6 @@ }, "ts_opts": { "npm_pkg_name": "@adl-lang/common", - "extra_dev_dependencies": { - "tsconfig": "workspace:*", - "typescript": "^4.9.3" - }, - "runtime_opts": { - "workspace_ref": "@adl-lang/runtime" - }, "outputs": { "gen": { "output_dir": "./generated/common", @@ -65,6 +86,7 @@ } }, { + "named_opts": "base", "ref": { "dir": { "path": "./adl/proj" @@ -76,13 +98,6 @@ "extra_dependencies": { "base64-js": "^1.5.1" }, - "extra_dev_dependencies": { - "tsconfig": "workspace:*", - "typescript": "^4.9.3" - }, - "runtime_opts": { - "workspace_ref": "@adl-lang/runtime" - }, "outputs": { "gen": { "output_dir": "./generated/protoclient", @@ -94,4 +109,4 @@ } } ] -} +} \ No newline at end of file diff --git a/typescript/workspace/generated/common/package.json b/typescript/workspace/generated/common/package.json index 90d3340e..2f5cf055 100644 --- a/typescript/workspace/generated/common/package.json +++ b/typescript/workspace/generated/common/package.json @@ -2,14 +2,12 @@ "name": "@adl-lang/common", "version": "1.0.0", "scripts": { + "clean": "rm -rf dist && rm -rf node_modules", "tsc": "tsc" }, "dependencies": { - "@adl-lang/runtime": "workspace:*", - "@adl-lang/sys": "workspace:*" + "@adl-lang/sys": "workspace:*", + "@adl-lang/runtime": "^1.0.0" }, - "devDependencies": { - "typescript": "^4.9.3", - "tsconfig": "workspace:*" - } + "devDependencies": {} } \ No newline at end of file diff --git a/typescript/workspace/generated/protoclient/package.json b/typescript/workspace/generated/protoclient/package.json index 7a7f8d5a..4c56e637 100644 --- a/typescript/workspace/generated/protoclient/package.json +++ b/typescript/workspace/generated/protoclient/package.json @@ -2,16 +2,14 @@ "name": "@adl-lang/protoclient", "version": "1.0.0", "scripts": { + "clean": "rm -rf dist && rm -rf node_modules", "tsc": "tsc" }, "dependencies": { + "@adl-lang/runtime": "^1.0.0", + "@adl-lang/common": "workspace:*", "@adl-lang/sys": "workspace:*", - "@adl-lang/runtime": "workspace:*", - "base64-js": "^1.5.1", - "@adl-lang/common": "workspace:*" + "base64-js": "^1.5.1" }, - "devDependencies": { - "typescript": "^4.9.3", - "tsconfig": "workspace:*" - } + "devDependencies": {} } \ No newline at end of file diff --git a/typescript/workspace/generated/sys/package.json b/typescript/workspace/generated/sys/package.json index edb84151..35c02a94 100644 --- a/typescript/workspace/generated/sys/package.json +++ b/typescript/workspace/generated/sys/package.json @@ -2,14 +2,12 @@ "name": "@adl-lang/sys", "version": "1.0.0", "scripts": { - "tsc": "tsc" + "tsc": "tsc", + "clean": "rm -rf dist && rm -rf node_modules" }, "dependencies": { - "@adl-lang/runtime": "workspace:*", - "base64-js": "^1.5.1" + "base64-js": "^1.5.1", + "@adl-lang/runtime": "^1.0.0" }, - "devDependencies": { - "typescript": "^4.9.3", - "tsconfig": "workspace:*" - } + "devDependencies": {} } \ No newline at end of file