create-better-t-stack 3.4.2 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.d.ts +0 -6
  3. package/dist/index.js +1 -1
  4. package/dist/{src-BmqgKPgS.js → src-C46pe-uS.js} +92 -436
  5. package/package.json +1 -1
  6. package/templates/api/orpc/server/package.json.hbs +1 -5
  7. package/templates/api/orpc/server/tsconfig.json.hbs +1 -4
  8. package/templates/api/trpc/server/package.json.hbs +1 -5
  9. package/templates/api/trpc/server/tsconfig.json.hbs +1 -4
  10. package/templates/auth/better-auth/server/base/package.json.hbs +1 -5
  11. package/templates/auth/better-auth/server/base/tsconfig.json.hbs +1 -4
  12. package/templates/db/base/package.json.hbs +1 -5
  13. package/templates/db/base/tsconfig.json.hbs +1 -4
  14. package/templates/db/drizzle/sqlite/drizzle.config.ts.hbs +0 -7
  15. package/templates/db/prisma/mongodb/prisma/schema/schema.prisma.hbs +1 -1
  16. package/templates/db/prisma/mysql/prisma/schema/schema.prisma.hbs +8 -12
  17. package/templates/db/prisma/mysql/prisma.config.ts.hbs +17 -14
  18. package/templates/db/prisma/mysql/src/index.ts.hbs +46 -4
  19. package/templates/db/prisma/postgres/prisma/schema/schema.prisma.hbs +1 -5
  20. package/templates/db/prisma/postgres/prisma.config.ts.hbs +9 -6
  21. package/templates/db/prisma/postgres/src/index.ts.hbs +46 -1
  22. package/templates/db/prisma/sqlite/prisma/schema/schema.prisma.hbs +1 -12
  23. package/templates/db/prisma/sqlite/prisma.config.ts.hbs +16 -9
  24. package/templates/db/prisma/sqlite/src/index.ts.hbs +15 -15
  25. package/templates/deploy/alchemy/alchemy.run.ts.hbs +67 -5
  26. package/templates/examples/ai/web/react/next/src/app/ai/page.tsx.hbs +2 -2
  27. package/templates/extras/_npmrc.hbs +2 -2
  28. package/templates/frontend/native/uniwind/app/(drawer)/_layout.tsx.hbs +21 -13
  29. package/templates/frontend/react/next/next.config.ts.hbs +5 -2
  30. package/templates/frontend/react/next/tsconfig.json.hbs +0 -3
  31. package/templates/packages/config/tsconfig.base.json.hbs +1 -1
  32. package/templates/api/orpc/server/tsdown.config.ts.hbs +0 -7
  33. package/templates/api/trpc/server/tsdown.config.ts.hbs +0 -7
  34. package/templates/auth/better-auth/server/base/tsdown.config.ts.hbs +0 -7
  35. package/templates/db/base/tsdown.config.ts.hbs +0 -7
  36. package/templates/deploy/wrangler/server/wrangler.jsonc.hbs +0 -39
  37. package/templates/deploy/wrangler/web/nuxt/wrangler.jsonc.hbs +0 -51
  38. package/templates/deploy/wrangler/web/react/next/open-next.config.ts +0 -6
  39. package/templates/deploy/wrangler/web/react/next/wrangler.jsonc.hbs +0 -22
  40. package/templates/deploy/wrangler/web/react/react-router/wrangler.jsonc.hbs +0 -8
  41. package/templates/deploy/wrangler/web/react/tanstack-router/wrangler.jsonc.hbs +0 -8
  42. package/templates/deploy/wrangler/web/react/tanstack-start/wrangler.jsonc.hbs +0 -20
  43. package/templates/deploy/wrangler/web/solid/wrangler.jsonc.hbs +0 -8
  44. package/templates/deploy/wrangler/web/svelte/wrangler.jsonc.hbs +0 -51
@@ -72,17 +72,22 @@ const dependencyVersionMap = {
72
72
  "drizzle-kit": "^0.31.2",
73
73
  "@planetscale/database": "^1.19.0",
74
74
  "@libsql/client": "^0.14.0",
75
- "@neondatabase/serverless": "^1.0.1",
75
+ libsql: "^0.5.22",
76
+ "@neondatabase/serverless": "^1.0.2",
76
77
  pg: "^8.14.1",
77
78
  "@types/pg": "^8.11.11",
78
79
  "@types/ws": "^8.18.1",
79
80
  ws: "^8.18.3",
80
81
  mysql2: "^3.14.0",
81
- "@prisma/client": "^6.15.0",
82
- prisma: "^6.15.0",
83
- "@prisma/adapter-d1": "^6.15.0",
84
- "@prisma/adapter-libsql": "^6.15.0",
85
- "@prisma/adapter-planetscale": "^6.15.0",
82
+ "@prisma/client": "^7.0.0",
83
+ prisma: "^7.0.0",
84
+ "@prisma/adapter-d1": "^7.0.0",
85
+ "@prisma/adapter-neon": "^7.0.0",
86
+ "@prisma/adapter-mariadb": "^7.0.0",
87
+ "@prisma/adapter-libsql": "^7.0.0",
88
+ "@prisma/adapter-better-sqlite3": "^7.0.0",
89
+ "@prisma/adapter-pg": "^7.0.0",
90
+ "@prisma/adapter-planetscale": "^7.0.0",
86
91
  mongoose: "^8.14.0",
87
92
  "vite-plugin-pwa": "^1.0.1",
88
93
  "@vite-pwa/assets-generator": "^1.0.0",
@@ -147,7 +152,7 @@ const dependencyVersionMap = {
147
152
  "@cloudflare/workers-types": "^4.20250822.0",
148
153
  alchemy: "^0.77.0",
149
154
  dotenv: "^17.2.2",
150
- tsdown: "^0.15.5",
155
+ tsdown: "^0.16.5",
151
156
  zod: "^4.1.11",
152
157
  srvx: "0.8.15",
153
158
  "@polar-sh/better-auth": "^1.1.3",
@@ -278,16 +283,8 @@ const ProjectNameSchema = z.string().min(1, "Project name cannot be empty").max(
278
283
  "*"
279
284
  ].some((char) => name.includes(char));
280
285
  }, "Project name contains invalid characters").refine((name) => name.toLowerCase() !== "node_modules", "Project name is reserved").describe("Project name or path");
