@prisma/cli 3.0.0-beta.8 → 3.0.0-beta.9

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.
@@ -56,6 +56,81 @@ var MockApi = class MockApi {
56
56
  getDeployment(deploymentId) {
57
57
  return this.data.deployments.find((deployment) => deployment.id === deploymentId);
58
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
+ }
59
134
  };
60
135
  //#endregion
61
136
  export { MockApi };
package/dist/cli2.js CHANGED
@@ -8,6 +8,7 @@ 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";
@@ -49,6 +50,7 @@ function createProgram(runtime) {
49
50
  program.addCommand(createProjectCommand(runtime));
50
51
  program.addCommand(createGitCommand(runtime));
51
52
  program.addCommand(createBranchCommand(runtime));
53
+ program.addCommand(createDatabaseCommand(runtime));
52
54
  program.addCommand(createAppCommand(runtime));
53
55
  return program;
54
56
  }
@@ -0,0 +1,159 @@
1
+ import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
+ import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
+ import { configureRuntimeCommand } from "../../shell/runtime.js";
4
+ import { runCommand } from "../../shell/command-runner.js";
5
+ import { runDatabaseConnectionCreate, runDatabaseConnectionList, runDatabaseConnectionRemove, runDatabaseCreate, runDatabaseList, runDatabaseRemove, runDatabaseShow } from "../../controllers/database.js";
6
+ import { renderDatabaseConnectionCreate, renderDatabaseConnectionCreateStdout, renderDatabaseConnectionList, renderDatabaseConnectionRemove, renderDatabaseCreate, renderDatabaseCreateStdout, renderDatabaseList, renderDatabaseRemove, renderDatabaseShow, serializeDatabaseConnectionCreate, serializeDatabaseConnectionList, serializeDatabaseConnectionRemove, serializeDatabaseCreate, serializeDatabaseList, serializeDatabaseRemove, serializeDatabaseShow } from "../../presenters/database.js";
7
+ import { Command, Option } from "commander";
8
+ //#region src/commands/database/index.ts
9
+ function createDatabaseCommand(runtime) {
10
+ const database = attachCommandDescriptor(configureRuntimeCommand(new Command("database"), runtime), "database");
11
+ addCompactGlobalFlags(database);
12
+ database.addCommand(createDatabaseListCommand(runtime));
13
+ database.addCommand(createDatabaseShowCommand(runtime));
14
+ database.addCommand(createDatabaseCreateCommand(runtime));
15
+ database.addCommand(createDatabaseRemoveCommand(runtime));
16
+ database.addCommand(createDatabaseConnectionCommand(runtime));
17
+ return database;
18
+ }
19
+ function addProjectAndBranchOptions(command) {
20
+ return command.addOption(new Option("--project <id-or-name>", "Project id or name")).addOption(new Option("--branch <git-name>", "Branch git name"));
21
+ }
22
+ function createDatabaseListCommand(runtime) {
23
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("list"), runtime), "database.list");
24
+ addProjectAndBranchOptions(command);
25
+ addGlobalFlags(command);
26
+ command.action(async (options) => {
27
+ const projectRef = options.project;
28
+ const branchName = options.branch;
29
+ await runCommand(runtime, "database.list", options, (context) => runDatabaseList(context, {
30
+ projectRef,
31
+ branchName
32
+ }), {
33
+ renderHuman: (context, descriptor, result) => renderDatabaseList(context, descriptor, result),
34
+ renderJson: (result) => serializeDatabaseList(result)
35
+ });
36
+ });
37
+ return command;
38
+ }
39
+ function createDatabaseShowCommand(runtime) {
40
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("show"), runtime), "database.show");
41
+ command.argument("<database>", "Database id or name");
42
+ addProjectAndBranchOptions(command);
43
+ addGlobalFlags(command);
44
+ command.action(async (databaseRef, options) => {
45
+ const projectRef = options.project;
46
+ const branchName = options.branch;
47
+ await runCommand(runtime, "database.show", options, (context) => runDatabaseShow(context, databaseRef, {
48
+ projectRef,
49
+ branchName
50
+ }), {
51
+ renderHuman: (context, descriptor, result) => renderDatabaseShow(context, descriptor, result),
52
+ renderJson: (result) => serializeDatabaseShow(result)
53
+ });
54
+ });
55
+ return command;
56
+ }
57
+ function createDatabaseCreateCommand(runtime) {
58
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("create"), runtime), "database.create");
59
+ command.argument("<name>", "Database name").addOption(new Option("--region <region>", "Prisma Postgres region id"));
60
+ addProjectAndBranchOptions(command);
61
+ addGlobalFlags(command);
62
+ command.action(async (name, options) => {
63
+ const projectRef = options.project;
64
+ const branchName = options.branch;
65
+ const region = options.region;
66
+ await runCommand(runtime, "database.create", options, (context) => runDatabaseCreate(context, name, {
67
+ projectRef,
68
+ branchName,
69
+ region
70
+ }), {
71
+ renderStdout: (context, descriptor, result) => renderDatabaseCreateStdout(context, descriptor, result),
72
+ renderHuman: (context, descriptor, result) => renderDatabaseCreate(context, descriptor, result),
73
+ renderJson: (result) => serializeDatabaseCreate(result)
74
+ });
75
+ });
76
+ return command;
77
+ }
78
+ function createDatabaseRemoveCommand(runtime) {
79
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("remove"), runtime), "database.remove");
80
+ command.argument("<database>", "Database id or name").addOption(new Option("--confirm <database-id>", "Exact database id required to remove"));
81
+ addProjectAndBranchOptions(command);
82
+ addGlobalFlags(command);
83
+ command.action(async (databaseRef, options) => {
84
+ const projectRef = options.project;
85
+ const branchName = options.branch;
86
+ const confirm = options.confirm;
87
+ await runCommand(runtime, "database.remove", options, (context) => runDatabaseRemove(context, databaseRef, {
88
+ projectRef,
89
+ branchName,
90
+ confirm
91
+ }), {
92
+ renderHuman: (context, descriptor, result) => renderDatabaseRemove(context, descriptor, result),
93
+ renderJson: (result) => serializeDatabaseRemove(result)
94
+ });
95
+ });
96
+ return command;
97
+ }
98
+ function createDatabaseConnectionCommand(runtime) {
99
+ const connection = attachCommandDescriptor(configureRuntimeCommand(new Command("connection"), runtime), "database.connection");
100
+ addCompactGlobalFlags(connection);
101
+ connection.addCommand(createDatabaseConnectionListCommand(runtime));
102
+ connection.addCommand(createDatabaseConnectionCreateCommand(runtime));
103
+ connection.addCommand(createDatabaseConnectionRemoveCommand(runtime));
104
+ return connection;
105
+ }
106
+ function createDatabaseConnectionListCommand(runtime) {
107
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("list"), runtime), "database.connection.list");
108
+ command.argument("<database>", "Database id or name");
109
+ addProjectAndBranchOptions(command);
110
+ addGlobalFlags(command);
111
+ command.action(async (databaseRef, options) => {
112
+ const projectRef = options.project;
113
+ const branchName = options.branch;
114
+ await runCommand(runtime, "database.connection.list", options, (context) => runDatabaseConnectionList(context, databaseRef, {
115
+ projectRef,
116
+ branchName
117
+ }), {
118
+ renderHuman: (context, descriptor, result) => renderDatabaseConnectionList(context, descriptor, result),
119
+ renderJson: (result) => serializeDatabaseConnectionList(result)
120
+ });
121
+ });
122
+ return command;
123
+ }
124
+ function createDatabaseConnectionCreateCommand(runtime) {
125
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("create"), runtime), "database.connection.create");
126
+ command.argument("<database>", "Database id or name").addOption(new Option("--name <name>", "Connection name"));
127
+ addProjectAndBranchOptions(command);
128
+ addGlobalFlags(command);
129
+ command.action(async (databaseRef, options) => {
130
+ const projectRef = options.project;
131
+ const branchName = options.branch;
132
+ const name = options.name;
133
+ await runCommand(runtime, "database.connection.create", options, (context) => runDatabaseConnectionCreate(context, databaseRef, {
134
+ projectRef,
135
+ branchName,
136
+ name
137
+ }), {
138
+ renderStdout: (context, descriptor, result) => renderDatabaseConnectionCreateStdout(context, descriptor, result),
139
+ renderHuman: (context, descriptor, result) => renderDatabaseConnectionCreate(context, descriptor, result),
140
+ renderJson: (result) => serializeDatabaseConnectionCreate(result)
141
+ });
142
+ });
143
+ return command;
144
+ }
145
+ function createDatabaseConnectionRemoveCommand(runtime) {
146
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("remove"), runtime), "database.connection.remove");
147
+ command.argument("<connection>", "Connection id").addOption(new Option("--confirm <connection-id>", "Exact connection id required to remove"));
148
+ addGlobalFlags(command);
149
+ command.action(async (connectionRef, options) => {
150
+ const confirm = options.confirm;
151
+ await runCommand(runtime, "database.connection.remove", options, (context) => runDatabaseConnectionRemove(context, connectionRef, { confirm }), {
152
+ renderHuman: (context, descriptor, result) => renderDatabaseConnectionRemove(context, descriptor, result),
153
+ renderJson: (result) => serializeDatabaseConnectionRemove(result)
154
+ });
155
+ });
156
+ return command;
157
+ }
158
+ //#endregion
159
+ export { createDatabaseCommand };
@@ -31,6 +31,7 @@ import { listRealWorkspaceProjects } from "./project.js";
31
31
  import { access, readFile } from "node:fs/promises";
