@prisma/cli 3.0.0-beta.3 → 3.0.0-beta.30

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 (99) hide show
  1. package/README.md +6 -15
  2. package/dist/adapters/local-state.js +15 -4
  3. package/dist/adapters/mock-api.js +244 -0
  4. package/dist/adapters/token-storage.js +335 -34
  5. package/dist/cli.js +7 -7
  6. package/dist/cli2.js +24 -5
  7. package/dist/commands/agent/index.js +60 -0
  8. package/dist/commands/app/index.js +91 -61
  9. package/dist/commands/auth/index.js +55 -2
  10. package/dist/commands/branch/index.js +2 -27
  11. package/dist/commands/bucket/index.js +123 -0
  12. package/dist/commands/build/index.js +29 -0
  13. package/dist/commands/database/index.js +249 -0
  14. package/dist/commands/env.js +8 -4
  15. package/dist/commands/feedback/index.js +20 -0
  16. package/dist/commands/git/index.js +1 -1
  17. package/dist/commands/init/index.js +33 -0
  18. package/dist/commands/project/index.js +54 -5
  19. package/dist/controllers/agent-setup.js +52 -0
  20. package/dist/controllers/agent.js +228 -0
  21. package/dist/controllers/app-env-api.js +55 -0
  22. package/dist/controllers/app-env-file.js +181 -0
  23. package/dist/controllers/app-env.js +227 -104
  24. package/dist/controllers/app.js +746 -306
  25. package/dist/controllers/auth.js +247 -3
  26. package/dist/controllers/branch.js +78 -48
  27. package/dist/controllers/bucket.js +278 -0
  28. package/dist/controllers/build.js +88 -0
  29. package/dist/controllers/database.js +567 -0
  30. package/dist/controllers/feedback.js +86 -0
  31. package/dist/controllers/init.js +753 -0
  32. package/dist/controllers/project.js +377 -22
  33. package/dist/controllers/select-prompt-port.js +1 -0
  34. package/dist/lib/agent/cli-command.js +20 -0
  35. package/dist/lib/agent/constants.js +12 -0
  36. package/dist/lib/agent/package-manager.js +99 -0
  37. package/dist/lib/agent/setup-status.js +83 -0
  38. package/dist/lib/app/{preview-provider.js → app-provider.js} +137 -88
  39. package/dist/lib/app/branch-database-api.js +102 -0
  40. package/dist/lib/app/branch-database-deploy.js +326 -0
  41. package/dist/lib/app/branch-database.js +216 -0
  42. package/dist/lib/app/build-settings.js +93 -0
  43. package/dist/lib/app/build.js +83 -0
  44. package/dist/lib/app/bun-project.js +3 -4
  45. package/dist/lib/app/compute-config.js +145 -0
  46. package/dist/lib/app/deploy-plan.js +59 -0
  47. package/dist/lib/app/{preview-progress.js → deploy-progress.js} +12 -12
  48. package/dist/lib/app/env-config.js +1 -1
  49. package/dist/lib/app/env-file.js +82 -0
  50. package/dist/lib/app/env-vars.js +28 -2
  51. package/dist/lib/app/local-dev.js +3 -60
  52. package/dist/lib/app/production-deploy-gate.js +162 -0
  53. package/dist/lib/app/read-branch.js +30 -0
  54. package/dist/lib/auth/auth-ops.js +10 -4
  55. package/dist/lib/auth/guard.js +4 -1
  56. package/dist/lib/auth/login.js +33 -26
  57. package/dist/lib/auth/recipient.js +42 -0
  58. package/dist/lib/bucket/provider.js +139 -0
  59. package/dist/lib/database/provider.js +378 -0
  60. package/dist/lib/diagnostics.js +15 -0
  61. package/dist/lib/fs/home-path.js +24 -0
  62. package/dist/lib/git/local-branch.js +53 -0
  63. package/dist/lib/git/local-status.js +57 -0
  64. package/dist/lib/project/interactive-setup.js +5 -4
  65. package/dist/lib/project/local-pin.js +171 -41
  66. package/dist/lib/project/provider.js +92 -0
  67. package/dist/lib/project/resolution.js +199 -48
  68. package/dist/lib/project/setup.js +67 -20
  69. package/dist/output/patterns.js +1 -1
  70. package/dist/presenters/agent.js +74 -0
  71. package/dist/presenters/app-env.js +149 -14
  72. package/dist/presenters/app.js +208 -27
  73. package/dist/presenters/auth.js +99 -2
  74. package/dist/presenters/branch.js +37 -102
  75. package/dist/presenters/bucket.js +174 -0
  76. package/dist/presenters/database.js +448 -0
  77. package/dist/presenters/feedback.js +26 -0
  78. package/dist/presenters/init.js +30 -0
  79. package/dist/presenters/project.js +139 -27
  80. package/dist/presenters/verbose-context.js +64 -0
  81. package/dist/shell/cli-command.js +12 -0
  82. package/dist/shell/command-arguments.js +7 -1
  83. package/dist/shell/command-meta.js +458 -17
  84. package/dist/shell/command-runner.js +58 -18
  85. package/dist/shell/diagnostics-output.js +57 -0
  86. package/dist/shell/errors.js +56 -1
  87. package/dist/shell/help.js +31 -20
  88. package/dist/shell/output.js +72 -1
  89. package/dist/shell/prompt.js +12 -5
  90. package/dist/shell/runtime.js +8 -4
  91. package/dist/shell/ui.js +42 -3
  92. package/dist/shell/update-check.js +2 -2
  93. package/dist/use-cases/auth.js +68 -1
  94. package/dist/use-cases/branch.js +20 -68
  95. package/dist/use-cases/create-cli-gateways.js +2 -17
  96. package/dist/use-cases/project.js +2 -1
  97. package/package.json +21 -4
  98. package/dist/lib/app/preview-build.js +0 -312
  99. package/dist/lib/app/preview-interaction.js +0 -5
