From 97ae7e3a156a03293def3e254bc4d6cf6b3ddb73 Mon Sep 17 00:00:00 2001 From: Bart van Andel Date: Thu, 5 Feb 2026 13:19:14 +0100 Subject: [PATCH] chore: require Node >=v18.20, and default to v22 Anything older than Node v22 is end-of-life, and doesn't get any more support outside of commercial support. See https://endoflife.date/nodejs The current code is still compatible with Node v18.20 and up though, which switched from import assertions (`assert` keyword) to import attributes (`with` keyword). See https://nodejs.org/en/blog/release/v18.20.0 We can't go higher than v22 yet due to certain dependencies depending on obsolete behavior and `node` command line flags. For instance, the current version of `argon2-browser` (which is 4 years old) breaks on Node's native `fetch` behavior, which used to be experimental, but is now mainstream, and can no longer be disabled in Node v23 and up. --- .devcontainer/devcontainer.json | 2 +- .github/workflows/master.yml | 2 +- .github/workflows/pull_requests.yml | 2 +- .github/workflows/releases.yml | 2 +- .npmrc | 5 +++++ .nvmrc | 10 +++++++++- Dockerfile | 2 +- mise.toml | 2 ++ package-lock.json | 6 +++--- package.json | 5 ++++- src/core/ChefWorker.js | 2 +- src/core/Recipe.mjs | 2 +- src/core/lib/Magic.mjs | 2 +- src/node/api.mjs | 2 +- src/web/index.js | 4 ++-- src/web/static/sitemap.mjs | 2 +- tests/node/tests/Categories.mjs | 4 ++-- 17 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 .npmrc create mode 100644 mise.toml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 92ebd43c..bbf41561 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "CyberChef", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bookworm", + "image": "mcr.microsoft.com/devcontainers/javascript-node:1-22", // Features to add to the dev container. More info: https://containers.dev/features. "features": { diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 74710dff..bf255ca7 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -20,7 +20,7 @@ jobs: - name: Set node version uses: actions/setup-node@v6 with: - node-version: 18 + node-version: 22 registry-url: "https://registry.npmjs.org" - name: Install diff --git a/.github/workflows/pull_requests.yml b/.github/workflows/pull_requests.yml index 8f04df72..88e3b474 100644 --- a/.github/workflows/pull_requests.yml +++ b/.github/workflows/pull_requests.yml @@ -17,7 +17,7 @@ jobs: - name: Set node version uses: actions/setup-node@v6 with: - node-version: 18 + node-version: 22 registry-url: "https://registry.npmjs.org" - name: Install diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index b40af876..dbf3827b 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -25,7 +25,7 @@ jobs: - name: Set node version uses: actions/setup-node@v6 with: - node-version: 18 + node-version: 22 registry-url: "https://registry.npmjs.org" - name: Install diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..c86b66ea --- /dev/null +++ b/.npmrc @@ -0,0 +1,5 @@ +# We can't currently enable strict engine enforcement, because +# `@astronautlabs/amf@0.0.6` enforces an old Node version. +# They've already fixed this, but the fix hasn't been released yet. +# See: https://github.com/astronautlabs/amf/issues/1 +# engine-strict=true diff --git a/.nvmrc b/.nvmrc index 3c032078..dc0f16e2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1,9 @@ -18 +# Currently, we're requiring at least Node v18.20, which introduced import +# attributes (`with` keyword) and removed import asserts (`assert` keyword). +# +# We can't support Node v23+, until `argon2-browser` receives an update that +# supports Node's native `fetch`, i.e., which doesn't require the now obsolete +# `--no-experimental-fetch` flag. +# +# So, let's default to v22. +22 diff --git a/Dockerfile b/Dockerfile index 2184a294..7ed0f1c1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # Modifier --platform=$BUILDPLATFORM limits the platform to "BUILDPLATFORM" during buildx multi-platform builds # This is because npm "chromedriver" package is not compatiable with all platforms # For more info see: https://docs.docker.com/build/building/multi-platform/#cross-compilation -FROM --platform=$BUILDPLATFORM node:18-alpine AS builder +FROM --platform=$BUILDPLATFORM node:22-alpine AS builder WORKDIR /app diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..6a0493c6 --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[tools] +node = "22" diff --git a/package-lock.json b/package-lock.json index 0b7bce14..3d3fee7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -159,6 +159,9 @@ "webpack-dev-server": "5.0.4", "webpack-node-externals": "^3.0.0", "worker-loader": "^3.0.8" + }, + "engines": { + "node": ">=18.20 <23" } }, "node_modules/@ampproject/remapping": { @@ -170,9 +173,6 @@ "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@asamuzakjp/css-color": { diff --git a/package.json b/package.json index fe50083c..54ce65b8 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "browserslist": [ "Chrome >= 50", "Firefox >= 38", - "node >= 16" + "node >= 18.20" ], "devDependencies": { "@babel/core": "^7.24.7", @@ -205,5 +205,8 @@ "minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs", "getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'", "setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048" + }, + "engines": { + "node": ">=18.20 <23" } } diff --git a/src/core/ChefWorker.js b/src/core/ChefWorker.js index a43993f9..3f56d855 100644 --- a/src/core/ChefWorker.js +++ b/src/core/ChefWorker.js @@ -7,7 +7,7 @@ */ import Chef from "./Chef.mjs"; -import OperationConfig from "./config/OperationConfig.json" assert {type: "json"}; +import OperationConfig from "./config/OperationConfig.json" with {type: "json"}; import OpModules from "./config/modules/OpModules.mjs"; import loglevelMessagePrefix from "loglevel-message-prefix"; diff --git a/src/core/Recipe.mjs b/src/core/Recipe.mjs index 3ce40aa4..31c02ee2 100755 --- a/src/core/Recipe.mjs +++ b/src/core/Recipe.mjs @@ -4,7 +4,7 @@ * @license Apache-2.0 */ -import OperationConfig from "./config/OperationConfig.json" assert {type: "json"}; +import OperationConfig from "./config/OperationConfig.json" with {type: "json"}; import OperationError from "./errors/OperationError.mjs"; import Operation from "./Operation.mjs"; import DishError from "./errors/DishError.mjs"; diff --git a/src/core/lib/Magic.mjs b/src/core/lib/Magic.mjs index 14111ec7..d1a0f2d0 100644 --- a/src/core/lib/Magic.mjs +++ b/src/core/lib/Magic.mjs @@ -1,4 +1,4 @@ -import OperationConfig from "../config/OperationConfig.json" assert {type: "json"}; +import OperationConfig from "../config/OperationConfig.json" with {type: "json"}; import Utils, { isWorkerEnvironment } from "../Utils.mjs"; import Recipe from "../Recipe.mjs"; import Dish from "../Dish.mjs"; diff --git a/src/node/api.mjs b/src/node/api.mjs index 88b3f834..b704a2bb 100644 --- a/src/node/api.mjs +++ b/src/node/api.mjs @@ -10,7 +10,7 @@ import NodeDish from "./NodeDish.mjs"; import NodeRecipe from "./NodeRecipe.mjs"; -import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"}; +import OperationConfig from "../core/config/OperationConfig.json" with {type: "json"}; import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs"; import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs"; diff --git a/src/web/index.js b/src/web/index.js index 90142b34..6e712d06 100755 --- a/src/web/index.js +++ b/src/web/index.js @@ -17,8 +17,8 @@ import * as CanvasComponents from "../core/lib/CanvasComponents.mjs"; // CyberChef import App from "./App.mjs"; -import Categories from "../core/config/Categories.json" assert {type: "json"}; -import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"}; +import Categories from "../core/config/Categories.json" with {type: "json"}; +import OperationConfig from "../core/config/OperationConfig.json" with {type: "json"}; /** diff --git a/src/web/static/sitemap.mjs b/src/web/static/sitemap.mjs index 4f8101d4..f373a277 100644 --- a/src/web/static/sitemap.mjs +++ b/src/web/static/sitemap.mjs @@ -1,5 +1,5 @@ import sm from "sitemap"; -import OperationConfig from "../../core/config/OperationConfig.json" assert { type: "json" }; +import OperationConfig from "../../core/config/OperationConfig.json" with { type: "json" }; /** * Generates an XML sitemap for all CyberChef operations and a number of recipes. diff --git a/tests/node/tests/Categories.mjs b/tests/node/tests/Categories.mjs index e6f8bd72..f37b43ec 100644 --- a/tests/node/tests/Categories.mjs +++ b/tests/node/tests/Categories.mjs @@ -1,6 +1,6 @@ import TestRegister from "../../lib/TestRegister.mjs"; -import Categories from "../../../src/core/config/Categories.json" assert {type: "json"}; -import OperationConfig from "../../../src/core/config/OperationConfig.json" assert {type: "json"}; +import Categories from "../../../src/core/config/Categories.json" with {type: "json"}; +import OperationConfig from "../../../src/core/config/OperationConfig.json" with {type: "json"}; import it from "../assertionHandler.mjs"; import assert from "assert";