Skip to content

Update to minimum node version 22.14 #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 19, 2025
Merged
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
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,21 @@ npx builder --type=module --outDir=build-esm-bundle --entryPoint=index.ts --outF

This module includes a number of integration-style tests,
to ensure that a specific version of TypeScript will interoperate
with `builder`, in addition to libraries and frameworks used by Check Digit:
with `builder`, in addition to runtimes, libraries and frameworks used by Check Digit:

- Recent TC39 proposals
- Node versions supported by AWS Lambda, Google Cloud Functions, and Azure Functions
- ESLint and `@typescript-eslint/eslint-plugin`
- Built-in `node:test` runner
- prettier
- tsc
- esbuild
- `prettier`
- `tsc`, and specific features introduced in each version of TypeScript
- `esbuild`
- Wallaby.js (supports `node:test` by including `@swc-node/register` as a peer dependency)

We do this to ensure that TypeScript upgrades do not break these dependencies.
New major versions of TypeScript are not immediately
We do this to ensure that TypeScript upgrades do not break these dependencies,
and that updates to these related projects do not break builds.

Note: New major versions of TypeScript are not immediately
supported by projects such as eslint, prettier, typescript-eslint,
etc. Our policy is to wait until these projects fully support
the new version of TypeScript, and/or without emitting warnings during these tests, before publishing.
Expand All @@ -77,8 +81,7 @@ Strict semver is a little complicated, as TypeScript itself does not adhere to s
We coordinate this with whatever the latest LTS version of Node is currently supported by Amazon Lambda,
Google Cloud Functions, and Azure Functions.
- Each new "major" version of TypeScript (e.g. `5.7.x` to `5.8.x`) will result in a new minor version of this module.
- A new minor update of TypeScript (e.g. `5.7.2` to `5.7.3`) _may_ result in a patch, in
a situation where a specific need or issue requires setting a new minimum version of TypeScript.
- A new minor update of TypeScript (e.g. `5.7.2` to `5.7.3`) or a key dependency (e.g., Node `22.11` to Node `22.14`) _may_ result in a patch.

Bear in mind, any update of TypeScript can potentially break your build. But hopefully in a way that's useful.

Expand Down
672 changes: 335 additions & 337 deletions package-lock.json

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@checkdigit/typescript-config",
"version": "9.1.0",
"version": "9.1.1",
"description": "Check Digit standard Typescript configuration",
"homepage": "https://github.com/checkdigit/typescript-config#readme",
"bugs": {
Expand Down Expand Up @@ -46,9 +46,9 @@
"build:dist-mjs": "rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs",
"build:dist-types": "rimraf dist-types && npx builder --type=types --outDir=dist-types",
"build:mjs": "rimraf build-mjs && bin/builder.mjs --type=module --outDir=build-mjs",
"build:mjs-bundle": "rimraf build-mjs-bundle && bin/builder.mjs --type=module --outDir=build-mjs-bundle --entryPoint=test/index.ts --outFile=test/index.mjs",
"build:mjs-bundle-minify": "rimraf build-mjs-bundle-minify && bin/builder.mjs --type=module --minify --outDir=build-mjs-bundle-minify --entryPoint=test/index.ts --outFile=test/index.mjs",
"build:mjs-bundle-no-external": "rimraf build-mjs-bundle-no-external && bin/builder.mjs --type=module --external=./node_modules/* --outDir=build-mjs-bundle-no-external --entryPoint=test/index.ts --outFile=test/index.mjs --minify",
"build:mjs-bundle": "rimraf build-mjs-bundle && bin/builder.mjs --type=module --outDir=build-mjs-bundle --entryPoint=index.test.ts --outFile=index.test.mjs",
"build:mjs-bundle-minify": "rimraf build-mjs-bundle-minify && bin/builder.mjs --type=module --minify --outDir=build-mjs-bundle-minify --entryPoint=index.test.ts --outFile=index.test.mjs",
"build:mjs-bundle-no-external": "rimraf build-mjs-bundle-no-external && bin/builder.mjs --type=module --external=./node_modules/* --outDir=build-mjs-bundle-no-external --entryPoint=index.test.ts --outFile=index.test.mjs --minify",
"build:types": "rimraf build-types && bin/builder.mjs --type=types --outDir=build-types",
"ci:compile": "tsc --noEmit --rootDir src",
"ci:lint": "npm run lint",
Expand All @@ -62,30 +62,30 @@
"prettier:fix": "prettier --ignore-path .gitignore --write .",
"test": "npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style",
"test:mjs": "node --test build-mjs/test/index.mjs",
"test:mjs-bundle": "node --test build-mjs-bundle/test/index.mjs",
"test:mjs-bundle-minify": "node --test build-mjs-bundle-minify/test/index.mjs",
"test:mjs-bundle-no-external": "node --test build-mjs-bundle-no-external/test/index.mjs",
"test:mjs-bundle": "node --test build-mjs-bundle/index.test.mjs",
"test:mjs-bundle-minify": "node --test build-mjs-bundle-minify/index.test.mjs",
"test:mjs-bundle-no-external": "node --test build-mjs-bundle-no-external/index.test.mjs",
"test:node-mjs": "node --disable-warning ExperimentalWarning --experimental-strip-types --test-timeout 600000 --test \"src/**/*.spec.ts\""
},
"prettier": "@checkdigit/prettier-config",
"devDependencies": {
"@checkdigit/prettier-config": "^6.3.0",
"@eslint/js": "^9.21.0",
"@eslint/json": "^0.10.0",
"@eslint/markdown": "^6.2.2",
"eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.2",
"@eslint/js": "^9.22.0",
"@eslint/json": "^0.11.0",
"@eslint/markdown": "^6.3.0",
"eslint": "^9.22.0",
"eslint-config-prettier": "^10.1.1",
"eslint-plugin-yml": "^1.17.0",
"rimraf": "^6.0.1",
"typescript-eslint": "^8.26.0"
"typescript-eslint": "^8.26.1"
},
"peerDependencies": {
"@swc-node/register": "1.10.9",
"@types/node": ">=22.11",
"esbuild": "0.25.0",
"@swc-node/register": "1.10.10",
"@types/node": ">=22",
"esbuild": "0.25.1",
"typescript": ">=5.8.2 <5.9.0"
},
"engines": {
"node": ">=22.11"
"node": ">=22.14"
}
}
3 changes: 3 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// index.ts

