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 .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22.22.0"
node-version: "22.18.0"

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
Expand Down Expand Up @@ -82,7 +82,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.22.0"
node-version: "22.18.0"
registry-url: "https://registry.npmjs.org"

- name: Compute preview metadata
Expand Down Expand Up @@ -251,7 +251,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.22.0"
node-version: "22.18.0"
registry-url: "https://registry.npmjs.org"

- name: Extract version from commit message
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Create a Prisma 8 app with Prisma Composer built in.

Requires Node.js 22.22 or newer.
Requires Node.js 22.18 or newer, matching the Prisma CLI.
Generated apps must also meet their selected framework's Node.js requirements.

## Quick start

Expand Down
7 changes: 0 additions & 7 deletions bun.lock

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

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-prisma",
"version": "0.14.0",
"version": "0.14.1",
"private": false,
"description": "Create Prisma 8 projects with first-party templates and great DX.",
"homepage": "https://github.com/prisma/create-prisma",
Expand Down Expand Up @@ -55,8 +55,7 @@
"@effect/platform-node-shared": "4.0.1",
"effect": "4.0.1",
"execa": "^10.0.1",
"handlebars": "^4.7.10",
"posthog-node": "^5.55.0"
"handlebars": "^4.7.10"
},
"devDependencies": {
"@prisma/dev": "0.25.2",
Expand All @@ -71,7 +70,7 @@
},
"engines": {
"bun": ">=1.3.0",
"node": ">=22.22.0"
"node": ">=22.18.0"
},
"packageManager": "bun@1.4.1"
}
10 changes: 7 additions & 3 deletions scripts/smoke-node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const env = {
CREATE_PRISMA_DISABLE_TELEMETRY: "1",
PRISMA_NEXT_DISABLE_TELEMETRY: "1",
NO_UPDATE_NOTIFIER: "1",
npm_config_engine_strict: "true",
npm_config_engine_strict: "false",
};

try {
Expand All @@ -32,7 +32,11 @@ try {
"--no-audit",
"--no-fund",
],
{ env, stdout: "inherit", stderr: "inherit" },
{
env: { ...env, npm_config_engine_strict: "true" },
stdout: "inherit",
stderr: "inherit",
},
);
const created = await execa(
process.execPath,
Expand All @@ -59,7 +63,7 @@ try {
await execa("npm", ["run", "build"], options);
await execa("npm", ["exec", "--", "tsc", "--noEmit"], options);
console.log(
`Packed CLI, dependency engines, scaffold, build and typecheck passed on Node ${process.versions.node}.`,
`Packed CLI engine check, scaffold, build and typecheck passed on Node ${process.versions.node}.`,
);
} finally {
await rm(directory, { recursive: true, force: true });
Expand Down
56 changes: 19 additions & 37 deletions src/telemetry/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Effect, FileSystem, Schema } from "effect";
import { randomUUID } from "node:crypto";
import os from "node:os";
import path from "node:path";
import { PostHog } from "posthog-node";

import { applicationRuntime } from "../runtime";

Expand Down Expand Up @@ -85,55 +84,38 @@ const sanitizeProperties = (properties: TelemetryProperties) =>
Object.entries(properties).filter(([, value]) => value !== undefined),
) as Record<string, Exclude<TelemetryValue, undefined>>;

export const shutdownTelemetryClientEffect = (
client: Pick<PostHog, "shutdown">,
timeoutMs = TELEMETRY_TIMEOUT_MS,
) =>
Effect.tryPromise({
try: () => Promise.resolve(client.shutdown(timeoutMs)),
catch: () => undefined,
}).pipe(
Effect.timeout(timeoutMs),
Effect.interruptible,
Effect.catch(() => Effect.void),
);

