From a950b995f207f1a21d547c0ac38f633ecd483c17 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 30 Apr 2024 12:54:24 -0700 Subject: [PATCH 1/2] fix(ses): fix broken types for CJS consumers Due to changes in TS v5.5, CJS consumers cannot import types from a `type: module` package unless the declaration file has the `.d.cts` extension. This may or may not work the other way. See https://devblogs.microsoft.com/typescript/announcing-typescript-5-5-beta/\#respecting-file-extensions-and-packagejson-in-other-module-modes for explanation. --- packages/ses/package.json | 26 ++++++++++++++++++-------- packages/ses/scripts/bundle.js | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/packages/ses/package.json b/packages/ses/package.json index 7e084c953d..5f85596f29 100644 --- a/packages/ses/package.json +++ b/packages/ses/package.json @@ -35,15 +35,25 @@ "unpkg": "./dist/ses.umd.js", "types": "./types.d.ts", "exports": { - ".": { - "types": "./types.d.ts", - "import": "./index.js", - "require": "./dist/ses.cjs" + ".": { + "import": { + "types": "./types.d.ts", + "default": "./index.js" + }, + "require": { + "types": "./dist/types.d.cts", + "default": "./dist/ses.cjs" + } }, - "./lockdown": { - "types": "./types.d.ts", - "import": "./index.js", - "require": "./dist/ses.cjs" + "./lockdown": { + "import": { + "types": "./types.d.ts", + "default": "./index.js" + }, + "require": { + "types": "./dist/types.d.cts", + "default": "./dist/ses.cjs" + } }, "./tools.js": "./tools.js", "./assert-shim.js": "./assert-shim.js", diff --git a/packages/ses/scripts/bundle.js b/packages/ses/scripts/bundle.js index d34fe238f2..da6ee816b3 100644 --- a/packages/ses/scripts/bundle.js +++ b/packages/ses/scripts/bundle.js @@ -53,6 +53,30 @@ const main = async () => { ...bundleFilePaths.map(dest => write(dest, versionedBundle)), ...terseFilePaths.map(dest => write(dest, terse)), ]); + + // When importing types from a CJS package, TS v5.5+ considers the "module" + // field in `ses`' `package.json`, so any .d.ts file is considered to be "ESM + // types" (I'm sure this makes sense if you think hard enojugh about it; let + // us know if it does). For CJS, we need to provide a `.d.cts` file instead. + // It's unclear if this file can be identical to the original in _all_ cases, + // or just ours. I imagine ES-specific types (e.g., `import.meta`) would break + // in CJS, but generally consumers have `skipLibCheck` enabled, so ¯\_(ツ)_/¯ + + // Also: this operation is in this script for portability's sake. + + /** The "ESM types" */ + const sourceDTS = /** @type {string} */ ( + packageJson.exports['.'].import.types + ); + /** The "CJS types" */ + const destDTS = /** @type {string} */ ( + packageJson.exports['.'].require.types + ); + await fs.promises.copyFile( + fileURLToPath(new URL(sourceDTS, root)), + fileURLToPath(new URL(destDTS, root)), + ); + console.log(`Copied ${sourceDTS} to ${destDTS}`); }; main().catch(err => { From 5f7e78eec7532944a8d0bf7bef032224eee41f2f Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Mon, 6 May 2024 12:20:49 -0700 Subject: [PATCH 2/2] chore(ses): update comment Co-authored-by: Kris Kowal --- packages/ses/NEWS.md | 1 + packages/ses/package.json.md | 26 ++++++++++++++++++++------ packages/ses/scripts/bundle.js | 9 +++++---- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/ses/NEWS.md b/packages/ses/NEWS.md index 427377ede1..a7f9c241d4 100644 --- a/packages/ses/NEWS.md +++ b/packages/ses/NEWS.md @@ -3,6 +3,7 @@ User-visible changes in SES: # Next release - Adds `importNowHook` to the `Compartment` options. The compartment will invoke the hook whenever it encounters a missing dependency while running `compartmentInstance.importNow(specifier)`, which cannot use an asynchronous `importHook`. +- To support TypeScript v5.5, a CommonJS-specific type declaration file is now explicitly exported. # v1.3.0 (2024-02-22) diff --git a/packages/ses/package.json.md b/packages/ses/package.json.md index 219038f772..b8321311a5 100644 --- a/packages/ses/package.json.md +++ b/packages/ses/package.json.md @@ -94,7 +94,11 @@ However, `@web/dev-server` gets confused by the extension. The variations differ only in file name extension. -## "import": "./index.js" +### "import": { + +Node.js and TypeScript will use these when importing `ses` as an ESM. + +#### "default": "./index.js" Node.js and other tools will use this file when importing `ses` as an ESM. (JavaScript module). @@ -102,16 +106,26 @@ We have in the past experimented with using the precompiled bundle of SES here (`./dist/ses.cjs` or `./dist/ses.umd.js`), but found that this interacted poorly with Endo, because an Endo bundle contains identifiers that SES censors. -## "require": "./dist/ses.cjs" - -Node.js and other tools will use this file when importing `ses` as an CommonJS module. - -## "types": "./types.d.ts" +#### "types": "./types.d.ts" Only applicable for TypeScript v4.7+ consumers configured with `node16` or `nodenext` [module resolution][]. This serves the same purpose as the `types` prop at the top level. +### "require": { + +Node.js and TypesScript will use these when importing `ses` as a CommonJS module. + +#### "default": "./dist/ses.cjs" + +Node.js and other tools will use this file when importing `ses` as an CommonJS module. + +#### "types": "./dist/types.d.cts" + +As of TypeScript v5.5 beta, if a package is an ESM package (`"type": "module"`), any `.d.ts` file in the package is considered to be for ESM consumers only. If CommonJS is targeted, ESM packages must now export types in `.d.cts` files. Think of it this way: *`.d.ts` is to `.d.cts` as `.js` is to `.cjs`*. + +At build time, `./types.d.ts` is copied to `./dist/types.d.ts`; it is otherwise identical. + ## "./lockdown" The most recent SES only provides one API, but a previous version diff --git a/packages/ses/scripts/bundle.js b/packages/ses/scripts/bundle.js index da6ee816b3..542995a6ac 100644 --- a/packages/ses/scripts/bundle.js +++ b/packages/ses/scripts/bundle.js @@ -56,11 +56,12 @@ const main = async () => { // When importing types from a CJS package, TS v5.5+ considers the "module" // field in `ses`' `package.json`, so any .d.ts file is considered to be "ESM - // types" (I'm sure this makes sense if you think hard enojugh about it; let - // us know if it does). For CJS, we need to provide a `.d.cts` file instead. + // types". + // For CJS, we need to provide a `.d.cts` file instead. // It's unclear if this file can be identical to the original in _all_ cases, - // or just ours. I imagine ES-specific types (e.g., `import.meta`) would break - // in CJS, but generally consumers have `skipLibCheck` enabled, so ¯\_(ツ)_/¯ + // or just ours. + // We imagine ES-specific types (e.g., `import.meta`) would break + // in CJS, but generally consumers have `skipLibCheck` enabled. // Also: this operation is in this script for portability's sake.