# Node.js 22 upgrade status Target: Node.js 22.x ## Progress - [x] Replace the NAN/OpenSSL addon with `node:crypto`. - [x] Replace native `diskusage` with `fs.statfsSync`. - [x] Replace `node-sass` with Dart Sass. - [x] Convert Gulp 3 task composition to Gulp 4. - [x] Make documentation generation wait for all output writes. - [x] Generate and track `package-lock.json`. - [x] Pass `npm ci` from a clean dependency tree. - [x] Pass lint and build on Node.js 22. - [x] Add the Docker Compose environment and validate its configuration. - [x] Pass the database-backed automated tests on Node.js 22. - [x] Verify application startup and HTTP/API/image smoke tests. ## Selected compatibility versions - Node.js: 22.x - Gulp: 4.0.2 - Webpack: 4.47.0 - webpack-cli: 3.3.12 - TypeScript: 3.9.10 - Sass: 1.77.8 - sass-loader: 10.5.2 - gulp-imagemin: 7.1.0 - chai-http: 4.4.0 ## Findings - The original project had no lockfile and targeted Node.js 9.8.0. - `node-sass@4`, `diskusage@0.2`, and the NAN-based `crypto_key` addon cannot be retained as a reproducible Node.js 22 toolchain. - The existing test task had an empty source glob; it has been reconnected to `test/**/*.ts`. - Wildcard transitive `@types` dependencies now resolve to declarations too new for the legacy compiler. TypeScript was minimally raised to 3.9 and the Koa/Webpack-era transitive declarations were pinned with npm overrides. - Webpack 4 finishes compilation but its CLI retains handles on Node.js 22. `webpack/build.js` uses the Webpack API and returns an explicit exit status after all assets are written. - The dependency tree intentionally retains deprecated application libraries to avoid an unrelated application/framework migration. - The API suite did not initialize Chai's `should` interface and still targeted the removed `posts` API and old nested `account` fixture schema. It now initializes `should`, targets `notes`, and uses the current user/note field names. - `object-assign-deep` cloned BSON ObjectID buffers into plain objects on modern Node.js. Flat drive-folder fixtures now use a shallow merge so ObjectIDs remain valid. - Dropping `noteReactions` between tests also removed its unique index. Test cleanup now removes documents while preserving the `(userId, noteId)` index. - Docker configuration now explicitly disables Elasticsearch; omitting the section caused an asynchronous messaging error after successful responses. - The client boot loader previously trusted a persisted regional language tag such as `ja-JP`, while Webpack emits base-tag bundles such as `ja`. Stored/browser language tags are now normalized, and the asset route provides a compatibility fallback for already-cached boot loaders. ## Verification log - `npm install --no-audit --no-fund` — passed on Node.js 22.23.2 / npm 12.0.1; package-lock generated. Deprecation warnings remain for preserved legacy dependencies. - `npm ci --no-audit --no-fund` — passed from a clean `node_modules` tree in 48 seconds. - `npm run lint` — passed. - `npm run build` — passed in 93 seconds. Webpack 4 and preserved plugins emit deprecation/localization warnings. - `npx mocha --require ts-node/register test/modern-node.ts test/text.ts` — 16 passing, including RSA and disk-usage regressions. - `docker compose config --quiet` — passed. - `npm start -- --only-server` — initialization and HTTP server creation succeeded; workers then exited because Redis is not installed locally. - `docker compose run --rm app npm test` — passed on Node.js 22.23.2: 107 passing, including 91 MongoDB-backed API tests, RSA/disk regressions, text parsing, signup, and image upload. - `docker compose up -d --build app` — passed; the image repeated `npm ci` from the lockfile and completed the production build. - `docker compose ps` — app, MongoDB, and Redis all healthy. - `Invoke-WebRequest http://localhost:3000/` — HTTP 200 with a 10,443-byte response. - `Invoke-WebRequest http://localhost:3000/assets/desktop.1.0.0.ja-JP.min.js` — HTTP 200 via the regional-tag compatibility fallback; content length matches the generated `ja` bundle. - Browser startup smoke test — document reached `complete`, the normalized `desktop.1.0.0.ja.min.js` loaded, the Misskey welcome UI rendered, and no console errors were reported.