@prisma/cli 3.0.0-beta.0 → 3.0.0-beta.10
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 +18 -3
- package/dist/adapters/git.js +8 -3
- package/dist/adapters/local-state.js +12 -4
- package/dist/adapters/mock-api.js +81 -2
- package/dist/adapters/token-storage.js +63 -22
- package/dist/cli.js +17 -2
- package/dist/cli2.js +7 -3
- package/dist/commands/app/index.js +26 -13
- package/dist/commands/branch/index.js +2 -27
- package/dist/commands/database/index.js +159 -0
- package/dist/commands/env.js +8 -4
- package/dist/commands/project/index.js +28 -2
- package/dist/controllers/app-env-api.js +54 -0
- package/dist/controllers/app-env-file.js +181 -0
- package/dist/controllers/app-env.js +284 -132
- package/dist/controllers/app.js +493 -344
- package/dist/controllers/auth.js +8 -8
- package/dist/controllers/branch.js +78 -48
- package/dist/controllers/database.js +318 -0
- package/dist/controllers/project.js +302 -75
- package/dist/lib/app/branch-database-deploy.js +373 -0
- package/dist/lib/app/branch-database.js +316 -0
- package/dist/lib/app/bun-project.js +12 -5
- package/dist/lib/app/deploy-output.js +10 -1
- 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 +34 -18
- package/dist/lib/app/preview-branch-database.js +102 -0
- package/dist/lib/app/preview-build-settings.js +385 -0
- package/dist/lib/app/preview-build.js +272 -81
- package/dist/lib/app/preview-provider.js +163 -54
- package/dist/lib/app/production-deploy-gate.js +161 -0
- package/dist/lib/auth/auth-ops.js +69 -19
- package/dist/lib/auth/guard.js +3 -2
- package/dist/lib/auth/login.js +109 -14
- package/dist/lib/database/provider.js +167 -0
- package/dist/lib/diagnostics.js +15 -0
- package/dist/lib/git/local-branch.js +41 -0
- package/dist/lib/git/local-status.js +57 -0
- package/dist/lib/project/interactive-setup.js +56 -0
- package/dist/lib/project/local-pin.js +182 -33
- package/dist/lib/project/resolution.js +287 -105
- package/dist/lib/project/setup.js +132 -0
- package/dist/presenters/app-env.js +149 -14
- package/dist/presenters/app.js +170 -20
- package/dist/presenters/auth.js +19 -6
- package/dist/presenters/branch.js +37 -102
- package/dist/presenters/database.js +274 -0
- package/dist/presenters/project.js +100 -47
- package/dist/presenters/verbose-context.js +64 -0
- package/dist/shell/command-arguments.js +6 -0
- package/dist/shell/command-meta.js +139 -16
- package/dist/shell/command-runner.js +38 -8
- package/dist/shell/diagnostics-output.js +63 -0
- package/dist/shell/errors.js +14 -1
- package/dist/shell/output.js +13 -2
- package/dist/shell/runtime.js +3 -3
- package/dist/shell/ui.js +23 -1
- package/dist/shell/update-check.js +247 -0
- package/dist/use-cases/auth.js +15 -4
- package/dist/use-cases/branch.js +20 -68
- package/dist/use-cases/create-cli-gateways.js +2 -17
- package/dist/use-cases/project.js +2 -1
- package/package.json +12 -10
package/dist/controllers/app.js
CHANGED
|
@@ -7,16 +7,23 @@ import { canPrompt } from "../shell/runtime.js";
|
|
|
7
7
|
import { confirmPrompt, selectPrompt, textPrompt } from "../shell/prompt.js";
|
|
8
8
|
import { requireComputeAuth } from "../lib/auth/guard.js";
|
|
9
9
|
import { readAuthState } from "../lib/auth/auth-ops.js";
|
|
10
|
-
import {
|
|
11
|
-
import { renderDeployOutputRows } from "../lib/app/deploy-output.js";
|
|
12
|
-
import { readBunPackageJson } from "../lib/app/bun-project.js";
|
|
10
|
+
import { envVarNames, parseEnvInputs } from "../lib/app/env-vars.js";
|
|
11
|
+
import { renderDeployOutputRows, renderDeploySettingsPreview } from "../lib/app/deploy-output.js";
|
|
12
|
+
import { readBunPackageEntrypoint, readBunPackageJson } from "../lib/app/bun-project.js";
|
|
13
13
|
import { DEFAULT_LOCAL_DEV_PORT, resolveLocalBuildType, runLocalApp } from "../lib/app/local-dev.js";
|
|
14
|
-
import {
|
|
15
|
-
import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH,
|
|
14
|
+
import { formatCommandArgument } from "../shell/command-arguments.js";
|
|
15
|
+
import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH, readLocalResolutionPin } from "../lib/project/local-pin.js";
|
|
16
|
+
import { buildProjectSetupNextActions, inferTargetName, projectNotFoundError, projectResolutionErrorToCliError, resolveDurablePlatformMapping, resolveProjectTarget, sortProjects } from "../lib/project/resolution.js";
|
|
17
|
+
import { bindProjectToDirectory, projectCreateFailedError, projectDirectoryBindingErrorToCliError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary } from "../lib/project/setup.js";
|
|
18
|
+
import { promptForProjectSetupChoice } from "../lib/project/interactive-setup.js";
|
|
19
|
+
import { readLocalGitBranch } from "../lib/git/local-branch.js";
|
|
20
|
+
import { resolveOrCreatePreviewBuildSettings } from "../lib/app/preview-build-settings.js";
|
|
16
21
|
import { PREVIEW_BUILD_TYPES, RESOLVED_PREVIEW_BUILD_TYPES, executePreviewBuild } from "../lib/app/preview-build.js";
|
|
17
22
|
import { PREVIEW_DEFAULT_REGION } from "../lib/app/preview-interaction.js";
|
|
23
|
+
import { maybeSetupBranchDatabase } from "../lib/app/branch-database-deploy.js";
|
|
18
24
|
import { createPreviewDeployProgress, createPreviewDeployProgressState, createPreviewPromoteProgress } from "../lib/app/preview-progress.js";
|
|
19
25
|
import { PreviewDomainApiError, createPreviewAppProvider } from "../lib/app/preview-provider.js";
|
|
26
|
+
import { enforceProductionDeployGate } from "../lib/app/production-deploy-gate.js";
|
|
20
27
|
import { formatDomainFailureFix } from "../lib/app/domain-guidance.js";
|
|
21
28
|
import { createSelectPromptPort } from "./select-prompt-port.js";
|
|
22
29
|
import { requireAuthenticatedAuthState } from "./auth.js";
|
|
@@ -24,12 +31,15 @@ import { listRealWorkspaceProjects } from "./project.js";
|
|
|
24
31
|
import { access, readFile } from "node:fs/promises";
|
|
25
32
|
import path from "node:path";
|
|
26
33
|
import open from "open";
|
|
34
|
+
import { Result, matchError } from "better-result";
|
|
27
35
|
//#region src/controllers/app.ts
|
|
28
36
|
const DEPLOY_FRAMEWORKS = [
|
|
29
37
|
"nextjs",
|
|
30
38
|
"hono",
|
|
31
|
-
"tanstack-start"
|
|
39
|
+
"tanstack-start",
|
|
40
|
+
"bun"
|
|
32
41
|
];
|
|
42
|
+
const TANSTACK_START_PACKAGES = ["@tanstack/react-start", "@tanstack/solid-start"];
|
|
33
43
|
const FRAMEWORK_DEFAULT_HTTP_PORT = 3e3;
|
|
34
44
|
const PRISMA_PROJECT_ID_ENV_VAR = "PRISMA_PROJECT_ID";
|
|
35
45
|
const PRISMA_APP_ID_ENV_VAR = "PRISMA_APP_ID";
|
|
@@ -43,7 +53,8 @@ async function runAppBuild(context, entrypoint, requestedBuildType) {
|
|
|
43
53
|
const { artifact, buildType: actualBuildType } = await executePreviewBuild({
|
|
44
54
|
appPath: context.runtime.cwd,
|
|
45
55
|
entrypoint,
|
|
46
|
-
buildType
|
|
56
|
+
buildType,
|
|
57
|
+
signal: context.runtime.signal
|
|
47
58
|
});
|
|
48
59
|
return {
|
|
49
60
|
command: "app.build",
|
|
@@ -73,12 +84,13 @@ async function runAppRun(context, entrypoint, requestedBuildType, requestedPort)
|
|
|
73
84
|
buildType: resolvedBuildType,
|
|
74
85
|
entrypoint,
|
|
75
86
|
port,
|
|
76
|
-
env: context.runtime.env
|
|
87
|
+
env: context.runtime.env,
|
|
88
|
+
signal: context.runtime.signal
|
|
77
89
|
});
|
|
78
90
|
} catch (error) {
|
|
79
91
|
throw runFailedError("Local app run failed", error);
|
|
80
92
|
}
|
|
81
|
-
if (runResult.signal === "SIGINT" || runResult.signal === "SIGTERM")
|
|
93
|
+
if (runResult.signal === "SIGINT" || runResult.signal === "SIGTERM") throw new DOMException("Command canceled", "AbortError");
|
|
82
94
|
else if (runResult.exitCode !== 0) throw runFailedError("Local app run failed", `The ${formatFrameworkName(runResult.framework)} process exited with code ${runResult.exitCode}.`, runResult.exitCode);
|
|
83
95
|
return {
|
|
84
96
|
command: "app.run",
|
|
@@ -96,67 +108,84 @@ async function runAppDeploy(context, appName, options) {
|
|
|
96
108
|
ensurePreviewAppMode(context);
|
|
97
109
|
const envProjectId = readDeployEnvOverride(context, PRISMA_PROJECT_ID_ENV_VAR);
|
|
98
110
|
const envAppId = readDeployEnvOverride(context, PRISMA_APP_ID_ENV_VAR);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
assertExclusiveDeployProjectInputs({
|
|
112
|
+
projectRef: options?.projectRef,
|
|
113
|
+
createProjectName: options?.createProjectName,
|
|
114
|
+
envProjectId
|
|
115
|
+
});
|
|
116
|
+
const localPinReadResult = Boolean(envProjectId || options?.projectRef || options?.createProjectName) ? Result.ok({ kind: "missing" }) : await readLocalResolutionPin(context.runtime.cwd, context.runtime.signal);
|
|
117
|
+
if (localPinReadResult.isErr()) throw localPinReadErrorToDeployError(localPinReadResult.error);
|
|
118
|
+
const localPin = localPinReadResult.value;
|
|
103
119
|
const branch = await resolveDeployBranch(context, options?.branchName);
|
|
104
120
|
if (options?.httpPort) parseDeployHttpPort(options.httpPort);
|
|
105
|
-
|
|
121
|
+
assertSupportedEntrypointForRequestedDeployShape({
|
|
106
122
|
requestedFramework: options?.framework,
|
|
107
|
-
|
|
108
|
-
explicitBuildType
|
|
123
|
+
entrypoint: options?.entrypoint
|
|
109
124
|
});
|
|
110
|
-
let runtime = resolveDeployRuntime(options?.httpPort, framework);
|
|
111
|
-
assertSupportedEntrypoint(framework.buildType, options?.entrypoint, "deploy");
|
|
112
|
-
const envVars = toOptionalEnvVars(parseEnvAssignments(options?.envAssignments, { commandName: "deploy" }));
|
|
113
|
-
const firstDeploy = !skipLocalPin && localPin.kind === "missing";
|
|
114
125
|
const { provider, target, projectId } = await requireProviderAndDeployProjectContext(context, options?.projectRef, {
|
|
115
|
-
allowCreate: true,
|
|
116
126
|
branch,
|
|
127
|
+
createProjectName: options?.createProjectName,
|
|
117
128
|
envProjectId,
|
|
118
129
|
localPin
|
|
119
130
|
});
|
|
131
|
+
let localPinResult;
|
|
132
|
+
if (target.localPinAction) {
|
|
133
|
+
const setupResult = await bindProjectToDirectory(context, target.workspace, target.project, target.localPinAction);
|
|
134
|
+
if (setupResult.isErr()) throw projectDirectoryBindingErrorToCliError(setupResult.error);
|
|
135
|
+
const projectSetup = setupResult.value;
|
|
136
|
+
localPinResult = projectSetup.localPin;
|
|
137
|
+
maybeRenderProjectLinked(context, projectSetup.directory, projectSetup.project.name, projectSetup.localPin.path);
|
|
138
|
+
}
|
|
139
|
+
let framework = await resolveDeployFramework(context, {
|
|
140
|
+
requestedFramework: options?.framework,
|
|
141
|
+
entrypoint: options?.entrypoint
|
|
142
|
+
});
|
|
143
|
+
let runtime = resolveDeployRuntime(options?.httpPort, framework);
|
|
144
|
+
assertSupportedEntrypoint(framework.buildType, options?.entrypoint, "deploy");
|
|
145
|
+
const envVars = toOptionalEnvVars(await parseEnvInputs(context.runtime.cwd, options?.envAssignments, { commandName: "deploy" }));
|
|
120
146
|
const selectedApp = await resolveDeployAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), {
|
|
121
147
|
explicitAppName: appName,
|
|
122
148
|
explicitAppId: envAppId,
|
|
123
|
-
firstDeploy,
|
|
124
|
-
inferName: () => inferTargetName(context.runtime.cwd)
|
|
149
|
+
firstDeploy: Boolean(target.localPinAction),
|
|
150
|
+
inferName: () => inferTargetName(context.runtime.cwd, context.runtime.signal)
|
|
125
151
|
});
|
|
126
152
|
await maybeRenderDeploySetupBlock(context, {
|
|
127
|
-
|
|
128
|
-
workspaceName: target.workspace.name,
|
|
153
|
+
includeDirectory: !target.localPinAction,
|
|
129
154
|
projectName: target.project.name,
|
|
130
|
-
projectAnnotation: annotationForProjectResolution(target.resolution),
|
|
131
155
|
branchName: target.branch.name,
|
|
132
|
-
|
|
133
|
-
appName: selectedApp.displayName,
|
|
134
|
-
appAnnotation: selectedApp.annotation,
|
|
135
|
-
framework,
|
|
136
|
-
runtime
|
|
156
|
+
appName: selectedApp.displayName
|
|
137
157
|
});
|
|
138
158
|
const customized = await maybeCustomizeDeploySettings(context, {
|
|
139
159
|
framework,
|
|
140
160
|
runtime,
|
|
141
161
|
firstDeploy: selectedApp.firstDeploy,
|
|
142
162
|
explicitFramework: Boolean(options?.framework),
|
|
143
|
-
|
|
163
|
+
explicitEntrypoint: Boolean(options?.entrypoint),
|
|
144
164
|
explicitHttpPort: Boolean(options?.httpPort)
|
|
145
165
|
});
|
|
146
166
|
framework = customized.framework;
|
|
147
167
|
runtime = customized.runtime;
|
|
168
|
+
const productionDeployGate = await enforceProductionDeployGate(context, provider, {
|
|
169
|
+
appId: selectedApp.appId,
|
|
170
|
+
appName: selectedApp.displayName,
|
|
171
|
+
branchKind: target.branch.kind,
|
|
172
|
+
prod: options?.prod === true
|
|
173
|
+
});
|
|
148
174
|
const buildType = framework.buildType;
|
|
149
175
|
assertSupportedEntrypoint(buildType, options?.entrypoint, "deploy");
|
|
176
|
+
const entrypoint = await resolveDeployEntrypoint(context.runtime.cwd, framework, options?.entrypoint, context.runtime.signal);
|
|
177
|
+
const buildSettingsResolution = await resolveOrCreatePreviewBuildSettings({
|
|
178
|
+
appPath: context.runtime.cwd,
|
|
179
|
+
buildType,
|
|
180
|
+
signal: context.runtime.signal
|
|
181
|
+
});
|
|
182
|
+
maybeRenderDeployBuildSettings(context, buildSettingsResolution);
|
|
150
183
|
const portMapping = parseDeployPortMapping(String(runtime.port));
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
});
|
|
157
|
-
await ensureLocalResolutionPinGitignore(context.runtime.cwd);
|
|
158
|
-
maybeRenderLocalPinBound(context, target.project.name);
|
|
159
|
-
}
|
|
184
|
+
const branchDatabaseSetup = await maybeSetupBranchDatabase(context, provider, projectId, toBranchDatabaseDeployBranch(target.branch), {
|
|
185
|
+
db: options?.db,
|
|
186
|
+
providedEnvVars: envVars,
|
|
187
|
+
firstProductionDeploy: productionDeployGate.firstProductionDeploy
|
|
188
|
+
});
|
|
160
189
|
const progressState = createPreviewDeployProgressState();
|
|
161
190
|
const deployStartedAt = Date.now();
|
|
162
191
|
const deployResult = await provider.deployApp({
|
|
@@ -166,11 +195,13 @@ async function runAppDeploy(context, appName, options) {
|
|
|
166
195
|
appId: selectedApp.appId,
|
|
167
196
|
appName: selectedApp.appName,
|
|
168
197
|
region: selectedApp.region,
|
|
169
|
-
entrypoint
|
|
198
|
+
entrypoint,
|
|
170
199
|
buildType,
|
|
200
|
+
buildSettings: buildSettingsResolution.settings,
|
|
171
201
|
portMapping,
|
|
172
202
|
envVars,
|
|
173
203
|
interaction: void 0,
|
|
204
|
+
signal: context.runtime.signal,
|
|
174
205
|
progress: createPreviewDeployProgress(context.output.stderr, context.ui, !context.flags.json && !context.flags.quiet, progressState)
|
|
175
206
|
}).catch((error) => {
|
|
176
207
|
throw appDeployFailedError(error, progressState);
|
|
@@ -186,38 +217,61 @@ async function runAppDeploy(context, appName, options) {
|
|
|
186
217
|
result: {
|
|
187
218
|
workspace: target.workspace,
|
|
188
219
|
project: target.project,
|
|
189
|
-
branch: target.branch,
|
|
220
|
+
branch: toResultBranch(target.branch),
|
|
190
221
|
resolution: target.resolution,
|
|
222
|
+
branchDatabase: branchDatabaseSetup.result,
|
|
191
223
|
app: {
|
|
192
224
|
id: deployResult.app.id,
|
|
193
225
|
name: deployResult.app.name
|
|
194
226
|
},
|
|
195
227
|
deployment: deployResult.deployment,
|
|
228
|
+
deploySettings: {
|
|
229
|
+
config: {
|
|
230
|
+
path: buildSettingsResolution.relativeConfigPath,
|
|
231
|
+
status: buildSettingsResolution.status
|
|
232
|
+
},
|
|
233
|
+
buildCommand: {
|
|
234
|
+
value: buildSettingsResolution.settings.buildCommand,
|
|
235
|
+
source: buildSettingsResolution.settings.buildCommandSource
|
|
236
|
+
},
|
|
237
|
+
outputDirectory: {
|
|
238
|
+
value: buildSettingsResolution.settings.outputDirectory,
|
|
239
|
+
source: buildSettingsResolution.settings.outputDirectorySource
|
|
240
|
+
},
|
|
241
|
+
framework: {
|
|
242
|
+
key: framework.key,
|
|
243
|
+
buildType,
|
|
244
|
+
name: framework.displayName,
|
|
245
|
+
source: framework.annotation
|
|
246
|
+
},
|
|
247
|
+
entrypoint: entrypoint ?? null,
|
|
248
|
+
httpPort: runtime.port,
|
|
249
|
+
region: selectedApp.region ?? null,
|
|
250
|
+
envVars: envVarNames(envVars)
|
|
251
|
+
},
|
|
196
252
|
durationMs: deployDurationMs,
|
|
197
|
-
localPin:
|
|
198
|
-
path: LOCAL_RESOLUTION_PIN_RELATIVE_PATH,
|
|
199
|
-
written: true
|
|
200
|
-
} : void 0
|
|
253
|
+
localPin: localPinResult
|
|
201
254
|
},
|
|
202
|
-
warnings:
|
|
255
|
+
warnings: branchDatabaseSetup.warnings,
|
|
203
256
|
nextSteps: ["prisma-cli app list-deploys", `prisma-cli app show-deploy ${deployResult.deployment.id}`]
|
|
204
257
|
};
|
|
205
258
|
}
|
|
206
259
|
async function runAppListDeploys(context, appName, projectRef) {
|
|
207
260
|
ensurePreviewAppMode(context);
|
|
208
|
-
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
261
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app list-deploys" });
|
|
209
262
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), appName);
|
|
210
263
|
if (!selectedApp) return {
|
|
211
264
|
command: "app.list-deploys",
|
|
212
265
|
result: {
|
|
213
266
|
projectId,
|
|
267
|
+
verboseContext: toAppVerboseContext(target),
|
|
214
268
|
app: null,
|
|
215
269
|
deployments: []
|
|
216
270
|
},
|
|
217
271
|
warnings: [],
|
|
218
272
|
nextSteps: ["prisma-cli app deploy"]
|
|
219
273
|
};
|
|
220
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
274
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
221
275
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app deploy"]);
|
|
222
276
|
});
|
|
223
277
|
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
@@ -230,6 +284,7 @@ async function runAppListDeploys(context, appName, projectRef) {
|
|
|
230
284
|
command: "app.list-deploys",
|
|
231
285
|
result: {
|
|
232
286
|
projectId,
|
|
287
|
+
verboseContext: toAppVerboseContext(target),
|
|
233
288
|
app: {
|
|
234
289
|
id: deploymentsResult.app.id,
|
|
235
290
|
name: deploymentsResult.app.name
|
|
@@ -242,12 +297,13 @@ async function runAppListDeploys(context, appName, projectRef) {
|
|
|
242
297
|
}
|
|
243
298
|
async function runAppShow(context, appName, projectRef) {
|
|
244
299
|
ensurePreviewAppMode(context);
|
|
245
|
-
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
300
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app show" });
|
|
246
301
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), appName);
|
|
247
302
|
if (!selectedApp) return {
|
|
248
303
|
command: "app.show",
|
|
249
304
|
result: {
|
|
250
305
|
projectId,
|
|
306
|
+
verboseContext: toAppVerboseContext(target),
|
|
251
307
|
app: null,
|
|
252
308
|
liveDeployment: null,
|
|
253
309
|
liveUrl: null,
|
|
@@ -256,7 +312,7 @@ async function runAppShow(context, appName, projectRef) {
|
|
|
256
312
|
warnings: [],
|
|
257
313
|
nextSteps: ["prisma-cli app deploy"]
|
|
258
314
|
};
|
|
259
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
315
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
260
316
|
throw deployFailedError("Failed to inspect app", error, ["prisma-cli app list-deploys"]);
|
|
261
317
|
});
|
|
262
318
|
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
@@ -270,6 +326,7 @@ async function runAppShow(context, appName, projectRef) {
|
|
|
270
326
|
command: "app.show",
|
|
271
327
|
result: {
|
|
272
328
|
projectId,
|
|
329
|
+
verboseContext: toAppVerboseContext(target),
|
|
273
330
|
app: {
|
|
274
331
|
id: deploymentsResult.app.id,
|
|
275
332
|
name: deploymentsResult.app.name
|
|
@@ -284,7 +341,7 @@ async function runAppShow(context, appName, projectRef) {
|
|
|
284
341
|
}
|
|
285
342
|
async function runAppShowDeploy(context, deploymentId) {
|
|
286
343
|
ensurePreviewAppMode(context);
|
|
287
|
-
const deployment = await (await requirePreviewAppProvider(context)).showDeployment(deploymentId).catch((error) => {
|
|
344
|
+
const deployment = await (await requirePreviewAppProvider(context)).showDeployment(deploymentId, { signal: context.runtime.signal }).catch((error) => {
|
|
288
345
|
throw deployFailedError("Failed to show deployment", error, ["prisma-cli app list-deploys"]);
|
|
289
346
|
});
|
|
290
347
|
if (!deployment) throw new CliError({
|
|
@@ -318,10 +375,10 @@ async function runAppShowDeploy(context, deploymentId) {
|
|
|
318
375
|
}
|
|
319
376
|
async function runAppOpen(context, appName, projectRef) {
|
|
320
377
|
ensurePreviewAppMode(context);
|
|
321
|
-
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
378
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app open" });
|
|
322
379
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), appName);
|
|
323
380
|
if (!selectedApp) throw noDeploymentsError("No deployments available to open", "The resolved project does not have any deployed app yet.");
|
|
324
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
381
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
325
382
|
throw deployFailedError("Failed to resolve app URL", error, ["prisma-cli app show"]);
|
|
326
383
|
});
|
|
327
384
|
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
@@ -334,11 +391,16 @@ async function runAppOpen(context, appName, projectRef) {
|
|
|
334
391
|
if (!liveDeployment) throw noDeploymentsError("No deployments available to open", `The selected app "${deploymentsResult.app.name}" does not have any deployments yet.`);
|
|
335
392
|
if (!deploymentsResult.app.liveUrl) throw featureUnavailableError("Live URL is not available for the selected app", "Deployments exist, but the provider does not expose a stable live service URL for this app yet.", "Run prisma-cli app show to inspect the current deployment state and try again after the app reports a live URL.", ["prisma-cli app show"], "app");
|
|
336
393
|
const shouldOpen = canPrompt(context);
|
|
337
|
-
if (shouldOpen)
|
|
394
|
+
if (shouldOpen) {
|
|
395
|
+
context.runtime.signal.throwIfAborted();
|
|
396
|
+
await open(deploymentsResult.app.liveUrl);
|
|
397
|
+
context.runtime.signal.throwIfAborted();
|
|
398
|
+
}
|
|
338
399
|
return {
|
|
339
400
|
command: "app.open",
|
|
340
401
|
result: {
|
|
341
402
|
projectId,
|
|
403
|
+
verboseContext: toAppVerboseContext(target),
|
|
342
404
|
app: {
|
|
343
405
|
id: deploymentsResult.app.id,
|
|
344
406
|
name: deploymentsResult.app.name
|
|
@@ -352,10 +414,11 @@ async function runAppOpen(context, appName, projectRef) {
|
|
|
352
414
|
}
|
|
353
415
|
async function runAppDomainAdd(context, hostname, options) {
|
|
354
416
|
const normalizedHostname = normalizeDomainHostname(hostname);
|
|
355
|
-
const target = await resolveAppDomainTarget(context, options);
|
|
417
|
+
const target = await resolveAppDomainTarget(context, options, `app domain add ${normalizedHostname}`);
|
|
356
418
|
const added = await target.provider.addDomain({
|
|
357
419
|
appId: target.app.id,
|
|
358
|
-
hostname: normalizedHostname
|
|
420
|
+
hostname: normalizedHostname,
|
|
421
|
+
signal: context.runtime.signal
|
|
359
422
|
}).catch((error) => {
|
|
360
423
|
throw domainCommandError("add", error, normalizedHostname);
|
|
361
424
|
});
|
|
@@ -372,9 +435,9 @@ async function runAppDomainAdd(context, hostname, options) {
|
|
|
372
435
|
}
|
|
373
436
|
async function runAppDomainShow(context, hostname, options) {
|
|
374
437
|
const normalizedHostname = normalizeDomainHostname(hostname);
|
|
375
|
-
const target = await resolveAppDomainTarget(context, options);
|
|
376
|
-
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "show");
|
|
377
|
-
const detail = await target.provider.showDomain(domain.id).catch((error) => {
|
|
438
|
+
const target = await resolveAppDomainTarget(context, options, `app domain show ${normalizedHostname}`);
|
|
439
|
+
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "show", context.runtime.signal);
|
|
440
|
+
const detail = await target.provider.showDomain(domain.id, { signal: context.runtime.signal }).catch((error) => {
|
|
378
441
|
throw domainCommandError("show", error, normalizedHostname);
|
|
379
442
|
});
|
|
380
443
|
return {
|
|
@@ -389,10 +452,10 @@ async function runAppDomainShow(context, hostname, options) {
|
|
|
389
452
|
}
|
|
390
453
|
async function runAppDomainRemove(context, hostname, options) {
|
|
391
454
|
const normalizedHostname = normalizeDomainHostname(hostname);
|
|
392
|
-
const target = await resolveAppDomainTarget(context, options);
|
|
393
|
-
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "remove");
|
|
455
|
+
const target = await resolveAppDomainTarget(context, options, `app domain remove ${normalizedHostname}`);
|
|
456
|
+
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "remove", context.runtime.signal);
|
|
394
457
|
await confirmDomainRemoval(context, target.resultTarget, normalizedHostname);
|
|
395
|
-
await target.provider.removeDomain(domain.id).catch((error) => {
|
|
458
|
+
await target.provider.removeDomain(domain.id, { signal: context.runtime.signal }).catch((error) => {
|
|
396
459
|
throw domainCommandError("remove", error, normalizedHostname);
|
|
397
460
|
});
|
|
398
461
|
return {
|
|
@@ -408,9 +471,9 @@ async function runAppDomainRemove(context, hostname, options) {
|
|
|
408
471
|
}
|
|
409
472
|
async function runAppDomainRetry(context, hostname, options) {
|
|
410
473
|
const normalizedHostname = normalizeDomainHostname(hostname);
|
|
411
|
-
const target = await resolveAppDomainTarget(context, options);
|
|
412
|
-
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "retry");
|
|
413
|
-
const retried = await target.provider.retryDomain(domain.id).catch((error) => {
|
|
474
|
+
const target = await resolveAppDomainTarget(context, options, `app domain retry ${normalizedHostname}`);
|
|
475
|
+
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "retry", context.runtime.signal);
|
|
476
|
+
const retried = await target.provider.retryDomain(domain.id, { signal: context.runtime.signal }).catch((error) => {
|
|
414
477
|
throw domainCommandError("retry", error, normalizedHostname);
|
|
415
478
|
});
|
|
416
479
|
return {
|
|
@@ -426,8 +489,8 @@ async function runAppDomainRetry(context, hostname, options) {
|
|
|
426
489
|
async function runAppDomainWait(context, hostname, options) {
|
|
427
490
|
const normalizedHostname = normalizeDomainHostname(hostname);
|
|
428
491
|
const timeoutMs = parseDomainWaitTimeout(options?.timeout);
|
|
429
|
-
const target = await resolveAppDomainTarget(context, options);
|
|
430
|
-
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "wait");
|
|
492
|
+
const target = await resolveAppDomainTarget(context, options, `app domain wait ${normalizedHostname}`);
|
|
493
|
+
const domain = await resolveDomainByHostname(target.provider, target.app.id, normalizedHostname, "wait", context.runtime.signal);
|
|
431
494
|
if (!context.flags.json && !context.flags.quiet) context.output.stderr.write([
|
|
432
495
|
`app domain wait -> Waiting for ${normalizedHostname} to become active.`,
|
|
433
496
|
"",
|
|
@@ -470,15 +533,15 @@ async function runAppDomainWait(context, hostname, options) {
|
|
|
470
533
|
exitCode: 1,
|
|
471
534
|
nextSteps: [`prisma-cli app domain show ${normalizedHostname}`]
|
|
472
535
|
});
|
|
473
|
-
await sleep(Math.min(pollIntervalMs, Math.max(deadline - Date.now(), 0)));
|
|
474
|
-
current = await target.provider.showDomain(current.id).catch((error) => {
|
|
536
|
+
await sleep(Math.min(pollIntervalMs, Math.max(deadline - Date.now(), 0)), context.runtime.signal);
|
|
537
|
+
current = await target.provider.showDomain(current.id, { signal: context.runtime.signal }).catch((error) => {
|
|
475
538
|
throw domainCommandError("wait", error, normalizedHostname);
|
|
476
539
|
});
|
|
477
540
|
}
|
|
478
541
|
}
|
|
479
542
|
async function runAppLogs(context, appName, deploymentId, projectRef) {
|
|
480
543
|
ensurePreviewAppMode(context);
|
|
481
|
-
const { provider, target: resolvedTarget, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
544
|
+
const { provider, target: resolvedTarget, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app logs" });
|
|
482
545
|
const target = deploymentId ? await resolveExplicitLogDeployment(context, provider, projectId, resolvedTarget.branch.name, appName, deploymentId) : await resolveLiveLogDeployment(context, provider, projectId, resolvedTarget.branch.name, appName);
|
|
483
546
|
if (!context.flags.json && !context.flags.quiet) {
|
|
484
547
|
const lines = renderCommandHeader(context.ui, {
|
|
@@ -504,6 +567,7 @@ async function runAppLogs(context, appName, deploymentId, projectRef) {
|
|
|
504
567
|
}
|
|
505
568
|
await provider.streamDeploymentLogs({
|
|
506
569
|
deploymentId: target.deployment.id,
|
|
570
|
+
signal: context.runtime.signal,
|
|
507
571
|
onRecord: (record) => writeLogRecord(context, record)
|
|
508
572
|
}).catch((error) => {
|
|
509
573
|
throw deployFailedError("Failed to stream app logs", error, [`prisma-cli app show-deploy ${target.deployment.id}`, "prisma-cli app list-deploys"]);
|
|
@@ -513,7 +577,7 @@ async function resolveExplicitLogDeployment(context, provider, projectId, branch
|
|
|
513
577
|
if (appName) {
|
|
514
578
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId, branchName), appName);
|
|
515
579
|
if (!selectedApp) throw noDeploymentsError("No deployments available to stream logs", "The resolved project does not have any deployed app yet.");
|
|
516
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
580
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
517
581
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
518
582
|
});
|
|
519
583
|
const deployment = requireDeploymentForApp(deploymentsResult.deployments, deploymentId, selectedApp.name);
|
|
@@ -526,7 +590,7 @@ async function resolveExplicitLogDeployment(context, provider, projectId, branch
|
|
|
526
590
|
deployment
|
|
527
591
|
};
|
|
528
592
|
}
|
|
529
|
-
const shown = await provider.showDeployment(deploymentId).catch((error) => {
|
|
593
|
+
const shown = await provider.showDeployment(deploymentId, { signal: context.runtime.signal }).catch((error) => {
|
|
530
594
|
throw deployFailedError("Failed to show deployment", error, ["prisma-cli app list-deploys"]);
|
|
531
595
|
});
|
|
532
596
|
if (!shown) throw new CliError({
|
|
@@ -569,7 +633,7 @@ async function resolveExplicitLogDeployment(context, provider, projectId, branch
|
|
|
569
633
|
async function resolveLiveLogDeployment(context, provider, projectId, branchName, appName) {
|
|
570
634
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId, branchName), appName);
|
|
571
635
|
if (!selectedApp) throw noDeploymentsError("No deployments available to stream logs", "The resolved project does not have any deployed app yet.");
|
|
572
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
636
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
573
637
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
574
638
|
});
|
|
575
639
|
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
@@ -602,9 +666,9 @@ function writeLogRecord(context, record) {
|
|
|
602
666
|
}
|
|
603
667
|
async function runAppPromote(context, deploymentId, appName, projectRef) {
|
|
604
668
|
ensurePreviewAppMode(context);
|
|
605
|
-
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
669
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app promote" });
|
|
606
670
|
const selectedApp = await requireReleaseAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), appName, "promote");
|
|
607
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
671
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
608
672
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
609
673
|
});
|
|
610
674
|
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
@@ -617,6 +681,7 @@ async function runAppPromote(context, deploymentId, appName, projectRef) {
|
|
|
617
681
|
if (!targetAlreadyLive) await provider.promoteDeployment({
|
|
618
682
|
appId: selectedApp.id,
|
|
619
683
|
deploymentId: targetDeployment.id,
|
|
684
|
+
signal: context.runtime.signal,
|
|
620
685
|
progress: createPreviewPromoteProgress(context.output.stderr, !context.flags.json && !context.flags.quiet)
|
|
621
686
|
}).catch((error) => {
|
|
622
687
|
throw deployFailedError("Failed to promote deployment", error, ["prisma-cli app list-deploys"]);
|
|
@@ -626,6 +691,7 @@ async function runAppPromote(context, deploymentId, appName, projectRef) {
|
|
|
626
691
|
command: "app.promote",
|
|
627
692
|
result: {
|
|
628
693
|
projectId,
|
|
694
|
+
verboseContext: toAppVerboseContext(target),
|
|
629
695
|
app: {
|
|
630
696
|
id: deploymentsResult.app.id,
|
|
631
697
|
name: deploymentsResult.app.name
|
|
@@ -642,9 +708,9 @@ async function runAppPromote(context, deploymentId, appName, projectRef) {
|
|
|
642
708
|
}
|
|
643
709
|
async function runAppRollback(context, appName, deploymentId, projectRef) {
|
|
644
710
|
ensurePreviewAppMode(context);
|
|
645
|
-
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
711
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app rollback" });
|
|
646
712
|
const selectedApp = await requireReleaseAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), appName, "rollback");
|
|
647
|
-
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
713
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
648
714
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
649
715
|
});
|
|
650
716
|
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
@@ -658,6 +724,7 @@ async function runAppRollback(context, appName, deploymentId, projectRef) {
|
|
|
658
724
|
if (!targetAlreadyLive) await provider.promoteDeployment({
|
|
659
725
|
appId: selectedApp.id,
|
|
660
726
|
deploymentId: targetDeployment.id,
|
|
727
|
+
signal: context.runtime.signal,
|
|
661
728
|
progress: createPreviewPromoteProgress(context.output.stderr, !context.flags.json && !context.flags.quiet)
|
|
662
729
|
}).catch((error) => {
|
|
663
730
|
throw deployFailedError("Failed to roll back deployment", error, ["prisma-cli app list-deploys"]);
|
|
@@ -667,6 +734,7 @@ async function runAppRollback(context, appName, deploymentId, projectRef) {
|
|
|
667
734
|
command: "app.rollback",
|
|
668
735
|
result: {
|
|
669
736
|
projectId,
|
|
737
|
+
verboseContext: toAppVerboseContext(target),
|
|
670
738
|
app: {
|
|
671
739
|
id: deploymentsResult.app.id,
|
|
672
740
|
name: deploymentsResult.app.name
|
|
@@ -684,10 +752,10 @@ async function runAppRollback(context, appName, deploymentId, projectRef) {
|
|
|
684
752
|
}
|
|
685
753
|
async function runAppRemove(context, appName, projectRef) {
|
|
686
754
|
ensurePreviewAppMode(context);
|
|
687
|
-
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
755
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, projectRef, { commandName: "app remove" });
|
|
688
756
|
const selectedApp = await requireReleaseAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), appName, "remove");
|
|
689
757
|
await confirmAppRemoval(context, selectedApp);
|
|
690
|
-
const removedApp = await provider.removeApp(selectedApp.id).catch((error) => {
|
|
758
|
+
const removedApp = await provider.removeApp(selectedApp.id, { signal: context.runtime.signal }).catch((error) => {
|
|
691
759
|
throw removeFailedError("Failed to remove app", error, ["prisma-cli app show", "prisma-cli app list-deploys"]);
|
|
692
760
|
});
|
|
693
761
|
const warnings = await cleanupRemovedAppState(context, projectId, removedApp.id);
|
|
@@ -695,6 +763,7 @@ async function runAppRemove(context, appName, projectRef) {
|
|
|
695
763
|
command: "app.remove",
|
|
696
764
|
result: {
|
|
697
765
|
projectId,
|
|
766
|
+
verboseContext: toAppVerboseContext(target),
|
|
698
767
|
app: {
|
|
699
768
|
id: removedApp.id,
|
|
700
769
|
name: removedApp.name
|
|
@@ -705,7 +774,7 @@ async function runAppRemove(context, appName, projectRef) {
|
|
|
705
774
|
nextSteps: ["prisma-cli app deploy", "prisma-cli app list-deploys"]
|
|
706
775
|
};
|
|
707
776
|
}
|
|
708
|
-
async function resolveAppDomainTarget(context, options) {
|
|
777
|
+
async function resolveAppDomainTarget(context, options, commandName = "app domain") {
|
|
709
778
|
ensurePreviewAppMode(context);
|
|
710
779
|
const branch = resolveDomainBranch(options?.branchName);
|
|
711
780
|
if (toBranchKind(branch.name) !== "production") throw new CliError({
|
|
@@ -719,14 +788,10 @@ async function resolveAppDomainTarget(context, options) {
|
|
|
719
788
|
});
|
|
720
789
|
const envProjectId = readDeployEnvOverride(context, PRISMA_PROJECT_ID_ENV_VAR);
|
|
721
790
|
const envAppId = readDeployEnvOverride(context, PRISMA_APP_ID_ENV_VAR);
|
|
722
|
-
const
|
|
723
|
-
const localPin = skipLocalPin ? { kind: "missing" } : await readLocalResolutionPin(context.runtime.cwd);
|
|
724
|
-
if (!skipLocalPin && localPin.kind === "invalid") throw localResolutionPinStaleError();
|
|
725
|
-
const { provider, target, projectId } = await requireProviderAndDeployProjectContext(context, options?.projectRef, {
|
|
726
|
-
allowCreate: false,
|
|
791
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, options?.projectRef, {
|
|
727
792
|
branch,
|
|
728
|
-
|
|
729
|
-
|
|
793
|
+
commandName,
|
|
794
|
+
envProjectId
|
|
730
795
|
});
|
|
731
796
|
const selectedApp = await resolveDomainAppSelection(context, projectId, await listApps(context, provider, projectId, target.branch.name), {
|
|
732
797
|
explicitAppName: options?.appName,
|
|
@@ -742,7 +807,7 @@ async function resolveAppDomainTarget(context, options) {
|
|
|
742
807
|
resultTarget: {
|
|
743
808
|
workspace: target.workspace,
|
|
744
809
|
project: target.project,
|
|
745
|
-
branch: target.branch,
|
|
810
|
+
branch: toResultBranch(target.branch),
|
|
746
811
|
app: {
|
|
747
812
|
id: selectedApp.id,
|
|
748
813
|
name: selectedApp.name
|
|
@@ -766,8 +831,8 @@ async function resolveDomainAppSelection(context, projectId, apps, options) {
|
|
|
766
831
|
if (selectedApp) return selectedApp;
|
|
767
832
|
throw usageError("Custom domain requires an existing app on the production branch", "The resolved production branch does not have an app that can receive a custom domain.", "Deploy or promote an app to production first, then rerun the domain command.", ["prisma-cli app deploy --branch production", "prisma-cli app show"], "app");
|
|
768
833
|
}
|
|
769
|
-
async function resolveDomainByHostname(provider, appId, hostname, command) {
|
|
770
|
-
const matched = (await provider.listDomains(appId).catch((error) => {
|
|
834
|
+
async function resolveDomainByHostname(provider, appId, hostname, command, signal) {
|
|
835
|
+
const matched = (await provider.listDomains(appId, { signal }).catch((error) => {
|
|
771
836
|
throw domainCommandError(command, error, hostname);
|
|
772
837
|
})).find((domain) => sameDomainHostname(domain.hostname, hostname));
|
|
773
838
|
if (matched) return matched;
|
|
@@ -998,9 +1063,20 @@ function formatElapsed(milliseconds) {
|
|
|
998
1063
|
const remainingSeconds = seconds % 60;
|
|
999
1064
|
return `${minutes}:${String(remainingSeconds).padStart(2, "0")}`;
|
|
1000
1065
|
}
|
|
1001
|
-
async function sleep(milliseconds) {
|
|
1066
|
+
async function sleep(milliseconds, signal) {
|
|
1002
1067
|
if (milliseconds <= 0) return;
|
|
1003
|
-
|
|
1068
|
+
signal.throwIfAborted();
|
|
1069
|
+
await new Promise((resolve, reject) => {
|
|
1070
|
+
const onAbort = () => {
|
|
1071
|
+
clearTimeout(timeout);
|
|
1072
|
+
reject(signal.reason);
|
|
1073
|
+
};
|
|
1074
|
+
const timeout = setTimeout(() => {
|
|
1075
|
+
signal.removeEventListener("abort", onAbort);
|
|
1076
|
+
resolve();
|
|
1077
|
+
}, milliseconds);
|
|
1078
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1079
|
+
});
|
|
1004
1080
|
}
|
|
1005
1081
|
async function resolveDeployAppSelection(context, projectId, apps, options) {
|
|
1006
1082
|
if (options.explicitAppName) {
|
|
@@ -1215,15 +1291,18 @@ function resolveRollbackTarget(deployments, currentLiveDeploymentId) {
|
|
|
1215
1291
|
});
|
|
1216
1292
|
}
|
|
1217
1293
|
async function listApps(context, provider, projectId, branchName) {
|
|
1218
|
-
return provider.listApps(projectId, {
|
|
1294
|
+
return provider.listApps(projectId, {
|
|
1295
|
+
branchName,
|
|
1296
|
+
signal: context.runtime.signal
|
|
1297
|
+
}).then(sortApps).catch((error) => {
|
|
1219
1298
|
if (isMissingProjectError(error)) throw new CliError({
|
|
1220
1299
|
code: "PROJECT_NOT_FOUND",
|
|
1221
1300
|
domain: "project",
|
|
1222
1301
|
summary: "Project not found",
|
|
1223
1302
|
why: `The resolved project "${projectId}" does not exist in the authenticated workspace or is no longer accessible.`,
|
|
1224
|
-
fix: "Pass --project <id-or-name>, or run prisma-cli project show to inspect
|
|
1303
|
+
fix: "Pass --project <id-or-name>, or run prisma-cli project show to inspect this directory's binding.",
|
|
1225
1304
|
exitCode: 1,
|
|
1226
|
-
nextSteps: ["prisma-cli project show", "prisma-cli
|
|
1305
|
+
nextSteps: ["prisma-cli project show", "prisma-cli project link <id-or-name>"]
|
|
1227
1306
|
});
|
|
1228
1307
|
throw deployFailedError("Failed to list apps", error, ["prisma-cli project show"]);
|
|
1229
1308
|
});
|
|
@@ -1233,20 +1312,20 @@ async function requirePreviewAppProvider(context) {
|
|
|
1233
1312
|
return provider;
|
|
1234
1313
|
}
|
|
1235
1314
|
async function requirePreviewAppProviderWithClient(context) {
|
|
1236
|
-
const client = await requireComputeAuth(context.runtime.env);
|
|
1315
|
+
const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
|
|
1237
1316
|
if (!client) throw authRequiredError(["prisma-cli auth login"]);
|
|
1238
1317
|
return {
|
|
1239
1318
|
client,
|
|
1240
|
-
provider: createPreviewAppProvider(client, createPreviewLogAuthOptions(context.runtime.env))
|
|
1319
|
+
provider: createPreviewAppProvider(client, createPreviewLogAuthOptions(context.runtime.env, context.runtime.signal))
|
|
1241
1320
|
};
|
|
1242
1321
|
}
|
|
1243
|
-
function createPreviewLogAuthOptions(env) {
|
|
1322
|
+
function createPreviewLogAuthOptions(env, signal) {
|
|
1244
1323
|
const rawToken = env[SERVICE_TOKEN_ENV_VAR]?.trim();
|
|
1245
1324
|
if (rawToken) return {
|
|
1246
1325
|
baseUrl: getApiBaseUrl(env),
|
|
1247
1326
|
getToken: async () => rawToken
|
|
1248
1327
|
};
|
|
1249
|
-
const tokenStorage = new FileTokenStorage(env);
|
|
1328
|
+
const tokenStorage = new FileTokenStorage(env, signal);
|
|
1250
1329
|
return {
|
|
1251
1330
|
baseUrl: getApiBaseUrl(env),
|
|
1252
1331
|
getToken: async () => {
|
|
@@ -1258,7 +1337,7 @@ function createPreviewLogAuthOptions(env) {
|
|
|
1258
1337
|
}
|
|
1259
1338
|
async function requireProviderAndProjectContext(context, explicitProject, options) {
|
|
1260
1339
|
const { client, provider } = await requirePreviewAppProviderWithClient(context);
|
|
1261
|
-
const target = await resolveProjectContext(context, client,
|
|
1340
|
+
const target = await resolveProjectContext(context, client, explicitProject, options);
|
|
1262
1341
|
return {
|
|
1263
1342
|
client,
|
|
1264
1343
|
provider,
|
|
@@ -1276,36 +1355,24 @@ async function requireProviderAndDeployProjectContext(context, explicitProject,
|
|
|
1276
1355
|
projectId: target.project.id
|
|
1277
1356
|
};
|
|
1278
1357
|
}
|
|
1279
|
-
async function resolveProjectContext(context, client,
|
|
1358
|
+
async function resolveProjectContext(context, client, explicitProject, options) {
|
|
1280
1359
|
const authState = await requireAuthenticatedAuthState(context);
|
|
1281
1360
|
if (!authState.workspace) throw workspaceRequiredError();
|
|
1282
|
-
const
|
|
1361
|
+
const resolvedResult = await resolveProjectTarget({
|
|
1283
1362
|
context,
|
|
1284
1363
|
workspace: authState.workspace,
|
|
1285
1364
|
explicitProject,
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
throw createProjectOnFirstDeployError({
|
|
1290
|
-
error,
|
|
1291
|
-
inferredName: name,
|
|
1292
|
-
workspaceName: authState.workspace.name
|
|
1293
|
-
});
|
|
1294
|
-
});
|
|
1295
|
-
return {
|
|
1296
|
-
id: project.id,
|
|
1297
|
-
name: project.name,
|
|
1298
|
-
workspace: authState.workspace
|
|
1299
|
-
};
|
|
1300
|
-
} : void 0,
|
|
1301
|
-
allowCreate: options?.allowCreate,
|
|
1302
|
-
prompt: createSelectPromptPort(context),
|
|
1303
|
-
remember: true
|
|
1365
|
+
envProjectId: options?.envProjectId,
|
|
1366
|
+
listProjects: () => listRealWorkspaceProjects(client, authState.workspace, context.runtime.signal),
|
|
1367
|
+
commandName: options?.commandName
|
|
1304
1368
|
});
|
|
1369
|
+
if (resolvedResult.isErr()) throw projectResolutionErrorToCliError(resolvedResult.error);
|
|
1370
|
+
const resolved = resolvedResult.value;
|
|
1305
1371
|
const branch = options?.branch ?? await resolveDeployBranch(context, void 0);
|
|
1306
1372
|
return {
|
|
1307
1373
|
...resolved,
|
|
1308
1374
|
branch: {
|
|
1375
|
+
id: null,
|
|
1309
1376
|
name: branch.name,
|
|
1310
1377
|
kind: toBranchKind(branch.name)
|
|
1311
1378
|
}
|
|
@@ -1315,35 +1382,35 @@ async function resolveDeployProjectContext(context, client, provider, explicitPr
|
|
|
1315
1382
|
const workspace = (await requireAuthenticatedAuthState(context)).workspace;
|
|
1316
1383
|
if (!workspace) throw workspaceRequiredError();
|
|
1317
1384
|
const branch = options.branch ?? await resolveDeployBranch(context, void 0);
|
|
1318
|
-
const projects = await listRealWorkspaceProjects(client, workspace);
|
|
1319
|
-
|
|
1320
|
-
const project = await provider.createProject({ name }).catch((error) => {
|
|
1321
|
-
throw createProjectOnFirstDeployError({
|
|
1322
|
-
error,
|
|
1323
|
-
inferredName: name,
|
|
1324
|
-
workspaceName: workspace.name
|
|
1325
|
-
});
|
|
1326
|
-
});
|
|
1327
|
-
return {
|
|
1328
|
-
id: project.id,
|
|
1329
|
-
name: project.name,
|
|
1330
|
-
workspace
|
|
1331
|
-
};
|
|
1332
|
-
} : void 0;
|
|
1333
|
-
if (explicitProject) return withDeployBranch(await resolveProjectTarget({
|
|
1334
|
-
context,
|
|
1385
|
+
const projects = await listRealWorkspaceProjects(client, workspace, context.runtime.signal);
|
|
1386
|
+
if (explicitProject) return withRemoteDeployBranch(provider, {
|
|
1335
1387
|
workspace,
|
|
1336
|
-
explicitProject,
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1388
|
+
project: toProjectSummary(resolveProjectForSetup(explicitProject, projects, workspace)),
|
|
1389
|
+
resolution: {
|
|
1390
|
+
projectSource: "explicit",
|
|
1391
|
+
targetName: explicitProject,
|
|
1392
|
+
targetNameSource: "explicit"
|
|
1393
|
+
},
|
|
1394
|
+
localPinAction: "linked"
|
|
1395
|
+
}, branch, context.runtime.signal);
|
|
1396
|
+
if (options.createProjectName) {
|
|
1397
|
+
const projectName = options.createProjectName.trim();
|
|
1398
|
+
if (!projectName) throw projectSetupNameRequiredError("app deploy --create-project");
|
|
1399
|
+
return withRemoteDeployBranch(provider, {
|
|
1400
|
+
workspace,
|
|
1401
|
+
project: toProjectSummary(await createProjectForDeploySetup(provider, projectName, workspace, context.runtime.signal)),
|
|
1402
|
+
resolution: {
|
|
1403
|
+
projectSource: "created",
|
|
1404
|
+
targetName: projectName,
|
|
1405
|
+
targetNameSource: "explicit"
|
|
1406
|
+
},
|
|
1407
|
+
localPinAction: "created"
|
|
1408
|
+
}, branch, context.runtime.signal);
|
|
1409
|
+
}
|
|
1343
1410
|
if (options.envProjectId) {
|
|
1344
1411
|
const project = projects.find((candidate) => candidate.id === options.envProjectId);
|
|
1345
1412
|
if (!project) throw projectNotFoundError(options.envProjectId, workspace);
|
|
1346
|
-
return
|
|
1413
|
+
return withRemoteDeployBranch(provider, {
|
|
1347
1414
|
workspace,
|
|
1348
1415
|
project: toProjectSummary(project),
|
|
1349
1416
|
resolution: {
|
|
@@ -1351,14 +1418,14 @@ async function resolveDeployProjectContext(context, client, provider, explicitPr
|
|
|
1351
1418
|
targetName: options.envProjectId,
|
|
1352
1419
|
targetNameSource: "env"
|
|
1353
1420
|
}
|
|
1354
|
-
}, branch);
|
|
1421
|
+
}, branch, context.runtime.signal);
|
|
1355
1422
|
}
|
|
1356
1423
|
const localPin = options.localPin;
|
|
1357
1424
|
if (localPin.kind === "present") {
|
|
1358
1425
|
if (localPin.pin.workspaceId !== workspace.id) throw localResolutionPinStaleError();
|
|
1359
1426
|
const project = projects.find((candidate) => candidate.id === localPin.pin.projectId);
|
|
1360
1427
|
if (!project) throw localResolutionPinStaleError();
|
|
1361
|
-
return
|
|
1428
|
+
return withRemoteDeployBranch(provider, {
|
|
1362
1429
|
workspace,
|
|
1363
1430
|
project: toProjectSummary(project),
|
|
1364
1431
|
resolution: {
|
|
@@ -1366,42 +1433,123 @@ async function resolveDeployProjectContext(context, client, provider, explicitPr
|
|
|
1366
1433
|
targetName: project.name,
|
|
1367
1434
|
targetNameSource: "local-pin"
|
|
1368
1435
|
}
|
|
1369
|
-
}, branch);
|
|
1436
|
+
}, branch, context.runtime.signal);
|
|
1370
1437
|
}
|
|
1371
|
-
|
|
1438
|
+
const platformMapping = await resolveDurablePlatformMapping();
|
|
1439
|
+
if (platformMapping && platformMapping.workspace.id === workspace.id) return withRemoteDeployBranch(provider, {
|
|
1440
|
+
workspace,
|
|
1441
|
+
project: toProjectSummary(platformMapping),
|
|
1442
|
+
resolution: {
|
|
1443
|
+
projectSource: "platform-mapping",
|
|
1444
|
+
targetName: platformMapping.name,
|
|
1445
|
+
targetNameSource: "platform-mapping"
|
|
1446
|
+
}
|
|
1447
|
+
}, branch, context.runtime.signal);
|
|
1448
|
+
if (canPrompt(context) && !context.flags.yes) return withRemoteDeployBranch(provider, await resolveInteractiveDeployProjectSetup(context, provider, workspace, projects), branch, context.runtime.signal);
|
|
1449
|
+
throw projectSetupRequiredError(projects, await inferTargetName(context.runtime.cwd, context.runtime.signal));
|
|
1450
|
+
}
|
|
1451
|
+
async function resolveInteractiveDeployProjectSetup(context, provider, workspace, projects) {
|
|
1452
|
+
const setup = await promptForProjectSetupChoice({
|
|
1372
1453
|
context,
|
|
1454
|
+
projects,
|
|
1455
|
+
createProject: (projectName) => createProjectForDeploySetup(provider, projectName, workspace, context.runtime.signal),
|
|
1456
|
+
cancel: {
|
|
1457
|
+
why: "Deploy needs a Project before it can continue.",
|
|
1458
|
+
fix: "Choose an existing Project or create a new one, then rerun deploy.",
|
|
1459
|
+
nextSteps: ["prisma-cli app deploy --project <id-or-name>", "prisma-cli app deploy --create-project <name>"]
|
|
1460
|
+
}
|
|
1461
|
+
});
|
|
1462
|
+
return {
|
|
1373
1463
|
workspace,
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1464
|
+
project: setup.project,
|
|
1465
|
+
resolution: {
|
|
1466
|
+
projectSource: setup.action === "created" ? "created" : "prompt",
|
|
1467
|
+
targetName: setup.targetName,
|
|
1468
|
+
targetNameSource: setup.targetNameSource
|
|
1469
|
+
},
|
|
1470
|
+
localPinAction: setup.action
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
async function createProjectForDeploySetup(provider, projectName, workspace, signal) {
|
|
1474
|
+
const created = await provider.createProject({
|
|
1475
|
+
name: projectName,
|
|
1476
|
+
signal
|
|
1477
|
+
}).catch((error) => {
|
|
1478
|
+
throw projectCreateFailedError(error, projectName, workspace, {
|
|
1479
|
+
nextSteps: [
|
|
1480
|
+
"prisma-cli project list",
|
|
1481
|
+
"prisma-cli app deploy --project <id-or-name>",
|
|
1482
|
+
`prisma-cli app deploy --create-project ${formatCommandArgument(projectName)}`
|
|
1483
|
+
],
|
|
1484
|
+
permissionFix: "Choose an existing Project with --project, or grant the token permission to create Projects in this workspace.",
|
|
1485
|
+
fallbackFix: "Choose an existing Project with --project, or retry after addressing the platform error above."
|
|
1486
|
+
});
|
|
1487
|
+
});
|
|
1488
|
+
return {
|
|
1489
|
+
id: created.id,
|
|
1490
|
+
name: created.name,
|
|
1491
|
+
workspace
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
async function withRemoteDeployBranch(provider, target, branch, signal) {
|
|
1495
|
+
const remoteBranch = await provider.resolveBranch(target.project.id, {
|
|
1496
|
+
branchName: branch.name,
|
|
1497
|
+
signal
|
|
1498
|
+
});
|
|
1382
1499
|
return {
|
|
1383
1500
|
...target,
|
|
1384
1501
|
branch: {
|
|
1385
|
-
|
|
1386
|
-
|
|
1502
|
+
id: remoteBranch.id,
|
|
1503
|
+
name: remoteBranch.name,
|
|
1504
|
+
kind: remoteBranch.role
|
|
1387
1505
|
}
|
|
1388
1506
|
};
|
|
1389
1507
|
}
|
|
1390
|
-
function
|
|
1508
|
+
function toBranchKind(name) {
|
|
1509
|
+
return name === "production" || name === "main" ? "production" : "preview";
|
|
1510
|
+
}
|
|
1511
|
+
function toResultBranch(branch) {
|
|
1391
1512
|
return {
|
|
1392
|
-
id:
|
|
1393
|
-
name:
|
|
1513
|
+
id: branch.id,
|
|
1514
|
+
name: branch.name,
|
|
1515
|
+
kind: branch.kind
|
|
1394
1516
|
};
|
|
1395
1517
|
}
|
|
1396
|
-
function
|
|
1397
|
-
return
|
|
1518
|
+
function toAppVerboseContext(target) {
|
|
1519
|
+
return {
|
|
1520
|
+
workspace: target.workspace,
|
|
1521
|
+
project: target.project,
|
|
1522
|
+
branch: target.branch,
|
|
1523
|
+
resolution: target.resolution
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
function toBranchDatabaseDeployBranch(branch) {
|
|
1527
|
+
if (!branch.id) throw new Error(`Deploy branch "${branch.name}" was not resolved remotely.`);
|
|
1528
|
+
return {
|
|
1529
|
+
id: branch.id,
|
|
1530
|
+
name: branch.name,
|
|
1531
|
+
kind: branch.kind
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
function assertExclusiveDeployProjectInputs(options) {
|
|
1535
|
+
const provided = [
|
|
1536
|
+
options.projectRef ? "--project" : null,
|
|
1537
|
+
options.createProjectName ? "--create-project" : null,
|
|
1538
|
+
options.envProjectId ? PRISMA_PROJECT_ID_ENV_VAR : null
|
|
1539
|
+
].filter((value) => Boolean(value));
|
|
1540
|
+
if (provided.length <= 1) return;
|
|
1541
|
+
throw usageError("Project selection is ambiguous", `${provided.join(", ")} cannot be used together.`, "Choose exactly one Project source for this deploy.", [
|
|
1542
|
+
"prisma-cli app deploy --project <id-or-name>",
|
|
1543
|
+
"prisma-cli app deploy --create-project <name>",
|
|
1544
|
+
`unset ${PRISMA_PROJECT_ID_ENV_VAR}`
|
|
1545
|
+
], "project");
|
|
1398
1546
|
}
|
|
1399
1547
|
async function resolveDeployBranch(context, explicitBranchName) {
|
|
1400
1548
|
if (explicitBranchName) return {
|
|
1401
1549
|
name: explicitBranchName,
|
|
1402
1550
|
annotation: "set by --branch"
|
|
1403
1551
|
};
|
|
1404
|
-
const gitBranch = await readLocalGitBranch(context.runtime.cwd);
|
|
1552
|
+
const gitBranch = await readLocalGitBranch(context.runtime.cwd, context.runtime.signal);
|
|
1405
1553
|
if (gitBranch) return {
|
|
1406
1554
|
name: gitBranch,
|
|
1407
1555
|
annotation: "from local Git branch"
|
|
@@ -1411,41 +1559,15 @@ async function resolveDeployBranch(context, explicitBranchName) {
|
|
|
1411
1559
|
annotation: "default"
|
|
1412
1560
|
};
|
|
1413
1561
|
}
|
|
1414
|
-
async function readLocalGitBranch(cwd) {
|
|
1415
|
-
const headPath = await resolveGitHeadPath(path.join(cwd, ".git"));
|
|
1416
|
-
if (!headPath) return null;
|
|
1417
|
-
try {
|
|
1418
|
-
const head = (await readFile(headPath, "utf8")).trim();
|
|
1419
|
-
if (head.startsWith("ref: refs/heads/")) return head.slice(16);
|
|
1420
|
-
} catch {
|
|
1421
|
-
return null;
|
|
1422
|
-
}
|
|
1423
|
-
return null;
|
|
1424
|
-
}
|
|
1425
|
-
async function resolveGitHeadPath(gitPath) {
|
|
1426
|
-
try {
|
|
1427
|
-
const raw = await readFile(gitPath, "utf8");
|
|
1428
|
-
if (raw.startsWith("gitdir:")) return path.join(path.resolve(path.dirname(gitPath), raw.slice(7).trim()), "HEAD");
|
|
1429
|
-
} catch {}
|
|
1430
|
-
try {
|
|
1431
|
-
await access(path.join(gitPath, "HEAD"));
|
|
1432
|
-
return path.join(gitPath, "HEAD");
|
|
1433
|
-
} catch {
|
|
1434
|
-
return null;
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
1562
|
async function resolveDeployFramework(context, options) {
|
|
1438
1563
|
if (options.requestedFramework) return frameworkFromUserFacingValue(options.requestedFramework, "set by --framework");
|
|
1439
|
-
if (options.
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
};
|
|
1447
|
-
}
|
|
1448
|
-
const detected = await detectDeployFramework(context.runtime.cwd);
|
|
1564
|
+
if (options.entrypoint) return {
|
|
1565
|
+
key: "bun",
|
|
1566
|
+
buildType: "bun",
|
|
1567
|
+
displayName: "Bun",
|
|
1568
|
+
annotation: "set by --entry"
|
|
1569
|
+
};
|
|
1570
|
+
const detected = await detectDeployFramework(context.runtime.cwd, context.runtime.signal);
|
|
1449
1571
|
if (detected) return detected;
|
|
1450
1572
|
throw frameworkNotDetectedError(context.runtime.cwd);
|
|
1451
1573
|
}
|
|
@@ -1459,9 +1581,30 @@ function resolveDeployRuntime(requestedHttpPort, framework) {
|
|
|
1459
1581
|
annotation: `${framework.displayName} default`
|
|
1460
1582
|
};
|
|
1461
1583
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1584
|
+
function assertSupportedEntrypointForRequestedDeployShape(options) {
|
|
1585
|
+
if (!options.requestedFramework) return;
|
|
1586
|
+
assertSupportedEntrypoint(frameworkFromUserFacingValue(options.requestedFramework, "set by --framework").buildType, options.entrypoint, "deploy");
|
|
1587
|
+
}
|
|
1588
|
+
async function resolveDeployEntrypoint(cwd, framework, explicitEntrypoint, signal) {
|
|
1589
|
+
if (explicitEntrypoint || framework.buildType !== "bun") return explicitEntrypoint;
|
|
1590
|
+
const packageEntrypoint = readBunPackageEntrypoint(await readBunPackageJson(cwd, signal));
|
|
1591
|
+
if (packageEntrypoint) return packageEntrypoint;
|
|
1592
|
+
if (framework.key !== "hono") return;
|
|
1593
|
+
const defaultEntrypoint = "src/index.ts";
|
|
1594
|
+
signal.throwIfAborted();
|
|
1595
|
+
try {
|
|
1596
|
+
await access(path.join(cwd, defaultEntrypoint));
|
|
1597
|
+
signal.throwIfAborted();
|
|
1598
|
+
return defaultEntrypoint;
|
|
1599
|
+
} catch (error) {
|
|
1600
|
+
if (signal.aborted) throw error;
|
|
1601
|
+
if (error.code !== "ENOENT") throw error;
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
async function detectDeployFramework(cwd, signal) {
|
|
1606
|
+
const packageJson = await readBunPackageJson(cwd, signal);
|
|
1607
|
+
const nextConfig = await detectNextConfig(cwd, signal);
|
|
1465
1608
|
if (nextConfig.exists || hasPackageDependency(packageJson, "next")) return {
|
|
1466
1609
|
key: "nextjs",
|
|
1467
1610
|
buildType: "nextjs",
|
|
@@ -1474,7 +1617,7 @@ async function detectDeployFramework(cwd) {
|
|
|
1474
1617
|
displayName: "Hono",
|
|
1475
1618
|
annotation: "detected from package.json"
|
|
1476
1619
|
};
|
|
1477
|
-
if (
|
|
1620
|
+
if (hasAnyPackageDependency(packageJson, TANSTACK_START_PACKAGES)) return {
|
|
1478
1621
|
key: "tanstack-start",
|
|
1479
1622
|
buildType: "tanstack-start",
|
|
1480
1623
|
displayName: "TanStack Start",
|
|
@@ -1482,21 +1625,26 @@ async function detectDeployFramework(cwd) {
|
|
|
1482
1625
|
};
|
|
1483
1626
|
return null;
|
|
1484
1627
|
}
|
|
1485
|
-
async function detectNextConfig(cwd) {
|
|
1628
|
+
async function detectNextConfig(cwd, signal) {
|
|
1486
1629
|
for (const candidate of [
|
|
1487
1630
|
"next.config.js",
|
|
1488
1631
|
"next.config.mjs",
|
|
1489
|
-
"next.config.
|
|
1490
|
-
"next.config.
|
|
1632
|
+
"next.config.ts",
|
|
1633
|
+
"next.config.mts"
|
|
1491
1634
|
]) {
|
|
1492
1635
|
const filePath = path.join(cwd, candidate);
|
|
1636
|
+
signal.throwIfAborted();
|
|
1493
1637
|
try {
|
|
1494
|
-
const content = await readFile(filePath,
|
|
1638
|
+
const content = await readFile(filePath, {
|
|
1639
|
+
encoding: "utf8",
|
|
1640
|
+
signal
|
|
1641
|
+
});
|
|
1495
1642
|
return {
|
|
1496
1643
|
exists: true,
|
|
1497
1644
|
standalone: /\boutput\s*:\s*["'`]standalone["'`]/.test(content)
|
|
1498
1645
|
};
|
|
1499
1646
|
} catch (error) {
|
|
1647
|
+
if (signal.aborted) throw error;
|
|
1500
1648
|
if (error.code !== "ENOENT") throw error;
|
|
1501
1649
|
}
|
|
1502
1650
|
}
|
|
@@ -1508,6 +1656,9 @@ async function detectNextConfig(cwd) {
|
|
|
1508
1656
|
function hasPackageDependency(packageJson, dependencyName) {
|
|
1509
1657
|
return hasDependency(packageJson?.dependencies, dependencyName) || hasDependency(packageJson?.devDependencies, dependencyName);
|
|
1510
1658
|
}
|
|
1659
|
+
function hasAnyPackageDependency(packageJson, dependencyNames) {
|
|
1660
|
+
return dependencyNames.some((dependencyName) => hasPackageDependency(packageJson, dependencyName));
|
|
1661
|
+
}
|
|
1511
1662
|
function hasDependency(dependencies, dependencyName) {
|
|
1512
1663
|
return Boolean(dependencies && typeof dependencies === "object" && dependencyName in dependencies);
|
|
1513
1664
|
}
|
|
@@ -1527,9 +1678,16 @@ function frameworkFromUserFacingValue(value, annotation) {
|
|
|
1527
1678
|
displayName: "Hono",
|
|
1528
1679
|
annotation
|
|
1529
1680
|
};
|
|
1681
|
+
case "bun": return {
|
|
1682
|
+
key: "bun",
|
|
1683
|
+
buildType: "bun",
|
|
1684
|
+
displayName: "Bun",
|
|
1685
|
+
annotation
|
|
1686
|
+
};
|
|
1530
1687
|
case "tanstack":
|
|
1531
1688
|
case "tanstack-start":
|
|
1532
|
-
case "@tanstack/start":
|
|
1689
|
+
case "@tanstack/react-start":
|
|
1690
|
+
case "@tanstack/solid-start": return {
|
|
1533
1691
|
key: "tanstack-start",
|
|
1534
1692
|
buildType: "tanstack-start",
|
|
1535
1693
|
displayName: "TanStack Start",
|
|
@@ -1539,82 +1697,61 @@ function frameworkFromUserFacingValue(value, annotation) {
|
|
|
1539
1697
|
}
|
|
1540
1698
|
}
|
|
1541
1699
|
function frameworkNotDetectedError(cwd, requestedFramework) {
|
|
1542
|
-
const supported = "Next.js, Hono, TanStack Start";
|
|
1700
|
+
const supported = "Next.js, Hono, TanStack Start, Bun";
|
|
1543
1701
|
const directory = cwd ? ` in ${formatDeployDirectory(cwd)}` : "";
|
|
1544
1702
|
return new CliError({
|
|
1545
1703
|
code: "FRAMEWORK_NOT_DETECTED",
|
|
1546
1704
|
domain: "app",
|
|
1547
1705
|
summary: requestedFramework ? `Unsupported framework "${requestedFramework}"` : `Cannot detect a supported framework${directory}`,
|
|
1548
1706
|
why: `Supported Beta frameworks: ${supported}.`,
|
|
1549
|
-
fix: "Add one of these frameworks as a dependency,
|
|
1707
|
+
fix: "Add one of these frameworks as a dependency, pass --framework <nextjs|hono|tanstack-start|bun>, or pass --entry <path> for a Bun app.",
|
|
1550
1708
|
exitCode: 2,
|
|
1551
1709
|
nextSteps: [
|
|
1552
1710
|
"prisma-cli app deploy --framework nextjs",
|
|
1553
1711
|
"prisma-cli app deploy --framework hono",
|
|
1554
|
-
"prisma-cli app deploy --framework tanstack-start"
|
|
1712
|
+
"prisma-cli app deploy --framework tanstack-start",
|
|
1713
|
+
"prisma-cli app deploy --framework bun --entry server.ts",
|
|
1714
|
+
"prisma-cli app deploy --entry server.ts"
|
|
1555
1715
|
]
|
|
1556
1716
|
});
|
|
1557
1717
|
}
|
|
1558
1718
|
async function maybeRenderDeploySetupBlock(context, details) {
|
|
1559
1719
|
if (context.flags.json || context.flags.quiet) return;
|
|
1560
1720
|
const directory = formatDeployDirectory(context.runtime.cwd);
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
return;
|
|
1564
|
-
}
|
|
1565
|
-
const title = `Setting up your local directory ${formatLocalDirectory(context.runtime.cwd, context.runtime.env)}`;
|
|
1566
|
-
const rows = details.firstDeploy ? [
|
|
1567
|
-
{
|
|
1568
|
-
label: "Workspace",
|
|
1569
|
-
value: details.workspaceName
|
|
1570
|
-
},
|
|
1571
|
-
{
|
|
1572
|
-
label: "Project",
|
|
1573
|
-
value: details.projectName,
|
|
1574
|
-
origin: details.projectAnnotation
|
|
1575
|
-
},
|
|
1576
|
-
{
|
|
1577
|
-
label: "Branch",
|
|
1578
|
-
value: details.branchName,
|
|
1579
|
-
origin: details.branchAnnotation
|
|
1580
|
-
},
|
|
1581
|
-
{
|
|
1582
|
-
label: "App",
|
|
1583
|
-
value: details.appName,
|
|
1584
|
-
origin: details.appAnnotation
|
|
1585
|
-
},
|
|
1586
|
-
{
|
|
1587
|
-
label: "Framework",
|
|
1588
|
-
value: details.framework.displayName,
|
|
1589
|
-
origin: details.framework.annotation
|
|
1590
|
-
},
|
|
1591
|
-
{
|
|
1592
|
-
label: "Runtime",
|
|
1593
|
-
value: `HTTP ${details.runtime.port}`,
|
|
1594
|
-
origin: details.runtime.annotation
|
|
1595
|
-
}
|
|
1596
|
-
] : [];
|
|
1597
|
-
const lines = [
|
|
1598
|
-
title,
|
|
1599
|
-
"",
|
|
1600
|
-
...renderDeployOutputRows(context.ui, rows),
|
|
1601
|
-
""
|
|
1602
|
-
];
|
|
1603
|
-
context.output.stderr.write(`${lines.join("\n")}\n`);
|
|
1721
|
+
const prefix = details.includeDirectory ? `Deploying ${directory} to` : "Deploying to";
|
|
1722
|
+
context.output.stderr.write(`${prefix} ${details.projectName} / ${details.branchName} / ${details.appName}\n\n`);
|
|
1604
1723
|
}
|
|
1605
|
-
function
|
|
1724
|
+
function maybeRenderDeployBuildSettings(context, resolution) {
|
|
1725
|
+
if (context.flags.json || context.flags.quiet) return;
|
|
1726
|
+
const settings = resolution.settings;
|
|
1727
|
+
const title = resolution.status === "created" ? `Created ${resolution.relativeConfigPath}` : `Using ${resolution.relativeConfigPath}`;
|
|
1728
|
+
context.output.stderr.write(`${title}\n${renderDeployOutputRows(context.ui, [{
|
|
1729
|
+
label: "Build Command",
|
|
1730
|
+
value: settings.buildCommand ?? "none",
|
|
1731
|
+
origin: settings.buildCommandSource ?? void 0
|
|
1732
|
+
}, {
|
|
1733
|
+
label: "Output Directory",
|
|
1734
|
+
value: settings.outputDirectory,
|
|
1735
|
+
origin: settings.outputDirectorySource ?? void 0
|
|
1736
|
+
}]).join("\n")}\n\n`);
|
|
1737
|
+
}
|
|
1738
|
+
function maybeRenderProjectLinked(context, directory, projectName, localPinPath) {
|
|
1606
1739
|
if (context.flags.json || context.flags.quiet) return;
|
|
1607
|
-
context.output.stderr.write(
|
|
1740
|
+
context.output.stderr.write(`${context.ui.success("✔")} Linked "${directory}" to Project "${projectName}"\nSaved ${localPinPath}\n\n`);
|
|
1608
1741
|
}
|
|
1609
1742
|
async function maybeCustomizeDeploySettings(context, options) {
|
|
1610
|
-
if (!options.firstDeploy || context.flags.yes || options.explicitFramework || options.
|
|
1743
|
+
if (!options.firstDeploy || context.flags.yes || options.explicitFramework || options.explicitEntrypoint || options.explicitHttpPort || !canPrompt(context)) return {
|
|
1611
1744
|
framework: options.framework,
|
|
1612
1745
|
runtime: options.runtime
|
|
1613
1746
|
};
|
|
1747
|
+
maybeRenderDeploySettingsPreview(context, {
|
|
1748
|
+
framework: options.framework,
|
|
1749
|
+
runtime: options.runtime
|
|
1750
|
+
});
|
|
1614
1751
|
if (!await confirmPrompt({
|
|
1615
1752
|
input: context.runtime.stdin,
|
|
1616
1753
|
output: context.runtime.stderr,
|
|
1617
|
-
message: "Customize settings?",
|
|
1754
|
+
message: "Customize build settings?",
|
|
1618
1755
|
initialValue: false
|
|
1619
1756
|
})) return {
|
|
1620
1757
|
framework: options.framework,
|
|
@@ -1659,24 +1796,22 @@ async function maybeCustomizeDeploySettings(context, options) {
|
|
|
1659
1796
|
runtime
|
|
1660
1797
|
};
|
|
1661
1798
|
}
|
|
1662
|
-
function
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
case "remembered-local": return "linked to existing project";
|
|
1672
|
-
case "prompt": return "selected by you";
|
|
1673
|
-
}
|
|
1799
|
+
function maybeRenderDeploySettingsPreview(context, options) {
|
|
1800
|
+
if (context.flags.quiet || context.flags.json) return;
|
|
1801
|
+
context.output.stderr.write(`Detected ${options.framework.displayName}\n${renderDeploySettingsPreview(context.ui, [{
|
|
1802
|
+
key: "framework",
|
|
1803
|
+
value: options.framework.displayName
|
|
1804
|
+
}, {
|
|
1805
|
+
key: "runtime",
|
|
1806
|
+
value: `HTTP ${options.runtime.port}`
|
|
1807
|
+
}]).join("\n")}\n\n`);
|
|
1674
1808
|
}
|
|
1675
1809
|
function frameworkDisplayName(framework) {
|
|
1676
1810
|
switch (framework) {
|
|
1677
1811
|
case "nextjs": return "Next.js";
|
|
1678
1812
|
case "hono": return "Hono";
|
|
1679
1813
|
case "tanstack-start": return "TanStack Start";
|
|
1814
|
+
case "bun": return "Bun";
|
|
1680
1815
|
}
|
|
1681
1816
|
}
|
|
1682
1817
|
function validateDeployHttpPortText(value) {
|
|
@@ -1692,19 +1827,10 @@ function formatDeployDirectory(cwd) {
|
|
|
1692
1827
|
const basename = path.basename(cwd);
|
|
1693
1828
|
return basename ? `./${basename}` : ".";
|
|
1694
1829
|
}
|
|
1695
|
-
function formatLocalDirectory(cwd, env) {
|
|
1696
|
-
const resolved = path.resolve(cwd);
|
|
1697
|
-
const home = env.HOME ? path.resolve(env.HOME) : null;
|
|
1698
|
-
if (home && (resolved === home || resolved.startsWith(`${home}${path.sep}`))) {
|
|
1699
|
-
const relative = path.relative(home, resolved);
|
|
1700
|
-
return relative ? `~/${relative}` : "~";
|
|
1701
|
-
}
|
|
1702
|
-
return resolved;
|
|
1703
|
-
}
|
|
1704
1830
|
async function readCurrentWorkspaceId(context) {
|
|
1705
1831
|
const state = await context.stateStore.read();
|
|
1706
1832
|
if (state.auth?.workspaceId) return state.auth.workspaceId;
|
|
1707
|
-
return (await readAuthState(context.runtime.env)).workspace?.id ?? null;
|
|
1833
|
+
return (await readAuthState(context.runtime.env, context.runtime.signal)).workspace?.id ?? null;
|
|
1708
1834
|
}
|
|
1709
1835
|
function normalizeBuildType(requestedBuildType) {
|
|
1710
1836
|
if (!requestedBuildType) return "auto";
|
|
@@ -1720,10 +1846,13 @@ function getBuildTypeExamples(commandName) {
|
|
|
1720
1846
|
});
|
|
1721
1847
|
}
|
|
1722
1848
|
function assertSupportedEntrypoint(buildType, entrypoint, commandName) {
|
|
1723
|
-
if (buildType !== "auto" && buildType !== "bun" && entrypoint)
|
|
1849
|
+
if (buildType !== "auto" && buildType !== "bun" && entrypoint) {
|
|
1850
|
+
if (commandName === "deploy") throw usageError(`App deploy does not accept --entry with ${formatBuildTypeName(buildType)}`, `${formatBuildTypeName(buildType)} apps derive their runtime entrypoint from build output.`, "Remove --entry, or use --framework bun when you want to target a Bun entrypoint directly.", [`prisma-cli app deploy --framework ${buildType}`, "prisma-cli app deploy --framework bun --entry server.ts"], "app");
|
|
1851
|
+
throw usageError(`App ${commandName} does not accept --entry with --build-type ${buildType}`, `${formatBuildTypeName(buildType)} apps do not use an entrypoint flag in the current preview.`, `Remove --entry, or rerun prisma-cli app ${commandName} with --build-type bun when you want to target a Bun entrypoint directly.`, [`prisma-cli app ${commandName} --build-type ${buildType}`, `prisma-cli app ${commandName} --build-type bun --entry server.ts`], "app");
|
|
1852
|
+
}
|
|
1724
1853
|
}
|
|
1725
1854
|
async function requireLocalBuildType(context, buildType, commandName) {
|
|
1726
|
-
const resolvedBuildType = await resolveLocalBuildType(context.runtime.cwd, buildType);
|
|
1855
|
+
const resolvedBuildType = await resolveLocalBuildType(context.runtime.cwd, buildType, context.runtime.signal);
|
|
1727
1856
|
if (resolvedBuildType) return resolvedBuildType;
|
|
1728
1857
|
throw usageError(`App ${commandName} requires an explicit framework when detection is ambiguous`, "This preview only starts local dev servers for clear Next.js or Bun project shapes.", "Pass --build-type nextjs for a Next.js app, or pass --build-type bun with --entry <path> for a Bun app.", [`prisma-cli app ${commandName} --build-type nextjs`, `prisma-cli app ${commandName} --build-type bun --entry server.ts`], "app");
|
|
1729
1858
|
}
|
|
@@ -1761,24 +1890,41 @@ function deployFailedError(summary, error, nextSteps) {
|
|
|
1761
1890
|
function appDeployFailedError(error, progress) {
|
|
1762
1891
|
const why = error instanceof Error ? error.message : String(error);
|
|
1763
1892
|
const debug = formatDebugDetails(error);
|
|
1764
|
-
if (progress.buildStarted && !progress.buildCompleted)
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
"",
|
|
1775
|
-
|
|
1776
|
-
"",
|
|
1777
|
-
|
|
1778
|
-
]
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1893
|
+
if (progress.buildStarted && !progress.buildCompleted) {
|
|
1894
|
+
const standaloneOutputFailure = isNextStandaloneOutputFailure(why);
|
|
1895
|
+
const fix = standaloneOutputFailure ? "Add output: \"standalone\" to next.config.*, then rerun deploy." : "Inspect the build output above, fix the error, and redeploy.";
|
|
1896
|
+
const nextSteps = standaloneOutputFailure ? ["Add output: \"standalone\" to next.config.*, then rerun prisma-cli app deploy"] : [];
|
|
1897
|
+
const nextActions = standaloneOutputFailure ? [{
|
|
1898
|
+
kind: "edit-file",
|
|
1899
|
+
journey: "deploy-app",
|
|
1900
|
+
label: "Add Next.js standalone output",
|
|
1901
|
+
reason: "Prisma Compute needs Next.js standalone output to build a deployable server artifact."
|
|
1902
|
+
}, {
|
|
1903
|
+
kind: "run-command",
|
|
1904
|
+
journey: "deploy-app",
|
|
1905
|
+
label: "Rerun deploy",
|
|
1906
|
+
command: "prisma-cli app deploy"
|
|
1907
|
+
}] : [];
|
|
1908
|
+
return new CliError({
|
|
1909
|
+
code: "BUILD_FAILED",
|
|
1910
|
+
domain: "app",
|
|
1911
|
+
summary: "Build failed locally.",
|
|
1912
|
+
why,
|
|
1913
|
+
fix,
|
|
1914
|
+
debug,
|
|
1915
|
+
meta: { phase: "build" },
|
|
1916
|
+
humanLines: [
|
|
1917
|
+
"Build failed locally.",
|
|
1918
|
+
"",
|
|
1919
|
+
`✗ Built ${why}`,
|
|
1920
|
+
"",
|
|
1921
|
+
`Fix: ${fix}`
|
|
1922
|
+
],
|
|
1923
|
+
exitCode: 1,
|
|
1924
|
+
nextSteps,
|
|
1925
|
+
nextActions
|
|
1926
|
+
});
|
|
1927
|
+
}
|
|
1782
1928
|
if (!progress.buildStarted) return deployFailedError("App deploy failed", error, ["prisma-cli app deploy"]);
|
|
1783
1929
|
const phaseHeadline = progress.containerLive ? "The deployment started, but the app is not ready yet." : "Deploy failed after the build completed.";
|
|
1784
1930
|
const recoveryLines = progress.versionId ? ["See what happened", `prisma-cli app logs --deployment ${progress.versionId}`] : ["Fix", "Retry the command, or rerun with --trace for more detailed diagnostics."];
|
|
@@ -1825,61 +1971,64 @@ function localResolutionPinStaleError() {
|
|
|
1825
1971
|
domain: "project",
|
|
1826
1972
|
summary: "Local project binding is stale",
|
|
1827
1973
|
why: `The target recorded in ${LOCAL_RESOLUTION_PIN_RELATIVE_PATH} is no longer available in the selected workspace.`,
|
|
1828
|
-
fix: `Delete ${LOCAL_RESOLUTION_PIN_RELATIVE_PATH}
|
|
1974
|
+
fix: `Delete ${LOCAL_RESOLUTION_PIN_RELATIVE_PATH}, then choose a Project explicitly.`,
|
|
1829
1975
|
meta: { pinPath: LOCAL_RESOLUTION_PIN_RELATIVE_PATH },
|
|
1830
1976
|
exitCode: 1,
|
|
1831
|
-
nextSteps: [
|
|
1977
|
+
nextSteps: [
|
|
1978
|
+
"prisma-cli project list",
|
|
1979
|
+
"prisma-cli project link <id-or-name>",
|
|
1980
|
+
"prisma-cli app deploy --project <id-or-name>"
|
|
1981
|
+
]
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
function localPinReadErrorToDeployError(error) {
|
|
1985
|
+
return matchError(error, {
|
|
1986
|
+
LocalResolutionPinInvalidJsonError: () => localResolutionPinStaleError(),
|
|
1987
|
+
LocalResolutionPinInvalidShapeError: () => localResolutionPinStaleError(),
|
|
1988
|
+
LocalResolutionPinReadAbortedError: (error) => {
|
|
1989
|
+
throw error;
|
|
1990
|
+
},
|
|
1991
|
+
UnhandledException: (error) => {
|
|
1992
|
+
throw error;
|
|
1993
|
+
}
|
|
1832
1994
|
});
|
|
1833
1995
|
}
|
|
1834
1996
|
function readDeployEnvOverride(context, name) {
|
|
1835
1997
|
const value = context.runtime.env[name]?.trim();
|
|
1836
1998
|
return value ? value : void 0;
|
|
1837
1999
|
}
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
* existing project matches the package.json name (or the cwd basename as a
|
|
1841
|
-
* fallback). When the create call fails the user often doesn't realise the
|
|
1842
|
-
* CLI was attempting to create a project at all — they thought the deploy
|
|
1843
|
-
* would find an existing project. Surface that context, and recommend the
|
|
1844
|
-
* explicit `--project` flag as the unambiguous way out.
|
|
1845
|
-
*/
|
|
1846
|
-
function createProjectOnFirstDeployError(options) {
|
|
1847
|
-
const { error, inferredName, workspaceName } = options;
|
|
1848
|
-
const status = extractHttpStatus(error);
|
|
1849
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1850
|
-
const inferredContext = `No existing project matched the package.json name \`${inferredName}\`, so the CLI attempted to create one.`;
|
|
1851
|
-
const nextSteps = ["prisma-cli project list", "prisma-cli app deploy --project <id-or-name>"];
|
|
1852
|
-
if (status === 401 || status === 403) return new CliError({
|
|
1853
|
-
code: "AUTH_FORBIDDEN",
|
|
1854
|
-
domain: "auth",
|
|
1855
|
-
summary: "Could not create a new project for this deploy",
|
|
1856
|
-
why: `${inferredContext} The platform rejected the create (HTTP ${status}).`,
|
|
1857
|
-
fix: `Pass --project <id-or-name> to deploy into an existing project, or grant the service token project-create permission on workspace \`${workspaceName}\`.`,
|
|
1858
|
-
debug: formatDebugDetails(error),
|
|
1859
|
-
exitCode: 1,
|
|
1860
|
-
nextSteps
|
|
1861
|
-
});
|
|
2000
|
+
function projectSetupRequiredError(projects, suggestedName) {
|
|
2001
|
+
const createCommand = `prisma-cli app deploy --create-project ${formatCommandArgument(suggestedName.name)}`;
|
|
1862
2002
|
return new CliError({
|
|
1863
|
-
code: "
|
|
1864
|
-
domain: "
|
|
1865
|
-
summary: "
|
|
1866
|
-
why:
|
|
1867
|
-
fix: "
|
|
1868
|
-
|
|
2003
|
+
code: "PROJECT_SETUP_REQUIRED",
|
|
2004
|
+
domain: "project",
|
|
2005
|
+
summary: "Choose a Project before deploying this directory",
|
|
2006
|
+
why: "This directory is not linked to a Prisma Project, and deploy will not choose or create one implicitly.",
|
|
2007
|
+
fix: "Choose an existing Project with --project, create one with --create-project, or rerun interactively to pick from the setup list.",
|
|
2008
|
+
meta: {
|
|
2009
|
+
candidates: sortProjects(projects).map((project) => ({
|
|
2010
|
+
id: project.id,
|
|
2011
|
+
name: project.name
|
|
2012
|
+
})),
|
|
2013
|
+
suggestedProjectName: suggestedName.name,
|
|
2014
|
+
suggestedProjectNameSource: suggestedName.source,
|
|
2015
|
+
recoveryCommands: ["prisma-cli app deploy --project <id-or-name>", createCommand]
|
|
2016
|
+
},
|
|
1869
2017
|
exitCode: 1,
|
|
1870
|
-
nextSteps
|
|
2018
|
+
nextSteps: [
|
|
2019
|
+
"prisma-cli project list",
|
|
2020
|
+
"prisma-cli app deploy --project <id-or-name>",
|
|
2021
|
+
createCommand
|
|
2022
|
+
],
|
|
2023
|
+
nextActions: buildProjectSetupNextActions({
|
|
2024
|
+
commandName: "app deploy",
|
|
2025
|
+
createCommand,
|
|
2026
|
+
reason: "This directory is not linked to a Prisma Project. Ask the user which Project to use before deploying; package and directory names are setup suggestions only."
|
|
2027
|
+
})
|
|
1871
2028
|
});
|
|
1872
2029
|
}
|
|
1873
|
-
function
|
|
1874
|
-
|
|
1875
|
-
const candidate = error;
|
|
1876
|
-
if (typeof candidate.statusCode === "number") return candidate.statusCode;
|
|
1877
|
-
if (typeof candidate.status === "number") return candidate.status;
|
|
1878
|
-
if (typeof candidate.message === "string") {
|
|
1879
|
-
const match = /\(HTTP (\d{3})\)/.exec(candidate.message);
|
|
1880
|
-
if (match) return Number.parseInt(match[1], 10);
|
|
1881
|
-
}
|
|
1882
|
-
return null;
|
|
2030
|
+
function isNextStandaloneOutputFailure(message) {
|
|
2031
|
+
return /next\.?js/i.test(message) && /standalone output/i.test(message);
|
|
1883
2032
|
}
|
|
1884
2033
|
function noDeploymentsError(summary, why) {
|
|
1885
2034
|
return new CliError({
|