create-better-t-stack 3.39.2 → 3.40.1

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.
package/README.md CHANGED
@@ -43,7 +43,7 @@ generated commands.
43
43
  | Category | Options |
44
44
  | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
45
  | **TypeScript** | End-to-end type safety across all parts of your application |
46
- | **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidStart v2 (SSR)<br>• Astro<br>• React Native bare Expo<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None |
46
+ | **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• Solid (SSR)<br>• Astro<br>• React Native bare Expo<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None |
47
47
  | **Backend** | • Hono<br>• Express<br>• Elysia<br>• Fastify<br>• Self (fullstack inside the web app)<br>• Convex<br>• None |
48
48
  | **API Layer** | • tRPC (type-safe APIs)<br>• oRPC (OpenAPI-compatible type-safe APIs)<br>• None |
49
49
  | **Runtime** | • Bun<br>• Node.js<br>• Cloudflare Workers<br>• None |
@@ -78,6 +78,7 @@ Options:
78
78
  --package-manager <pm> Package manager (npm, pnpm, bun)
79
79
  --install Install dependencies
80
80
  --no-install Skip installing dependencies
81
+ --open <target> Open in an editor, IDE, or coding agent after creation
81
82
  --db-setup <setup> Database setup (turso, d1, neon, supabase, prisma-postgres, planetscale, mongodb-atlas, docker, none)
82
83
  --web-deploy <setup> Web deployment (cloudflare, docker, vercel, none)
83
84
  --server-deploy <setup> Server deployment (cloudflare, docker, vercel, none)
@@ -259,8 +260,8 @@ npx create-better-t-stack --frontend none --backend hono --api trpc --database n
259
260
  - **Cloudflare D1 setup**: Requires `sqlite` and either `--runtime workers --server-deploy cloudflare` or `--backend self --web-deploy cloudflare`. For `backend self`, D1 is supported on `next`, `tanstack-start`, `nuxt`, `svelte`, `solid`, and `astro`.
260
261
  - **Addons 'none'**: Skips all addons.
261
262
  - **Examples 'none'**: Skips all example implementations (todo, AI chat).
262
- - **Nuxt, Svelte, SolidStart, and Astro** frontends are only compatible with the oRPC API layer
263
- - **PWA support** requires TanStack Router, React Router, Next.js, or SolidStart
263
+ - **Nuxt, Svelte, Solid, and Astro** frontends are only compatible with the oRPC API layer
264
+ - **PWA support** requires TanStack Router, React Router, Next.js, or Solid
264
265
  - **Tauri desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, or Astro
265
266
  - **Electrobun desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, or Astro. Desktop packaging uses static web assets, so SSR-first frontends need a static/export build before desktop builds will work.
266
267
  - **AI example** is not compatible with Solid or Astro. With Convex backend, it also excludes Nuxt and Svelte.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-BYgmfow5.mjs";
2
+ import { i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as types_exports, y as getLatestCLIVersion } from "./src-DBE8djc0.mjs";
3
3
  import z from "zod";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/index.d.mts CHANGED
@@ -96,6 +96,39 @@ declare class DatabaseSetupError extends DatabaseSetupError_base<{
96
96
  });
97
97
  }
98
98
  //#endregion
99
+ //#region src/utils/project-launcher.d.ts
100
+ declare const ProjectLauncherSchema: z.ZodEnum<{
101
+ none: "none";
102
+ cursor: "cursor";
103
+ vscode: "vscode";
104
+ "vscode-insiders": "vscode-insiders";
105
+ zed: "zed";
106
+ windsurf: "windsurf";
107
+ vscodium: "vscodium";
108
+ webstorm: "webstorm";
109
+ "intellij-idea": "intellij-idea";
110
+ "sublime-text": "sublime-text";
111
+ neovim: "neovim";
112
+ "codex-app": "codex-app";
113
+ codex: "codex";
114
+ "claude-code": "claude-code";
115
+ opencode: "opencode";
116
+ pi: "pi";
117
+ "gemini-cli": "gemini-cli";
118
+ "github-copilot": "github-copilot";
119
+ "kiro-cli": "kiro-cli";
120
+ droid: "droid";
121
+ goose: "goose";
122
+ cline: "cline";
123
+ continue: "continue";
124
+ amp: "amp";
125
+ aider: "aider";
126
+ "qwen-code": "qwen-code";
127
+ crush: "crush";
128
+ "cursor-agent": "cursor-agent";
129
+ }>;
130
+ type ProjectLauncher = z.infer<typeof ProjectLauncherSchema>;
131
+ //#endregion
99
132
  //#region src/helpers/core/command-handlers.d.ts
