/** * Name: bundle-import * Version: 0.0.2 * Author: CondorHero * Homepage: https://github.com/condorheroblog/bundle-import#readme * License MIT © 2023-Present */ 'use strict'; var importFromString = require('import-from-string'); var node_path = require('node:path'); var node_fs = require('node:fs'); var node_url = require('node:url'); var process = require('node:process'); var getTsconfig = require('get-tsconfig'); const JS_EXT_RE = /\.([mc]?[tj]s|[tj]sx)$/; async function moduleFromString(code, options) { const isESM = options.format === "esm"; if (isESM) { return await importFromString.importFromString(code, { filename: options.filename, dirname: options.dirname, skipBuild: false }); } else { return importFromString.requireFromString(code, { filename: options.filename, dirname: options.dirname }); } } var name = "bundle-import"; var version = "0.0.2"; function 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}/`); }); } function externalPlugin({ external, notExternal } = {}) { return { name: `${name}:external`, setup(ctx) { ctx.onResolve({ filter: /.*/ }, async (args) => { if (args.path[0] === "." || node_path.isAbsolute(args.path)) { return; } if (match(args.path, external)) { return { external: true }; } if (match(args.path, notExternal)) { return; } return { external: true }; }); } }; } const DIRNAME_VAR_NAME = "__injected_dirname__"; const FILENAME_VAR_NAME = "__injected_filename__"; const IMPORT_META_URL_VAR_NAME = "__injected_import_meta_url__"; function injectFileScopePlugin() { return { name: `[${name}]:inject-file-scope`, setup(build) { build.initialOptions.define = { ...build.initialOptions.define, "__dirname": DIRNAME_VAR_NAME, "__filename": FILENAME_VAR_NAME, "import.meta.url": IMPORT_META_URL_VAR_NAME }; build.onLoad({ filter: JS_EXT_RE }, async (args) => { const contents = await node_fs.promises.readFile(args.path, "utf-8"); const injectLines = [ `const ${FILENAME_VAR_NAME} = ${JSON.stringify(args.path)};`, `const ${DIRNAME_VAR_NAME} = ${JSON.stringify(node_path.dirname(args.path))};`, `const ${IMPORT_META_URL_VAR_NAME} = ${JSON.stringify(node_url.pathToFileURL(args.path).href)};` ]; return { contents: injectLines.join("") + contents, loader: importFromString.inferLoader(node_path.extname(args.path)) }; }); } }; } function getPkgType() { try { const pkg = JSON.parse(node_fs.readFileSync(node_path.resolve("package.json"), "utf-8")); return pkg.type; } catch { } } function guessFormat(inputFile, type = getPkgType()) { const ext = node_path.extname(inputFile); if (ext === ".js") { return type === "module" ? "esm" : "cjs"; } else if (ext === ".ts" || ext === ".mts" || ext === ".mjs") { return "esm"; } return "cjs"; } function tsconfigPathsToRegExp(paths) { return Object.keys(paths).map((key) => { return new RegExp(`^${key.replace(/\*/, ".*")}$`); }); } function resolveOptions(options) { return { filepath: options.filepath, tsconfig: options.tsconfig ?? "tsconfig.json", external: options.external ?? [], cwd: options.cwd ?? process.cwd(), format: options.format ?? guessFormat(options.filepath), esbuildOptions: options.esbuildOptions }; } function bundleImport(options) { return new Promise((resolve, reject) => { if (!JS_EXT_RE.test(options.filepath)) { throw new Error(`${options.filepath} is not a valid JS file`); } const resolved = resolveOptions(options); const tsconfig = getTsconfig.getTsconfig(resolved.cwd, options.tsconfig) ?? getTsconfig.getTsconfig(resolved.cwd, "jsconfig.json"); importFromString.buildBundler({ entryPoints: [resolved.filepath], absWorkingDir: resolved.cwd, outfile: "out.js", format: resolved.format, platform: "node", bundle: true, metafile: true, write: false, ...resolved.esbuildOptions, plugins: [ externalPlugin({ external: resolved.external, notExternal: tsconfigPathsToRegExp(tsconfig?.config.compilerOptions?.paths ?? {}) }), injectFileScopePlugin(), ...resolved.esbuildOptions?.plugins ?? [] ] }).then(async (result) => { if (result.outputFiles) { const absFilePath = node_path.join(resolved.cwd, resolved.filepath); const code = result.outputFiles[0].text; const mod = await moduleFromString(code, { format: resolved.format, dirname: node_path.dirname(absFilePath), filename: node_path.basename(absFilePath) }); resolve({ mod, dependencies: result.metafile?.inputs || {} }); } resolve({ mod: {}, dependencies: {} }); }).catch(reject); }); } exports.JS_EXT_RE = JS_EXT_RE; exports.bundleImport = bundleImport; exports.getPkgType = getPkgType; exports.guessFormat = guessFormat; exports.moduleFromString = moduleFromString; exports.resolveOptions = resolveOptions; exports.tsconfigPathsToRegExp = tsconfigPathsToRegExp; exports.version = version;