next_swc_napi/
react_compiler.rs1use std::{path::PathBuf, sync::Arc};
2
3use napi::bindgen_prelude::*;
4use napi_derive::napi;
5use next_custom_transforms::react_compiler;
6use swc_core::{
7 common::{GLOBALS, SourceMap},
8 ecma::{
9 ast::EsVersion,
10 parser::{Syntax, TsSyntax, parse_file_as_program},
11 },
12};
13
14pub struct CheckTask {
15 pub filename: PathBuf,
16}
17
18#[napi]
19impl Task for CheckTask {
20 type Output = bool;
21 type JsValue = bool;
22
23 fn compute(&mut self) -> napi::Result<Self::Output> {
24 GLOBALS.set(&Default::default(), || {
25 let cm = Arc::new(SourceMap::default());
27 let Ok(fm) = cm.load_file(&self.filename) else {
28 return Ok(false);
29 };
30 let mut errors = vec![];
31 let Ok(program) = parse_file_as_program(
32 &fm,
33 Syntax::Typescript(TsSyntax {
34 tsx: true,
35 ..Default::default()
36 }),
37 EsVersion::EsNext,
38 None,
39 &mut errors,
40 ) else {
41 return Ok(false);
42 };
43 if !errors.is_empty() {
44 return Ok(false);
45 }
46
47 Ok(react_compiler::is_required(&program))
48 })
49 }
50
51 fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result<Self::JsValue> {
52 Ok(result)
53 }
54}
55
56#[napi]
57pub fn is_react_compiler_required(
58 filename: String,
59 signal: Option<AbortSignal>,
60) -> AsyncTask<CheckTask> {
61 let filename = PathBuf::from(filename);
62 AsyncTask::with_optional_signal(CheckTask { filename }, signal)
63}