Repository navigation
build!: ship ESM-only output for Node.js ^20.19.0 || >=22.12.0 - #97
Merged
Merged
Conversation
donskov
force-pushed
the
donskov/webcrypto-3-test
branch
from
October 27, 2026 10:03
107f5cc to
4f8379b
Compare
This was referenced Oct 27, 2026
donskov
force-pushed
the
donskov/webcrypto-4-build
branch
from
October 27, 2026 10:56
f55b59b to
7a1d61c
Compare
Replace rollup and @rollup/plugin-typescript with tsdown, using the
pvtsutils/webcrypto-core config with platform "node" (the mechanisms
use node:crypto) and the SPDX banner. Types are generated from the
source, so the hand-written index.d.ts is gone. tsconfig follows
pvtsutils with lib DOM, types ["node"] and experimentalDecorators
(@JsonProp in src). Type-only imports for verbatimModuleSyntax, tslib
dropped, dev dependencies updated (TypeScript stays on 6).
Crypto.subtle is typed with the DOM SubtleCrypto overloads on top of
core's type, so consumer code written against the old index.d.ts
(EcdsaParams/AesGcmParams literals, `as const` usages) still compiles.
src/index.spec.ts covers that. @types/node stays on 25: 26 drops the
crypto.RsaPublicKey/RsaPrivateKey option types the RSA code uses.
BREAKING CHANGE: @peculiar/webcrypto is ESM-only and requires Node.js
^20.19.0 || >=22.12.0 (was >=14.18.0). The bundles
build/webcrypto.js (CommonJS) and build/webcrypto.es.js and the
hand-written index.d.ts are replaced by unbundled ES modules with
build/index.js and build/index.d.ts as the entry point; the
react-native field is removed. Deep imports into build/ are blocked by
exports. CommonJS code can still require("@peculiar/webcrypto") on
supported Node.js versions through require(esm); Node.js 22.0-22.11
can't. TypeScript projects that compile to CommonJS need "module":
"node20" or "nodenext". The exported names (Crypto, CryptoKey) are
unchanged; their declarations are now generated, so Crypto shows its
webcrypto-core base class. See "Breaking Changes In v2" in the README.
donskov
force-pushed
the
donskov/webcrypto-4-build
branch
from
October 27, 2026 11:07
7a1d61c to
1f210fb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #87: the package is now
"type": "module"with a single ESM entry (build/index.js), so theimportcondition no longer points at ESM syntax in a CommonJS-typed.jsfile. Verified withtsx@4.23.1from the report.Stacked on #96 (part 4 of 7 for @peculiar/webcrypto 2.0.0; merge in order).
Packaging only.
@rollup/plugin-typescript→ tsdown (webcrypto-core's config +platform: "node", SPDX banner kept). Generated declarations replace the hand-writtenindex.d.ts.tslib,rimraf,react-nativefield and theclear/rebuildscripts are gone.lib: ["es2023", "DOM"](typecheck fails without DOM:KeyUsage,JsonWebKey, …),types: ["node"],experimentalDecorators(@JsonPropinsrc/keys,src/mechs/{aes,des,hmac}). NostripInternal.engines>=14.18.0→^20.19.0 || >=22.12.0,"type": "module","sideEffects": false,publishConfig.access: public,filesbuild/,README.md,LICENSE.md.@types/nodestays on 25 (rule 1 exception). 26 drops thecrypto.RsaPublicKey/RsaPrivateKeyoption types the RSA code uses, and 24 and lower reject the DOMJsonWebKeyincreatePublicKey({ format: "jwk" }). On 25 the source compiles unchanged.crypto.subtlewould be core'sSubtleCrypto, which only acceptsAlgorithmIdentifier. Code that compiles against 1.7.1 (sign({ name: "ECDSA", hash }),encrypt({ name: "AES-GCM", iv }),generateKey(..., usages as const)) would fail.Crypto.subtleis nowGenerateKeyPair & SubtleCrypto & globalThis.SubtleCrypto;src/index.spec.tscompiles these calls innpm run typecheck.Public types vs npm 1.7.1
index.d.tsclass Crypto implements globalThis.Cryptoclass Crypto extends core.Crypto(whichimplements globalThis.Crypto)subtle: SubtleCrypto(DOM)subtle: GenerateKeyPair & SubtleCrypto & globalThis.SubtleCrypto; addsprovidersand core's overloadsgetRandomValues<T extends ArrayBufferView | null>(array: T): TrandomUUID(): \${string}-…``class CryptoKey implements globalThis.CryptoKey(algorithm,extractable,type,usages)CryptoKey(same members, plus staticcreate/isKeyType)Same two runtime exports. Consumers still need the DOM lib (as with 1.7.1). Consumer call shapes, 1.7.1 vs 2.0.0: all compile in both.
Verification (packed tarball of the full stack, installed with its peers)
Workload: ECDSA P-256 sign/verify, JWK and PKCS8/SPKI round trips, AES-GCM, RSA-PSS, Ed25519, and pkijs 4
setEngine/CryptoEnginewith a self-signed certificate sign/parse/verify().require()importERR_REQUIRE_ESM(expected)Dual-package probe:
require(x).Crypto === import(x).Cryptorequire(x).CryptoKey === import(x).CryptoKeyCryptoKey=== coreCryptoKey(require / import)requireinstanceofimport / coreCryptoKeyimportCrypto signs / exports JWK with arequirekeysideEffects: false(rolldown 1.2.15, esbuild 0.28.2, webpack 5.112.2, target node):falsetrue@JsonPropregistrations)CryptoKeyonlyTypeScript 6 consumers (
skipLibCheck: false, noexperimentalDecorators, lib DOM):nodenext,node20(.mtsand.cts)preserve+bundlernode16.mtspass,.ctsTS1479 (documented)commonjs+node10ignoreDeprecations: "6.0"; then passes withskipLibCheck. WithskipLibCheck: false, 2 × TS2307 from webcrypto-core 2's own.d.ts(@peculiar/utils/bytessubpath); core alone reproduces itrelease-please dry run on the full stack: finds
v1.7.1, proposeschore(release): v2.0.0with both BREAKING CHANGE notes.BEGIN_COMMIT_OVERRIDE
build!: ship ESM-only output for Node.js ^20.19.0 || >=22.12.0
BREAKING CHANGE: @peculiar/webcrypto is ESM-only and requires Node.js ^20.19.0 || >=22.12.0 (was >=14.18.0). The bundles build/webcrypto.js (CommonJS) and build/webcrypto.es.js and the hand-written index.d.ts are replaced by unbundled ES modules with build/index.js and build/index.d.ts as the entry point; the react-native field is removed. Deep imports into build/ stay blocked by exports. CommonJS code can still require("@peculiar/webcrypto") on supported Node.js versions through require(esm); Node.js 22.0-22.11 can't. require() and import now load the same module, so CryptoKey instanceof checks and keys work across both. TypeScript projects that compile to CommonJS need "module": "node20" or "nodenext". The exported names (Crypto, CryptoKey) are unchanged; their declarations are now generated, so Crypto shows its webcrypto-core base class. See "Breaking Changes In v2" in the README.
END_COMMIT_OVERRIDE