oxc_transform_napi/
isolated_declaration.rs1use std::path::Path;
2
3use napi::{Task, bindgen_prelude::AsyncTask};
4use napi_derive::napi;
5
6use oxc::{
7 allocator::Allocator,
8 codegen::{Codegen, CodegenOptions, CommentOptions},
9 isolated_declarations::IsolatedDeclarations,
10 parser::Parser,
11 span::SourceType,
12};
13use oxc_napi::OxcError;
14use oxc_sourcemap::napi::SourceMap;
15
16#[napi(object)]
17pub struct IsolatedDeclarationsResult {
18 pub code: String,
19 pub map: Option<SourceMap>,
20 pub errors: Vec<OxcError>,
21}
22
23#[napi(object)]
24#[derive(Debug, Default, Clone, Copy)]
25pub struct IsolatedDeclarationsOptions {
26 pub strip_internal: Option<bool>,
33
34 pub sourcemap: Option<bool>,
35}
36
37impl From<IsolatedDeclarationsOptions> for oxc::isolated_declarations::IsolatedDeclarationsOptions {
38 fn from(options: IsolatedDeclarationsOptions) -> Self {
39 Self { strip_internal: options.strip_internal.unwrap_or_default() }
40 }
41}
42
43fn isolated_declaration_impl(
44 filename: &str,
45 source_text: &str,
46 options: Option<IsolatedDeclarationsOptions>,
47) -> IsolatedDeclarationsResult {
48 let source_path = Path::new(filename);
49 let source_type = SourceType::from_path(source_path).unwrap_or_default().with_typescript(true);
50 let allocator = Allocator::default();
51 let options = options.unwrap_or_default();
52
53 let ret = Parser::new(&allocator, source_text, source_type).parse();
54
55 let transformed_ret = IsolatedDeclarations::new(
56 &allocator,
57 oxc::isolated_declarations::IsolatedDeclarationsOptions {
58 strip_internal: options.strip_internal.unwrap_or(false),
59 },
60 )
61 .build(&ret.program);
62
63 let source_map_path = match options.sourcemap {
64 Some(true) => Some(source_path.to_path_buf()),
65 _ => None,
66 };
67 let codegen_ret = Codegen::new()
68 .with_options(CodegenOptions {
69 comments: CommentOptions { jsdoc: true, ..CommentOptions::disabled() },
70 source_map_path,
71 ..CodegenOptions::default()
72 })
73 .build(&transformed_ret.program);
74
75 let diagnostics = ret.errors.into_iter().chain(transformed_ret.errors).collect::<Vec<_>>();
76 let errors = OxcError::from_diagnostics(filename, source_text, diagnostics);
77
78 IsolatedDeclarationsResult {
79 code: codegen_ret.code,
80 map: codegen_ret.map.map(SourceMap::from),
81 errors,
82 }
83}
84
85#[allow(clippy::needless_pass_by_value, clippy::allow_attributes)]
87#[napi]
88pub fn isolated_declaration_sync(
89 filename: String,
90 source_text: String,
91 options: Option<IsolatedDeclarationsOptions>,
92) -> IsolatedDeclarationsResult {
93 isolated_declaration_impl(&filename, &source_text, options)
94}
95
96pub struct IsolatedDeclarationTask {
97 filename: String,
98 source_text: String,
99 options: Option<IsolatedDeclarationsOptions>,
100}
101
102#[napi]
103impl Task for IsolatedDeclarationTask {
104 type JsValue = IsolatedDeclarationsResult;
105 type Output = IsolatedDeclarationsResult;
106
107 fn compute(&mut self) -> napi::Result<Self::Output> {
108 Ok(isolated_declaration_impl(&self.filename, &self.source_text, self.options.take()))
109 }
110
111 fn resolve(&mut self, _: napi::Env, result: Self::Output) -> napi::Result<Self::JsValue> {
112 Ok(result)
113 }
114}
115
116#[napi]
120pub fn isolated_declaration(
121 filename: String,
122 source_text: String,
123 options: Option<IsolatedDeclarationsOptions>,
124) -> AsyncTask<IsolatedDeclarationTask> {
125 AsyncTask::new(IsolatedDeclarationTask { filename, source_text, options })
126}