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