From 30e2e86442609bf4434994599ca83d810a85f9ea Mon Sep 17 00:00:00 2001 From: Yoriyasu Yano <430092+yorinasub17@users.noreply.github.com> Date: Tue, 21 Nov 2023 11:46:06 -0600 Subject: [PATCH] feat: Add support for importing yaml files Signed-off-by: Yoriyasu Yano <430092+yorinasub17@users.noreply.github.com> --- src/engine.rs | 114 +++++++++++---------------------- src/module_loader.rs | 62 ++++++++++++------ tests/fixtures/import_json.js | 8 +++ tests/fixtures/import_yaml.js | 8 +++ tests/fixtures/someconfig.json | 3 + tests/fixtures/someconfig.yaml | 1 + 6 files changed, 99 insertions(+), 97 deletions(-) create mode 100644 tests/fixtures/import_json.js create mode 100644 tests/fixtures/import_yaml.js create mode 100644 tests/fixtures/someconfig.json create mode 100644 tests/fixtures/someconfig.yaml diff --git a/src/engine.rs b/src/engine.rs index 44a2517..815a280 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -450,101 +450,36 @@ mod tests { static EXPECTED_RELPATH_OUTPUT_JSON: &str = "{\"state\":\"aws/us-east-1/vpc/terraform.tfstate\",\"mainf\":\"aws/us-east-1/vpc/main.js\"}"; static EXPECTED_OUTFILE_OUTPUT_JSON: &str = "{\"this\":\"outfile.js\"}"; + static EXPECTED_IMPORT_CONFIG_OUTPUT_JSON: &str = "{\"msg\":\"hello world\"}"; #[tokio::test] async fn test_engine_runs_js() { - let expected_output: serde_json::Value = serde_json::from_str(EXPECTED_SIMPLE_OUTPUT_JSON) - .expect("error unpacking simple expected output json"); - - let p = get_fixture_path("simple.js"); - let req = RunRequest { - in_file: String::from(p.as_path().to_string_lossy()), - out_file_stem: String::from(""), - }; - let od_vec = run_js(&get_context(), &req) - .await - .expect("error running js"); - assert_eq!(od_vec.len(), 1); - let od = &od_vec[0]; - - assert_eq!(od.out_path, None); - assert_eq!(od.out_ext, Some(String::from(".json"))); - assert_eq!(od.out_prefix, None); - let actual_output: serde_json::Value = - serde_json::from_str(&od.data).expect("error unpacking js data"); - assert_eq!(actual_output, expected_output); + check_single_json_output(EXPECTED_SIMPLE_OUTPUT_JSON, "simple.js").await; } #[tokio::test] async fn test_engine_runs_ts() { - let expected_output: serde_json::Value = serde_json::from_str(EXPECTED_SIMPLE_OUTPUT_JSON) - .expect("error unpacking simple expected output json"); + check_single_json_output(EXPECTED_SIMPLE_OUTPUT_JSON, "simple.ts").await; + } - let p = get_fixture_path("simple.ts"); - let req = RunRequest { - in_file: String::from(p.as_path().to_string_lossy()), - out_file_stem: String::from(""), - }; - let od_vec = run_js(&get_context(), &req) - .await - .expect("error running js"); - assert_eq!(od_vec.len(), 1); - let od = &od_vec[0]; + #[tokio::test] + async fn test_engine_runs_code_with_config_json_import() { + check_single_json_output(EXPECTED_IMPORT_CONFIG_OUTPUT_JSON, "import_json.js").await; + } - assert_eq!(od.out_path, None); - assert_eq!(od.out_ext, Some(String::from(".json"))); - assert_eq!(od.out_prefix, None); - let actual_output: serde_json::Value = - serde_json::from_str(&od.data).expect("error unpacking js data"); - assert_eq!(actual_output, expected_output); + #[tokio::test] + async fn test_engine_runs_code_with_config_yaml_import() { + check_single_json_output(EXPECTED_IMPORT_CONFIG_OUTPUT_JSON, "import_yaml.js").await; } #[tokio::test] async fn test_engine_runs_code_with_node_modules() { - let expected_output: serde_json::Value = serde_json::from_str(EXPECTED_LODASH_OUTPUT_JSON) - .expect("error unpacking lodash expected output json"); - - let p = get_fixture_path("with_lodash.js"); - let req = RunRequest { - in_file: String::from(p.as_path().to_string_lossy()), - out_file_stem: String::from(""), - }; - let od_vec = run_js(&get_context(), &req) - .await - .expect("error running js"); - assert_eq!(od_vec.len(), 1); - let od = &od_vec[0]; - - assert_eq!(od.out_path, None); - assert_eq!(od.out_ext, Some(String::from(".json"))); - assert_eq!(od.out_prefix, None); - let actual_output: serde_json::Value = - serde_json::from_str(&od.data).expect("error unpacking js data"); - assert_eq!(actual_output, expected_output); + check_single_json_output(EXPECTED_LODASH_OUTPUT_JSON, "with_lodash.js").await; } #[tokio::test] async fn test_engine_runs_code_with_builtin_filefunctions() { - let expected_output: serde_json::Value = serde_json::from_str(EXPECTED_RELPATH_OUTPUT_JSON) - .expect("error unpacking relpath output json"); - - let p = get_fixture_path("aws/us-east-1/vpc/main.js"); - let req = RunRequest { - in_file: String::from(p.as_path().to_string_lossy()), - out_file_stem: String::from(""), - }; - let od_vec = run_js(&get_context(), &req) - .await - .expect("error running js"); - assert_eq!(od_vec.len(), 1); - let od = &od_vec[0]; - - assert_eq!(od.out_path, None); - assert_eq!(od.out_ext, Some(String::from(".json"))); - assert_eq!(od.out_prefix, None); - let actual_output: serde_json::Value = - serde_json::from_str(&od.data).expect("error unpacking js data"); - assert_eq!(actual_output, expected_output); + check_single_json_output(EXPECTED_RELPATH_OUTPUT_JSON, "aws/us-east-1/vpc/main.js").await; } #[tokio::test] @@ -685,6 +620,29 @@ mod tests { let _ = step_result.expect("wrong output"); } + async fn check_single_json_output(output_json_str: &str, fixture_fname: &str) { + let expected_output: serde_json::Value = + serde_json::from_str(output_json_str).expect("error unpacking expected output json"); + + let p = get_fixture_path(fixture_fname); + let req = RunRequest { + in_file: String::from(p.as_path().to_string_lossy()), + out_file_stem: String::from(""), + }; + let od_vec = run_js(&get_context(), &req) + .await + .expect("error running js"); + assert_eq!(od_vec.len(), 1); + let od = &od_vec[0]; + + assert_eq!(od.out_path, None); + assert_eq!(od.out_ext, Some(String::from(".json"))); + assert_eq!(od.out_prefix, None); + let actual_output: serde_json::Value = + serde_json::from_str(&od.data).expect("error unpacking js data"); + assert_eq!(actual_output, expected_output); + } + fn get_context() -> Context { let node_modules_dir = Some(get_fixture_path("node_modules")); let projectroot = get_fixture_path(""); diff --git a/src/module_loader.rs b/src/module_loader.rs index 81b7b53..0074684 100644 --- a/src/module_loader.rs +++ b/src/module_loader.rs @@ -13,6 +13,13 @@ use deno_core::futures::FutureExt; use deno_core::*; use log::*; +// The transpile type. Determines how the code should be transpiled before loading. +enum TranspileType { + No, // No transpilation. + Typescript, // Transpile typescript files to javascript. + YAML, // Transpile yaml files to json. +} + // The TypeScript module loader. // This will check to see if the file is a TypeScript file, and run those through swc to transpile // to JS. @@ -89,7 +96,7 @@ impl ModuleLoader for TsModuleLoader { // If there is no extension, assume .ts or .js (in that order) depending on if the path // exists. let path = match orig_path.extension() { - Some(_) => orig_path, + Some(_) => orig_path.clone(), None => { let mut maybe_ts = orig_path.clone(); maybe_ts.set_extension("ts"); @@ -108,38 +115,55 @@ impl ModuleLoader for TsModuleLoader { // Determine what the MediaType is (this is done based on the file // extension) and whether transpiling is required. let media_type = MediaType::from_path(&path); - let (module_type, should_transpile) = match media_type { + let (module_type, transpile_type) = match media_type { MediaType::JavaScript | MediaType::Mjs | MediaType::Cjs => { - (ModuleType::JavaScript, false) + (ModuleType::JavaScript, TranspileType::No) } - MediaType::Jsx => (ModuleType::JavaScript, true), + MediaType::Jsx => (ModuleType::JavaScript, TranspileType::Typescript), MediaType::TypeScript | MediaType::Mts | MediaType::Cts | MediaType::Dts | MediaType::Dmts | MediaType::Dcts - | MediaType::Tsx => (ModuleType::JavaScript, true), - MediaType::Json => (ModuleType::Json, false), + | MediaType::Tsx => (ModuleType::JavaScript, TranspileType::Typescript), + MediaType::Json => (ModuleType::Json, TranspileType::No), _ => { - return Err(anyhow!("Unknown extension {:?}", path.extension())); + let e = Err(anyhow!("Unknown extension {:?}", path.extension())); + match orig_path.extension() { + Some(os_str) => { + let lowercase_str = os_str.to_str().map(|s| s.to_lowercase()); + match lowercase_str.as_deref() { + Some("yaml") | Some("yml") => { + (ModuleType::Json, TranspileType::YAML) + } + _ => return e, + } + } + _ => return e, + } } }; // Read the file, transpile if necessary. let code = fs::read_to_string(&path)?; - let code = if should_transpile { - let parsed = deno_ast::parse_module(ParseParams { - specifier: module_specifier.to_string(), - text_info: SourceTextInfo::from_string(code), - media_type, - capture_tokens: false, - scope_analysis: false, - maybe_syntax: None, - })?; - parsed.transpile(&Default::default())?.text - } else { - code + let code = match transpile_type { + TranspileType::No => code, + TranspileType::Typescript => { + let parsed = deno_ast::parse_module(ParseParams { + specifier: module_specifier.to_string(), + text_info: SourceTextInfo::from_string(code), + media_type, + capture_tokens: false, + scope_analysis: false, + maybe_syntax: None, + })?; + parsed.transpile(&Default::default())?.text + } + TranspileType::YAML => { + let parsed: serde_json::Value = serde_yaml::from_str(&code)?; + serde_json::to_string(&parsed)? + } }; // Load and return module. diff --git a/tests/fixtures/import_json.js b/tests/fixtures/import_json.js new file mode 100644 index 0000000..1e861c3 --- /dev/null +++ b/tests/fixtures/import_json.js @@ -0,0 +1,8 @@ +// Copyright (c) Fensak, LLC. +// SPDX-License-Identifier: MPL-2.0 + +import cfg from "./someconfig.json" with { type: "json" }; + +export function main() { + return cfg; +} diff --git a/tests/fixtures/import_yaml.js b/tests/fixtures/import_yaml.js new file mode 100644 index 0000000..68a335a --- /dev/null +++ b/tests/fixtures/import_yaml.js @@ -0,0 +1,8 @@ +// Copyright (c) Fensak, LLC. +// SPDX-License-Identifier: MPL-2.0 + +import cfg from "./someconfig.yaml" with { type: "json" }; + +export function main() { + return cfg; +} diff --git a/tests/fixtures/someconfig.json b/tests/fixtures/someconfig.json new file mode 100644 index 0000000..8299a99 --- /dev/null +++ b/tests/fixtures/someconfig.json @@ -0,0 +1,3 @@ +{ + "msg": "hello world" +} diff --git a/tests/fixtures/someconfig.yaml b/tests/fixtures/someconfig.yaml new file mode 100644 index 0000000..e5e2d95 --- /dev/null +++ b/tests/fixtures/someconfig.yaml @@ -0,0 +1 @@ +msg: "hello world"