100
133
  /**
101
134
  * Result type for project creation
@@ -175,6 +208,7 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
175
208
  git?: boolean | undefined;
176
209
  packageManager?: "bun" | "npm" | "pnpm" | undefined;
177
210
  install?: boolean | undefined;
211
+ open?: "none" | "cursor" | "vscode" | "vscode-insiders" | "zed" | "windsurf" | "vscodium" | "webstorm" | "intellij-idea" | "sublime-text" | "neovim" | "codex-app" | "codex" | "claude-code" | "opencode" | "pi" | "gemini-cli" | "github-copilot" | "kiro-cli" | "droid" | "goose" | "cline" | "continue" | "amp" | "aider" | "qwen-code" | "crush" | "cursor-agent" | undefined;
178
212
  dbSetup?: "none" | "turso" | "neon" | "prisma-postgres" | "planetscale" | "mongodb-atlas" | "supabase" | "d1" | "docker" | undefined;
179
213
  backend?: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self" | undefined;
180
214
  runtime?: "none" | "bun" | "node" | "workers" | undefined;
@@ -186,7 +220,7 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
186
220
  disableAnalytics?: boolean | undefined;
187
221
  manualDb?: boolean | undefined;
188
222
  dbSetupOptions?: {
189
- mode?: "manual" | "auto" | undefined;
223
+ mode?: "manual" | "auto" | "alchemy" | undefined;
190
224
  neon?: {
191
225
  method?: "neon" | "neon-new" | "neondb" | "neonctl" | undefined;
192
226
  projectName?: string | undefined;
@@ -231,11 +265,11 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
231
265
  mcp?: {
232
266
  scope?: "project" | "global" | undefined;
233
267
  servers?: ("nx" | "better-auth" | "clerk" | "polar" | "neon" | "planetscale" | "supabase" | "convex" | "better-t-stack" | "context7" | "cloudflare-docs" | "shadcn" | "next-devtools" | "nuxt-docs" | "nuxt-ui-docs" | "svelte-docs" | "astro-docs" | "expo")[] | undefined;
234
- agents?: ("antigravity" | "cline" | "cline-cli" | "cursor" | "claude-code" | "codex" | "opencode" | "gemini-cli" | "github-copilot-cli" | "grok-build" | "mcporter" | "vscode" | "windsurf" | "zed" | "claude-desktop" | "goose")[] | undefined;
268
+ agents?: ("cursor" | "vscode" | "zed" | "windsurf" | "codex" | "claude-code" | "opencode" | "gemini-cli" | "goose" | "cline" | "antigravity" | "cline-cli" | "github-copilot-cli" | "grok-build" | "mcporter" | "claude-desktop")[] | undefined;
235
269
  } | undefined;
236
270
  skills?: {
237
271
  scope?: "project" | "global" | undefined;
238
- agents?: ("antigravity" | "cline" | "cursor" | "claude-code" | "codex" | "opencode" | "gemini-cli" | "windsurf" | "zed" | "goose" | "universal" | "adal" | "aider-desk" | "amp" | "antigravity-cli" | "astrbot" | "augment" | "autohand-code" | "bob" | "codearts-agent" | "codebuddy" | "codemaker" | "codestudio" | "command-code" | "continue" | "cortex" | "crush" | "deepagents" | "devin" | "dexto" | "droid" | "eve" | "firebender" | "forgecode" | "github-copilot" | "grok" | "hermes-agent" | "iflow-cli" | "inference-sh" | "jazz" | "junie" | "kilo" | "kimchi" | "kimi-code-cli" | "kiro-cli" | "kode" | "lingma" | "loaf" | "mcpjam" | "mistral-vibe" | "moxby" | "mux" | "neovate" | "ona" | "clawdbot" | "openclaw" | "openhands" | "pi" | "pochi" | "promptscript" | "qoder" | "qoder-cn" | "qwen-code" | "reasonix" | "replit" | "roo" | "rovodev" | "tabnine-cli" | "terramind" | "tinycloud" | "trae" | "trae-cn" | "warp" | "zcode" | "zencoder" | "zenflow")[] | undefined;
272
+ agents?: ("cursor" | "zed" | "windsurf" | "codex" | "claude-code" | "opencode" | "pi" | "gemini-cli" | "github-copilot" | "kiro-cli" | "droid" | "goose" | "cline" | "continue" | "amp" | "qwen-code" | "crush" | "antigravity" | "universal" | "adal" | "aider-desk" | "antigravity-cli" | "astrbot" | "augment" | "autohand-code" | "bob" | "codearts-agent" | "codebuddy" | "codemaker" | "codestudio" | "command-code" | "cortex" | "deepagents" | "devin" | "dexto" | "eve" | "firebender" | "forgecode" | "grok" | "hermes-agent" | "iflow-cli" | "inference-sh" | "jazz" | "junie" | "kilo" | "kimchi" | "kimi-code-cli" | "kode" | "lingma" | "loaf" | "mcpjam" | "mistral-vibe" | "moxby" | "mux" | "neovate" | "ona" | "clawdbot" | "openclaw" | "openhands" | "pochi" | "promptscript" | "qoder" | "qoder-cn" | "reasonix" | "replit" | "roo" | "rovodev" | "tabnine-cli" | "terramind" | "tinycloud" | "trae" | "trae-cn" | "warp" | "zcode" | "zencoder" | "zenflow")[] | undefined;
239
273
  selections?: {
240
274
  source: "vercel-labs/agent-skills" | "vercel/ai" | "vercel/turborepo" | "yusukebe/hono-skill" | "vercel-labs/next-skills" | "nuxt/ui" | "heroui-inc/heroui" | "shadcn/ui" | "better-auth/skills" | "clerk/skills" | "neondatabase/agent-skills" | "supabase/agent-skills" | "planetscale/database-skills" | "expo/skills" | "prisma/skills" | "elysiajs/skills" | "waynesutton/convexskills" | "msmps/opentui-skill" | "haydenbleasel/ultracite" | "https://www.evlog.dev";
241
275
  skills: string[];
@@ -243,13 +277,13 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
243
277
  } | undefined;
244
278
  ultracite?: {
245
279
  linter?: "biome" | "oxlint" | undefined;
246
- editors?: ("void" | "antigravity" | "cursor" | "vscode" | "windsurf" | "zed" | "bob" | "codebuddy" | "trae" | "kiro")[] | undefined;
247
- agents?: ("vercel" | "cline" | "codex" | "opencode" | "goose" | "universal" | "adal" | "amp" | "bob" | "continue" | "crush" | "deepagents" | "devin" | "droid" | "firebender" | "junie" | "mcpjam" | "mistral-vibe" | "mux" | "ona" | "openclaw" | "pi" | "qoder" | "replit" | "warp" | "zencoder" | "claude" | "jules" | "lovable" | "snowflake-cortex" | "kimi-cli" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "augmentcode" | "kilo-code" | "roo-code" | "qwen" | "amazon-q-cli" | "cursor-cli")[] | undefined;
280
+ editors?: ("void" | "cursor" | "vscode" | "zed" | "windsurf" | "antigravity" | "bob" | "codebuddy" | "trae" | "kiro")[] | undefined;
281
+ agents?: ("codex" | "opencode" | "pi" | "droid" | "goose" | "cline" | "continue" | "amp" | "aider" | "crush" | "vercel" | "universal" | "adal" | "bob" | "deepagents" | "devin" | "firebender" | "junie" | "mcpjam" | "mistral-vibe" | "mux" | "ona" | "openclaw" | "qoder" | "replit" | "warp" | "zencoder" | "claude" | "jules" | "lovable" | "snowflake-cortex" | "kimi-cli" | "copilot" | "firebase-studio" | "open-hands" | "gemini" | "augmentcode" | "kilo-code" | "roo-code" | "qwen" | "amazon-q-cli" | "cursor-cli")[] | undefined;
248
282
  hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
249
283
  } | undefined;
250
284
  } | undefined;
251
285
  dbSetupOptions?: {
252
- mode?: "manual" | "auto" | undefined;
286
+ mode?: "manual" | "auto" | "alchemy" | undefined;
253
287
  neon?: {
254
288
  method?: "neon" | "neon-new" | "neondb" | "neonctl" | undefined;
255
289
  projectName?: string | undefined;
@@ -342,11 +376,11 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
342
376
  mcp?: {
343
377
  scope?: "project" | "global" | undefined;
344
378
  servers?: ("nx" | "better-auth" | "clerk" | "polar" | "neon" | "planetscale" | "supabase" | "convex" | "better-t-stack" | "context7" | "cloudflare-docs" | "shadcn" | "next-devtools" | "nuxt-docs" | "nuxt-ui-docs" | "svelte-docs" | "astro-docs" | "expo")[] | undefined;
345
- agents?: ("antigravity" | "cline" | "cline-cli" | "cursor" | "claude-code" | "codex" | "opencode" | "gemini-cli" | "github-copilot-cli" | "grok-build" | "mcporter" | "vscode" | "windsurf" | "zed" | "claude-desktop" | "goose")[] | undefined;
379
+ agents?: ("cursor" | "vscode" | "zed" | "windsurf" | "codex" | "claude-code" | "opencode" | "gemini-cli" | "goose" | "cline" | "antigravity" | "cline-cli" | "github-copilot-cli" | "grok-build" | "mcporter" | "claude-desktop")[] | undefined;
346
380
  } | undefined;
347
381
  skills?: {
348
382
  scope?: "project" | "global" | undefined;
349
- agents?: ("antigravity" | "cline" | "cursor" | "claude-code" | "codex" | "opencode" | "gemini-cli" | "windsurf" | "zed" | "goose" | "universal" | "adal" | "aider-desk" | "amp" | "antigravity-cli" | "astrbot" | "augment" | "autohand-code" | "bob" | "codearts-agent" | "codebuddy" | "codemaker" | "codestudio" | "command-code" | "continue" | "cortex" | "crush" | "deepagents" | "devin" | "dexto" | "droid" | "eve" | "firebender" | "forgecode" | "github-copilot" | "grok" | "hermes-agent" | "iflow-cli" | "inference-sh" | "jazz" | "junie" | "kilo" | "kimchi" | "kimi-code-cli" | "kiro-cli" | "kode" | "lingma" | "loaf" | "mcpjam" | "mistral-vibe" | "moxby" | "mux" | "neovate" | "ona" | "clawdbot" | "openclaw" | "openhands" | "pi" | "pochi" | "promptscript" | "qoder" | "qoder-cn" | "qwen-code" | "reasonix" | "replit" | "roo" | "rovodev" | "tabnine-cli" | "terramind" | "tinycloud" | "trae" | "trae-cn" | "warp" | "zcode" | "zencoder" | "zenflow")[] | undefined;
383
+ agents?: ("cursor" | "zed" | "windsurf" | "codex" | "claude-code" | "opencode" | "pi" | "gemini-cli" | "github-copilot" | "kiro-cli" | "droid" | "goose" | "cline" | "continue" | "amp" | "qwen-code" | "crush" | "antigravity" | "universal" | "adal" | "aider-desk" | "antigravity-cli" | "astrbot" | "augment" | "autohand-code" | "bob" | "codearts-agent" | "codebuddy" | "codemaker" | "codestudio" | "command-code" | "cortex" | "deepagents" | "devin" | "dexto" | "eve" | "firebender" | "forgecode" | "grok" | "hermes-agent" | "iflow-cli" | "inference-sh" | "jazz" | "junie" | "kilo" | "kimchi" | "kimi-code-cli" | "kode" | "lingma" | "loaf" | "mcpjam" | "mistral-vibe" | "moxby" | "mux" | "neovate" | "ona" | "clawdbot" | "openclaw" | "openhands" | "pochi" | "promptscript" | "qoder" | "qoder-cn" | "reasonix" | "replit" | "roo" | "rovodev" | "tabnine-cli" | "terramind" | "tinycloud" | "trae" | "trae-cn" | "warp" | "zcode" | "zencoder" | "zenflow")[] | undefined;
350
384
  selections?: {
351
385
  source: "vercel-labs/agent-skills" | "vercel/ai" | "vercel/turborepo" | "yusukebe/hono-skill" | "vercel-labs/next-skills" | "nuxt/ui" | "heroui-inc/heroui" | "shadcn/ui" | "better-auth/skills" | "clerk/skills" | "neondatabase/agent-skills" | "supabase/agent-skills" | "planetscale/database-skills" | "expo/skills" | "prisma/skills" | "elysiajs/skills" | "waynesutton/convexskills" | "msmps/opentui-skill" | "haydenbleasel/ultracite" | "https://www.evlog.dev";
352
386
  skills: string[];
@@ -354,8 +388,8 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
354
388
  } | undefined;
355
389
  ultracite?: {
356
390
  linter?: "biome" | "oxlint" | undefined;
357
- editors?: ("void" | "antigravity" | "cursor" | "vscode" | "windsurf" | "zed" | "bob" | "codebuddy" | "trae" | "kiro")[] | undefined;
358
- agents?: ("vercel" | "cline" | "codex" | "opencode" | "goose" | "universal" | "adal" | "amp" | "bob" | "continue" | "crush" | "deepagents" | "devin" | "droid" | "firebender" | "junie" | "mcpjam" | "mistral-vibe" | "mux" | "ona" | "openclaw" | "pi" | "qoder" | "replit" | "warp" | "zencoder" | "claude" | "jules" | "lovable" | "snowflake-cortex" | "kimi-cli" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "augmentcode" | "kilo-code" | "roo-code" | "qwen" | "amazon-q-cli" | "cursor-cli")[] | undefined;
391
+ editors?: ("void" | "cursor" | "vscode" | "zed" | "windsurf" | "antigravity" | "bob" | "codebuddy" | "trae" | "kiro")[] | undefined;
392
+ agents?: ("codex" | "opencode" | "pi" | "droid" | "goose" | "cline" | "continue" | "amp" | "aider" | "crush" | "vercel" | "universal" | "adal" | "bob" | "deepagents" | "devin" | "firebender" | "junie" | "mcpjam" | "mistral-vibe" | "mux" | "ona" | "openclaw" | "qoder" | "replit" | "warp" | "zencoder" | "claude" | "jules" | "lovable" | "snowflake-cortex" | "kimi-cli" | "copilot" | "firebase-studio" | "open-hands" | "gemini" | "augmentcode" | "kilo-code" | "roo-code" | "qwen" | "amazon-q-cli" | "cursor-cli")[] | undefined;
359
393
  hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
360
394
  } | undefined;
361
395
  } | undefined;
@@ -478,4 +512,4 @@ type Runtime = import__better_t_stack_types.Runtime;
478
512
  type ServerDeploy = import__better_t_stack_types.ServerDeploy;
479
513
  type Template = import__better_t_stack_types.Template;
480
514
  type WebDeploy = import__better_t_stack_types.WebDeploy;
481
- export { type API, AddOptions, type AddResult, type AddonOptions, type Addons, type Auth, type Backend, type BetterTStackConfig, CLIError, CompatibilityError, CreateError, type CreateInput, type Database, type DatabaseSetup, DatabaseSetupError, type DbSetupOptions, type DirectoryConflict, DirectoryConflictError, EMBEDDED_TEMPLATES, type Examples, type Frontend, GeneratorError, type GeneratorOptions, type InitResult, type ORM, type PackageManager, type Payments, type ProjectConfig, ProjectCreationError, Result, type Runtime, SchemaName, SchemaNameSchema, type ServerDeploy, TEMPLATE_COUNT, type Template, UserCancelledError, ValidationError, type VirtualDirectory, type VirtualFile, VirtualFileSystem, type VirtualFileTree, type VirtualNode, type WebDeploy, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
515
+ export { type API, AddOptions, type AddResult, type AddonOptions, type Addons, type Auth, type Backend, type BetterTStackConfig, CLIError, CompatibilityError, CreateError, type CreateInput, type Database, type DatabaseSetup, DatabaseSetupError, type DbSetupOptions, type DirectoryConflict, DirectoryConflictError, EMBEDDED_TEMPLATES, type Examples, type Frontend, GeneratorError, type GeneratorOptions, type InitResult, type ORM, type PackageManager, type Payments, type ProjectConfig, ProjectCreationError, type ProjectLauncher, ProjectLauncherSchema, Result, type Runtime, SchemaName, SchemaNameSchema, type ServerDeploy, TEMPLATE_COUNT, type Template, UserCancelledError, ValidationError, type VirtualDirectory, type VirtualFile, VirtualFileSystem, type VirtualFileTree, type VirtualNode, type WebDeploy, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-BYgmfow5.mjs";
3
- export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
2
+ import { C as DirectoryConflictError, E as ValidationError, S as DatabaseSetupError, T as UserCancelledError, _ as ProjectLauncherSchema, a as TEMPLATE_COUNT, b as CLIError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as ProjectCreationError, x as CompatibilityError } from "./src-DBE8djc0.mjs";
3
+ export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, ProjectLauncherSchema, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
@@ -32,7 +32,7 @@ const VALUE_LABELS = {
32
32
  next: "Next.js",
33
33
  nuxt: "Nuxt",
34
34
  svelte: "SvelteKit",
35
- solid: "SolidStart",
35
+ solid: "Solid",
36
36
  astro: "Astro",
37
37
  "native-bare": "Expo (bare)",
38
38
  "native-uniwind": "Expo + Uniwind",
@@ -88,6 +88,9 @@ const VALUE_LABELS = {
88
88
  docker: "Docker",
89
89
  cloudflare: "Cloudflare",
90
90
  vercel: "Vercel",
91
+ alchemy: "Alchemy",
92
+ auto: "Automatic",
93
+ manual: "Manual",
91
94
  npm: "npm",
92
95
  pnpm: "pnpm"
93
96
  };
@@ -132,7 +135,8 @@ function getConfigSections(config) {
132
135
  section("Data", [
133
136
  ["Database", config.database],
134
137
  ["ORM", config.orm],
135
- ["Setup", config.dbSetup]
138
+ ["Setup", config.dbSetup],
139
+ ["Provisioning", config.dbSetupOptions?.mode]
136
140
  ]),
137
141
  section("Product", [
138
142
  ["Auth", config.auth],
@@ -964,11 +968,11 @@ function validateSelfBackendCompatibility(providedFlags, options, config) {
964
968
  const frontends = config.frontend || options.frontend || [];
965
969
  if (backend === "self") {
966
970
  const { web, native } = splitFrontends(frontends);
967
- if (!(web.length === 1 && FULLSTACK_FRONTENDS$1.includes(web[0]))) return validationErr$1("Backend 'self' (fullstack) currently only supports Next.js, TanStack Start, Nuxt, SvelteKit, SolidStart, and Astro frontends. Please use --frontend next, --frontend tanstack-start, --frontend nuxt, --frontend svelte, --frontend solid, or --frontend astro.");
971
+ if (!(web.length === 1 && FULLSTACK_FRONTENDS$1.includes(web[0]))) return validationErr$1("Backend 'self' (fullstack) currently only supports Next.js, TanStack Start, Nuxt, SvelteKit, Solid, and Astro frontends. Please use --frontend next, --frontend tanstack-start, --frontend nuxt, --frontend svelte, --frontend solid, or --frontend astro.");
968
972
  if (native.length > 1) return validationErr$1("Cannot select multiple native frameworks. Choose only one of: native-bare, native-uniwind, native-unistyles");
969
973
  }
970
974
  const hasFullstackFrontend = frontends.some((f) => FULLSTACK_FRONTENDS$1.includes(f));
971
- if (providedFlags.has("backend") && !hasFullstackFrontend && backend === "self") return validationErr$1("Backend 'self' (fullstack) currently only supports Next.js, TanStack Start, Nuxt, SvelteKit, SolidStart, and Astro frontends. Please use --frontend next, --frontend tanstack-start, --frontend nuxt, --frontend svelte, --frontend solid, --frontend astro, or choose a different backend.");
975
+ if (providedFlags.has("backend") && !hasFullstackFrontend && backend === "self") return validationErr$1("Backend 'self' (fullstack) currently only supports Next.js, TanStack Start, Nuxt, SvelteKit, Solid, and Astro frontends. Please use --frontend next, --frontend tanstack-start, --frontend nuxt, --frontend svelte, --frontend solid, --frontend astro, or choose a different backend.");
972
976
  return Result.ok(void 0);
973
977
  }
974
978
  function validateWorkersCompatibility(providedFlags, options, config) {
@@ -1074,7 +1078,7 @@ function supportsPrismaWebDeploy(frontend) {
1074
1078
  }
1075
1079
  function validatePrismaWebDeploy(webDeploy, frontend) {
1076
1080
  if (webDeploy !== "prisma" || !frontend) return Result.ok(void 0);
1077
- if (!supportsPrismaWebDeploy(frontend)) return validationErr$1("'--web-deploy prisma' requires a supported server frontend. Choose Next.js, Nuxt, Astro, React Router, TanStack Start, SvelteKit, or SolidStart. TanStack Router is a static SPA, while Prisma Compute requires an executable server artifact.");
1081
+ if (!supportsPrismaWebDeploy(frontend)) return validationErr$1("'--web-deploy prisma' requires a supported server frontend. Choose Next.js, Nuxt, Astro, React Router, TanStack Start, SvelteKit, or Solid. TanStack Router is a static SPA, while Prisma Compute requires an executable server artifact.");
1078
1082
  return Result.ok(void 0);
1079
1083
  }
1080
1084
  function validateCloudflareWebDeployKnownIssues(config) {
@@ -1763,7 +1767,7 @@ function getNodeToolingRequirements(config) {
1763
1767
  addNodeRequirement(requirements, "^22.19.0 || ^24.11.0 || >=26.0.0", "Nuxt 4");
1764
1768
  break;
1765
1769
  case "solid":
1766
- addNodeRequirement(requirements, ">=24.0.0", "SolidStart 2");
1770
+ addNodeRequirement(requirements, ">=24.0.0", "Solid");
1767
1771
  break;
1768
1772
  case "react-router":
1769
1773
  addNodeRequirement(requirements, ">=22.22.0", "React Router 8");
@@ -4888,6 +4892,54 @@ async function addHandlerInternal(input) {
4888
4892
  });
4889
4893
  }
4890
4894
  //#endregion
4895
+ //#region src/helpers/core/db-setup-options.ts
4896
+ function withDbSetupMode(dbSetupOptions, mode) {
4897
+ const resolved = { ...dbSetupOptions };
4898
+ if (mode === void 0) delete resolved.mode;
4899
+ else resolved.mode = mode;
4900
+ return Object.keys(resolved).length === 0 ? void 0 : resolved;
4901
+ }
4902
+ const REMOTE_PROVISIONING_DB_SETUPS = [
4903
+ "turso",
4904
+ "neon",
4905
+ "prisma-postgres",
4906
+ "supabase",
4907
+ "mongodb-atlas"
4908
+ ];
4909
+ function requiresProvisioningGuardrails(dbSetup) {
4910
+ return REMOTE_PROVISIONING_DB_SETUPS.includes(dbSetup);
4911
+ }
4912
+ function resolveDbSetupMode(dbSetup, cliOptions = {}) {
4913
+ if (dbSetup === "none") return;
4914
+ const explicitMode = cliOptions.dbSetupOptions?.mode;
4915
+ if (explicitMode) return explicitMode;
4916
+ if (cliOptions.manualDb === true) return "manual";
4917
+ if (isSilent() && requiresProvisioningGuardrails(dbSetup)) return "manual";
4918
+ }
4919
+ function mergeResolvedDbSetupOptions(dbSetup, dbSetupOptions, cliOptions = {}) {
4920
+ if (dbSetup === "none") return;
4921
+ const resolvedMode = resolveDbSetupMode(dbSetup, {
4922
+ ...cliOptions,
4923
+ dbSetupOptions: dbSetupOptions ?? cliOptions.dbSetupOptions
4924
+ });
4925
+ if (!dbSetupOptions && !resolvedMode) return;
4926
+ return {
4927
+ ...dbSetupOptions,
4928
+ mode: resolvedMode
4929
+ };
4930
+ }
4931
+ function resolveProjectDbSetupOptions(config, cliOptions = {}) {
4932
+ const dbSetupOptions = config.dbSetupOptions ?? cliOptions.dbSetupOptions;
4933
+ if (!(dbSetupOptions?.mode ?? (cliOptions.manualDb === true ? "manual" : void 0)) && (0, types_exports.supportsAlchemyManagedDatabase)(config)) return {
4934
+ ...dbSetupOptions,
4935
+ mode: "alchemy"
4936
+ };
4937
+ return mergeResolvedDbSetupOptions(config.dbSetup, dbSetupOptions, {
4938
+ ...cliOptions,
4939
+ dbSetupOptions
4940
+ });
4941
+ }
4942
+ //#endregion
4891
4943
  //#region src/prompts/api.ts
4892
4944
  async function getApiChoice(Api, frontend, backend, previousValue) {
4893
4945
  if (backend === "convex" || backend === "none") return "none";
@@ -5164,6 +5216,47 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime, p
5164
5216
  if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
5165
5217
  return response;
5166
5218
  }
5219
+ const providerLabels = {
5220
+ neon: "Neon",
5221
+ planetscale: "PlanetScale",
5222
+ "prisma-postgres": "Prisma Postgres"
5223
+ };
5224
+ async function getDbProvisioningChoice(mode, dbSetup, backend, webDeploy, serverDeploy, previousValue) {
5225
+ if (!dbSetup || !backend || !webDeploy || !serverDeploy) return mode;
5226
+ if (!(0, types_exports.supportsAlchemyManagedDatabase)({
5227
+ backend,
5228
+ dbSetup,
5229
+ webDeploy,
5230
+ serverDeploy
5231
+ })) return mode === "alchemy" ? void 0 : mode;
5232
+ if (mode !== void 0) return mode;
5233
+ const provider = providerLabels[dbSetup];
5234
+ if (!provider) return void 0;
5235
+ const options = [
5236
+ {
5237
+ value: "alchemy",
5238
+ label: "Alchemy",
5239
+ hint: `Provision ${provider} during deploy and inject its credentials`
5240
+ },
5241
+ ...dbSetup === "neon" || dbSetup === "prisma-postgres" ? [{
5242
+ value: "auto",
5243
+ label: "Automatic",
5244
+ hint: `Set up ${provider} now and write its connection credentials`
5245
+ }] : [],
5246
+ {
5247
+ value: "manual",
5248
+ label: "Manual",
5249
+ hint: `Use an existing ${provider} database and configure credentials yourself`
5250
+ }
5251
+ ];
5252
+ const response = await navigableSelect({
5253
+ message: `How should ${provider} be provisioned?`,
5254
+ options,
5255
+ initialValue: preferValidInitial(options, previousValue, "alchemy")
5256
+ });
5257
+ if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
5258
+ return response;
5259
+ }
5167
5260
  //#endregion
5168
5261
  //#region src/prompts/examples.ts
5169
5262
  async function getExamplesChoice(examples, database, frontends, backend, api, previousValue) {
@@ -5431,6 +5524,20 @@ function validateDatabaseSetup(config, providedFlags) {
5431
5524
  }
5432
5525
  return Result.ok(void 0);
5433
5526
  }
5527
+ function validateDatabaseProvisioningMode(config) {
5528
+ if (config.dbSetup === "planetscale" && config.dbSetupOptions?.mode === "auto") return validationErr("PlanetScale does not support automatic database setup. Use dbSetupOptions.mode 'alchemy' or 'manual'.");
5529
+ if (config.dbSetupOptions?.mode !== "alchemy") return Result.ok(void 0);
5530
+ const { backend, dbSetup, webDeploy, serverDeploy } = config;
5531
+ if (!backend || !dbSetup || !webDeploy || !serverDeploy) return Result.ok(void 0);
5532
+ if (!(0, types_exports.supportsAlchemyManagedDatabase)({
5533
+ backend,
5534
+ dbSetup,
5535
+ webDeploy,
5536
+ serverDeploy,
5537
+ dbSetupOptions: config.dbSetupOptions
5538
+ })) return validationErr("Alchemy database provisioning requires Neon, PlanetScale, or Prisma Postgres and an Alchemy deployment target for the app that consumes the database.");
5539
+ return Result.ok(void 0);
5540
+ }
5434
5541
  function validateConvexConstraints(config, providedFlags) {
5435
5542
  const { backend } = config;
5436
5543
  if (backend !== "convex") return Result.ok(void 0);
@@ -5515,6 +5622,7 @@ function validateFullConfig(config, providedFlags, options) {
5515
5622
  return Result.gen(function* () {
5516
5623
  yield* validateDatabaseOrmAuth(config, providedFlags);
5517
5624
  yield* validateDatabaseSetup(config, providedFlags);
5625
+ yield* validateDatabaseProvisioningMode(config);
5518
5626
  yield* validateConvexConstraints(config, providedFlags);
5519
5627
  yield* validateBackendNoneConstraints(config, providedFlags);
5520
5628
  yield* validateSelfBackendConstraints(config, providedFlags);
@@ -5827,6 +5935,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath, option
5827
5935
  examples: ({ results, previousAnswer }) => getExamplesChoice(flags.examples, results.database, results.frontend, results.backend, results.api, previousAnswer),
5828
5936
  webDeploy: ({ results, previousAnswer }) => getDeploymentChoice(flags.webDeploy, results.runtime, results.backend, results.frontend, results.dbSetup, results.database, results.orm, results.addons, previousAnswer),
5829
5937
  serverDeploy: ({ results, previousAnswer }) => getServerDeploymentChoice(flags.serverDeploy, results.runtime, results.backend, results.webDeploy, previousAnswer),
5938
+ dbSetupMode: ({ results, previousAnswer }) => getDbProvisioningChoice(flags.dbSetupOptions?.mode ?? (options.manualDb === true ? "manual" : void 0), results.dbSetup, results.backend, results.webDeploy, results.serverDeploy, previousAnswer),
5830
5939
  git: ({ previousAnswer }) => getGitChoice(flags.git, previousAnswer),
5831
5940
  packageManager: ({ previousAnswer }) => getPackageManagerChoice(flags.packageManager, previousAnswer),
5832
5941
  install: ({ previousAnswer }) => getinstallChoice(flags.install, previousAnswer)
@@ -5864,6 +5973,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath, option
5864
5973
  prompts: [
5865
5974
  "webDeploy",
5866
5975
  "serverDeploy",
5976
+ "dbSetupMode",
5867
5977
  "git",
5868
5978
  "packageManager",
5869
5979
  "install"
@@ -5879,7 +5989,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath, option
5879
5989
  projectDir,
5880
5990
  relativePath,
5881
5991
  addonOptions: flags.addonOptions,
5882
- dbSetupOptions: flags.dbSetupOptions,
5992
+ dbSetupOptions: withDbSetupMode(flags.dbSetupOptions, result.dbSetupMode),
5883
5993
  frontend: result.frontend,
5884
5994
  backend: result.backend,
5885
5995
  runtime: result.runtime,
@@ -6203,6 +6313,321 @@ async function findAvailableIncrementedPath(currentPathInput) {
6203
6313
  }
6204
6314
  }
6205
6315
  //#endregion
6316
+ //#region src/utils/command-exists.ts
6317
+ async function commandExists(command) {
6318
+ const result = await Result.tryPromise({
6319
+ try: async () => {
6320
+ if (process.platform === "win32") return (await $({ reject: false })`where ${command}`).exitCode === 0;
6321
+ return (await $({ reject: false })`which ${command}`).exitCode === 0;
6322
+ },
6323
+ catch: () => false
6324
+ });
6325
+ return result.isOk() ? result.value : false;
6326
+ }
6327
+ //#endregion
6328
+ //#region src/utils/project-launcher.ts
6329
+ const ProjectLauncherSchema = z.enum([
6330
+ "cursor",
6331
+ "vscode",
6332
+ "vscode-insiders",
6333
+ "zed",
6334
+ "windsurf",
6335
+ "vscodium",
6336
+ "webstorm",
6337
+ "intellij-idea",
6338
+ "sublime-text",
6339
+ "neovim",
6340
+ "codex-app",
6341
+ "codex",
6342
+ "claude-code",
6343
+ "opencode",
6344
+ "pi",
6345
+ "gemini-cli",
6346
+ "github-copilot",
6347
+ "kiro-cli",
6348
+ "droid",
6349
+ "goose",
6350
+ "cline",
6351
+ "continue",
6352
+ "amp",
6353
+ "aider",
6354
+ "qwen-code",
6355
+ "crush",
6356
+ "cursor-agent",
6357
+ "none"
6358
+ ]).describe("Editor, IDE, or coding agent to open after creating the project");
6359
+ const PROJECT_LAUNCHERS = [
6360
+ {
6361
+ id: "cursor",
6362
+ label: "Cursor",
6363
+ kind: "editor",
6364
+ commands: ["cursor"],
6365
+ args: (projectDir) => [projectDir]
6366
+ },
6367
+ {
6368
+ id: "vscode",
6369
+ label: "Visual Studio Code",
6370
+ kind: "editor",
6371
+ commands: ["code"],
6372
+ args: (projectDir) => [projectDir]
6373
+ },
6374
+ {
6375
+ id: "vscode-insiders",
6376
+ label: "Visual Studio Code Insiders",
6377
+ kind: "editor",
6378
+ commands: ["code-insiders"],
6379
+ args: (projectDir) => [projectDir]
6380
+ },
6381
+ {
6382
+ id: "zed",
6383
+ label: "Zed",
6384
+ kind: "editor",
6385
+ commands: ["zed", "zeditor"],
6386
+ args: (projectDir) => [projectDir]
6387
+ },
6388
+ {
6389
+ id: "windsurf",
6390
+ label: "Windsurf",
6391
+ kind: "editor",
6392
+ commands: ["windsurf"],
6393
+ args: (projectDir) => [projectDir]
6394
+ },
6395
+ {
6396
+ id: "vscodium",
6397
+ label: "VSCodium",
6398
+ kind: "editor",
6399
+ commands: ["codium"],
6400
+ args: (projectDir) => [projectDir]
6401
+ },
6402
+ {
6403
+ id: "webstorm",
6404
+ label: "JetBrains WebStorm",
6405
+ kind: "editor",
6406
+ commands: [
6407
+ "webstorm",
6408
+ "webstorm64.exe",
6409
+ "webstorm.bat",
6410
+ "webstorm.sh"
6411
+ ],
6412
+ args: (projectDir) => [projectDir]
6413
+ },
6414
+ {
6415
+ id: "intellij-idea",
6416
+ label: "JetBrains IntelliJ IDEA",
6417
+ kind: "editor",
6418
+ commands: [
6419
+ "idea",
6420
+ "intellij-idea",
6421
+ "idea64.exe",
6422
+ "idea.bat",
6423
+ "idea.sh"
6424
+ ],
6425
+ args: (projectDir) => [projectDir]
6426
+ },
6427
+ {
6428
+ id: "sublime-text",
6429
+ label: "Sublime Text",
6430
+ kind: "editor",
6431
+ commands: ["subl"],
6432
+ args: (projectDir) => [projectDir]
6433
+ },
6434
+ {
6435
+ id: "neovim",
6436
+ label: "Neovim",
6437
+ kind: "editor",
6438
+ commands: ["nvim"],
6439
+ args: () => ["."],
6440
+ cwd: (projectDir) => projectDir
6441
+ },
6442
+ {
6443
+ id: "codex-app",
6444
+ label: "Codex app",
6445
+ kind: "agent",
6446
+ commands: ["codex"],
6447
+ args: (projectDir) => ["app", projectDir],
6448
+ platforms: ["darwin"]
6449
+ },
6450
+ {
6451
+ id: "codex",
6452
+ label: "Codex CLI",
6453
+ kind: "agent",
6454
+ commands: ["codex"],
6455
+ cwd: (projectDir) => projectDir
6456
+ },
6457
+ {
6458
+ id: "claude-code",
6459
+ label: "Claude Code",
6460
+ kind: "agent",
6461
+ commands: ["claude"],
6462
+ cwd: (projectDir) => projectDir
6463
+ },
6464
+ {
6465
+ id: "opencode",
6466
+ label: "OpenCode",
6467
+ kind: "agent",
6468
+ commands: ["opencode"],
6469
+ cwd: (projectDir) => projectDir
6470
+ },
6471
+ {
6472
+ id: "pi",
6473
+ label: "Pi",
6474
+ kind: "agent",
6475
+ commands: ["pi"],
6476
+ cwd: (projectDir) => projectDir
6477
+ },
6478
+ {
6479
+ id: "gemini-cli",
6480
+ label: "Gemini CLI",
6481
+ kind: "agent",
6482
+ commands: ["gemini"],
6483
+ cwd: (projectDir) => projectDir
6484
+ },
6485
+ {
6486
+ id: "github-copilot",
6487
+ label: "GitHub Copilot CLI",
6488
+ kind: "agent",
6489
+ commands: ["copilot"],
6490
+ cwd: (projectDir) => projectDir
6491
+ },
6492
+ {
6493
+ id: "kiro-cli",
6494
+ label: "Kiro CLI",
6495
+ kind: "agent",
6496
+ commands: ["kiro-cli"],
6497
+ cwd: (projectDir) => projectDir
6498
+ },
6499
+ {
6500
+ id: "droid",
6501
+ label: "Factory Droid",
6502
+ kind: "agent",
6503
+ commands: ["droid"],
6504
+ cwd: (projectDir) => projectDir
6505
+ },
6506
+ {
6507
+ id: "goose",
6508
+ label: "goose",
6509
+ kind: "agent",
6510
+ commands: ["goose"],
6511
+ args: () => ["session"],
6512
+ cwd: (projectDir) => projectDir
6513
+ },
6514
+ {
6515
+ id: "cline",
6516
+ label: "Cline CLI",
6517
+ kind: "agent",
6518
+ commands: ["cline"],
6519
+ cwd: (projectDir) => projectDir,
6520
+ platforms: ["darwin", "linux"]
6521
+ },
6522
+ {
6523
+ id: "continue",
6524
+ label: "Continue CLI",
6525
+ kind: "agent",
6526
+ commands: ["cn"],
6527
+ cwd: (projectDir) => projectDir
6528
+ },
6529
+ {
6530
+ id: "amp",
6531
+ label: "Amp",
6532
+ kind: "agent",
6533
+ commands: ["amp"],
6534
+ cwd: (projectDir) => projectDir
6535
+ },
6536
+ {
6537
+ id: "aider",
6538
+ label: "Aider",
6539
+ kind: "agent",
6540
+ commands: ["aider"],
6541
+ cwd: (projectDir) => projectDir
6542
+ },
6543
+ {
6544
+ id: "qwen-code",
6545
+ label: "Qwen Code",
6546
+ kind: "agent",
6547
+ commands: ["qwen"],
6548
+ cwd: (projectDir) => projectDir
6549
+ },
6550
+ {
6551
+ id: "crush",
6552
+ label: "Crush",
6553
+ kind: "agent",
6554
+ commands: ["crush"],
6555
+ cwd: (projectDir) => projectDir
6556
+ },
6557
+ {
6558
+ id: "cursor-agent",
6559
+ label: "Cursor Agent",
6560
+ kind: "agent",
6561
+ commands: ["cursor-agent"],
6562
+ cwd: (projectDir) => projectDir
6563
+ }
6564
+ ];
6565
+ async function detectProjectLaunchers(projectDir, detectCommand = commandExists, platform = process.platform) {
6566
+ const supportedDefinitions = PROJECT_LAUNCHERS.filter(({ platforms }) => platforms === void 0 || platforms.includes(platform));
6567
+ const commands = [...new Set(supportedDefinitions.flatMap(({ commands }) => commands))];
6568
+ const detectedCommands = new Map(await Promise.all(commands.map(async (command) => [command, await detectCommand(command)])));
6569
+ return supportedDefinitions.flatMap((launcher) => {
6570
+ const command = launcher.commands.find((candidate) => detectedCommands.get(candidate));
6571
+ if (!command) return [];
6572
+ return [{
6573
+ id: launcher.id,
6574
+ label: launcher.label,
6575
+ kind: launcher.kind,
6576
+ command,
6577
+ args: launcher.args?.(projectDir) ?? [],
6578
+ cwd: launcher.cwd?.(projectDir)
6579
+ }];
6580
+ });
6581
+ }
6582
+ async function getProjectLauncherChoice(requestedLauncher, projectDir, options = {}) {
6583
+ if (requestedLauncher === "none") return Result.ok(void 0);
6584
+ if (!requestedLauncher && options.prompt === false) return Result.ok(void 0);
6585
+ const availableLaunchers = await detectProjectLaunchers(projectDir, options.detectCommand, options.platform);
6586
+ if (requestedLauncher) {
6587
+ const launcher = availableLaunchers.find(({ id }) => id === requestedLauncher);
6588
+ if (launcher) return Result.ok(launcher);
6589
+ const definition = PROJECT_LAUNCHERS.find(({ id }) => id === requestedLauncher);
6590
+ return Result.err(new CLIError({ message: `${definition?.label ?? requestedLauncher} is not installed or its command is not available in PATH.` }));
6591
+ }
6592
+ if (availableLaunchers.length === 0) return Result.ok(void 0);
6593
+ setIsFirstPrompt(true);
6594
+ try {
6595
+ const selected = await navigableSelect({
6596
+ message: "Open project with?",
6597
+ options: [...availableLaunchers.map(({ id, label, kind }) => ({
6598
+ value: id,
6599
+ label,
6600
+ hint: kind === "editor" ? "editor / IDE" : "coding agent"
6601
+ })), {
6602
+ value: "none",
6603
+ label: "Not now"
6604
+ }],
6605
+ initialValue: "none",
6606
+ maxItems: 12
6607
+ });
6608
+ if (isCancel$1(selected) || selected === "none") return Result.ok(void 0);
6609
+ return Result.ok(availableLaunchers.find(({ id }) => id === selected));
6610
+ } finally {
6611
+ setIsFirstPrompt(false);
6612
+ }
6613
+ }
6614
+ const runCommand = async (command, args, options) => {
6615
+ await execa(command, args, options);
6616
+ };
6617
+ async function launchProject(launcher, options = {}) {
6618
+ if (options.skipExternalCommands ?? shouldSkipExternalCommands()) return Result.ok(void 0);
6619
+ return Result.tryPromise({
6620
+ try: () => (options.runner ?? runCommand)(launcher.command, launcher.args, {
6621
+ cwd: launcher.cwd,
6622
+ stdio: launcher.cwd ? "inherit" : "ignore"
6623
+ }),
6624
+ catch: (cause) => new CLIError({
6625
+ message: `Could not open the project with ${launcher.label}.`,
6626
+ cause
6627
+ })
6628
+ });
6629
+ }
6630
+ //#endregion
6206
6631
  //#region src/utils/project-name-validation.ts
6207
6632
  function validateProjectName(name) {
6208
6633
  const hardeningResult = validateAgentSafePathInput(name, "projectName");
@@ -6558,49 +6983,6 @@ function getDatabaseUrl(database, projectName) {
6558
6983
  }
6559
6984
  }
6560
6985
  //#endregion
6561
- //#region src/utils/command-exists.ts
6562
- async function commandExists(command) {
6563
- const result = await Result.tryPromise({
6564
- try: async () => {
6565
- if (process.platform === "win32") return (await $({ reject: false })`where ${command}`).exitCode === 0;
6566
- return (await $({ reject: false })`which ${command}`).exitCode === 0;
6567
- },
6568
- catch: () => false
6569
- });
6570
- return result.isOk() ? result.value : false;
6571
- }
6572
- //#endregion
6573
- //#region src/helpers/core/db-setup-options.ts
6574
- const REMOTE_PROVISIONING_DB_SETUPS = [
6575
- "turso",
6576
- "neon",
6577
- "prisma-postgres",
6578
- "supabase",
6579
- "mongodb-atlas"
6580
- ];
6581
- function requiresProvisioningGuardrails(dbSetup) {
6582
- return REMOTE_PROVISIONING_DB_SETUPS.includes(dbSetup);
6583
- }
6584
- function resolveDbSetupMode(dbSetup, cliOptions = {}) {
6585
- if (dbSetup === "none") return;
6586
- const explicitMode = cliOptions.dbSetupOptions?.mode;
6587
- if (explicitMode) return explicitMode;
6588
- if (cliOptions.manualDb === true) return "manual";
6589
- if (isSilent() && requiresProvisioningGuardrails(dbSetup)) return "manual";
6590
- }
6591
- function mergeResolvedDbSetupOptions(dbSetup, dbSetupOptions, cliOptions = {}) {
6592
- if (dbSetup === "none") return;
6593
- const resolvedMode = resolveDbSetupMode(dbSetup, {
6594
- ...cliOptions,
6595
- dbSetupOptions: dbSetupOptions ?? cliOptions.dbSetupOptions
6596
- });
6597
- if (!dbSetupOptions && !resolvedMode) return;
6598
- return {
6599
- ...dbSetupOptions,
6600
- mode: resolvedMode
6601
- };
6602
- }
6603
- //#endregion
6604
6986
  //#region src/helpers/database-providers/mongodb-atlas-setup.ts
6605
6987
  async function checkAtlasCLI() {
6606
6988
  const exists = await commandExists("atlas");
@@ -7893,7 +8275,7 @@ function getDesktopStaticBuildNote(frontend) {
7893
8275
  return `${pc.yellow("NOTE:")} Desktop builds package static web assets.\n ${staticBuildFrontends.get(staticBuildFrontend)} needs a static/export web build before desktop packaging will work.`;
7894
8276
  }
7895
8277
  async function displayPostInstallInstructions(config) {
7896
- const { api, database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy, serverDeploy } = config;
8278
+ const { api, database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy, serverDeploy, dbSetupOptions } = config;
7897
8279
  const isConvex = backend === "convex";
7898
8280
  const isBackendSelf = backend === "self";
7899
8281
  const runCmd = packageManager === "npm" ? "npm run" : packageManager === "pnpm" ? "pnpm run" : "bun run";
@@ -7903,7 +8285,7 @@ async function displayPostInstallInstructions(config) {
7903
8285
  const hasVitePlus = addons?.includes("vite-plus");
7904
8286
  const hasVitePlusNativeHooks = hasVitePlus && !hasHusky && !hasLefthook;
7905
8287
  const hasGitHooksOrLinting = addons?.includes("husky") || addons?.includes("biome") || addons?.includes("lefthook") || addons?.includes("oxlint") || hasVitePlus;
7906
- const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, webDeploy, serverDeploy, backend) : "";
8288
+ const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, webDeploy, serverDeploy, backend, dbSetupOptions) : "";
7907
8289
  const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd, frontend) : "";
7908
8290
  const electrobunInstructions = addons?.includes("electrobun") ? getElectrobunInstructions(runCmd, frontend) : "";
7909
8291
  const huskyInstructions = hasHusky ? getHuskyInstructions(runCmd) : "";
@@ -7914,7 +8296,7 @@ async function displayPostInstallInstructions(config) {
7914
8296
  const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
7915
8297
  const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
7916
8298
  const clerkInstructions = config.auth === "clerk" ? getClerkInstructions(frontend || [], backend, api) : "";
7917
- const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
8299
+ const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend, config.auth, frontend || []);
7918
8300
  const hasWeb = frontend?.some((f) => types_exports.webFrontends.includes(f));
7919
8301
  const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
7920
8302
  const hasReactRouter = frontend?.includes("react-router");
@@ -8038,7 +8420,7 @@ function getLefthookInstructions(packageManager) {
8038
8420
  function getVitePlusNativeHooksInstructions(runCmd) {
8039
8421
  return `${pc.bold("Vite+ native Git hooks:")}\n${pc.cyan("•")} Optional hook setup: ${`${runCmd} hooks:setup`}\n${pc.dim(" (runs vp config; hooks install into .vite-hooks and use vp staged)")}\n`;
8040
8422
  }
8041
- async function getDatabaseInstructions(database, orm, runCmd, _runtime, dbSetup, webDeploy, serverDeploy, backend) {
8423
+ async function getDatabaseInstructions(database, orm, runCmd, _runtime, dbSetup, webDeploy, serverDeploy, backend, dbSetupOptions) {
8042
8424
  const notes = [];
8043
8425
  const commands = [];
8044
8426
  const isD1Alchemy = dbSetup === "d1" && (serverDeploy === "cloudflare" || backend === "self" && webDeploy === "cloudflare");
@@ -8046,7 +8428,8 @@ async function getDatabaseInstructions(database, orm, runCmd, _runtime, dbSetup,
8046
8428
  backend,
8047
8429
  dbSetup,
8048
8430
  webDeploy,
8049
- serverDeploy
8431
+ serverDeploy,
8432
+ dbSetupOptions
8050
8433
  });
8051
8434
  if (dbSetup === "docker") {
8052
8435
  const dockerStatus = await getDockerStatus(database);
@@ -8210,7 +8593,7 @@ function getPolarInstructions(backend, packageManager) {
8210
8593
  const envPath = backend === "self" ? "apps/web/.env" : "apps/server/.env";
8211
8594
  return `${pc.bold("Polar Payments Setup:")}\n${pc.cyan("•")} Get access token & product ID from ${pc.underline("https://sandbox.polar.sh/")}\n${pc.cyan("•")} Set POLAR_ACCESS_TOKEN in ${envPath}`;
8212
8595
  }
8213
- function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend) {
8596
+ function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend, auth, frontend) {
8214
8597
  const instructions = [];
8215
8598
  const isBackendSelf = backend === "self";
8216
8599
  const hasAlchemyWeb = (0, types_exports.isAlchemyDeployTarget)(webDeploy);
@@ -8219,7 +8602,12 @@ function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend)
8219
8602
  if (hasAlchemyWeb || hasAlchemyServer) {
8220
8603
  const targetParts = [...hasAlchemyWeb ? [`web on ${webDeploy === "cloudflare" ? "Cloudflare" : "Prisma"}`] : [], ...hasAlchemyServer && !isBackendSelf ? [`server on ${serverDeploy === "cloudflare" ? "Cloudflare" : "Prisma"}`] : []];
8221
8604
  const deployScript = webDeploy === "vercel" ? "deploy:server" : serverDeploy === "vercel" ? "deploy:web" : "deploy";
8222
- instructions.push(`${pc.bold(`Deploy with Alchemy (${targetParts.join(" + ")}):`)}\n${pc.cyan("•")} Configure provider login: ${`cd packages/infra && ${alchemyExec} alchemy login --configure`}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} ${deployScript}`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
8605
+ const originSteps = [];
8606
+ const hasWeb = frontend.some((value) => types_exports.webFrontends.includes(value));
8607
+ if (!isBackendSelf && hasAlchemyServer && hasWeb) originSteps.push(`${pc.cyan("•")} Required after the first deploy: set CORS_ORIGIN in apps/server/.env to the deployed web origin, then deploy again`);
8608
+ if (auth === "better-auth" && isBackendSelf && webDeploy === "prisma") originSteps.push(`${pc.cyan("•")} After the first deploy, set BETTER_AUTH_URL in apps/web/.env to the returned web URL, then deploy again`);
8609
+ else if (auth === "better-auth" && !isBackendSelf && serverDeploy === "prisma") originSteps.push(`${pc.cyan("•")} After the first deploy, set BETTER_AUTH_URL in apps/server/.env to the returned server URL, then deploy again`);
8610
+ instructions.push(`${pc.bold(`Deploy with Alchemy (${targetParts.join(" + ")}):`)}\n${pc.cyan("•")} Configure provider login: ${`cd packages/infra && ${alchemyExec} alchemy login --configure`}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} ${deployScript}`}\n${originSteps.join("\n")}${originSteps.length > 0 ? "\n" : ""}${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
8223
8611
  }
8224
8612
  if (webDeploy === "docker" || serverDeploy === "docker") {
8225
8613
  const dockerTargets = webDeploy === "docker" && serverDeploy === "docker" ? "web + server" : webDeploy === "docker" ? "web" : "server";
@@ -8466,7 +8854,10 @@ async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
8466
8854
  const isTemplateSetup = input.template && input.template !== "none";
8467
8855
  if (!isSilent() && !isTemplateSetup && Object.keys(otherFlags).length > 0) log.info(pc.dim("Command-line options applied."));
8468
8856
  config = yield* Result.await(Result.tryPromise({
8469
- try: async () => gatherConfig(flagConfig, finalBaseName, finalResolvedPath, finalPathInput, { skipCompatibilityChecks: cliInput.yolo }),
8857
+ try: async () => gatherConfig(flagConfig, finalBaseName, finalResolvedPath, finalPathInput, {
8858
+ skipCompatibilityChecks: cliInput.yolo,
8859
+ manualDb: cliInput.manualDb ?? input.manualDb
8860
+ }),
8470
8861
  catch: (cause) => {
8471
8862
  if (cause instanceof UserCancelledError) return cause;
8472
8863
  return new CLIError({
@@ -8476,7 +8867,7 @@ async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
8476
8867
  }
8477
8868
  }));
8478
8869
  }
8479
- const effectiveDbSetupOptions = mergeResolvedDbSetupOptions(config.dbSetup, config.dbSetupOptions, {
8870
+ const effectiveDbSetupOptions = resolveProjectDbSetupOptions(config, {
8480
8871
  manualDb: cliInput.manualDb ?? input.manualDb,
8481
8872
  dbSetupOptions: cliInput.dbSetupOptions ?? input.dbSetupOptions
8482
8873
  });
@@ -8541,10 +8932,20 @@ async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
8541
8932
  const historyCommand = getCliSubcommandCommand("history", config.packageManager);
8542
8933
  log.message(`${pc.dim("Setup saved to history")}\n${pc.cyan(historyCommand)}`);
8543
8934
  }
8935
+ let projectLauncher;
8936
+ if (!isSilent()) {
8937
+ const launcherResult = await getProjectLauncherChoice(input.open, config.projectDir, { prompt: !input.yes && process.env.CI === void 0 && process.stdin.isTTY === true && process.stdout.isTTY === true });
8938
+ if (launcherResult.isErr()) log.warn(pc.yellow(launcherResult.error.message));
8939
+ else projectLauncher = launcherResult.value;
8940
+ }
8544
8941
  const elapsedTimeMs = Date.now() - startTime;
8545
8942
  if (!isSilent()) {
8546
8943
  const elapsedTimeInSeconds = (elapsedTimeMs / 1e3).toFixed(1);
8547
8944
  outro(pc.magenta(`Project ready in ${pc.bold(`${elapsedTimeInSeconds}s`)}`));
8945
+ if (projectLauncher) {
8946
+ const launchResult = await launchProject(projectLauncher);
8947
+ if (launchResult.isErr()) log.warn(pc.yellow(launchResult.error.message));
8948
+ }
8548
8949
  }
8549
8950
  return Result.ok({
8550
8951
  success: true,
@@ -8699,6 +9100,7 @@ const router = t.router({
8699
9100
  git: z.boolean().optional(),
8700
9101
  packageManager: types_exports.PackageManagerSchema.optional(),
8701
9102
  install: z.boolean().optional(),
9103
+ open: ProjectLauncherSchema.optional(),
8702
9104
  dbSetup: types_exports.DatabaseSetupSchema.optional(),
8703
9105
  backend: types_exports.BackendSchema.optional(),
8704
9106
  runtime: types_exports.RuntimeSchema.optional(),
@@ -8937,4 +9339,4 @@ async function add(options = {}) {
8937
9339
  };
8938
9340
  }
8939
9341
  //#endregion
8940
- export { ProjectCreationError as C, DirectoryConflictError as S, ValidationError as T, types_exports as _, TEMPLATE_COUNT as a, CompatibilityError as b, builder as c, createVirtual as d, docs as f, sponsors as g, router as h, SchemaNameSchema as i, create as l, getSchemaResult as m, GeneratorError$1 as n, VirtualFileSystem$1 as o, generate$1 as p, Result$1 as r, add as s, EMBEDDED_TEMPLATES$1 as t, createBtsCli as u, getLatestCLIVersion as v, UserCancelledError as w, DatabaseSetupError as x, CLIError as y };
9342
+ export { DirectoryConflictError as C, ValidationError as E, DatabaseSetupError as S, UserCancelledError as T, ProjectLauncherSchema as _, TEMPLATE_COUNT as a, CLIError as b, builder as c, createVirtual as d, docs as f, sponsors as g, router as h, SchemaNameSchema as i, create as l, getSchemaResult as m, GeneratorError$1 as n, VirtualFileSystem$1 as o, generate$1 as p, Result$1 as r, add as s, EMBEDDED_TEMPLATES$1 as t, createBtsCli as u, types_exports as v, ProjectCreationError as w, CompatibilityError as x, getLatestCLIVersion as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "3.39.2",
3
+ "version": "3.40.1",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "keywords": [
6
6
  "better-auth",
@@ -69,8 +69,8 @@
69
69
  "prepublishOnly": "npm run build"
70
70
  },
71
71
  "dependencies": {
72
- "@better-t-stack/template-generator": "^3.39.2",
73
- "@better-t-stack/types": "^3.39.2",
72
+ "@better-t-stack/template-generator": "^3.40.1",
73
+ "@better-t-stack/types": "^3.40.1",
74
74
  "@clack/core": "^1.4.3",
75
75
  "@clack/prompts": "^1.7.0",
76
76
  "@modelcontextprotocol/sdk": "1.30.0",