Every published package keeps its Node floor: >=18 in api, better-auth, definitions, express, fastify, helper-server, httpsig, nextjs, react; >=18.3 in quickstart; >=20 in email-verification and web-identity. Node 18 is EOL. Raising the floor is semver-major for every consumer, so it should be one coordinated release rather than package by package.
What a >=22 floor unblocks (all held back on chore/deps-latest for this reason):
- cookie 2.0.1 in api, express, nextjs — ESM-only, engines
>=22; parse → parseCookie, serialize(name, value, opts) → stringifySetCookie({ name, value, ...opts }). About six lines. Importing an ESM-only package from the CJS output fails type-checking under node16 resolution (TS1479) and at runtime on Node <20.19/22.12. Also removes the second cookie copy in cdk-client's protocol.zip.
- jose 6 in api, email-verification, web-identity — Node ≥19, ESM-only (
exports has only default), removes the KeyLike type these packages re-export. The tree currently has jose 5 there and jose 6 via better-auth.
- nanoid 6 in identifier — Node
^22.
- chalk 6 (Node ≥22) and open 11 (Node ≥20) in quickstart.
- better-auth CJS:
better-auth/api, better-auth/cookies, better-auth/oauth2 are ESM-only while @hellocoop/better-auth emits CJS. Works today via require(esm) (Node ≥20.19/22.12) but the package says >=18. Raise engines or make the package ESM.
- TypeScript 7: the CJS builds of httpsig, email-verification, web-identity (
tsconfig.cjs.json) and better-auth use module: CommonJS + moduleResolution: node10, which is behind ignoreDeprecations: "6.0" in TS 6 and removed in TS 7. Options: emit CJS with tsdown/tsup/esbuild, or drop the CJS build and ship ESM-only with an engines floor ≥20.19 (require(esm)). TS 7 is separately blocked by typescript-eslint (<6.1), svelte-check and @sveltejs/kit peer ranges.
@tsconfig/node18 (extended by all 15 tsconfigs; sets emitted target/lib/module) moves to @tsconfig/node22 with the floor.
Not unblocked by this, waiting on upstream peers: eslint 10 (eslint-plugin-react 7.37.5 peers ^9.7 max) and vitest 5 (better-auth 1.7.3 peerOptional vitest ^2||^3||^4).
Found during the Node 24 / dependency upgrade, 2026-09-06 (see chore/deps-prune branch)
Every published package keeps its Node floor:
>=18in api, better-auth, definitions, express, fastify, helper-server, httpsig, nextjs, react;>=18.3in quickstart;>=20in email-verification and web-identity. Node 18 is EOL. Raising the floor is semver-major for every consumer, so it should be one coordinated release rather than package by package.What a
>=22floor unblocks (all held back onchore/deps-latestfor this reason):>=22;parse→parseCookie,serialize(name, value, opts)→stringifySetCookie({ name, value, ...opts }). About six lines. Importing an ESM-only package from the CJS output fails type-checking under node16 resolution (TS1479) and at runtime on Node <20.19/22.12. Also removes the secondcookiecopy in cdk-client'sprotocol.zip.exportshas onlydefault), removes theKeyLiketype these packages re-export. The tree currently has jose 5 there and jose 6 via better-auth.^22.better-auth/api,better-auth/cookies,better-auth/oauth2are ESM-only while@hellocoop/better-authemits CJS. Works today viarequire(esm)(Node ≥20.19/22.12) but the package says>=18. Raise engines or make the package ESM.tsconfig.cjs.json) and better-auth usemodule: CommonJS+moduleResolution: node10, which is behindignoreDeprecations: "6.0"in TS 6 and removed in TS 7. Options: emit CJS with tsdown/tsup/esbuild, or drop the CJS build and ship ESM-only with an engines floor ≥20.19 (require(esm)). TS 7 is separately blocked by typescript-eslint (<6.1), svelte-check and @sveltejs/kit peer ranges.@tsconfig/node18(extended by all 15 tsconfigs; sets emittedtarget/lib/module) moves to@tsconfig/node22with the floor.Not unblocked by this, waiting on upstream peers: eslint 10 (eslint-plugin-react 7.37.5 peers
^9.7max) and vitest 5 (better-auth 1.7.3peerOptional vitest ^2||^3||^4).Found during the Node 24 / dependency upgrade, 2026-09-06 (see
chore/deps-prunebranch)