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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Create a Prisma 8 app with Prisma Composer built in.

## Supported versions

create-prisma supports exactly what Prisma ORM supports: Node.js 22.18 or newer on the 22 line, 24.11 or newer on the 24 line, or 26 and newer (`^22.18.0 || ^24.11.0 || >=26.0.0`). Node.js 23 and 24.0 to 24.10 are not supported. create-prisma refuses unsupported Node.js versions before it writes any files, and the generated minimal, hono, elysia, nest and turborepo projects declare the same range in `engines.node`.
create-prisma supports exactly what Prisma ORM supports: Node.js 22.18 or newer on the 22 line, 24.11 or newer on the 24 line, or 26 and newer (`^22.18.0 || ^24.11.0 || >=26.0.0`). create-prisma refuses unsupported Node.js versions before it writes any files, and the generated minimal, hono, elysia, nest and turborepo projects declare the same range in `engines.node`. The next, svelte, astro and tanstack-start templates declare no `engines` field.

Each supported Node.js release works with the npm it ships, including npm 10 on Node.js 22. pnpm, Yarn 4.10 or newer, Bun and Deno are also supported. Yarn 1 is not supported. When create-prisma runs on Bun or Deno instead of Node.js, it skips the Node.js check.
Each supported Node.js release works with the npm it ships, including npm 10 on Node.js 22. pnpm, Yarn 4.10 or newer, Bun and Deno (local minimal PostgreSQL apps only, see below) are also supported. Yarn 1 is not supported. When create-prisma runs on Bun or Deno instead of Node.js, it skips the Node.js check.

The one exception is the `nuxt` template. Nuxt itself requires Node.js `^22.22.3 || ^24.15.0 || >=26.0.0`, so Nuxt projects declare that narrower range.

Expand Down Expand Up @@ -59,7 +59,7 @@ workspace. Choosing another workspace also updates the Prisma CLI's active works
- `nuxt`
- `tanstack-start`

PostgreSQL and MongoDB are supported with PSL or TypeScript contract authoring. npm, pnpm, Yarn, and Bun are supported.
PostgreSQL and MongoDB are supported with PSL or TypeScript contract authoring. For supported package managers, see [Supported versions](#supported-versions).

Deno is supported for local minimal PostgreSQL apps:

Expand Down
38 changes: 24 additions & 14 deletions src/utils/node-version.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
type Version = readonly [major: number, minor: number, patch: number];

export const SUPPORTED_NODE_RANGE = "^22.18.0 || ^24.11.0 || >=26.0.0";

const minimumByMajor: ReadonlyMap<number, Version> = new Map([
[22, [22, 18, 0]],
[24, [24, 11, 0]],
]);
const supportedNodeLines = [
{ major: 22, minimum: [22, 18, 0] },
{ major: 24, minimum: [24, 11, 0] },
] as const satisfies readonly { major: number; minimum: Version }[];
const FIRST_MAJOR_WITH_EVERY_RELEASE_SUPPORTED = 26;

export const MINIMUM_NODE_VERSION = minimumByMajor.get(22)!;
export const SUPPORTED_NODE_RANGE = [
...supportedNodeLines.map(({ minimum }) => `^${minimum.join(".")}`),
`>=${FIRST_MAJOR_WITH_EVERY_RELEASE_SUPPORTED}.0.0`,
].join(" || ");

export const MINIMUM_NODE_VERSION: Version = supportedNodeLines[0].minimum;

const SUPPORTED_NODE_DESCRIPTION = `${supportedNodeLines
.map(({ major, minimum }) => `${minimum[0]}.${minimum[1]} or newer on the ${major} line`)
.join(", ")}, or ${FIRST_MAJOR_WITH_EVERY_RELEASE_SUPPORTED} and newer`;

const RELEASE_VERSION_PATTERN = /^v?(\d+)\.(\d+)\.(\d+)(?:\+[0-9A-Za-z.-]+)?$/;

function parseVersion(version: string): Version {
const [major = "0", minor = "0", patch = "0"] = version.replace(/^v/, "").split(".");
return [Number(major), Number(minor), Number.parseInt(patch, 10)];
function parseReleaseVersion(version: string): Version | undefined {
const match = RELEASE_VERSION_PATTERN.exec(version);
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : undefined;
}

function isAtLeast(current: Version, minimum: Version): boolean {
Expand All @@ -29,16 +38,17 @@ export function runsOnNode(
}

export function supportsPrisma(nodeVersion = process.versions.node): boolean {
const current = parseVersion(nodeVersion);
const current = parseReleaseVersion(nodeVersion);
if (!current) return false;
if (current[0] >= FIRST_MAJOR_WITH_EVERY_RELEASE_SUPPORTED) return true;
const minimum = minimumByMajor.get(current[0]);
return minimum !== undefined && isAtLeast(current, minimum);
const line = supportedNodeLines.find(({ major }) => major === current[0]);
return line !== undefined && isAtLeast(current, line.minimum);
}

export function getUnsupportedNodeMessage(nodeVersion = process.versions.node): string {
return [
`Node.js ${nodeVersion} is unsupported by create-prisma@latest.`,
"Required: Node.js 22.18 or newer on the 22 line, 24.11 or newer on the 24 line, or 26 and newer.",
`Required: Node.js ${SUPPORTED_NODE_DESCRIPTION}.`,
"Update Node.js and run the command again.",
].join("\n");
}
40 changes: 30 additions & 10 deletions tests/node-version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,43 @@ import { npmForMinimumNode } from "../src/utils/package-manager";
const repositoryRoot = path.join(import.meta.dir, "..");

describe("Prisma 8 Node compatibility", () => {
test("accepts exactly the Node.js versions Prisma ORM supports", () => {
test("accepts exactly the versions in the supported range, as semver decides", () => {
for (const version of [
"20.19.0",
"22.17.9",
"22.18.0",
"22.22.3",
"23.0.0",
"23.11.0",
"24.0.0",
"24.10.9",
"24.11.0",
"24.15.0",
"25.9.0",
"26.0.0",
"27.1.0",
"22.18.0-rc.1",
"24.11.0-rc.1",
"26.0.0-nightly20261001abcdef",
"27.0.0-pre",
]) {
expect([version, supportsPrisma(version)]).toEqual([
version,
Bun.semver.satisfies(version, SUPPORTED_NODE_RANGE),
]);
}
});

test("checks the boundaries of the supported range", () => {
for (const [version, supported] of [
["20.19.0", false],
["22.17.9", false],
["v22.17.9", false],
["22.18.0", true],
["v22.18.0", true],
["22.22.3", true],
["23.0.0", false],
["23.11.0", false],
["24.0.0", false],
["24.10.9", false],
["24.11.0", true],
["24.15.0", true],
["25.9.0", false],
["24.11.0-rc.1", false],
["26.0.0", true],
["27.1.0", true],
["26.0.0-nightly20261001abcdef", false],
] as const) {
expect([version, supportsPrisma(version)]).toEqual([version, supported]);
}
Expand Down
Loading