@@ -1,7 +1,10 @@
1
- import { CliError, usageError } from "../../shell/errors.js";
2
1
  import "../../shell/command-arguments.js";
2
+ import { CliError, usageError } from "../../shell/errors.js";
3
+ import { shortenHomePath } from "../fs/home-path.js";
3
4
  import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH, ensureLocalResolutionPinGitignore, writeLocalResolutionPin } from "./local-pin.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,28 +19,71 @@ 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 {
38
83
  id: project.id,
39
84
  name: project.name,
40
- ...project.url ? { url: project.url } : {}
85
+ ...project.url ? { url: project.url } : {},
86
+ ...project.defaultRegion != null ? { defaultRegion: project.defaultRegion } : {}
41
87
  };
42
88
  }
43
89
  function projectSetupNameRequiredError(command) {
@@ -66,8 +112,9 @@ function projectCreateFailedError(error, projectName, workspace, options) {
66
112
  nextSteps: options.nextSteps
67
113
  });
68
114
  }
69
- function formatSetupDirectory(cwd) {
70
- const basename = cwd.split(/[\\/]/).filter(Boolean).pop();
115
+ function formatSetupDirectory(directory, context) {
116
+ if (path.resolve(directory) !== path.resolve(context.runtime.cwd)) return shortenHomePath(directory, context.runtime.env);
117
+ const basename = directory.split(/[\\/]/).filter(Boolean).pop();
71
118
  return basename ? `./${basename}` : ".";
72
119
  }
73
120
  function extractHttpStatus(error) {
@@ -86,4 +133,4 @@ function formatDebugDetails(error) {
86
133
  return typeof error === "string" ? error : null;
87
134
  }
88
135
  //#endregion
89
- export { bindProjectToDirectory, isValidProjectSetupName, projectCreateFailedError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary, validateProjectSetupNameText };
136
+ 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) {
@@ -0,0 +1,74 @@
1
+ import { formatShellCommand } from "../shell/command-arguments.js";
2
+ import { formatDescriptorLabel } from "../shell/command-meta.js";
3
+ import { renderSummaryLine } from "../shell/ui.js";
4
+ //#region src/presenters/agent.ts
5
+ function renderAgentInstall(context, descriptor, result) {
6
+ const ui = context.ui;
7
+ const rail = ui.dim("│");
8
+ return [
9
+ renderSummaryLine(ui, "success", `${formatDescriptorLabel(descriptor)} → ${operationSummary(result)} Prisma skills.`),
10
+ "",
11
+ `${rail} ${ui.accent("skills:")} ${result.skills.status.replace("-", " ")}`,
12
+ `${rail} ${ui.dim(formatShellCommand(result.skills.command))}`
13
+ ];
14
+ }
15
+ function renderAgentStatus(context, descriptor, result) {
16
+ const ui = context.ui;
17
+ const rail = ui.dim("│");
18
+ return [
19
+ `${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim(`Checking ${result.statusScope} Prisma skills.`)}`,
20
+ "",
21
+ `${rail} ${ui.accent("skills:")} ${result.skillsInstalled ? "installed" : "not found"}`,
22
+ ...renderInstalledSkills(context, result.skills),
23
+ `${rail}`,
24
+ `${rail} ${ui.accent("source:")} ${formatStatusSource(result)}`,
25
+ `${rail} ${ui.dim(formatShellCommand(result.skillsListCommand))}`,
26
+ ...renderProjectStatusDetails(context, result)
27
+ ];
28
+ }
29
+ function serializeAgentInstall(result) {
30
+ return result;
31
+ }
32
+ function serializeAgentStatus(result) {
33
+ return result;
34
+ }
35
+ function formatSetupPromptStatus(result) {
36
+ if (result.skillsInstalled) return "not needed";
37
+ if (result.promptDismissedAt) return `dismissed ${result.promptDismissedAt}`;
38
+ return "active";
39
+ }
40
+ function formatStatusSource(result) {
41
+ if (result.statusSource === "skills-cli") return result.statusScope === "global" ? "skills list -g --json" : "skills list --json";
42
+ if (result.statusSource === "skills-lock") return result.skillsLockPath;
43
+ return "unavailable";
44
+ }
45
+ function renderProjectStatusDetails(context, result) {
46
+ if (result.statusScope !== "project") return [];
47
+ const ui = context.ui;
48
+ const rail = ui.dim("│");
49
+ return [
50
+ `${rail}`,
51
+ `${rail} ${ui.accent("skills lock:")} ${result.skillsLockInstalled ? "installed" : "not found"}`,
52
+ `${rail} ${ui.dim(result.skillsLockPath)}`,
53
+ `${rail}`,
54
+ `${rail} ${ui.accent("setup prompt:")} ${formatSetupPromptStatus(result)}`
55
+ ];
56
+ }
57
+ function renderInstalledSkills(context, skills) {
58
+ const ui = context.ui;
59
+ const rail = ui.dim("│");
60
+ if (skills.length === 0) return [`${rail} ${ui.dim("No Prisma skills reported.")}`];
61
+ return skills.map((skill) => {
62
+ const agents = skill.agents.length > 0 ? skill.agents.join(", ") : "no agents reported";
63
+ return `${rail} ${skill.name} ${ui.dim(`${skill.scope}; ${agents}`)}`;
64
+ });
65
+ }
66
+ function operationSummary(result) {
67
+ if (result.skills.status === "would-install") return "Would install";
68
+ return operationLabel(result.operation);
69
+ }
70
+ function operationLabel(operation) {
71
+ return operation === "update" ? "Updated" : "Installed";
72
+ }
73
+ //#endregion
74
+ export { renderAgentInstall, renderAgentStatus, serializeAgentInstall, serializeAgentStatus };
@@ -1,11 +1,117 @@
1
+ import { renderVerboseBlock } from "../shell/ui.js";
1
2
  import { renderList, renderShow, serializeList } from "../output/patterns.js";
3
+ import { renderResolvedProjectContextBlock, stripVerboseContext } from "./verbose-context.js";
2
4
  //#region src/presenters/app-env.ts
3
5
  function scopeLabel(scope) {
4
6
  if (scope.kind === "role") return scope.role ?? "unknown";
7
+ if (scope.kind === "overview") return "overview";
5
8
  return `branch:${scope.branchName ?? scope.branchId ?? "unknown"}`;
6
9
  }
10
+ function listTargetLabel(result) {
11
+ const target = result.target;
12
+ if (target.source === "overview") return "overview";
13
+ if (target.branchName) {
14
+ const suffix = target.branchExists === false ? " (not created yet)" : "";
15
+ return `branch:${target.branchName} -> ${target.envMap}${suffix}`;
16
+ }
17
+ return scopeLabel(result.scope);
18
+ }
19
+ function renderEnvVerboseBlocks(context, result) {
20
+ return [...renderEnvResolvedContextBlock(context, result.verboseContext), ...renderEnvTargetBlock(context, result)];
21
+ }
22
+ function renderEnvResolvedContextBlock(context, verboseContext) {
23
+ return renderResolvedProjectContextBlock(context.ui, verboseContext);
24
+ }
25
+ function renderEnvTargetBlock(context, result) {
26
+ return renderVerboseBlock(context.ui, envTargetRows(result), { title: "Env target" });
27
+ }
28
+ function envTargetRows(result) {
29
+ return [
30
+ {
31
+ key: "project id",
32
+ value: result.projectId,
33
+ tone: "dim"
34
+ },
35
+ {
36
+ key: "scope",
37
+ value: scopeLabel(result.scope)
38
+ },
39
+ ...envListTargetRows(result),
40
+ ...envFileRows(result),
41
+ {
42
+ key: "keys",
43
+ value: formatKeyNames(envResultKeys(result)),
44
+ tone: envResultKeys(result).length > 0 ? "default" : "dim"
45
+ }
46
+ ];
47
+ }
48
+ function envListTargetRows(result) {
49
+ if (!("target" in result)) return [];
50
+ return [
51
+ {
52
+ key: "target source",
53
+ value: result.target.source
54
+ },
55
+ {
56
+ key: "env map",
57
+ value: result.target.envMap
58
+ },
59
+ ...result.target.branchName ? [{
60
+ key: "branch",
61
+ value: result.target.branchName
62
+ }] : [],
63
+ ...result.target.branchId ? [{
64
+ key: "branch id",
65
+ value: result.target.branchId,
66
+ tone: "dim"
67
+ }] : [],
68
+ ...result.target.branchExists === false ? [{
69
+ key: "branch state",
70
+ value: "not created yet",
71
+ tone: "warning"
72
+ }] : []
73
+ ];
74
+ }
75
+ function envFileRows(result) {
76
+ if (!("file" in result) || !result.file) return [];
77
+ return [{
78
+ key: "file",
79
+ value: result.file.path
80
+ }, {
81
+ key: "file count",
82
+ value: String(result.file.count)
83
+ }];
84
+ }
85
+ function envResultKeys(result) {
86
+ if ("variables" in result && result.variables) return result.variables.map((variable) => variable.key).sort((left, right) => left.localeCompare(right));
87
+ if ("variable" in result && result.variable) return [result.variable.key];
88
+ if ("key" in result) return [result.key];
89
+ return [];
90
+ }
91
+ function formatKeyNames(keys) {
92
+ return keys.length > 0 ? keys.join(", ") : "none";
93
+ }
7
94
  function renderEnvAdd(context, descriptor, result) {
8
- return renderShow({
95
+ if (result.variables !== void 0) {
96
+ const lines = renderList({
97
+ title: "Setting new environment variables from file.",
98
+ descriptor,
99
+ parentContext: {
100
+ key: "target",
101
+ value: `${scopeLabel(result.scope)} from ${result.file.path}`
102
+ },
103
+ items: result.variables.map((variable) => ({
104
+ noun: "variable",
105
+ label: `${variable.key} (${variable.source})`,
106
+ id: variable.id,
107
+ status: variable.isManagedBySystem ? "default" : null
108
+ })),
109
+ emptyMessage: "No environment variables imported."
110
+ }, context.ui);
111
+ lines.push(...renderEnvVerboseBlocks(context, result));
112
+ return lines;
113
+ }
114
+ const lines = renderShow({
9
115
  title: "Setting a new environment variable.",
10
116
  descriptor,
11
117
  fields: [
@@ -33,12 +139,33 @@ function renderEnvAdd(context, descriptor, result) {
33
139
  }
34
140
  ]
35
141
  }, context.ui);
142
+ lines.push(...renderEnvVerboseBlocks(context, result));
143
+ return lines;
36
144
  }
37
145
  function serializeEnvAdd(result) {
38
- return result;
146
+ return stripVerboseContext(result);
39
147
  }
40
148
  function renderEnvUpdate(context, descriptor, result) {
41
- return renderShow({
149
+ if (result.variables !== void 0) {
150
+ const lines = renderList({
151
+ title: "Replacing environment variable values from file.",
152
+ descriptor,
153
+ parentContext: {
154
+ key: "target",
155
+ value: `${scopeLabel(result.scope)} from ${result.file.path}`
156
+ },
157
+ items: result.variables.map((variable) => ({
158
+ noun: "variable",
159
+ label: `${variable.key} (${variable.source})`,
160
+ id: variable.id,
161
+ status: variable.isManagedBySystem ? "default" : null
162
+ })),
163
+ emptyMessage: "No environment variables updated."
164
+ }, context.ui);
165
+ lines.push(...renderEnvVerboseBlocks(context, result));
166
+ return lines;
167
+ }
168
+ const lines = renderShow({
42
169
  title: "Replacing the environment variable's value.",
43
170
  descriptor,
44
171
  fields: [
@@ -66,17 +193,19 @@ function renderEnvUpdate(context, descriptor, result) {
66
193
  }
67
194
  ]
68
195
  }, context.ui);
196
+ lines.push(...renderEnvVerboseBlocks(context, result));
197
+ return lines;
69
198
  }
70
199
  function serializeEnvUpdate(result) {
71
- return result;
200
+ return stripVerboseContext(result);
72
201
  }
73
202
  function renderEnvList(context, descriptor, result) {
74
- return renderList({
203
+ const lines = renderList({
75
204
  title: "Listing environment variables for the selected scope.",
76
205
  descriptor,
77
206
  parentContext: {
78
- key: "scope",
79
- value: scopeLabel(result.scope)
207
+ key: "target",
208
+ value: listTargetLabel(result)
80
209
  },
81
210
  items: result.variables.map((variable) => ({
82
211
  noun: "variable",
@@ -86,25 +215,29 @@ function renderEnvList(context, descriptor, result) {
86
215
  })),
87
216
  emptyMessage: "No environment variables defined in this scope."
88
217
  }, context.ui);
218
+ lines.push(...renderEnvVerboseBlocks(context, result));
219
+ return lines;
89
220
  }
90
221
  function serializeEnvList(result) {
222
+ const serializable = stripVerboseContext(result);
91
223
  return {
92
- projectId: result.projectId,
93
- scope: result.scope,
224
+ projectId: serializable.projectId,
225
+ scope: serializable.scope,
226
+ target: serializable.target,
94
227
  ...serializeList({
95
- context: { scope: scopeLabel(result.scope) },
96
- items: result.variables.map((variable) => ({
228
+ context: { target: listTargetLabel(serializable) },
229
+ items: serializable.variables.map((variable) => ({
97
230
  noun: "variable",
98
231
  label: `${variable.key} (${variable.source})`,
99
232
  id: variable.id,
100
233
  status: variable.isManagedBySystem ? "default" : null
101
234
  }))
102
235
  }),
103
- variables: result.variables
236
+ variables: serializable.variables
104
237
  };
105
238
  }
106
239
  function renderEnvRm(context, descriptor, result) {
107
- return renderShow({
240
+ const lines = renderShow({
108
241
  title: "Removing the environment variable from the scope.",
109
242
  descriptor,
110
243
  fields: [
@@ -122,9 +255,11 @@ function renderEnvRm(context, descriptor, result) {
122
255
  }
123
256
  ]
124
257
  }, context.ui);
258
+ lines.push(...renderEnvVerboseBlocks(context, result));
259
+ return lines;
125
260
  }
126
261
  function serializeEnvRm(result) {
127
- return result;
262
+ return stripVerboseContext(result);
128
263
  }
129
264
  //#endregion
130
265
  export { renderEnvAdd, renderEnvList, renderEnvRm, renderEnvUpdate, serializeEnvAdd, serializeEnvList, serializeEnvRm, serializeEnvUpdate };