@prisma/cli 3.0.0-beta.8 → 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/mock-api.js +75 -0
- package/dist/adapters/token-storage.js +311 -33
- package/dist/cli.js +7 -7
- package/dist/cli2.js +5 -3
- package/dist/commands/app/index.js +65 -52
- package/dist/commands/auth/index.js +55 -2
- package/dist/commands/database/index.js +159 -0
- package/dist/controllers/app-env.js +10 -7
- package/dist/controllers/app.js +550 -208
- package/dist/controllers/auth.js +211 -2
- package/dist/controllers/branch.js +5 -6
- package/dist/controllers/database.js +318 -0
- package/dist/controllers/project.js +49 -20
- 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 +13 -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/database/provider.js +167 -0
- 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 +170 -40
- package/dist/lib/project/resolution.js +166 -61
- 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 +274 -0
- package/dist/presenters/project.js +3 -9
- package/dist/shell/command-meta.js +153 -2
- package/dist/shell/command-runner.js +39 -21
- 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 +18 -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,46 +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 { Result, TaggedError, matchError } from "better-result";
|
|
6
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
|
+
};
|
|
7
54
|
async function resolveProjectTarget(options) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
+
}));
|
|
20
69
|
});
|
|
21
70
|
}
|
|
22
71
|
async function inspectProjectBinding(options) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
+
});
|
|
28
92
|
});
|
|
29
|
-
if (target) return target;
|
|
30
|
-
return {
|
|
31
|
-
workspace: options.workspace,
|
|
32
|
-
project: null,
|
|
33
|
-
localBinding: { status: "not-linked" },
|
|
34
|
-
resolution: { projectSource: "unbound" },
|
|
35
|
-
...await buildProjectSetupSuggestion({
|
|
36
|
-
cwd: options.context.runtime.cwd,
|
|
37
|
-
projects,
|
|
38
|
-
commandName: options.commandName ?? "project show",
|
|
39
|
-
signal: options.context.runtime.signal
|
|
40
|
-
})
|
|
41
|
-
};
|
|
42
93
|
}
|
|
43
94
|
function projectNotFoundError(projectRef, workspace) {
|
|
95
|
+
return projectResolutionErrorToCliError(new ProjectNotFoundError(projectRef, workspace));
|
|
96
|
+
}
|
|
97
|
+
function projectNotFoundCliError(projectRef, workspace) {
|
|
44
98
|
return new CliError({
|
|
45
99
|
code: "PROJECT_NOT_FOUND",
|
|
46
100
|
domain: "project",
|
|
@@ -52,6 +106,9 @@ function projectNotFoundError(projectRef, workspace) {
|
|
|
52
106
|
});
|
|
53
107
|
}
|
|
54
108
|
function projectAmbiguousError(projectRef, matches) {
|
|
109
|
+
return projectResolutionErrorToCliError(new ProjectAmbiguousError(projectRef, matches));
|
|
110
|
+
}
|
|
111
|
+
function projectAmbiguousCliError(projectRef, matches) {
|
|
55
112
|
const firstMatch = matches[0];
|
|
56
113
|
const nextSteps = ["prisma-cli project list"];
|
|
57
114
|
if (firstMatch) nextSteps.push(`prisma-cli app deploy --project ${firstMatch.id}`);
|
|
@@ -69,7 +126,7 @@ function projectAmbiguousError(projectRef, matches) {
|
|
|
69
126
|
nextSteps
|
|
70
127
|
});
|
|
71
128
|
}
|
|
72
|
-
function
|
|
129
|
+
function localStateStaleCliError() {
|
|
73
130
|
return new CliError({
|
|
74
131
|
code: "LOCAL_STATE_STALE",
|
|
75
132
|
domain: "project",
|
|
@@ -82,12 +139,15 @@ function localStateStaleError() {
|
|
|
82
139
|
});
|
|
83
140
|
}
|
|
84
141
|
function localProjectWorkspaceMismatchError(options) {
|
|
142
|
+
return projectResolutionErrorToCliError(new LocalProjectWorkspaceMismatchError(options));
|
|
143
|
+
}
|
|
144
|
+
function localProjectWorkspaceMismatchCliError(options) {
|
|
85
145
|
return new CliError({
|
|
86
146
|
code: "LOCAL_PROJECT_WORKSPACE_MISMATCH",
|
|
87
147
|
domain: "project",
|
|
88
148
|
summary: "Project link uses another workspace",
|
|
89
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}).`,
|
|
90
|
-
fix: "
|
|
150
|
+
fix: "Switch to the linked workspace, or relink this directory to a project in the current workspace.",
|
|
91
151
|
meta: {
|
|
92
152
|
pinPath: LOCAL_RESOLUTION_PIN_RELATIVE_PATH,
|
|
93
153
|
pinnedWorkspaceId: options.pinnedWorkspaceId,
|
|
@@ -97,12 +157,37 @@ function localProjectWorkspaceMismatchError(options) {
|
|
|
97
157
|
},
|
|
98
158
|
exitCode: 1,
|
|
99
159
|
nextSteps: [
|
|
100
|
-
|
|
160
|
+
`prisma-cli auth workspace use ${options.pinnedWorkspaceId}`,
|
|
101
161
|
"prisma-cli project list",
|
|
102
162
|
"prisma-cli project link <id-or-name>"
|
|
103
163
|
]
|
|
104
164
|
});
|
|
105
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
|
+
}
|
|
106
191
|
async function buildProjectSetupSuggestion(options) {
|
|
107
192
|
const suggestedName = await inferTargetName(options.cwd, options.signal);
|
|
108
193
|
const candidates = sortProjects(options.projects.filter((project) => projectMatchesSuggestedName(project, suggestedName.name))).map(toProjectSummary);
|
|
@@ -115,17 +200,24 @@ async function buildProjectSetupSuggestion(options) {
|
|
|
115
200
|
}
|
|
116
201
|
async function projectSetupRequiredError(options) {
|
|
117
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;
|
|
118
210
|
return new CliError({
|
|
119
211
|
code: "PROJECT_SETUP_REQUIRED",
|
|
120
212
|
domain: "project",
|
|
121
213
|
summary: "Choose a Project before running this command",
|
|
122
|
-
why:
|
|
214
|
+
why: error.message,
|
|
123
215
|
fix: "Link the directory to an existing Project, or pass --project <id-or-name> for this command.",
|
|
124
216
|
meta: { ...suggestion },
|
|
125
217
|
exitCode: 1,
|
|
126
218
|
nextSteps: ["prisma-cli project list", ...suggestion.recoveryCommands],
|
|
127
219
|
nextActions: buildProjectSetupNextActions({
|
|
128
|
-
commandName:
|
|
220
|
+
commandName: error.commandName,
|
|
129
221
|
suggestedProjectName: suggestion.suggestedProjectName
|
|
130
222
|
})
|
|
131
223
|
});
|
|
@@ -199,9 +291,9 @@ function sortProjects(projects) {
|
|
|
199
291
|
}
|
|
200
292
|
function resolveExplicitProject(projectRef, projects, workspace) {
|
|
201
293
|
const matches = projects.filter((project) => project.id === projectRef || project.name === projectRef);
|
|
202
|
-
if (matches.length === 1) return matches[0];
|
|
203
|
-
if (matches.length > 1)
|
|
204
|
-
|
|
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));
|
|
205
297
|
}
|
|
206
298
|
function projectMatchesSuggestedName(project, suggestedName) {
|
|
207
299
|
return project.id === suggestedName || project.name === suggestedName || project.slug === suggestedName;
|
|
@@ -210,50 +302,63 @@ async function resolveDurablePlatformMapping() {
|
|
|
210
302
|
return null;
|
|
211
303
|
}
|
|
212
304
|
async function resolveBoundProjectTarget(options, projects, settings) {
|
|
213
|
-
if (options.explicitProject)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
+
}
|
|
217
313
|
if (settings.allowEnvProjectId && options.envProjectId) {
|
|
218
314
|
const project = projects.find((candidate) => candidate.id === options.envProjectId);
|
|
219
|
-
if (!project)
|
|
220
|
-
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", {
|
|
221
317
|
targetName: options.envProjectId,
|
|
222
318
|
targetNameSource: "env"
|
|
223
|
-
});
|
|
319
|
+
}));
|
|
224
320
|
}
|
|
225
321
|
const localPin = settings.localPin;
|
|
226
|
-
if (!localPin) return null;
|
|
227
|
-
if (localPin.kind === "invalid") throw localStateStaleError();
|
|
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
|
|
251
|
-
if (
|
|
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));
|
|
347
|
+
const localPin = localPinResult.value;
|
|
348
|
+
if (localPin.kind === "present" && localPin.pin.workspaceId !== options.workspace.id) return Result.err(new LocalProjectWorkspaceMismatchError({
|
|
252
349
|
pinnedWorkspaceId: localPin.pin.workspaceId,
|
|
253
350
|
pinnedProjectId: localPin.pin.projectId,
|
|
254
351
|
activeWorkspace: options.workspace
|
|
352
|
+
}));
|
|
353
|
+
return Result.ok(localPin);
|
|
354
|
+
}
|
|
355
|
+
function localPinReadErrorToProjectError(error) {
|
|
356
|
+
return matchError(error, {
|
|
357
|
+
LocalResolutionPinInvalidJsonError: () => new LocalStateStaleError(),
|
|
358
|
+
LocalResolutionPinInvalidShapeError: () => new LocalStateStaleError(),
|
|
359
|
+
LocalResolutionPinReadAbortedError: (error) => error,
|
|
360
|
+
UnhandledException: (error) => error
|
|
255
361
|
});
|
|
256
|
-
return localPin;
|
|
257
362
|
}
|
|
258
363
|
function resolvedTarget(workspace, project, projectSource, resolutionDetails) {
|
|
259
364
|
return {
|
|
@@ -278,4 +383,4 @@ function toProjectSummary(project) {
|
|
|
278
383
|
};
|
|
279
384
|
}
|
|
280
385
|
//#endregion
|
|
281
|
-
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 };
|