Rest/Struct/
SWC.rs

1#[derive(Debug, Clone, Serialize, Deserialize)]
2pub struct FileInfo {
3	path: PathBuf,
4	last_modified: SystemTime,
5}
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct CompilerConfig {
9	pub Target: String,
10	pub Module: String,
11	pub Strict: bool,
12	pub EmitDecoratorsMetadata: bool,
13}
14
15#[derive(Debug, Clone)]
16pub struct Option {
17	pub entry: Vec<Vec<String>>,
18	pub separator: char,
19	pub pattern: String,
20	pub config: CompilerConfig,
21}
22
23#[derive(Debug, Default)]
24pub struct CompilerMetrics {
25	pub Count: usize,
26	pub Elapsed: Duration,
27	pub Error: usize,
28}
29
30impl Default for CompilerConfig {
31	fn default() -> Self {
32		Self {
33			Target: "es2022".to_string(),
34			Module: "commonjs".to_string(),
35			Strict: true,
36			EmitDecoratorsMetadata: true,
37		}
38	}
39}
40
41#[derive(Debug)]
42pub struct Compiler {
43	pub config: CompilerConfig,
44	pub Outlook: Arc<Mutex<CompilerMetrics>>,
45}
46
47impl Compiler {
48	pub fn new(config: CompilerConfig) -> Self {
49		Self { config, Outlook: Arc::new(Mutex::new(CompilerMetrics::default())) }
50	}
51
52	#[tracing::instrument(skip(self, input))]
53	pub fn compile_file(&self, File: &str, input: String) -> anyhow::Result<String> {
54		let Begin = Instant::now();
55
56		let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
57
58		let source_file = cm.new_source_file(FileName::Real(File.into()).into(), input);
59
60		let mut parser = Parser::new_from(Lexer::new(
61			Syntax::Typescript(Default::default()),
62			EsVersion::Es2022,
63			StringInput::from(&*source_file),
64			None,
65		));
66
67		let module = parser.parse_module().map_err(|e| anyhow::anyhow!("Failed to parse TypeScript module: {:?}", e))?;
68
69		let Unresolved = Mark::new();
70		let Top = Mark::new();
71
72		// Convert module to program to apply passes
73		let mut program = swc_ecma_ast::Program::Module(module);
74
75		// Apply transforms using process() or visit_mut_with()
76		
77		// 1. Resolver
78		{
79			let mut pass = swc_ecma_transforms_base::resolver(Unresolved, Top, true);
80			pass.process(&mut program);
81		}
82
83		// 2. Strip TypeScript
84		{
85			let mut pass = swc_ecma_transforms_typescript::strip(Unresolved, Top);
86			pass.process(&mut program);
87		}
88		
89		// 3. Decorators
90		{
91			let mut pass = decorators::decorators(decorators::Config {
92				legacy: false,
93				emit_metadata: self.config.EmitDecoratorsMetadata,
94				use_define_for_class_fields: true,
95				..Default::default()
96			});
97			pass.process(&mut program);
98		}
99
100		// 4. Inject Helpers
101		{
102			let mut pass = inject_helpers(Unresolved);
103			pass.process(&mut program);
104		}
105
106		// Convert back to module for emitting
107		let module = match program {
108			swc_ecma_ast::Program::Module(m) => m,
109			_ => return Err(anyhow::anyhow!("Unexpected script")),
110		};
111
112		let mut Output = vec![];
113
114		let mut Emitter = Emitter {
115			cfg: swc_ecma_codegen::Config::default(),
116			cm: cm.clone(),
117			comments: None,
118			wr: JsWriter::new(cm.clone(), "\n", &mut Output, None),
119		};
120
121		Emitter.emit_module(&module).map_err(|e| anyhow::anyhow!("Failed to emit JavaScript: {:?}", e))?;
122
123		let Path = Path::new(File).with_extension("js");
124
125		std::fs::write(&Path, &Output)?;
126
127		let Elapsed = Begin.elapsed();
128
129		{
130			let mut Outlook = self.Outlook.lock().unwrap();
131			Outlook.Count += 1;
132			Outlook.Elapsed += Elapsed;
133		}
134
135		debug!("Compiled {} in {:?}", File, Elapsed);
136
137		Ok(Path.to_string_lossy().to_string())
138	}
139}
140
141use std::path::{Path, PathBuf};
142use std::sync::{Arc, Mutex};
143use std::time::{Duration, Instant, SystemTime};
144use serde::{Deserialize, Serialize};
145use tracing::debug;
146use swc_common::{SourceMap, FilePathMapping, FileName, Mark};
147use swc_ecma_ast::{EsVersion, Pass};
148use swc_ecma_parser::{Parser, StringInput, Syntax, lexer::Lexer};
149use swc_ecma_codegen::{Emitter, text_writer::JsWriter};
150use swc_ecma_transforms_base::helpers::inject_helpers;
151use swc_ecma_transforms_proposal::decorators;