@prisma/cli 3.0.0-beta.2 → 3.0.0-beta.21
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 +5 -16
- package/dist/adapters/git.js +8 -3
- package/dist/adapters/local-state.js +26 -7
- package/dist/adapters/mock-api.js +81 -2
- package/dist/adapters/token-storage.js +344 -25
- package/dist/cli.js +18 -3
- package/dist/cli2.js +12 -4
- package/dist/commands/agent/index.js +60 -0
- package/dist/commands/app/index.js +90 -61
- package/dist/commands/auth/index.js +55 -2
- package/dist/commands/branch/index.js +2 -27
- package/dist/commands/build/index.js +29 -0
- package/dist/commands/database/index.js +159 -0
- package/dist/commands/env.js +8 -4
- package/dist/commands/git/index.js +1 -1
- package/dist/commands/project/index.js +1 -1
- package/dist/controllers/agent.js +228 -0
- package/dist/controllers/app-env-api.js +55 -0
- package/dist/controllers/app-env-file.js +181 -0
- package/dist/controllers/app-env.js +286 -131
- package/dist/controllers/app.js +849 -309
- package/dist/controllers/auth.js +255 -11
- package/dist/controllers/branch.js +78 -48
- package/dist/controllers/build.js +88 -0
- package/dist/controllers/database.js +318 -0
- package/dist/controllers/project.js +156 -87
- package/dist/controllers/select-prompt-port.js +1 -0
- package/dist/lib/agent/cli-command.js +17 -0
- package/dist/lib/agent/constants.js +12 -0
- package/dist/lib/agent/package-manager.js +99 -0
- package/dist/lib/agent/setup-status.js +83 -0
- package/dist/lib/app/app-interaction.js +5 -0
- package/dist/lib/app/{preview-provider.js → app-provider.js} +220 -104
- package/dist/lib/app/branch-database-api.js +102 -0
- package/dist/lib/app/branch-database-deploy.js +326 -0
- package/dist/lib/app/branch-database.js +216 -0
- package/dist/lib/app/build-settings.js +93 -0
- package/dist/lib/app/build.js +82 -0
- package/dist/lib/app/bun-project.js +15 -9
- package/dist/lib/app/compute-config.js +145 -0
- package/dist/lib/app/deploy-plan.js +59 -0
- package/dist/lib/app/{preview-progress.js → deploy-progress.js} +12 -12
- package/dist/lib/app/env-config.js +1 -1
- package/dist/lib/app/env-file.js +82 -0
- package/dist/lib/app/env-vars.js +28 -2
- package/dist/lib/app/local-dev.js +8 -49
- package/dist/lib/app/production-deploy-gate.js +162 -0
- package/dist/lib/app/read-branch.js +30 -0
- package/dist/lib/auth/auth-ops.js +38 -23
- package/dist/lib/auth/guard.js +6 -2
- package/dist/lib/auth/login.js +117 -15
- package/dist/lib/database/provider.js +167 -0
- package/dist/lib/diagnostics.js +15 -0
- package/dist/lib/fs/home-path.js +24 -0
- package/dist/lib/git/local-branch.js +53 -0
- package/dist/lib/git/local-status.js +57 -0
- package/dist/lib/project/interactive-setup.js +2 -1
- package/dist/lib/project/local-pin.js +183 -34
- package/dist/lib/project/resolution.js +206 -50
- package/dist/lib/project/setup.js +64 -18
- package/dist/output/patterns.js +1 -1
- package/dist/presenters/agent.js +74 -0
- package/dist/presenters/app-env.js +149 -14
- package/dist/presenters/app.js +187 -26
- package/dist/presenters/auth.js +99 -2
- package/dist/presenters/branch.js +37 -102
- package/dist/presenters/database.js +274 -0
- package/dist/presenters/project.js +44 -26
- package/dist/presenters/verbose-context.js +64 -0
- package/dist/shell/cli-command.js +12 -0
- package/dist/shell/command-arguments.js +7 -1
- package/dist/shell/command-meta.js +243 -15
- package/dist/shell/command-runner.js +60 -21
- package/dist/shell/diagnostics-output.js +57 -0
- package/dist/shell/errors.js +61 -1
- package/dist/shell/help.js +31 -20
- package/dist/shell/output.js +10 -1
- package/dist/shell/prompt.js +7 -3
- package/dist/shell/runtime.js +10 -6
- package/dist/shell/ui.js +42 -3
- package/dist/shell/update-check.js +247 -0
- package/dist/use-cases/auth.js +68 -1
- package/dist/use-cases/branch.js +20 -68
- package/dist/use-cases/create-cli-gateways.js +2 -17
- package/package.json +27 -10
- package/dist/lib/app/preview-build.js +0 -284
- package/dist/lib/app/preview-interaction.js +0 -5
|
@@ -1,111 +1,46 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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:
|
|
34
|
-
projectName:
|
|
35
|
-
|
|
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
|
|
45
|
-
|
|
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,
|
|
46
|
+
export { renderBranchList, serializeBranchList };
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { formatDescriptorLabel } from "../shell/command-meta.js";
|
|
2
|
+
import { formatColumns, renderSummaryLine } from "../shell/ui.js";
|
|
3
|
+
import { renderMutate, renderShow, serializeList } from "../output/patterns.js";
|
|
4
|
+
import { renderResolvedProjectContextBlock, stripVerboseContext } from "./verbose-context.js";
|
|
5
|
+
//#region src/presenters/database.ts
|
|
6
|
+
function renderDatabaseList(context, descriptor, result) {
|
|
7
|
+
const ui = context.ui;
|
|
8
|
+
const lines = [`${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim("Listing databases for the resolved project.")}`, ""];
|
|
9
|
+
const rail = ui.dim("│");
|
|
10
|
+
lines.push(`${rail} ${ui.accent("project:")} ${result.projectName}`);
|
|
11
|
+
if (result.branchName) lines.push(`${rail} ${ui.accent("branch:")} ${result.branchName}`);
|
|
12
|
+
lines.push(rail);
|
|
13
|
+
if (result.databases.length === 0) {
|
|
14
|
+
lines.push(`${rail} ${ui.dim("No databases found.")}`);
|
|
15
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
|
|
16
|
+
return lines;
|
|
17
|
+
}
|
|
18
|
+
const rows = result.databases.map((database) => [
|
|
19
|
+
database.name,
|
|
20
|
+
database.branchName ?? "unscoped",
|
|
21
|
+
database.region ?? "unknown",
|
|
22
|
+
formatStatus(database),
|
|
23
|
+
database.id
|
|
24
|
+
]);
|
|
25
|
+
const widths = [
|
|
26
|
+
Math.max(4, ...rows.map((row) => row[0].length)),
|
|
27
|
+
Math.max(6, ...rows.map((row) => row[1].length)),
|
|
28
|
+
Math.max(6, ...rows.map((row) => row[2].length)),
|
|
29
|
+
Math.max(6, ...rows.map((row) => row[3].length)),
|
|
30
|
+
Math.max(2, ...rows.map((row) => row[4].length))
|
|
31
|
+
];
|
|
32
|
+
lines.push(`${rail} ${ui.accent(formatColumns([
|
|
33
|
+
"Name",
|
|
34
|
+
"Branch",
|
|
35
|
+
"Region",
|
|
36
|
+
"Status",
|
|
37
|
+
"Id"
|
|
38
|
+
], widths))}`);
|
|
39
|
+
for (const row of rows) lines.push(`${rail} ${formatColumns(row, widths)}`);
|
|
40
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
|
|
41
|
+
return lines;
|
|
42
|
+
}
|
|
43
|
+
function serializeDatabaseList(result) {
|
|
44
|
+
return {
|
|
45
|
+
...serializeList({
|
|
46
|
+
context: {
|
|
47
|
+
project: result.projectName,
|
|
48
|
+
...result.branchName ? { branch: result.branchName } : {}
|
|
49
|
+
},
|
|
50
|
+
items: result.databases.map((database) => ({
|
|
51
|
+
noun: "database",
|
|
52
|
+
label: database.name,
|
|
53
|
+
id: database.id,
|
|
54
|
+
status: database.isDefault ? "default" : null
|
|
55
|
+
}))
|
|
56
|
+
}),
|
|
57
|
+
projectId: result.projectId,
|
|
58
|
+
branchName: result.branchName,
|
|
59
|
+
databases: result.databases
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function renderDatabaseShow(context, descriptor, result) {
|
|
63
|
+
const lines = renderShow({
|
|
64
|
+
title: "Showing database metadata.",
|
|
65
|
+
descriptor,
|
|
66
|
+
fields: [
|
|
67
|
+
{
|
|
68
|
+
key: "project",
|
|
69
|
+
value: result.projectName
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: "database",
|
|
73
|
+
value: result.database.name
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: "id",
|
|
77
|
+
value: result.database.id,
|
|
78
|
+
tone: "dim"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: "branch",
|
|
82
|
+
value: result.database.branchName ?? "unscoped",
|
|
83
|
+
tone: result.database.branchName ? "default" : "dim"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
key: "region",
|
|
87
|
+
value: result.database.region ?? "unknown",
|
|
88
|
+
tone: result.database.region ? "default" : "dim"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
key: "status",
|
|
92
|
+
value: formatStatus(result.database)
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
key: "connections",
|
|
96
|
+
value: String(result.connections.length)
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}, context.ui);
|
|
100
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
|
|
101
|
+
return lines;
|
|
102
|
+
}
|
|
103
|
+
function serializeDatabaseShow(result) {
|
|
104
|
+
return stripVerboseContext(result);
|
|
105
|
+
}
|
|
106
|
+
function renderDatabaseCreateStdout(_context, _descriptor, result) {
|
|
107
|
+
return [result.connectionString];
|
|
108
|
+
}
|
|
109
|
+
function renderDatabaseCreate(context, _descriptor, result) {
|
|
110
|
+
const ui = context.ui;
|
|
111
|
+
const lines = [
|
|
112
|
+
"Creating database...",
|
|
113
|
+
renderSummaryLine(ui, "success", `Created database "${result.database.name}" in ${formatDatabaseTarget(result.projectName, result.database.branchName)}.`),
|
|
114
|
+
" The connection URL below is shown once, so save it now."
|
|
115
|
+
];
|
|
116
|
+
if (ui.verbose) {
|
|
117
|
+
lines.push("");
|
|
118
|
+
lines.push(...renderDatabaseCreateVerboseRows(context, result));
|
|
119
|
+
}
|
|
120
|
+
return lines;
|
|
121
|
+
}
|
|
122
|
+
function serializeDatabaseCreate(result) {
|
|
123
|
+
return stripVerboseContext(result);
|
|
124
|
+
}
|
|
125
|
+
function renderDatabaseRemove(context, descriptor, result) {
|
|
126
|
+
const lines = renderMutate({
|
|
127
|
+
title: "Removing database.",
|
|
128
|
+
descriptor,
|
|
129
|
+
context: [
|
|
130
|
+
{
|
|
131
|
+
key: "project",
|
|
132
|
+
value: result.projectName
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "database",
|
|
136
|
+
value: result.database.name
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
key: "id",
|
|
140
|
+
value: result.database.id,
|
|
141
|
+
tone: "dim"
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
operationDescription: "Removing database",
|
|
145
|
+
operationCount: 1,
|
|
146
|
+
details: ["Database and its connection metadata were removed."]
|
|
147
|
+
}, context.ui);
|
|
148
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
|
|
149
|
+
return lines;
|
|
150
|
+
}
|
|
151
|
+
function serializeDatabaseRemove(result) {
|
|
152
|
+
return stripVerboseContext(result);
|
|
153
|
+
}
|
|
154
|
+
function renderDatabaseConnectionList(context, descriptor, result) {
|
|
155
|
+
const ui = context.ui;
|
|
156
|
+
const lines = [`${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim("Listing database connection metadata.")}`, ""];
|
|
157
|
+
const rail = ui.dim("│");
|
|
158
|
+
lines.push(`${rail} ${ui.accent("database:")} ${result.database.name}`);
|
|
159
|
+
lines.push(rail);
|
|
160
|
+
if (result.connections.length === 0) {
|
|
161
|
+
lines.push(`${rail} ${ui.dim("No database connections found.")}`);
|
|
162
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
|
|
163
|
+
return lines;
|
|
164
|
+
}
|
|
165
|
+
const rows = result.connections.map((connection) => [
|
|
166
|
+
connection.name,
|
|
167
|
+
connection.id,
|
|
168
|
+
connection.createdAt ?? "unknown"
|
|
169
|
+
]);
|
|
170
|
+
const widths = [
|
|
171
|
+
Math.max(4, ...rows.map((row) => row[0].length)),
|
|
172
|
+
Math.max(2, ...rows.map((row) => row[1].length)),
|
|
173
|
+
Math.max(7, ...rows.map((row) => row[2].length))
|
|
174
|
+
];
|
|
175
|
+
lines.push(`${rail} ${ui.accent(formatColumns([
|
|
176
|
+
"Name",
|
|
177
|
+
"Id",
|
|
178
|
+
"Created"
|
|
179
|
+
], widths))}`);
|
|
180
|
+
for (const row of rows) lines.push(`${rail} ${formatColumns(row, widths)}`);
|
|
181
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, result.verboseContext));
|
|
182
|
+
return lines;
|
|
183
|
+
}
|
|
184
|
+
function serializeDatabaseConnectionList(result) {
|
|
185
|
+
return {
|
|
186
|
+
...serializeList({
|
|
187
|
+
context: {
|
|
188
|
+
project: result.projectName,
|
|
189
|
+
database: result.database.name
|
|
190
|
+
},
|
|
191
|
+
items: result.connections.map((connection) => ({
|
|
192
|
+
noun: "connection",
|
|
193
|
+
label: connection.name,
|
|
194
|
+
id: connection.id,
|
|
195
|
+
status: null
|
|
196
|
+
}))
|
|
197
|
+
}),
|
|
198
|
+
projectId: result.projectId,
|
|
199
|
+
database: result.database,
|
|
200
|
+
connections: result.connections
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function renderDatabaseConnectionCreateStdout(_context, _descriptor, result) {
|
|
204
|
+
return [result.connectionString];
|
|
205
|
+
}
|
|
206
|
+
function renderDatabaseConnectionCreate(context, _descriptor, result) {
|
|
207
|
+
const ui = context.ui;
|
|
208
|
+
const lines = [
|
|
209
|
+
"Creating connection...",
|
|
210
|
+
renderSummaryLine(ui, "success", `Added a connection to "${result.database.name}" in ${formatDatabaseTarget(result.projectName, result.database.branchName)}.`),
|
|
211
|
+
" The connection URL below is shown once, so save it now."
|
|
212
|
+
];
|
|
213
|
+
if (ui.verbose) {
|
|
214
|
+
lines.push("");
|
|
215
|
+
lines.push(...renderDatabaseConnectionCreateVerboseRows(context, result));
|
|
216
|
+
}
|
|
217
|
+
return lines;
|
|
218
|
+
}
|
|
219
|
+
function serializeDatabaseConnectionCreate(result) {
|
|
220
|
+
return stripVerboseContext(result);
|
|
221
|
+
}
|
|
222
|
+
function renderDatabaseConnectionRemove(context, descriptor, result) {
|
|
223
|
+
return renderMutate({
|
|
224
|
+
title: "Removing database connection.",
|
|
225
|
+
descriptor,
|
|
226
|
+
context: [{
|
|
227
|
+
key: "connection",
|
|
228
|
+
value: result.connection.id,
|
|
229
|
+
tone: "dim"
|
|
230
|
+
}],
|
|
231
|
+
operationDescription: "Removing database connection",
|
|
232
|
+
operationCount: 1,
|
|
233
|
+
details: ["The connection metadata was removed. Existing one-time secrets were not shown."]
|
|
234
|
+
}, context.ui);
|
|
235
|
+
}
|
|
236
|
+
function serializeDatabaseConnectionRemove(result) {
|
|
237
|
+
return { connection: result.connection };
|
|
238
|
+
}
|
|
239
|
+
function formatStatus(database) {
|
|
240
|
+
return database.status ?? (database.isDefault ? "default" : "unknown");
|
|
241
|
+
}
|
|
242
|
+
function formatDatabaseTarget(projectName, branchName) {
|
|
243
|
+
return branchName ? `${projectName} / ${branchName}` : projectName;
|
|
244
|
+
}
|
|
245
|
+
function renderDatabaseCreateVerboseRows(context, result) {
|
|
246
|
+
return renderMetadataRows([
|
|
247
|
+
...renderWorkspaceProjectRows(result),
|
|
248
|
+
["branch", result.database.branchName ?? "unscoped"],
|
|
249
|
+
["database", formatResourceWithId(context, result.database.name, result.database.id)],
|
|
250
|
+
["region", result.database.region ?? "unknown"],
|
|
251
|
+
["status", formatStatus(result.database)],
|
|
252
|
+
["connection", formatResourceWithId(context, result.connection.name, result.connection.id)]
|
|
253
|
+
]);
|
|
254
|
+
}
|
|
255
|
+
function renderDatabaseConnectionCreateVerboseRows(context, result) {
|
|
256
|
+
return renderMetadataRows([
|
|
257
|
+
...renderWorkspaceProjectRows(result),
|
|
258
|
+
["branch", result.database.branchName ?? "unscoped"],
|
|
259
|
+
["database", formatResourceWithId(context, result.database.name, result.database.id)],
|
|
260
|
+
["connection", formatResourceWithId(context, result.connection.name, result.connection.id)]
|
|
261
|
+
]);
|
|
262
|
+
}
|
|
263
|
+
function renderWorkspaceProjectRows(result) {
|
|
264
|
+
return [...result.verboseContext ? [["workspace", result.verboseContext.workspace.name]] : [], ["project", result.projectName]];
|
|
265
|
+
}
|
|
266
|
+
function formatResourceWithId(context, name, id) {
|
|
267
|
+
return `${name} ${context.ui.dim(`(${id})`)}`;
|
|
268
|
+
}
|
|
269
|
+
function renderMetadataRows(rows) {
|
|
270
|
+
const widths = [Math.max(...rows.map((row) => row[0].length)), 0];
|
|
271
|
+
return rows.map(([key, value]) => ` ${formatColumns([key, value], widths)}`);
|
|
272
|
+
}
|
|
273
|
+
//#endregion
|
|
274
|
+
export { renderDatabaseConnectionCreate, renderDatabaseConnectionCreateStdout, renderDatabaseConnectionList, renderDatabaseConnectionRemove, renderDatabaseCreate, renderDatabaseCreateStdout, renderDatabaseList, renderDatabaseRemove, renderDatabaseShow, serializeDatabaseConnectionCreate, serializeDatabaseConnectionList, serializeDatabaseConnectionRemove, serializeDatabaseCreate, serializeDatabaseList, serializeDatabaseRemove, serializeDatabaseShow };
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import { padDisplay, renderNextSteps, renderSummaryLine } from "../shell/ui.js";
|
|
2
|
-
import { formatDescriptorLabel } from "../shell/command-meta.js";
|
|
3
1
|
import { formatCommandArgument } from "../shell/command-arguments.js";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
2
|
+
import { formatDescriptorLabel } from "../shell/command-meta.js";
|
|
3
|
+
import { padDisplay, renderNextSteps, renderSummaryLine, renderVerboseBlock } from "../shell/ui.js";
|
|
4
|
+
import { shortenHomePath } from "../lib/fs/home-path.js";
|
|
5
|
+
import { renderMutate, renderShow, serializeList } from "../output/patterns.js";
|
|
6
|
+
import { renderResolvedProjectContextBlock } from "./verbose-context.js";
|
|
7
|
+
import stringWidth from "string-width";
|
|
6
8
|
//#region src/presenters/project.ts
|
|
7
9
|
function renderProjectList(context, descriptor, result) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
emptyMessage: "No projects found."
|
|
22
|
-
}, context.ui);
|
|
10
|
+
const ui = context.ui;
|
|
11
|
+
const rail = ui.dim("│");
|
|
12
|
+
const lines = [`${ui.strong(formatDescriptorLabel(descriptor))} ${ui.dim("→")} ${ui.dim("Listing projects for the authenticated workspace.")}`, ""];
|
|
13
|
+
lines.push(`${rail} ${ui.accent("workspace:")} ${result.workspace.name}`);
|
|
14
|
+
if (result.projects.length === 0) {
|
|
15
|
+
lines.push(`${rail} ${ui.dim("No projects found.")}`);
|
|
16
|
+
if (result.localBinding?.status === "not-linked" || result.localBinding?.status === "invalid") lines.push(...renderNextSteps(["Link an existing Project you choose: prisma-cli project link <id-or-name>", "Create a new Project: prisma-cli project create <name>"]));
|
|
17
|
+
return lines;
|
|
18
|
+
}
|
|
19
|
+
const nameWidth = Math.max(4, ...result.projects.map((project) => stringWidth(project.name)));
|
|
20
|
+
lines.push(rail);
|
|
21
|
+
lines.push(`${rail} ${ui.accent(padDisplay("name", nameWidth))} ${ui.accent("id")}`);
|
|
22
|
+
for (const project of result.projects) lines.push(`${rail} ${padDisplay(project.name, nameWidth)} ${project.id}`);
|
|
23
23
|
if (result.localBinding?.status === "not-linked" || result.localBinding?.status === "invalid") lines.push(...renderNextSteps(["Link an existing Project you choose: prisma-cli project link <id-or-name>", "Create a new Project: prisma-cli project create <name>"]));
|
|
24
24
|
return lines;
|
|
25
25
|
}
|
|
@@ -51,6 +51,25 @@ function renderProjectShow(context, descriptor, result) {
|
|
|
51
51
|
tone: "warning"
|
|
52
52
|
}]
|
|
53
53
|
}, context.ui);
|
|
54
|
+
lines.push(...renderVerboseBlock(context.ui, [
|
|
55
|
+
{
|
|
56
|
+
key: "workspace",
|
|
57
|
+
value: result.workspace.name
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: "workspace id",
|
|
61
|
+
value: result.workspace.id,
|
|
62
|
+
tone: "dim"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
key: "project source",
|
|
66
|
+
value: "unbound"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: "suggested name",
|
|
70
|
+
value: `${result.suggestedProjectName} (${result.suggestedProjectNameSource})`
|
|
71
|
+
}
|
|
72
|
+
], { title: "Resolved context" }));
|
|
54
73
|
lines.push(...renderNextSteps(["Link an existing Project you choose: prisma-cli project link <id-or-name>", `Create a new Project: prisma-cli project create ${formatCommandArgument(result.suggestedProjectName)}`]));
|
|
55
74
|
return lines;
|
|
56
75
|
}
|
|
@@ -133,16 +152,15 @@ function renderBoundProjectShow(context, descriptor, result) {
|
|
|
133
152
|
lines.push(rail);
|
|
134
153
|
lines.push(`${rail} ${ui.dim("→")} ${ui.link(result.project.url)}`);
|
|
135
154
|
}
|
|
155
|
+
lines.push(...renderResolvedProjectContextBlock(context.ui, {
|
|
156
|
+
workspace: result.workspace,
|
|
157
|
+
project: result.project,
|
|
158
|
+
resolution: result.resolution
|
|
159
|
+
}));
|
|
136
160
|
return lines;
|
|
137
161
|
}
|
|
138
162
|
function formatLocalRepoPath(cwd, env) {
|
|
139
|
-
|
|
140
|
-
const home = env.HOME ? path.resolve(env.HOME) : null;
|
|
141
|
-
if (home && (resolved === home || resolved.startsWith(`${home}${path.sep}`))) {
|
|
142
|
-
const relative = path.relative(home, resolved);
|
|
143
|
-
return relative ? `~/${relative}` : "~";
|
|
144
|
-
}
|
|
145
|
-
return resolved;
|
|
163
|
+
return shortenHomePath(cwd, env);
|
|
146
164
|
}
|
|
147
165
|
function formatGitConnectionDetail(status) {
|
|
148
166
|
switch (status) {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { renderVerboseBlock } from "../shell/ui.js";
|
|
2
|
+
//#region src/presenters/verbose-context.ts
|
|
3
|
+
function renderResolvedProjectContextBlock(ui, context, options = {}) {
|
|
4
|
+
if (!context) return [];
|
|
5
|
+
return renderVerboseBlock(ui, [...projectResolutionRows(context), ...options.extraRows ?? []], { title: options.title ?? "Resolved context" });
|
|
6
|
+
}
|
|
7
|
+
function projectResolutionRows(context) {
|
|
8
|
+
return [
|
|
9
|
+
{
|
|
10
|
+
key: "workspace",
|
|
11
|
+
value: context.workspace.name
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
key: "workspace id",
|
|
15
|
+
value: context.workspace.id,
|
|
16
|
+
tone: "dim"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: "project",
|
|
20
|
+
value: context.project.name
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: "project id",
|
|
24
|
+
value: context.project.id,
|
|
25
|
+
tone: "dim"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: "project source",
|
|
29
|
+
value: formatProjectSource(context.resolution.projectSource)
|
|
30
|
+
},
|
|
31
|
+
...context.resolution.targetName ? [{
|
|
32
|
+
key: "target name",
|
|
33
|
+
value: formatTargetName(context.resolution)
|
|
34
|
+
}] : [],
|
|
35
|
+
...context.branch ? [{
|
|
36
|
+
key: "branch",
|
|
37
|
+
value: `${context.branch.name} (${context.branch.kind})`
|
|
38
|
+
}, ...context.branch.id ? [{
|
|
39
|
+
key: "branch id",
|
|
40
|
+
value: context.branch.id,
|
|
41
|
+
tone: "dim"
|
|
42
|
+
}] : []] : []
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
function stripVerboseContext(result) {
|
|
46
|
+
const { verboseContext: _verboseContext, ...serialized } = result;
|
|
47
|
+
return serialized;
|
|
48
|
+
}
|
|
49
|
+
function formatProjectSource(source) {
|
|
50
|
+
switch (source) {
|
|
51
|
+
case "explicit": return "--project";
|
|
52
|
+
case "env": return "environment";
|
|
53
|
+
case "local-pin": return ".prisma/local.json";
|
|
54
|
+
case "platform-mapping": return "platform mapping";
|
|
55
|
+
case "created": return "created";
|
|
56
|
+
case "prompt": return "prompt";
|
|
57
|
+
case "unbound": return "unbound";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function formatTargetName(resolution) {
|
|
61
|
+
return resolution.targetNameSource ? `${resolution.targetName} (${resolution.targetNameSource})` : String(resolution.targetName);
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { renderResolvedProjectContextBlock, stripVerboseContext };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const PRISMA_CLI_PACKAGE_SPEC = `@prisma/cli@latest`;
|
|
2
|
+
const DEFAULT_PRISMA_CLI_PACKAGE_RUNNER = ["npx", "-y"];
|
|
3
|
+
const PRISMA_CLI_BINARY = "prisma-cli";
|
|
4
|
+
function formatPrismaCliCommand(args, options = {}) {
|
|
5
|
+
return [...getPrismaCliCommandPrefix(options), ...args].join(" ");
|
|
6
|
+
}
|
|
7
|
+
function getPrismaCliCommandPrefix({ invocation = "package", packageRunner = DEFAULT_PRISMA_CLI_PACKAGE_RUNNER }) {
|
|
8
|
+
if (invocation === "binary") return [PRISMA_CLI_BINARY];
|
|
9
|
+
return [...packageRunner, PRISMA_CLI_PACKAGE_SPEC];
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { formatPrismaCliCommand };
|
|
@@ -2,5 +2,11 @@
|
|
|
2
2
|
function formatCommandArgument(value) {
|
|
3
3
|
return /^[A-Za-z0-9._/-]+$/.test(value) && !value.startsWith("-") ? value : `'${value.replace(/'/g, "'\\''")}'`;
|
|
4
4
|
}
|
|
5
|
+
function formatShellCommand(command) {
|
|
6
|
+
return command.map(formatShellCommandWord).join(" ");
|
|
7
|
+
}
|
|
8
|
+
function formatShellCommandWord(value) {
|
|
9
|
+
return /^[A-Za-z0-9_./:@=-]+$/.test(value) ? value : `'${value.replace(/'/g, "'\\''")}'`;
|
|
10
|
+
}
|
|
5
11
|
//#endregion
|
|
6
|
-
export { formatCommandArgument };
|
|
12
|
+
export { formatCommandArgument, formatShellCommand };
|