Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-third-party-dts-extractor-esm-require.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@module-federation/third-party-dts-extractor': patch
---

Fix `extractThirdParty` silently producing no output when `@module-federation/dts-plugin` runs as ESM. `getPackageRootDir()` and `resolvePackageJson()` called the bare `require.resolve()`, which tsup's ESM build shims to a stub without `.resolve`; the resulting TypeError was swallowed, leaving third-party type extraction a no-op. Both now resolve via `createRequire(import.meta.url)`, matching existing usage elsewhere in the monorepo.
4 changes: 4 additions & 0 deletions packages/third-party-dts-extractor/src/ThirdPartyExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { copyFile, lstat, mkdir, readdir } from 'fs/promises';
import { existsSync, readFileSync } from 'fs';
import path from 'path';
import { createRequire } from 'node:module';
import { getTypedName, getPackageRootDir, resolvePackageJson } from './utils';

// See utils.ts: bare `require` is not a real require in tsup's ESM output.
const require = createRequire(import.meta.url);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid import.meta.url in the CommonJS build

When consumers load the package through its documented require export, tsup.config.ts emits this source as CommonJS, where esbuild replaces unsupported import.meta with an empty object. This consequently calls createRequire(undefined) and throws ERR_INVALID_ARG_VALUE during module initialization, breaking the entire CommonJS entry point; use a build-format-safe filename/URL or configure a CommonJS shim while retaining import.meta.url for ESM.

AGENTS.md reference: AGENTS.md:L289-L289

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed — verified by building this exact source in isolation with tsup 7.3.0. Without shims, the cjs output does exactly what you describe: import.meta becomes {}, so createRequire(import_meta.url) is createRequire(undefined) and throws ERR_INVALID_ARG_VALUE at module load, breaking require() for every consumer.

Enabled tsup's shims: true option in tsup.config.ts (see latest commit), which injects a proper import.meta.url polyfill (new URL("file:" + __filename).href) for the cjs build. Re-verified both outputs directly: cjs and esm now both resolve correctly with no crash.

Thanks for catching this before it shipped.


const ignoredPkgs = ['typescript'];

// require.resolve('path')==='path'
Expand Down
7 changes: 7 additions & 0 deletions packages/third-party-dts-extractor/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import path from 'node:path';
import fs from 'node:fs';
import { createRequire } from 'node:module';

// tsup's ESM output shims bare `require` to a stub whose `.resolve` is
// undefined, so `getPackageRootDir`/`resolvePackageJson` silently failed
// (caught by their callers) whenever this package ran as ESM. A require
// bound via createRequire() works in both the cjs and esm builds.
const require = createRequire(import.meta.url);

function getTypedName(name: string) {
return `@types/${name.replace(/^@/, '').replace('/', '__')}`;
Expand Down
5 changes: 5 additions & 0 deletions packages/third-party-dts-extractor/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ const shared = {
splitting: true,
outDir: join('packages', 'third-party-dts-extractor', 'dist'),
external: [join(__dirname, 'package.json')],
// Needed so createRequire(import.meta.url) in src/utils.ts and
// src/ThirdPartyExtractor.ts resolves to a real file URL in the cjs
// build too — without this, esbuild leaves import.meta empty under
// the cjs target and createRequire(undefined) throws at load time.
shims: true,
};

export default defineConfig([
Expand Down