From b3860c0cc74beca3888fc4b11e103350447a3579 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 28 Mar 2026 11:28:40 +0000 Subject: [PATCH] fix: auto-detect native binary distributor packages as externals Packages like @secure-exec/v8 distribute platform-specific native binaries via optionalDependencies (e.g. @secure-exec/v8-darwin-arm64). These packages use createRequire(import.meta.url).resolve() at runtime to locate the correct platform binary, which breaks when esbuild bundles them because import.meta.url then points to the bundle output directory. Add a heuristic to the auto-external detection that checks if a package has optionalDependencies with platform-specific names (darwin, linux, win32, etc.). When 2+ such deps are found, the package is marked as external so it resolves binaries from its real node_modules location. https://claude.ai/code/session_01ScLShmDQ92z8bY9A2T1cPB --- packages/cli-v3/src/build/externals.ts | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/cli-v3/src/build/externals.ts b/packages/cli-v3/src/build/externals.ts index c35f90cf182..296cbe825ad 100644 --- a/packages/cli-v3/src/build/externals.ts +++ b/packages/cli-v3/src/build/externals.ts @@ -402,6 +402,14 @@ function createExternalsCollector( return markExternal("binding.gyp exists"); } + // Check if the package distributes platform-specific native binaries + // via optionalDependencies (common pattern for Rust/napi-rs packages). + // These packages use createRequire(import.meta.url).resolve() at runtime + // to locate the correct platform binary, which breaks when bundled. + if (hasPlatformSpecificOptionalDeps(packageJson)) { + return markExternal("has platform-specific optionalDependencies"); + } + // Cache the negative result isExternalCache.set(packageRoot, false); @@ -655,3 +663,28 @@ async function findNearestPackageJson( cache.set(baseDir, packageJsonPath); return packageJsonPath; } + +// Matches platform/arch identifiers commonly found in native binary package names +// e.g. @secure-exec/v8-darwin-arm64, @rollup/rollup-linux-x64-gnu, esbuild-windows-64 +const platformPattern = + /[-.](darwin|linux|win32|windows|freebsd|android|macos|sunos|openbsd|aix)/i; + +function hasPlatformSpecificOptionalDeps(packageJson: Record): boolean { + const optionalDeps = packageJson.optionalDependencies; + + if (!optionalDeps || typeof optionalDeps !== "object") { + return false; + } + + const depNames = Object.keys(optionalDeps); + + if (depNames.length === 0) { + return false; + } + + // If a significant portion of optionalDependencies match platform patterns, + // this is likely a native binary distributor package + const platformDeps = depNames.filter((name) => platformPattern.test(name)); + + return platformDeps.length >= 2; +}