diff --git a/tsdown.config.ts b/tsdown.config.ts index 0d39ea90..cb554d6e 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -20,8 +20,24 @@ export default defineConfig({ NODE_ENV: process.env.WIZARD_BUILD_NODE_ENV || 'production', }, - // Keep npm dependencies external — they're installed at runtime. - skipNodeModulesBundle: true, + // Keep npm dependencies external — they're installed at runtime — with one + // exception: semver is bundled into the output. + // + // semver's entry file eagerly `require()`s its entire ./functions/* and + // ./ranges/* submodule tree at load. When a package runner (npx/bunx) + // extracts a corrupted/partial semver tarball into its cache (a known failure + // mode when antivirus or a concurrent run interrupts extraction), that eager + // require throws MODULE_NOT_FOUND (e.g. './ranges/intersects', './functions/sort') + // before any wizard code runs — an instant, unrecoverable startup crash. + // Bundling semver means a corrupted runtime install can no longer surface a + // missing-submodule crash. semver is dependency-free, so this is self-contained. + // + // Note: `deps.skipNodeModulesBundle` and `deps.alwaysBundle` are mutually + // exclusive in tsdown, so we rely on the default behavior (externalize + // production dependencies declared in package.json) and force-bundle semver. + deps: { + alwaysBundle: ['semver'], + }, sourcemap: true, clean: true,