@prisma/cli 3.0.0-beta.1 → 3.0.0-beta.10

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 (61) hide show
  1. package/README.md +5 -3
  2. package/dist/adapters/git.js +8 -3
  3. package/dist/adapters/local-state.js +12 -4
  4. package/dist/adapters/mock-api.js +81 -2
  5. package/dist/adapters/token-storage.js +63 -22
  6. package/dist/cli.js +17 -2
  7. package/dist/cli2.js +7 -3
  8. package/dist/commands/app/index.js +22 -10
  9. package/dist/commands/branch/index.js +2 -27
  10. package/dist/commands/database/index.js +159 -0
  11. package/dist/commands/env.js +8 -4
  12. package/dist/controllers/app-env-api.js +54 -0
  13. package/dist/controllers/app-env-file.js +181 -0
  14. package/dist/controllers/app-env.js +283 -129
  15. package/dist/controllers/app.js +247 -106
  16. package/dist/controllers/auth.js +8 -8
  17. package/dist/controllers/branch.js +78 -48
  18. package/dist/controllers/database.js +318 -0
  19. package/dist/controllers/project.js +153 -82
  20. package/dist/lib/app/branch-database-deploy.js +373 -0
  21. package/dist/lib/app/branch-database.js +316 -0
  22. package/dist/lib/app/bun-project.js +12 -5
  23. package/dist/lib/app/deploy-output.js +10 -1
  24. package/dist/lib/app/env-config.js +1 -1
  25. package/dist/lib/app/env-file.js +82 -0
  26. package/dist/lib/app/env-vars.js +28 -2
  27. package/dist/lib/app/local-dev.js +34 -18
  28. package/dist/lib/app/preview-branch-database.js +102 -0
  29. package/dist/lib/app/preview-build-settings.js +385 -0
  30. package/dist/lib/app/preview-build.js +272 -81
  31. package/dist/lib/app/preview-provider.js +163 -54
  32. package/dist/lib/app/production-deploy-gate.js +161 -0
  33. package/dist/lib/auth/auth-ops.js +30 -21
  34. package/dist/lib/auth/guard.js +3 -2
  35. package/dist/lib/auth/login.js +109 -14
  36. package/dist/lib/database/provider.js +167 -0
  37. package/dist/lib/diagnostics.js +15 -0
  38. package/dist/lib/git/local-branch.js +41 -0
  39. package/dist/lib/git/local-status.js +57 -0
  40. package/dist/lib/project/interactive-setup.js +1 -1
  41. package/dist/lib/project/local-pin.js +182 -33
  42. package/dist/lib/project/resolution.js +203 -49
  43. package/dist/lib/project/setup.js +59 -15
  44. package/dist/presenters/app-env.js +149 -14
  45. package/dist/presenters/app.js +170 -20
  46. package/dist/presenters/branch.js +37 -102
  47. package/dist/presenters/database.js +274 -0
  48. package/dist/presenters/project.js +63 -39
  49. package/dist/presenters/verbose-context.js +64 -0
  50. package/dist/shell/command-meta.js +103 -13
  51. package/dist/shell/command-runner.js +34 -6
  52. package/dist/shell/diagnostics-output.js +63 -0
  53. package/dist/shell/errors.js +12 -1
  54. package/dist/shell/output.js +10 -1
  55. package/dist/shell/runtime.js +3 -3
  56. package/dist/shell/ui.js +23 -1
  57. package/dist/shell/update-check.js +247 -0
  58. package/dist/use-cases/branch.js +20 -68
  59. package/dist/use-cases/create-cli-gateways.js +2 -17
  60. package/dist/use-cases/project.js +2 -1
  61. package/package.json +12 -10
package/README.md CHANGED
@@ -57,6 +57,8 @@ Useful next commands:
57
57
  npx prisma-cli app logs
58
58
  npx prisma-cli app open
59
59
  npx prisma-cli project env add DATABASE_URL=postgresql://example --role preview
60
+ npx prisma-cli project env add --file .env --role preview
61
+ npx prisma-cli project env list
60
62
  npx prisma-cli project env list --role preview
