// src/index.ts
import fs2 from "fs";
import path2 from "path";
import { pathToFileURL } from "url";
import {
build,
context
} from "esbuild";
import { loadTsConfig } from "load-tsconfig";
// src/utils.ts
import fs from "fs";
import path from "path";
import { createRequire } from "module";
var getPkgType = () => {
try {
const pkg = JSON.parse(
fs.readFileSync(path.resolve("package.json"), "utf-8")
);
return pkg.type;
} catch (error) {
}
};
function guessFormat(inputFile) {
if (!usingDynamicImport)
return "cjs";
const ext = path.extname(inputFile);
const type = getPkgType();
if (ext === ".js") {
return type === "module" ? "esm" : "cjs";
} else if (ext === ".ts" || ext === ".mts") {
return "esm";
} else if (ext === ".mjs") {
return "esm";
}
return "cjs";
}
var usingDynamicImport = typeof jest === "undefined";
var dynamicImport = async (id, { format }) => {
const fn = format === "esm" ? (file) => import(file) : true ? createRequire(import.meta.url) : __require;
return fn(id);
};
var getRandomId = () => {
return Math.random().toString(36).substring(2, 15);
};
// src/index.ts
var DIRNAME_VAR_NAME = "__injected_dirname__";
var FILENAME_VAR_NAME = "__injected_filename__";
var IMPORT_META_URL_VAR_NAME = "__injected_import_meta_url__";
var JS_EXT_RE = /\.([mc]?[tj]s|[tj]sx)$/;
var PATH_NODE_MODULES_RE = /[\/\\]node_modules[\/\\]/;
function inferLoader(ext) {
if (ext === ".mjs" || ext === ".cjs")
return "js";
if (ext === ".mts" || ext === ".cts")
return "ts";
return ext.slice(1);
}
var defaultReadFile = (filepath) => fs2.readFileSync(filepath, "utf-8");
var defaultGetOutputFile = (filepath, format) => filepath.replace(
JS_EXT_RE,
`.bundled_${getRandomId()}.${format === "esm" ? "mjs" : "cjs"}`
);
var tsconfigPathsToRegExp = (paths) => {
return Object.keys(paths || {}).map((key) => {
return new RegExp(`^${key.replace(/\*/, ".*")}$`);
});
};
var match = (id, patterns) => {
if (!patterns)
return false;
return patterns.some((p) => {
if (p instanceof RegExp) {
return p.test(id);
}
return id === p || id.startsWith(p + "/");
});
};
var externalPlugin = ({
external,
notExternal,
externalNodeModules = true
} = {}) => {
return {
name: "bundle-require:external",
setup(ctx) {
ctx.onResolve({ filter: /.*/ }, async (args) => {
if (match(args.path, external)) {
return {
external: true
};
}
if (match(args.path, notExternal)) {
return;
}
if (externalNodeModules && args.path.match(PATH_NODE_MODULES_RE)) {
const resolved = args.path[0] === "." ? path2.resolve(args.resolveDir, args.path) : args.path;
return {
path: pathToFileURL(resolved).toString(),
external: true
};
}
if (args.path[0] === "." || path2.isAbsolute(args.path)) {
return;
}
return {
external: true
};
});
}
};
};
var injectFileScopePlugin = ({
readFile = defaultReadFile
} = {}) => {
return {
name: "bundle-require:inject-file-scope",
setup(ctx) {
ctx.initialOptions.define = {
...ctx.initialOptions.define,
__dirname: DIRNAME_VAR_NAME,
__filename: FILENAME_VAR_NAME,
"import.meta.url": IMPORT_META_URL_VAR_NAME
};
ctx.onLoad({ filter: JS_EXT_RE }, (args) => {
const contents = readFile(args.path);
const injectLines = [
`const ${FILENAME_VAR_NAME} = ${JSON.stringify(args.path)};`,
`const ${DIRNAME_VAR_NAME} = ${JSON.stringify(
path2.dirname(args.path)
)};`,
`const ${IMPORT_META_URL_VAR_NAME} = ${JSON.stringify(
pathToFileURL(args.path).href
)};`
];
return {
contents: injectLines.join("") + contents,
loader: inferLoader(path2.extname(args.path))
};
});
}
};
};
function bundleRequire(options) {
return new Promise((resolve, reject) => {
var _a, _b, _c, _d, _e;
if (!JS_EXT_RE.test(options.filepath)) {
throw new Error(`${options.filepath} is not a valid JS file`);
}
const preserveTemporaryFile = (_a = options.preserveTemporaryFile) != null ? _a : !!process.env.BUNDLE_REQUIRE_PRESERVE;
const cwd = options.cwd || process.cwd();
const format = (_b = options.format) != null ? _b : guessFormat(options.filepath);
const tsconfig = options.tsconfig === false ? void 0 : typeof options.tsconfig === "string" || !options.tsconfig ? loadTsConfig(cwd, options.tsconfig) : { data: options.tsconfig, path: void 0 };
const resolvePaths = tsconfigPathsToRegExp(
((_c = tsconfig == null ? void 0 : tsconfig.data.compilerOptions) == null ? void 0 : _c.paths) || {}
);
const extractResult = async (result) => {
if (!result.outputFiles) {
throw new Error(`[bundle-require] no output files`);
}
const { text } = result.outputFiles[0];
const getOutputFile = options.getOutputFile || defaultGetOutputFile;
const outfile = getOutputFile(options.filepath, format);
await fs2.promises.writeFile(outfile, text, "utf8");
let mod;
const req = options.require || dynamicImport;
try {
mod = await req(
format === "esm" ? pathToFileURL(outfile).href : outfile,
{ format }
);
} finally {
if (!preserveTemporaryFile) {
await fs2.promises.unlink(outfile);
}
}
return {
mod,
dependencies: result.metafile ? Object.keys(result.metafile.inputs) : []
};
};
const { watch: watchMode, ...restEsbuildOptions } = options.esbuildOptions || {};
const esbuildOptions = {
...restEsbuildOptions,
entryPoints: [options.filepath],
absWorkingDir: cwd,
outfile: "out.js",
format,
platform: "node",
sourcemap: "inline",
bundle: true,
metafile: true,
write: false,
...(tsconfig == null ? void 0 : tsconfig.path) ? { tsconfig: tsconfig.path } : { tsconfigRaw: (tsconfig == null ? void 0 : tsconfig.data) || {} },
plugins: [
...((_d = options.esbuildOptions) == null ? void 0 : _d.plugins) || [],
externalPlugin({
external: options.external,
notExternal: [...options.notExternal || [], ...resolvePaths],
externalNodeModules: (_e = options.externalNodeModules) != null ? _e : !options.filepath.match(PATH_NODE_MODULES_RE)
}),
injectFileScopePlugin({
readFile: options.readFile
})
]
};
const run = async () => {
if (!(watchMode || options.onRebuild)) {
const result = await build(esbuildOptions);
resolve(await extractResult(result));
} else {
const rebuildCallback = typeof watchMode === "object" && typeof watchMode.onRebuild === "function" ? watchMode.onRebuild : async (error, result) => {
var _a2, _b2;
if (error) {
(_a2 = options.onRebuild) == null ? void 0 : _a2.call(options, { err: error });
}
if (result) {
(_b2 = options.onRebuild) == null ? void 0 : _b2.call(options, await extractResult(result));
}
};
const onRebuildPlugin = () => {
return {
name: "bundle-require:on-rebuild",
setup(ctx2) {
let count = 0;
ctx2.onEnd(async (result) => {
if (count++ === 0) {
if (result.errors.length === 0)
resolve(await extractResult(result));
} else {
if (result.errors.length > 0) {
return rebuildCallback(
{ errors: result.errors, warnings: result.warnings },
null
);
}
if (result) {
rebuildCallback(null, result);
}
}
});
}
};
};
esbuildOptions.plugins.push(onRebuildPlugin());
const ctx = await context(esbuildOptions);
await ctx.watch();
}
};
run().catch(reject);
});
}
export {
JS_EXT_RE,
bundleRequire,
dynamicImport,
externalPlugin,
injectFileScopePlugin,
loadTsConfig,
match,
tsconfigPathsToRegExp
};