import { readFileSync } from "node:fs"; import { extname } from "node:path"; import type babel from "@babel/core"; import { transformSync } from "@babel/core"; import type * as esbuild from "esbuild"; import { once } from "lodash-es"; /** * An esbuild plugin that processes files with Babel if `plugins` is not empty. */ export const babelPlugin = ({ filter = /\.[jt]sx?$/, plugins: getPlugins, }: { filter?: RegExp; plugins: | babel.PluginItem[] | ((file: { path: string; contents: string }) => babel.PluginItem[]); }): esbuild.Plugin => ({ name: "babel-plugin", setup(build) { build.onLoad({ filter, namespace: "file" }, ({ path }) => { const load = once(() => readFileSync(path, "utf-8")); const plugins = Array.isArray(getPlugins) ? getPlugins : getPlugins({ path, get contents() { return load(); }, }); if (!plugins.length) { return; } const { code } = transformSync(load(), { assumptions: { noDocumentAll: true, noClassCalls: true, }, parserOpts: { createImportExpressions: true, plugins: [ "jsx", "decorators", "typescript", "importAttributes", "explicitResourceManagement", "v8intrinsic", ], }, filename: path, plugins, sourceType: "module", })!; return { contents: code!, loader: extname(path).slice(1) as "js" | "ts", }; }); }, });