create-prisma 0.7.2 → 0.8.0-pr.57.218.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.
Files changed (131) hide show
  1. package/README.md +39 -155
  2. package/dist/cli.mjs +9 -3
  3. package/dist/create-BHt4J1kk.mjs +1489 -0
  4. package/dist/index.d.mts +43 -59
  5. package/dist/index.mjs +35 -2
  6. package/package.json +24 -19
  7. package/templates/create/_shared/.gitattributes.hbs +11 -0
  8. package/templates/create/_shared/README.md.hbs +72 -0
  9. package/templates/create/_shared/module.ts.hbs +30 -0
  10. package/templates/create/_shared/pnpm-workspace.yaml.hbs +16 -0
  11. package/templates/create/_shared/prisma-composer.config.ts.hbs +13 -0
  12. package/templates/create/_shared/prisma.config.ts.hbs +19 -0
  13. package/templates/create/_shared/service.ts.hbs +44 -0
  14. package/templates/create/_shared/src/prisma/composer.ts.hbs +10 -0
  15. package/templates/create/_shared/src/prisma/db.ts.hbs +63 -0
  16. package/templates/create/_shared/src/prisma/seed.ts.hbs +36 -0
  17. package/templates/create/_shared/src/prisma/users.ts.hbs +35 -0
  18. package/templates/create/astro/{astro.config.mjs.hbs → astro.config.mjs} +1 -2
  19. package/templates/create/astro/package.json.hbs +5 -5
  20. package/templates/create/astro/src/pages/api/users.ts.hbs +6 -23
  21. package/templates/create/astro/src/pages/index.astro.hbs +19 -56
  22. package/templates/create/astro/tsconfig.json +3 -0
  23. package/templates/create/elysia/package.json.hbs +6 -7
  24. package/templates/create/elysia/src/index.ts.hbs +18 -27
  25. package/templates/create/elysia/tsconfig.json +3 -1
  26. package/templates/create/hono/package.json.hbs +6 -7
  27. package/templates/create/hono/src/index.ts.hbs +11 -15
  28. package/templates/create/hono/tsconfig.json +3 -1
  29. package/templates/create/minimal/.yarnrc.yml.hbs +3 -0
  30. package/templates/create/minimal/package.json.hbs +21 -0
  31. package/templates/create/minimal/src/index.ts.hbs +19 -0
  32. package/templates/create/{turborepo/apps/api → minimal}/tsconfig.json +2 -2
  33. package/templates/create/nest/package.json.hbs +7 -7
  34. package/templates/create/nest/src/app.module.ts.hbs +9 -10
  35. package/templates/create/nest/src/main.ts.hbs +3 -10
  36. package/templates/create/nest/src/prisma.service.ts.hbs +6 -5
  37. package/templates/create/nest/src/users.controller.ts.hbs +3 -5
  38. package/templates/create/nest/src/users.service.ts.hbs +4 -11
  39. package/templates/create/nest/tsconfig.json +3 -2
  40. package/templates/create/next/eslint.config.mjs +8 -1
  41. package/templates/create/next/package.json.hbs +10 -10
  42. package/templates/create/next/src/app/page.tsx.hbs +17 -56
  43. package/templates/create/next/tsconfig.json +1 -0
  44. package/templates/create/nuxt/app/pages/index.vue.hbs +12 -45
  45. package/templates/create/nuxt/package.json.hbs +8 -7
  46. package/templates/create/nuxt/server/api/users.get.ts.hbs +3 -15
  47. package/templates/create/nuxt/tsconfig.json +3 -0
  48. package/templates/create/svelte/package.json.hbs +9 -11
  49. package/templates/create/svelte/src/routes/+page.server.ts.hbs +4 -16
  50. package/templates/create/svelte/src/routes/+page.svelte.hbs +14 -164
  51. package/templates/create/svelte/svelte.config.js +1 -4
  52. package/templates/create/svelte/tsconfig.json +2 -1
  53. package/templates/create/svelte/vite.config.ts +3 -0
  54. package/templates/create/tanstack-start/package.json.hbs +14 -14
  55. package/templates/create/tanstack-start/src/routes/__root.tsx.hbs +2 -3
  56. package/templates/create/tanstack-start/src/routes/index.tsx.hbs +27 -78
  57. package/templates/create/tanstack-start/tsconfig.json +4 -2
  58. package/templates/create/tanstack-start/vite.config.ts +2 -4
  59. package/dist/src-B3hRLZ0U.mjs +0 -2527
  60. package/templates/create/astro/README.md.hbs +0 -47
  61. package/templates/create/astro/prisma/schema.prisma.hbs +0 -21
  62. package/templates/create/astro/prisma/seed.ts.hbs +0 -38
  63. package/templates/create/astro/prisma.compute.ts.hbs +0 -10
  64. package/templates/create/astro/prisma.config.ts.hbs +0 -15
  65. package/templates/create/astro/src/lib/prisma.ts.hbs +0 -55
  66. package/templates/create/elysia/README.md.hbs +0 -43
  67. package/templates/create/elysia/deno.json.hbs +0 -5
  68. package/templates/create/elysia/prisma/schema.prisma.hbs +0 -25
  69. package/templates/create/elysia/prisma/seed.ts.hbs +0 -38
  70. package/templates/create/elysia/prisma.compute.ts.hbs +0 -11
  71. package/templates/create/elysia/prisma.config.ts.hbs +0 -15
  72. package/templates/create/elysia/src/lib/prisma.ts.hbs +0 -56
  73. package/templates/create/hono/README.md.hbs +0 -43
  74. package/templates/create/hono/deno.json.hbs +0 -5
  75. package/templates/create/hono/prisma/schema.prisma.hbs +0 -25
  76. package/templates/create/hono/prisma/seed.ts.hbs +0 -38
  77. package/templates/create/hono/prisma.compute.ts.hbs +0 -10
  78. package/templates/create/hono/prisma.config.ts.hbs +0 -15
  79. package/templates/create/hono/src/lib/prisma.ts.hbs +0 -56
  80. package/templates/create/nest/README.md.hbs +0 -43
  81. package/templates/create/nest/deno.json.hbs +0 -5
  82. package/templates/create/nest/prisma/schema.prisma.hbs +0 -25
  83. package/templates/create/nest/prisma/seed.ts.hbs +0 -40
  84. package/templates/create/nest/prisma.compute.ts.hbs +0 -10
  85. package/templates/create/nest/prisma.config.ts.hbs +0 -15
  86. package/templates/create/nest/src/lib/prisma.ts.hbs +0 -58
  87. package/templates/create/next/README.md.hbs +0 -42
  88. package/templates/create/next/deno.json.hbs +0 -12
  89. package/templates/create/next/prisma/schema.prisma.hbs +0 -21
  90. package/templates/create/next/prisma/seed.ts.hbs +0 -38
  91. package/templates/create/next/prisma.compute.ts.hbs +0 -9
  92. package/templates/create/next/prisma.config.ts.hbs +0 -15
  93. package/templates/create/next/src/lib/prisma.ts.hbs +0 -56
  94. package/templates/create/nuxt/README.md.hbs +0 -44
  95. package/templates/create/nuxt/deno.json.hbs +0 -5
  96. package/templates/create/nuxt/prisma/schema.prisma.hbs +0 -21
  97. package/templates/create/nuxt/prisma/seed.ts.hbs +0 -38
  98. package/templates/create/nuxt/prisma.compute.ts.hbs +0 -9
  99. package/templates/create/nuxt/prisma.config.ts.hbs +0 -15
  100. package/templates/create/nuxt/server/utils/prisma.ts.hbs +0 -56
  101. package/templates/create/svelte/README.md.hbs +0 -45
  102. package/templates/create/svelte/deno.json.hbs +0 -5
  103. package/templates/create/svelte/prisma/schema.prisma.hbs +0 -21
  104. package/templates/create/svelte/prisma/seed.ts.hbs +0 -38
  105. package/templates/create/svelte/prisma.config.ts.hbs +0 -15
  106. package/templates/create/svelte/src/lib/server/prisma.ts.hbs +0 -53
  107. package/templates/create/tanstack-start/README.md.hbs +0 -43
  108. package/templates/create/tanstack-start/deno.json.hbs +0 -13
  109. package/templates/create/tanstack-start/prisma/schema.prisma.hbs +0 -21
  110. package/templates/create/tanstack-start/prisma/seed.ts.hbs +0 -38
  111. package/templates/create/tanstack-start/prisma.compute.ts.hbs +0 -9
  112. package/templates/create/tanstack-start/prisma.config.ts.hbs +0 -15
  113. package/templates/create/tanstack-start/src/lib/prisma.server.ts.hbs +0 -56
  114. package/templates/create/turborepo/README.md.hbs +0 -42
  115. package/templates/create/turborepo/apps/api/package.json.hbs +0 -26
  116. package/templates/create/turborepo/apps/api/src/index.ts.hbs +0 -55
  117. package/templates/create/turborepo/deno.json.hbs +0 -5
  118. package/templates/create/turborepo/package.json.hbs +0 -30
  119. package/templates/create/turborepo/packages/db/package.json.hbs +0 -22
  120. package/templates/create/turborepo/packages/db/prisma/schema.prisma.hbs +0 -21
  121. package/templates/create/turborepo/packages/db/prisma/seed.ts.hbs +0 -38
  122. package/templates/create/turborepo/packages/db/prisma.config.ts.hbs +0 -15
  123. package/templates/create/turborepo/packages/db/src/client.ts.hbs +0 -63
  124. package/templates/create/turborepo/packages/db/src/index.ts +0 -2
  125. package/templates/create/turborepo/packages/db/tsconfig.json +0 -15
  126. package/templates/create/turborepo/pnpm-workspace.yaml +0 -3
  127. package/templates/create/turborepo/prisma.compute.ts.hbs +0 -14
  128. package/templates/create/turborepo/turbo.json +0 -28
  129. /package/templates/create/{astro → _shared}/deno.json.hbs +0 -0
  130. /package/templates/create/{turborepo → elysia}/.yarnrc.yml.hbs +0 -0
  131. /package/templates/create/next/{next.config.ts.hbs → next.config.ts} +0 -0
