@looma/prisma-cli 0.1.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.
- package/README.md +39 -0
- package/dist/adapters/config.js +74 -0
- package/dist/adapters/local-state.js +98 -0
- package/dist/adapters/mock-api.js +57 -0
- package/dist/adapters/token-storage.js +43 -0
- package/dist/cli.js +9 -0
- package/dist/cli2.js +59 -0
- package/dist/commands/app/index.js +178 -0
- package/dist/commands/auth/index.js +42 -0
- package/dist/commands/env/index.js +51 -0
- package/dist/commands/project/index.js +45 -0
- package/dist/controllers/app.js +658 -0
- package/dist/controllers/auth.js +107 -0
- package/dist/controllers/env.js +73 -0
- package/dist/controllers/project.js +214 -0
- package/dist/controllers/select-prompt-port.js +12 -0
- package/dist/lib/app/local-dev.js +178 -0
- package/dist/lib/app/prototype-build.js +109 -0
- package/dist/lib/app/prototype-interaction.js +38 -0
- package/dist/lib/app/prototype-progress.js +115 -0
- package/dist/lib/app/prototype-provider.js +163 -0
- package/dist/lib/auth/auth-ops.js +57 -0
- package/dist/lib/auth/client.js +22 -0
- package/dist/lib/auth/guard.js +34 -0
- package/dist/lib/auth/login.js +117 -0
- package/dist/output/patterns.js +93 -0
- package/dist/presenters/app.js +333 -0
- package/dist/presenters/auth.js +73 -0
- package/dist/presenters/env.js +111 -0
- package/dist/presenters/project.js +84 -0
- package/dist/shell/command-meta.js +294 -0
- package/dist/shell/command-runner.js +33 -0
- package/dist/shell/errors.js +64 -0
- package/dist/shell/global-flags.js +25 -0
- package/dist/shell/help.js +78 -0
- package/dist/shell/output.js +48 -0
- package/dist/shell/prompt.js +31 -0
- package/dist/shell/runtime.js +51 -0
- package/dist/shell/ui.js +59 -0
- package/dist/use-cases/auth.js +70 -0
- package/dist/use-cases/create-cli-gateways.js +93 -0
- package/dist/use-cases/env.js +104 -0
- package/dist/use-cases/project.js +75 -0
- package/package.json +30 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { formatDescriptorLabel } from "../shell/command-meta.js";
|
|
2
|
+
import { maskValue, padDisplay, renderSummaryLine } from "../shell/ui.js";
|
|
3
|
+
import stringWidth from "string-width";
|
|
4
|
+
//#region src/output/patterns.ts
|
|
5
|
+
function renderList(input, ui) {
|
|
6
|
+
const keyWidth = Math.max(stringWidth(`${input.parentContext.key}:`), ...input.items.map((item) => stringWidth(`⚬ ${item.noun}:`)), stringWidth("Read more"));
|
|
7
|
+
const lines = renderCardTitle(input.descriptor, input.title, ui);
|
|
8
|
+
lines.push(renderCardRow(ui, keyWidth, input.parentContext.key, input.parentContext.value));
|
|
9
|
+
if (input.items.length === 0) lines.push(renderPlainCardLine(ui, ui.dim(input.emptyMessage)));
|
|
10
|
+
else for (const item of input.items) lines.push(renderCardRow(ui, keyWidth, `⚬ ${item.noun}`, formatListItemValue(ui, item)));
|
|
11
|
+
lines.push(renderCardDivider(ui));
|
|
12
|
+
lines.push(renderReadMore(ui, keyWidth, input.descriptor));
|
|
13
|
+
return lines;
|
|
14
|
+
}
|
|
15
|
+
function serializeList(input) {
|
|
16
|
+
return {
|
|
17
|
+
context: input.context,
|
|
18
|
+
items: input.items.map((item) => ({
|
|
19
|
+
name: item.label,
|
|
20
|
+
id: item.id,
|
|
21
|
+
status: item.status
|
|
22
|
+
})),
|
|
23
|
+
count: input.items.length
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function renderShow(input, ui) {
|
|
27
|
+
const keyWidth = Math.max(...input.fields.map((field) => stringWidth(`${field.key}:`)), stringWidth("Read more"));
|
|
28
|
+
const lines = renderCardTitle(input.descriptor, input.title, ui);
|
|
29
|
+
for (const field of input.fields) lines.push(renderCardRow(ui, keyWidth, field.key, formatValue(ui, field.value, field.tone, field.sensitive)));
|
|
30
|
+
lines.push(renderCardDivider(ui));
|
|
31
|
+
lines.push(renderReadMore(ui, keyWidth, input.descriptor));
|
|
32
|
+
return lines;
|
|
33
|
+
}
|
|
34
|
+
function renderMutate(input, ui) {
|
|
35
|
+
const rows = [...input.context, {
|
|
36
|
+
key: "mode",
|
|
37
|
+
value: "apply",
|
|
38
|
+
tone: "dim"
|
|
39
|
+
}];
|
|
40
|
+
const keyWidth = Math.max(...rows.map((row) => stringWidth(`${row.key}:`)), stringWidth("Read more"));
|
|
41
|
+
const lines = renderCardTitle(input.descriptor, input.title, ui);
|
|
42
|
+
for (const row of rows) lines.push(renderCardRow(ui, keyWidth, row.key, formatValue(ui, row.value, row.tone, row.sensitive)));
|
|
43
|
+
lines.push(renderCardDivider(ui));
|
|
44
|
+
lines.push(renderReadMore(ui, keyWidth, input.descriptor));
|
|
45
|
+
lines.push("");
|
|
46
|
+
lines.push(`${ui.warning("◇")} ${input.operationDescription}...`);
|
|
47
|
+
lines.push(renderSummaryLine(ui, "success", `Applied ${input.operationCount} operation(s)`));
|
|
48
|
+
for (const detail of input.details) lines.push(` ${detail}`);
|
|
49
|
+
for (const alert of input.alerts ?? []) {
|
|
50
|
+
lines.push("");
|
|
51
|
+
lines.push(renderSummaryLine(ui, alert.tone, alert.text));
|
|
52
|
+
}
|
|
53
|
+
return lines;
|
|
54
|
+
}
|
|
55
|
+
function renderCardTitle(descriptor, title, ui) {
|
|
56
|
+
return [`${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim(title)}`, ""];
|
|
57
|
+
}
|
|
58
|
+
function renderCardRow(ui, keyWidth, key, value) {
|
|
59
|
+
return `${renderCardRail(ui)} ${ui.accent(padDisplay(`${key}:`, keyWidth))} ${value}`;
|
|
60
|
+
}
|
|
61
|
+
function renderPlainCardLine(ui, text) {
|
|
62
|
+
return `${renderCardRail(ui)} ${text}`;
|
|
63
|
+
}
|
|
64
|
+
function renderCardDivider(ui) {
|
|
65
|
+
return renderCardRail(ui);
|
|
66
|
+
}
|
|
67
|
+
function renderReadMore(ui, keyWidth, descriptor) {
|
|
68
|
+
return `${renderCardRail(ui)} ${ui.accent(padDisplay("Read more", keyWidth))} ${ui.link(descriptor.docsPath ?? "")}`;
|
|
69
|
+
}
|
|
70
|
+
function renderCardRail(ui) {
|
|
71
|
+
return ui.dim("│");
|
|
72
|
+
}
|
|
73
|
+
function formatListItemValue(ui, item) {
|
|
74
|
+
const annotation = renderAnnotation(ui, item.status);
|
|
75
|
+
return annotation ? `${item.label} ${annotation}` : item.label;
|
|
76
|
+
}
|
|
77
|
+
function renderAnnotation(ui, status) {
|
|
78
|
+
if (status === "active") return ui.success("(active)");
|
|
79
|
+
if (status === "linked") return ui.accent("(linked)");
|
|
80
|
+
if (status === "default") return ui.dim("(default)");
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
function formatValue(ui, value, tone = "default", sensitive = false) {
|
|
84
|
+
const resolvedValue = sensitive ? maskValue(value) : value;
|
|
85
|
+
if (tone === "success") return ui.success(resolvedValue);
|
|
86
|
+
if (tone === "warning") return ui.warning(resolvedValue);
|
|
87
|
+
if (tone === "error") return ui.error(resolvedValue);
|
|
88
|
+
if (tone === "link") return ui.link(resolvedValue);
|
|
89
|
+
if (tone === "dim") return ui.dim(resolvedValue);
|
|
90
|
+
return resolvedValue;
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { renderList, renderMutate, renderShow, serializeList };
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { renderList, renderShow, serializeList } from "../output/patterns.js";
|
|
2
|
+
//#region src/presenters/app.ts
|
|
3
|
+
function renderAppBuild(context, descriptor, result) {
|
|
4
|
+
return renderShow({
|
|
5
|
+
title: "Building the local app artifact.",
|
|
6
|
+
descriptor,
|
|
7
|
+
fields: [
|
|
8
|
+
{
|
|
9
|
+
key: "build type",
|
|
10
|
+
value: result.buildType
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
key: "entrypoint",
|
|
14
|
+
value: result.entrypoint ?? "none",
|
|
15
|
+
tone: result.entrypoint ? "default" : "dim"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
key: "directory",
|
|
19
|
+
value: result.directory
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}, context.ui);
|
|
23
|
+
}
|
|
24
|
+
function serializeAppBuild(result) {
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
function renderAppDeploy(context, descriptor, result) {
|
|
28
|
+
return renderShow({
|
|
29
|
+
title: "Deploying the selected app.",
|
|
30
|
+
descriptor,
|
|
31
|
+
fields: [
|
|
32
|
+
{
|
|
33
|
+
key: "project",
|
|
34
|
+
value: result.projectId
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: "app",
|
|
38
|
+
value: result.app.name
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "deployment",
|
|
42
|
+
value: result.deployment.id
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
key: "status",
|
|
46
|
+
value: result.deployment.status,
|
|
47
|
+
tone: toneForStatus(result.deployment.status)
|
|
48
|
+
},
|
|
49
|
+
...result.deployment.url ? [{
|
|
50
|
+
key: "url",
|
|
51
|
+
value: result.deployment.url,
|
|
52
|
+
tone: "link"
|
|
53
|
+
}] : []
|
|
54
|
+
]
|
|
55
|
+
}, context.ui);
|
|
56
|
+
}
|
|
57
|
+
function serializeAppDeploy(result) {
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
function renderAppListDeploys(context, descriptor, result) {
|
|
61
|
+
return renderList({
|
|
62
|
+
title: "Listing deployments for the selected app.",
|
|
63
|
+
descriptor,
|
|
64
|
+
parentContext: {
|
|
65
|
+
key: "app",
|
|
66
|
+
value: result.app?.name ?? "not selected"
|
|
67
|
+
},
|
|
68
|
+
items: result.deployments.map((deployment) => ({
|
|
69
|
+
noun: "deployment",
|
|
70
|
+
label: deployment.id,
|
|
71
|
+
id: deployment.id,
|
|
72
|
+
status: deployment.live ? "active" : null
|
|
73
|
+
})),
|
|
74
|
+
emptyMessage: result.app ? "No deployments found." : "No apps found."
|
|
75
|
+
}, context.ui);
|
|
76
|
+
}
|
|
77
|
+
function serializeAppListDeploys(result) {
|
|
78
|
+
if (!result.app) return {
|
|
79
|
+
projectId: result.projectId,
|
|
80
|
+
app: null,
|
|
81
|
+
items: [],
|
|
82
|
+
count: 0
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
projectId: result.projectId,
|
|
86
|
+
app: result.app,
|
|
87
|
+
...serializeList({
|
|
88
|
+
context: { app: result.app.name },
|
|
89
|
+
items: result.deployments.map((deployment) => ({
|
|
90
|
+
noun: "deployment",
|
|
91
|
+
label: deployment.id,
|
|
92
|
+
id: deployment.id,
|
|
93
|
+
status: deployment.live ? "active" : null
|
|
94
|
+
}))
|
|
95
|
+
})
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function renderAppShow(context, descriptor, result) {
|
|
99
|
+
return renderShow({
|
|
100
|
+
title: "Showing the selected app state.",
|
|
101
|
+
descriptor,
|
|
102
|
+
fields: [
|
|
103
|
+
{
|
|
104
|
+
key: "project",
|
|
105
|
+
value: result.projectId
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
key: "app",
|
|
109
|
+
value: result.app?.name ?? "not selected",
|
|
110
|
+
tone: result.app ? "default" : "dim"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
key: "live deployment",
|
|
114
|
+
value: result.liveDeployment?.id ?? "none",
|
|
115
|
+
tone: result.liveDeployment ? toneForStatus(result.liveDeployment.status) : "dim"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
key: "live url",
|
|
119
|
+
value: result.liveUrl ?? "unavailable",
|
|
120
|
+
tone: result.liveUrl ? "link" : "dim"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: "recent deployments",
|
|
124
|
+
value: formatRecentDeployments(result.recentDeployments),
|
|
125
|
+
tone: result.recentDeployments.length > 0 ? "default" : "dim"
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}, context.ui);
|
|
129
|
+
}
|
|
130
|
+
function serializeAppShow(result) {
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
function renderAppShowDeploy(context, descriptor, result) {
|
|
134
|
+
return renderShow({
|
|
135
|
+
title: "Showing deployment details.",
|
|
136
|
+
descriptor,
|
|
137
|
+
fields: [
|
|
138
|
+
...result.app ? [{
|
|
139
|
+
key: "app",
|
|
140
|
+
value: result.app.name
|
|
141
|
+
}] : [],
|
|
142
|
+
{
|
|
143
|
+
key: "deployment",
|
|
144
|
+
value: result.deployment.id
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: "status",
|
|
148
|
+
value: result.deployment.status,
|
|
149
|
+
tone: toneForStatus(result.deployment.status)
|
|
150
|
+
},
|
|
151
|
+
...result.deployment.url ? [{
|
|
152
|
+
key: "url",
|
|
153
|
+
value: result.deployment.url,
|
|
154
|
+
tone: "link"
|
|
155
|
+
}] : [],
|
|
156
|
+
...result.deployment.live === null ? [] : [{
|
|
157
|
+
key: "live",
|
|
158
|
+
value: result.deployment.live ? "yes" : "no",
|
|
159
|
+
tone: result.deployment.live ? "success" : "dim"
|
|
160
|
+
}],
|
|
161
|
+
{
|
|
162
|
+
key: "created",
|
|
163
|
+
value: result.deployment.createdAt,
|
|
164
|
+
tone: "dim"
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
}, context.ui);
|
|
168
|
+
}
|
|
169
|
+
function serializeAppShowDeploy(result) {
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
function renderAppOpen(context, descriptor, result) {
|
|
173
|
+
return renderShow({
|
|
174
|
+
title: result.opened ? "Opening the live URL for the selected app." : "Resolving the live URL for the selected app.",
|
|
175
|
+
descriptor,
|
|
176
|
+
fields: [
|
|
177
|
+
{
|
|
178
|
+
key: "project",
|
|
179
|
+
value: result.projectId
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
key: "app",
|
|
183
|
+
value: result.app.name
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
key: "url",
|
|
187
|
+
value: result.url,
|
|
188
|
+
tone: "link"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
key: "opened",
|
|
192
|
+
value: result.opened ? "yes" : "no",
|
|
193
|
+
tone: result.opened ? "success" : "dim"
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
}, context.ui);
|
|
197
|
+
}
|
|
198
|
+
function serializeAppOpen(result) {
|
|
199
|
+
return result;
|
|
200
|
+
}
|
|
201
|
+
function renderAppPromote(context, descriptor, result) {
|
|
202
|
+
return renderShow({
|
|
203
|
+
title: "Switching the live deployment for the selected app.",
|
|
204
|
+
descriptor,
|
|
205
|
+
fields: [
|
|
206
|
+
{
|
|
207
|
+
key: "project",
|
|
208
|
+
value: result.projectId
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
key: "app",
|
|
212
|
+
value: result.app.name
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
key: "deployment",
|
|
216
|
+
value: result.deployment.id
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
key: "status",
|
|
220
|
+
value: result.deployment.status,
|
|
221
|
+
tone: toneForStatus(result.deployment.status)
|
|
222
|
+
},
|
|
223
|
+
...result.deployment.url ? [{
|
|
224
|
+
key: "url",
|
|
225
|
+
value: result.deployment.url,
|
|
226
|
+
tone: "link"
|
|
227
|
+
}] : [],
|
|
228
|
+
{
|
|
229
|
+
key: "live",
|
|
230
|
+
value: result.deployment.live ? "yes" : "no",
|
|
231
|
+
tone: result.deployment.live ? "success" : "dim"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
key: "created",
|
|
235
|
+
value: result.deployment.createdAt,
|
|
236
|
+
tone: "dim"
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
}, context.ui);
|
|
240
|
+
}
|
|
241
|
+
function serializeAppPromote(result) {
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
function renderAppRollback(context, descriptor, result) {
|
|
245
|
+
return renderShow({
|
|
246
|
+
title: "Restoring the selected app to an earlier deployment.",
|
|
247
|
+
descriptor,
|
|
248
|
+
fields: [
|
|
249
|
+
{
|
|
250
|
+
key: "project",
|
|
251
|
+
value: result.projectId
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
key: "app",
|
|
255
|
+
value: result.app.name
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
key: "deployment",
|
|
259
|
+
value: result.deployment.id
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
key: "status",
|
|
263
|
+
value: result.deployment.status,
|
|
264
|
+
tone: toneForStatus(result.deployment.status)
|
|
265
|
+
},
|
|
266
|
+
...result.deployment.url ? [{
|
|
267
|
+
key: "url",
|
|
268
|
+
value: result.deployment.url,
|
|
269
|
+
tone: "link"
|
|
270
|
+
}] : [],
|
|
271
|
+
{
|
|
272
|
+
key: "live",
|
|
273
|
+
value: result.deployment.live ? "yes" : "no",
|
|
274
|
+
tone: result.deployment.live ? "success" : "dim"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
key: "created",
|
|
278
|
+
value: result.deployment.createdAt,
|
|
279
|
+
tone: "dim"
|
|
280
|
+
},
|
|
281
|
+
...result.previousLiveDeploymentId ? [{
|
|
282
|
+
key: "replaced",
|
|
283
|
+
value: result.previousLiveDeploymentId,
|
|
284
|
+
tone: "dim"
|
|
285
|
+
}] : []
|
|
286
|
+
]
|
|
287
|
+
}, context.ui);
|
|
288
|
+
}
|
|
289
|
+
function serializeAppRollback(result) {
|
|
290
|
+
return result;
|
|
291
|
+
}
|
|
292
|
+
function renderAppRun(_context, _descriptor, _result) {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
function serializeAppRun(result) {
|
|
296
|
+
return result;
|
|
297
|
+
}
|
|
298
|
+
function renderAppRemove(context, descriptor, result) {
|
|
299
|
+
return renderShow({
|
|
300
|
+
title: "Removing the selected app.",
|
|
301
|
+
descriptor,
|
|
302
|
+
fields: [
|
|
303
|
+
{
|
|
304
|
+
key: "project",
|
|
305
|
+
value: result.projectId
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
key: "app",
|
|
309
|
+
value: result.app.name
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
key: "removed",
|
|
313
|
+
value: result.removed ? "yes" : "no",
|
|
314
|
+
tone: result.removed ? "success" : "dim"
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}, context.ui);
|
|
318
|
+
}
|
|
319
|
+
function serializeAppRemove(result) {
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
function toneForStatus(status) {
|
|
323
|
+
if (status === "running" || status === "ready" || status === "healthy") return "success";
|
|
324
|
+
if (status === "provisioning" || status === "building" || status === "starting") return "warning";
|
|
325
|
+
if (status === "failed" || status === "error") return "error";
|
|
326
|
+
return "default";
|
|
327
|
+
}
|
|
328
|
+
function formatRecentDeployments(deployments) {
|
|
329
|
+
if (deployments.length === 0) return "none";
|
|
330
|
+
return deployments.map((deployment) => `${deployment.id}${deployment.live ? " (live)" : ""}`).join(", ");
|
|
331
|
+
}
|
|
332
|
+
//#endregion
|
|
333
|
+
export { renderAppBuild, renderAppDeploy, renderAppListDeploys, renderAppOpen, renderAppPromote, renderAppRemove, renderAppRollback, renderAppRun, renderAppShow, renderAppShowDeploy, serializeAppBuild, serializeAppDeploy, serializeAppListDeploys, serializeAppOpen, serializeAppPromote, serializeAppRemove, serializeAppRollback, serializeAppRun, serializeAppShow, serializeAppShowDeploy };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { renderMutate, renderShow } from "../output/patterns.js";
|
|
2
|
+
//#region src/presenters/auth.ts
|
|
3
|
+
function renderAuthSuccess(context, descriptor, command, result) {
|
|
4
|
+
if (command === "auth.login") {
|
|
5
|
+
const rows = [];
|
|
6
|
+
if (result.provider) rows.push({
|
|
7
|
+
key: "provider",
|
|
8
|
+
value: providerLabel(result.provider)
|
|
9
|
+
});
|
|
10
|
+
if (result.user) rows.push({
|
|
11
|
+
key: "user",
|
|
12
|
+
value: `${result.user.name} <${result.user.email}>`
|
|
13
|
+
});
|
|
14
|
+
if (result.workspace?.name) rows.push({
|
|
15
|
+
key: "workspace",
|
|
16
|
+
value: result.workspace.name
|
|
17
|
+
});
|
|
18
|
+
return renderMutate({
|
|
19
|
+
title: "Starting an authenticated CLI session.",
|
|
20
|
+
descriptor,
|
|
21
|
+
context: rows,
|
|
22
|
+
operationDescription: "Applying authentication session changes",
|
|
23
|
+
operationCount: 1,
|
|
24
|
+
details: ["Session stored in local CLI state."]
|
|
25
|
+
}, context.ui);
|
|
26
|
+
}
|
|
27
|
+
if (command === "auth.logout") return renderMutate({
|
|
28
|
+
title: "Clearing the current CLI session.",
|
|
29
|
+
descriptor,
|
|
30
|
+
context: [{
|
|
31
|
+
key: "session",
|
|
32
|
+
value: "local CLI state",
|
|
33
|
+
tone: "dim"
|
|
34
|
+
}],
|
|
35
|
+
operationDescription: "Applying authentication session changes",
|
|
36
|
+
operationCount: 1,
|
|
37
|
+
details: ["Session removed from local CLI state."]
|
|
38
|
+
}, context.ui);
|
|
39
|
+
return renderShow({
|
|
40
|
+
title: "Showing the current authenticated identity.",
|
|
41
|
+
descriptor,
|
|
42
|
+
fields: result.authenticated ? [
|
|
43
|
+
{
|
|
44
|
+
key: "status",
|
|
45
|
+
value: "signed in",
|
|
46
|
+
tone: "success"
|
|
47
|
+
},
|
|
48
|
+
...result.user ? [{
|
|
49
|
+
key: "user",
|
|
50
|
+
value: `${result.user.name} <${result.user.email}>`
|
|
51
|
+
}] : [],
|
|
52
|
+
...result.provider ? [{
|
|
53
|
+
key: "provider",
|
|
54
|
+
value: providerLabel(result.provider)
|
|
55
|
+
}] : [],
|
|
56
|
+
...result.workspace?.name ? [{
|
|
57
|
+
key: "workspace",
|
|
58
|
+
value: result.workspace.name
|
|
59
|
+
}] : []
|
|
60
|
+
] : [{
|
|
61
|
+
key: "status",
|
|
62
|
+
value: "signed out",
|
|
63
|
+
tone: "dim"
|
|
64
|
+
}]
|
|
65
|
+
}, context.ui);
|
|
66
|
+
}
|
|
67
|
+
function providerLabel(provider) {
|
|
68
|
+
if (provider === "github") return "GitHub";
|
|
69
|
+
if (provider === "google") return "Google";
|
|
70
|
+
return "";
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { renderAuthSuccess };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { renderList, renderMutate, renderShow, serializeList } from "../output/patterns.js";
|
|
2
|
+
//#region src/presenters/env.ts
|
|
3
|
+
function renderEnvList(context, descriptor, result) {
|
|
4
|
+
return renderList({
|
|
5
|
+
title: "Listing environments for the linked project.",
|
|
6
|
+
descriptor,
|
|
7
|
+
parentContext: {
|
|
8
|
+
key: "project",
|
|
9
|
+
value: result.projectName ?? "not linked"
|
|
10
|
+
},
|
|
11
|
+
items: result.environments.map((environment) => ({
|
|
12
|
+
noun: "environment",
|
|
13
|
+
label: environment.name,
|
|
14
|
+
id: environment.id,
|
|
15
|
+
status: environment.active ? "active" : null
|
|
16
|
+
})),
|
|
17
|
+
emptyMessage: "No environments found."
|
|
18
|
+
}, context.ui);
|
|
19
|
+
}
|
|
20
|
+
function serializeEnvList(result) {
|
|
21
|
+
return serializeList({
|
|
22
|
+
context: { project: result.projectName ?? "not linked" },
|
|
23
|
+
items: result.environments.map((environment) => ({
|
|
24
|
+
noun: "environment",
|
|
25
|
+
label: environment.name,
|
|
26
|
+
id: environment.id,
|
|
27
|
+
status: environment.active ? "active" : null
|
|
28
|
+
}))
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function serializeEnvShow(result) {
|
|
32
|
+
return {
|
|
33
|
+
linkedProjectId: result.linkedProjectId,
|
|
34
|
+
projectName: result.projectName,
|
|
35
|
+
environment: {
|
|
36
|
+
name: result.environment.name,
|
|
37
|
+
kind: result.environment.kind,
|
|
38
|
+
active: result.environment.active,
|
|
39
|
+
remoteState: result.environment.remoteState,
|
|
40
|
+
liveDeployment: result.environment.liveDeployment
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function renderEnvShow(context, descriptor, result) {
|
|
45
|
+
const fields = [
|
|
46
|
+
{
|
|
47
|
+
key: "project",
|
|
48
|
+
value: result.projectName ?? "not linked",
|
|
49
|
+
tone: result.projectName ? "default" : "dim"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
key: "environment",
|
|
53
|
+
value: result.environment.name,
|
|
54
|
+
tone: result.environment.active ? "success" : "default"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: "kind",
|
|
58
|
+
value: result.environment.kind
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
if (result.environment.liveDeployment) {
|
|
62
|
+
fields.push({
|
|
63
|
+
key: "status",
|
|
64
|
+
value: result.environment.liveDeployment.status,
|
|
65
|
+
tone: toneForDeploymentStatus(result.environment.liveDeployment.status)
|
|
66
|
+
});
|
|
67
|
+
if (result.environment.liveDeployment.url) fields.push({
|
|
68
|
+
key: "url",
|
|
69
|
+
value: result.environment.liveDeployment.url,
|
|
70
|
+
tone: "link"
|
|
71
|
+
});
|
|
72
|
+
} else if (result.environment.kind !== "local" && !result.environment.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 environment 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 renderEnvUse(context, descriptor, result) {
|
|
90
|
+
return renderMutate({
|
|
91
|
+
title: "Changing the local default environment context.",
|
|
92
|
+
descriptor,
|
|
93
|
+
context: [{
|
|
94
|
+
key: "project",
|
|
95
|
+
value: result.projectName ?? "not linked",
|
|
96
|
+
tone: result.projectName ? "default" : "dim"
|
|
97
|
+
}, {
|
|
98
|
+
key: "environment",
|
|
99
|
+
value: result.environment.name
|
|
100
|
+
}],
|
|
101
|
+
operationDescription: "Applying active environment change",
|
|
102
|
+
operationCount: 1,
|
|
103
|
+
details: ["Active environment updated in local CLI state for this repo."],
|
|
104
|
+
alerts: result.environment.kind === "production" ? [{
|
|
105
|
+
tone: "warning",
|
|
106
|
+
text: "Production is now the default target"
|
|
107
|
+
}] : void 0
|
|
108
|
+
}, context.ui);
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { renderEnvList, renderEnvShow, renderEnvUse, serializeEnvList, serializeEnvShow };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { renderList, renderMutate, renderShow, serializeList } from "../output/patterns.js";
|
|
2
|
+
//#region src/presenters/project.ts
|
|
3
|
+
function renderProjectList(context, descriptor, result) {
|
|
4
|
+
return renderList({
|
|
5
|
+
title: "Listing projects for the authenticated workspace.",
|
|
6
|
+
descriptor,
|
|
7
|
+
parentContext: {
|
|
8
|
+
key: "workspace",
|
|
9
|
+
value: result.workspace.name
|
|
10
|
+
},
|
|
11
|
+
items: result.projects.map((project) => ({
|
|
12
|
+
noun: "project",
|
|
13
|
+
label: project.name,
|
|
14
|
+
id: project.id,
|
|
15
|
+
status: result.linkedProjectId === project.id ? "linked" : null
|
|
16
|
+
})),
|
|
17
|
+
emptyMessage: "No projects found."
|
|
18
|
+
}, context.ui);
|
|
19
|
+
}
|
|
20
|
+
function serializeProjectList(result) {
|
|
21
|
+
return serializeList({
|
|
22
|
+
context: { workspace: result.workspace.name },
|
|
23
|
+
items: result.projects.map((project) => ({
|
|
24
|
+
noun: "project",
|
|
25
|
+
label: project.name,
|
|
26
|
+
id: project.id,
|
|
27
|
+
status: result.linkedProjectId === project.id ? "linked" : null
|
|
28
|
+
}))
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function renderProjectShow(context, descriptor, result) {
|
|
32
|
+
if (!result.linkedProjectId) return renderShow({
|
|
33
|
+
title: "Showing the linked project for the current repo.",
|
|
34
|
+
descriptor,
|
|
35
|
+
fields: [{
|
|
36
|
+
key: "project",
|
|
37
|
+
value: "not linked",
|
|
38
|
+
tone: "dim"
|
|
39
|
+
}]
|
|
40
|
+
}, context.ui);
|
|
41
|
+
if (!result.project || !result.workspace) return renderShow({
|
|
42
|
+
title: "Showing the linked project for the current repo.",
|
|
43
|
+
descriptor,
|
|
44
|
+
fields: [{
|
|
45
|
+
key: "project",
|
|
46
|
+
value: "linked",
|
|
47
|
+
tone: "success"
|
|
48
|
+
}, {
|
|
49
|
+
key: "remote details",
|
|
50
|
+
value: "unavailable until you sign in",
|
|
51
|
+
tone: "dim"
|
|
52
|
+
}]
|
|
53
|
+
}, context.ui);
|
|
54
|
+
return renderShow({
|
|
55
|
+
title: "Showing the linked project for the current repo.",
|
|
56
|
+
descriptor,
|
|
57
|
+
fields: [{
|
|
58
|
+
key: "project",
|
|
59
|
+
value: result.project.name
|
|
60
|
+
}, {
|
|
61
|
+
key: "workspace",
|
|
62
|
+
value: result.workspace.name
|
|
63
|
+
}]
|
|
64
|
+
}, context.ui);
|
|
65
|
+
}
|
|
66
|
+
function renderProjectLink(context, descriptor, result) {
|
|
67
|
+
if (!result.project || !result.workspace) throw new Error("Linked project result must be enriched for human output.");
|
|
68
|
+
return renderMutate({
|
|
69
|
+
title: "Linking the current repo to an existing project.",
|
|
70
|
+
descriptor,
|
|
71
|
+
context: [{
|
|
72
|
+
key: "project",
|
|
73
|
+
value: result.project.name
|
|
74
|
+
}, {
|
|
75
|
+
key: "workspace",
|
|
76
|
+
value: result.workspace.name
|
|
77
|
+
}],
|
|
78
|
+
operationDescription: "Applying local project link",
|
|
79
|
+
operationCount: 1,
|
|
80
|
+
details: ["Project link written to local repo config."]
|
|
81
|
+
}, context.ui);
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
export { renderProjectLink, renderProjectList, renderProjectShow, serializeProjectList };
|