32
32
  import path from "node:path";
33
33
  import open from "open";
34
+ import { Result, matchError } from "better-result";
34
35
  //#region src/controllers/app.ts
35
36
  const DEPLOY_FRAMEWORKS = [
36
37
  "nextjs",
@@ -112,9 +113,9 @@ async function runAppDeploy(context, appName, options) {
112
113
  createProjectName: options?.createProjectName,
113
114
  envProjectId
114
115
  });
115
- const skipLocalPin = Boolean(envProjectId || options?.projectRef || options?.createProjectName);
116
- const localPin = skipLocalPin ? { kind: "missing" } : await readLocalResolutionPin(context.runtime.cwd, context.runtime.signal);
117
- if (!skipLocalPin && localPin.kind === "invalid") throw localResolutionPinStaleError();
116
+ const localPinReadResult = Boolean(envProjectId || options?.projectRef || options?.createProjectName) ? Result.ok({ kind: "missing" }) : await readLocalResolutionPin(context.runtime.cwd, context.runtime.signal);
117
+ if (localPinReadResult.isErr()) throw localPinReadErrorToDeployError(localPinReadResult.error);
118
+ const localPin = localPinReadResult.value;
118
119
  const branch = await resolveDeployBranch(context, options?.branchName);
119
120
  if (options?.httpPort) parseDeployHttpPort(options.httpPort);
