@prisma/cli 3.0.0-beta.4 → 3.0.0-beta.6

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.
@@ -7,7 +7,7 @@ import { canPrompt } from "../shell/runtime.js";
7
7
  import { confirmPrompt, selectPrompt, textPrompt } from "../shell/prompt.js";
8
8
  import { requireComputeAuth } from "../lib/auth/guard.js";
9
9
  import { readAuthState } from "../lib/auth/auth-ops.js";
10
- import { parseEnvAssignments } from "../lib/app/env-vars.js";
10
+ import { envVarNames, parseEnvAssignments } from "../lib/app/env-vars.js";
11
11
  import { renderDeployOutputRows, renderDeploySettingsPreview } from "../lib/app/deploy-output.js";
12
12
  import { readBunPackageEntrypoint, readBunPackageJson } from "../lib/app/bun-project.js";
13
13
  import { DEFAULT_LOCAL_DEV_PORT, resolveLocalBuildType, runLocalApp } from "../lib/app/local-dev.js";
@@ -19,6 +19,7 @@ import { promptForProjectSetupChoice } from "../lib/project/interactive-setup.js
19
19
  import { readLocalGitBranch } from "../lib/git/local-branch.js";
20
20
  import { PREVIEW_BUILD_TYPES, RESOLVED_PREVIEW_BUILD_TYPES, executePreviewBuild } from "../lib/app/preview-build.js";
21
21
  import { PREVIEW_DEFAULT_REGION } from "../lib/app/preview-interaction.js";
22
+ import { maybeSetupBranchDatabase } from "../lib/app/branch-database-deploy.js";
22
23
  import { createPreviewDeployProgress, createPreviewDeployProgressState, createPreviewPromoteProgress } from "../lib/app/preview-progress.js";
23
24
  import { PreviewDomainApiError, createPreviewAppProvider } from "../lib/app/preview-provider.js";
24
25
  import { enforceProductionDeployGate } from "../lib/app/production-deploy-gate.js";
