Skip to content

Commit bc66f0c

Browse files
feat(cli): Add prisma 7 support and improve alchemy support (#692)
* fix(cli): remove wrangler support * dont paste env.d.ts in packages when self backend * change npm link strategy from hoisted to isolated * update * fix uniwind * update prisma * fix * fix * fix * update stack builder
1 parent 0561a11 commit bc66f0c

File tree

69 files changed

+441
-1290
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+441
-1290
lines changed

apps/cli/src/constants.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,25 @@ export const dependencyVersionMap = {
5353
"@planetscale/database": "^1.19.0",
5454

5555
"@libsql/client": "^0.14.0",
56+
libsql: "^0.5.22",
5657

57-
"@neondatabase/serverless": "^1.0.1",
58+
"@neondatabase/serverless": "^1.0.2",
5859
pg: "^8.14.1",
5960
"@types/pg": "^8.11.11",
6061
"@types/ws": "^8.18.1",
6162
ws: "^8.18.3",
6263

6364
mysql2: "^3.14.0",
6465

65-
"@prisma/client": "^6.15.0",
66-
prisma: "^6.15.0",
67-
"@prisma/adapter-d1": "^6.15.0",
68-
"@prisma/adapter-libsql": "^6.15.0",
69-
70-
"@prisma/adapter-planetscale": "^6.15.0",
66+
"@prisma/client": "^7.0.0",
67+
prisma: "^7.0.0",
68+
"@prisma/adapter-d1": "^7.0.0",
69+
"@prisma/adapter-neon": "^7.0.0",
70+
"@prisma/adapter-mariadb": "^7.0.0",
71+
"@prisma/adapter-libsql": "^7.0.0",
72+
"@prisma/adapter-better-sqlite3": "^7.0.0",
73+
"@prisma/adapter-pg": "^7.0.0",
74+
"@prisma/adapter-planetscale": "^7.0.0",
7175

7276
mongoose: "^8.14.0",
7377

@@ -157,7 +161,7 @@ export const dependencyVersionMap = {
157161
alchemy: "^0.77.0",
158162

159163
dotenv: "^17.2.2",
160-
tsdown: "^0.15.5",
164+
tsdown: "^0.16.5",
161165
zod: "^4.1.11",
162166
srvx: "0.8.15",
163167

apps/cli/src/helpers/core/create-readme.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ function generateDatabaseSetup(
540540
packageManagerRunCmd: string,
541541
orm: ORM,
542542
dbSetup: DatabaseSetup,
543-
serverDeploy?: string,
543+
_serverDeploy?: string,
544544
backend?: string,
545545
) {
546546
if (database === "none") {
@@ -565,9 +565,7 @@ function generateDatabaseSetup(
565565
1. Start the local SQLite database:
566566
${
567567
dbSetup === "d1"
568-
? serverDeploy === "alchemy"
569-
? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy."
570-
: "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command."
568+
? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy."
571569
: `\`\`\`bash
572570
cd ${dbLocalPath} && ${packageManagerRunCmd} db:local
573571
\`\`\`
@@ -765,18 +763,5 @@ function generateDeploymentCommands(
765763
}
766764
}
767765

768-
if (webDeploy === "wrangler" || serverDeploy === "wrangler") {
769-
lines.push("\n## Deployment (Cloudflare Wrangler)");
770-
if (webDeploy === "wrangler") {
771-
lines.push(`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`);
772-
}
773-
if (serverDeploy === "wrangler") {
774-
lines.push(
775-
`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`,
776-
`- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`,
777-
);
778-
}
779-
}
780-
781766
return lines.length ? `\n${lines.join("\n")}\n` : "";
782767
}

apps/cli/src/helpers/core/db-setup.ts

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { spinner } from "@clack/prompts";
33
import consola from "consola";
44
import fs from "fs-extra";
55
import pc from "picocolors";
6+
import type { AvailableDependencies } from "../../constants";
67
import type { ProjectConfig } from "../../types";
78
import { addPackageDependency } from "../../utils/add-package-deps";
89
import { setupCloudflareD1 } from "../database-providers/d1-setup";
@@ -33,51 +34,89 @@ export async function setupDatabase(
3334

3435
const s = spinner();
3536
const dbPackageDir = path.join(projectDir, "packages/db");
37+
const webDir = path.join(projectDir, "apps/web");
3638

3739
if (!(await fs.pathExists(dbPackageDir))) {
3840
return;
3941
}
4042

4143
try {
4244
if (orm === "prisma") {
43-
if (database === "mysql" && dbSetup === "planetscale") {
45+
if (database === "mongodb") {
4446
await addPackageDependency({
45-
dependencies: [
46-
"@prisma/client",
47-
"@prisma/adapter-planetscale",
48-
"@planetscale/database",
49-
],
50-
devDependencies: ["prisma"],
51-
projectDir: dbPackageDir,
52-
});
53-
} else if (database === "sqlite" && dbSetup === "turso") {
54-
await addPackageDependency({
55-
dependencies: ["@prisma/client", "@prisma/adapter-libsql"],
56-
devDependencies: ["prisma"],
47+
customDependencies: {
48+
"@prisma/client": "6.19.0",
49+
},
50+
customDevDependencies: {
51+
prisma: "6.19.0",
52+
},
5753
projectDir: dbPackageDir,
5854
});
5955
} else {
56+
const prismaDependencies: AvailableDependencies[] = ["@prisma/client"];
57+
const prismaDevDependencies: AvailableDependencies[] = ["prisma"];
58+
59+
if (database === "mysql" && dbSetup === "planetscale") {
60+
prismaDependencies.push(
61+
"@prisma/adapter-planetscale",
62+
"@planetscale/database",
63+
);
64+
} else if (database === "mysql") {
65+
prismaDependencies.push("@prisma/adapter-mariadb");
66+
} else if (database === "sqlite") {
67+
if (dbSetup === "d1") {
68+
prismaDependencies.push("@prisma/adapter-d1");
69+
} else {
70+
prismaDependencies.push("@prisma/adapter-libsql");
71+
}
72+
} else if (database === "postgres") {
73+
if (dbSetup === "neon") {
74+
prismaDependencies.push(
75+
"@prisma/adapter-neon",
76+
"@neondatabase/serverless",
77+
"ws",
78+
);
79+
prismaDevDependencies.push("@types/ws");
80+
} else {
81+
prismaDependencies.push("@prisma/adapter-pg");
82+
prismaDependencies.push("pg");
83+
prismaDevDependencies.push("@types/pg");
84+
}
85+
}
86+
6087
await addPackageDependency({
61-
dependencies: ["@prisma/client"],
62-
devDependencies: ["prisma"],
88+
dependencies: prismaDependencies,
89+
devDependencies: prismaDevDependencies,
6390
projectDir: dbPackageDir,
6491
});
6592
}
6693

67-
const webDir = path.join(projectDir, "apps/web");
6894
if (await fs.pathExists(webDir)) {
69-
await addPackageDependency({
70-
dependencies: ["@prisma/client"],
71-
projectDir: webDir,
72-
});
95+
if (database === "mongodb") {
96+
await addPackageDependency({
97+
customDependencies: {
98+
"@prisma/client": "6.19.0",
99+
},
100+
projectDir: webDir,
101+
});
102+
} else {
103+
await addPackageDependency({
104+
dependencies: ["@prisma/client"],
105+
projectDir: webDir,
106+
});
107+
}
73108
}
74109
} else if (orm === "drizzle") {
75110
if (database === "sqlite") {
76111
await addPackageDependency({
77-
dependencies: ["drizzle-orm", "@libsql/client"],
112+
dependencies: ["drizzle-orm", "@libsql/client", "libsql"],
78113
devDependencies: ["drizzle-kit"],
79114
projectDir: dbPackageDir,
80115
});
116+
await addPackageDependency({
117+
dependencies: ["@libsql/client", "libsql"],
118+
projectDir: webDir,
119+
});
81120
} else if (database === "postgres") {
82121
if (dbSetup === "neon") {
83122
await addPackageDependency({

apps/cli/src/helpers/core/env-setup.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,6 @@ ${hasWeb ? "# npx convex env set SITE_URL http://localhost:3001\n" : ""}
356356
case "sqlite":
357357
if (
358358
config.runtime === "workers" ||
359-
webDeploy === "wrangler" ||
360-
serverDeploy === "wrangler" ||
361359
webDeploy === "alchemy" ||
362360
serverDeploy === "alchemy"
363361
) {

apps/cli/src/helpers/core/post-installation.ts

Lines changed: 15 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,6 @@ export async function displayPostInstallInstructions(
7777
config.payments === "polar" && config.auth === "better-auth"
7878
? getPolarInstructions(backend)
7979
: "";
80-
const wranglerDeployInstructions = getWranglerDeployInstructions(
81-
runCmd,
82-
webDeploy,
83-
serverDeploy,
84-
backend,
85-
);
8680
const alchemyDeployInstructions = getAlchemyDeployInstructions(
8781
runCmd,
8882
webDeploy,
@@ -127,10 +121,7 @@ export async function displayPostInstallInstructions(
127121
if (
128122
database === "sqlite" &&
129123
dbSetup === "none" &&
130-
(serverDeploy === "wrangler" ||
131-
serverDeploy === "alchemy" ||
132-
webDeploy === "wrangler" ||
133-
webDeploy === "alchemy")
124+
(serverDeploy === "alchemy" || webDeploy === "alchemy")
134125
) {
135126
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(
136127
" (starts local SQLite server for Workers compatibility)",
@@ -162,9 +153,6 @@ export async function displayPostInstallInstructions(
162153
)} Complete D1 database setup first\n (see Database commands below)\n`;
163154
}
164155
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
165-
if (serverDeploy === "wrangler") {
166-
output += `${pc.cyan(`${stepCounter++}.`)} cd apps/server && ${runCmd} cf-typegen\n`;
167-
}
168156
}
169157
}
170158

@@ -203,8 +191,6 @@ export async function displayPostInstallInstructions(
203191
if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
204192
if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
205193
if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
206-
if (wranglerDeployInstructions)
207-
output += `\n${wranglerDeployInstructions.trim()}\n`;
208194
if (alchemyDeployInstructions)
209195
output += `\n${alchemyDeployInstructions.trim()}\n`;
210196
if (starlightInstructions) output += `\n${starlightInstructions.trim()}\n`;
@@ -261,10 +247,10 @@ async function getDatabaseInstructions(
261247
database: Database,
262248
orm?: ORM,
263249
runCmd?: string,
264-
runtime?: Runtime,
250+
_runtime?: Runtime,
265251
dbSetup?: DatabaseSetup,
266252
serverDeploy?: string,
267-
backend?: string,
253+
_backend?: string,
268254
) {
269255
const instructions: string[] = [];
270256

@@ -277,49 +263,6 @@ async function getDatabaseInstructions(
277263
}
278264
}
279265

280-
if (serverDeploy === "wrangler" && dbSetup === "d1") {
281-
if (orm === "prisma" && runtime === "workers") {
282-
instructions.push(
283-
`\n${pc.yellow(
284-
"WARNING:",
285-
)} Prisma + D1 on Workers with Wrangler has migration issues.\n Consider using Alchemy deploy instead of Wrangler for D1 projects.\n`,
286-
);
287-
}
288-
const packageManager = runCmd === "npm run" ? "npm" : runCmd || "npm";
289-
290-
instructions.push(
291-
`${pc.cyan("1.")} Login to Cloudflare: ${pc.white(
292-
`${packageManager} wrangler login`,
293-
)}`,
294-
);
295-
instructions.push(
296-
`${pc.cyan("2.")} Create D1 database: ${pc.white(
297-
`${packageManager} wrangler d1 create your-database-name`,
298-
)}`,
299-
);
300-
const wranglerPath = backend === "self" ? "apps/web" : "apps/server";
301-
instructions.push(
302-
`${pc.cyan(
303-
"3.",
304-
)} Update ${wranglerPath}/wrangler.jsonc with database_id and database_name`,
305-
);
306-
instructions.push(
307-
`${pc.cyan("4.")} Generate migrations: ${pc.white(
308-
`cd ${wranglerPath} && ${runCmd} db:generate`,
309-
)}`,
310-
);
311-
instructions.push(
312-
`${pc.cyan("5.")} Apply migrations locally: ${pc.white(
313-
`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME --local`,
314-
)}`,
315-
);
316-
instructions.push(
317-
`${pc.cyan("6.")} Apply migrations to production: ${pc.white(
318-
`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME`,
319-
)}`,
320-
);
321-
}
322-
323266
if (dbSetup === "d1" && serverDeploy === "alchemy") {
324267
if (orm === "drizzle") {
325268
instructions.push(
@@ -354,6 +297,14 @@ async function getDatabaseInstructions(
354297
}
355298
}
356299

300+
if (dbSetup === "turso" && orm === "prisma") {
301+
instructions.push(
302+
`${pc.yellow(
303+
"NOTE:",
304+
)} Follow Turso's Prisma guide for migrations via the Turso CLI:\n https://docs.turso.tech/sdk/ts/orm/prisma`,
305+
);
306+
}
307+
357308
if (orm === "prisma") {
358309
if (database === "mongodb" && dbSetup === "docker") {
359310
instructions.push(
@@ -368,6 +319,9 @@ async function getDatabaseInstructions(
368319
);
369320
}
370321
if (!(dbSetup === "d1" && serverDeploy === "alchemy")) {
322+
instructions.push(
323+
`${pc.cyan("•")} Generate Prisma Client: ${`${runCmd} db:generate`}`,
324+
);
371325
instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
372326
}
373327
if (!(dbSetup === "d1" && serverDeploy === "alchemy")) {
@@ -442,29 +396,6 @@ function getBunWebNativeWarning() {
442396
)} 'bun' might cause issues with web + native apps in a monorepo.\n Use 'pnpm' if problems arise.`;
443397
}
444398

445-
function getWranglerDeployInstructions(
446-
runCmd?: string,
447-
webDeploy?: string,
448-
serverDeploy?: string,
449-
backend?: string,
450-
) {
451-
const instructions: string[] = [];
452-
453-
if (webDeploy === "wrangler") {
454-
const deployPath = backend === "self" ? "apps/web" : "apps/web";
455-
instructions.push(
456-
`${pc.bold("Deploy web to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd ${deployPath} && ${runCmd} deploy`}`,
457-
);
458-
}
459-
if (serverDeploy === "wrangler" && backend !== "self") {
460-
instructions.push(
461-
`${pc.bold("Deploy server to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}`,
462-
);
463-
}
464-
465-
return instructions.length ? `\n${instructions.join("\n")}` : "";
466-
}
467-
468399
function getClerkInstructions() {
469400
return `${pc.bold("Clerk Authentication Setup:")}\n${pc.cyan("•")} Follow the guide: ${pc.underline("https://docs.convex.dev/auth/clerk")}\n${pc.cyan("•")} Set CLERK_JWT_ISSUER_DOMAIN in Convex Dashboard\n${pc.cyan("•")} Set CLERK_PUBLISHABLE_KEY in apps/*/.env`;
470401
}
@@ -485,7 +416,7 @@ function getAlchemyDeployInstructions(
485416

486417
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") {
487418
instructions.push(
488-
`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`,
419+
`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} alchemy dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`,
489420
);
490421
} else if (
491422
serverDeploy === "alchemy" &&

0 commit comments

Comments
 (0)