281
- const WebDeploySchema = z.enum([
282
- "wrangler",
283
- "alchemy",
284
- "none"
285
- ]).describe("Web deployment");
286
- const ServerDeploySchema = z.enum([
287
- "wrangler",
288
- "alchemy",
289
- "none"
290
- ]).describe("Server deployment");
286
+ const WebDeploySchema = z.enum(["alchemy", "none"]).describe("Web deployment");
287
+ const ServerDeploySchema = z.enum(["alchemy", "none"]).describe("Server deployment");
291
288
  const DirectoryConflictSchema = z.enum([
292
289
  "merge",
293
290
  "overwrite",
@@ -1131,10 +1128,6 @@ async function getRuntimeChoice(runtime, backend) {
1131
1128
  //#endregion
1132
1129
  //#region src/prompts/server-deploy.ts
1133
1130
  function getDeploymentDisplay$1(deployment) {
1134
- if (deployment === "wrangler") return {
1135
- label: "Wrangler",
1136
- hint: "Deploy to Cloudflare Workers using Wrangler"
1137
- };
1138
1131
  if (deployment === "alchemy") return {
1139
1132
  label: "Alchemy",
1140
1133
  hint: "Deploy to Cloudflare Workers using Alchemy"
@@ -1144,40 +1137,17 @@ function getDeploymentDisplay$1(deployment) {
1144
1137
  hint: `Add ${deployment} deployment`
1145
1138
  };
1146
1139
  }
1147
- async function getServerDeploymentChoice(deployment, runtime, backend, webDeploy) {
1140
+ async function getServerDeploymentChoice(deployment, runtime, backend, _webDeploy) {
1148
1141
  if (deployment !== void 0) return deployment;
1149
1142
  if (backend === "none" || backend === "convex") return "none";
1150
1143
  if (backend !== "hono") return "none";
1151
- const options = [];
1152
- if (runtime !== "workers") return "none";
1153
- ["alchemy", "wrangler"].forEach((deploy) => {
1154
- const { label, hint } = getDeploymentDisplay$1(deploy);
1155
- options.unshift({
1156
- value: deploy,
1157
- label,
1158
- hint
1159
- });
1160
- });
1161
- const response = await select({
1162
- message: "Select server deployment",
1163
- options,
1164
- initialValue: webDeploy === "alchemy" ? "alchemy" : runtime === "workers" ? "wrangler" : DEFAULT_CONFIG.serverDeploy
1165
- });
1166
- if (isCancel(response)) return exitCancelled("Operation cancelled");
1167
- return response;
1144
+ if (runtime === "workers") return "alchemy";
1145
+ return "none";
1168
1146
  }
1169
1147
  async function getServerDeploymentToAdd(runtime, existingDeployment, backend) {
1170
1148
  if (backend !== "hono") return "none";
1171
1149
  const options = [];
1172
1150
  if (runtime === "workers") {
1173
- if (existingDeployment !== "wrangler") {
1174
- const { label, hint } = getDeploymentDisplay$1("wrangler");
1175
- options.push({
1176
- value: "wrangler",
1177
- label,
1178
- hint
1179
- });
1180
- }
1181
1151
  if (existingDeployment !== "alchemy") {
1182
1152
  const { label, hint } = getDeploymentDisplay$1("alchemy");
1183
1153
  options.push({
@@ -1193,7 +1163,7 @@ async function getServerDeploymentToAdd(runtime, existingDeployment, backend) {
1193
1163
  const response = await select({
1194
1164
  message: "Select server deployment",
1195
1165
  options,
1196
- initialValue: runtime === "workers" ? "wrangler" : DEFAULT_CONFIG.serverDeploy
1166
+ initialValue: DEFAULT_CONFIG.serverDeploy
1197
1167
  });
1198
1168
  if (isCancel(response)) return exitCancelled("Operation cancelled");
1199
1169
  return response;
@@ -1205,10 +1175,6 @@ function hasWebFrontend(frontends) {
1205
1175
  return frontends.some((f) => WEB_FRAMEWORKS.includes(f));
1206
1176
  }
1207
1177
  function getDeploymentDisplay(deployment) {
1208
- if (deployment === "wrangler") return {
1209
- label: "Wrangler",
1210
- hint: "Deploy to Cloudflare Workers using Wrangler"
1211
- };
1212
1178
  if (deployment === "alchemy") return {
1213
1179
  label: "Alchemy",
1214
1180
  hint: "Deploy to Cloudflare Workers using Alchemy"
@@ -1223,11 +1189,7 @@ async function getDeploymentChoice(deployment, _runtime, _backend, frontend = []
1223
1189
  if (!hasWebFrontend(frontend)) return "none";
1224
1190
  const response = await select({
1225
1191
  message: "Select web deployment",
1226
- options: [
1227
- "wrangler",
1228
- "alchemy",
1229
- "none"
1230
- ].map((deploy) => {
1192
+ options: ["alchemy", "none"].map((deploy) => {
1231
1193
  const { label, hint } = getDeploymentDisplay(deploy);
1232
1194
  return {
1233
1195
  value: deploy,
@@ -1243,14 +1205,6 @@ async function getDeploymentChoice(deployment, _runtime, _backend, frontend = []
1243
1205
  async function getDeploymentToAdd(frontend, existingDeployment) {
1244
1206
  if (!hasWebFrontend(frontend)) return "none";
1245
1207
  const options = [];
1246
- if (existingDeployment !== "wrangler") {
1247
- const { label, hint } = getDeploymentDisplay("wrangler");
1248
- options.push({
1249
- value: "wrangler",
1250
- label,
1251
- hint
1252
- });
1253
- }
1254
1208
  if (existingDeployment !== "alchemy") {
1255
1209
  const { label, hint } = getDeploymentDisplay("alchemy");
1256
1210
  options.push({
@@ -1814,8 +1768,8 @@ function validateFullConfig(config, providedFlags, options) {
1814
1768
  validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
1815
1769
  validateSelfBackendCompatibility(providedFlags, options, config);
1816
1770
  validateWorkersCompatibility(providedFlags, options, config);
1817
- if (config.runtime === "workers" && config.serverDeploy === "none") exitWithError("Cloudflare Workers runtime requires a server deployment. Please choose 'wrangler' or 'alchemy' for --server-deploy.");
1818
- if (providedFlags.has("serverDeploy") && (config.serverDeploy === "alchemy" || config.serverDeploy === "wrangler") && config.runtime !== "workers") exitWithError(`Server deployment '${config.serverDeploy}' requires '--runtime workers'. Please use '--runtime workers' or choose a different server deployment.`);
1771
+ if (config.runtime === "workers" && config.serverDeploy === "none") exitWithError("Cloudflare Workers runtime requires a server deployment. Please choose 'alchemy' for --server-deploy.");
1772
+ if (providedFlags.has("serverDeploy") && config.serverDeploy === "alchemy" && config.runtime !== "workers") exitWithError(`Server deployment '${config.serverDeploy}' requires '--runtime workers'. Please use '--runtime workers' or choose a different server deployment.`);
1819
1773
  if (config.addons && config.addons.length > 0) {
1820
1774
  validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
1821
1775
  config.addons = [...new Set(config.addons)];
@@ -3226,14 +3180,14 @@ async function setupDeploymentTemplates(projectDir, context) {
3226
3180
  if (await fs.pathExists(alchemyTemplateSrc)) {
3227
3181
  const webAppDir = path.join(projectDir, "apps/web");
3228
3182
  await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, isBackendSelf && await fs.pathExists(webAppDir) ? webAppDir : projectDir, context);
3229
- await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
3183
+ if (!isBackendSelf) await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
3230
3184
  }
3231
3185
  } else {
3232
3186
  if (context.webDeploy === "alchemy") {
3233
3187
  const webAppDir = path.join(projectDir, "apps/web");
3234
3188
  if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(webAppDir)) {
3235
3189
  await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, webAppDir, context);
3236
- await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
3190
+ if (!isBackendSelf) await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
3237
3191
  }
3238
3192
  }
3239
3193
  if (context.serverDeploy === "alchemy" && !isBackendSelf) {
@@ -3337,54 +3291,13 @@ async function addAddonsToProject(input) {
3337
3291
  //#region src/helpers/deployment/server-deploy-setup.ts
3338
3292
  async function setupServerDeploy(config) {
3339
3293
  const { serverDeploy, webDeploy, projectDir } = config;
3340
- const { packageManager } = config;
3341
3294
  if (serverDeploy === "none") return;
3342
3295
  if (serverDeploy === "alchemy" && webDeploy === "alchemy") return;
3343
3296
  const serverDir = path.join(projectDir, "apps/server");
3344
3297
  if (!await fs.pathExists(serverDir)) return;
3345
- if (serverDeploy === "wrangler") {
3346
- await setupWorkersServerDeploy(serverDir, packageManager);
3347
- await generateCloudflareWorkerTypes({
3348
- serverDir,
3349
- packageManager
3350
- });
3351
- } else if (serverDeploy === "alchemy") await setupAlchemyServerDeploy(serverDir, packageManager, projectDir);
3352
- }
3353
- async function setupWorkersServerDeploy(serverDir, _packageManager) {
3354
- const packageJsonPath = path.join(serverDir, "package.json");
3355
- if (!await fs.pathExists(packageJsonPath)) return;
3356
- const packageJson = await fs.readJson(packageJsonPath);
3357
- packageJson.scripts = {
3358
- ...packageJson.scripts,
3359
- dev: "wrangler dev --port=3000",
3360
- start: "wrangler dev",
3361
- deploy: "wrangler deploy",
3362
- build: "wrangler deploy --dry-run",
3363
- "cf-typegen": "wrangler types --env-interface CloudflareBindings"
3364
- };
3365
- await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
3366
- await addPackageDependency({
3367
- devDependencies: ["wrangler", "@types/node"],
3368
- projectDir: serverDir
3369
- });
3370
- }
3371
- async function generateCloudflareWorkerTypes({ serverDir, packageManager }) {
3372
- if (!await fs.pathExists(serverDir)) return;
3373
- const s = spinner();
3374
- try {
3375
- s.start("Generating Cloudflare Workers types...");
3376
- await execa(getPackageExecutionCommand(packageManager, "wrangler types --env-interface CloudflareBindings"), {
3377
- cwd: serverDir,
3378
- shell: true
3379
- });
3380
- s.stop("Cloudflare Workers types generated successfully!");
3381
- } catch {
3382
- s.stop(pc.yellow("Failed to generate Cloudflare Workers types"));
3383
- const managerCmd = `${packageManager} run`;
3384
- log.warn(`Note: You can manually run 'cd apps/server && ${managerCmd} cf-typegen' in the project directory later`);
3385
- }
3298
+ if (serverDeploy === "alchemy") await setupAlchemyServerDeploy(serverDir, projectDir);
3386
3299
  }
3387
- async function setupAlchemyServerDeploy(serverDir, _packageManager, projectDir) {
3300
+ async function setupAlchemyServerDeploy(serverDir, projectDir) {
3388
3301
  if (!await fs.pathExists(serverDir)) return;
3389
3302
  await addPackageDependency({
3390
3303
  devDependencies: [
@@ -3719,7 +3632,7 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
3719
3632
  await fs.writeJson(rootPkgPath, pkg, { spaces: 2 });
3720
3633
  }
3721
3634
  const serverDir = path.join(projectDir, "apps/server");
3722
- if (await fs.pathExists(serverDir)) await setupAlchemyServerDeploy(serverDir, packageManager, projectDir);
3635
+ if (await fs.pathExists(serverDir)) await setupAlchemyServerDeploy(serverDir, projectDir);
3723
3636
  const frontend = config.frontend;
3724
3637
  const isNext = frontend.includes("next");
3725
3638
  const isNuxt = frontend.includes("nuxt");
@@ -3737,219 +3650,13 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
3737
3650
  else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
3738
3651
  }
3739
3652
 
3740
- //#endregion
3741
- //#region src/helpers/deployment/workers/workers-next-setup.ts
3742
- async function setupNextWorkersDeploy(projectDir, _packageManager) {
3743
- const webAppDir = path.join(projectDir, "apps/web");
3744
- if (!await fs.pathExists(webAppDir)) return;
3745
- await addPackageDependency({
3746
- dependencies: ["@opennextjs/cloudflare"],
3747
- devDependencies: ["wrangler"],
3748
- projectDir: webAppDir
3749
- });
3750
- const packageJsonPath = path.join(webAppDir, "package.json");
3751
- if (await fs.pathExists(packageJsonPath)) {
3752
- const pkg = await fs.readJson(packageJsonPath);
3753
- pkg.scripts = {
3754
- ...pkg.scripts,
3755
- preview: "opennextjs-cloudflare build && opennextjs-cloudflare preview",
3756
- deploy: "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
3757
- upload: "opennextjs-cloudflare build && opennextjs-cloudflare upload",
3758
- "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
3759
- };
3760
- await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
3761
- }
3762
- }
3763
-
3764
- //#endregion
3765
- //#region src/helpers/deployment/workers/workers-nuxt-setup.ts
3766
- async function setupNuxtWorkersDeploy(projectDir, packageManager) {
3767
- const webAppDir = path.join(projectDir, "apps/web");
3768
- if (!await fs.pathExists(webAppDir)) return;
3769
- await addPackageDependency({
3770
- devDependencies: ["nitro-cloudflare-dev", "wrangler"],
3771
- projectDir: webAppDir
3772
- });
3773
- const pkgPath = path.join(webAppDir, "package.json");
3774
- if (await fs.pathExists(pkgPath)) {
3775
- const pkg = await fs.readJson(pkgPath);
3776
- pkg.scripts = {
3777
- ...pkg.scripts,
3778
- deploy: `${packageManager} run build && wrangler deploy`,
3779
- "cf-typegen": "wrangler types"
3780
- };
3781
- await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3782
- }
3783
- const nuxtConfigPath = path.join(webAppDir, "nuxt.config.ts");
3784
- if (!await fs.pathExists(nuxtConfigPath)) return;
3785
- const sourceFile = tsProject.addSourceFileAtPathIfExists(nuxtConfigPath);
3786
- if (!sourceFile) return;
3787
- const defineCall = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).find((expr) => {
3788
- const expression = expr.getExpression();
3789
- return Node.isIdentifier(expression) && expression.getText() === "defineNuxtConfig";
3790
- });
3791
- if (!defineCall) return;
3792
- const configObj = defineCall.getArguments()[0];
3793
- if (!configObj) return;
3794
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3795
- const compatProp = configObj.getProperty("compatibilityDate");
3796
- if (compatProp && compatProp.getKind() === SyntaxKind.PropertyAssignment) compatProp.setInitializer(`'${today}'`);
3797
- else configObj.addPropertyAssignment({
3798
- name: "compatibilityDate",
3799
- initializer: `'${today}'`
3800
- });
3801
- const nitroInitializer = `{
3802
- preset: "cloudflare_module",
3803
- cloudflare: {
3804
- deployConfig: true,
3805
- nodeCompat: true
3806
- }
3807
- }`;
3808
- const nitroProp = configObj.getProperty("nitro");
3809
- if (nitroProp && nitroProp.getKind() === SyntaxKind.PropertyAssignment) nitroProp.setInitializer(nitroInitializer);
3810
- else configObj.addPropertyAssignment({
3811
- name: "nitro",
3812
- initializer: nitroInitializer
3813
- });
3814
- const modulesProp = configObj.getProperty("modules");
3815
- if (modulesProp && modulesProp.getKind() === SyntaxKind.PropertyAssignment) {
3816
- const arrayExpr = modulesProp.getFirstDescendantByKind(SyntaxKind.ArrayLiteralExpression);
3817
- if (arrayExpr) {
3818
- if (!arrayExpr.getElements().some((el) => el.getText().replace(/['"`]/g, "") === "nitro-cloudflare-dev")) arrayExpr.addElement("'nitro-cloudflare-dev'");
3819
- }
3820
- } else configObj.addPropertyAssignment({
3821
- name: "modules",
3822
- initializer: "['nitro-cloudflare-dev']"
3823
- });
3824
- await tsProject.save();
3825
- }
3826
-
3827
- //#endregion
3828
- //#region src/helpers/deployment/workers/workers-svelte-setup.ts
3829
- async function setupSvelteWorkersDeploy(projectDir, packageManager) {
3830
- const webAppDir = path.join(projectDir, "apps/web");
3831
- if (!await fs.pathExists(webAppDir)) return;
3832
- await addPackageDependency({
3833
- devDependencies: ["@sveltejs/adapter-cloudflare", "wrangler"],
3834
- projectDir: webAppDir
3835
- });
3836
- const pkgPath = path.join(webAppDir, "package.json");
3837
- if (await fs.pathExists(pkgPath)) {
3838
- const pkg = await fs.readJson(pkgPath);
3839
- pkg.scripts = {
3840
- ...pkg.scripts,
3841
- deploy: `${packageManager} run build && wrangler deploy`,
3842
- "cf-typegen": "wrangler types ./src/worker-configuration.d.ts"
3843
- };
3844
- await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3845
- }
3846
- const possibleConfigFiles = [path.join(webAppDir, "svelte.config.js"), path.join(webAppDir, "svelte.config.ts")];
3847
- const existingConfigPath = (await Promise.all(possibleConfigFiles.map(async (p) => await fs.pathExists(p) ? p : ""))).find((p) => p);
3848
- if (existingConfigPath) {
3849
- const sourceFile = tsProject.addSourceFileAtPathIfExists(existingConfigPath);
3850
- if (!sourceFile) return;
3851
- const adapterImport = sourceFile.getImportDeclarations().find((imp) => ["@sveltejs/adapter-auto", "@sveltejs/adapter-node"].includes(imp.getModuleSpecifierValue()));
3852
- if (adapterImport) adapterImport.setModuleSpecifier("@sveltejs/adapter-cloudflare");
3853
- else if (!sourceFile.getImportDeclarations().some((imp) => imp.getModuleSpecifierValue() === "@sveltejs/adapter-cloudflare")) sourceFile.insertImportDeclaration(0, {
3854
- defaultImport: "adapter",
3855
- moduleSpecifier: "@sveltejs/adapter-cloudflare"
3856
- });
3857
- await tsProject.save();
3858
- }
3859
- }
3860
-
3861
- //#endregion
3862
- //#region src/helpers/deployment/workers/workers-tanstack-start-setup.ts
3863
- async function setupTanstackStartWorkersDeploy(projectDir, packageManager) {
3864
- const webAppDir = path.join(projectDir, "apps/web");
3865
- if (!await fs.pathExists(webAppDir)) return;
3866
- await addPackageDependency({
3867
- devDependencies: ["wrangler", "@cloudflare/vite-plugin"],
3868
- projectDir: webAppDir
3869
- });
3870
- const pkgPath = path.join(webAppDir, "package.json");
3871
- if (await fs.pathExists(pkgPath)) {
3872
- const pkg = await fs.readJson(pkgPath);
3873
- pkg.scripts = {
3874
- ...pkg.scripts,
3875
- deploy: `${packageManager} run build && wrangler deploy`,
3876
- "cf-typegen": "wrangler types --env-interface Env"
3877
- };
3878
- await fs.writeJson(pkgPath, pkg, { spaces: 2 });
3879
- }
3880
- const viteConfigPath = path.join(webAppDir, "vite.config.ts");
3881
- if (!await fs.pathExists(viteConfigPath)) return;
3882
- const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath);
3883
- if (!sourceFile) return;
3884
- const cfImport = sourceFile.getImportDeclaration("@cloudflare/vite-plugin");
3885
- if (!cfImport) sourceFile.addImportDeclaration({
3886
- moduleSpecifier: "@cloudflare/vite-plugin",
3887
- namedImports: [{ name: "cloudflare" }]
3888
- });
3889
- else if (!cfImport.getNamedImports().some((ni) => ni.getName() === "cloudflare")) cfImport.addNamedImport({ name: "cloudflare" });
3890
- const reactImport = sourceFile.getImportDeclaration("@vitejs/plugin-react");
3891
- let reactPluginIdentifier = "viteReact";
3892
- if (!reactImport) sourceFile.addImportDeclaration({
3893
- moduleSpecifier: "@vitejs/plugin-react",
3894
- defaultImport: "viteReact"
3895
- });
3896
- else {
3897
- const defaultImport = reactImport.getDefaultImport();
3898
- if (defaultImport) reactPluginIdentifier = defaultImport.getText();
3899
- else reactImport.setDefaultImport("viteReact");
3900
- }
3901
- const defineCall = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).find((expr) => {
3902
- const expression = expr.getExpression();
3903
- return Node.isIdentifier(expression) && expression.getText() === "defineConfig";
3904
- });
3905
- if (!defineCall) return;
3906
- const configObj = defineCall.getArguments()[0];
3907
- if (!configObj) return;
3908
- const pluginsArray = ensureArrayProperty(configObj, "plugins");
3909
- if (!pluginsArray.getElements().some((el) => el.getText().includes("cloudflare("))) pluginsArray.insertElement(0, "cloudflare({ viteEnvironment: { name: 'ssr' } })");
3910
- if (!pluginsArray.getElements().some((el) => Node.isCallExpression(el) && el.getExpression().getText() === reactPluginIdentifier)) {
3911
- const nextIndex = pluginsArray.getElements().findIndex((el) => el.getText().includes("tanstackStart(")) + 1;
3912
- if (nextIndex > 0) pluginsArray.insertElement(nextIndex, `${reactPluginIdentifier}()`);
3913
- else pluginsArray.addElement(`${reactPluginIdentifier}()`);
3914
- }
3915
- await tsProject.save();
3916
- }
3917
-
3918
- //#endregion
3919
- //#region src/helpers/deployment/workers/workers-vite-setup.ts
3920
- async function setupWorkersVitePlugin(projectDir) {
3921
- const webAppDir = path.join(projectDir, "apps/web");
3922
- const viteConfigPath = path.join(webAppDir, "vite.config.ts");
3923
- if (!await fs.pathExists(viteConfigPath)) throw new Error("vite.config.ts not found in web app directory");
3924
- await addPackageDependency({
3925
- devDependencies: ["@cloudflare/vite-plugin", "wrangler"],
3926
- projectDir: webAppDir
3927
- });
3928
- const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath);
3929
- if (!sourceFile) throw new Error("vite.config.ts not found in web app directory");
3930
- if (!sourceFile.getImportDeclarations().some((imp) => imp.getModuleSpecifierValue() === "@cloudflare/vite-plugin")) sourceFile.insertImportDeclaration(0, {
3931
- namedImports: ["cloudflare"],
3932
- moduleSpecifier: "@cloudflare/vite-plugin"
3933
- });
3934
- const defineCall = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).find((expr) => {
3935
- const expression = expr.getExpression();
3936
- return Node.isIdentifier(expression) && expression.getText() === "defineConfig";
3937
- });
3938
- if (!defineCall) throw new Error("Could not find defineConfig call in vite config");
3939
- const configObject = defineCall.getArguments()[0];
3940
- if (!configObject) throw new Error("defineConfig argument is not an object literal");
3941
- const pluginsArray = ensureArrayProperty(configObject, "plugins");
3942
- if (!pluginsArray.getElements().some((el) => el.getText().includes("cloudflare("))) pluginsArray.addElement("cloudflare()");
3943
- await tsProject.save();
3944
- }
3945
-
3946
3653
  //#endregion
3947
3654
  //#region src/helpers/deployment/web-deploy-setup.ts
3948
3655
  async function setupWebDeploy(config) {
3949
3656
  const { webDeploy, serverDeploy, frontend, projectDir } = config;
3950
3657
  const { packageManager } = config;
3951
3658
  if (webDeploy === "none") return;
3952
- if (webDeploy !== "wrangler" && webDeploy !== "alchemy") return;
3659
+ if (webDeploy !== "alchemy") return;
3953
3660
  if (webDeploy === "alchemy" && serverDeploy === "alchemy") {
3954
3661
  await setupCombinedAlchemyDeploy(projectDir, packageManager, config);
3955
3662
  await addAlchemyPackagesDependencies(projectDir);
@@ -3962,37 +3669,14 @@ async function setupWebDeploy(config) {
3962
3669
  const isTanstackStart = frontend.includes("tanstack-start");
3963
3670
  const isReactRouter = frontend.includes("react-router");
3964
3671
  const isSolid = frontend.includes("solid");
3965
- if (webDeploy === "wrangler") {
3966
- if (isNext) await setupNextWorkersDeploy(projectDir, packageManager);
3967
- else if (isNuxt) await setupNuxtWorkersDeploy(projectDir, packageManager);
3968
- else if (isSvelte) await setupSvelteWorkersDeploy(projectDir, packageManager);
3969
- else if (isTanstackStart) await setupTanstackStartWorkersDeploy(projectDir, packageManager);
3970
- else if (isTanstackRouter || isReactRouter || isSolid) await setupWorkersWebDeploy(projectDir, packageManager);
3971
- } else if (webDeploy === "alchemy") {
3972
- if (isNext) await setupNextAlchemyDeploy(projectDir, packageManager);
3973
- else if (isNuxt) await setupNuxtAlchemyDeploy(projectDir, packageManager);
3974
- else if (isSvelte) await setupSvelteAlchemyDeploy(projectDir, packageManager);
3975
- else if (isTanstackStart) await setupTanStackStartAlchemyDeploy(projectDir, packageManager);
3976
- else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager);
3977
- else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager);
3978
- else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager);
3979
- await addAlchemyPackagesDependencies(projectDir);
3980
- }
3981
- }
3982
- async function setupWorkersWebDeploy(projectDir, pkgManager) {
3983
- const webAppDir = path.join(projectDir, "apps/web");
3984
- if (!await fs.pathExists(webAppDir)) return;
3985
- const packageJsonPath = path.join(webAppDir, "package.json");
3986
- if (await fs.pathExists(packageJsonPath)) {
3987
- const packageJson = await fs.readJson(packageJsonPath);
3988
- packageJson.scripts = {
3989
- ...packageJson.scripts,
3990
- "wrangler:dev": "wrangler dev --port=3001",
3991
- deploy: `${pkgManager} run build && wrangler deploy`
3992
- };
3993
- await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
3994
- }
3995
- await setupWorkersVitePlugin(projectDir);
3672
+ if (isNext) await setupNextAlchemyDeploy(projectDir, packageManager);
3673
+ else if (isNuxt) await setupNuxtAlchemyDeploy(projectDir, packageManager);
3674
+ else if (isSvelte) await setupSvelteAlchemyDeploy(projectDir, packageManager);
3675
+ else if (isTanstackStart) await setupTanStackStartAlchemyDeploy(projectDir, packageManager);
3676
+ else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager);
3677
+ else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager);
3678
+ else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager);
3679
+ await addAlchemyPackagesDependencies(projectDir);
3996
3680
  }
3997
3681
  async function addAlchemyPackagesDependencies(projectDir) {
3998
3682
  await addPackageDependency({
@@ -4853,7 +4537,7 @@ ${hasWeb ? "# npx convex env set SITE_URL http://localhost:3001\n" : ""}
4853
4537
  databaseUrl = "mongodb://localhost:27017/mydatabase";
4854
4538
  break;
4855
4539
  case "sqlite":
4856
- if (config.runtime === "workers" || webDeploy === "wrangler" || serverDeploy === "wrangler" || webDeploy === "alchemy" || serverDeploy === "alchemy") databaseUrl = "http://127.0.0.1:8080";
4540
+ if (config.runtime === "workers" || webDeploy === "alchemy" || serverDeploy === "alchemy") databaseUrl = "http://127.0.0.1:8080";
4857
4541
  else {
4858
4542
  const dbAppDir = backend === "self" ? "apps/web" : "apps/server";
4859
4543
  databaseUrl = `file:${path.join(config.projectDir, dbAppDir, "local.db")}`;
@@ -4935,31 +4619,7 @@ ${hasWeb ? "# npx convex env set SITE_URL http://localhost:3001\n" : ""}
4935
4619
  //#region src/helpers/database-providers/d1-setup.ts
4936
4620
  async function setupCloudflareD1(config) {
4937
4621
  const { projectDir, serverDeploy, orm, backend } = config;
4938
- if (serverDeploy === "wrangler") {
4939
- const targetApp = backend === "self" ? "apps/web" : "apps/server";
4940
- const envPath = path.join(projectDir, targetApp, ".env");
4941
- const variables = [
4942
- {
4943
- key: "CLOUDFLARE_ACCOUNT_ID",
4944
- value: "",
4945
- condition: true
4946
- },
4947
- {
4948
- key: "CLOUDFLARE_DATABASE_ID",
4949
- value: "",
4950
- condition: true
4951
- },
4952
- {
4953
- key: "CLOUDFLARE_D1_TOKEN",
4954
- value: "",
4955
- condition: true
4956
- }
4957
- ];
4958
- try {
4959
- await addEnvVariablesToFile(envPath, variables);
4960
- } catch (_err) {}
4961
- }
4962
- if ((serverDeploy === "wrangler" || serverDeploy === "alchemy") && orm === "prisma") {
4622
+ if (serverDeploy === "alchemy" && orm === "prisma") {
4963
4623
  const targetApp2 = backend === "self" ? "apps/web" : "apps/server";
4964
4624
  const envPath = path.join(projectDir, targetApp2, ".env");
4965
4625
  const variables = [{
@@ -5951,40 +5611,60 @@ async function setupDatabase(config, cliInput) {
5951
5611
  }
5952
5612
  const s = spinner();
5953
5613
  const dbPackageDir = path.join(projectDir, "packages/db");
5614
+ const webDir = path.join(projectDir, "apps/web");
5954
5615
  if (!await fs.pathExists(dbPackageDir)) return;
5955
5616
  try {
5956
5617
  if (orm === "prisma") {
5957
- if (database === "mysql" && dbSetup === "planetscale") await addPackageDependency({
5958
- dependencies: [
5959
- "@prisma/client",
5960
- "@prisma/adapter-planetscale",
5961
- "@planetscale/database"
5962
- ],
5963
- devDependencies: ["prisma"],
5618
+ if (database === "mongodb") await addPackageDependency({
5619
+ customDependencies: { "@prisma/client": "6.19.0" },
5620
+ customDevDependencies: { prisma: "6.19.0" },
5964
5621
  projectDir: dbPackageDir
5965
5622
  });
5966
- else if (database === "sqlite" && dbSetup === "turso") await addPackageDependency({
5967
- dependencies: ["@prisma/client", "@prisma/adapter-libsql"],
5968
- devDependencies: ["prisma"],
5969
- projectDir: dbPackageDir
5623
+ else {
5624
+ const prismaDependencies = ["@prisma/client"];
5625
+ const prismaDevDependencies = ["prisma"];
5626
+ if (database === "mysql" && dbSetup === "planetscale") prismaDependencies.push("@prisma/adapter-planetscale", "@planetscale/database");
5627
+ else if (database === "mysql") prismaDependencies.push("@prisma/adapter-mariadb");
5628
+ else if (database === "sqlite") if (dbSetup === "d1") prismaDependencies.push("@prisma/adapter-d1");
5629
+ else prismaDependencies.push("@prisma/adapter-libsql");
5630
+ else if (database === "postgres") if (dbSetup === "neon") {
5631
+ prismaDependencies.push("@prisma/adapter-neon", "@neondatabase/serverless", "ws");
5632
+ prismaDevDependencies.push("@types/ws");
5633
+ } else {
5634
+ prismaDependencies.push("@prisma/adapter-pg");
5635
+ prismaDependencies.push("pg");
5636
+ prismaDevDependencies.push("@types/pg");
5637
+ }
5638
+ await addPackageDependency({
5639
+ dependencies: prismaDependencies,
5640
+ devDependencies: prismaDevDependencies,
5641
+ projectDir: dbPackageDir
5642
+ });
5643
+ }
5644
+ if (await fs.pathExists(webDir)) if (database === "mongodb") await addPackageDependency({
5645
+ customDependencies: { "@prisma/client": "6.19.0" },
5646
+ projectDir: webDir
5970
5647
  });
5971
5648
  else await addPackageDependency({
5972
- dependencies: ["@prisma/client"],
5973
- devDependencies: ["prisma"],
5974
- projectDir: dbPackageDir
5975
- });
5976
- const webDir = path.join(projectDir, "apps/web");
5977
- if (await fs.pathExists(webDir)) await addPackageDependency({
5978
5649
  dependencies: ["@prisma/client"],
5979
5650
  projectDir: webDir
5980
5651
  });
5981
5652
  } else if (orm === "drizzle") {
5982
- if (database === "sqlite") await addPackageDependency({
5983
- dependencies: ["drizzle-orm", "@libsql/client"],
5984
- devDependencies: ["drizzle-kit"],
5985
- projectDir: dbPackageDir
5986
- });
5987
- else if (database === "postgres") if (dbSetup === "neon") await addPackageDependency({
5653
+ if (database === "sqlite") {
5654
+ await addPackageDependency({
5655
+ dependencies: [
5656
+ "drizzle-orm",
5657
+ "@libsql/client",
5658
+ "libsql"
5659
+ ],
5660
+ devDependencies: ["drizzle-kit"],
5661
+ projectDir: dbPackageDir
5662
+ });
5663
+ await addPackageDependency({
5664
+ dependencies: ["@libsql/client", "libsql"],
5665
+ projectDir: webDir
5666
+ });
5667
+ } else if (database === "postgres") if (dbSetup === "neon") await addPackageDependency({
5988
5668
  dependencies: [
5989
5669
  "drizzle-orm",
5990
5670
  "@neondatabase/serverless",
@@ -6303,7 +5983,7 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
6303
5983
  else if (addon === "turborepo") addonsList.push("- **Turborepo** - Optimized monorepo build system");
6304
5984
  return addonsList.join("\n");
6305
5985
  }
6306
- function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup, serverDeploy, backend) {
5986
+ function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup, _serverDeploy, backend) {
6307
5987
  if (database === "none") return "";
6308
5988
  const isBackendSelf = backend === "self";
6309
5989
  const envPath = isBackendSelf ? "apps/web/.env" : "apps/server/.env";
@@ -6312,7 +5992,7 @@ function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSet
6312
5992
  if (database === "sqlite") setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
6313
5993
 
6314
5994
  1. Start the local SQLite database:
6315
- ${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." : `\`\`\`bash
5995
+ ${dbSetup === "d1" ? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy." : `\`\`\`bash
6316
5996
  cd ${dbLocalPath} && ${packageManagerRunCmd} db:local
6317
5997
  \`\`\`
6318
5998
  `}
@@ -6410,11 +6090,6 @@ function generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeplo
6410
6090
  if (serverDeploy === "alchemy" && webDeploy !== "alchemy") lines.push(`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`, `- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`, `- Server destroy: cd apps/server && ${packageManagerRunCmd} destroy`);
6411
6091
  if (webDeploy === "alchemy" && serverDeploy === "alchemy") lines.push(`- Dev: ${packageManagerRunCmd} dev`, `- Deploy: ${packageManagerRunCmd} deploy`, `- Destroy: ${packageManagerRunCmd} destroy`);
6412
6092
  }
6413
- if (webDeploy === "wrangler" || serverDeploy === "wrangler") {
6414
- lines.push("\n## Deployment (Cloudflare Wrangler)");
6415
- if (webDeploy === "wrangler") lines.push(`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`);
6416
- if (serverDeploy === "wrangler") lines.push(`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`, `- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`);
6417
- }
6418
6093
  return lines.length ? `\n${lines.join("\n")}\n` : "";
6419
6094
  }
6420
6095
 
@@ -6538,7 +6213,6 @@ async function displayPostInstallInstructions(config) {
6538
6213
  const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
6539
6214
  const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
6540
6215
  const polarInstructions = config.payments === "polar" && config.auth === "better-auth" ? getPolarInstructions(backend) : "";
6541
- const wranglerDeployInstructions = getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
6542
6216
  const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
6543
6217
  const hasWeb = frontend?.some((f) => [
6544
6218
  "tanstack-router",
@@ -6558,7 +6232,7 @@ async function displayPostInstallInstructions(config) {
6558
6232
  let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
6559
6233
  let stepCounter = 2;
6560
6234
  if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} ${packageManager} install\n`;
6561
- if (database === "sqlite" && dbSetup === "none" && (serverDeploy === "wrangler" || serverDeploy === "alchemy" || webDeploy === "wrangler" || webDeploy === "alchemy")) output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (starts local SQLite server for Workers compatibility)")}\n`;
6235
+ if (database === "sqlite" && dbSetup === "none" && (serverDeploy === "alchemy" || webDeploy === "alchemy")) output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (starts local SQLite server for Workers compatibility)")}\n`;
6562
6236
  if (isConvex) {
6563
6237
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
6564
6238
  output += `${pc.cyan(`${stepCounter++}.`)} Copy environment variables from\n${pc.white(" packages/backend/.env.local")} to ${pc.white("apps/*/.env")}\n`;
@@ -6569,7 +6243,6 @@ async function displayPostInstallInstructions(config) {
6569
6243
  if (runtime === "workers") {
6570
6244
  if (dbSetup === "d1") output += `${pc.yellow("IMPORTANT:")} Complete D1 database setup first\n (see Database commands below)\n`;
6571
6245
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
6572
- if (serverDeploy === "wrangler") output += `${pc.cyan(`${stepCounter++}.`)} cd apps/server && ${runCmd} cf-typegen\n`;
6573
6246
  }
6574
6247
  }
6575
6248
  output += `${pc.bold("Your project will be available at:")}\n`;
@@ -6587,7 +6260,6 @@ async function displayPostInstallInstructions(config) {
6587
6260
  if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
6588
6261
  if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
6589
6262
  if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
6590
- if (wranglerDeployInstructions) output += `\n${wranglerDeployInstructions.trim()}\n`;
6591
6263
  if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
6592
6264
  if (starlightInstructions) output += `\n${starlightInstructions.trim()}\n`;
6593
6265
  if (clerkInstructions) output += `\n${clerkInstructions.trim()}\n`;
@@ -6610,7 +6282,7 @@ function getNativeInstructions(isConvex, isBackendSelf, _frontend) {
6610
6282
  function getLintingInstructions(runCmd) {
6611
6283
  return `${pc.bold("Linting and formatting:")}\n${pc.cyan("•")} Format and lint fix: ${`${runCmd} check`}\n`;
6612
6284
  }
6613
- async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) {
6285
+ async function getDatabaseInstructions(database, orm, runCmd, _runtime, dbSetup, serverDeploy, _backend) {
6614
6286
  const instructions = [];
6615
6287
  if (dbSetup === "docker") {
6616
6288
  const dockerStatus = await getDockerStatus(database);
@@ -6619,17 +6291,6 @@ async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup,
6619
6291
  instructions.push("");
6620
6292
  }
6621
6293
  }
6622
- if (serverDeploy === "wrangler" && dbSetup === "d1") {
6623
- 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`);
6624
- const packageManager = runCmd === "npm run" ? "npm" : runCmd || "npm";
6625
- instructions.push(`${pc.cyan("1.")} Login to Cloudflare: ${pc.white(`${packageManager} wrangler login`)}`);
6626
- instructions.push(`${pc.cyan("2.")} Create D1 database: ${pc.white(`${packageManager} wrangler d1 create your-database-name`)}`);
6627
- const wranglerPath = backend === "self" ? "apps/web" : "apps/server";
6628
- instructions.push(`${pc.cyan("3.")} Update ${wranglerPath}/wrangler.jsonc with database_id and database_name`);
6629
- instructions.push(`${pc.cyan("4.")} Generate migrations: ${pc.white(`cd ${wranglerPath} && ${runCmd} db:generate`)}`);
6630
- instructions.push(`${pc.cyan("5.")} Apply migrations locally: ${pc.white(`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME --local`)}`);
6631
- instructions.push(`${pc.cyan("6.")} Apply migrations to production: ${pc.white(`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME`)}`);
6632
- }
6633
6294
  if (dbSetup === "d1" && serverDeploy === "alchemy") {
6634
6295
  if (orm === "drizzle") instructions.push(`${pc.yellow("NOTE:")} D1 migrations are automatically handled by Alchemy`);
6635
6296
  else if (orm === "prisma") {
@@ -6641,10 +6302,14 @@ async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup,
6641
6302
  if (database === "mysql" && orm === "drizzle") instructions.push(`${pc.yellow("NOTE:")} Enable foreign key constraints in PlanetScale database settings`);
6642
6303
  if (database === "mysql" && orm === "prisma") instructions.push(`${pc.yellow("NOTE:")} How to handle Prisma migrations with PlanetScale:\n https://github.com/prisma/prisma/issues/7292`);
6643
6304
  }
6305
+ if (dbSetup === "turso" && orm === "prisma") instructions.push(`${pc.yellow("NOTE:")} Follow Turso's Prisma guide for migrations via the Turso CLI:\n https://docs.turso.tech/sdk/ts/orm/prisma`);
6644
6306
  if (orm === "prisma") {
6645
6307
  if (database === "mongodb" && dbSetup === "docker") instructions.push(`${pc.yellow("WARNING:")} Prisma + MongoDB + Docker combination\n may not work.`);
6646
6308
  if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
6647
- if (!(dbSetup === "d1" && serverDeploy === "alchemy")) instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
6309
+ if (!(dbSetup === "d1" && serverDeploy === "alchemy")) {
6310
+ instructions.push(`${pc.cyan("•")} Generate Prisma Client: ${`${runCmd} db:generate`}`);
6311
+ instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
6312
+ }
6648
6313
  if (!(dbSetup === "d1" && serverDeploy === "alchemy")) instructions.push(`${pc.cyan("•")} Database UI: ${`${runCmd} db:studio`}`);
6649
6314
  } else if (orm === "drizzle") {
6650
6315
  if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
@@ -6670,15 +6335,6 @@ function getNoOrmWarning() {
6670
6335
  function getBunWebNativeWarning() {
6671
6336
  return `\n${pc.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo.\n Use 'pnpm' if problems arise.`;
6672
6337
  }
6673
- function getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy, backend) {
6674
- const instructions = [];
6675
- if (webDeploy === "wrangler") {
6676
- const deployPath = backend === "self" ? "apps/web" : "apps/web";
6677
- instructions.push(`${pc.bold("Deploy web to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd ${deployPath} && ${runCmd} deploy`}`);
6678
- }
6679
- if (serverDeploy === "wrangler" && backend !== "self") instructions.push(`${pc.bold("Deploy server to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}`);
6680
- return instructions.length ? `\n${instructions.join("\n")}` : "";
6681
- }
6682
6338
  function getClerkInstructions() {
6683
6339
  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`;
6684
6340
  }
@@ -6689,7 +6345,7 @@ function getPolarInstructions(backend) {
6689
6345
  function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend) {
6690
6346
  const instructions = [];
6691
6347
  const isBackendSelf = backend === "self";
6692
- 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`}`);
6348
+ if (webDeploy === "alchemy" && serverDeploy !== "alchemy") instructions.push(`${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`}`);
6693
6349
  else if (serverDeploy === "alchemy" && webDeploy !== "alchemy" && !isBackendSelf) instructions.push(`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/server && ${runCmd} destroy`}`);
6694
6350
  else if (webDeploy === "alchemy" && (serverDeploy === "alchemy" || isBackendSelf)) instructions.push(`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
6695
6351
  return instructions.length ? `\n${instructions.join("\n")}` : "";
@@ -6701,7 +6357,7 @@ async function setupWorkspaceDependencies(projectDir, options) {
6701
6357
  const projectName = options.projectName;
6702
6358
  const workspaceVersion = options.packageManager === "npm" ? "*" : "workspace:*";
6703
6359
  const commonDeps = ["dotenv", "zod"];
6704
- const commonDevDeps = ["tsdown"];
6360
+ const commonDevDeps = [];
6705
6361
  const configPackageDir = path.join(projectDir, "packages/config");
6706
6362
  const configDep = {};
6707
6363
  if (await fs.pathExists(configPackageDir)) configDep[`@${projectName}/config`] = workspaceVersion;
@@ -6745,7 +6401,7 @@ async function setupWorkspaceDependencies(projectDir, options) {
6745
6401
  if (options.database !== "none" && await fs.pathExists(dbPackageDir)) serverDeps[`@${projectName}/db`] = workspaceVersion;
6746
6402
  await addPackageDependency({
6747
6403
  dependencies: commonDeps,
6748
- devDependencies: commonDevDeps,
6404
+ devDependencies: [...commonDevDeps, "tsdown"],
6749
6405
  customDependencies: serverDeps,
6750
6406
  customDevDependencies: configDep,
6751
6407
  projectDir: serverPackageDir