Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
18 changes: 11 additions & 7 deletions apps/cli/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const dependencyVersionMap = {
"@planetscale/database": "^1.19.0",

"@libsql/client": "^0.14.0",
libsql: "^0.5.22",

"@neondatabase/serverless": "^1.0.1",
pg: "^8.14.1",
Expand All @@ -62,12 +63,15 @@ export const dependencyVersionMap = {

mysql2: "^3.14.0",

"@prisma/client": "^6.15.0",
prisma: "^6.15.0",
"@prisma/adapter-d1": "^6.15.0",
"@prisma/adapter-libsql": "^6.15.0",

"@prisma/adapter-planetscale": "^6.15.0",
"@prisma/client": "dev",
prisma: "dev",
"@prisma/adapter-d1": "dev",
"@prisma/adapter-neon": "dev",
"@prisma/adapter-mariadb": "dev",
"@prisma/adapter-libsql": "dev",
"@prisma/adapter-better-sqlite3": "dev",
"@prisma/adapter-pg": "dev",
"@prisma/adapter-planetscale": "dev",

mongoose: "^8.14.0",

Expand Down Expand Up @@ -157,7 +161,7 @@ export const dependencyVersionMap = {
alchemy: "^0.77.0",

dotenv: "^17.2.2",
tsdown: "^0.15.5",
tsdown: "^0.16.5",
zod: "^4.1.11",
Comment on lines 161 to 165
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

tsdown bump to ^0.16.5 – ensure all configs and templates are aligned

Bumping tsdown to ^0.16.5 matches the PR summary; just double‑check that:

  • all tsdown configs in generated projects are compatible with this version, and
  • you don’t have any template/package.json still pinning an older tsdown (especially now that it’s meant to live only in the server app).

🏁 Script executed:

#!/bin/bash
# Audit tsdown usage and versions across the repo
rg -n 'tsdown' -C3 .

Length of output: 5011


Update apps/cli/package.json to match the tsdown bump

The CLI app's own package.json still pins tsdown to ^0.15.9 while src/constants.ts was updated to ^0.16.5. This creates a mismatch: generated projects will use 0.16.5, but the CLI itself remains on 0.15.9.

Update apps/cli/package.json line 91 from "tsdown": "^0.15.9" to "tsdown": "^0.16.5" and regenerate bun.lock.

🤖 Prompt for AI Agents
In apps/cli/package.json around line 91, the tsdown dependency is still pinned
to "^0.15.9" while src/constants.ts was updated to "^0.16.5"; change the tsdown
entry at line 91 to "tsdown": "^0.16.5" and then regenerate the lockfile (run
your bun install or equivalent to update bun.lock) so the CLI package and
generated projects use the same tsdown version.

srvx: "0.8.15",

Expand Down
19 changes: 2 additions & 17 deletions apps/cli/src/helpers/core/create-readme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ function generateDatabaseSetup(
packageManagerRunCmd: string,
orm: ORM,
dbSetup: DatabaseSetup,
serverDeploy?: string,
_serverDeploy?: string,
backend?: string,
) {
if (database === "none") {
Expand All @@ -565,9 +565,7 @@ function generateDatabaseSetup(
1. Start the local SQLite database:
${
dbSetup === "d1"
? serverDeploy === "alchemy"
? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy."
: "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command."
? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy."
: `\`\`\`bash
cd ${dbLocalPath} && ${packageManagerRunCmd} db:local
\`\`\`
Expand Down Expand Up @@ -765,18 +763,5 @@ function generateDeploymentCommands(
}
}

if (webDeploy === "wrangler" || serverDeploy === "wrangler") {
lines.push("\n## Deployment (Cloudflare Wrangler)");
if (webDeploy === "wrangler") {
lines.push(`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`);
}
if (serverDeploy === "wrangler") {
lines.push(
`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`,
`- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`,
);
}
}

return lines.length ? `\n${lines.join("\n")}\n` : "";
}
72 changes: 51 additions & 21 deletions apps/cli/src/helpers/core/db-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { spinner } from "@clack/prompts";
import consola from "consola";
import fs from "fs-extra";
import pc from "picocolors";
import type { AvailableDependencies } from "../../constants";
import type { ProjectConfig } from "../../types";
import { addPackageDependency } from "../../utils/add-package-deps";
import { setupCloudflareD1 } from "../database-providers/d1-setup";
Expand Down Expand Up @@ -33,51 +34,80 @@ export async function setupDatabase(

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

if (!(await fs.pathExists(dbPackageDir))) {
return;
}

try {
if (orm === "prisma") {
if (database === "mysql" && dbSetup === "planetscale") {
if (database === "mongodb") {
await addPackageDependency({
dependencies: [
"@prisma/client",
"@prisma/adapter-planetscale",
"@planetscale/database",
],
devDependencies: ["prisma"],
projectDir: dbPackageDir,
});
} else if (database === "sqlite" && dbSetup === "turso") {
await addPackageDependency({
dependencies: ["@prisma/client", "@prisma/adapter-libsql"],
devDependencies: ["prisma"],
customDependencies: {
"@prisma/client": "6.19.0",
},
customDevDependencies: {
prisma: "6.19.0",
},
projectDir: dbPackageDir,
});
} else {
const prismaDependencies: AvailableDependencies[] = ["@prisma/client"];
const prismaDevDependencies: AvailableDependencies[] = ["prisma"];

if (database === "mysql" && dbSetup === "planetscale") {
prismaDependencies.push(
"@prisma/adapter-planetscale",
"@planetscale/database",
);
} else if (database === "mysql") {
prismaDependencies.push("@prisma/adapter-mariadb");
} else if (database === "sqlite") {
prismaDependencies.push("@prisma/adapter-libsql");
} else if (database === "postgres") {
if (dbSetup === "neon") {
prismaDependencies.push("@prisma/adapter-neon");
} else {
prismaDependencies.push("@prisma/adapter-pg");
prismaDependencies.push("pg");
prismaDevDependencies.push("@types/pg");
}
}

await addPackageDependency({
dependencies: ["@prisma/client"],
devDependencies: ["prisma"],
dependencies: prismaDependencies,
devDependencies: prismaDevDependencies,
projectDir: dbPackageDir,
});
}

const webDir = path.join(projectDir, "apps/web");
if (await fs.pathExists(webDir)) {
await addPackageDependency({
dependencies: ["@prisma/client"],
projectDir: webDir,
});
if (database === "mongodb") {
await addPackageDependency({
customDependencies: {
"@prisma/client": "6.19.0",
},
projectDir: webDir,
});
} else {
await addPackageDependency({
dependencies: ["@prisma/client"],
projectDir: webDir,
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Prisma MongoDB hardcoded to v6.19.0 instead of v7.0.0

The code hardcodes Prisma and @prisma/client to version 6.19.0 when setting up MongoDB projects (lines 48-49 and 98-99), but the dependencyVersionMap in constants.ts specifies version ^7.0.0 for all Prisma packages. This creates a version mismatch where MongoDB projects will use an older Prisma version than all other database configurations, causing inconsistency and potential compatibility issues. All Prisma packages including MongoDB should use ^7.0.0 to align with the PR's Prisma 7 support goal.

Fix in Cursor Fix in Web

}
} else if (orm === "drizzle") {
if (database === "sqlite") {
await addPackageDependency({
dependencies: ["drizzle-orm", "@libsql/client"],
dependencies: ["drizzle-orm", "@libsql/client", "libsql"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Verify that both @libsql/client and libsql packages are required.

The dependency array now includes both @libsql/client and libsql. Please confirm whether both packages are necessary for libsql/Drizzle integration with SQLite, or if there's any redundancy.


🌐 Web query:

Do libsql Drizzle projects require both @libsql/client and libsql npm packages?

💡 Result:

Short answer: No — Drizzle projects using the libSQL driver only require the @libsql/client package (plus drizzle-orm/drizzle-kit as usual). The separate libsql npm package is a different libSQL JS binding and is not required by Drizzle. [1][2][3]

Sources:

  • Drizzle docs (libsql driver install instructions — recommends @libsql/client). [1]
  • @libsql/client npm page (client/SDK used by Drizzle). [2]
  • libsql npm page (separate libSQL Node bindings / different package). [3]

Remove the libsql package from dependencies — only @libsql/client is required.

Drizzle's libSQL driver only requires @libsql/client; the separate libsql package is an unrelated libSQL JS binding and should not be included in the dependencies array at line 77.

🤖 Prompt for AI Agents
In apps/cli/src/helpers/core/db-setup.ts around line 77, the dependencies array
incorrectly includes the standalone "libsql" package; remove "libsql" so the
array only lists "drizzle-orm" and "@libsql/client". Update the dependencies
entry to delete the "libsql" string and ensure no other references to the
removed package exist in this file.

devDependencies: ["drizzle-kit"],
projectDir: dbPackageDir,
});
await addPackageDependency({
dependencies: ["@libsql/client", "libsql"],
projectDir: webDir,
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Drizzle: Inconsistent Directory Checks

For Drizzle with SQLite, webDir dependencies are added without checking if the directory exists first. The Prisma section (line 85) checks if (await fs.pathExists(webDir)) before proceeding, but the Drizzle section skips this check, potentially causing errors if apps/web doesn't exist.

Fix in Cursor Fix in Web

} else if (database === "postgres") {
if (dbSetup === "neon") {
await addPackageDependency({
Expand Down
2 changes: 0 additions & 2 deletions apps/cli/src/helpers/core/env-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,6 @@ ${hasWeb ? "# npx convex env set SITE_URL http://localhost:3001\n" : ""}
case "sqlite":
if (
config.runtime === "workers" ||
webDeploy === "wrangler" ||
serverDeploy === "wrangler" ||
webDeploy === "alchemy" ||
serverDeploy === "alchemy"
) {
Expand Down
91 changes: 7 additions & 84 deletions apps/cli/src/helpers/core/post-installation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,6 @@ export async function displayPostInstallInstructions(
config.payments === "polar" && config.auth === "better-auth"
? getPolarInstructions(backend)
: "";
const wranglerDeployInstructions = getWranglerDeployInstructions(
runCmd,
webDeploy,
serverDeploy,
backend,
);
const alchemyDeployInstructions = getAlchemyDeployInstructions(
runCmd,
webDeploy,
Expand Down Expand Up @@ -127,10 +121,7 @@ export async function displayPostInstallInstructions(
if (
database === "sqlite" &&
dbSetup === "none" &&
(serverDeploy === "wrangler" ||
serverDeploy === "alchemy" ||
webDeploy === "wrangler" ||
webDeploy === "alchemy")
(serverDeploy === "alchemy" || webDeploy === "alchemy")
) {
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(
" (starts local SQLite server for Workers compatibility)",
Expand Down Expand Up @@ -162,9 +153,6 @@ export async function displayPostInstallInstructions(
)} Complete D1 database setup first\n (see Database commands below)\n`;
}
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
if (serverDeploy === "wrangler") {
output += `${pc.cyan(`${stepCounter++}.`)} cd apps/server && ${runCmd} cf-typegen\n`;
}
}
}

Expand Down Expand Up @@ -203,8 +191,6 @@ export async function displayPostInstallInstructions(
if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
if (wranglerDeployInstructions)
output += `\n${wranglerDeployInstructions.trim()}\n`;
if (alchemyDeployInstructions)
output += `\n${alchemyDeployInstructions.trim()}\n`;
if (starlightInstructions) output += `\n${starlightInstructions.trim()}\n`;
Expand Down Expand Up @@ -261,10 +247,10 @@ async function getDatabaseInstructions(
database: Database,
orm?: ORM,
runCmd?: string,
runtime?: Runtime,
_runtime?: Runtime,
dbSetup?: DatabaseSetup,
serverDeploy?: string,
backend?: string,
_backend?: string,
) {
const instructions: string[] = [];

Expand All @@ -277,49 +263,6 @@ async function getDatabaseInstructions(
}
}

if (serverDeploy === "wrangler" && dbSetup === "d1") {
if (orm === "prisma" && runtime === "workers") {
instructions.push(
`\n${pc.yellow(
"WARNING:",
)} Prisma + D1 on Workers with Wrangler has migration issues.\n Consider using Alchemy deploy instead of Wrangler for D1 projects.\n`,
);
}
const packageManager = runCmd === "npm run" ? "npm" : runCmd || "npm";

instructions.push(
`${pc.cyan("1.")} Login to Cloudflare: ${pc.white(
`${packageManager} wrangler login`,
)}`,
);
instructions.push(
`${pc.cyan("2.")} Create D1 database: ${pc.white(
`${packageManager} wrangler d1 create your-database-name`,
)}`,
);
const wranglerPath = backend === "self" ? "apps/web" : "apps/server";
instructions.push(
`${pc.cyan(
"3.",
)} Update ${wranglerPath}/wrangler.jsonc with database_id and database_name`,
);
instructions.push(
`${pc.cyan("4.")} Generate migrations: ${pc.white(
`cd ${wranglerPath} && ${runCmd} db:generate`,
)}`,
);
instructions.push(
`${pc.cyan("5.")} Apply migrations locally: ${pc.white(
`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME --local`,
)}`,
);
instructions.push(
`${pc.cyan("6.")} Apply migrations to production: ${pc.white(
`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME`,
)}`,
);
}

if (dbSetup === "d1" && serverDeploy === "alchemy") {
if (orm === "drizzle") {
instructions.push(
Expand Down Expand Up @@ -368,6 +311,9 @@ async function getDatabaseInstructions(
);
}
if (!(dbSetup === "d1" && serverDeploy === "alchemy")) {
instructions.push(
`${pc.cyan("•")} Generate Prisma Client: ${`${runCmd} db:generate`}`,
);
instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
}
if (!(dbSetup === "d1" && serverDeploy === "alchemy")) {
Expand Down Expand Up @@ -442,29 +388,6 @@ function getBunWebNativeWarning() {
)} 'bun' might cause issues with web + native apps in a monorepo.\n Use 'pnpm' if problems arise.`;
}

function getWranglerDeployInstructions(
runCmd?: string,
webDeploy?: string,
serverDeploy?: string,
backend?: string,
) {
const instructions: string[] = [];

if (webDeploy === "wrangler") {
const deployPath = backend === "self" ? "apps/web" : "apps/web";
instructions.push(
`${pc.bold("Deploy web to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd ${deployPath} && ${runCmd} deploy`}`,
);
}
if (serverDeploy === "wrangler" && backend !== "self") {
instructions.push(
`${pc.bold("Deploy server to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}`,
);
}

return instructions.length ? `\n${instructions.join("\n")}` : "";
}

function getClerkInstructions() {
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`;
}
Expand All @@ -485,7 +408,7 @@ function getAlchemyDeployInstructions(

if (webDeploy === "alchemy" && serverDeploy !== "alchemy") {
instructions.push(
`${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`}`,
`${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`}`,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Inconsistent Alchemy Command Prefixes

Inconsistent alchemy command prefix in deployment instructions. The "Dev" command includes alchemy prefix (cd apps/web && ${runCmd} alchemy dev), but the "Deploy" and "Destroy" commands don't (cd apps/web && ${runCmd} deploy). This mismatch will cause the deploy and destroy commands to fail. All three should consistently use either just ${runCmd} deploy or ${runCmd} alchemy deploy.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Alchemy Web Deployment: Command Prefix Error

The web Alchemy deployment instructions include an incorrect Dev command prefix. For web-only Alchemy deployment, the instruction shows cd apps/web && ${runCmd} alchemy dev, but should be cd apps/web && ${runCmd} dev since the alchemy scripts are defined in the root package.json (as dev: "alchemy dev"). The current format attempts to run npm run alchemy dev which is incorrect.

Fix in Cursor Fix in Web

);
} else if (
serverDeploy === "alchemy" &&
Expand Down
8 changes: 6 additions & 2 deletions apps/cli/src/helpers/core/template-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,9 @@ export async function setupDeploymentTemplates(
context,
);

await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
if (!isBackendSelf) {
await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
}
}
} else {
if (context.webDeploy === "alchemy") {
Expand All @@ -1183,7 +1185,9 @@ export async function setupDeploymentTemplates(
context,
);

await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
if (!isBackendSelf) {
await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
}
}
}

Expand Down
Loading