chore: align Node 26.7.0 toolchain
CI / check (push) Successful in 35s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s

This commit is contained in:
Simo committed 2026-08-24 19:12:11 +02:00
1 parent f94246e067
commit 6ed1b03e24
7 files changed
+57 -7

No files matched your search

+5 -1
View File
@@ -36,6 +36,8 @@ jobs:
git fetch --depth 50 origin "${REF}"
git checkout -f "${REF}"
node scripts/check-node-toolchain.mjs
export SKIP_ENV_VALIDATION=1
export NODE_ENV=test
export DATABASE_URL="mysql://test:test@localhost:3306/test?charset=utf8mb4"
@@ -130,6 +132,7 @@ jobs:
fi
cd "${STAGE}"
node scripts/check-node-toolchain.mjs
rm -f tsconfig.tsbuildinfo .tsbuildinfo
find . -maxdepth 3 -name '*.tsbuildinfo' -delete 2>/dev/null || true
rm -rf .output dist .next .next/types .next/dev .next/cache
@@ -291,6 +294,7 @@ jobs:
"${WORK}"
cd "${WORK}"
git checkout "${VERSION}"
node scripts/check-node-toolchain.mjs
export NODE_ENV=production
export SKIP_ENV_VALIDATION=1
pnpm install --frozen-lockfile
@@ -369,7 +373,7 @@ jobs:
echo ""
echo "| Component | Version | Notes |"
echo "| --------- | ------- | ----- |"
echo "| Node.js | >= 22 | Required by Next.js 16 |"
echo "| Node.js | 26.7.0 | Current release pinned in .nvmrc |"
echo "| pnpm | >= 10.33.4 | Package manager (npm/yarn not supported) |"
echo "| MySQL / MariaDB | 8.0+ / 10.6+ | Shared with the emulator |"
echo "| Redis | 7.x+ | Optional — caching, rate limiting, SSE |"
+1 -1
View File
@@ -1 +1 @@
22
26.7.0
+1 -1
View File
@@ -10,7 +10,7 @@ Features a premium animated homepage (typewriter hero, floating orbs, scroll cou
| Component | Version | Notes |
| --------------- | -------------- | ---------------------------------------- |
| Node.js | >= 22 | Required by Next.js 16 |
| Node.js | 26.7.0 | Current release pinned in `.nvmrc` |
| pnpm | >= 10.33.4 | Package manager (npm/yarn not supported) |
| MySQL / MariaDB | 8.0+ / 10.6+ | Shared with the emulator |
| DragonflyDB | 1.x+ | Optional — caching, rate limiting, SSE (Redis-protocol compatible) |
+3 -2
View File
@@ -3,19 +3,20 @@
"private": true,
"type": "module",
"engines": {
"node": ">=26"
"node": ">=26.7.0 <27"
},
"packageManager": "[email protected]",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"toolchain:check": "node scripts/check-node-toolchain.mjs",
"lint": "biome check .",
"biome:lint": "biome check .",
"format": "biome format --write .",
"knip": "knip --include files,dependencies,devDependencies,unlisted,binaries",
"jobs:worker": "tsx scripts/jobs-worker.ts",
"test": "DATABASE_URL=mysql://root:root@localhost:3306/test vitest run",
"test": "vitest run",
"typecheck": "tsc --noEmit",
"db:generate": "drizzle-kit generate",
"db:migrate": "tsx scripts/apply-migrations.ts",
+39
View File
@@ -0,0 +1,39 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const readProjectFile = (path) =>
readFileSync(resolve(projectRoot, path), "utf8");
const pinnedVersion = readProjectFile(".nvmrc").trim();
assert.match(
pinnedVersion,
/^\d+\.\d+\.\d+$/,
".nvmrc must pin an exact Node.js version",
);
const major = Number.parseInt(pinnedVersion.split(".")[0], 10);
const packageJson = JSON.parse(readProjectFile("package.json"));
assert.equal(
packageJson.engines?.node,
`>=${pinnedVersion} <${major + 1}`,
"package.json engines.node must match the .nvmrc release line",
);
assert.equal(
Number.parseInt(packageJson.devDependencies?.["@types/node"], 10),
major,
"@types/node must match the pinned Node.js major",
);
if (!process.argv.includes("--static")) {
assert.equal(
process.versions.node,
pinnedVersion,
"the active Node.js runtime must match .nvmrc",
);
}
console.log(`Node.js toolchain is aligned on ${pinnedVersion}`);
+4 -1
View File
@@ -1,3 +1,4 @@
import { join } from "node:path";
import { beforeEach, describe, expect, it, vi } from "vitest";
const fsMock = vi.hoisted(() => ({
@@ -29,7 +30,9 @@ describe("getSoundtrackPath", () => {
);
});
it("joins the safe code into the soundtrack dir", () => {
expect(getSoundtrackPath("song").endsWith("mp3/song.mp3")).toBe(true);
expect(getSoundtrackPath("song").endsWith(join("mp3", "song.mp3"))).toBe(
true,
);
});
});
+4 -1
View File
@@ -17,7 +17,10 @@ export default defineConfig({
environment: "node",
// Modules under test transitively import @/env; skip its strict parse so
// unit tests run without a populated .env.
env: { SKIP_ENV_VALIDATION: "1" },
env: {
SKIP_ENV_VALIDATION: "1",
DATABASE_URL: "mysql://root:root@localhost:3306/test",
},
testTimeout: 10000,
exclude: ["e2e/**", "node_modules/**", ".next/**", ".next.prev/**"],
coverage: {