@prisma/cli 3.0.0-beta.8 → 3.0.0-dev.101.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 (56) hide show
  1. package/README.md +0 -13
  2. package/dist/adapters/mock-api.js +75 -0
  3. package/dist/adapters/token-storage.js +311 -33
  4. package/dist/cli.js +7 -7
  5. package/dist/cli2.js +5 -3
  6. package/dist/commands/app/index.js +65 -52
  7. package/dist/commands/auth/index.js +55 -2
  8. package/dist/commands/database/index.js +159 -0
  9. package/dist/controllers/app-env.js +10 -7
  10. package/dist/controllers/app.js +550 -208
  11. package/dist/controllers/auth.js +211 -2
  12. package/dist/controllers/branch.js +5 -6
  13. package/dist/controllers/database.js +318 -0
  14. package/dist/controllers/project.js +49 -20
  15. package/dist/lib/app/app-interaction.js +5 -0
  16. package/dist/lib/app/{preview-provider.js → app-provider.js} +32 -28
  17. package/dist/lib/app/{preview-branch-database.js → branch-database-api.js} +1 -1
  18. package/dist/lib/app/branch-database-deploy.js +13 -60
  19. package/dist/lib/app/branch-database.js +1 -102
  20. package/dist/lib/app/build-settings.js +93 -0
  21. package/dist/lib/app/build.js +82 -0
  22. package/dist/lib/app/bun-project.js +2 -3
  23. package/dist/lib/app/compute-config.js +147 -0
  24. package/dist/lib/app/deploy-plan.js +58 -0
  25. package/dist/lib/app/{preview-progress.js → deploy-progress.js} +5 -5
  26. package/dist/lib/app/local-dev.js +3 -60
  27. package/dist/lib/app/production-deploy-gate.js +3 -3
  28. package/dist/lib/app/read-branch.js +30 -0
  29. package/dist/lib/auth/auth-ops.js +10 -4
  30. package/dist/lib/auth/guard.js +4 -1
  31. package/dist/lib/auth/login.js +32 -25
  32. package/dist/lib/database/provider.js +167 -0
  33. package/dist/lib/diagnostics.js +1 -1
  34. package/dist/lib/fs/home-path.js +24 -0
  35. package/dist/lib/git/local-branch.js +15 -3
  36. package/dist/lib/project/local-pin.js +170 -40
  37. package/dist/lib/project/resolution.js +166 -61
  38. package/dist/lib/project/setup.js +65 -19
  39. package/dist/output/patterns.js +1 -1
  40. package/dist/presenters/app.js +44 -39
  41. package/dist/presenters/auth.js +98 -1
  42. package/dist/presenters/branch.js +1 -1
  43. package/dist/presenters/database.js +274 -0
  44. package/dist/presenters/project.js +3 -9
  45. package/dist/shell/command-meta.js +153 -2
  46. package/dist/shell/command-runner.js +39 -21
  47. package/dist/shell/diagnostics-output.js +2 -8
  48. package/dist/shell/errors.js +50 -1
  49. package/dist/shell/help.js +30 -20
  50. package/dist/shell/runtime.js +8 -4
  51. package/dist/shell/ui.js +19 -2
  52. package/dist/use-cases/auth.js +68 -1
  53. package/package.json +18 -3
  54. package/dist/lib/app/preview-build-settings.js +0 -385
  55. package/dist/lib/app/preview-build.js +0 -475
  56. package/dist/lib/app/preview-interaction.js +0 -5
@@ -1,46 +1,100 @@
1
1
  import { CliError } from "../../shell/errors.js";
2
- import { formatCommandArgument } from "../../shell/command-arguments.js";
3
2
  import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH, readLocalResolutionPin } from "./local-pin.js";
3
+ import { formatCommandArgument } from "../../shell/command-arguments.js";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import path from "node:path";
6
+ import { Result, TaggedError, matchError } from "better-result";
6
7
  //#region src/lib/project/resolution.ts