120
121
  assertSupportedEntrypointForRequestedDeployShape({
@@ -1976,6 +1977,18 @@ function localResolutionPinStaleError() {
1976
1977
  ]
1977
1978
  });
1978
1979
  }
1980
+ function localPinReadErrorToDeployError(error) {
1981
+ return matchError(error, {
1982
+ LocalResolutionPinInvalidJsonError: () => localResolutionPinStaleError(),
1983
+ LocalResolutionPinInvalidShapeError: () => localResolutionPinStaleError(),
1984
+ LocalResolutionPinReadAbortedError: (error) => {
1985
+ throw error;
1986
+ },
1987
+ UnhandledException: (error) => {
1988
+ throw error;
1989
+ }
1990
+ });
1991
+ }
1979
1992
  function readDeployEnvOverride(context, name) {
1980
1993
  const value = context.runtime.env[name]?.trim();
1981
1994
  return value ? value : void 0;
@@ -0,0 +1,316 @@
1
+ import { CliError, authRequiredError, usageError, workspaceRequiredError } from "../shell/errors.js";
2
+ import { requireComputeAuth } from "../lib/auth/guard.js";
3
+ import { resolveProjectTarget } from "../lib/project/resolution.js";
4
+ import { requireAuthenticatedAuthState } from "./auth.js";
5
+ import { listFixtureWorkspaceProjects, listRealWorkspaceProjects } from "./project.js";
6
+ import { createManagementDatabaseProvider, normalizeConnection, normalizeDatabase } from "../lib/database/provider.js";
7
+ import { randomBytes } from "node:crypto";
8
+ //#region src/controllers/database.ts
9
+ function isRealMode(context) {
10
+ return !context.runtime.fixturePath && !context.runtime.env.PRISMA_CLI_MOCK_FIXTURE_PATH;
11
+ }
12
+ async function runDatabaseList(context, flags) {
13
+ const { provider, target } = await requireDatabaseContext(context, flags, "database list");
14
+ const databases = sortDatabases(await provider.listDatabases({
15
+ projectId: target.project.id,
16
+ branchName: flags.branchName,
17
+ signal: context.runtime.signal
18
+ }));
19
+ return {
20
+ command: "database.list",
21
+ result: {
22
+ projectId: target.project.id,
23
+ projectName: target.project.name,
24
+ branchName: flags.branchName ?? null,
25
+ verboseContext: target,
26
+ databases
27
+ },
28
+ warnings: [],
29
+ nextSteps: []
30
+ };
31
+ }
32
+ async function runDatabaseShow(context, databaseRef, flags) {
33
+ const { provider, target } = await requireDatabaseContext(context, flags, "database show");
34
+ const database = await resolveDatabase(provider, target, databaseRef, flags.branchName, context.runtime.signal);
35
+ const connections = await provider.listConnections(database.id, { signal: context.runtime.signal });
36
+ return {
37
+ command: "database.show",
38
+ result: {
39
+ projectId: target.project.id,
40
+ projectName: target.project.name,
41
+ verboseContext: target,
42
+ database,
43
+ connections
44
+ },
45
+ warnings: [],
46
+ nextSteps: []
47
+ };
48
+ }
49
+ async function runDatabaseCreate(context, name, flags) {
50
+ const databaseName = name.trim();
51
+ if (!databaseName) throw usageError("Database name required", "Database create needs a non-empty name.", "Pass a database name.", ["prisma-cli database create <name>"], "database");
52
+ const { provider, target } = await requireDatabaseContext(context, flags, "database create");
53
+ const created = await provider.createDatabase({
54
+ projectId: target.project.id,
55
+ name: databaseName,
56
+ branchName: flags.branchName,
57
+ region: flags.region,
58
+ signal: context.runtime.signal
59
+ });
60
+ return {
61
+ command: "database.create",
62
+ result: {
63
+ projectId: target.project.id,
64
+ projectName: target.project.name,
65
+ verboseContext: target,
66
+ database: ensureProjectId(created.database, target.project.id),
67
+ connection: created.connection,
68
+ connectionString: created.connectionString
69
+ },
70
+ warnings: [],
71
+ nextSteps: []
72
+ };
73
+ }
74
+ async function runDatabaseRemove(context, databaseRef, flags) {
75
+ const { provider, target } = await requireDatabaseContext(context, flags, "database remove");
76
+ const database = await resolveDatabase(provider, target, databaseRef, flags.branchName, context.runtime.signal);
77
+ requireExactConfirmation({
78
+ resourceName: "database",
79
+ commandName: "database remove",
80
+ id: database.id,
81
+ confirm: flags.confirm
82
+ });
83
+ await provider.removeDatabase(database.id, { signal: context.runtime.signal });
84
+ return {
85
+ command: "database.remove",
86
+ result: {
87
+ projectId: target.project.id,
88
+ projectName: target.project.name,
89
+ verboseContext: target,
90
+ database
91
+ },
92
+ warnings: [],
93
+ nextSteps: []
94
+ };
95
+ }
96
+ async function runDatabaseConnectionList(context, databaseRef, flags) {
97
+ const { provider, target } = await requireDatabaseContext(context, flags, "database connection list");
98
+ const database = await resolveDatabase(provider, target, databaseRef, flags.branchName, context.runtime.signal);
99
+ const connections = await provider.listConnections(database.id, { signal: context.runtime.signal });
100
+ return {
101
+ command: "database.connection.list",
102
+ result: {
103
+ projectId: target.project.id,
104
+ projectName: target.project.name,
105
+ verboseContext: target,
106
+ database,
107
+ connections
108
+ },
109
+ warnings: [],
110
+ nextSteps: []
111
+ };
112
+ }
113
+ async function runDatabaseConnectionCreate(context, databaseRef, flags) {
114
+ const { provider, target } = await requireDatabaseContext(context, flags, "database connection create");
115
+ const database = await resolveDatabase(provider, target, databaseRef, flags.branchName, context.runtime.signal);
116
+ const created = await provider.createConnection({
117
+ databaseId: database.id,
118
+ name: flags.name?.trim() || defaultConnectionName(),
119
+ signal: context.runtime.signal
120
+ });
121
+ return {
122
+ command: "database.connection.create",
123
+ result: {
124
+ projectId: target.project.id,
125
+ projectName: target.project.name,
126
+ verboseContext: target,
127
+ database,
128
+ connection: created.connection,
129
+ connectionString: created.connectionString
130
+ },
131
+ warnings: [],
132
+ nextSteps: []
133
+ };
134
+ }
135
+ async function runDatabaseConnectionRemove(context, connectionRef, flags) {
136
+ const connectionId = connectionRef.trim();
137
+ if (!connectionId) throw usageError("Connection id required", "Database connection removal needs a connection id.", "Pass the connection id to remove.", ["prisma-cli database connection remove <connection-id> --confirm <connection-id>"], "database");
138
+ requireExactConfirmation({
139
+ resourceName: "database connection",
140
+ commandName: "database connection remove",
141
+ id: connectionId,
142
+ confirm: flags.confirm
143
+ });
144
+ await (await requireDatabaseProviderOnly(context)).removeConnection(connectionId, { signal: context.runtime.signal });
145
+ return {
146
+ command: "database.connection.remove",
147
+ result: { connection: { id: connectionId } },
148
+ warnings: [],
149
+ nextSteps: []
150
+ };
151
+ }
152
+ async function requireDatabaseContext(context, flags, commandName) {
153
+ const workspace = (await requireAuthenticatedAuthState(context)).workspace;
154
+ if (!workspace) throw workspaceRequiredError();
155
+ if (isRealMode(context)) {
156
+ const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
157
+ if (!client) throw authRequiredError();
158
+ const target = await resolveProjectTarget({
159
+ context,
160
+ workspace,
161
+ explicitProject: flags.projectRef,
162
+ listProjects: () => listRealWorkspaceProjects(client, workspace, context.runtime.signal),
163
+ commandName
164
+ });
165
+ return {
166
+ provider: createManagementDatabaseProvider(client),
167
+ target
168
+ };
169
+ }
170
+ const target = await resolveProjectTarget({
171
+ context,
172
+ workspace,
173
+ explicitProject: flags.projectRef,
174
+ listProjects: async () => listFixtureWorkspaceProjects(context, workspace),
175
+ commandName
176
+ });
177
+ return {
178
+ provider: createFixtureDatabaseProvider(context),
179
+ target
180
+ };
181
+ }
182
+ async function requireDatabaseProviderOnly(context) {
183
+ await requireAuthenticatedAuthState(context);
184
+ if (isRealMode(context)) {
185
+ const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
186
+ if (!client) throw authRequiredError();
187
+ return createManagementDatabaseProvider(client);
188
+ }
189
+ return createFixtureDatabaseProvider(context);
190
+ }
191
+ function createFixtureDatabaseProvider(context) {
192
+ return {
193
+ async listDatabases(options) {
194
+ return context.api.listDatabasesForProject(options.projectId, options.branchName).map((database) => normalizeDatabase(database, database.projectId));
195
+ },
196
+ async showDatabase(databaseId) {
197
+ const database = context.api.getDatabase(databaseId);
198
+ return database ? normalizeDatabase(database, database.projectId) : null;
199
+ },
200
+ async createDatabase(options) {
201
+ const created = context.api.createDatabase(options);
202
+ return {
203
+ database: normalizeDatabase(created.database, created.database.projectId),
204
+ connection: normalizeConnection(created.connection, created.connection.databaseId),
205
+ connectionString: created.connectionString
206
+ };
207
+ },
208
+ async removeDatabase(databaseId) {
209
+ if (!context.api.removeDatabase(databaseId)) throw databaseNotFoundError(databaseId);
210
+ },
211
+ async listConnections(databaseId) {
212
+ if (!context.api.getDatabase(databaseId)) throw databaseNotFoundError(databaseId);
213
+ return context.api.listDatabaseConnections(databaseId).map((connection) => normalizeConnection(connection, connection.databaseId));
214
+ },
215
+ async createConnection(options) {
216
+ const created = context.api.createDatabaseConnection(options);
217
+ if (!created) throw databaseNotFoundError(options.databaseId);
218
+ return {
219
+ connection: normalizeConnection(created.connection, created.connection.databaseId),
220
+ connectionString: created.connectionString
221
+ };
222
+ },
223
+ async removeConnection(connectionId) {
224
+ if (!context.api.removeDatabaseConnection(connectionId)) throw connectionNotFoundError(connectionId);
225
+ }
226
+ };
227
+ }
228
+ async function resolveDatabase(provider, target, databaseRef, branchName, signal) {
229
+ const ref = databaseRef.trim();
230
+ if (!ref) throw usageError("Database id or name required", "This command needs a database id or name.", "Pass a database id or name.", ["prisma-cli database list"], "database");
231
+ const matches = (await provider.listDatabases({
232
+ projectId: target.project.id,
233
+ branchName,
234
+ signal
235
+ })).filter((database) => database.id === ref || database.name === ref);
236
+ if (matches.length === 0) throw databaseNotFoundError(ref, target.project.name, branchName);
237
+ if (matches.length > 1) throw databaseAmbiguousError(ref, matches, branchName);
238
+ const selected = matches[0];
239
+ return ensureProjectId(await provider.showDatabase(selected.id, {
240
+ projectId: target.project.id,
241
+ signal
242
+ }) ?? selected, target.project.id);
243
+ }
244
+ function ensureProjectId(database, projectId) {
245
+ return database.projectId ? database : {
246
+ ...database,
247
+ projectId
248
+ };
249
+ }
250
+ function sortDatabases(databases) {
251
+ return databases.slice().sort((left, right) => {
252
+ const branchOrder = (left.branchName ?? "").localeCompare(right.branchName ?? "");
253
+ if (branchOrder !== 0) return branchOrder;
254
+ const nameOrder = left.name.localeCompare(right.name);
255
+ return nameOrder !== 0 ? nameOrder : left.id.localeCompare(right.id);
256
+ });
257
+ }
258
+ function requireExactConfirmation(options) {
259
+ if (options.confirm === options.id) return;
260
+ throw new CliError({
261
+ code: "CONFIRMATION_REQUIRED",
262
+ domain: "database",
263
+ summary: `Confirm ${options.resourceName} removal`,
264
+ why: `Removing this ${options.resourceName} is destructive and requires the exact id.`,
265
+ fix: `Rerun with --confirm ${options.id}.`,
266
+ exitCode: 2,
267
+ nextSteps: [`prisma-cli ${options.commandName} ${options.id} --confirm ${options.id}`],
268
+ meta: {
269
+ expectedConfirm: options.id,
270
+ receivedConfirm: options.confirm ?? null
271
+ }
272
+ });
273
+ }
274
+ function defaultConnectionName() {
275
+ return `cli-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:.TZ]/g, "").slice(0, 17)}-${randomBytes(2).toString("hex")}`;
276
+ }
277
+ function databaseNotFoundError(databaseRef, projectName, branchName) {
278
+ return new CliError({
279
+ code: "DATABASE_NOT_FOUND",
280
+ domain: "database",
281
+ summary: "Database not found",
282
+ why: `No database matched "${databaseRef}"${projectName ? ` in project "${projectName}"${branchName ? ` on branch "${branchName}"` : ""}` : ""}.`,
283
+ fix: "Pass a database id or name from prisma-cli database list.",
284
+ exitCode: 1,
285
+ nextSteps: ["prisma-cli database list"]
286
+ });
287
+ }
288
+ function databaseAmbiguousError(databaseRef, matches, branchName) {
289
+ return new CliError({
290
+ code: "DATABASE_AMBIGUOUS",
291
+ domain: "database",
292
+ summary: "Database resolution is ambiguous",
293
+ why: branchName ? `Multiple databases matched "${databaseRef}" on branch "${branchName}".` : `Multiple databases matched "${databaseRef}".`,
294
+ fix: "Pass the database id, or pass --branch <git-name> to narrow the match.",
295
+ exitCode: 1,
296
+ nextSteps: ["prisma-cli database list"],
297
+ meta: { matches: matches.map((database) => ({
298
+ id: database.id,
299
+ name: database.name,
300
+ branchName: database.branchName
301
+ })) }
302
+ });
303
+ }
304
+ function connectionNotFoundError(connectionId) {
305
+ return new CliError({
306
+ code: "DATABASE_CONNECTION_NOT_FOUND",
307
+ domain: "database",
308
+ summary: "Database connection not found",
309
+ why: `No database connection matched "${connectionId}".`,
310
+ fix: "Pass a connection id from prisma-cli database connection list <database>.",
311
+ exitCode: 1,
312
+ nextSteps: ["prisma-cli database connection list <database>"]
313
+ });
314
+ }
315
+ //#endregion
316
+ export { runDatabaseConnectionCreate, runDatabaseConnectionList, runDatabaseConnectionRemove, runDatabaseCreate, runDatabaseList, runDatabaseRemove, runDatabaseShow };
@@ -13,6 +13,7 @@ import { requireAuthenticatedAuthState } from "./auth.js";
13
13
  import { parseGitHubRepositoryUrl, readGitOriginRemote } from "../adapters/git.js";
14
14
  import { createProjectUseCases } from "../use-cases/project.js";
15
15
  import open from "open";
16
+ import { matchError } from "better-result";
16
17
  //#region src/controllers/project.ts
17
18
  const GITHUB_INSTALL_POLL_INTERVAL_MS = 2e3;
18
19
  const GITHUB_INSTALL_POLL_TIMEOUT_MS = 12e4;
@@ -20,11 +21,24 @@ function isRealMode(context) {
20
21
  return !context.runtime.fixturePath && !context.runtime.env.PRISMA_CLI_MOCK_FIXTURE_PATH;
21
22
  }
22
23
  async function readProjectListLocalBinding(cwd, workspace, projects, signal) {
23
- const pin = await readLocalResolutionPin(cwd, signal);
24
+ const pinResult = await readLocalResolutionPin(cwd, signal);
25
+ if (pinResult.isErr()) return localPinReadErrorToInvalidLocalBinding(pinResult.error);
26
+ const pin = pinResult.value;
24
27
  if (pin.kind === "present") return pin.pin.workspaceId === workspace.id && projects.some((project) => project.id === pin.pin.projectId) ? { status: "linked" } : { status: "invalid" };
25
- if (pin.kind === "invalid") return { status: "invalid" };
26
28
  return { status: "not-linked" };
27
29
  }
30
+ function localPinReadErrorToInvalidLocalBinding(error) {
31
+ return matchError(error, {
32
+ LocalResolutionPinInvalidJsonError: () => ({ status: "invalid" }),
33
+ LocalResolutionPinInvalidShapeError: () => ({ status: "invalid" }),
34
+ LocalResolutionPinReadAbortedError: (error) => {
35
+ throw error;
36
+ },
37
+ UnhandledException: (error) => {
38
+ throw error;
39
+ }
40
+ });
41
+ }
28
42
  async function runProjectList(context) {
29
43
  const authState = await requireAuthenticatedAuthState(context);
30
44
  const workspace = authState.workspace;
@@ -699,4 +713,4 @@ function repoConnectionFixForStatus(status) {
699
713
  return "Re-run with --trace for the underlying API response details.";
700
714
  }
701
715
  //#endregion
702
- export { listRealWorkspaceProjects, runGitConnect, runGitDisconnect, runProjectCreate, runProjectLink, runProjectList, runProjectShow };
716
+ export { listFixtureWorkspaceProjects, listRealWorkspaceProjects, runGitConnect, runGitDisconnect, runProjectCreate, runProjectLink, runProjectList, runProjectShow };
@@ -3,6 +3,7 @@ import { renderSummaryLine } from "../../shell/ui.js";
3
3
  import { canPrompt } from "../../shell/runtime.js";
4
4
  import { confirmPrompt } from "../../shell/prompt.js";
5
5
  import { formatCommandArgument } from "../../shell/command-arguments.js";
6
+ import "../project/setup.js";
6
7
  import { hasBranchDatabaseSignal, inspectBranchDatabaseSignal, runBranchDatabaseSchemaSetup } from "./branch-database.js";
7
8
  import path from "node:path";
8
9
  //#region src/lib/app/branch-database-deploy.ts