61
63
  ```
62
64
 
@@ -73,7 +75,7 @@ The beta package exposes `prisma-cli` so it can coexist with the existing
73
75
  | `auth` | Log in, log out, and inspect the active Prisma account. |
74
76
  | `project` | List projects, show the resolved project, and manage project environment variables. |
75
77
  | `git` | Connect or disconnect a project from a GitHub repository. |
76
- | `branch` | Inspect the Prisma branch that maps to the current work context. |
78
+ | `branch` | List Prisma branches for the resolved project. |
77
79
  | `app` | Build, run, deploy, inspect, open, stream logs, promote, roll back, and remove apps. |
78
80
 
79
81
  Common examples:
@@ -82,7 +84,7 @@ Common examples:
82
84
  npx prisma-cli version
83
85
  npx prisma-cli auth whoami
84
86
  npx prisma-cli project show
85
- npx prisma-cli branch show
87
+ npx prisma-cli branch list
86
88
  npx prisma-cli app deploy --branch feat-login --framework nextjs
87
89
  npx prisma-cli app promote <deployment-id>
88
90
  ```
@@ -113,7 +115,7 @@ the result, and route CLI / Compute feedback to the right Prisma channel.
113
115
 
114
116
  ## Beta notes
115
117
 
116
- - Requires Node.js 20 or newer.
118
+ - Requires Node.js 22.12 or newer.
117
119
  - This is a beta package and may change quickly.
118
120
  - Official beta releases publish as `@prisma/cli`.
119
121
  - The package binary is `prisma-cli`, not `prisma`, during beta.
@@ -2,7 +2,7 @@ import { execFile } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
3
  //#region src/adapters/git.ts
4
4
  const execFileAsync = promisify(execFile);
