From af209f564f59480c71a365acb74ef29bc517945c Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 26 Jul 2024 10:43:34 -0400 Subject: [PATCH] fix(bundling): explicitly set types for exports entries in package.json --- e2e/rollup/src/rollup-legacy.test.ts | 4 +++ e2e/rollup/src/rollup.test.ts | 4 +++ .../package-json/update-package-json.spec.ts | 26 ++++++++++++++----- .../package-json/update-package-json.ts | 25 +++++++++++++----- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/e2e/rollup/src/rollup-legacy.test.ts b/e2e/rollup/src/rollup-legacy.test.ts index ac11f8a6c3ce6..c3c70043c5d4d 100644 --- a/e2e/rollup/src/rollup-legacy.test.ts +++ b/e2e/rollup/src/rollup-legacy.test.ts @@ -44,6 +44,7 @@ describe('Rollup Plugin', () => { module: './index.esm.js', import: './index.cjs.mjs', default: './index.cjs.js', + types: './index.esm.d.ts', }, './package.json': './package.json', }); @@ -111,16 +112,19 @@ describe('Rollup Plugin', () => { module: './index.esm.js', import: './index.cjs.mjs', default: './index.cjs.js', + types: './index.esm.d.ts', }, './bar': { module: './bar.esm.js', import: './bar.cjs.mjs', default: './bar.cjs.js', + types: './bar.esm.d.ts', }, './foo': { module: './foo.esm.js', import: './foo.cjs.mjs', default: './foo.cjs.js', + types: './foo.esm.d.ts', }, }); }); diff --git a/e2e/rollup/src/rollup.test.ts b/e2e/rollup/src/rollup.test.ts index 9b8cb11c40cfa..02f1d9ada9d9e 100644 --- a/e2e/rollup/src/rollup.test.ts +++ b/e2e/rollup/src/rollup.test.ts @@ -47,6 +47,7 @@ describe('Rollup Plugin', () => { module: './index.esm.js', import: './index.cjs.mjs', default: './index.cjs.js', + types: './index.esm.d.ts', }, './package.json': './package.json', }); @@ -142,16 +143,19 @@ describe('Rollup Plugin', () => { module: './index.esm.js', import: './index.cjs.mjs', default: './index.cjs.js', + types: './index.esm.d.ts', }, './bar': { module: './bar.esm.js', import: './bar.cjs.mjs', default: './bar.cjs.js', + types: './bar.esm.d.ts', }, './foo': { module: './foo.esm.js', import: './foo.cjs.mjs', default: './foo.cjs.js', + types: './foo.esm.d.ts', }, }); }); diff --git a/packages/rollup/src/plugins/package-json/update-package-json.spec.ts b/packages/rollup/src/plugins/package-json/update-package-json.spec.ts index c04a83889728c..c10f92a926e15 100644 --- a/packages/rollup/src/plugins/package-json/update-package-json.spec.ts +++ b/packages/rollup/src/plugins/package-json/update-package-json.spec.ts @@ -30,7 +30,10 @@ describe('updatePackageJson', () => { expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { exports: { './package.json': './package.json', - '.': './index.esm.js', + '.': { + import: './index.esm.js', + types: './index.esm.d.ts', + }, }, main: './index.esm.js', module: './index.esm.js', @@ -85,11 +88,12 @@ describe('updatePackageJson', () => { module: './index.esm.js', import: './index.cjs.mjs', default: './index.cjs.js', + types: './index.esm.d.ts', }, }, main: './index.cjs.js', module: './index.esm.js', - types: './index.cjs.d.ts', + types: './index.esm.d.ts', }); spy.mockRestore(); @@ -106,7 +110,10 @@ describe('updatePackageJson', () => { }, { exports: { - './foo': './foo.esm.js', + './foo': { + import: './some/custom/path/foo.esm.js', + types: './some/custom/path/foo.d.ts', + }, }, } as unknown as PackageJson ); @@ -114,9 +121,14 @@ describe('updatePackageJson', () => { expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { exports: { './package.json': './package.json', - '.': './index.esm.js', - - './foo': './foo.esm.js', + '.': { + import: './index.esm.js', + types: './index.esm.d.ts', + }, + './foo': { + import: './some/custom/path/foo.esm.js', + types: './some/custom/path/foo.d.ts', + }, }, main: './index.esm.js', module: './index.esm.js', @@ -184,7 +196,7 @@ describe('updatePackageJson', () => { expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { main: './index.cjs.js', module: './index.esm.js', - types: './index.cjs.d.ts', + types: './index.esm.d.ts', }); spy.mockRestore(); diff --git a/packages/rollup/src/plugins/package-json/update-package-json.ts b/packages/rollup/src/plugins/package-json/update-package-json.ts index aaddad649afe8..ce5cf85295b7c 100644 --- a/packages/rollup/src/plugins/package-json/update-package-json.ts +++ b/packages/rollup/src/plugins/package-json/update-package-json.ts @@ -40,12 +40,14 @@ export function updatePackageJson( if (options.generateExportsField) { for (const [exportEntry, filePath] of Object.entries(esmExports)) { - packageJson.exports[exportEntry] = hasCjsFormat - ? // If CJS format is used, make sure `import` (from Node) points to same instance of the package. - // Otherwise, packages that are required to be singletons (like React, RxJS, etc.) will break. - // Reserve `module` entry for bundlers to accommodate tree-shaking. - { [hasCjsFormat ? 'module' : 'import']: filePath } - : filePath; + packageJson.exports[exportEntry] = + // If CJS format is used, make sure `import` (from Node) points to same instance of the package. + // Otherwise, packages that are required to be singletons (like React, RxJS, etc.) will break. + // Reserve `module` entry for bundlers to accommodate tree-shaking. + { + [hasCjsFormat ? 'module' : 'import']: filePath, + types: filePath.replace(/\.js$/, '.d.ts'), + }; } } } @@ -72,6 +74,11 @@ export function updatePackageJson( const fauxEsmFilePath = filePath.replace(/\.cjs\.js$/, '.cjs.mjs'); packageJson.exports[exportEntry]['import'] ??= fauxEsmFilePath; packageJson.exports[exportEntry]['default'] ??= filePath; + // Set `types` field only if it's not already set as the preferred ESM Format. + packageJson.exports[exportEntry]['types'] ??= filePath.replace( + /\.js$/, + '.d.ts' + ); // Re-export from relative CJS file, and Node will synthetically export it as ESM. // Make sure both ESM and CJS point to same instance of the package because libs like React, RxJS, etc. requires it. // Also need a special .cjs.default.js file that re-exports the `default` from CJS, or else @@ -102,7 +109,11 @@ export function updatePackageJson( } } - packageJson.types ??= packageJson.main.replace(/\.js$/, '.d.ts'); + if (packageJson.module) { + packageJson.types ??= packageJson.module.replace(/\.js$/, '.d.ts'); + } else { + packageJson.types ??= packageJson.main.replace(/\.js$/, '.d.ts'); + } writeJsonFile( join(workspaceRoot, options.outputPath, 'package.json'),