summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreu Botella <andreu@andreubotella.com>2022-01-31 13:43:32 +0100
committerGitHub <noreply@github.com>2022-01-31 13:43:32 +0100
commit56ea75817e57a908a3894abc7f1b85327d8a2efb (patch)
tree9770c0ed39dba51779a6e68bebaada7edf8156d1
parent68c8c66b0f0889657e48742aed05030c70e0a266 (diff)
example(core): Add example for TypeScript transpiling via deno_ast (#13545)
-rw-r--r--Cargo.lock1
-rw-r--r--core/Cargo.toml1
-rw-r--r--core/examples/ts_module_loader.rs122
3 files changed, 124 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 28c8eb83b..0d89411c7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -835,6 +835,7 @@ name = "deno_core"
version = "0.117.0"
dependencies = [
"anyhow",
+ "deno_ast",
"futures",
"indexmap",
"libc",
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 972975085..4bf6b9aeb 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -33,4 +33,5 @@ path = "examples/http_bench_json_ops.rs"
# These dependencies are only used for the 'http_bench_*_ops' examples.
[dev-dependencies]
+deno_ast = { version = "0.9.0", features = ["transpiling"] }
tokio = { version = "1.10.1", features = ["full"] }
diff --git a/core/examples/ts_module_loader.rs b/core/examples/ts_module_loader.rs
new file mode 100644
index 000000000..963533ffc
--- /dev/null
+++ b/core/examples/ts_module_loader.rs
@@ -0,0 +1,122 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+//! This example shows how to use swc to transpile TypeScript and JSX/TSX
+//! modules.
+//!
+//! It will only transpile, not typecheck (like Deno's `--no-check` flag).
+
+use std::pin::Pin;
+use std::rc::Rc;
+
+use anyhow::anyhow;
+use anyhow::bail;
+use anyhow::Error;
+use deno_ast::MediaType;
+use deno_ast::ParseParams;
+use deno_ast::SourceTextInfo;
+use deno_core::resolve_import;
+use deno_core::resolve_path;
+use deno_core::JsRuntime;
+use deno_core::ModuleLoader;
+use deno_core::ModuleSource;
+use deno_core::ModuleSourceFuture;
+use deno_core::ModuleSpecifier;
+use deno_core::ModuleType;
+use deno_core::RuntimeOptions;
+use futures::FutureExt;
+
+struct TypescriptModuleLoader;
+
+impl ModuleLoader for TypescriptModuleLoader {
+ fn resolve(
+ &self,
+ specifier: &str,
+ referrer: &str,
+ _is_main: bool,
+ ) -> Result<ModuleSpecifier, Error> {
+ Ok(resolve_import(specifier, referrer)?)
+ }
+
+ fn load(
+ &self,
+ module_specifier: &ModuleSpecifier,
+ _maybe_referrer: Option<ModuleSpecifier>,
+ _is_dyn_import: bool,
+ ) -> Pin<Box<ModuleSourceFuture>> {
+ let module_specifier = module_specifier.clone();
+ async move {
+ let path = module_specifier
+ .to_file_path()
+ .map_err(|_| anyhow!("Only file: URLs are supported."))?;
+
+ let media_type = MediaType::from(&path);
+ let (module_type, should_transpile) = match MediaType::from(&path) {
+ MediaType::JavaScript | MediaType::Mjs | MediaType::Cjs => {
+ (ModuleType::JavaScript, false)
+ }
+ MediaType::Jsx => (ModuleType::JavaScript, true),
+ MediaType::TypeScript
+ | MediaType::Mts
+ | MediaType::Cts
+ | MediaType::Dts
+ | MediaType::Dmts
+ | MediaType::Dcts
+ | MediaType::Tsx => (ModuleType::JavaScript, true),
+ MediaType::Json => (ModuleType::Json, false),
+ _ => bail!("Unknown extension {:?}", path.extension()),
+ };
+
+ let code = std::fs::read_to_string(&path)?;
+ let code = if should_transpile {
+ let parsed = deno_ast::parse_module(ParseParams {
+ specifier: module_specifier.to_string(),
+ source: SourceTextInfo::from_string(code),
+ media_type,
+ capture_tokens: false,
+ scope_analysis: false,
+ maybe_syntax: None,
+ })?;
+ parsed.transpile(&Default::default())?.text
+ } else {
+ code
+ };
+ let module = ModuleSource {
+ code,
+ module_type,
+ module_url_specified: module_specifier.to_string(),
+ module_url_found: module_specifier.to_string(),
+ };
+ Ok(module)
+ }
+ .boxed_local()
+ }
+}
+
+fn main() -> Result<(), Error> {
+ let args: Vec<String> = std::env::args().collect();
+ if args.len() < 2 {
+ println!("Usage: target/examples/debug/ts_module_loader <path_to_module>");
+ std::process::exit(1);
+ }
+ let main_url = args[1].clone();
+ println!("Run {}", main_url);
+
+ let mut js_runtime = JsRuntime::new(RuntimeOptions {
+ module_loader: Some(Rc::new(TypescriptModuleLoader)),
+ ..Default::default()
+ });
+
+ let main_module = resolve_path(&main_url)?;
+
+ let future = async move {
+ let mod_id = js_runtime.load_main_module(&main_module, None).await?;
+ let _ = js_runtime.mod_evaluate(mod_id);
+ js_runtime.run_event_loop(false).await?;
+ Ok(())
+ };
+
+ tokio::runtime::Builder::new_current_thread()
+ .enable_all()
+ .build()
+ .unwrap()
+ .block_on(future)
+}