diff --git a/packages/node-modules-tools/src/analyze-esm.test.ts b/packages/node-modules-tools/src/analyze-esm.test.ts index 77adb7f..a157b1d 100644 --- a/packages/node-modules-tools/src/analyze-esm.test.ts +++ b/packages/node-modules-tools/src/analyze-esm.test.ts @@ -26,4 +26,14 @@ describe('analyzePackageModuleType', () => { exports: nestExports(11, './index.mjs'), })).toBe('unknown') }) + + it('handles main: false without crashing', () => { + // Some packages (e.g. math-intrinsics, dunder-proto) declare "main": false + // to indicate exports-only packages. Should not crash. + expect(analyze({ + name: 'math-intrinsics', + main: false as any, + exports: { './abs': './abs.js' }, + })).toBe('unknown') + }) }) diff --git a/packages/node-modules-tools/src/analyze-esm.ts b/packages/node-modules-tools/src/analyze-esm.ts index 9eb96fe..e42fcb7 100644 --- a/packages/node-modules-tools/src/analyze-esm.ts +++ b/packages/node-modules-tools/src/analyze-esm.ts @@ -69,13 +69,16 @@ export function analyzePackageModuleType(pkgJson: PackageJson): PackageModuleTyp if (pkgJson.name?.startsWith('@types/')) return 'dts' + // Ensure main is a string (can be false in some packages) + const main = typeof pkgJson.main === 'string' ? pkgJson.main : undefined + // Native binary packages (e.g. @oxc-parser/binding-linux-x64-gnu) - if (pkgJson.main?.endsWith('.node')) + if (main?.endsWith('.node')) return 'bin' const hasExports = pkgJson.exports != null const hasModule = !!pkgJson.module - const hasMain = !!pkgJson.main + const hasMain = !!main const isTypeModule = pkgJson.type === 'module' // Check exports field for module format indicators @@ -103,15 +106,15 @@ export function analyzePackageModuleType(pkgJson: PackageJson): PackageModuleTyp // Legacy detection (no exports or exports without clear conditions) if (hasModule && hasMain) { - const mainIsCJS = pkgJson.main?.endsWith('.cjs') - || (pkgJson.main?.endsWith('.js') && !isTypeModule) + const mainIsCJS = main?.endsWith('.cjs') + || (main?.endsWith('.js') && !isTypeModule) return mainIsCJS ? 'faux' : 'esm' } if (hasModule) return 'faux' - if (isTypeModule || (hasMain && pkgJson.main?.endsWith('.mjs'))) + if (isTypeModule || (hasMain && main?.endsWith('.mjs'))) return 'esm' if (hasMain)