export const trackCliTelemetryEffect = Effect.fn("Telemetry.track")(function* (
event: string,
properties: TelemetryProperties,
) {
if (shouldDisableTelemetry()) return;
const distinctId = yield* getAnonymousIdEffect();
const client = yield* Effect.acquireRelease(
Effect.sync(
() =>
new PostHog(TELEMETRY_API_KEY, {
host: TELEMETRY_HOST,
disableGeoip: true,
flushAt: 1,
flushInterval: 0,
yield* Effect.tryPromise(async (signal) => {
const response = await fetch(new URL("/i/v0/e/", TELEMETRY_HOST), {
method: "POST",
headers: { "content-type": "application/json" },
redirect: "error",
body: JSON.stringify({
api_key: TELEMETRY_API_KEY,
distinct_id: distinctId,
event,
properties: sanitizeProperties({
...getCommonProperties(),
...properties,
$process_person_profile: false,
$geoip_disable: true,
}),
),
(posthog) => shutdownTelemetryClientEffect(posthog),
);
yield* Effect.tryPromise(() =>
client.captureImmediate({
distinctId,
event,
properties: sanitizeProperties({
...getCommonProperties(),
...properties,
$process_person_profile: false,
timestamp: new Date().toISOString(),
}),
disableGeoip: true,
}),
);
signal,
});
await response.body?.cancel();
});
});

export function trackCliTelemetry(event: string, properties: TelemetryProperties): Promise<void> {
return applicationRuntime.runPromise(
trackCliTelemetryEffect(event, properties).pipe(
Effect.scoped,
Effect.timeout(TELEMETRY_TIMEOUT_MS),
Effect.catch(() => Effect.void),
),
Expand Down
3 changes: 0 additions & 3 deletions src/telemetry/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ export const trackCreateCompletedEffect = Effect.fn("Telemetry.createCompleted")
"duration-ms": params.durationMs,
},
).pipe(
Effect.scoped,
Effect.timeout(TELEMETRY_TIMEOUT_MS),
Effect.catch(() => Effect.void),
);
Expand Down Expand Up @@ -184,7 +183,6 @@ export const trackCreateFailedEffect = Effect.fn("Telemetry.createFailed")(funct
: null,
},
).pipe(
Effect.scoped,
Effect.timeout(TELEMETRY_TIMEOUT_MS),
Effect.catch(() => Effect.void),
);
Expand All @@ -207,7 +205,6 @@ export const trackCreateCancelledEffect = Effect.fn("Telemetry.createCancelled")
"cancellation-stage": params.stage,
},
).pipe(
Effect.scoped,
Effect.timeout(TELEMETRY_TIMEOUT_MS),
Effect.catch(() => Effect.void),
);
Expand Down
4 changes: 2 additions & 2 deletions src/utils/node-version.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const MINIMUM_NODE_VERSION = [22, 22, 0] as const;
const MINIMUM_NODE_VERSION = [22, 18, 0] as const;

function parseVersion(version: string): [number, number, number] {
const [major = "0", minor = "0", patch = "0"] = version.replace(/^v/, "").split(".");
Expand All @@ -17,7 +17,7 @@ export function supportsPrisma(nodeVersion = process.versions.node): boolean {
export function getUnsupportedNodeMessage(nodeVersion = process.versions.node): string {
return [
`Node.js ${nodeVersion} is unsupported by create-prisma@latest.`,
"Required: Node.js 22.22 or newer.",
"Required: Node.js 22.18 or newer.",
"Update Node.js and run the command again.",
].join("\n");
}
2 changes: 1 addition & 1 deletion tests/install.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,5 +631,5 @@ describe("generated templates", () => {
}
}
}
});
}, 30_000);
});
9 changes: 5 additions & 4 deletions tests/node-version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { describe, expect, test } from "bun:test";
import { getUnsupportedNodeMessage, supportsPrisma } from "../src/utils/node-version";

describe("Prisma 8 Node compatibility", () => {
test("requires Node 22.22 or newer", () => {
expect(supportsPrisma("22.21.9")).toBe(false);
expect(supportsPrisma("22.22.0")).toBe(true);
test("requires Node 22.18 or newer", () => {
expect(supportsPrisma("22.17.9")).toBe(false);
expect(supportsPrisma("22.18.0")).toBe(true);
expect(supportsPrisma("22.20.0")).toBe(true);
expect(supportsPrisma("24.0.0")).toBe(true);
});

test("returns an actionable message", () => {
expect(getUnsupportedNodeMessage("20.19.0")).toContain("Required: Node.js 22.22 or newer.");
expect(getUnsupportedNodeMessage("20.19.0")).toContain("Required: Node.js 22.18 or newer.");
});
});
Loading
Loading