@@ -170,6 +171,10 @@ async function runAppDeploy(context, appName, options) {
170
171
  assertSupportedEntrypoint(buildType, options?.entrypoint, "deploy");
171
172
  const entrypoint = await resolveDeployEntrypoint(context.runtime.cwd, framework, options?.entrypoint, context.runtime.signal);
172
173
  const portMapping = parseDeployPortMapping(String(runtime.port));
174
+ const branchDatabaseSetup = await maybeSetupBranchDatabase(context, provider, projectId, toBranchDatabaseDeployBranch(target.branch), {
175
+ db: options?.db,
176
+ inlineEnvVars: envVars
177
+ });
173
178
  const progressState = createPreviewDeployProgressState();
174
179
  const deployStartedAt = Date.now();
175
180
  const deployResult = await provider.deployApp({
@@ -200,17 +205,30 @@ async function runAppDeploy(context, appName, options) {
200
205
  result: {
201
206
  workspace: target.workspace,
202
207
  project: target.project,
203
- branch: target.branch,
208
+ branch: toResultBranch(target.branch),
204
209
  resolution: target.resolution,
210
+ branchDatabase: branchDatabaseSetup.result,
205
211
  app: {
206
212
  id: deployResult.app.id,
207
213
  name: deployResult.app.name
208
214
  },
209
215
  deployment: deployResult.deployment,
216
+ deploySettings: {
217
+ framework: {
218
+ key: framework.key,
219
+ buildType,
220
+ name: framework.displayName,
221
+ source: framework.annotation
222
+ },
223
+ entrypoint: entrypoint ?? null,
224
+ httpPort: runtime.port,
225
+ region: selectedApp.region ?? null,
226
+ envVars: envVarNames(envVars)
227
+ },
210
228
  durationMs: deployDurationMs,
211
229
  localPin: localPinResult
212
230
  },
213
- warnings: [],
231
+ warnings: branchDatabaseSetup.warnings,
214
232
  nextSteps: ["prisma-cli app list-deploys", `prisma-cli app show-deploy ${deployResult.deployment.id}`]
215
233
  };
216
234
  }
@@ -222,6 +240,7 @@ async function runAppListDeploys(context, appName, projectRef) {
222
240
  command: "app.list-deploys",
223
241
  result: {
224
242
  projectId,
243
+ verboseContext: toAppVerboseContext(target),
225
244
  app: null,
226
245
  deployments: []
227
246
  },
@@ -241,6 +260,7 @@ async function runAppListDeploys(context, appName, projectRef) {
241
260
  command: "app.list-deploys",
242
261
  result: {
243
262
  projectId,
263
+ verboseContext: toAppVerboseContext(target),
244
264
  app: {
245
265
  id: deploymentsResult.app.id,
246
266
  name: deploymentsResult.app.name
@@ -259,6 +279,7 @@ async function runAppShow(context, appName, projectRef) {
259
279
  command: "app.show",
260
280
  result: {
261
281
  projectId,
282
+ verboseContext: toAppVerboseContext(target),
262
283
  app: null,
263
284
  liveDeployment: null,
264
285
  liveUrl: null,
@@ -281,6 +302,7 @@ async function runAppShow(context, appName, projectRef) {
281
302
  command: "app.show",
282
303
  result: {
283
304
  projectId,
305
+ verboseContext: toAppVerboseContext(target),
284
306
  app: {
285
307
  id: deploymentsResult.app.id,
286
308
  name: deploymentsResult.app.name
@@ -354,6 +376,7 @@ async function runAppOpen(context, appName, projectRef) {
354
376
  command: "app.open",
355
377
  result: {
356
378
  projectId,
379
+ verboseContext: toAppVerboseContext(target),
357
380
  app: {
358
381
  id: deploymentsResult.app.id,
359
382
  name: deploymentsResult.app.name
@@ -644,6 +667,7 @@ async function runAppPromote(context, deploymentId, appName, projectRef) {
644
667
  command: "app.promote",
645
668
  result: {
646
669
  projectId,
670
+ verboseContext: toAppVerboseContext(target),
647
671
  app: {
648
672
  id: deploymentsResult.app.id,
649
673
  name: deploymentsResult.app.name
@@ -686,6 +710,7 @@ async function runAppRollback(context, appName, deploymentId, projectRef) {
686
710
  command: "app.rollback",
687
711
  result: {
688
712
  projectId,
713
+ verboseContext: toAppVerboseContext(target),
689
714
  app: {
690
715
  id: deploymentsResult.app.id,
691
716
  name: deploymentsResult.app.name
@@ -714,6 +739,7 @@ async function runAppRemove(context, appName, projectRef) {
714
739
  command: "app.remove",
715
740
  result: {
716
741
  projectId,
742
+ verboseContext: toAppVerboseContext(target),
717
743
  app: {
718
744
  id: removedApp.id,
719
745
  name: removedApp.name
@@ -757,7 +783,7 @@ async function resolveAppDomainTarget(context, options, commandName = "app domai
757
783
  resultTarget: {
758
784
  workspace: target.workspace,
759
785
  project: target.project,
760
- branch: target.branch,
786
+ branch: toResultBranch(target.branch),
761
787
  app: {
762
788
  id: selectedApp.id,
763
789
  name: selectedApp.name
@@ -1320,6 +1346,7 @@ async function resolveProjectContext(context, client, explicitProject, options)
1320
1346
  return {
1321
1347
  ...resolved,
1322
1348
  branch: {
1349
+ id: null,
1323
1350
  name: branch.name,
1324
1351
  kind: toBranchKind(branch.name)
1325
1352
  }
@@ -1446,6 +1473,7 @@ async function withRemoteDeployBranch(provider, target, branch, signal) {
1446
1473
  return {
1447
1474
  ...target,
1448
1475
  branch: {
1476
+ id: remoteBranch.id,
1449
1477
  name: remoteBranch.name,
1450
1478
  kind: remoteBranch.role
1451
1479
  }
@@ -1454,6 +1482,29 @@ async function withRemoteDeployBranch(provider, target, branch, signal) {
1454
1482
  function toBranchKind(name) {
1455
1483
  return name === "production" || name === "main" ? "production" : "preview";
1456
1484
  }
1485
+ function toResultBranch(branch) {
1486
+ return {
1487
+ id: branch.id,
1488
+ name: branch.name,
1489
+ kind: branch.kind
1490
+ };
1491
+ }
1492
+ function toAppVerboseContext(target) {
1493
+ return {
1494
+ workspace: target.workspace,
1495
+ project: target.project,
1496
+ branch: target.branch,
1497
+ resolution: target.resolution
1498
+ };
1499
+ }
1500
+ function toBranchDatabaseDeployBranch(branch) {
1501
+ if (!branch.id) throw new Error(`Deploy branch "${branch.name}" was not resolved remotely.`);
1502
+ return {
1503
+ id: branch.id,
1504
+ name: branch.name,
1505
+ kind: branch.kind
1506
+ };
1507
+ }
1457
1508
  function assertExclusiveDeployProjectInputs(options) {
1458
1509
  const provided = [
1459
1510
  options.projectRef ? "--project" : null,
@@ -41,6 +41,11 @@ async function listRealBranches(context) {
41
41
  return {
42
42
  projectId: target.project.id,
43
43
  projectName: target.project.name,
44
+ verboseContext: {
45
+ workspace,
46
+ project: target.project,
47
+ resolution: target.resolution
48
+ },
44
49
  branches: sortBranches(branches.map(toBranchSummary))
45
50
  };
46
51
  }
@@ -0,0 +1,323 @@
1
+ import { CliError, usageError } from "../../shell/errors.js";
2
+ import { renderSummaryLine } from "../../shell/ui.js";
3
+ import { canPrompt } from "../../shell/runtime.js";
4
+ import { confirmPrompt } from "../../shell/prompt.js";
5
+ import { formatCommandArgument } from "../../shell/command-arguments.js";
6
+ import { hasBranchDatabaseSignal, inspectBranchDatabaseSignal, runBranchDatabaseSchemaSetup } from "./branch-database.js";
7
+ import path from "node:path";
8
+ //#region src/lib/app/branch-database-deploy.ts
9
+ async function maybeSetupBranchDatabase(context, provider, projectId, branch, options) {
10
+ if (options.db === false) return emptyBranchDatabaseSetupOutcome();
11
+ if (hasInlineDatabaseEnvVars(options.inlineEnvVars)) {
12
+ if (options.db === true) throw usageError("Branch database setup cannot be combined with inline database env vars", "The deploy command received --db and an inline DATABASE_URL or DIRECT_URL value.", "Remove the inline --env database value to let --db create a branch override, or remove --db to deploy with the provided value.", ["prisma-cli app deploy --db", "prisma-cli app deploy --env DATABASE_URL=postgresql://example"], "app");
13
+ return emptyBranchDatabaseSetupOutcome();
14
+ }
15
+ if (branch.kind === "production") {
16
+ if (options.db === true) throw usageError("Branch database setup is only available for preview branches", "Production database wiring is a durable environment decision and is not created implicitly by app deploy.", "Use project env commands to manage production DATABASE_URL, or deploy a preview branch with --db.", ["prisma-cli project env add DATABASE_URL=<value> --role production", "prisma-cli app deploy --branch feature/db --db"], "app");
17
+ return emptyBranchDatabaseSetupOutcome();
18
+ }
19
+ const localSignal = await inspectBranchDatabaseSignal(context.runtime.cwd, context.runtime.signal);
20
+ const envState = await inspectBranchDatabaseEnv(provider, projectId, branch.id, context.runtime.signal);
21
+ const branchEnvVars = [envState.branchDatabaseUrl, envState.branchDirectUrl].filter((variable) => Boolean(variable)).map((variable) => variable.key).sort();
22
+ if (envState.branchDatabaseUrl) {
23
+ const warning = options.db === true ? `Branch "${branch.name}" already has DATABASE_URL. Leaving branch database env vars unchanged.` : null;
24
+ if (warning) emitBranchDatabaseWarning(context, warning);
25
+ return {
26
+ result: options.db === true ? {
27
+ status: "skipped",
28
+ reason: "branch-env-exists",
29
+ envVars: branchEnvVars,
30
+ schema: null
31
+ } : void 0,
32
+ warnings: warning ? [warning] : []
33
+ };
34
+ }
35
+ if (localSignal.unsupportedSchema) {
36
+ if (options.db === true) throw unsupportedBranchDatabaseSchemaError(localSignal.unsupportedSchema, branch.name, context);
37
+ return emptyBranchDatabaseSetupOutcome();
38
+ }
39
+ const hasSignal = hasBranchDatabaseSignal(localSignal) || Boolean(envState.previewDatabaseUrl);
40
+ if (options.db !== true) {
41
+ if (!hasSignal) return emptyBranchDatabaseSetupOutcome();
42
+ if (!canPrompt(context) || context.flags.yes) {
43
+ const warning = "This app appears to use DATABASE_URL. Run prisma-cli app deploy --db to create an isolated database for this preview branch.";
44
+ emitBranchDatabaseWarning(context, warning);
45
+ return {
46
+ result: void 0,
47
+ warnings: [warning]
48
+ };
49
+ }
50
+ maybeRenderBranchDatabaseSignal(context, branch.name, localSignal, envState);
51
+ if (!await confirmPrompt({
52
+ input: context.runtime.stdin,
53
+ output: context.output.stderr,
54
+ message: `Create an isolated database for branch "${branch.name}"?`,
55
+ initialValue: false
56
+ })) return emptyBranchDatabaseSetupOutcome();
57
+ }
58
+ return setupBranchDatabase(context, provider, projectId, branch, localSignal, envState);
59
+ }
60
+ async function setupBranchDatabase(context, provider, projectId, branch, signal, envState) {
61
+ emitBranchDatabaseProgress(context, "pending", "Creating branch database");
62
+ const database = await provider.createBranchDatabase({
63
+ projectId,
64
+ branchId: branch.id,
65
+ branchName: branch.name,
66
+ signal: context.runtime.signal
67
+ }).catch((error) => {
68
+ throw branchDatabaseSetupFailedError("Failed to create branch database", error, branch.name);
69
+ });
70
+ emitBranchDatabaseProgress(context, "success", "Created branch database");
71
+ try {
72
+ let schemaSetup = null;
73
+ const warnings = [];
74
+ let skippedSchemaWarning = null;
75
+ if (signal.schema) {
76
+ emitBranchDatabaseProgress(context, "pending", `Applying database schema with ${formatSchemaSetupCommand(signal.schema.command)}`);
77
+ schemaSetup = await runBranchDatabaseSchemaSetup({
78
+ context,
79
+ schema: signal.schema,
80
+ databaseUrl: database.databaseUrl,
81
+ directUrl: database.directUrl
82
+ }).catch((error) => {
83
+ throw schemaSetupFailedError(error, signal.schema, branch.name, context.runtime.cwd);
84
+ });
85
+ emitBranchDatabaseProgress(context, "success", "Applied database schema");
86
+ } else skippedSchemaWarning = "No supported Prisma schema source was found. Branch database env vars were created, but schema setup was skipped.";
87
+ const envVars = await upsertBranchDatabaseEnvVars(context, provider, projectId, branch, database, envState);
88
+ emitBranchDatabaseProgress(context, "success", `Added branch env override${envVars.length === 1 ? "" : "s"} ${envVars.join(", ")}`);
89
+ if (skippedSchemaWarning) {
90
+ emitBranchDatabaseWarning(context, skippedSchemaWarning);
91
+ warnings.push(skippedSchemaWarning);
92
+ }
93
+ return {
94
+ result: {
95
+ status: "created",
96
+ database: {
97
+ id: database.id,
98
+ name: database.name
99
+ },
100
+ envVars,
101
+ schema: schemaSetup ? {
102
+ command: schemaSetup.command,
103
+ source: schemaSetup.source,
104
+ path: schemaSetup.schemaPath
105
+ } : null
106
+ },
107
+ warnings
108
+ };
109
+ } catch (error) {
110
+ throw await cleanupCreatedBranchDatabaseAfterFailure(context, provider, database, branch.name, error);
111
+ }
112
+ }
113
+ async function upsertBranchDatabaseEnvVars(context, provider, projectId, branch, database, envState) {
114
+ const written = [];
115
+ await upsertBranchDatabaseEnvVar(context, provider, {
116
+ projectId,
117
+ branchId: branch.id,
118
+ className: "preview",
119
+ key: "DATABASE_URL",
120
+ value: database.databaseUrl,
121
+ existing: envState.branchDatabaseUrl,
122
+ branchName: branch.name
123
+ });
124
+ written.push("DATABASE_URL");
125
+ if (database.directUrl) {
126
+ await upsertBranchDatabaseEnvVar(context, provider, {
127
+ projectId,
128
+ branchId: branch.id,
129
+ className: "preview",
130
+ key: "DIRECT_URL",
131
+ value: database.directUrl,
132
+ existing: envState.branchDirectUrl,
133
+ branchName: branch.name
134
+ });
135
+ written.push("DIRECT_URL");
136
+ } else if (envState.branchDirectUrl) await provider.deleteEnvironmentVariable({
137
+ envVarId: envState.branchDirectUrl.id,
138
+ signal: context.runtime.signal
139
+ }).catch((error) => {
140
+ throw branchDatabaseSetupFailedError("Failed to remove stale DIRECT_URL", error, branch.name);
141
+ });
142
+ return written;
143
+ }
144
+ async function upsertBranchDatabaseEnvVar(context, provider, options) {
145
+ if (options.existing) {
146
+ await provider.updateEnvironmentVariable({
147
+ envVarId: options.existing.id,
148
+ value: options.value,
149
+ signal: context.runtime.signal
150
+ }).catch((error) => {
151
+ throw branchDatabaseSetupFailedError(`Failed to update ${options.key}`, error, options.branchName);
152
+ });
153
+ return;
154
+ }
155
+ await provider.createEnvironmentVariable({
156
+ projectId: options.projectId,
157
+ branchId: options.branchId,
158
+ className: options.className,
159
+ key: options.key,
160
+ value: options.value,
161
+ signal: context.runtime.signal
162
+ }).catch((error) => {
163
+ throw branchDatabaseSetupFailedError(`Failed to write ${options.key}`, error, options.branchName);
164
+ });
165
+ }
166
+ async function inspectBranchDatabaseEnv(provider, projectId, branchId, signal) {
167
+ const [databaseUrlRows, directUrlRows] = await Promise.all([provider.listEnvironmentVariables({
168
+ projectId,
169
+ className: "preview",
170
+ key: "DATABASE_URL",
171
+ signal
172
+ }), provider.listEnvironmentVariables({
173
+ projectId,
174
+ className: "preview",
175
+ key: "DIRECT_URL",
176
+ signal
177
+ })]);
178
+ return {
179
+ branchDatabaseUrl: findEnvVar(databaseUrlRows, { branchId }),
180
+ branchDirectUrl: findEnvVar(directUrlRows, { branchId }),
181
+ previewDatabaseUrl: findEnvVar(databaseUrlRows, { branchId: null })
182
+ };
183
+ }
184
+ function findEnvVar(rows, options) {
185
+ return rows.find((row) => row.branchId === options.branchId) ?? null;
186
+ }
187
+ function hasInlineDatabaseEnvVars(envVars) {
188
+ return Boolean(envVars && ("DATABASE_URL" in envVars || "DIRECT_URL" in envVars));
189
+ }
190
+ function maybeRenderBranchDatabaseSignal(context, branchName, signal, envState) {
191
+ if (context.flags.json || context.flags.quiet) return;
192
+ const rows = [
193
+ signal.schema ? ` Schema ${path.relative(context.runtime.cwd, signal.schema.path) || defaultSchemaSourcePath(signal.schema)}` : null,
194
+ signal.databaseUrlReferences.length > 0 ? ` Code ${signal.databaseUrlReferences.slice(0, 3).join(", ")}` : null,
195
+ envState.previewDatabaseUrl ? " Env preview DATABASE_URL is inherited by this branch" : null
196
+ ].filter((row) => Boolean(row));
197
+ context.output.stderr.write(`Database signal found for branch "${branchName}"\n${rows.join("\n")}\n\n`);
198
+ }
199
+ function emitBranchDatabaseProgress(context, status, message) {
200
+ if (context.flags.json || context.flags.quiet) return;
201
+ const line = status === "pending" ? `${context.ui.warning("◇")} ${message}...` : renderSummaryLine(context.ui, "success", message);
202
+ context.output.stderr.write(`${line}\n`);
203
+ }
204
+ function emitBranchDatabaseWarning(context, warning) {
205
+ if (context.flags.json || context.flags.quiet) return;
206
+ context.output.stderr.write(`${renderSummaryLine(context.ui, "warning", warning)}\n`);
207
+ }
208
+ function emptyBranchDatabaseSetupOutcome() {
209
+ return {
210
+ result: void 0,
211
+ warnings: []
212
+ };
213
+ }
214
+ function formatSchemaSetupCommand(command) {
215
+ switch (command) {
216
+ case "migrate-deploy": return "prisma migrate deploy";
217
+ case "db-push": return "prisma db push";
218
+ case "prisma-next-db-init": return "prisma-next db init";
219
+ }
220
+ }
221
+ function branchDatabaseSetupFailedError(summary, error, branchName) {
222
+ return new CliError({
223
+ code: "BRANCH_DATABASE_SETUP_FAILED",
224
+ domain: "app",
225
+ summary,
226
+ why: error instanceof Error ? error.message : String(error),
227
+ fix: "Retry the command, or create the branch database and env vars manually with project env commands.",
228
+ debug: formatDebugDetails(error),
229
+ meta: { branch: branchName },
230
+ exitCode: 1,
231
+ nextSteps: [`prisma-cli app deploy --branch ${formatCommandArgument(branchName)} --db`, `prisma-cli project env list --branch ${formatCommandArgument(branchName)}`]
232
+ });
233
+ }
234
+ async function cleanupCreatedBranchDatabaseAfterFailure(context, provider, database, branchName, error) {
235
+ const setupError = error instanceof CliError ? error : branchDatabaseSetupFailedError("Branch database setup failed", error, branchName);
236
+ emitBranchDatabaseProgress(context, "pending", "Removing branch database after setup failed");
237
+ try {
238
+ await provider.deleteBranchDatabase({
239
+ databaseId: database.id,
240
+ signal: context.runtime.signal
241
+ });
242
+ emitBranchDatabaseProgress(context, "success", "Removed branch database after setup failed");
243
+ } catch (cleanupError) {
244
+ return branchDatabaseCleanupFailedError(setupError, cleanupError, database, branchName);
245
+ }
246
+ return setupError;
247
+ }
248
+ function branchDatabaseCleanupFailedError(setupError, cleanupError, database, branchName) {
249
+ const cleanupWhy = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
250
+ const setupWhy = setupError.why ?? "Branch database setup failed.";
251
+ return new CliError({
252
+ code: setupError.code,
253
+ domain: setupError.domain,
254
+ summary: setupError.summary,
255
+ why: `${setupWhy} Prisma could not delete the created database "${database.name}" (${database.id}): ${cleanupWhy}`,
256
+ fix: "Delete the created branch database from Console or contact Prisma support, then rerun deploy with --db.",
257
+ debug: formatCombinedDebugDetails(setupError, cleanupError),
258
+ meta: {
259
+ ...setupError.meta,
260
+ branch: branchName,
261
+ databaseId: database.id,
262
+ databaseName: database.name,
263
+ cleanupFailed: true
264
+ },
265
+ exitCode: setupError.exitCode,
266
+ nextSteps: []
267
+ });
268
+ }
269
+ function schemaSetupFailedError(error, schema, branchName, cwd) {
270
+ return new CliError({
271
+ code: "SCHEMA_SETUP_FAILED",
272
+ domain: "app",
273
+ summary: "Database schema setup failed",
274
+ why: error instanceof Error ? error.message : String(error),
275
+ fix: "Fix the Prisma schema or migrations, then rerun deploy with --db.",
276
+ debug: formatDebugDetails(error),
277
+ meta: {
278
+ branch: branchName,
279
+ schemaPath: schema.path,
280
+ source: schema.kind,
281
+ command: schema.command
282
+ },
283
+ exitCode: 1,
284
+ nextSteps: [...formatSchemaSetupNextSteps(schema, cwd), `prisma-cli app deploy --branch ${formatCommandArgument(branchName)} --db`]
285
+ });
286
+ }
287
+ function unsupportedBranchDatabaseSchemaError(schema, branchName, context) {
288
+ return usageError("Branch database setup is not available for this Prisma schema", `${path.relative(context.runtime.cwd, schema.path) || defaultUnsupportedSchemaSourcePath(schema)} targets ${formatUnsupportedSchemaTarget(schema.target)}, but --db creates Prisma Postgres databases.`, "Use project env commands to provide a database URL for this branch, or switch the Prisma schema source to PostgreSQL before using --db.", [`prisma-cli project env add DATABASE_URL=<value> --branch ${formatCommandArgument(branchName)}`, `prisma-cli app deploy --branch ${formatCommandArgument(branchName)}`], "app");
289
+ }
290
+ function formatSchemaSetupNextSteps(schema, cwd) {
291
+ const sourcePath = path.relative(cwd, schema.path) || defaultSchemaSourcePath(schema);
292
+ switch (schema.command) {
293
+ case "migrate-deploy": return [`npx --no-install prisma migrate deploy --schema ${formatCommandArgument(sourcePath)}`];
294
+ case "db-push": return [`npx --no-install prisma db push --schema ${formatCommandArgument(sourcePath)}`];
295
+ case "prisma-next-db-init": return [`npx --no-install prisma-next contract emit --config ${formatCommandArgument(sourcePath)}`, `npx --no-install prisma-next db init --config ${formatCommandArgument(sourcePath)} --db <DATABASE_URL>`];
296
+ }
297
+ }
298
+ function defaultSchemaSourcePath(schema) {
299
+ return schema.kind === "prisma-next" ? "prisma-next.config.ts" : "schema.prisma";
300
+ }
301
+ function defaultUnsupportedSchemaSourcePath(schema) {
302
+ return schema.kind === "prisma-next" ? "prisma-next.config.ts" : "schema.prisma";
303
+ }
304
+ function formatUnsupportedSchemaTarget(target) {
305
+ switch (target) {
306
+ case "cockroachdb": return "CockroachDB";
307
+ case "mongodb": return "MongoDB";
308
+ case "mysql": return "MySQL";
309
+ case "sqlite": return "SQLite";
310
+ case "sqlserver": return "SQL Server";
311
+ }
312
+ }
313
+ function formatDebugDetails(error) {
314
+ if (error instanceof Error) return error.stack ?? error.message;
315
+ return typeof error === "string" ? error : null;
316
+ }
317
+ function formatCombinedDebugDetails(setupError, cleanupError) {
318
+ const setupDebug = setupError.debug ?? setupError.stack ?? setupError.message;
319
+ const cleanupDebug = formatDebugDetails(cleanupError);
320
+ return [setupDebug ? `Setup error:\n${setupDebug}` : null, cleanupDebug ? `Cleanup error:\n${cleanupDebug}` : null].filter((line) => Boolean(line)).join("\n\n") || null;
321
+ }
322
+ //#endregion
323
+ export { maybeSetupBranchDatabase };