8
+ var ProjectNotFoundError = class extends TaggedError("ProjectNotFoundError")() {
9
+ constructor(projectRef, workspace) {
10
+ super({
11
+ message: `Project "${projectRef}" was not found in workspace "${workspace.name}".`,
12
+ projectRef,
13
+ workspace
14
+ });
15
+ }
16
+ };
17
+ var ProjectAmbiguousError = class extends TaggedError("ProjectAmbiguousError")() {
18
+ constructor(projectRef, matches) {
19
+ super({
20
+ message: projectRef ? `Multiple projects matched "${projectRef}".` : "Multiple projects matched the current directory context.",
21
+ projectRef,
22
+ matches
23
+ });
24
+ }
25
+ };
26
+ var LocalStateStaleError = class extends TaggedError("LocalStateStaleError")() {
27
+ constructor() {
28
+ super({
29
+ message: `The target recorded in ${LOCAL_RESOLUTION_PIN_RELATIVE_PATH} is no longer available in the selected workspace.`,
30
+ pinPath: LOCAL_RESOLUTION_PIN_RELATIVE_PATH
31
+ });
32
+ }
33
+ };
34
+ var LocalProjectWorkspaceMismatchError = class extends TaggedError("LocalProjectWorkspaceMismatchError")() {
35
+ constructor(options) {
36
+ super({
37
+ message: `${LOCAL_RESOLUTION_PIN_RELATIVE_PATH} links this directory to project ${options.pinnedProjectId} in workspace ${options.pinnedWorkspaceId}, but the active workspace is "${options.activeWorkspace.name}" (${options.activeWorkspace.id}).`,
38
+ pinnedWorkspaceId: options.pinnedWorkspaceId,
39
+ pinnedProjectId: options.pinnedProjectId,
40
+ activeWorkspace: options.activeWorkspace
41
+ });
42
+ }
43
+ };
44
+ var ProjectSetupRequiredError = class extends TaggedError("ProjectSetupRequiredError")() {
45
+ constructor(options) {
46
+ const commandLabel = options.commandName ? `prisma-cli ${options.commandName}` : "this command";
47
+ super({
48
+ message: `This directory is not linked to a Prisma Project, and ${commandLabel} will not choose one from package or directory names.`,
49
+ commandName: options.commandName,
50
+ suggestion: options.suggestion
51
+ });
52
+ }
53
+ };
7
54
  async function resolveProjectTarget(options) {
8
- const localPin = await readImplicitLocalPin(options, { allowEnvProjectId: true });
9
- const projects = await options.listProjects();
10
- const target = await resolveBoundProjectTarget(options, projects, {
11
- allowEnvProjectId: true,
12
- localPin
13
- });
14
- if (target) return target;
15
- throw await projectSetupRequiredError({
16
- cwd: options.context.runtime.cwd,
17
- projects,
18
- commandName: options.commandName,
19
- signal: options.context.runtime.signal
55
+ return Result.gen(async function* () {
56
+ const localPin = yield* Result.await(readImplicitLocalPin(options, { allowEnvProjectId: true }));
57
+ const projects = await options.listProjects();
58
+ const target = yield* Result.await(resolveBoundProjectTarget(options, projects, {
59
+ allowEnvProjectId: true,
60
+ localPin
61
+ }));
62
+ if (target) return Result.ok(target);
63
+ return Result.err(await projectSetupRequiredError({
64
+ cwd: options.context.runtime.cwd,
65
+ projects,
66
+ commandName: options.commandName,
67
+ signal: options.context.runtime.signal
68
+ }));
20
69
  });
21
70
  }
22
71
  async function inspectProjectBinding(options) {
23
- const localPin = await readImplicitLocalPin(options, { allowEnvProjectId: false });
24
- const projects = await options.listProjects();
25
- const target = await resolveBoundProjectTarget(options, projects, {
26
- allowEnvProjectId: false,
27
- localPin
72
+ return Result.gen(async function* () {
73
+ const localPin = yield* Result.await(readImplicitLocalPin(options, { allowEnvProjectId: false }));
74
+ const projects = await options.listProjects();
75
+ const target = yield* Result.await(resolveBoundProjectTarget(options, projects, {
76
+ allowEnvProjectId: false,
77
+ localPin
78
+ }));
79
+ if (target) return Result.ok(target);
80
+ return Result.ok({
81
+ workspace: options.workspace,
82
+ project: null,
83
+ localBinding: { status: "not-linked" },
84
+ resolution: { projectSource: "unbound" },
85
+ ...await buildProjectSetupSuggestion({
86
+ cwd: options.context.runtime.cwd,
87
+ projects,
88
+ commandName: options.commandName ?? "project show",
89
+ signal: options.context.runtime.signal
90
+ })
91
+ });
28
92
  });
29
- if (target) return target;
30
- return {
31
- workspace: options.workspace,
32
- project: null,
33
- localBinding: { status: "not-linked" },
34
- resolution: { projectSource: "unbound" },
35
- ...await buildProjectSetupSuggestion({
36
- cwd: options.context.runtime.cwd,
37
- projects,
38
- commandName: options.commandName ?? "project show",
39
- signal: options.context.runtime.signal
40
- })
41
- };
42
93
  }
43
94
  function projectNotFoundError(projectRef, workspace) {
95
+ return projectResolutionErrorToCliError(new ProjectNotFoundError(projectRef, workspace));
96
+ }
97
+ function projectNotFoundCliError(projectRef, workspace) {
44
98
  return new CliError({
45
99
  code: "PROJECT_NOT_FOUND",
46
100
  domain: "project",
@@ -52,6 +106,9 @@ function projectNotFoundError(projectRef, workspace) {
52
106
  });
53
107
  }
54
108
  function projectAmbiguousError(projectRef, matches) {
109
+ return projectResolutionErrorToCliError(new ProjectAmbiguousError(projectRef, matches));
110
+ }
111
+ function projectAmbiguousCliError(projectRef, matches) {
55
112
  const firstMatch = matches[0];
56
113
  const nextSteps = ["prisma-cli project list"];
57
114
  if (firstMatch) nextSteps.push(`prisma-cli app deploy --project ${firstMatch.id}`);
@@ -69,7 +126,7 @@ function projectAmbiguousError(projectRef, matches) {
69
126
  nextSteps
70
127
  });
71
128
  }
72
- function localStateStaleError() {
129
+ function localStateStaleCliError() {
73
130
  return new CliError({
74
131
  code: "LOCAL_STATE_STALE",
75
132
  domain: "project",
@@ -82,12 +139,15 @@ function localStateStaleError() {
82
139
  });
83
140
  }
84
141
  function localProjectWorkspaceMismatchError(options) {
142
+ return projectResolutionErrorToCliError(new LocalProjectWorkspaceMismatchError(options));
143
+ }
144
+ function localProjectWorkspaceMismatchCliError(options) {
85
145
  return new CliError({
86
146
  code: "LOCAL_PROJECT_WORKSPACE_MISMATCH",
87
147
  domain: "project",
88
148
  summary: "Project link uses another workspace",
89
149
  why: `${LOCAL_RESOLUTION_PIN_RELATIVE_PATH} links this directory to project ${options.pinnedProjectId} in workspace ${options.pinnedWorkspaceId}, but your current CLI session is workspace "${options.activeWorkspace.name}" (${options.activeWorkspace.id}).`,
90
- fix: "Sign in to the linked workspace, or relink this directory to a project in the current workspace.",
150
+ fix: "Switch to the linked workspace, or relink this directory to a project in the current workspace.",
91
151
  meta: {
92
152
  pinPath: LOCAL_RESOLUTION_PIN_RELATIVE_PATH,
93
153
  pinnedWorkspaceId: options.pinnedWorkspaceId,
@@ -97,12 +157,37 @@ function localProjectWorkspaceMismatchError(options) {
97
157
  },
98
158
  exitCode: 1,
99
159
  nextSteps: [
100
- "prisma-cli auth login",
160
+ `prisma-cli auth workspace use ${options.pinnedWorkspaceId}`,
101
161
  "prisma-cli project list",
102
162
  "prisma-cli project link <id-or-name>"
103
163
  ]
104
164
  });
105
165
  }
166
+ /**
167
+ * Converts expected project-resolution variants to command-boundary CliErrors.
168
+ * `LocalResolutionPinReadAbortedError` and `UnhandledException` intentionally
169
+ * propagate as exceptions; callers such as `resolveProjectShowInRealMode`
170
+ * throw this helper's result, so passthrough variants should keep bubbling.
171
+ */
172
+ function projectResolutionErrorToCliError(error) {
173
+ return matchError(error, {
174
+ ProjectNotFoundError: (error) => projectNotFoundCliError(error.projectRef, error.workspace),
175
+ ProjectAmbiguousError: (error) => projectAmbiguousCliError(error.projectRef, error.matches),
176
+ ProjectSetupRequiredError: (error) => projectSetupRequiredCliError(error),
177
+ LocalStateStaleError: () => localStateStaleCliError(),
178
+ LocalProjectWorkspaceMismatchError: (error) => localProjectWorkspaceMismatchCliError({
179
+ pinnedWorkspaceId: error.pinnedWorkspaceId,
180
+ pinnedProjectId: error.pinnedProjectId,
181
+ activeWorkspace: error.activeWorkspace
182
+ }),
183
+ LocalResolutionPinReadAbortedError: (error) => {
184
+ throw error;
185
+ },
186
+ UnhandledException: (error) => {
187
+ throw error;
188
+ }
189
+ });
190
+ }
106
191
  async function buildProjectSetupSuggestion(options) {
107
192
  const suggestedName = await inferTargetName(options.cwd, options.signal);
108
193
  const candidates = sortProjects(options.projects.filter((project) => projectMatchesSuggestedName(project, suggestedName.name))).map(toProjectSummary);
@@ -115,17 +200,24 @@ async function buildProjectSetupSuggestion(options) {
115
200
  }
116
201
  async function projectSetupRequiredError(options) {
117
202
  const suggestion = await buildProjectSetupSuggestion(options);
203
+ return new ProjectSetupRequiredError({
204
+ commandName: options.commandName,
205
+ suggestion
206
+ });
207
+ }
208
+ function projectSetupRequiredCliError(error) {
209
+ const suggestion = error.suggestion;
118
210
  return new CliError({
119
211
  code: "PROJECT_SETUP_REQUIRED",
120
212
  domain: "project",
121
213
  summary: "Choose a Project before running this command",
122
- why: `This directory is not linked to a Prisma Project, and ${options.commandName ? `prisma-cli ${options.commandName}` : "this command"} will not choose one from package or directory names.`,
214
+ why: error.message,
123
215
  fix: "Link the directory to an existing Project, or pass --project <id-or-name> for this command.",
124
216
  meta: { ...suggestion },
125
217
  exitCode: 1,
126
218
  nextSteps: ["prisma-cli project list", ...suggestion.recoveryCommands],
127
219
  nextActions: buildProjectSetupNextActions({
128
- commandName: options.commandName,
220
+ commandName: error.commandName,
129
221
  suggestedProjectName: suggestion.suggestedProjectName
130
222
  })
131
223
  });
@@ -199,9 +291,9 @@ function sortProjects(projects) {
199
291
  }
200
292
  function resolveExplicitProject(projectRef, projects, workspace) {
201
293
  const matches = projects.filter((project) => project.id === projectRef || project.name === projectRef);
202
- if (matches.length === 1) return matches[0];
203
- if (matches.length > 1) throw projectAmbiguousError(projectRef, matches);
204
- throw projectNotFoundError(projectRef, workspace);
294
+ if (matches.length === 1) return Result.ok(matches[0]);
295
+ if (matches.length > 1) return Result.err(new ProjectAmbiguousError(projectRef, matches));
296
+ return Result.err(new ProjectNotFoundError(projectRef, workspace));
205
297
  }
206
298
  function projectMatchesSuggestedName(project, suggestedName) {
207
299
  return project.id === suggestedName || project.name === suggestedName || project.slug === suggestedName;
@@ -210,50 +302,63 @@ async function resolveDurablePlatformMapping() {
210
302
  return null;
211
303
  }
212
304
  async function resolveBoundProjectTarget(options, projects, settings) {
213
- if (options.explicitProject) return resolvedTarget(options.workspace, resolveExplicitProject(options.explicitProject, projects, options.workspace), "explicit", {
214
- targetName: options.explicitProject,
215
- targetNameSource: "explicit"
216
- });
305
+ if (options.explicitProject) {
306
+ const projectResult = resolveExplicitProject(options.explicitProject, projects, options.workspace);
307
+ if (projectResult.isErr()) return Result.err(projectResult.error);
308
+ return Result.ok(resolvedTarget(options.workspace, projectResult.value, "explicit", {
309
+ targetName: options.explicitProject,
310
+ targetNameSource: "explicit"
311
+ }));
312
+ }
217
313
  if (settings.allowEnvProjectId && options.envProjectId) {
218
314
  const project = projects.find((candidate) => candidate.id === options.envProjectId);
219
- if (!project) throw projectNotFoundError(options.envProjectId, options.workspace);
220
- return resolvedTarget(options.workspace, project, "env", {
315
+ if (!project) return Result.err(new ProjectNotFoundError(options.envProjectId, options.workspace));
316
+ return Result.ok(resolvedTarget(options.workspace, project, "env", {
221
317
  targetName: options.envProjectId,
222
318
  targetNameSource: "env"
223
- });
319
+ }));
224
320
  }
225
321
  const localPin = settings.localPin;
226
- if (!localPin) return null;
227
- if (localPin.kind === "invalid") throw localStateStaleError();
322
+ if (!localPin) return Result.ok(null);
228
323
  if (localPin.kind === "present") {
229
- if (localPin.pin.workspaceId !== options.workspace.id) throw localProjectWorkspaceMismatchError({
324
+ if (localPin.pin.workspaceId !== options.workspace.id) return Result.err(new LocalProjectWorkspaceMismatchError({
230
325
  pinnedWorkspaceId: localPin.pin.workspaceId,
231
326
  pinnedProjectId: localPin.pin.projectId,
232
327
  activeWorkspace: options.workspace
233
- });
328
+ }));
234
329
  const project = projects.find((candidate) => candidate.id === localPin.pin.projectId);
235
- if (!project) throw localStateStaleError();
236
- return resolvedTarget(options.workspace, project, "local-pin", {
330
+ if (!project) return Result.err(new LocalStateStaleError());
331
+ return Result.ok(resolvedTarget(options.workspace, project, "local-pin", {
237
332
  targetName: project.name,
238
333
  targetNameSource: "local-pin"
239
- });
334
+ }));
240
335
  }
241
336
  const platformMapping = await resolveDurablePlatformMapping();
242
- if (platformMapping && platformMapping.workspace.id === options.workspace.id) return resolvedTarget(options.workspace, platformMapping, "platform-mapping", {
337
+ if (platformMapping && platformMapping.workspace.id === options.workspace.id) return Result.ok(resolvedTarget(options.workspace, platformMapping, "platform-mapping", {
243
338
  targetName: platformMapping.name,
244
339
  targetNameSource: "platform-mapping"
245
- });
246
- return null;
340
+ }));
341
+ return Result.ok(null);
247
342
  }
248
343
  async function readImplicitLocalPin(options, settings) {
249
- if (options.explicitProject || settings.allowEnvProjectId && options.envProjectId) return null;
250
- const localPin = await readLocalResolutionPin(options.context.runtime.cwd, options.context.runtime.signal);
251
- if (localPin.kind === "present" && localPin.pin.workspaceId !== options.workspace.id) throw localProjectWorkspaceMismatchError({
344
+ if (options.explicitProject || settings.allowEnvProjectId && options.envProjectId) return Result.ok(null);
345
+ const localPinResult = await readLocalResolutionPin(options.projectDir ?? options.context.runtime.cwd, options.context.runtime.signal);
346
+ if (localPinResult.isErr()) return Result.err(localPinReadErrorToProjectError(localPinResult.error));
347
+ const localPin = localPinResult.value;
348
+ if (localPin.kind === "present" && localPin.pin.workspaceId !== options.workspace.id) return Result.err(new LocalProjectWorkspaceMismatchError({
252
349
  pinnedWorkspaceId: localPin.pin.workspaceId,
253
350
  pinnedProjectId: localPin.pin.projectId,
254
351
  activeWorkspace: options.workspace
352
+ }));
353
+ return Result.ok(localPin);
354
+ }
355
+ function localPinReadErrorToProjectError(error) {
356
+ return matchError(error, {
357
+ LocalResolutionPinInvalidJsonError: () => new LocalStateStaleError(),
358
+ LocalResolutionPinInvalidShapeError: () => new LocalStateStaleError(),
359
+ LocalResolutionPinReadAbortedError: (error) => error,
360
+ UnhandledException: (error) => error
255
361
  });
256
- return localPin;
257
362
  }
258
363
  function resolvedTarget(workspace, project, projectSource, resolutionDetails) {
259
364
  return {
@@ -278,4 +383,4 @@ function toProjectSummary(project) {
278
383
  };
279
384
  }
280
385
  //#endregion
281
- export { buildProjectSetupNextActions, inferTargetName, inspectProjectBinding, projectAmbiguousError, projectNotFoundError, resolveDurablePlatformMapping, resolveProjectTarget, sortProjects };
386
+ export { buildProjectSetupNextActions, inferTargetName, inspectProjectBinding, localProjectWorkspaceMismatchError, projectAmbiguousError, projectNotFoundError, projectResolutionErrorToCliError, resolveDurablePlatformMapping, resolveProjectTarget, sortProjects };
@@ -1,7 +1,10 @@
1
1
  import { CliError, usageError } from "../../shell/errors.js";
2
- import "../../shell/command-arguments.js";
2
+ import { shortenHomePath } from "../fs/home-path.js";
3
3
  import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH, ensureLocalResolutionPinGitignore, writeLocalResolutionPin } from "./local-pin.js";
4
+ import "../../shell/command-arguments.js";
4
5
  import { projectAmbiguousError, projectNotFoundError } from "./resolution.js";
6
+ import path from "node:path";
7
+ import { Result, matchError } from "better-result";
5
8
  //#region src/lib/project/setup.ts
6
9
  function isValidProjectSetupName(projectName) {
7
10
  return projectName.trim().length > 0;
@@ -16,22 +19,64 @@ function resolveProjectForSetup(projectRef, projects, workspace) {
16
19
  if (matches.length > 1) throw projectAmbiguousError(projectRef, matches);
17
20
  throw projectNotFoundError(projectRef, workspace);
18
21
  }
19
- async function bindProjectToDirectory(context, workspace, project, action) {
20
- await writeLocalResolutionPin(context.runtime.cwd, {
21
- workspaceId: workspace.id,
22
- projectId: project.id
23
- }, context.runtime.signal);
24
- await ensureLocalResolutionPinGitignore(context.runtime.cwd, context.runtime.signal);
25
- return {
26
- workspace,
27
- project,
28
- directory: formatSetupDirectory(context.runtime.cwd),
29
- localPin: {
30
- path: LOCAL_RESOLUTION_PIN_RELATIVE_PATH,
31
- written: true
22
+ async function bindProjectToDirectory(context, workspace, project, action, directory = context.runtime.cwd) {
23
+ return Result.gen(async function* () {
24
+ yield* Result.await(writeLocalResolutionPin(directory, {
25
+ workspaceId: workspace.id,
26
+ projectId: project.id
27
+ }, context.runtime.signal));
28
+ yield* Result.await(ensureLocalResolutionPinGitignore(directory, context.runtime.signal));
29
+ return Result.ok({
30
+ workspace,
31
+ project,
32
+ directory: formatSetupDirectory(directory, context),
33
+ localPin: {
34
+ path: LOCAL_RESOLUTION_PIN_RELATIVE_PATH,
35
+ written: true
36
+ },
37
+ action
38
+ });
39
+ });
40
+ }
41
+ function projectDirectoryBindingErrorToCliError(error) {
42
+ return matchError(error, {
43
+ LocalResolutionPinSerializationError: (error) => {
44
+ throw error;
32
45
  },
33
- action
34
- };
46
+ LocalResolutionPinWriteAbortedError: (error) => {
47
+ throw error;
48
+ },
49
+ LocalResolutionPinWriteFailedError: (error) => localStateWriteFailedError(error, {
50
+ why: `The CLI could not write ${LOCAL_RESOLUTION_PIN_RELATIVE_PATH}.`,
51
+ meta: {
52
+ pinPath: error.pinPath,
53
+ operation: error.operation
54
+ }
55
+ }),
56
+ LocalResolutionPinGitignoreUpdateAbortedError: (error) => {
57
+ throw error;
58
+ },
59
+ LocalResolutionPinGitignoreUpdateFailedError: (error) => localStateWriteFailedError(error, {
60
+ why: "The CLI could not update .gitignore to keep local Project binding state out of git.",
61
+ meta: {
62
+ gitignorePath: error.gitignorePath,
63
+ operation: error.operation
64
+ }
65
+ })
66
+ });
67
+ }
68
+ function localStateWriteFailedError(error, options) {
69
+ return new CliError({
70
+ code: "LOCAL_STATE_WRITE_FAILED",
71
+ domain: "project",
72
+ summary: "Could not save local Project binding",
73
+ why: options.why,
74
+ fix: "Check that this directory is writable and that .prisma/local.json and .gitignore are not blocked by directories or permissions, then retry.",
75
+ debug: formatDebugDetails(error.cause),
76
+ meta: options.meta,
77
+ exitCode: 1,
78
+ nextSteps: ["prisma-cli project link <id-or-name>", "prisma-cli app deploy --project <id-or-name>"]
79
+ });
35
80
  }
36
81
  function toProjectSummary(project) {
37
82
  return {
@@ -66,8 +111,9 @@ function projectCreateFailedError(error, projectName, workspace, options) {
66
111
  nextSteps: options.nextSteps
67
112
  });
68
113
  }
69
- function formatSetupDirectory(cwd) {
70
- const basename = cwd.split(/[\\/]/).filter(Boolean).pop();
114
+ function formatSetupDirectory(directory, context) {
115
+ if (path.resolve(directory) !== path.resolve(context.runtime.cwd)) return shortenHomePath(directory, context.runtime.env);
116
+ const basename = directory.split(/[\\/]/).filter(Boolean).pop();
71
117
  return basename ? `./${basename}` : ".";
72
118
  }
73
119
  function extractHttpStatus(error) {
@@ -86,4 +132,4 @@ function formatDebugDetails(error) {
86
132
  return typeof error === "string" ? error : null;
87
133
  }
88
134
  //#endregion
89
- export { bindProjectToDirectory, isValidProjectSetupName, projectCreateFailedError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary, validateProjectSetupNameText };
135
+ export { bindProjectToDirectory, isValidProjectSetupName, projectCreateFailedError, projectDirectoryBindingErrorToCliError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary, validateProjectSetupNameText };
@@ -1,5 +1,5 @@
1
- import { maskValue, padDisplay, renderSummaryLine } from "../shell/ui.js";
2
1
  import { formatDescriptorLabel } from "../shell/command-meta.js";
2
+ import { maskValue, padDisplay, renderSummaryLine } from "../shell/ui.js";
3
3
  import stringWidth from "string-width";
4
4
  //#region src/output/patterns.ts
5
5
  function renderList(input, ui) {
@@ -28,7 +28,8 @@ function renderAppBuild(context, descriptor, result) {
28
28
  function serializeAppBuild(result) {
29
29
  return result;
30
30
  }
31
- function renderAppDeploy(context, descriptor, result) {
31
+ function renderAppDeploy(context, descriptor, result, options) {
32
+ const logsCommand = options?.logsTarget ? `prisma-cli app logs ${options.logsTarget}` : "prisma-cli app logs";
32
33
  return [
33
34
  `Live in ${formatDuration(result.durationMs)}`,
34
35
  ...result.deployment.url ? [context.ui.link(result.deployment.url)] : [],
@@ -36,12 +37,37 @@ function renderAppDeploy(context, descriptor, result) {
36
37
  "",
37
38
  ...renderDeployOutputRows(context.ui, [{
38
39
  label: "Logs",
39
- value: "prisma-cli app logs"
40
+ value: logsCommand
40
41
  }]),
41
42
  ...renderDeployResolvedContextBlock(context, result),
42
43
  ...renderDeploySettingsBlock(context, result)
43
44
  ];
44
45
  }
46
+ function isAppDeployAllResult(result) {
47
+ return "deployments" in result;
48
+ }
49
+ function renderAppDeployAll(context, descriptor, result) {
50
+ const lines = [];
51
+ for (const deployment of result.deployments) {
52
+ lines.push(deployment.target);
53
+ lines.push(...renderAppDeploy(context, descriptor, deployment.result, { logsTarget: deployment.target }).map((line) => line ? ` ${line}` : line));
54
+ lines.push("");
55
+ }
56
+ lines.push(...renderDeployOutputRows(context.ui, result.deployments.map((deployment) => ({
57
+ label: deployment.target,
58
+ value: deployment.result.deployment.url ?? deployment.result.deployment.id
59
+ }))));
60
+ return lines;
61
+ }
62
+ function serializeAppDeployAll(result) {
63
+ return {
64
+ count: result.deployments.length,
65
+ deployments: result.deployments.map((deployment) => ({
66
+ target: deployment.target,
67
+ ...serializeAppDeploy(deployment.result)
68
+ }))
69
+ };
70
+ }
45
71
  function serializeAppDeploy(result) {
46
72
  const { deploySettings, localPin: _localPin, ...serialized } = result;
47
73
  const { id: _branchId, ...branch } = serialized.branch;
@@ -57,27 +83,13 @@ function serializeAppDeploy(result) {
57
83
  }
58
84
  function renderBranchDatabaseDeploySummary(context, result) {
59
85
  if (!result.branchDatabase || result.branchDatabase.status !== "created") return [];
60
- return ["", ...renderDeployOutputRows(context.ui, [
61
- {
62
- label: "Database",
63
- value: result.branchDatabase.database?.name ?? "created"
64
- },
65
- {
66
- label: "Env",
67
- value: result.branchDatabase.envVars.join(", ")
68
- },
69
- ...result.branchDatabase.schema ? [{
70
- label: "Schema",
71
- value: formatBranchDatabaseSchemaCommand(result.branchDatabase.schema.command)
72
- }] : []
73
- ])];
74
- }
75
- function formatBranchDatabaseSchemaCommand(command) {
76
- switch (command) {
77
- case "migrate-deploy": return "prisma migrate deploy";
78
- case "db-push": return "prisma db push";
79
- case "prisma-next-db-init": return "prisma-next db init";
80
- }
86
+ return ["", ...renderDeployOutputRows(context.ui, [{
87
+ label: "Database",
88
+ value: result.branchDatabase.database?.name ?? "created"
89
+ }, {
90
+ label: "Env",
91
+ value: result.branchDatabase.envVars.join(", ")
92
+ }])];
81
93
  }
82
94
  function formatDuration(durationMs) {
83
95
  if (durationMs < 1e3) return `${durationMs}ms`;
@@ -163,21 +175,14 @@ function branchDatabaseRows(branchDatabase) {
163
175
  value: "not configured",
164
176
  tone: "dim"
165
177
  }];
166
- return [
167
- {
168
- key: "branch db",
169
- value: branchDatabase.status === "created" ? `created${branchDatabase.database ? ` (${branchDatabase.database.name})` : ""}` : `skipped${branchDatabase.reason ? ` (${branchDatabase.reason})` : ""}`,
170
- tone: branchDatabase.status === "created" ? "success" : "dim"
171
- },
172
- ...branchDatabase.envVars.length > 0 ? [{
173
- key: "branch db env",
174
- value: branchDatabase.envVars.join(", ")
175
- }] : [],
176
- ...branchDatabase.schema ? [{
177
- key: "branch db schema",
178
- value: `${formatBranchDatabaseSchemaCommand(branchDatabase.schema.command)} (${branchDatabase.schema.source}, ${branchDatabase.schema.path})`
179
- }] : []
180
- ];
178
+ return [{
179
+ key: "branch db",
180
+ value: branchDatabase.status === "created" ? `created${branchDatabase.database ? ` (${branchDatabase.database.name})` : ""}` : `skipped${branchDatabase.reason ? ` (${branchDatabase.reason})` : ""}`,
181
+ tone: branchDatabase.status === "created" ? "success" : "dim"
182
+ }, ...branchDatabase.envVars.length > 0 ? [{
183
+ key: "branch db env",
184
+ value: branchDatabase.envVars.join(", ")
185
+ }] : []];
181
186
  }
182
187
  function formatEnvVarNames(envVars) {
183
188
  return envVars.length > 0 ? envVars.join(", ") : "none";
@@ -638,4 +643,4 @@ function formatRecentDeployments(deployments) {
638
643
  return deployments.map((deployment) => `${deployment.id}${deployment.live ? " (live)" : ""}`).join(", ");
639
644
  }
640
645
  //#endregion
641
- export { renderAppBuild, renderAppDeploy, renderAppDomainAdd, renderAppDomainRemove, renderAppDomainRetry, renderAppDomainShow, renderAppListDeploys, renderAppOpen, renderAppPromote, renderAppRemove, renderAppRollback, renderAppRun, renderAppShow, renderAppShowDeploy, serializeAppBuild, serializeAppDeploy, serializeAppDomainAdd, serializeAppDomainRemove, serializeAppDomainRetry, serializeAppDomainShow, serializeAppListDeploys, serializeAppOpen, serializeAppPromote, serializeAppRemove, serializeAppRollback, serializeAppRun, serializeAppShow, serializeAppShowDeploy };
646
+ export { isAppDeployAllResult, renderAppBuild, renderAppDeploy, renderAppDeployAll, renderAppDomainAdd, renderAppDomainRemove, renderAppDomainRetry, renderAppDomainShow, renderAppListDeploys, renderAppOpen, renderAppPromote, renderAppRemove, renderAppRollback, renderAppRun, renderAppShow, renderAppShowDeploy, serializeAppBuild, serializeAppDeploy, serializeAppDeployAll, serializeAppDomainAdd, serializeAppDomainRemove, serializeAppDomainRetry, serializeAppDomainShow, serializeAppListDeploys, serializeAppOpen, serializeAppPromote, serializeAppRemove, serializeAppRollback, serializeAppRun, serializeAppShow, serializeAppShowDeploy };