import './test/index.ts';
1 change: 1 addition & 0 deletions src/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// test/index.ts

import './lib/index.ts';
import './node/index.ts';
import './typescript/index.ts';
2 changes: 1 addition & 1 deletion src/test/lib/es2023.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';

describe('supports es2023', () => {
describe('es2023', () => {
it('supports Array.findLastIndex (from es2023.array)', async () => {
assert.equal(
['a', 'b', 'c'].findLastIndex((value) => value === 'b'),
Expand Down
2 changes: 1 addition & 1 deletion src/test/lib/es2024.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';

describe('supports es2024', () => {
describe('es2024', () => {
// https://github.com/tc39/proposal-array-grouping
it('supports array grouping', async () => {
const objectGroupBy = Object.groupBy([0, 1, 2, 3, 4, 5], (num) => (num % 2 === 0 ? 'even' : 'odd'));
Expand Down
48 changes: 39 additions & 9 deletions src/test/lib/es2025.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';

describe('supports es2025', () => {
describe('es2025', () => {
// https://github.com/tc39/proposal-duplicate-named-capturing-groups
it('supports duplicate named capturing groups', async () => {
// commented out due to parsing error in Node 22 (works in Node 23)
// assert.equal(/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u.exec('12-1984')?.groups?.['year'], '1984');
// assert.equal(/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u.exec('1984-12')?.groups?.['year'], '1984');
});
if (process.version < 'v23') {
it('does not support duplicate named capturing groups', async () => {
assert.throws(
// eslint-disable-next-line no-eval
() => eval("/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u.exec('12-1984')?.groups?.['year']"),
{
name: 'SyntaxError',
message:
'Invalid regular expression: /(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u: Duplicate capture group name',
},
);
});
} else {
it('supports duplicate named capturing groups', async () => {
assert.equal(
// eslint-disable-next-line no-eval
eval("/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u.exec('12-1984')?.groups?.['year']"),
'1984',
);
// commented out due to parsing error in Node 22 (works in Node 23)
// assert.equal(/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u.exec('12-1984')?.groups?.['year'], '1984');
// assert.equal(/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/u.exec('1984-12')?.groups?.['year'], '1984');
});
}

// https://github.com/tc39/proposal-set-methods
it('supports new Set methods', async () => {
Expand Down Expand Up @@ -146,15 +165,26 @@ describe('supports es2025', () => {
});

// https://github.com/tc39/proposal-float16array
it('supports Float16Array', async () => {
// neither Node 22 nor 23 currently support Float16Array
it('does not support Float16Array', async () => {
// neither Node 22 nor 23 currently support Float16Array or Math.f16round()
assert.throws(() => new Float16Array(8), {
name: 'ReferenceError',
message: 'Float16Array is not defined',
});
assert.equal(Math.f16round, undefined);
// const array = new Float16Array(8);
// assert.equal(array.length, 8);
// assert.equal(Math.f16round(1.2), 1.2001953125);
});

// https://github.com/tc39/proposal-regex-escaping
it('supports RegExp escaping', async () => {
it('does not support RegExp escaping', async () => {
// neither Node 22 nor 23 currently support RegExp.escape
// eslint-disable-next-line no-eval
assert.throws(() => eval('RegExp.escape("")'), {
name: 'TypeError',
message: 'RegExp.escape is not a function',
});
// assert.equal(RegExp.escape('The Quick Brown Fox'), '\\x54he\\x20Quick\\x20Brown\\x20Fox');
});
});
3 changes: 3 additions & 0 deletions src/test/node/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// test/node/index.ts

import './node-22.spec.ts';
34 changes: 34 additions & 0 deletions src/test/node/node-22.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// test/typescript/typescript-5.0.spec.ts

import { strict as assert } from 'node:assert';
import module from 'node:module';
import { describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';

describe('node-22', () => {
// 22.13+
it('has assert.partialDeepStrictEqual()', () => {
assert.partialDeepStrictEqual({ a: 1, b: 1 }, { a: 1 });
});

// 22.14+
it('has module.findPackageJSON()', async () => {
const packageJSONFileName = module.findPackageJSON('typescript', fileURLToPath(import.meta.url));
assert.ok(packageJSONFileName !== undefined);
const packageJSON = await import(packageJSONFileName, {
with: { type: 'json' },
});
assert.partialDeepStrictEqual(packageJSON.default, {
name: 'typescript',
});

const packageJSONFileNameLocal = module.findPackageJSON('.', fileURLToPath(import.meta.url));
assert.ok(packageJSONFileNameLocal !== undefined);
const packageJSONLocal = await import(packageJSONFileNameLocal, {
with: { type: 'json' },
});
assert.partialDeepStrictEqual(packageJSONLocal.default, {
name: '@checkdigit/typescript-config',
});
});
});