Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 24
node-version-file: .nvmrc
cache: npm

- run: npm install
Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
14 changes: 12 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,17 @@ in-range updates, evaluates each major separately, sweeps OSV.dev for advisories
its "Held back" section records what is already known to be blocked and the exact
condition that clears it. Do not re-derive that analysis.

- **Node**: `engines.node` is `^22.22.2 || ^24.15.0 || >=26.0.0`, mirroring the
strictest dev dependency (jsdom 30). Node 20 is EOL and unsupported.
- **Node**: pinned to the **Node 24 LTS line** — `engines.node` is `^24.15.0`
(the `24.15` floor is jsdom 30's, the strictest dev dependency). `@types/node`
is pinned to the matching major (`^24.13.4`); do not let it drift ahead of the
runtime. `.nvmrc` holds `24` and CI reads it via `node-version-file`.
**Vercel** deploys the latest `24.x` for this range (it only offers majors:
24.x/22.x/20.x), so `engines.node` overrides whatever the project's
Build & Deployment setting says. Node 20 and 22 are no longer supported here.
**Hold this pin until Vercel's default Node version moves forward** — re-check
with <https://vercel.com/docs/functions/runtimes/node-js/node-js-versions>,
then bump `engines.node`, `.nvmrc`, `@types/node`, and `REQUIRED_NODE_MAJOR`
in `scripts/setup.ts` together.
- **CI gates tests only** — `.github/workflows/test.yml` runs `npm run test:coverage`
and never `npm run build`, so type errors do not fail CI. Type-check locally.
- **Coverage path is load-bearing**: CI uploads `coverage/coverage-final.json` to
Expand All @@ -269,6 +278,7 @@ condition that clears it. Do not re-derive that analysis.
| `typescript` 7 | No stable Compiler API until 7.1; `typescript-eslint` peers `typescript: >=4.8.4 <6.1.0` | `npm view typescript-eslint peerDependencies` |
| `eslint` 10 | `eslint-plugin-react@7.37.5` (latest) peers `eslint ^9.7` and calls a removed context method | `npm view eslint-plugin-react peerDependencies` |
| `grapesjs` 0.23 | `@grapesjs/react@2.0.0` (latest) peers `grapesjs ^0.22.5` | `npm view @grapesjs/react peerDependencies` |
| `@types/node` 25+ | Runtime is pinned to Node 24 (`engines.node: ^24.15.0`) because 24.x is Vercel's current default/newest offering; types must not lead the runtime | Vercel's [supported Node versions](https://vercel.com/docs/functions/runtimes/node-js/node-js-versions) |

## Reference Documents

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Component -> Server Action -> Service (singleton) -> MPHelper -> Ministry Platfo

## Prerequisites

- **Node.js**: v20 or higher (enforced via `engines` in `package.json` and the setup script). Required by Next.js 16, React 19, and TypeScript 6.0.
- **Node.js**: **v24.15.0 or later on the 24.x line** (pinned via `engines.node` in `package.json`, `.nvmrc`, and the setup script). Node 24 is the current LTS and the version Vercel deploys; 20.x and 22.x are not supported. Use `nvm use` (or `fnm use`) to pick it up from `.nvmrc`.
- **Package Manager**: npm
- **Ministry Platform**: Active instance with API credentials and OAuth client configured
- **Ministry Platform Database**: SQL install script applied (see [Database Setup](#database-setup) below)
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"engines": {
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
"node": "^24.15.0"
},
"scripts": {
"dev": "next dev",
Expand Down Expand Up @@ -69,7 +69,7 @@
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.3.3",
"@types/mjml": "^5.0.0",
"@types/node": "^26.5.1",
"@types/node": "^24.13.4",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@vitejs/plugin-react": "^6.1.1",
Expand Down
32 changes: 24 additions & 8 deletions scripts/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ const MODELS_PATH = path.join(
);
const NEXT_BUILD_PATH = path.join(PROJECT_ROOT, '.next');

const REQUIRED_NODE_VERSION = 20;
// Pinned to the Node 24 LTS line: `engines.node` is `^24.15.0` and Vercel only
// offers major versions (24.x is its current default). Bump both together when
// Vercel moves its default forward.
const REQUIRED_NODE_MAJOR = 24;
const REQUIRED_NODE_MINOR = 15;

const SQL_INSTALL_PATH = path.join(PROJECT_ROOT, '_INSTALL', 'ministryplatform-install.sql');

Expand Down Expand Up @@ -341,9 +345,11 @@ async function execCommandStreaming(
});
}

function getNodeVersion(): number | null {
const match = process.version.match(/^v(\d+)/);
return match ? parseInt(match[1], 10) : null;
function getNodeVersion(): { major: number; minor: number } | null {
const match = process.version.match(/^v(\d+)\.(\d+)/);
return match
? { major: parseInt(match[1], 10), minor: parseInt(match[2], 10) }
: null;
}

function countFilesInDir(dir: string): number {
Expand Down Expand Up @@ -555,17 +561,27 @@ function checkNodeVersion(): StepResult {
};
}

if (version < REQUIRED_NODE_VERSION) {
const required = `v${REQUIRED_NODE_MAJOR}.${REQUIRED_NODE_MINOR}.0`;

if (version.major !== REQUIRED_NODE_MAJOR) {
return {
success: false,
message: `Node.js ${process.version} is not on the pinned v${REQUIRED_NODE_MAJOR} line`,
details: `This project pins Node.js to ${REQUIRED_NODE_MAJOR}.x (see \`engines.node\` and \`.nvmrc\`). Install ${required} or later within v${REQUIRED_NODE_MAJOR}.`,
};
}

if (version.minor < REQUIRED_NODE_MINOR) {
return {
success: false,
message: `Node.js v${version} is below minimum required v${REQUIRED_NODE_VERSION}`,
details: 'Please upgrade Node.js to v18 or later',
message: `Node.js ${process.version} is below minimum required ${required}`,
details: `Please upgrade to ${required} or later within v${REQUIRED_NODE_MAJOR}.`,
};
}

return {
success: true,
message: `Node.js ${process.version} (meets v${REQUIRED_NODE_VERSION}+ requirement)`,
message: `Node.js ${process.version} (meets the pinned ${required}+ requirement)`,
};
}

Expand Down
Loading