1use anyhow::Context;
30use napi::bindgen_prelude::*;
31use swc_core::{
32 base::{TransformOutput, config::JsMinifyOptions, try_with_handler},
33 common::{FileName, GLOBALS, errors::ColorConfig},
34};
35
36use crate::{get_compiler, util::MapErr};
37
38pub struct MinifyTask {
39 c: swc_core::base::Compiler,
40 code: Option<String>,
41 opts: JsMinifyOptions,
42}
43
44#[napi]
45impl Task for MinifyTask {
46 type Output = TransformOutput;
47
48 type JsValue = TransformOutput;
49
50 fn compute(&mut self) -> napi::Result<Self::Output> {
51 let code = self.code.take().unwrap_or_default();
52
53 try_with_handler(
54 self.c.cm.clone(),
55 swc_core::base::HandlerOpts {
56 color: ColorConfig::Never,
57 skip_filename: true,
58 },
59 |handler| {
60 GLOBALS.set(&Default::default(), || {
61 let fm = self.c.cm.new_source_file(FileName::Anon.into(), code);
62
63 self.c.minify(fm, handler, &self.opts, Default::default())
64 })
65 },
66 )
67 .map_err(|e| e.to_pretty_error())
68 .convert_err()
69 }
70
71 fn resolve(&mut self, _: napi::Env, output: Self::Output) -> napi::Result<Self::JsValue> {
72 Ok(output)
73 }
74}
75
76#[napi]
77pub fn minify(
78 input: Buffer,
79 opts: Buffer,
80 signal: Option<AbortSignal>,
81) -> napi::Result<AsyncTask<MinifyTask>> {
82 let code = String::from_utf8(input.into())
83 .context("failed to convert input to string")
84 .convert_err()?;
85 let opts = serde_json::from_slice(&opts)?;
86
87 let c = get_compiler();
88
89 let task = MinifyTask {
90 c,
91 code: Some(code),
92 opts,
93 };
94
95 Ok(AsyncTask::with_optional_signal(task, signal))
96}
97
98#[napi]
99pub fn minify_sync(input: Buffer, opts: Buffer) -> napi::Result<TransformOutput> {
100 let code = String::from_utf8(input.into())
101 .context("failed to convert input to string")
102 .convert_err()?;
103 let opts = serde_json::from_slice(&opts)?;
104
105 let c = get_compiler();
106
107 let fm = c.cm.new_source_file(FileName::Anon.into(), code);
108
109 try_with_handler(
110 c.cm.clone(),
111 swc_core::base::HandlerOpts {
112 color: ColorConfig::Never,
113 skip_filename: true,
114 },
115 |handler| {
116 GLOBALS.set(&Default::default(), || {
117 c.minify(fm, handler, &opts, Default::default())
118 })
119 },
120 )
121 .map_err(|e| e.to_pretty_error())
122 .convert_err()
123}