@@ -0,0 +1,1489 @@
1
+ #!/usr/bin/env node
2
+ import { z } from "zod";
3
+ import { cancel, confirm, intro, isCancel, log, note, outro, select, spinner, text } from "@clack/prompts";
4
+ import fs from "fs-extra";
5
+ import path from "node:path";
6
+ import { randomUUID } from "node:crypto";
7
+ import os from "node:os";
8
+ import { PostHog } from "posthog-node";
9
+ import Handlebars from "handlebars";
10
+ import { existsSync } from "node:fs";
11
+ import { fileURLToPath } from "node:url";
12
+ import { execa } from "execa";
13
+ import { styleText } from "node:util";
14
+
15
+ //#region src/telemetry/client.ts
16
+ const TELEMETRY_API_KEY = "";
17
+ const TELEMETRY_HOST = "https://us.i.posthog.com";
18
+ const TELEMETRY_CONFIG_FILE = "telemetry.json";
19
+ const UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
20
+ function shouldDisableTelemetry() {
21
+ return true;
22
+ }
23
+ function getTelemetryConfigDir() {
24
+ if (process.platform === "darwin") return path.join(os.homedir(), "Library", "Application Support", "create-prisma");
25
+ if (process.platform === "win32") return path.join(process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming"), "create-prisma");
26
+ return path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "create-prisma");
27
+ }
28
+ async function getAnonymousId() {
29
+ const telemetryConfigPath = path.join(getTelemetryConfigDir(), TELEMETRY_CONFIG_FILE);
30
+ try {
31
+ const config = await fs.readJSON(telemetryConfigPath);
32
+ if (typeof config.anonymousId === "string" && UUID_V4_REGEX.test(config.anonymousId)) return config.anonymousId;
33
+ } catch {}
34
+ const anonymousId = randomUUID();
35
+ try {
36
+ await fs.ensureDir(path.dirname(telemetryConfigPath));
37
+ await fs.writeJSON(telemetryConfigPath, { anonymousId }, { spaces: 2 });
38
+ } catch {}
39
+ return anonymousId;
40
+ }
41
+ function getCommonProperties() {
42
+ return {
43
+ "cli-version": "0.8.0-pr.57.218.1",
44
+ "node-version": process.version,
45
+ platform: process.platform,
46
+ arch: process.arch
47
+ };
48
+ }
49
+ function sanitizeProperties(properties) {
50
+ return Object.fromEntries(Object.entries(properties).filter(([, value]) => value !== void 0));
51
+ }
52
+ async function trackCliTelemetry(event, properties) {
53
+ if (shouldDisableTelemetry()) return;
54
+ let client;
55
+ try {
56
+ const distinctId = await getAnonymousId();
57
+ const sanitizedProperties = sanitizeProperties({
58
+ ...getCommonProperties(),
59
+ ...properties,
60
+ $process_person_profile: false
61
+ });
62
+ client = new PostHog(TELEMETRY_API_KEY, {
63
+ host: TELEMETRY_HOST,
64
+ disableGeoip: true,
65
+ flushAt: 1,
66
+ flushInterval: 0
67
+ });
68
+ await client.captureImmediate({
69
+ distinctId,
70
+ event,
71
+ properties: sanitizedProperties,
72
+ disableGeoip: true
73
+ });
74
+ } catch {} finally {
75
+ if (client) await client.shutdown().catch(() => {});
76
+ }
77
+ }
78
+
79
+ //#endregion
80
+ //#region src/telemetry/create.ts
81
+ const CREATE_PRISMA_NEXT_COMPLETED_EVENT = "cli:create_prisma_next_command_completed";
82
+ const CREATE_PRISMA_NEXT_FAILED_EVENT = "cli:create_prisma_next_command_failed";
83
+ function getTargetDirectoryState(context) {
84
+ if (!context.targetPathState.exists) return "new";
85
+ if (context.targetPathState.isEmptyDirectory) return "empty_directory";
86
+ return "non_empty_directory";
87
+ }
88
+ function getBaseCreateProperties(input, context) {
89
+ return {
90
+ command: "create",
91
+ "uses-defaults": input.yes === true,
92
+ verbose: input.verbose === true,
93
+ force: input.force === true,
94
+ template: context?.template ?? input.template ?? null,
95
+ "database-provider": context?.prismaSetupContext.databaseProvider ?? input.provider ?? null,
96
+ "authoring-style": context?.prismaSetupContext.authoring ?? input.authoring ?? null,
97
+ "package-manager": context?.prismaSetupContext.packageManager ?? input.packageManager ?? null,
98
+ "should-deploy": context?.prismaSetupContext.shouldDeploy ?? input.deploy ?? null,
99
+ "target-directory-state": context ? getTargetDirectoryState(context) : null
100
+ };
101
+ }
102
+ function getErrorName(error) {
103
+ if (error instanceof Error) return error.name;
104
+ return error === void 0 ? null : "UnknownError";
105
+ }
106
+ function getErrorCode(error) {
107
+ if (typeof error !== "object" || error === null) return null;
108
+ const exitCode = Reflect.get(error, "exitCode");
109
+ if (typeof exitCode === "number") return exitCode;
110
+ const code = Reflect.get(error, "code");
111
+ return typeof code === "number" || typeof code === "string" ? code : null;
112
+ }
113
+ async function trackCreateCompleted(params) {
114
+ await trackCliTelemetry(CREATE_PRISMA_NEXT_COMPLETED_EVENT, {
115
+ ...getBaseCreateProperties(params.input, params.context),
116
+ "duration-ms": params.durationMs
117
+ });
118
+ }
119
+ async function trackCreateFailed(params) {
120
+ await trackCliTelemetry(CREATE_PRISMA_NEXT_FAILED_EVENT, {
121
+ ...getBaseCreateProperties(params.input, params.context),
122
+ "duration-ms": params.durationMs,
123
+ "failure-stage": params.stage,
124
+ "error-name": getErrorName(params.error),
125
+ "error-code": getErrorCode(params.error)
126
+ });
127
+ }
128
+
129
+ //#endregion
130
+ //#region src/types.ts
131
+ const databaseProviderInputs = [
132
+ "postgres",
133
+ "postgresql",
134
+ "mongo",
135
+ "mongodb"
136
+ ];
137
+ const packageManagers = [
138
+ "npm",
139
+ "pnpm",
140
+ "yarn",
141
+ "bun",
142
+ "deno"
143
+ ];
144
+ const authoringStyles = ["psl", "typescript"];
145
+ const createTemplates = [
146
+ "minimal",
147
+ "hono",
148
+ "elysia",
149
+ "nest",
150
+ "next",
151
+ "svelte",
152
+ "astro",
153
+ "nuxt",
154
+ "tanstack-start"
155
+ ];
156
+ function normalizeDatabaseProvider(value) {
157
+ if (value === "postgresql") return "postgres";
158
+ if (value === "mongodb") return "mongo";
159
+ return value;
160
+ }
161
+ const DatabaseProviderSchema = z.enum(databaseProviderInputs).transform(normalizeDatabaseProvider);
162
+ const PackageManagerSchema = z.enum(packageManagers);
163
+ const AuthoringStyleSchema = z.enum(authoringStyles);
164
+ const CreateTemplateSchema = z.enum(createTemplates);
165
+ const CommonCommandOptionsSchema = z.object({
166
+ yes: z.boolean().optional().describe("Skip prompts and accept default choices"),
167
+ verbose: z.boolean().optional().describe("Show verbose command output during setup")
168
+ });
169
+ const PrismaSetupOptionsSchema = z.object({
170
+ provider: DatabaseProviderSchema.optional().describe("Prisma 8 database target: PostgreSQL relational models or MongoDB document models"),
171
+ authoring: AuthoringStyleSchema.optional().describe("Contract authoring style"),
172
+ packageManager: PackageManagerSchema.optional().describe("Package manager used for dependency installation"),
173
+ deploy: z.boolean().optional().describe("Deploy the generated app to Prisma immediately"),
174
+ workspace: z.string().trim().min(1, "Please enter a valid workspace id or name").optional().describe("Prisma workspace id or name to deploy into")
175
+ });
176
+ const PrismaSetupCommandInputSchema = CommonCommandOptionsSchema.extend(PrismaSetupOptionsSchema.shape);
177
+ const CreateScaffoldOptionsSchema = z.object({
178
+ name: z.string().trim().min(1, "Please enter a valid project name").optional().describe("Project name / directory"),
179
+ template: CreateTemplateSchema.optional().describe("Project template"),
180
+ force: z.boolean().optional().describe("Allow scaffolding into a non-empty target directory")
181
+ });
182
+ const CreateCommandInputSchema = PrismaSetupCommandInputSchema.extend(CreateScaffoldOptionsSchema.shape);
183
+
184
+ //#endregion
185
+ //#region src/utils/package-manager.ts
186
+ const packageManagerManifestValues = {
187
+ npm: "npm@10.9.0",
188
+ pnpm: "pnpm@11.21.0",
189
+ yarn: "yarn@4.13.0",
190
+ bun: "bun@1.3.9"
191
+ };
192
+ function parseUserAgent(userAgent) {
193
+ if (userAgent?.startsWith("pnpm")) return "pnpm";
194
+ if (userAgent?.startsWith("yarn")) return "yarn";
195
+ if (userAgent?.startsWith("bun")) return "bun";
196
+ if (userAgent?.startsWith("deno")) return "deno";
197
+ if (userAgent?.startsWith("npm")) return "npm";
198
+ return null;
199
+ }
200
+ function parsePackageManagerField(packageManagerField) {
201
+ if (typeof packageManagerField !== "string" || packageManagerField.length === 0) return null;
202
+ const managerName = packageManagerField.split("@")[0];
203
+ const parsed = PackageManagerSchema.safeParse(managerName);
204
+ return parsed.success ? parsed.data : null;
205
+ }
206
+ async function detectFromPackageJson(projectDir) {
207
+ const packageJsonPath = path.join(projectDir, "package.json");
208
+ if (!await fs.pathExists(packageJsonPath)) return null;
209
+ return parsePackageManagerField((await fs.readJson(packageJsonPath)).packageManager);
210
+ }
211
+ async function detectFromDenoConfig(projectDir) {
212
+ for (const configFile of ["deno.json", "deno.jsonc"]) if (await fs.pathExists(path.join(projectDir, configFile))) return "deno";
213
+ return null;
214
+ }
215
+ async function detectFromLockfile(projectDir) {
216
+ for (const check of [
217
+ {
218
+ manager: "pnpm",
219
+ lockfile: "pnpm-lock.yaml"
220
+ },
221
+ {
222
+ manager: "yarn",
223
+ lockfile: "yarn.lock"
224
+ },
225
+ {
226
+ manager: "bun",
227
+ lockfile: "bun.lockb"
228
+ },
229
+ {
230
+ manager: "bun",
231
+ lockfile: "bun.lock"
232
+ },
233
+ {
234
+ manager: "npm",
235
+ lockfile: "package-lock.json"
236
+ },
237
+ {
238
+ manager: "npm",
239
+ lockfile: "npm-shrinkwrap.json"
240
+ },
241
+ {
242
+ manager: "deno",
243
+ lockfile: "deno.lock"
244
+ }
245
+ ]) if (await fs.pathExists(path.join(projectDir, check.lockfile))) return check.manager;
246
+ return null;
247
+ }
248
+ async function detectPackageManager(projectDir = process.cwd()) {
249
+ const fromPackageJson = await detectFromPackageJson(projectDir);
250
+ if (fromPackageJson) return fromPackageJson;
251
+ const fromLockfile = await detectFromLockfile(projectDir);
252
+ if (fromLockfile) return fromLockfile;
253
+ const fromDenoConfig = await detectFromDenoConfig(projectDir);
254
+ if (fromDenoConfig) return fromDenoConfig;
255
+ const fromUserAgent = parseUserAgent(process.env.npm_config_user_agent);
256
+ if (fromUserAgent) return fromUserAgent;
257
+ return "npm";
258
+ }
259
+ function getPackageManagerManifestValue(packageManager) {
260
+ if (!packageManager) return;
261
+ if (packageManager === "deno") return;
262
+ return packageManagerManifestValues[packageManager];
263
+ }
264
+ function getInstallCommand(packageManager) {
265
+ if (packageManager === "deno") return "deno install --allow-scripts";
266
+ return `${packageManager} install`;
267
+ }
268
+ function getRunScriptCommand(packageManager, scriptName) {
269
+ switch (packageManager) {
270
+ case "deno": return `deno task ${scriptName}`;
271
+ case "bun": return `bun run ${scriptName}`;
272
+ case "pnpm": return `pnpm run ${scriptName}`;
273
+ case "yarn": return `yarn run ${scriptName}`;
274
+ default: return `npm run ${scriptName}`;
275
+ }
276
+ }
277
+ function getRuntimeScriptCommand(packageManager, kind, options) {
278
+ const { sourceEntrypoint, builtEntrypoint } = options;
279
+ if (packageManager === "deno") switch (kind) {
280
+ case "dev": return `deno run -A --env-file=.env --watch ${sourceEntrypoint}`;
281
+ case "build": return `deno check ${sourceEntrypoint}`;
282
+ case "start": return `deno run -A --env-file=.env ${sourceEntrypoint}`;
283
+ }
284
+ if (packageManager === "bun") switch (kind) {
285
+ case "dev": return `bun --watch ${sourceEntrypoint}`;
286
+ case "build": return "tsc --noEmit";
287
+ case "start": return `bun ${sourceEntrypoint}`;
288
+ }
289
+ switch (kind) {
290
+ case "dev": return `tsx watch ${sourceEntrypoint}`;
291
+ case "build": return "tsc";
292
+ case "start": return builtEntrypoint ? `node ${builtEntrypoint}` : `tsx ${sourceEntrypoint}`;
293
+ }
294
+ }
295
+ function getInstallArgs(packageManager) {
296
+ if (packageManager === "deno") return {
297
+ command: "deno",
298
+ args: ["install", "--allow-scripts"]
299
+ };
300
+ return {
301
+ command: packageManager,
302
+ args: ["install"]
303
+ };
304
+ }
305
+ function getPackageExecutionArgs(packageManager, commandArgs) {
306
+ switch (packageManager) {
307
+ case "deno": {
308
+ const [packageName, ...args] = commandArgs;
309
+ if (!packageName) throw new Error("Package execution requires a package name.");
310
+ return {
311
+ command: "deno",
312
+ args: [
313
+ "run",
314
+ "-A",
315
+ `npm:${packageName}`,
316
+ ...args
317
+ ]
318
+ };
319
+ }
320
+ case "pnpm": return {
321
+ command: "pnpm",
322
+ args: ["dlx", ...commandArgs]
323
+ };
324
+ case "yarn": return {
325
+ command: "yarn",
326
+ args: ["dlx", ...commandArgs]
327
+ };
328
+ case "bun": return {
329
+ command: "bunx",
330
+ args: [...commandArgs]
331
+ };
332
+ default: return {
333
+ command: "npx",
334
+ args: ["--yes", ...commandArgs]
335
+ };
336
+ }
337
+ }
338
+ function getPackageExecutionCommand(packageManager, commandArgs) {
339
+ const execution = getPackageExecutionArgs(packageManager, commandArgs);
340
+ return [execution.command, ...execution.args].join(" ");
341
+ }
342
+ function getRunScriptArgs(packageManager, scriptName) {
343
+ switch (packageManager) {
344
+ case "deno": return {
345
+ command: "deno",
346
+ args: ["task", scriptName]
347
+ };
348
+ case "bun": return {
349
+ command: "bun",
350
+ args: ["run", scriptName]
351
+ };
352
+ case "pnpm": return {
353
+ command: "pnpm",
354
+ args: ["run", scriptName]
355
+ };
356
+ case "yarn": return {
357
+ command: "yarn",
358
+ args: ["run", scriptName]
359
+ };
360
+ default: return {
361
+ command: "npm",
362
+ args: ["run", scriptName]
363
+ };
364
+ }
365
+ }
366
+
367
+ //#endregion
368
+ //#region src/templates/shared.ts
369
+ Handlebars.registerHelper("eq", (left, right) => left === right);
370
+ Handlebars.registerHelper("runScriptCommand", (packageManager, scriptName) => packageManager ? getRunScriptCommand(packageManager, scriptName) : "");
371
+ Handlebars.registerHelper("packageManagerManifestValue", (packageManager) => getPackageManagerManifestValue(packageManager) ?? "");
372
+ Handlebars.registerHelper("runtimeScript", (packageManager, kind, sourceEntrypoint, builtEntrypoint, _options) => {
373
+ if (!packageManager) return "";
374
+ return getRuntimeScriptCommand(packageManager, kind, {
375
+ sourceEntrypoint,
376
+ builtEntrypoint
377
+ });
378
+ });
379
+ function findPackageRoot(startDir) {
380
+ let currentDir = startDir;
381
+ while (true) {
382
+ if (existsSync(path.join(currentDir, "package.json"))) return currentDir;
383
+ const parentDir = path.dirname(currentDir);
384
+ if (parentDir === currentDir) break;
385
+ currentDir = parentDir;
386
+ }
387
+ throw new Error(`Unable to locate package root from: ${startDir}`);
388
+ }
389
+ function resolveTemplatesDir(relativeTemplatesDir) {
390
+ const currentFilePath = fileURLToPath(import.meta.url);
391
+ const packageRoot = findPackageRoot(path.dirname(currentFilePath));
392
+ const templatePath = path.join(packageRoot, relativeTemplatesDir);
393
+ if (!existsSync(templatePath)) throw new Error(`Template directory not found at: ${templatePath}`);
394
+ return templatePath;
395
+ }
396
+ async function getTemplateFilesRecursively(dir) {
397
+ const entries = await fs.readdir(dir, { withFileTypes: true });
398
+ return (await Promise.all(entries.map(async (entry) => {
399
+ const entryPath = path.join(dir, entry.name);
400
+ if (entry.isDirectory()) return getTemplateFilesRecursively(entryPath);
401
+ if (!entry.isFile()) return [];
402
+ return [entryPath];
403
+ }))).flat();
404
+ }
405
+ function stripHbsExtension(filePath) {
406
+ return filePath.endsWith(".hbs") ? filePath.slice(0, -4) : filePath;
407
+ }
408
+ function ensureTrailingNewline(content) {
409
+ return content.endsWith("\n") ? content : `${content}\n`;
410
+ }
411
+ async function renderTemplateFile(opts) {
412
+ const { templateFilePath, outputPath, context } = opts;
413
+ const templateContent = await fs.readFile(templateFilePath, "utf8");
414
+ const outputContent = templateFilePath.endsWith(".hbs") ? Handlebars.compile(templateContent, {
415
+ noEscape: true,
416
+ strict: true
417
+ })(context) : templateContent;
418
+ if (templateFilePath.endsWith(".hbs") && outputContent.trim().length === 0) return;
419
+ await fs.outputFile(outputPath, ensureTrailingNewline(outputContent), "utf8");
420
+ }
421
+ async function renderTemplateTree(opts) {
422
+ const { templateRoot, outputDir, context } = opts;
423
+ const templateFiles = await getTemplateFilesRecursively(templateRoot);
424
+ for (const templateFilePath of templateFiles) {
425
+ const relativeOutputPath = stripHbsExtension(path.relative(templateRoot, templateFilePath));
426
+ await renderTemplateFile({
427
+ templateFilePath,
428
+ outputPath: path.join(outputDir, relativeOutputPath),
429
+ context
430
+ });
431
+ }
432
+ }
433
+
434
+ //#endregion
435
+ //#region src/templates/render-create-template.ts
436
+ function getCreateTemplateDir(template) {
437
+ return resolveTemplatesDir(`templates/create/${template}`);
438
+ }
439
+ function getCreateSharedTemplateDir() {
440
+ return resolveTemplatesDir("templates/create/_shared");
441
+ }
442
+ function createTemplateContext(projectName, template, provider, authoring, packageManager) {
443
+ return {
444
+ projectName,
445
+ template,
446
+ provider,
447
+ authoring,
448
+ packageManager
449
+ };
450
+ }
451
+ async function scaffoldCreateSharedTemplates(opts) {
452
+ const { projectDir, projectName, template, provider, authoring, packageManager } = opts;
453
+ await renderTemplateTree({
454
+ templateRoot: getCreateSharedTemplateDir(),
455
+ outputDir: projectDir,
456
+ context: createTemplateContext(projectName, template, provider, authoring, packageManager)
457
+ });
458
+ }
459
+ async function scaffoldCreateFrameworkTemplate(opts) {
460
+ const { projectDir, projectName, template, provider, authoring, packageManager } = opts;
461
+ await renderTemplateTree({
462
+ templateRoot: getCreateTemplateDir(template),
463
+ outputDir: projectDir,
464
+ context: createTemplateContext(projectName, template, provider, authoring, packageManager)
465
+ });
466
+ }
467
+
468
+ //#endregion
469
+ //#region src/constants/dependencies.ts
470
+ const dependencyVersionMap = {
471
+ "@astrojs/node": "^10.0.2",
472
+ "@elysiajs/node": "^1.4.5",
473
+ "@prisma/cli-engine": "0.2.0",
474
+ "@prisma/composer": "0.10.0",
475
+ "@prisma/composer-prisma-cloud": "0.10.0",
476
+ "@prisma/orm-mongo": "8.0.0-rc.4",
477
+ "@prisma/orm-postgres": "8.0.0-rc.4",
478
+ "@sveltejs/adapter-node": "^5.3.2",
479
+ "@types/node": "^25.6.2",
480
+ alchemy: "2.0.0-beta.67",
481
+ arktype: "^2.2.3",
482
+ dotenv: "^17.4.2",
483
+ esbuild: "^0.28.1",
484
+ effect: "4.0.0-beta.103",
485
+ mongodb: "^7.1.0",
486
+ "mongodb-memory-server": "^11.1.0",
487
+ nitro: "^3.0.260610-beta",
488
+ tsx: "^4.21.0",
489
+ typescript: "^5.9.3"
490
+ };
491
+ const PRISMA_PLATFORM_CLI_PACKAGE = "prisma@next";
492
+ const PRISMA_DENO_CLI_PACKAGE = "prisma-next";
493
+ function getDependencyVersion(packageName) {
494
+ return dependencyVersionMap[packageName];
495
+ }
496
+ function usesEsbuild(template) {
497
+ return template === "minimal" || template === "hono" || template === "elysia" || template === "nest";
498
+ }
499
+ function getCreateTemplateDependencies(template, _packageManager) {
500
+ const dependencies = [
501
+ "@prisma/composer",
502
+ "@prisma/composer-prisma-cloud",
503
+ "alchemy"
504
+ ];
505
+ const devDependencies = ["@prisma/cli-engine"];
506
+ if (usesEsbuild(template)) devDependencies.push("esbuild");
507
+ if (template === "minimal" || usesEsbuild(template)) devDependencies.push("tsx");
508
+ if (template === "minimal") devDependencies.push("typescript");
509
+ if (template === "elysia") {
510
+ dependencies.push("@elysiajs/node");
511
+ devDependencies.push("@types/node");
512
+ }
513
+ if (template === "svelte") devDependencies.push("@sveltejs/adapter-node");
514
+ if (template === "astro") dependencies.push("@astrojs/node");
515
+ if (template === "tanstack-start") devDependencies.push("nitro");
516
+ return [{
517
+ packageJsonPath: "package.json",
518
+ dependencies,
519
+ devDependencies
520
+ }];
521
+ }
522
+
523
+ //#endregion
524
+ //#region src/constants/db-packages.ts
525
+ function getDbPackages(provider) {
526
+ switch (provider) {
527
+ case "postgres": return "@prisma/orm-postgres";
528
+ case "mongo": return "@prisma/orm-mongo";
529
+ }
530
+ }
531
+
532
+ //#endregion
533
+ //#region src/tasks/install.ts
534
+ function getPrismaScriptMap(packageManager) {
535
+ if (packageManager === "deno") {
536
+ const prismaCommand = (needsDatabase, ...args) => [
537
+ "deno run -A",
538
+ ...needsDatabase ? ["--env-file=.env"] : [],
539
+ `npm:${PRISMA_DENO_CLI_PACKAGE}`,
540
+ ...args
541
+ ].join(" ");
542
+ return {
543
+ "contract:emit": prismaCommand(false, "contract", "emit"),
544
+ "db:init": prismaCommand(true, "db", "init"),
545
+ "db:update": prismaCommand(true, "db", "update"),
546
+ "db:verify": prismaCommand(true, "db", "verify"),
547
+ "migration:plan": prismaCommand(true, "migration", "plan"),
548
+ migrate: prismaCommand(true, "migrate"),
549
+ "migration:status": prismaCommand(true, "migration", "status"),
550
+ "migration:show": prismaCommand(true, "migration", "show")
551
+ };
552
+ }
553
+ const prismaCommand = (...args) => getPackageExecutionCommand(packageManager, [PRISMA_PLATFORM_CLI_PACKAGE, ...args]);
554
+ return {
555
+ "contract:emit": prismaCommand("contract", "emit"),
556
+ "db:init": prismaCommand("db", "init"),
557
+ "db:update": prismaCommand("db", "update"),
558
+ "db:verify": prismaCommand("db", "verify"),
559
+ "migration:plan": prismaCommand("migration", "plan"),
560
+ migrate: prismaCommand("migrate"),
561
+ "migration:status": prismaCommand("migration", "status"),
562
+ "migration:show": prismaCommand("migration", "show")
563
+ };
564
+ }
565
+ function getComposerScriptMap(packageManager) {
566
+ if (packageManager === "deno") return {};
567
+ const composerCommand = (subcommand, extraArgs = []) => getPackageExecutionCommand(packageManager, [
568
+ PRISMA_PLATFORM_CLI_PACKAGE,
569
+ "composer",
570
+ subcommand,
571
+ "module.ts",
572
+ ...extraArgs
573
+ ]);
574
+ return {
575
+ "composer:dev": composerCommand("dev"),
576
+ "composer:deploy": composerCommand("deploy"),
577
+ "composer:destroy": composerCommand("destroy", ["--production"]),
578
+ deploy: `${getRunScriptCommand(packageManager, "build")} && ${getRunScriptCommand(packageManager, "composer:deploy")}`,
579
+ "dev:composer": `${getRunScriptCommand(packageManager, "build")} && ${getRunScriptCommand(packageManager, "composer:dev")}`
580
+ };
581
+ }
582
+ function unique(items) {
583
+ return [...new Set(items)];
584
+ }
585
+ function sortRecord(record) {
586
+ return Object.fromEntries(Object.entries(record).sort(([a], [b]) => a.localeCompare(b)));
587
+ }
588
+ async function addPackageDependency(opts) {
589
+ const { dependencies = [], devDependencies = [], customDependencies = {}, scripts = {}, scriptMode, projectDir } = opts;
590
+ const pkgJsonPath = path.join(projectDir, "package.json");
591
+ if (!await fs.pathExists(pkgJsonPath)) throw new Error(`No package.json found in ${projectDir}. Run this command inside an existing JavaScript/TypeScript project.`);
592
+ const pkgJson = await fs.readJson(pkgJsonPath);
593
+ pkgJson.dependencies ??= {};
594
+ pkgJson.devDependencies ??= {};
595
+ pkgJson.scripts ??= {};
596
+ for (const packageName of unique(dependencies)) {
597
+ const version = getDependencyVersion(packageName);
598
+ if (!version) throw new Error(`Dependency ${packageName} is missing from the version map.`);
599
+ pkgJson.dependencies[packageName] = version;
600
+ }
601
+ for (const packageName of unique(devDependencies)) {
602
+ const version = getDependencyVersion(packageName);
603
+ if (!version) throw new Error(`Dependency ${packageName} is missing from the version map.`);
604
+ pkgJson.devDependencies[packageName] = version;
605
+ }
606
+ for (const [packageName, version] of Object.entries(customDependencies)) pkgJson.dependencies[packageName] = version;
607
+ for (const [scriptName, command] of Object.entries(scripts)) {
608
+ if (scriptMode === "if-missing" && typeof pkgJson.scripts[scriptName] === "string" && pkgJson.scripts[scriptName].trim().length > 0) continue;
609
+ pkgJson.scripts[scriptName] = command;
610
+ }
611
+ pkgJson.dependencies = sortRecord(pkgJson.dependencies);
612
+ pkgJson.devDependencies = sortRecord(pkgJson.devDependencies);
613
+ pkgJson.scripts = sortRecord(pkgJson.scripts);
614
+ await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
615
+ }
616
+ async function writePrismaDependencies(provider, packageManager, _authoring, projectDir = process.cwd()) {
617
+ const dependencies = [getDbPackages(provider)];
618
+ if (provider === "mongo") dependencies.push("arktype", "mongodb");
619
+ if (packageManager === "deno") dependencies.push("dotenv");
620
+ await addPackageDependency({
621
+ dependencies,
622
+ devDependencies: packageManager === "deno" ? ["@types/node"] : ["@prisma/cli-engine", "@types/node"],
623
+ scripts: getPrismaScriptMap(packageManager),
624
+ projectDir
625
+ });
626
+ }
627
+ async function writeCreateTemplateDependencies(opts) {
628
+ const { template, packageManager, projectDir = process.cwd() } = opts;
629
+ if (packageManager === "deno") return;
630
+ for (const target of getCreateTemplateDependencies(template, packageManager)) await addPackageDependency({
631
+ dependencies: target.dependencies,
632
+ devDependencies: target.devDependencies,
633
+ customDependencies: target.customDependencies,
634
+ scripts: getComposerScriptMap(packageManager),
635
+ projectDir: path.join(projectDir, path.dirname(target.packageJsonPath))
636
+ });
637
+ const packageJsonPath = path.join(projectDir, "package.json");
638
+ const packageJson = await fs.readJson(packageJsonPath);
639
+ const effectVersion = getDependencyVersion("effect");
640
+ if (!effectVersion) throw new Error("Dependency effect is missing from the version map.");
641
+ if (packageManager === "yarn") packageJson.resolutions = {
642
+ ...packageJson.resolutions,
643
+ effect: effectVersion
644
+ };
645
+ else if (packageManager !== "pnpm") packageJson.overrides = {
646
+ ...packageJson.overrides,
647
+ effect: effectVersion
648
+ };
649
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
650
+ }
651
+ async function installProjectDependencies(packageManager, projectDir = process.cwd(), options = {}) {
652
+ const installCommand = getInstallArgs(packageManager);
653
+ const env = packageManager === "yarn" ? { YARN_ENABLE_IMMUTABLE_INSTALLS: "false" } : void 0;
654
+ await execa(installCommand.command, installCommand.args, {
655
+ cwd: projectDir,
656
+ env,
657
+ stdio: options.verbose === true ? "inherit" : "pipe"
658
+ });
659
+ }
660
+
661
+ //#endregion
662
+ //#region src/tasks/deploy-with-composer.ts
663
+ function redactSecrets(message) {
664
+ return message.replace(/\b((?:prisma\+)?postgres(?:ql)?:\/\/)[^\s'"]+/gi, "$1<redacted>").replace(/\b([A-Z0-9_]*(?:DATABASE_URL|TOKEN|SECRET|PASSWORD|API_KEY|PRIVATE_KEY)[A-Z0-9_]*=)[^\s]+/g, "$1<redacted>");
665
+ }
666
+ function getErrorMessage(error) {
667
+ if (error instanceof Error) return redactSecrets(error.message);
668
+ return redactSecrets(String(error));
669
+ }
670
+ function stripResourcePrefix(id, prefix) {
671
+ const marker = `${prefix}_`;
672
+ return id.startsWith(marker) ? id.slice(marker.length) : id;
673
+ }
674
+ function getConsoleProjectUrl(workspaceId, projectId) {
675
+ const consoleWorkspaceId = stripResourcePrefix(workspaceId, "wksp");
676
+ const consoleProjectId = stripResourcePrefix(projectId, "proj");
677
+ return `https://console.prisma.io/${encodeURIComponent(consoleWorkspaceId)}/${encodeURIComponent(consoleProjectId)}`;
678
+ }
679
+ function parsePrismaCliEnvelope(output) {
680
+ const lines = output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).reverse();
681
+ for (const line of lines) try {
682
+ const parsed = JSON.parse(line);
683
+ const candidate = parsed.kind === "result" ? parsed.envelope : parsed;
684
+ if (typeof candidate !== "object" || candidate === null) continue;
685
+ if (typeof Reflect.get(candidate, "ok") !== "boolean") continue;
686
+ return candidate;
687
+ } catch {}
688
+ throw new Error("Prisma CLI returned output that is not a valid result envelope.");
689
+ }
690
+ function getPrismaCliArgs(packageManager, args) {
691
+ return getPackageExecutionArgs(packageManager, [PRISMA_PLATFORM_CLI_PACKAGE, ...args]);
692
+ }
693
+ async function runPrismaJsonCommand(options) {
694
+ const invocation = getPrismaCliArgs(options.packageManager, [
695
+ ...options.args,
696
+ "--json",
697
+ "--no-interactive"
698
+ ]);
699
+ const result = await execa(invocation.command, invocation.args, {
700
+ cwd: options.projectDir,
701
+ env: process.env,
702
+ reject: false
703
+ });
704
+ if (options.forwardStderr && result.stderr) process.stderr.write(result.stderr.endsWith("\n") ? result.stderr : `${result.stderr}\n`);
705
+ let envelope;
706
+ try {
707
+ envelope = parsePrismaCliEnvelope(result.stdout);
708
+ } catch (error) {
709
+ if (result.exitCode !== 0 && result.stderr.trim()) throw new Error(result.stderr.trim());
710
+ throw error;
711
+ }
712
+ if (result.exitCode !== 0 || !envelope.ok || envelope.result === void 0) {
713
+ const summary = envelope.error?.summary ?? envelope.error?.message;
714
+ throw new Error([summary, envelope.error?.why].filter(Boolean).join(": ") || result.stderr.trim() || "Prisma CLI command failed.");
715
+ }
716
+ return envelope.result;
717
+ }
718
+ async function ensureAuthentication(packageManager, projectDir, beforeInteractiveLogin) {
719
+ const whoami = () => runPrismaJsonCommand({
720
+ packageManager,
721
+ projectDir,
722
+ args: ["auth", "whoami"]
723
+ });
724
+ const authState = await whoami();
725
+ if (authState.authenticated) return authState;
726
+ const loginCommand = getPackageExecutionCommand(packageManager, [
727
+ PRISMA_PLATFORM_CLI_PACKAGE,
728
+ "auth",
729
+ "login"
730
+ ]);
731
+ if (process.stdin.isTTY !== true) throw new Error(`Sign in first with ${loginCommand}, then run ${getRunScriptCommand(packageManager, "deploy")}.`);
732
+ beforeInteractiveLogin?.();
733
+ log.info("Sign in to Prisma to deploy.");
734
+ const login = getPrismaCliArgs(packageManager, ["auth", "login"]);
735
+ await execa(login.command, login.args, {
736
+ cwd: projectDir,
737
+ env: process.env,
738
+ stdio: "inherit"
739
+ });
740
+ const authenticatedState = await whoami();
741
+ if (!authenticatedState.authenticated) throw new Error("Prisma sign-in completed without an active workspace session.");
742
+ return authenticatedState;
743
+ }
744
+ function workspaceLabel(workspace) {
745
+ return workspace.name ?? workspace.id;
746
+ }
747
+ async function useWorkspace(options) {
748
+ return (await runPrismaJsonCommand({
749
+ packageManager: options.packageManager,
750
+ projectDir: options.projectDir,
751
+ args: [
752
+ "auth",
753
+ "workspace",
754
+ "use",
755
+ options.workspace
756
+ ]
757
+ })).workspace;
758
+ }
759
+ async function selectDeploymentWorkspace(options) {
760
+ const activeWorkspace = options.authState.workspace;
761
+ if (!activeWorkspace) throw new Error("The active Prisma credential does not specify a workspace.");
762
+ if (options.workspace) {
763
+ if (options.authState.source === "environment") {
764
+ if (options.workspace === activeWorkspace.id || options.workspace === activeWorkspace.name) return activeWorkspace;
765
+ throw new Error(`The environment credential is fixed to workspace ${workspaceLabel(activeWorkspace)}. Unset it before using --workspace ${options.workspace}.`);
766
+ }
767
+ return useWorkspace({
768
+ packageManager: options.packageManager,
769
+ projectDir: options.projectDir,
770
+ workspace: options.workspace
771
+ });
772
+ }
773
+ if (!options.shouldPrompt || process.stdin.isTTY !== true) return activeWorkspace;
774
+ const available = await runPrismaJsonCommand({
775
+ packageManager: options.packageManager,
776
+ projectDir: options.projectDir,
777
+ args: [
778
+ "auth",
779
+ "workspace",
780
+ "list"
781
+ ]
782
+ });
783
+ if (available.items.length <= 1) return activeWorkspace;
784
+ options.beforePrompt?.();
785
+ const selectedWorkspaceId = await select({
786
+ message: "Select Prisma workspace for deployment",
787
+ initialValue: activeWorkspace.id,
788
+ options: available.items.map((workspace) => ({
789
+ value: workspace.workspaceId,
790
+ label: workspace.workspaceName ?? workspace.workspaceId,
791
+ hint: workspace.current ? `${workspace.workspaceId}, current` : workspace.workspaceId
792
+ }))
793
+ });
794
+ if (isCancel(selectedWorkspaceId)) {
795
+ cancel("Operation cancelled.");
796
+ return;
797
+ }
798
+ options.afterPrompt?.();
799
+ if (selectedWorkspaceId === activeWorkspace.id) return activeWorkspace;
800
+ return useWorkspace({
801
+ packageManager: options.packageManager,
802
+ projectDir: options.projectDir,
803
+ workspace: selectedWorkspaceId
804
+ });
805
+ }
806
+ function parseComposerDeployResult(result) {
807
+ const summary = result.summary;
808
+ if (!summary) return;
809
+ const computeService = summary.nodes.flatMap((node) => node.entities).find((entity) => entity.kind === "compute-service");
810
+ return {
811
+ appName: summary.app,
812
+ ...computeService?.url ? { appUrl: computeService.url.replace(/\/$/, "") } : {}
813
+ };
814
+ }
815
+ async function getProjectDetails(options) {
816
+ try {
817
+ const result = await runPrismaJsonCommand({
818
+ packageManager: options.packageManager,
819
+ projectDir: options.projectDir,
820
+ args: [
821
+ "project",
822
+ "show",
823
+ "--project",
824
+ options.appName
825
+ ]
826
+ });
827
+ if (!result.project) return;
828
+ return {
829
+ workspace: result.workspace,
830
+ project: {
831
+ id: result.project.id,
832
+ name: result.project.name,
833
+ consoleUrl: getConsoleProjectUrl(result.workspace.id, result.project.id)
834
+ }
835
+ };
836
+ } catch {
837
+ return;
838
+ }
839
+ }
840
+ async function deployWithComposer(options) {
841
+ const progress = options.verbose ? void 0 : spinner();
842
+ let progressRunning = false;
843
+ const showProgress = (message) => {
844
+ if (!progress) return;
845
+ if (progressRunning) progress.message(message);
846
+ else {
847
+ progress.start(message);
848
+ progressRunning = true;
849
+ }
850
+ };
851
+ const clearProgress = () => {
852
+ if (!progress || !progressRunning) return;
853
+ progress.clear();
854
+ progressRunning = false;
855
+ };
856
+ try {
857
+ showProgress("Checking Prisma account...");
858
+ if (options.verbose) log.step("Checking Prisma account.");
859
+ const authState = await ensureAuthentication(options.packageManager, options.projectDir, clearProgress);
860
+ showProgress("Checking Prisma workspace...");
861
+ if (options.verbose) log.step("Checking Prisma workspace.");
862
+ const selectedWorkspace = await selectDeploymentWorkspace({
863
+ packageManager: options.packageManager,
864
+ projectDir: options.projectDir,
865
+ shouldPrompt: options.shouldPromptForWorkspace,
866
+ authState,
867
+ beforePrompt: clearProgress,
868
+ afterPrompt: () => showProgress("Selecting Prisma workspace..."),
869
+ ...options.workspace ? { workspace: options.workspace } : {}
870
+ });
871
+ if (!selectedWorkspace) return;
872
+ showProgress("Building for deployment...");
873
+ if (options.verbose) log.step("Building for deployment.");
874
+ const build = getRunScriptArgs(options.packageManager, "build");
875
+ await execa(build.command, build.args, {
876
+ cwd: options.projectDir,
877
+ env: process.env,
878
+ stdio: options.verbose ? "inherit" : "pipe"
879
+ });
880
+ showProgress("Deploying to Prisma...");
881
+ if (options.verbose) log.step("Deploying to Prisma.");
882
+ const deployment = parseComposerDeployResult(await runPrismaJsonCommand({
883
+ packageManager: options.packageManager,
884
+ projectDir: options.projectDir,
885
+ args: [
886
+ "composer",
887
+ "deploy",
888
+ "module.ts"
889
+ ],
890
+ forwardStderr: options.verbose
891
+ }));
892
+ const appName = deployment?.appName ?? options.appName;
893
+ showProgress("Loading deployment details...");
894
+ const details = await getProjectDetails({
895
+ packageManager: options.packageManager,
896
+ projectDir: options.projectDir,
897
+ appName
898
+ });
899
+ progress?.stop("Deployed to Prisma.");
900
+ progressRunning = false;
901
+ if (options.verbose) log.success("Deployed to Prisma.");
902
+ const workspace = details?.workspace ?? selectedWorkspace;
903
+ return {
904
+ appName,
905
+ ...deployment?.appUrl ? { appUrl: deployment.appUrl } : {},
906
+ ...workspace ? { workspace } : {},
907
+ project: details?.project ?? { name: appName }
908
+ };
909
+ } catch (error) {
910
+ progress?.error("Deployment failed.");
911
+ progressRunning = false;
912
+ log.error(`Deploy failed: ${getErrorMessage(error)}`);
913
+ return;
914
+ }
915
+ }
916
+
917
+ //#endregion
918
+ //#region src/tasks/setup-prisma.ts
919
+ const DEFAULT_DATABASE_PROVIDER = "postgres";
920
+ const DEFAULT_AUTHORING = "psl";
921
+ async function promptForDatabaseProvider() {
922
+ const databaseProvider = await select({
923
+ message: "Select your database",
924
+ initialValue: DEFAULT_DATABASE_PROVIDER,
925
+ options: [{
926
+ value: "postgres",
927
+ label: "PostgreSQL",
928
+ hint: "Prisma Postgres with Composer"
929
+ }, {
930
+ value: "mongo",
931
+ label: "MongoDB",
932
+ hint: "Connect an existing MongoDB database"
933
+ }]
934
+ });
935
+ if (isCancel(databaseProvider)) {
936
+ cancel("Operation cancelled.");
937
+ return;
938
+ }
939
+ return DatabaseProviderSchema.parse(databaseProvider);
940
+ }
941
+ async function promptForAuthoringStyle() {
942
+ const authoring = await select({
943
+ message: "Choose contract authoring style",
944
+ initialValue: DEFAULT_AUTHORING,
945
+ options: [{
946
+ value: "psl",
947
+ label: "PSL",
948
+ hint: "Prisma schema syntax"
949
+ }, {
950
+ value: "typescript",
951
+ label: "TypeScript",
952
+ hint: "TypeScript contract builder"
953
+ }]
954
+ });
955
+ if (isCancel(authoring)) {
956
+ cancel("Operation cancelled.");
957
+ return;
958
+ }
959
+ return AuthoringStyleSchema.parse(authoring);
960
+ }
961
+ function getPackageManagerHint(option, detected) {
962
+ const hints = {
963
+ npm: "Node.js default",
964
+ pnpm: "Fast, disk-efficient package manager",
965
+ yarn: "Yarn package manager",
966
+ bun: "Fast runtime and package manager",
967
+ deno: "Deno runtime (minimal PostgreSQL apps)"
968
+ };
969
+ return option === detected ? `Detected; ${hints[option]}` : hints[option];
970
+ }
971
+ async function promptForPackageManager(detected) {
972
+ const packageManager = await select({
973
+ message: "Choose package manager",
974
+ initialValue: detected,
975
+ options: packageManagers.map((value) => ({
976
+ value,
977
+ label: value,
978
+ hint: getPackageManagerHint(value, detected)
979
+ }))
980
+ });
981
+ if (isCancel(packageManager)) {
982
+ cancel("Operation cancelled.");
983
+ return;
984
+ }
985
+ return PackageManagerSchema.parse(packageManager);
986
+ }
987
+ async function promptForDeployment() {
988
+ const shouldDeploy = await confirm({
989
+ message: "Deploy to Prisma now?",
990
+ initialValue: true
991
+ });
992
+ if (isCancel(shouldDeploy)) {
993
+ cancel("Operation cancelled.");
994
+ return;
995
+ }
996
+ return Boolean(shouldDeploy);
997
+ }
998
+ async function collectPrismaSetupContext(input, options = {}) {
999
+ const projectDir = path.resolve(options.projectDir ?? process.cwd());
1000
+ const useDefaults = input.yes === true;
1001
+ const databaseProvider = input.provider ?? (useDefaults ? DEFAULT_DATABASE_PROVIDER : await promptForDatabaseProvider());
1002
+ if (!databaseProvider) return;
1003
+ const authoring = input.authoring ?? (useDefaults ? DEFAULT_AUTHORING : await promptForAuthoringStyle());
1004
+ if (!authoring) return;
1005
+ const detectedPackageManager = await detectPackageManager(projectDir);
1006
+ const packageManager = input.packageManager ?? (useDefaults ? detectedPackageManager : await promptForPackageManager(detectedPackageManager));
1007
+ if (!packageManager) return;
1008
+ if (packageManager === "deno" && databaseProvider !== "postgres") throw new Error("Deno support currently requires PostgreSQL.");
1009
+ if (packageManager === "deno" && options.template && options.template !== "minimal") throw new Error("Deno support currently requires the minimal template.");
1010
+ if (packageManager === "deno" && input.deploy === true) throw new Error("Prisma Compute does not support Deno deployments yet. Use --no-deploy.");
1011
+ const shouldDeploy = packageManager === "deno" ? false : input.deploy ?? (useDefaults ? false : await promptForDeployment());
1012
+ if (shouldDeploy === void 0) return;
1013
+ return {
1014
+ projectDir,
1015
+ verbose: input.verbose === true,
1016
+ databaseProvider,
1017
+ authoring,
1018
+ packageManager,
1019
+ shouldDeploy,
1020
+ shouldPromptForWorkspace: !useDefaults,
1021
+ ...input.workspace ? { workspace: input.workspace } : {}
1022
+ };
1023
+ }
1024
+ function getCommandErrorMessage(error) {
1025
+ if (error instanceof Error && "stderr" in error) {
1026
+ const stderr = String(error.stderr ?? "").trim();
1027
+ if (stderr) return stderr;
1028
+ }
1029
+ return error instanceof Error ? error.message : String(error);
1030
+ }
1031
+ function getContractPath(authoring) {
1032
+ return `src/prisma/contract${authoring === "typescript" ? ".ts" : ".prisma"}`;
1033
+ }
1034
+ function getInitTarget(provider) {
1035
+ return provider === "mongo" ? "mongodb" : "postgres";
1036
+ }
1037
+ function getPrismaCliInvocation(packageManager, args) {
1038
+ return getPackageExecutionArgs(packageManager, [packageManager === "deno" ? PRISMA_DENO_CLI_PACKAGE : PRISMA_PLATFORM_CLI_PACKAGE, ...args]);
1039
+ }
1040
+ async function runPrismaInit(context, projectDir) {
1041
+ const args = context.packageManager === "deno" ? [
1042
+ "init",
1043
+ "--yes",
1044
+ "--no-interactive",
1045
+ "--target",
1046
+ getInitTarget(context.databaseProvider),
1047
+ "--authoring",
1048
+ context.authoring,
1049
+ "--schema-path",
1050
+ getContractPath(context.authoring),
1051
+ "--no-install",
1052
+ "--no-skill"
1053
+ ] : [
1054
+ "orm",
1055
+ "init",
1056
+ "--yes",
1057
+ "--no-interactive",
1058
+ "--target",
1059
+ getInitTarget(context.databaseProvider),
1060
+ "--authoring",
1061
+ context.authoring,
1062
+ "--schema-path",
1063
+ getContractPath(context.authoring),
1064
+ "--skip-install",
1065
+ "--skip-skills"
1066
+ ];
1067
+ const invocation = getPrismaCliInvocation(context.packageManager, args);
1068
+ if (context.verbose) log.step(`Running ${[invocation.command, ...invocation.args].join(" ")}`);
1069
+ await execa(invocation.command, invocation.args, {
1070
+ cwd: projectDir,
1071
+ stdio: context.verbose ? "inherit" : "pipe",
1072
+ env: {
1073
+ ...process.env,
1074
+ CI: "1"
1075
+ }
1076
+ });
1077
+ if (context.packageManager === "deno") await fs.remove(path.join(projectDir, "prisma-next.md"));
1078
+ }
1079
+ async function ensureGitignoreEntry(projectDir, entry) {
1080
+ const gitignorePath = path.join(projectDir, ".gitignore");
1081
+ const existing = await fs.pathExists(gitignorePath) ? await fs.readFile(gitignorePath, "utf8") : "";
1082
+ const lines = existing.split(/\r?\n/).map((line) => line.trim());
1083
+ if (lines.includes(entry) || lines.includes(`/${entry}`)) return;
1084
+ const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
1085
+ await fs.writeFile(gitignorePath, `${existing}${separator}${entry}\n`, "utf8");
1086
+ }
1087
+ async function ensureMongoEnvironment(projectDir) {
1088
+ const envPath = path.join(projectDir, ".env");
1089
+ if (!await fs.pathExists(envPath)) await fs.writeFile(envPath, "DATABASE_URL=\"mongodb://localhost:27017/mydb?replicaSet=rs0&directConnection=true\"\n", "utf8");
1090
+ await ensureGitignoreEntry(projectDir, ".env");
1091
+ }
1092
+ async function ensureComposerTypeScriptOptions(projectDir) {
1093
+ const tsconfigPath = path.join(projectDir, "tsconfig.json");
1094
+ const tsconfig = await fs.readFile(tsconfigPath, "utf8");
1095
+ const additions = [];
1096
+ if (!/"allowImportingTsExtensions"\s*:/.test(tsconfig)) additions.push(" \"allowImportingTsExtensions\": true,");
1097
+ if (!/"noEmit"\s*:/.test(tsconfig)) additions.push(" \"noEmit\": true,");
1098
+ if (additions.length === 0) return;
1099
+ const updated = tsconfig.replace(/"compilerOptions"\s*:\s*\{/, (match) => `${match}\n${additions.join("\n")}`);
1100
+ if (updated === tsconfig) throw new Error("tsconfig.json is missing compilerOptions.");
1101
+ await fs.writeFile(tsconfigPath, updated, "utf8");
1102
+ }
1103
+ async function emitContract(context, projectDir) {
1104
+ const invocation = getPrismaCliInvocation(context.packageManager, ["contract", "emit"]);
1105
+ if (context.verbose) log.step([invocation.command, ...invocation.args].join(" "));
1106
+ await execa(invocation.command, invocation.args, {
1107
+ cwd: projectDir,
1108
+ stdio: context.verbose ? "inherit" : "pipe"
1109
+ });
1110
+ }
1111
+ function formatNextSteps(steps) {
1112
+ return steps.map((step) => `${step.command}\n ${step.description}`).join("\n\n");
1113
+ }
1114
+ function formatPlatformTarget(name, id) {
1115
+ return name ? `${name} (${id})` : id;
1116
+ }
1117
+ function formatProjectSummary(options) {
1118
+ const lines = [];
1119
+ if (options.createdProjectPath) lines.push(`Path: ${path.resolve(options.createdProjectPath)}`);
1120
+ if (options.deployment?.workspace) lines.push(`Workspace: ${formatPlatformTarget(options.deployment.workspace.name, options.deployment.workspace.id)}`);
1121
+ if (options.deployment) {
1122
+ lines.push(`Project: ${options.deployment.project.id ? formatPlatformTarget(options.deployment.project.name, options.deployment.project.id) : options.deployment.project.name}`);
1123
+ lines.push(`App: ${options.deployment.appUrl ?? options.deployment.appName}`);
1124
+ if (options.deployment.project.consoleUrl) lines.push(`Console: ${options.deployment.project.consoleUrl}`);
1125
+ }
1126
+ return lines.join("\n");
1127
+ }
1128
+ function buildNextSteps(context, options) {
1129
+ const nextSteps = [...options.prependNextSteps ?? []];
1130
+ if (context.databaseProvider === "mongo") nextSteps.push({
1131
+ command: "Set MONGODB_URL in your environment",
1132
+ description: "Composer uses this secret when deploying the MongoDB template."
1133
+ });
1134
+ if (options.includeDevNextStep) nextSteps.push({
1135
+ command: getRunScriptCommand(context.packageManager, context.packageManager === "deno" ? "dev" : "dev:composer"),
1136
+ description: context.packageManager === "deno" ? "Start the Deno app after setting DATABASE_URL in .env." : "Build and start the app with Prisma Composer locally."
1137
+ });
1138
+ if (context.packageManager === "deno") return nextSteps;
1139
+ nextSteps.push({
1140
+ command: getRunScriptCommand(context.packageManager, "deploy"),
1141
+ description: "Build and deploy the app with Prisma Composer."
1142
+ });
1143
+ return nextSteps;
1144
+ }
1145
+ async function executePrismaSetupContext(context, options = {}) {
1146
+ const projectDir = path.resolve(options.projectDir ?? context.projectDir);
1147
+ const projectName = options.projectName ?? path.basename(projectDir);
1148
+ const template = options.template ?? "minimal";
1149
+ const progress = context.verbose ? void 0 : options.progressSpinner ?? spinner();
1150
+ if (progress !== void 0 && !options.progressSpinner) progress.start("Creating Prisma 8 project...");
1151
+ try {
1152
+ progress?.message("Preparing Prisma 8 project files...");
1153
+ await runPrismaInit(context, projectDir);
1154
+ await scaffoldCreateSharedTemplates({
1155
+ projectDir,
1156
+ projectName,
1157
+ template,
1158
+ provider: context.databaseProvider,
1159
+ authoring: context.authoring,
1160
+ packageManager: context.packageManager
1161
+ });
1162
+ await writePrismaDependencies(context.databaseProvider, context.packageManager, context.authoring, projectDir);
1163
+ await ensureComposerTypeScriptOptions(projectDir);
1164
+ if (context.databaseProvider === "mongo") await ensureMongoEnvironment(projectDir);
1165
+ progress?.message(`Installing dependencies with ${getInstallCommand(context.packageManager)}...`);
1166
+ await installProjectDependencies(context.packageManager, projectDir, { verbose: context.verbose });
1167
+ progress?.message("Generating Prisma 8 contract artifacts...");
1168
+ await emitContract(context, projectDir);
1169
+ progress?.stop("Prisma 8 project ready.");
1170
+ } catch (error) {
1171
+ progress?.error("Could not create Prisma 8 project.");
1172
+ cancel(getCommandErrorMessage(error));
1173
+ return false;
1174
+ }
1175
+ let deployment;
1176
+ if (context.shouldDeploy) {
1177
+ deployment = await deployWithComposer({
1178
+ appName: projectName,
1179
+ packageManager: context.packageManager,
1180
+ projectDir,
1181
+ shouldPromptForWorkspace: context.shouldPromptForWorkspace,
1182
+ verbose: context.verbose,
1183
+ ...context.workspace ? { workspace: context.workspace } : {}
1184
+ });
1185
+ if (!deployment) return false;
1186
+ }
1187
+ const projectSummary = formatProjectSummary({
1188
+ createdProjectPath: options.createdProjectPath,
1189
+ deployment
1190
+ });
1191
+ if (projectSummary) note(projectSummary, context.shouldDeploy ? "Deployment" : "Project");
1192
+ note(formatNextSteps(buildNextSteps(context, options)), "Next steps");
1193
+ outro(context.shouldDeploy ? "Prisma 8 app deployed." : "Prisma 8 project ready.");
1194
+ return true;
1195
+ }
1196
+
1197
+ //#endregion
1198
+ //#region src/ui/branding.ts
1199
+ const prismaTitle = `${styleText(["bold", "cyanBright"], "◭")} ${styleText(["bold", "cyanBright"], "Create")} ${styleText(["bold", "magentaBright"], "Prisma")} ${styleText(["bold", "blueBright"], "8")}`;
1200
+ function getCreatePrismaIntro() {
1201
+ return prismaTitle;
1202
+ }
1203
+
1204
+ //#endregion
1205
+ //#region src/utils/node-version.ts
1206
+ const MINIMUM_NODE_VERSION = [
1207
+ 22,
1208
+ 18,
1209
+ 0
1210
+ ];
1211
+ function parseVersion(version) {
1212
+ const [major = "0", minor = "0", patch = "0"] = version.replace(/^v/, "").split(".");
1213
+ return [
1214
+ Number(major),
1215
+ Number(minor),
1216
+ Number.parseInt(patch, 10)
1217
+ ];
1218
+ }
1219
+ function supportsPrismaNext(nodeVersion = process.versions.node) {
1220
+ const current = parseVersion(nodeVersion);
1221
+ for (let index = 0; index < MINIMUM_NODE_VERSION.length; index += 1) {
1222
+ if (current[index] > MINIMUM_NODE_VERSION[index]) return true;
1223
+ if (current[index] < MINIMUM_NODE_VERSION[index]) return false;
1224
+ }
1225
+ return true;
1226
+ }
1227
+ function getUnsupportedNodeMessage(nodeVersion = process.versions.node) {
1228
+ return [
1229
+ `Node.js ${nodeVersion} is unsupported by create-prisma@next.`,
1230
+ "Required: Node.js 22.18 or newer.",
1231
+ "Update Node.js and run the command again."
1232
+ ].join("\n");
1233
+ }
1234
+
1235
+ //#endregion
1236
+ //#region src/commands/create.ts
1237
+ const DEFAULT_PROJECT_NAME = "my-app";
1238
+ const DEFAULT_TEMPLATE = "minimal";
1239
+ function toPackageName(projectName) {
1240
+ return projectName.toLowerCase().replace(/[^a-z0-9._-]/g, "-").replace(/^-+/, "").replace(/-+$/, "") || "app";
1241
+ }
1242
+ function formatPathForDisplay(filePath) {
1243
+ return path.relative(process.cwd(), filePath) || ".";
1244
+ }
1245
+ function validateProjectName(value) {
1246
+ const trimmed = String(value ?? "").trim();
1247
+ if (trimmed.length === 0) return "Please enter a project name.";
1248
+ if (trimmed === "..") return "Project name cannot be '..'.";
1249
+ if (path.isAbsolute(trimmed)) return "Use a relative project name instead of an absolute path.";
1250
+ }
1251
+ async function promptForProjectName() {
1252
+ const projectName = await text({
1253
+ message: "Project name",
1254
+ placeholder: DEFAULT_PROJECT_NAME,
1255
+ initialValue: DEFAULT_PROJECT_NAME,
1256
+ validate: validateProjectName
1257
+ });
1258
+ if (isCancel(projectName)) {
1259
+ cancel("Operation cancelled.");
1260
+ return;
1261
+ }
1262
+ return String(projectName).trim();
1263
+ }
1264
+ async function promptForCreateTemplate() {
1265
+ const template = await select({
1266
+ message: "Select template",
1267
+ initialValue: DEFAULT_TEMPLATE,
1268
+ options: [
1269
+ {
1270
+ value: "minimal",
1271
+ label: "Minimal",
1272
+ hint: "Script-first Prisma 8 starter with no web framework"
1273
+ },
1274
+ {
1275
+ value: "hono",
1276
+ label: "Hono",
1277
+ hint: "Lightweight TypeScript API server"
1278
+ },
1279
+ {
1280
+ value: "elysia",
1281
+ label: "Elysia",
1282
+ hint: "Bun-friendly TypeScript API server"
1283
+ },
1284
+ {
1285
+ value: "nest",
1286
+ label: "NestJS",
1287
+ hint: "Structured Node API with controllers and services"
1288
+ },
1289
+ {
1290
+ value: "next",
1291
+ label: "Next.js",
1292
+ hint: "Full-stack React app with App Router"
1293
+ },
1294
+ {
1295
+ value: "svelte",
1296
+ label: "SvelteKit",
1297
+ hint: "Full-stack Svelte 5 app with Vite"
1298
+ },
1299
+ {
1300
+ value: "astro",
1301
+ label: "Astro",
1302
+ hint: "Content-oriented web app with server routes"
1303
+ },
1304
+ {
1305
+ value: "nuxt",
1306
+ label: "Nuxt",
1307
+ hint: "Full-stack Vue app with Nitro server routes"
1308
+ },
1309
+ {
1310
+ value: "tanstack-start",
1311
+ label: "TanStack Start",
1312
+ hint: "React app with file routes and server functions"
1313
+ }
1314
+ ]
1315
+ });
1316
+ if (isCancel(template)) {
1317
+ cancel("Operation cancelled.");
1318
+ return;
1319
+ }
1320
+ return CreateTemplateSchema.parse(template);
1321
+ }
1322
+ async function inspectTargetPath(targetPath) {
1323
+ if (!await fs.pathExists(targetPath)) return {
1324
+ exists: false,
1325
+ isDirectory: true,
1326
+ isEmptyDirectory: true
1327
+ };
1328
+ if (!(await fs.stat(targetPath)).isDirectory()) return {
1329
+ exists: true,
1330
+ isDirectory: false,
1331
+ isEmptyDirectory: false
1332
+ };
1333
+ return {
1334
+ exists: true,
1335
+ isDirectory: true,
1336
+ isEmptyDirectory: (await fs.readdir(targetPath)).length === 0
1337
+ };
1338
+ }
1339
+ async function runCreateCommand(rawInput = {}) {
1340
+ const startedAt = Date.now();
1341
+ let input = {};
1342
+ let context;
1343
+ let failureStage = "validate_input";
1344
+ try {
1345
+ input = CreateCommandInputSchema.parse(rawInput);
1346
+ if (!supportsPrismaNext()) {
1347
+ cancel(getUnsupportedNodeMessage());
1348
+ process.exitCode = 1;
1349
+ return;
1350
+ }
1351
+ intro(getCreatePrismaIntro());
1352
+ failureStage = "collect_context";
1353
+ context = await collectCreateContext(input);
1354
+ if (!context) return;
1355
+ failureStage = "unknown";
1356
+ const executionResult = await executeCreateContext(context);
1357
+ if (!executionResult.ok) {
1358
+ process.exitCode = 1;
1359
+ if (executionResult.error) cancel(`Create command failed: ${executionResult.error instanceof Error ? executionResult.error.message : String(executionResult.error)}`);
1360
+ await trackCreateFailed({
1361
+ input,
1362
+ context,
1363
+ durationMs: Date.now() - startedAt,
1364
+ error: executionResult.error,
1365
+ stage: executionResult.stage
1366
+ });
1367
+ return;
1368
+ }
1369
+ await trackCreateCompleted({
1370
+ input,
1371
+ context,
1372
+ durationMs: Date.now() - startedAt
1373
+ });
1374
+ } catch (error) {
1375
+ process.exitCode = 1;
1376
+ cancel(`Create command failed: ${error instanceof Error ? error.message : String(error)}`);
1377
+ await trackCreateFailed({
1378
+ input,
1379
+ context,
1380
+ durationMs: Date.now() - startedAt,
1381
+ error,
1382
+ stage: failureStage
1383
+ });
1384
+ }
1385
+ }
1386
+ async function collectCreateContext(input) {
1387
+ const force = input.force === true;
1388
+ const useDefaults = input.yes === true;
1389
+ const projectNameInput = input.name ?? (useDefaults ? DEFAULT_PROJECT_NAME : await promptForProjectName());
1390
+ if (projectNameInput === void 0) return;
1391
+ const projectName = String(projectNameInput).trim();
1392
+ const projectNameValidationError = validateProjectName(projectName);
1393
+ if (projectNameValidationError) {
1394
+ cancel(projectNameValidationError);
1395
+ return;
1396
+ }
1397
+ const template = input.template ?? (useDefaults ? DEFAULT_TEMPLATE : await promptForCreateTemplate());
1398
+ if (!template) return;
1399
+ const targetDirectory = path.resolve(process.cwd(), projectName);
1400
+ const targetPathState = await inspectTargetPath(targetDirectory);
1401
+ if (targetPathState.exists && !targetPathState.isDirectory) {
1402
+ cancel(`Target path ${formatPathForDisplay(targetDirectory)} already exists and is not a directory. Choose a different project name.`);
1403
+ return;
1404
+ }
1405
+ if (targetPathState.exists && !targetPathState.isEmptyDirectory && !force) {
1406
+ cancel(`Target directory ${formatPathForDisplay(targetDirectory)} is not empty. Use --force to continue.`);
1407
+ return;
1408
+ }
1409
+ const prismaSetupContext = await collectPrismaSetupContext(input, {
1410
+ projectDir: targetDirectory,
1411
+ template
1412
+ });
1413
+ if (!prismaSetupContext) return;
1414
+ return {
1415
+ targetDirectory,
1416
+ targetPathState,
1417
+ force,
1418
+ template,
1419
+ projectPackageName: toPackageName(path.basename(targetDirectory)),
1420
+ prismaSetupContext
1421
+ };
1422
+ }
1423
+ async function executeCreateContext(context) {
1424
+ const createSpinner = context.prismaSetupContext.verbose ? void 0 : spinner();
1425
+ createSpinner?.start("Creating Prisma 8 project...");
1426
+ try {
1427
+ if (context.prismaSetupContext.verbose) log.step(`Scaffolding ${context.template} starter.`);
1428
+ await scaffoldCreateFrameworkTemplate({
1429
+ projectDir: context.targetDirectory,
1430
+ projectName: context.projectPackageName,
1431
+ template: context.template,
1432
+ provider: context.prismaSetupContext.databaseProvider,
1433
+ authoring: context.prismaSetupContext.authoring,
1434
+ packageManager: context.prismaSetupContext.packageManager
1435
+ });
1436
+ if (context.prismaSetupContext.verbose) log.success("Starter files scaffolded.");
1437
+ } catch (error) {
1438
+ createSpinner?.error("Could not create Prisma 8 project.");
1439
+ return {
1440
+ ok: false,
1441
+ stage: "scaffold_template",
1442
+ error
1443
+ };
1444
+ }
1445
+ try {
1446
+ await writeCreateTemplateDependencies({
1447
+ template: context.template,
1448
+ packageManager: context.prismaSetupContext.packageManager,
1449
+ projectDir: context.targetDirectory
1450
+ });
1451
+ } catch (error) {
1452
+ createSpinner?.error("Could not create Prisma 8 project.");
1453
+ return {
1454
+ ok: false,
1455
+ stage: "scaffold_template",
1456
+ error
1457
+ };
1458
+ }
1459
+ if (context.targetPathState.exists && !context.targetPathState.isEmptyDirectory && context.force) log.warn(`Used --force in non-empty directory ${formatPathForDisplay(context.targetDirectory)}.`);
1460
+ const nextSteps = formatPathForDisplay(context.targetDirectory) === "." ? [] : [{
1461
+ command: `cd ${formatPathForDisplay(context.targetDirectory)}`,
1462
+ description: "Enter your new project directory."
1463
+ }];
1464
+ try {
1465
+ if (!await executePrismaSetupContext(context.prismaSetupContext, {
1466
+ prependNextSteps: nextSteps,
1467
+ projectDir: context.targetDirectory,
1468
+ projectName: context.projectPackageName,
1469
+ template: context.template,
1470
+ createdProjectPath: context.targetDirectory,
1471
+ includeDevNextStep: true,
1472
+ progressSpinner: createSpinner
1473
+ })) return {
1474
+ ok: false,
1475
+ stage: "prisma_setup"
1476
+ };
1477
+ } catch (error) {
1478
+ createSpinner?.error("Could not create Prisma 8 project.");
1479
+ return {
1480
+ ok: false,
1481
+ stage: "prisma_setup",
1482
+ error
1483
+ };
1484
+ }
1485
+ return { ok: true };
1486
+ }
1487
+
1488
+ //#endregion
1489
+ export { DatabaseProviderSchema as a, CreateTemplateSchema as i, AuthoringStyleSchema as n, PackageManagerSchema as o, CreateCommandInputSchema as r, runCreateCommand as t };