import type { TransformOptions as BabelTransformOptions, PluginItem, } from "@babel/core"; import { transformSync } from "@babel/core"; import proposalDecoratorsPlugin from "@babel/plugin-proposal-decorators"; import syntaxClassPropertiesPlugin from "@babel/plugin-syntax-class-properties"; import syntaxImportAssertionsPlugin from "@babel/plugin-syntax-import-assertions"; import syntaxJSXPlugin from "@babel/plugin-syntax-jsx"; import transformExportNamespaceFromPlugin from "@babel/plugin-transform-export-namespace-from"; import transformReactJSX from "@babel/plugin-transform-react-jsx"; import transformTypeScriptPlugin from "@babel/plugin-transform-typescript"; import parameterDecoratorPlugin from "babel-plugin-parameter-decorator"; import transformTypeScriptMetaPlugin from "./plugins/babel-plugin-transform-typescript-metadata"; import importMetaEnvPlugin from "./plugins/import-meta-env"; import importMetaResolvePlugin from "./plugins/import-meta-resolve"; import importMetaPathsPlugin from "./plugins/import-meta-paths"; import transformModulesPlugin from "./plugins/transform-module"; import type { TransformOptions, TransformResult } from "./types"; export default function transform(opts: TransformOptions): TransformResult { const _opts: BabelTransformOptions & { plugins: PluginItem[] } = { babelrc: false, configFile: false, compact: false, retainLines: typeof opts.retainLines === "boolean" ? opts.retainLines : true, filename: "", cwd: "/", ...opts.babel, plugins: [ [ transformModulesPlugin, { allowTopLevelThis: true, noInterop: !opts.interopDefault, async: opts.async, }, ], [importMetaPathsPlugin, { filename: opts.filename }], [importMetaEnvPlugin], [importMetaResolvePlugin], [syntaxClassPropertiesPlugin], [transformExportNamespaceFromPlugin], ], }; if (opts.jsx) { _opts.plugins.push( [syntaxJSXPlugin], [transformReactJSX, Object.assign({}, opts.jsx)], ); } if (opts.ts) { _opts.plugins.push([ transformTypeScriptPlugin, { allowDeclareFields: true, isTSX: opts.jsx && /\.[cm]?tsx$/.test(opts.filename || ""), }, ]); // `unshift` because these plugin must come before `@babel/plugin-syntax-class-properties` _opts.plugins.unshift( [transformTypeScriptMetaPlugin], [proposalDecoratorsPlugin, { legacy: true }], ); _opts.plugins.push(parameterDecoratorPlugin); _opts.plugins.push(syntaxImportAssertionsPlugin); } if (opts.babel && Array.isArray(opts.babel.plugins)) { _opts.plugins?.push(...opts.babel.plugins); } try { return { code: transformSync(opts.source, _opts)?.code || "", }; } catch (error: any) { return { error, code: "exports.__JITI_ERROR__ = " + JSON.stringify({ filename: opts.filename, line: error.loc?.line || 0, column: error.loc?.column || 0, code: error.code ?.replace("BABEL_", "") .replace("PARSE_ERROR", "ParseError"), message: error.message?.replace("/: ", "").replace(/\(.+\)\s*$/, ""), }), }; } }