diff --git a/scripts/bash-bundle/build.mjs b/scripts/bash-bundle/build.mjs index b409bdf..e3e3acd 100644 --- a/scripts/bash-bundle/build.mjs +++ b/scripts/bash-bundle/build.mjs @@ -8,7 +8,7 @@ // // Prerequisites: npm install (just-bash and esbuild must be in node_modules) -import { execSync } from "node:child_process"; +import { build } from "esbuild"; import { readFileSync, writeFileSync, existsSync, unlinkSync } from "node:fs"; import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; @@ -32,37 +32,44 @@ if (!existsSync(join(repoRoot, "node_modules", "just-bash"))) { process.exit(1); } -const aliasArgs = [ - `--alias:node:module=${join(stubDir, "module-stub.mjs")}`, - `--alias:node:zlib=${join(stubDir, "zlib-stub.mjs")}`, - `--alias:node:worker_threads=${join(stubDir, "worker-stub.mjs")}`, - `--alias:node:path=${join(stubDir, "node-path-stub.mjs")}`, - `--alias:node:dns=${join(stubDir, "dns-stub.mjs")}`, - `--alias:node:crypto=${join(stubDir, "crypto-stub.mjs")}`, - `--alias:node:url=${join(stubDir, "url-stub.mjs")}`, - `--alias:node:fs=${join(stubDir, "fs-stub.mjs")}`, - `--alias:node:fs/promises=${join(stubDir, "fs-stub.mjs")}`, - `--alias:node:child_process=${join(stubDir, "worker-stub.mjs")}`, - `--alias:node:os=${join(stubDir, "worker-stub.mjs")}`, - `--alias:node:async_hooks=${join(stubDir, "worker-stub.mjs")}`, - `--alias:turndown=${join(stubDir, "turndown-stub.mjs")}`, - `--alias:seek-bzip=${join(stubDir, "bzip-stub.mjs")}`, - `--alias:node-liblzma=${join(stubDir, "liblzma-stub.mjs")}`, - `--alias:@mongodb-js/zstd=${join(stubDir, "zstd-stub.mjs")}`, - `--alias:sql.js=${join(stubDir, "sqljs-stub.mjs")}`, -].join(" "); +const alias = { + "node:module": join(stubDir, "module-stub.mjs"), + "node:zlib": join(stubDir, "zlib-stub.mjs"), + "node:worker_threads": join(stubDir, "worker-stub.mjs"), + "node:path": join(stubDir, "node-path-stub.mjs"), + "node:dns": join(stubDir, "dns-stub.mjs"), + "node:crypto": join(stubDir, "crypto-stub.mjs"), + "node:url": join(stubDir, "url-stub.mjs"), + "node:fs": join(stubDir, "fs-stub.mjs"), + "node:fs/promises": join(stubDir, "fs-stub.mjs"), + "node:child_process": join(stubDir, "worker-stub.mjs"), + "node:os": join(stubDir, "worker-stub.mjs"), + "node:async_hooks": join(stubDir, "worker-stub.mjs"), + turndown: join(stubDir, "turndown-stub.mjs"), + "seek-bzip": join(stubDir, "bzip-stub.mjs"), + "node-liblzma": join(stubDir, "liblzma-stub.mjs"), + "@mongodb-js/zstd": join(stubDir, "zstd-stub.mjs"), + "sql.js": join(stubDir, "sqljs-stub.mjs"), +}; const tmpBundle = join(stubDir, "_tmp_bundle.js"); -execSync( - `npx esbuild ${entryFile} ` + - `--bundle --format=esm --platform=neutral --target=es2020 ` + - `--main-fields=module,main ` + - `${aliasArgs} ` + - `--outfile=${tmpBundle} ` + - `--minify --tree-shaking=true`, - { stdio: "inherit", cwd: repoRoot }, -); +// Use esbuild's JS API rather than spawning the CLI. This avoids passing +// interpolated paths through a shell entirely (resolving the CodeQL +// shell-injection alert) and is portable: the esbuild CLI bin is a native +// binary on some platforms, so it can't be launched via `node`. +await build({ + entryPoints: [entryFile], + bundle: true, + format: "esm", + platform: "neutral", + target: "es2020", + mainFields: ["module", "main"], + alias, + outfile: tmpBundle, + minify: true, + treeShaking: true, +}); // ── Step 2: Prepend polyfills ─────────────────────────────────────── diff --git a/scripts/build-modules.js b/scripts/build-modules.js index 9f0da01..c69933f 100644 --- a/scripts/build-modules.js +++ b/scripts/build-modules.js @@ -12,12 +12,14 @@ * 7. Regenerates host-modules.d.ts */ -import { execSync } from "child_process"; +import { execSync, execFileSync } from "child_process"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; +import { createRequire } from "module"; import { existsSync, unlinkSync, readdirSync, statSync } from "fs"; const __dirname = dirname(fileURLToPath(import.meta.url)); +const require = createRequire(import.meta.url); const ROOT = join(__dirname, ".."); const BUILTIN_DIR = join(ROOT, "builtin-modules"); const PLUGINS_DIR = join(ROOT, "plugins"); @@ -68,10 +70,20 @@ execSync("npx tsx scripts/generate-ha-modules-dts.ts", { }); // Step 4: Format with Prettier -execSync(`prettier --write "${BUILTIN_DIR}/*.js"`, { - cwd: ROOT, - stdio: "inherit", -}); +// Invoke prettier without a shell (execFileSync) so the interpolated path +// can't be interpreted as a shell command. Prettier expands the glob itself. +execFileSync( + process.execPath, + [ + require.resolve("prettier/bin/prettier.cjs"), + "--write", + join(BUILTIN_DIR, "*.js"), + ], + { + cwd: ROOT, + stdio: "inherit", + }, +); console.log("\nUpdating module hashes..."); @@ -161,5 +173,4 @@ execSync("npx tsx scripts/generate-host-modules-dts.ts", { stdio: "inherit", }); - console.log("✓ Build complete");