5
- async function readGitOriginRemote(cwd) {
5
+ async function readGitOriginRemote(cwd, signal) {
6
6
  try {
7
7
  const { stdout } = await execFileAsync("git", [
8
8
  "config",
@@ -10,14 +10,19 @@ async function readGitOriginRemote(cwd) {
10
10
  "remote.origin.url"
11
11
  ], {
12
12
  cwd,
13
- timeout: 5e3
13
+ timeout: 5e3,
14
+ signal
14
15
  });
15
16
  const remote = stdout.trim();
16
17
  return remote.length > 0 ? remote : null;
17
- } catch {
18
+ } catch (error) {
19
+ if (signal?.aborted || isAbortError(error)) throw error;
18
20
  return null;
19
21
  }
20
22
  }
23
+ function isAbortError(error) {
24
+ return error instanceof Error && error.name === "AbortError";
25
+ }
21
26
  function parseGitHubRepositoryUrl(value) {
22
27
  const input = value.trim();
23
28
  const shorthand = input.match(/^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/);
@@ -20,12 +20,17 @@ function resolveLocalStateFilePath(stateDir) {
20
20
  }
21
21
  var LocalStateStore = class {
22
22
  stateFilePath;
23
- constructor(stateDir) {
23
+ constructor(stateDir, signal) {
24
+ this.signal = signal;
24
25
  this.stateFilePath = resolveLocalStateFilePath(stateDir);
25
26
  }
26
27
  async read() {
28
+ this.signal?.throwIfAborted();
27
29
  try {
28
- const raw = await readFile(this.stateFilePath, "utf8");
30
+ const raw = await readFile(this.stateFilePath, {
31
+ encoding: "utf8",
32
+ signal: this.signal
33
+ });
29
34
  const parsed = JSON.parse(raw);
30
35
  return {
31
36
  auth: parsed.auth ?? structuredClone(DEFAULT_STATE.auth),
@@ -46,8 +51,11 @@ var LocalStateStore = class {
46
51
  }
47
52
  }
48
53
  async write(state) {
54
+ this.signal?.throwIfAborted();
49
55
  await mkdir(path.dirname(this.stateFilePath), { recursive: true });
50
- await writeFile(this.stateFilePath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
56
+ this.signal?.throwIfAborted();
57
+ await writeFile(this.stateFilePath, `${JSON.stringify(state, null, 2)}\n`, { encoding: "utf8" });
58
+ this.signal?.throwIfAborted();
51
59
  }
52
60
  async setAuthSession(session) {
53
61
  const state = await this.read();
@@ -133,4 +141,4 @@ var LocalStateStore = class {
133
141
  }
134
142
  };
135
143
  //#endregion
136
- export { LocalStateStore };
144
+ export { LocalStateStore, resolveLocalStateFilePath };
@@ -5,8 +5,12 @@ var MockApi = class MockApi {
5
5
  constructor(data) {
6
6
  this.data = data;
7
7
  }
8
- static async load(fixturePath) {
9
- const raw = await readFile(fixturePath, "utf8");
8
+ static async load(fixturePath, signal) {
9
+ signal?.throwIfAborted();
10
+ const raw = await readFile(fixturePath, {
11
+ encoding: "utf8",
12
+ signal
13
+ });
10
14
  return new MockApi(JSON.parse(raw));
11
15
  }
12
16
  listProviders() {
@@ -52,6 +56,81 @@ var MockApi = class MockApi {
52
56
  getDeployment(deploymentId) {
53
57
  return this.data.deployments.find((deployment) => deployment.id === deploymentId);
54
58
  }
59
+ listDatabasesForProject(projectId, branchName) {
60
+ return (this.data.databases ?? []).filter((database) => database.projectId === projectId && (!branchName || database.branchName === branchName));
61
+ }
62
+ getDatabase(databaseId) {
63
+ return (this.data.databases ?? []).find((database) => database.id === databaseId);
64
+ }
65
+ createDatabase(input) {
66
+ this.data.databases ??= [];
67
+ this.data.databaseConnections ??= [];
68
+ const database = {
69
+ id: `db_${this.data.databases.length + 1e3}`,
70
+ projectId: input.projectId,
71
+ branchId: input.branchName ? this.getBranchForProject(input.projectId, input.branchName)?.id ?? null : null,
72
+ branchName: input.branchName ?? null,
73
+ name: input.name,
74
+ region: input.region ?? null,
75
+ status: "ready",
76
+ isDefault: false,
77
+ createdAt: "2026-06-09T00:00:00.000Z"
78
+ };
79
+ const connectionString = `postgresql://${database.id}.example.prisma.io/postgres`;
80
+ const connection = {
81
+ id: `conn_${this.data.databaseConnections.length + 1e3}`,
82
+ databaseId: database.id,
83
+ name: "primary",
84
+ createdAt: "2026-06-09T00:00:00.000Z",
85
+ connectionString
86
+ };
87
+ this.data.databases.push(database);
88
+ this.data.databaseConnections.push(connection);
89
+ return {
90
+ database,
91
+ connection,
92
+ connectionString
93
+ };
94
+ }
95
+ removeDatabase(databaseId) {
96
+ this.data.databases ??= [];
97
+ this.data.databaseConnections ??= [];
98
+ const database = this.getDatabase(databaseId);
99
+ if (!database) return;
100
+ this.data.databases = this.data.databases.filter((candidate) => candidate.id !== databaseId);
101
+ this.data.databaseConnections = this.data.databaseConnections.filter((connection) => connection.databaseId !== databaseId);
102
+ return database;
103
+ }
104
+ listDatabaseConnections(databaseId) {
105
+ return (this.data.databaseConnections ?? []).filter((connection) => connection.databaseId === databaseId);
106
+ }
107
+ getDatabaseConnection(connectionId) {
108
+ return (this.data.databaseConnections ?? []).find((connection) => connection.id === connectionId);
109
+ }
110
+ createDatabaseConnection(input) {
111
+ if (!this.getDatabase(input.databaseId)) return;
112
+ this.data.databaseConnections ??= [];
113
+ const connectionString = `postgresql://${input.databaseId}-${this.data.databaseConnections.length + 1}.example.prisma.io/postgres`;
114
+ const connection = {
115
+ id: `conn_${this.data.databaseConnections.length + 1e3}`,
116
+ databaseId: input.databaseId,
117
+ name: input.name,
118
+ createdAt: "2026-06-09T00:00:00.000Z",
119
+ connectionString
120
+ };
121
+ this.data.databaseConnections.push(connection);
122
+ return {
123
+ connection,
124
+ connectionString
125
+ };
126
+ }
127
+ removeDatabaseConnection(connectionId) {
128
+ this.data.databaseConnections ??= [];
129
+ const connection = this.getDatabaseConnection(connectionId);
130
+ if (!connection) return;
131
+ this.data.databaseConnections = this.data.databaseConnections.filter((candidate) => candidate.id !== connectionId);
132
+ return connection;
133
+ }
55
134
  };
56
135
  //#endregion
57
136
  export { MockApi };
@@ -20,37 +20,60 @@ function findLatestValidTokens(allCredentials) {
20
20
  function tokensEqual(a, b) {
21
21
  return a?.workspaceId === b?.workspaceId && a?.accessToken === b?.accessToken && a?.refreshToken === b?.refreshToken;
22
22
  }
23
- function sleep(ms) {
24
- return new Promise((resolve) => setTimeout(resolve, ms));
23
+ function sleep(ms, signal) {
24
+ signal?.throwIfAborted();
25
+ return new Promise((resolve, reject) => {
26
+ const onAbort = () => {
27
+ clearTimeout(timeout);
28
+ reject(signal?.reason);
29
+ };
30
+ const timeout = setTimeout(() => {
31
+ signal?.removeEventListener("abort", onAbort);
32
+ resolve();
33
+ }, ms);
34
+ signal?.addEventListener("abort", onAbort, { once: true });
35
+ });
25
36
  }
26
37
  var FileTokenStorage = class {
27
38
  credentialsStore;
28
39
  lockFilePath;
29
- constructor(env = process.env) {
40
+ constructor(env = process.env, signal) {
41
+ this.signal = signal;
30
42
  const authFilePath = getAuthFilePath(env);
31
43
  this.credentialsStore = new CredentialsStore(authFilePath);
32
44
  this.lockFilePath = `${authFilePath}.lock`;
33
45
  }
34
46
  async getTokens() {
47
+ this.signal?.throwIfAborted();
35
48
  try {
36
- return findLatestValidTokens(await this.credentialsStore.getCredentials());
37
- } catch {
49
+ const all = await this.credentialsStore.getCredentials();
50
+ this.signal?.throwIfAborted();
51
+ return findLatestValidTokens(all);
52
+ } catch (error) {
53
+ if (this.signal?.aborted) throw this.signal.reason;
38
54
  return null;
39
55
  }
40
56
  }
41
57
  async setTokens(tokens) {
58
+ this.signal?.throwIfAborted();
42
59
  await this.credentialsStore.storeCredentials({
43
60
  workspaceId: tokens.workspaceId,
44
61
  token: tokens.accessToken,
45
62
  refreshToken: tokens.refreshToken
46
63
  });
64
+ this.signal?.throwIfAborted();
47
65
  }
48
66
  async clearTokens() {
49
- const tokens = findLatestValidTokens(await this.credentialsStore.getCredentials());
67
+ this.signal?.throwIfAborted();
68
+ const all = await this.credentialsStore.getCredentials();
69
+ this.signal?.throwIfAborted();
70
+ const tokens = findLatestValidTokens(all);
50
71
  if (!tokens) return;
51
72
  await this.credentialsStore.deleteCredentials(tokens.workspaceId);
73
+ this.signal?.throwIfAborted();
52
74
  }
53
75
  async clearTokensIfCurrent(tokens) {
76
+ this.signal?.throwIfAborted();
54
77
  if (!tokensEqual(await this.getTokens(), tokens)) return;
55
78
  await this.clearTokens();
56
79
  }
@@ -64,34 +87,52 @@ var FileTokenStorage = class {
64
87
  }
65
88
  async acquireRefreshLock() {
66
89
  const lockId = randomUUID();
90
+ this.signal?.throwIfAborted();
67
91
  await fs.mkdir(path.dirname(this.lockFilePath), { recursive: true });
68
- while (true) try {
69
- const handle = await fs.open(this.lockFilePath, "wx");
92
+ while (true) {
93
+ this.signal?.throwIfAborted();
94
+ let lockFileCreated = false;
70
95
  try {
71
- await handle.writeFile(lockId, "utf8");
72
- } finally {
73
- await handle.close();
74
- }
75
- return lockId;
76
- } catch (error) {
77
- if (error.code !== "EEXIST") throw error;
78
- const staleLockId = await this.getStaleRefreshLockId();
79
- if (staleLockId) {
80
- await this.releaseRefreshLock(staleLockId);
81
- continue;
96
+ const handle = await fs.open(this.lockFilePath, "wx");
97
+ lockFileCreated = true;
98
+ try {
99
+ this.signal?.throwIfAborted();
100
+ await handle.writeFile(lockId, { encoding: "utf8" });
101
+ this.signal?.throwIfAborted();
102
+ } finally {
103
+ await handle.close();
104
+ }
105
+ return lockId;
106
+ } catch (error) {
107
+ if (lockFileCreated) await fs.unlink(this.lockFilePath).catch(() => void 0);
108
+ if (error.code !== "EEXIST") throw error;
109
+ const staleLockId = await this.getStaleRefreshLockId();
110
+ if (staleLockId) {
111
+ await this.releaseRefreshLock(staleLockId);
112
+ continue;
113
+ }
114
+ await sleep(100, this.signal);
82
115
  }
83
- await sleep(100);
84
116
  }
85
117
  }
86
118
  async getStaleRefreshLockId() {
87
- const lockId = await fs.readFile(this.lockFilePath, "utf8").catch(() => null);
119
+ this.signal?.throwIfAborted();
120
+ const lockId = await fs.readFile(this.lockFilePath, {
121
+ encoding: "utf8",
122
+ signal: this.signal
123
+ }).catch((error) => {
124
+ if (this.signal?.aborted) throw error;
125
+ return null;
126
+ });
88
127
  if (lockId === null) return null;
128
+ this.signal?.throwIfAborted();
89
129
  const stats = await fs.stat(this.lockFilePath).catch(() => null);
130
+ this.signal?.throwIfAborted();
90
131
  if (!stats) return null;
91
132
  return Date.now() - stats.mtimeMs > 3e4 ? lockId : null;
92
133
  }
93
134
  async releaseRefreshLock(lockId) {
94
- if (await fs.readFile(this.lockFilePath, "utf8").catch(() => null) !== lockId) return;
135
+ if (await fs.readFile(this.lockFilePath, { encoding: "utf8" }).catch(() => null) !== lockId) return;
95
136
  await fs.unlink(this.lockFilePath).catch(() => {});
96
137
  }
97
138
  };
package/dist/cli.js CHANGED
@@ -1,9 +1,24 @@
1
1
  #!/usr/bin/env node
2
+ import { runUpdateDiscoveryWorker } from "./shell/update-check.js";
2
3
  import { runCli } from "./cli2.js";
3
4
  import process from "node:process";
4
5
  //#region src/bin.ts
5
- runCli().then((exitCode) => {
6
- process.exitCode = exitCode;
6
+ if (process.env.PRISMA_CLI_RUN_UPDATE_CHECK_WORKER === "1") runUpdateDiscoveryWorker().then(() => {
7
+ process.exitCode = 0;
7
8
  });
9
+ else {
10
+ const controller = new AbortController();
11
+ const abortCli = () => {
12
+ if (!controller.signal.aborted) controller.abort(new DOMException("Command canceled", "AbortError"));
13
+ };
14
+ process.once("SIGINT", abortCli);
15
+ process.once("SIGTERM", abortCli);
16
+ runCli({ signal: controller.signal }).then((exitCode) => {
17
+ process.exitCode = exitCode;
18
+ }).finally(() => {
19
+ process.off("SIGINT", abortCli);
20
+ process.off("SIGTERM", abortCli);
21
+ });
22
+ }
8
23
  //#endregion
9
24
  export {};
package/dist/cli2.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CliError } from "./shell/errors.js";
2
2
  import { createShellUi } from "./shell/ui.js";
3
- import { writeHumanError, writeJsonError, writeJsonSuccess } from "./shell/output.js";
3
+ import { formatUnexpectedError, writeHumanError, writeJsonError, writeJsonSuccess } from "./shell/output.js";
4
4
  import { attachCommandDescriptor } from "./shell/command-meta.js";
5
5
  import { addCompactGlobalFlags } from "./shell/global-flags.js";
6
6
  import { configureRuntimeCommand, createCommandContext } from "./shell/runtime.js";
@@ -8,11 +8,13 @@ import "./shell/prompt.js";
8
8
  import { createAppCommand } from "./commands/app/index.js";
9
9
  import { createAuthCommand } from "./commands/auth/index.js";
10
10
  import { createBranchCommand } from "./commands/branch/index.js";
11
+ import { createDatabaseCommand } from "./commands/database/index.js";
11
12
  import { createGitCommand } from "./commands/git/index.js";
12
13
  import { createProjectCommand } from "./commands/project/index.js";
13
14
  import { getCliName, getCliVersion } from "./lib/version.js";
14
15
  import { runVersion } from "./controllers/version.js";
15
16
  import { createVersionCommand } from "./commands/version/index.js";
17
+ import { maybeWriteCachedUpdateNotification } from "./shell/update-check.js";
16
18
  import process from "node:process";
17
19
  import { Command, CommanderError, Option } from "commander";
18
20
  //#region src/cli.ts
@@ -21,6 +23,7 @@ async function runCli(options = {}) {
21
23
  const program = createProgram(runtime);
22
24
  process.exitCode = 0;
23
25
  try {
26
+ await maybeWriteCachedUpdateNotification(runtime);
24
27
  if (runtime.argv.includes("--version")) return await handleVersionFlag(runtime);
25
28
  const bareHelpCommand = resolveBareHelpCommand(program, runtime.argv);
26
29
  if (bareHelpCommand) {
@@ -31,8 +34,7 @@ async function runCli(options = {}) {
31
34
  return process.exitCode ?? 0;
32
35
  } catch (error) {
33
36
  if (error instanceof CommanderError) return error.code === "commander.helpDisplayed" ? 0 : 2;
34
- const message = error instanceof Error ? error.stack ?? error.message : String(error);
35
- runtime.stderr.write(`${message}\n`);
37
+ runtime.stderr.write(formatUnexpectedError(error, runtime.argv.includes("--trace")));
36
38
  return 1;
37
39
  } finally {
38
40
  runtime.stdin;
@@ -48,6 +50,7 @@ function createProgram(runtime) {
48
50
  program.addCommand(createProjectCommand(runtime));
49
51
  program.addCommand(createGitCommand(runtime));
50
52
  program.addCommand(createBranchCommand(runtime));
53
+ program.addCommand(createDatabaseCommand(runtime));
51
54
  program.addCommand(createAppCommand(runtime));
52
55
  return program;
53
56
  }
@@ -104,6 +107,7 @@ function resolveRuntime(options) {
104
107
  argv: options.argv ?? process.argv.slice(2),
105
108
  cwd: options.cwd ?? process.env.INIT_CWD ?? process.cwd(),
106
109
  env: options.env ?? process.env,
110
+ signal: options.signal ?? new AbortController().signal,
107
111
  stdin: options.stdin ?? process.stdin,
108
112
  stdout: options.stdout ?? process.stdout,
109
113
  stderr: options.stderr ?? process.stderr,
@@ -1,3 +1,4 @@
1
+ import { usageError } from "../../shell/errors.js";
1
2
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
3
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
4
  import { configureRuntimeCommand } from "../../shell/runtime.js";
@@ -64,7 +65,7 @@ function createDeployCommand(runtime) {
64
65
  "hono",
65
66
  "tanstack-start",
66
67
  "bun"
67
- ])).addOption(new Option("--entry <path>", "Entrypoint path for Bun deploys")).addOption(new Option("--http-port <port>", "HTTP port override for the deployed app")).addOption(new Option("--env <name=value>", "Environment variable").argParser(collectRepeatableValues));
68
+ ])).addOption(new Option("--entry <path>", "Entrypoint path for Bun deploys")).addOption(new Option("--http-port <port>", "HTTP port override for the deployed app")).addOption(new Option("--env <name=value|file>", "Environment variable assignment or dotenv file").argParser(collectRepeatableValues)).addOption(new Option("--db", "Create and wire a Prisma Postgres database for this deploy target")).addOption(new Option("--no-db", "Skip database setup")).addOption(new Option("--prod", "Confirm intent to deploy to production"));
68
69
  addGlobalFlags(command);
69
70
  command.action(async (options) => {
70
71
  const appName = options.app;
@@ -75,21 +76,32 @@ function createDeployCommand(runtime) {
75
76
  const envAssignments = options.env;
76
77
  const projectRef = options.project;
77
78
  const createProjectName = options.createProject;
78
- await runCommand(runtime, "app.deploy", options, (context) => runAppDeploy(context, appName, {
79
- projectRef,
80
- createProjectName,
81
- branchName,
82
- entrypoint: entry,
83
- framework,
84
- httpPort,
85
- envAssignments
86
- }), {
79
+ const prod = options.prod;
80
+ const db = options.db;
81
+ const hasDbConflict = hasFlag(runtime.argv, "--db") && hasFlag(runtime.argv, "--no-db");
82
+ await runCommand(runtime, "app.deploy", options, (context) => {
83
+ if (hasDbConflict) throw usageError("app deploy accepts either --db or --no-db", "--db requests database setup, while --no-db disables it.", "Pass exactly one database setup flag.", ["prisma-cli app deploy --db", "prisma-cli app deploy --no-db"], "app");
84
+ return runAppDeploy(context, appName, {
85
+ projectRef,
86
+ createProjectName,
87
+ branchName,
88
+ entrypoint: entry,
89
+ framework,
90
+ httpPort,
91
+ envAssignments,
92
+ prod: prod === true,
93
+ db
94
+ });
95
+ }, {
87
96
  renderHuman: (context, descriptor, result) => renderAppDeploy(context, descriptor, result),
88
97
  renderJson: (result) => serializeAppDeploy(result)
89
98
  });
90
99
  });
91
100
  return command;
92
101
  }
102
+ function hasFlag(argv, flag) {
103
+ return argv.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
104
+ }
93
105
  function createShowCommand(runtime) {
94
106
  const command = attachCommandDescriptor(configureRuntimeCommand(new Command("show"), runtime), "app.show");
95
107
  command.addOption(new Option("--app <name>", "App name")).addOption(new Option("--project <id-or-name>", "Project id or name"));
@@ -2,16 +2,14 @@ import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
4
  import { runCommand } from "../../shell/command-runner.js";
5
- import { runBranchList, runBranchShow, runBranchUse } from "../../controllers/branch.js";
6
- import { renderBranchList, renderBranchShow, renderBranchUse, serializeBranchList, serializeBranchShow } from "../../presenters/branch.js";
5
+ import { runBranchList } from "../../controllers/branch.js";
6
+ import { renderBranchList, serializeBranchList } from "../../presenters/branch.js";
7
7
  import { Command } from "commander";
8
8
  //#region src/commands/branch/index.ts
9
9
  function createBranchCommand(runtime) {
10
10
  const branch = attachCommandDescriptor(configureRuntimeCommand(new Command("branch"), runtime), "branch");
11
11
  addCompactGlobalFlags(branch);
12
12
  branch.addCommand(createBranchListCommand(runtime));
13
- branch.addCommand(createBranchShowCommand(runtime));
14
- branch.addCommand(createBranchUseCommand(runtime));
15
13
  return branch;
16
14
  }
17
15
  function createBranchListCommand(runtime) {
@@ -25,28 +23,5 @@ function createBranchListCommand(runtime) {
25
23
  });
26
24
  return command;
27
25
  }
28
- function createBranchShowCommand(runtime) {
29
- const command = attachCommandDescriptor(configureRuntimeCommand(new Command("show"), runtime), "branch.show");
30
- addGlobalFlags(command);
31
- command.action(async (options) => {
32
- await runCommand(runtime, "branch.show", options, (context) => runBranchShow(context), {
33
- renderHuman: (context, descriptor, result) => renderBranchShow(context, descriptor, result),
34
- renderJson: (result) => serializeBranchShow(result)
35
- });
36
- });
37
- return command;
38
- }
39
- function createBranchUseCommand(runtime) {
40
- const command = attachCommandDescriptor(configureRuntimeCommand(new Command("use"), runtime), "branch.use");
41
- command.argument("[name]", "Branch name");
42
- addGlobalFlags(command);
43
- command.action(async (branchName, options) => {
44
- await runCommand(runtime, "branch.use", options, (context) => runBranchUse(context, branchName), {
45
- renderHuman: (context, descriptor, result) => renderBranchUse(context, descriptor, result),
46
- renderJson: (result) => serializeBranchShow(result)
47
- });
48
- });
49
- return command;
50
- }
51
26
  //#endregion
52
27
  export { createBranchCommand };