@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,6 +1,9 @@
1
+ import { resolvePrismaCliPackageCommandSync } from "../lib/agent/cli-command.js";
2
+ import { renderVerboseBlock } from "../shell/ui.js";
1
3
  import { renderDeployOutputRows } from "../lib/app/deploy-output.js";
2
4
  import { formatDomainFailureFix } from "../lib/app/domain-guidance.js";
3
5
  import { renderList, renderShow, serializeList } from "../output/patterns.js";
6
+ import { renderResolvedProjectContextBlock, stripVerboseContext } from "./verbose-context.js";
4
7
  //#region src/presenters/app.ts
5
8
  function renderAppBuild(context, descriptor, result) {
6
9
  return renderShow({
@@ -26,27 +29,192 @@ function renderAppBuild(context, descriptor, result) {
26
29
  function serializeAppBuild(result) {
27
30
  return result;
28
31
  }
29
- function renderAppDeploy(context, descriptor, result) {
32
+ function renderAppDeploy(context, descriptor, result, options) {
33
+ const logsCommand = options?.logsTarget ? `prisma-cli app logs ${options.logsTarget}` : "prisma-cli app logs";
30
34
  return [
31
- `Live in ${formatDuration(result.durationMs)}`,
32
- ...result.deployment.url ? [context.ui.link(result.deployment.url)] : [],
35
+ ...result.promoted ? [`Live in ${formatDuration(result.durationMs)}`, ...result.deployment.url ? [context.ui.link(result.deployment.url)] : []] : [
36
+ `Built ${result.deployment.id} in ${formatDuration(result.durationMs)} (not promoted)`,
37
+ ...result.deployment.url ? [context.ui.link(result.deployment.url)] : [],
38
+ context.ui.dim("The live deployment is unchanged.")
39
+ ],
40
+ ...renderBranchDatabaseDeploySummary(context, result),
33
41
  "",
34
- ...renderDeployOutputRows(context.ui, [{
35
- label: "Logs",
36
- value: "prisma-cli app logs"
37
- }])
42
+ ...renderDeployOutputRows(context.ui, [
43
+ ...result.promoted ? [] : [{
44
+ label: "Promote",
45
+ value: `prisma-cli app promote ${result.deployment.id}`
46
+ }],
47
+ {
48
+ label: "Logs",
49
+ value: logsCommand
50
+ },
51
+ ...result.deploySettings.region && result.deploySettings.regionSource === null ? [{
52
+ label: "Region",
53
+ value: result.deploySettings.region,
54
+ origin: result.project.defaultRegion != null ? "project default" : "platform default — pass --region to choose"
55
+ }] : [],
56
+ ...deployUsedComputeConfig(result) ? [] : [{
57
+ label: "Config",
58
+ value: resolvePrismaCliPackageCommandSync(context.runtime.cwd, ["init"])
59
+ }]
60
+ ]),
61
+ ...renderDeployResolvedContextBlock(context, result),
62
+ ...renderDeploySettingsBlock(context, result)
38
63
  ];
39
64
  }
65
+ function deployUsedComputeConfig(result) {
66
+ return result.deploySettings.config.path !== null || [
67
+ result.deploySettings.framework.source,
68
+ result.deploySettings.buildCommand.source,
69
+ result.deploySettings.outputDirectory.source
70
+ ].some((source) => source?.includes("prisma.compute"));
71
+ }
72
+ function isAppDeployAllResult(result) {
73
+ return "deployments" in result;
74
+ }
75
+ function renderAppDeployAll(context, descriptor, result) {
76
+ const lines = [];
77
+ for (const deployment of result.deployments) {
78
+ lines.push(deployment.target);
79
+ lines.push(...renderAppDeploy(context, descriptor, deployment.result, { logsTarget: deployment.target }).map((line) => line ? ` ${line}` : line));
80
+ lines.push("");
81
+ }
82
+ lines.push(...renderDeployOutputRows(context.ui, result.deployments.map((deployment) => ({
83
+ label: deployment.target,
84
+ value: deployment.result.deployment.url ?? deployment.result.deployment.id
85
+ }))));
86
+ return lines;
87
+ }
88
+ function serializeAppDeployAll(result) {
89
+ return {
90
+ count: result.deployments.length,
91
+ deployments: result.deployments.map((deployment) => ({
92
+ target: deployment.target,
93
+ ...serializeAppDeploy(deployment.result)
94
+ }))
95
+ };
96
+ }
40
97
  function serializeAppDeploy(result) {
41
- const { localPin: _localPin, ...serialized } = result;
42
- return serialized;
98
+ const { deploySettings, localPin: _localPin, ...serialized } = result;
99
+ const { id: _branchId, ...branch } = serialized.branch;
100
+ return {
101
+ ...serialized,
102
+ branch,
103
+ deploySettings: {
104
+ config: deploySettings.config,
105
+ buildCommand: deploySettings.buildCommand,
106
+ outputDirectory: deploySettings.outputDirectory
107
+ }
108
+ };
109
+ }
110
+ function renderBranchDatabaseDeploySummary(context, result) {
111
+ if (!result.branchDatabase || result.branchDatabase.status !== "created") return [];
112
+ return ["", ...renderDeployOutputRows(context.ui, [{
113
+ label: "Database",
114
+ value: result.branchDatabase.database?.name ?? "created"
115
+ }, {
116
+ label: "Env",
117
+ value: result.branchDatabase.envVars.join(", ")
118
+ }])];
43
119
  }
44
120
  function formatDuration(durationMs) {
45
121
  if (durationMs < 1e3) return `${durationMs}ms`;
46
122
  return `${(durationMs / 1e3).toFixed(1)}s`;
47
123
  }
124
+ function renderDeployResolvedContextBlock(context, result) {
125
+ return renderResolvedProjectContextBlock(context.ui, {
126
+ workspace: result.workspace,
127
+ project: result.project,
128
+ resolution: result.resolution,
129
+ branch: {
130
+ id: result.branch.id,
131
+ name: result.branch.name,
132
+ kind: result.branch.kind
133
+ }
134
+ }, { extraRows: [
135
+ {
136
+ key: "app",
137
+ value: result.app.name
138
+ },
139
+ {
140
+ key: "app id",
141
+ value: result.app.id,
142
+ tone: "dim"
143
+ },
144
+ {
145
+ key: "deployment id",
146
+ value: result.deployment.id,
147
+ tone: "dim"
148
+ },
149
+ {
150
+ key: "deployment status",
151
+ value: result.deployment.status
152
+ },
153
+ ...result.localPin ? [{
154
+ key: "local pin",
155
+ value: result.localPin.path
156
+ }] : [],
157
+ {
158
+ key: "deploy duration",
159
+ value: formatDuration(result.durationMs)
160
+ }
161
+ ] });
162
+ }
163
+ function renderDeploySettingsBlock(context, result) {
164
+ return renderVerboseBlock(context.ui, [...deploySettingsRows(result.deploySettings), ...branchDatabaseRows(result.branchDatabase)], { title: "Deploy settings" });
165
+ }
166
+ function deploySettingsRows(settings) {
167
+ return [
168
+ {
169
+ key: "framework",
170
+ value: `${settings.framework.name} (${settings.framework.buildType})`
171
+ },
172
+ {
173
+ key: "framework source",
174
+ value: settings.framework.source,
175
+ tone: "dim"
176
+ },
177
+ {
178
+ key: "entrypoint",
179
+ value: settings.entrypoint ?? "derived from build output",
180
+ tone: settings.entrypoint ? "default" : "dim"
181
+ },
182
+ {
183
+ key: "http port",
184
+ value: String(settings.httpPort)
185
+ },
186
+ {
187
+ key: "region",
188
+ value: settings.region ?? "existing app region",
189
+ tone: settings.region ? "default" : "dim"
190
+ },
191
+ {
192
+ key: "env vars",
193
+ value: formatEnvVarNames(settings.envVars),
194
+ tone: settings.envVars.length > 0 ? "default" : "dim"
195
+ }
196
+ ];
197
+ }
198
+ function branchDatabaseRows(branchDatabase) {
199
+ if (!branchDatabase) return [{
200
+ key: "branch db",
201
+ value: "not configured",
202
+ tone: "dim"
203
+ }];
204
+ return [{
205
+ key: "branch db",
206
+ value: branchDatabase.status === "created" ? `created${branchDatabase.database ? ` (${branchDatabase.database.name})` : ""}` : `skipped${branchDatabase.reason ? ` (${branchDatabase.reason})` : ""}`,
207
+ tone: branchDatabase.status === "created" ? "success" : "dim"
208
+ }, ...branchDatabase.envVars.length > 0 ? [{
209
+ key: "branch db env",
210
+ value: branchDatabase.envVars.join(", ")
211
+ }] : []];
212
+ }
213
+ function formatEnvVarNames(envVars) {
214
+ return envVars.length > 0 ? envVars.join(", ") : "none";
215
+ }
48
216
  function renderAppListDeploys(context, descriptor, result) {
49
- return renderList({
217
+ const lines = renderList({
50
218
  title: "Listing deployments for the selected app.",
51
219
  descriptor,
52
220
  parentContext: {
@@ -61,20 +229,23 @@ function renderAppListDeploys(context, descriptor, result) {
61
229
  })),
62
230
  emptyMessage: result.app ? "No deployments found." : "No apps found."
63
231
  }, context.ui);
232
+ lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
233
+ return lines;
64
234
  }
65
235
  function serializeAppListDeploys(result) {
66
- if (!result.app) return {
67
- projectId: result.projectId,
236
+ const { verboseContext: _verboseContext, ...serializable } = result;
237
+ if (!serializable.app) return {
238
+ projectId: serializable.projectId,
68
239
  app: null,
69
240
  items: [],
70
241
  count: 0
71
242
  };
72
243
  return {
73
- projectId: result.projectId,
74
- app: result.app,
244
+ projectId: serializable.projectId,
245
+ app: serializable.app,
75
246
  ...serializeList({
76
- context: { app: result.app.name },
77
- items: result.deployments.map((deployment) => ({
247
+ context: { app: serializable.app.name },
248
+ items: serializable.deployments.map((deployment) => ({
78
249
  noun: "deployment",
79
250
  label: deployment.id,
80
251
  id: deployment.id,
@@ -84,7 +255,7 @@ function serializeAppListDeploys(result) {
84
255
  };
85
256
  }
86
257
  function renderAppShow(context, descriptor, result) {
87
- return renderShow({
258
+ const lines = renderShow({
88
259
  title: "Showing the selected app state.",
89
260
  descriptor,
90
261
  fields: [
@@ -114,9 +285,11 @@ function renderAppShow(context, descriptor, result) {
114
285
  }
115
286
  ]
116
287
  }, context.ui);
288
+ lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
289
+ return lines;
117
290
  }
118
291
  function serializeAppShow(result) {
119
- return result;
292
+ return stripVerboseContext(result);
120
293
  }
121
294
  function renderAppShowDeploy(context, descriptor, result) {
122
295
  return renderShow({
@@ -158,7 +331,7 @@ function serializeAppShowDeploy(result) {
158
331
  return result;
159
332
  }
160
333
  function renderAppOpen(context, descriptor, result) {
161
- return renderShow({
334
+ const lines = renderShow({
162
335
  title: result.opened ? "Opening the live URL for the selected app." : "Resolving the live URL for the selected app.",
163
336
  descriptor,
164
337
  fields: [
@@ -182,9 +355,11 @@ function renderAppOpen(context, descriptor, result) {
182
355
  }
183
356
  ]
184
357
  }, context.ui);
358
+ lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
359
+ return lines;
185
360
  }
186
361
  function serializeAppOpen(result) {
187
- return result;
362
+ return stripVerboseContext(result);
188
363
  }
189
364
  function renderAppDomainAdd(context, descriptor, result) {
190
365
  return renderShow({
@@ -286,7 +461,7 @@ function serializeAppDomainRetry(result) {
286
461
  return result;
287
462
  }
288
463
  function renderAppPromote(context, descriptor, result) {
289
- return renderShow({
464
+ const lines = renderShow({
290
465
  title: "Switching the live deployment for the selected app.",
291
466
  descriptor,
292
467
  fields: [
@@ -324,12 +499,14 @@ function renderAppPromote(context, descriptor, result) {
324
499
  }
325
500
  ]
326
501
  }, context.ui);
502
+ lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
503
+ return lines;
327
504
  }
328
505
  function serializeAppPromote(result) {
329
- return result;
506
+ return stripVerboseContext(result);
330
507
  }
331
508
  function renderAppRollback(context, descriptor, result) {
332
- return renderShow({
509
+ const lines = renderShow({
333
510
  title: "Restoring the selected app to an earlier deployment.",
334
511
  descriptor,
335
512
  fields: [
@@ -372,9 +549,11 @@ function renderAppRollback(context, descriptor, result) {
372
549
  }] : []
373
550
  ]
374
551
  }, context.ui);
552
+ lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
553
+ return lines;
375
554
  }
376
555
  function serializeAppRollback(result) {
377
- return result;
556
+ return stripVerboseContext(result);
378
557
  }
379
558
  function renderAppRun(_context, _descriptor, _result) {
380
559
  return [];
@@ -383,7 +562,7 @@ function serializeAppRun(result) {
383
562
  return result;
384
563
  }
385
564
  function renderAppRemove(context, descriptor, result) {
386
- return renderShow({
565
+ const lines = renderShow({
387
566
  title: "Removing the selected app.",
388
567
  descriptor,
389
568
  fields: [
@@ -402,9 +581,11 @@ function renderAppRemove(context, descriptor, result) {
402
581
  }
403
582
  ]
404
583
  }, context.ui);
584
+ lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
585
+ return lines;
405
586
  }
406
587
  function serializeAppRemove(result) {
407
- return result;
588
+ return stripVerboseContext(result);
408
589
  }
409
590
  function toneForStatus(status) {
410
591
  if (status === "running" || status === "ready" || status === "healthy") return "success";
@@ -488,4 +669,4 @@ function formatRecentDeployments(deployments) {
488
669
  return deployments.map((deployment) => `${deployment.id}${deployment.live ? " (live)" : ""}`).join(", ");
489
670
  }
490
671
  //#endregion
491
- 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 };
672
+ 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 };
@@ -1,4 +1,7 @@
1
+ import { formatDescriptorLabel } from "../shell/command-meta.js";
2
+ import { padDisplay } from "../shell/ui.js";
1
3
  import { renderMutate, renderShow } from "../output/patterns.js";
4
+ import stringWidth from "string-width";
2
5
  //#region src/presenters/auth.ts
3
6
  function renderAuthSuccess(context, descriptor, command, result) {
4
7
  if (command === "auth.login") {
@@ -22,7 +25,7 @@ function renderAuthSuccess(context, descriptor, command, result) {
22
25
  context: rows,
23
26
  operationDescription: "Applying authentication session changes",
24
27
  operationCount: 1,
25
- details: ["Session stored in local CLI state."]
28
+ details: ["Session stored in local CLI state.", ...result.agentSetupTip ? [`Install Prisma skills for this project with ${result.agentSetupTip.command}.`] : []]
26
29
  }, context.ui);
27
30
  }
28
31
  if (command === "auth.logout") return renderMutate({
@@ -62,11 +65,105 @@ function renderAuthSuccess(context, descriptor, command, result) {
62
65
  }]
63
66
  }, context.ui);
64
67
  }
68
+ function renderAuthWorkspaceList(context, descriptor, result) {
69
+ const ui = context.ui;
70
+ const rail = ui.dim("│");
71
+ const lines = [
72
+ `${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim("Listing authenticated workspaces on this machine.")}`,
73
+ "",
74
+ `${rail} ${ui.accent("auth source:")} ${authSourceLabel(result.authSource)}`
75
+ ];
76
+ const hasMixedSources = new Set(result.workspaces.map((workspace) => workspace.source)).size > 1;
77
+ if (result.workspaces.length === 0) {
78
+ lines.push(`${rail} ${ui.dim("No local OAuth workspaces found.")}`);
79
+ return lines;
80
+ }
81
+ const nameWidth = Math.max(4, ...result.workspaces.map((workspace) => stringWidth(workspace.name)));
82
+ const idWidth = Math.max(2, ...result.workspaces.map((workspace) => stringWidth(workspace.id)));
83
+ const sourceWidth = hasMixedSources ? Math.max(6, ...result.workspaces.map((workspace) => stringWidth(workspaceSourceLabel(workspace.source)))) : 0;
84
+ lines.push(rail);
85
+ lines.push(hasMixedSources ? `${rail} ${ui.accent(padDisplay("name", nameWidth))} ${ui.accent(padDisplay("id", idWidth))} ${ui.accent(padDisplay("source", sourceWidth))} ${ui.accent("status")}` : `${rail} ${ui.accent(padDisplay("name", nameWidth))} ${ui.accent(padDisplay("id", idWidth))} ${ui.accent("status")}`);
86
+ for (const workspace of result.workspaces) {
87
+ const status = workspace.active ? "active" : "";
88
+ const source = workspaceSourceLabel(workspace.source);
89
+ lines.push(hasMixedSources ? `${rail} ${padDisplay(workspace.name, nameWidth)} ${padDisplay(workspace.id, idWidth)} ${padDisplay(source, sourceWidth)} ${status}` : `${rail} ${padDisplay(workspace.name, nameWidth)} ${padDisplay(workspace.id, idWidth)} ${status}`);
90
+ }
91
+ return lines;
92
+ }
93
+ function serializeAuthWorkspaceList(result) {
94
+ return {
95
+ context: {
96
+ authSource: result.authSource,
97
+ activeWorkspaceId: result.activeWorkspace?.id ?? null,
98
+ activeWorkspaceName: result.activeWorkspace?.name ?? null
99
+ },
100
+ items: result.workspaces.map((workspace) => ({
101
+ id: workspace.id,
102
+ name: workspace.name,
103
+ status: workspace.active ? "active" : null,
104
+ source: workspace.source,
105
+ switchable: workspace.switchable,
106
+ credentialWorkspaceId: workspace.credentialWorkspaceId,
107
+ lastSeenAt: workspace.lastSeenAt
108
+ })),
109
+ count: result.workspaces.length
110
+ };
111
+ }
112
+ function renderAuthWorkspaceUse(context, descriptor, result) {
113
+ return renderMutate({
114
+ title: "Switching the local CLI workspace.",
115
+ descriptor,
116
+ context: [...result.previousWorkspace ? [{
117
+ key: "previous",
118
+ value: result.previousWorkspace.name
119
+ }] : [], {
120
+ key: "workspace",
121
+ value: result.workspace.name
122
+ }],
123
+ operationDescription: "Applying workspace selection",
124
+ operationCount: 1,
125
+ details: ["Local OAuth workspace selection updated."]
126
+ }, context.ui);
127
+ }
128
+ function serializeAuthWorkspaceUse(result) {
129
+ return result;
130
+ }
131
+ function renderAuthWorkspaceLogout(context, descriptor, result) {
132
+ return renderMutate({
133
+ title: "Removing a local OAuth workspace session.",
134
+ descriptor,
135
+ context: [{
136
+ key: "workspace",
137
+ value: result.workspace.name
138
+ }, ...result.activeWorkspace ? [{
139
+ key: "active",
140
+ value: result.activeWorkspace.name
141
+ }] : [{
142
+ key: "active",
143
+ value: "none",
144
+ tone: "dim"
145
+ }]],
146
+ operationDescription: "Removing workspace session",
147
+ operationCount: 1,
148
+ details: [result.wasActive ? "Removed active workspace session; no replacement workspace was selected." : "Removed workspace session."]
149
+ }, context.ui);
150
+ }
151
+ function serializeAuthWorkspaceLogout(result) {
152
+ return result;
153
+ }
65
154
  function providerLabel(provider) {
66
155
  if (provider === "github") return "GitHub";
67
156
  if (provider === "google") return "Google";
68
157
  return "";
69
158
  }
159
+ function authSourceLabel(source) {
160
+ if (source === "oauth") return "local OAuth";
161
+ if (source === "service_token") return "PRISMA_SERVICE_TOKEN";
162
+ return "none";
163
+ }
164
+ function workspaceSourceLabel(source) {
165
+ return source === "service_token" ? "service token" : "OAuth";
166
+ }
70
167
  function authUserLabel(result) {
71
168
  return result.user?.email ?? credentialUserLabel(result);
72
169
  }
@@ -83,4 +180,4 @@ function credentialUserLabel(result) {
83
180
  return null;
84
181
  }
85
182
  //#endregion
86
- export { renderAuthSuccess };
183
+ export { renderAuthSuccess, renderAuthWorkspaceList, renderAuthWorkspaceLogout, renderAuthWorkspaceUse, serializeAuthWorkspaceList, serializeAuthWorkspaceLogout, serializeAuthWorkspaceUse };
@@ -1,111 +1,46 @@
1
- import { renderList, renderMutate, renderShow, serializeList } from "../output/patterns.js";
1
+ import { formatDescriptorLabel } from "../shell/command-meta.js";
2
+ import { formatColumns } from "../shell/ui.js";
3
+ import { renderResolvedProjectContextBlock } from "./verbose-context.js";
2
4
  //#region src/presenters/branch.ts
3
5
  function renderBranchList(context, descriptor, result) {
4
- return renderList({
5
- title: "Listing branches for the resolved project.",
6
- descriptor,
7
- parentContext: {
8
- key: "project",
9
- value: result.projectName ?? "not resolved"
10
- },
11
- items: result.branches.map((branch) => ({
12
- noun: "branch",
13
- label: branch.name,
14
- id: branch.id,
15
- status: branch.active ? "active" : null
16
- })),
17
- emptyMessage: "No branches found."
18
- }, context.ui);
6
+ const ui = context.ui;
7
+ const lines = [`${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim("Listing branches for the resolved project.")}`, ""];
8
+ const rail = ui.dim("│");
9
+ lines.push(`${rail} ${ui.accent("project:")} ${result.projectName}`);
10
+ lines.push(rail);
11
+ if (result.branches.length === 0) {
12
+ lines.push(`${rail} ${ui.dim("No branches found.")}`);
13
+ lines.push(...renderBranchResolvedContextBlock(context, result));
14
+ return lines;
15
+ }
16
+ const widths = [
17
+ Math.max(4, ...result.branches.map((branch) => branch.name.length)),
18
+ Math.max(4, ...result.branches.map((branch) => branch.role.length)),
19
+ Math.max(7, ...result.branches.map((branch) => branch.envMap.length))
20
+ ];
21
+ lines.push(`${rail} ${ui.accent(formatColumns([
22
+ "Name",
23
+ "Role",
24
+ "Env map"
25
+ ], widths))}`);
26
+ for (const branch of result.branches) lines.push(`${rail} ${formatColumns([
27
+ branch.name,
28
+ branch.role,
29
+ branch.envMap
30
+ ], widths)}`);
31
+ lines.push(...renderBranchResolvedContextBlock(context, result));
32
+ return lines;
19
33
  }
20
34
  function serializeBranchList(result) {
21
- return serializeList({
22
- context: { project: result.projectName ?? "not resolved" },
23
- items: result.branches.map((branch) => ({
24
- noun: "branch",
25
- label: branch.name,
26
- id: branch.id,
27
- status: branch.active ? "active" : null
28
- }))
29
- });
30
- }
31
- function serializeBranchShow(result) {
35
+ const { verboseContext: _verboseContext, ...serializable } = result;
32
36
  return {
33
- projectId: result.projectId,
34
- projectName: result.projectName,
35
- branch: {
36
- name: result.branch.name,
37
- kind: result.branch.kind,
38
- active: result.branch.active,
39
- remoteState: result.branch.remoteState,
40
- liveDeployment: result.branch.liveDeployment
41
- }
37
+ projectId: serializable.projectId,
38
+ projectName: serializable.projectName,
39
+ branches: serializable.branches
42
40
  };
43
41
  }
44
- function renderBranchShow(context, descriptor, result) {
45
- const fields = [
46
- {
47
- key: "project",
48
- value: result.projectName ?? "not resolved",
49
- tone: result.projectName ? "default" : "dim"
50
- },
51
- {
52
- key: "branch",
53
- value: result.branch.name,
54
- tone: result.branch.active ? "success" : "default"
55
- },
56
- {
57
- key: "kind",
58
- value: result.branch.kind
59
- }
60
- ];
61
- if (result.branch.liveDeployment) {
62
- fields.push({
63
- key: "status",
64
- value: result.branch.liveDeployment.status,
65
- tone: toneForDeploymentStatus(result.branch.liveDeployment.status)
66
- });
67
- if (result.branch.liveDeployment.url) fields.push({
68
- key: "url",
69
- value: result.branch.liveDeployment.url,
70
- tone: "link"
71
- });
72
- } else if (!result.branch.remoteState) fields.push({
73
- key: "remote state",
74
- value: "not created yet",
75
- tone: "dim"
76
- });
77
- return renderShow({
78
- title: "Showing the current active branch context.",
79
- descriptor,
80
- fields
81
- }, context.ui);
82
- }
83
- function toneForDeploymentStatus(status) {
84
- if (status === "ready" || status === "active" || status === "healthy") return "success";
85
- if (status === "pending" || status === "building" || status === "starting") return "warning";
86
- if (status === "failed" || status === "error") return "error";
87
- return "default";
88
- }
89
- function renderBranchUse(context, descriptor, result) {
90
- return renderMutate({
91
- title: "Changing the local default branch context.",
92
- descriptor,
93
- context: [{
94
- key: "project",
95
- value: result.projectName ?? "not resolved",
96
- tone: result.projectName ? "default" : "dim"
97
- }, {
98
- key: "branch",
99
- value: result.branch.name
100
- }],
101
- operationDescription: "Applying active branch change",
102
- operationCount: 1,
103
- details: ["Active branch updated in local CLI state for this repo."],
104
- alerts: result.branch.kind === "production" ? [{
105
- tone: "warning",
106
- text: "Production is protected and durable. Use with care"
107
- }] : void 0
108
- }, context.ui);
42
+ function renderBranchResolvedContextBlock(context, result) {
43
+ return renderResolvedProjectContextBlock(context.ui, result.verboseContext);
109
44
  }
110
45
  //#endregion
111
- export { renderBranchList, renderBranchShow, renderBranchUse, serializeBranchList, serializeBranchShow };
46
+ export { renderBranchList, serializeBranchList };