@prisma/cli 3.0.0-alpha.2 → 3.0.0-alpha.4
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/dist/adapters/git.js +49 -0
- package/dist/adapters/local-state.js +38 -0
- package/dist/cli2.js +3 -1
- package/dist/commands/app/index.js +31 -20
- package/dist/commands/auth/index.js +1 -1
- package/dist/commands/env.js +87 -0
- package/dist/commands/git/index.js +36 -0
- package/dist/commands/project/index.js +10 -13
- package/dist/controllers/app-env.js +223 -0
- package/dist/controllers/app.js +260 -86
- package/dist/controllers/auth.js +2 -2
- package/dist/controllers/branch.js +1 -1
- package/dist/controllers/project.js +451 -161
- package/dist/lib/app/env-config.js +57 -0
- package/dist/lib/app/preview-provider.js +15 -2
- package/dist/lib/auth/auth-ops.js +8 -10
- package/dist/lib/auth/client.js +1 -1
- package/dist/lib/project/resolution.js +148 -0
- package/dist/output/patterns.js +1 -2
- package/dist/presenters/app-env.js +129 -0
- package/dist/presenters/app.js +9 -1
- package/dist/presenters/auth.js +2 -2
- package/dist/presenters/branch.js +6 -6
- package/dist/presenters/project.js +84 -44
- package/dist/shell/command-meta.js +91 -9
- package/dist/shell/command-runner.js +32 -2
- package/dist/shell/errors.js +4 -1
- package/dist/shell/help.js +1 -1
- package/dist/shell/output.js +18 -12
- package/dist/shell/runtime.js +1 -1
- package/dist/shell/ui.js +19 -1
- package/dist/use-cases/auth.js +5 -8
- package/dist/use-cases/branch.js +20 -20
- package/dist/use-cases/create-cli-gateways.js +3 -13
- package/dist/use-cases/project.js +2 -48
- package/package.json +2 -2
- package/dist/adapters/config.js +0 -74
package/dist/controllers/app.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "../lib/auth/client.js";
|
|
2
|
+
import { FileTokenStorage } from "../adapters/token-storage.js";
|
|
3
|
+
import { CliError, authRequiredError, featureUnavailableError, usageError, workspaceRequiredError } from "../shell/errors.js";
|
|
4
|
+
import { renderCommandHeader } from "../shell/ui.js";
|
|
5
|
+
import { writeJsonEvent } from "../shell/output.js";
|
|
3
6
|
import { canPrompt } from "../shell/runtime.js";
|
|
4
7
|
import { textPrompt } from "../shell/prompt.js";
|
|
5
8
|
import { requireComputeAuth } from "../lib/auth/guard.js";
|
|
9
|
+
import { readAuthState } from "../lib/auth/auth-ops.js";
|
|
6
10
|
import { parseEnvAssignments } from "../lib/app/env-vars.js";
|
|
7
11
|
import { DEFAULT_LOCAL_DEV_PORT, resolveLocalBuildType, runLocalApp } from "../lib/app/local-dev.js";
|
|
8
|
-
import {
|
|
12
|
+
import { resolveProjectTarget } from "../lib/project/resolution.js";
|
|
9
13
|
import { PREVIEW_BUILD_TYPES, RESOLVED_PREVIEW_BUILD_TYPES, executePreviewBuild } from "../lib/app/preview-build.js";
|
|
10
14
|
import { PREVIEW_DEFAULT_REGION, createPreviewDeployInteraction } from "../lib/app/preview-interaction.js";
|
|
11
15
|
import { createPreviewDeployProgress, createPreviewPromoteProgress, createPreviewUpdateEnvProgress } from "../lib/app/preview-progress.js";
|
|
12
16
|
import { createPreviewAppProvider } from "../lib/app/preview-provider.js";
|
|
13
17
|
import { createSelectPromptPort } from "./select-prompt-port.js";
|
|
14
|
-
import
|
|
18
|
+
import { requireAuthenticatedAuthState } from "./auth.js";
|
|
19
|
+
import { listRealWorkspaceProjects } from "./project.js";
|
|
15
20
|
import open from "open";
|
|
16
21
|
//#region src/controllers/app.ts
|
|
17
22
|
function isRealMode(context) {
|
|
@@ -79,8 +84,7 @@ async function runAppDeploy(context, appName, options) {
|
|
|
79
84
|
assertSupportedEntrypoint(buildType, options?.entrypoint, "deploy");
|
|
80
85
|
const portMapping = parseDeployPortMapping(options?.httpPort);
|
|
81
86
|
const envVars = toOptionalEnvVars(parseEnvAssignments(options?.envAssignments, { commandName: "deploy" }));
|
|
82
|
-
const provider = await
|
|
83
|
-
const projectId = await resolveProjectIdForDeploy(context, provider);
|
|
87
|
+
const { provider, target, projectId } = await requireProviderAndProjectContext(context, options?.projectRef, { allowCreate: true });
|
|
84
88
|
const selectedApp = await resolveDeploySelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
85
89
|
const deployResult = await provider.deployApp({
|
|
86
90
|
cwd: context.runtime.cwd,
|
|
@@ -105,7 +109,10 @@ async function runAppDeploy(context, appName, options) {
|
|
|
105
109
|
return {
|
|
106
110
|
command: "app.deploy",
|
|
107
111
|
result: {
|
|
108
|
-
|
|
112
|
+
workspace: target.workspace,
|
|
113
|
+
project: target.project,
|
|
114
|
+
branch: target.branch,
|
|
115
|
+
resolution: target.resolution,
|
|
109
116
|
app: {
|
|
110
117
|
id: deployResult.app.id,
|
|
111
118
|
name: deployResult.app.name
|
|
@@ -116,16 +123,16 @@ async function runAppDeploy(context, appName, options) {
|
|
|
116
123
|
nextSteps: ["prisma-cli app list-deploys", `prisma-cli app show-deploy ${deployResult.deployment.id}`]
|
|
117
124
|
};
|
|
118
125
|
}
|
|
119
|
-
async function runAppUpdateEnv(context, appName, envAssignments) {
|
|
126
|
+
async function runAppUpdateEnv(context, appName, envAssignments, projectRef) {
|
|
120
127
|
ensurePreviewAppMode(context);
|
|
128
|
+
emitLegacyEnvDeprecationWarning(context, "app update-env", "project env add");
|
|
121
129
|
const envVars = parseEnvAssignments(envAssignments, {
|
|
122
130
|
commandName: "update-env",
|
|
123
131
|
requireAtLeastOne: true
|
|
124
132
|
});
|
|
125
|
-
const projectId = await
|
|
126
|
-
const provider = await requirePreviewAppProvider(context);
|
|
133
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
127
134
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
128
|
-
if (!selectedApp) throw noDeploymentsError("No deployments available to update environment variables", "The
|
|
135
|
+
if (!selectedApp) throw noDeploymentsError("No deployments available to update environment variables", "The resolved project does not have any deployed app yet.");
|
|
129
136
|
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
130
137
|
throw deployFailedError("Failed to inspect app deployments", error, ["prisma-cli app list-deploys"]);
|
|
131
138
|
});
|
|
@@ -158,10 +165,10 @@ async function runAppUpdateEnv(context, appName, envAssignments) {
|
|
|
158
165
|
nextSteps: ["prisma-cli app list-env", `prisma-cli app show-deploy ${updateResult.deployment.id}`]
|
|
159
166
|
};
|
|
160
167
|
}
|
|
161
|
-
async function runAppListEnv(context, appName) {
|
|
168
|
+
async function runAppListEnv(context, appName, projectRef) {
|
|
162
169
|
ensurePreviewAppMode(context);
|
|
163
|
-
|
|
164
|
-
const provider = await
|
|
170
|
+
emitLegacyEnvDeprecationWarning(context, "app list-env", "project env list");
|
|
171
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
165
172
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
166
173
|
if (!selectedApp) return {
|
|
167
174
|
command: "app.list-env",
|
|
@@ -246,10 +253,9 @@ async function runAppListEnv(context, appName) {
|
|
|
246
253
|
nextSteps: deployment.id ? [`prisma-cli app show-deploy ${deployment.id}`] : ["prisma-cli app deploy"]
|
|
247
254
|
};
|
|
248
255
|
}
|
|
249
|
-
async function runAppListDeploys(context, appName) {
|
|
256
|
+
async function runAppListDeploys(context, appName, projectRef) {
|
|
250
257
|
ensurePreviewAppMode(context);
|
|
251
|
-
const projectId = await
|
|
252
|
-
const provider = await requirePreviewAppProvider(context);
|
|
258
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
253
259
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
254
260
|
if (!selectedApp) return {
|
|
255
261
|
command: "app.list-deploys",
|
|
@@ -284,10 +290,9 @@ async function runAppListDeploys(context, appName) {
|
|
|
284
290
|
nextSteps: deployments.length > 0 ? [`prisma-cli app show-deploy ${deployments[0]?.id}`] : ["prisma-cli app deploy"]
|
|
285
291
|
};
|
|
286
292
|
}
|
|
287
|
-
async function runAppShow(context, appName) {
|
|
293
|
+
async function runAppShow(context, appName, projectRef) {
|
|
288
294
|
ensurePreviewAppMode(context);
|
|
289
|
-
const projectId = await
|
|
290
|
-
const provider = await requirePreviewAppProvider(context);
|
|
295
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
291
296
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
292
297
|
if (!selectedApp) return {
|
|
293
298
|
command: "app.show",
|
|
@@ -341,8 +346,9 @@ async function runAppShowDeploy(context, deploymentId) {
|
|
|
341
346
|
exitCode: 1,
|
|
342
347
|
nextSteps: ["prisma-cli app list-deploys"]
|
|
343
348
|
});
|
|
344
|
-
const
|
|
345
|
-
const
|
|
349
|
+
const workspaceId = deployment?.app ? await readCurrentWorkspaceId(context) : null;
|
|
350
|
+
const rememberedProject = workspaceId ? await context.stateStore.readRememberedProject(workspaceId) : null;
|
|
351
|
+
const knownLiveDeploymentId = deployment?.app && rememberedProject ? await context.stateStore.readKnownLiveDeployment(rememberedProject.id, deployment.app.id) : null;
|
|
346
352
|
const providerLiveDeploymentId = deployment.app?.liveDeploymentId ?? null;
|
|
347
353
|
return {
|
|
348
354
|
command: "app.show-deploy",
|
|
@@ -360,12 +366,11 @@ async function runAppShowDeploy(context, deploymentId) {
|
|
|
360
366
|
nextSteps: []
|
|
361
367
|
};
|
|
362
368
|
}
|
|
363
|
-
async function runAppOpen(context, appName) {
|
|
369
|
+
async function runAppOpen(context, appName, projectRef) {
|
|
364
370
|
ensurePreviewAppMode(context);
|
|
365
|
-
const projectId = await
|
|
366
|
-
const provider = await requirePreviewAppProvider(context);
|
|
371
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
367
372
|
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
368
|
-
if (!selectedApp) throw noDeploymentsError("No deployments available to open", "The
|
|
373
|
+
if (!selectedApp) throw noDeploymentsError("No deployments available to open", "The resolved project does not have any deployed app yet.");
|
|
369
374
|
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
370
375
|
throw deployFailedError("Failed to resolve app URL", error, ["prisma-cli app show"]);
|
|
371
376
|
});
|
|
@@ -395,14 +400,133 @@ async function runAppOpen(context, appName) {
|
|
|
395
400
|
nextSteps: ["prisma-cli app show", `prisma-cli app show-deploy ${liveDeployment.id}`]
|
|
396
401
|
};
|
|
397
402
|
}
|
|
398
|
-
async function runAppLogs(context,
|
|
403
|
+
async function runAppLogs(context, appName, deploymentId, projectRef) {
|
|
399
404
|
ensurePreviewAppMode(context);
|
|
400
|
-
|
|
405
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
406
|
+
const target = deploymentId ? await resolveExplicitLogDeployment(context, provider, projectId, appName, deploymentId) : await resolveLiveLogDeployment(context, provider, projectId, appName);
|
|
407
|
+
if (!context.flags.json && !context.flags.quiet) {
|
|
408
|
+
const lines = renderCommandHeader(context.ui, {
|
|
409
|
+
commandLabel: "app logs",
|
|
410
|
+
description: "Streaming logs for the selected deployment.",
|
|
411
|
+
docsPath: "docs/product/command-spec.md#prisma-cli-app-logs---app-name---deployment-id",
|
|
412
|
+
rows: [
|
|
413
|
+
{
|
|
414
|
+
key: "project",
|
|
415
|
+
value: projectId
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
key: "app",
|
|
419
|
+
value: target.app.name
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
key: "deployment",
|
|
423
|
+
value: target.deployment.id
|
|
424
|
+
}
|
|
425
|
+
]
|
|
426
|
+
});
|
|
427
|
+
if (lines.length > 0) context.output.stderr.write(`${lines.join("\n")}\n`);
|
|
428
|
+
}
|
|
429
|
+
await provider.streamDeploymentLogs({
|
|
430
|
+
deploymentId: target.deployment.id,
|
|
431
|
+
onRecord: (record) => writeLogRecord(context, record)
|
|
432
|
+
}).catch((error) => {
|
|
433
|
+
throw deployFailedError("Failed to stream app logs", error, [`prisma-cli app show-deploy ${target.deployment.id}`, "prisma-cli app list-deploys"]);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
async function resolveExplicitLogDeployment(context, provider, projectId, appName, deploymentId) {
|
|
437
|
+
if (appName) {
|
|
438
|
+
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
439
|
+
if (!selectedApp) throw noDeploymentsError("No deployments available to stream logs", "The resolved project does not have any deployed app yet.");
|
|
440
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
441
|
+
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
442
|
+
});
|
|
443
|
+
const deployment = requireDeploymentForApp(deploymentsResult.deployments, deploymentId, selectedApp.name);
|
|
444
|
+
await context.stateStore.setSelectedApp(projectId, {
|
|
445
|
+
id: deploymentsResult.app.id,
|
|
446
|
+
name: deploymentsResult.app.name
|
|
447
|
+
});
|
|
448
|
+
return {
|
|
449
|
+
app: deploymentsResult.app,
|
|
450
|
+
deployment
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
const shown = await provider.showDeployment(deploymentId).catch((error) => {
|
|
454
|
+
throw deployFailedError("Failed to show deployment", error, ["prisma-cli app list-deploys"]);
|
|
455
|
+
});
|
|
456
|
+
if (!shown) throw new CliError({
|
|
457
|
+
code: "DEPLOYMENT_NOT_FOUND",
|
|
458
|
+
domain: "app",
|
|
459
|
+
summary: `Deployment "${deploymentId}" not found`,
|
|
460
|
+
why: "The requested deployment does not exist or is no longer available.",
|
|
461
|
+
fix: "Run prisma-cli app list-deploys to choose an available deployment id.",
|
|
462
|
+
exitCode: 1,
|
|
463
|
+
nextSteps: ["prisma-cli app list-deploys"]
|
|
464
|
+
});
|
|
465
|
+
if (!shown.app) throw new CliError({
|
|
466
|
+
code: "DEPLOYMENT_NOT_FOUND",
|
|
467
|
+
domain: "app",
|
|
468
|
+
summary: `Deployment "${deploymentId}" is not attached to an app`,
|
|
469
|
+
why: "The requested deployment could be found, but its app could not be resolved.",
|
|
470
|
+
fix: "Run prisma-cli app list-deploys to choose an available deployment id for the selected app.",
|
|
471
|
+
exitCode: 1,
|
|
472
|
+
nextSteps: ["prisma-cli app list-deploys"]
|
|
473
|
+
});
|
|
474
|
+
const resolvedProjectApp = (await listApps(context, provider, projectId)).find((app) => app.id === shown.app?.id);
|
|
475
|
+
if (!resolvedProjectApp) throw new CliError({
|
|
476
|
+
code: "DEPLOYMENT_NOT_FOUND",
|
|
477
|
+
domain: "app",
|
|
478
|
+
summary: `Deployment "${deploymentId}" not found in the resolved project`,
|
|
479
|
+
why: "The requested deployment does not belong to an app in the resolved project.",
|
|
480
|
+
fix: "Run prisma-cli app list-deploys to choose an available deployment id for this project.",
|
|
481
|
+
exitCode: 1,
|
|
482
|
+
nextSteps: ["prisma-cli app list-deploys"]
|
|
483
|
+
});
|
|
484
|
+
await context.stateStore.setSelectedApp(projectId, {
|
|
485
|
+
id: resolvedProjectApp.id,
|
|
486
|
+
name: resolvedProjectApp.name
|
|
487
|
+
});
|
|
488
|
+
return {
|
|
489
|
+
app: resolvedProjectApp,
|
|
490
|
+
deployment: shown.deployment
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
async function resolveLiveLogDeployment(context, provider, projectId, appName) {
|
|
494
|
+
const selectedApp = await resolveExistingAppSelection(context, projectId, await listApps(context, provider, projectId), appName);
|
|
495
|
+
if (!selectedApp) throw noDeploymentsError("No deployments available to stream logs", "The resolved project does not have any deployed app yet.");
|
|
496
|
+
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
497
|
+
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
498
|
+
});
|
|
499
|
+
const currentLiveDeploymentId = await resolveCurrentLiveDeploymentId(context, projectId, deploymentsResult.app, deploymentsResult.deployments);
|
|
500
|
+
const deployments = applyLiveDeploymentHint(deploymentsResult.deployments, currentLiveDeploymentId);
|
|
501
|
+
const deployment = currentLiveDeploymentId ? deployments.find((candidate) => candidate.id === currentLiveDeploymentId) ?? null : null;
|
|
502
|
+
await context.stateStore.setSelectedApp(projectId, {
|
|
503
|
+
id: deploymentsResult.app.id,
|
|
504
|
+
name: deploymentsResult.app.name
|
|
505
|
+
});
|
|
506
|
+
if (!deployment) throw noDeploymentsError("No deployments available to stream logs", `The selected app "${deploymentsResult.app.name}" does not have any deployments yet.`);
|
|
507
|
+
return {
|
|
508
|
+
app: deploymentsResult.app,
|
|
509
|
+
deployment
|
|
510
|
+
};
|
|
401
511
|
}
|
|
402
|
-
|
|
512
|
+
function writeLogRecord(context, record) {
|
|
513
|
+
if (context.flags.json) {
|
|
514
|
+
writeJsonEvent(context.output, {
|
|
515
|
+
type: record.type,
|
|
516
|
+
command: "app.logs",
|
|
517
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
518
|
+
data: record
|
|
519
|
+
});
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
if (record.type === "log") {
|
|
523
|
+
context.output.stdout.write(record.text);
|
|
524
|
+
if (!record.text.endsWith("\n")) context.output.stdout.write("\n");
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
async function runAppPromote(context, deploymentId, appName, projectRef) {
|
|
403
528
|
ensurePreviewAppMode(context);
|
|
404
|
-
const projectId = await
|
|
405
|
-
const provider = await requirePreviewAppProvider(context);
|
|
529
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
406
530
|
const selectedApp = await requireReleaseAppSelection(context, projectId, await listApps(context, provider, projectId), appName, "promote");
|
|
407
531
|
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
408
532
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
@@ -440,10 +564,9 @@ async function runAppPromote(context, deploymentId, appName) {
|
|
|
440
564
|
nextSteps: ["prisma-cli app list-deploys", `prisma-cli app show-deploy ${targetDeployment.id}`]
|
|
441
565
|
};
|
|
442
566
|
}
|
|
443
|
-
async function runAppRollback(context, appName, deploymentId) {
|
|
567
|
+
async function runAppRollback(context, appName, deploymentId, projectRef) {
|
|
444
568
|
ensurePreviewAppMode(context);
|
|
445
|
-
const projectId = await
|
|
446
|
-
const provider = await requirePreviewAppProvider(context);
|
|
569
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
447
570
|
const selectedApp = await requireReleaseAppSelection(context, projectId, await listApps(context, provider, projectId), appName, "rollback");
|
|
448
571
|
const deploymentsResult = await provider.listDeployments(selectedApp.id).catch((error) => {
|
|
449
572
|
throw deployFailedError("Failed to list app deployments", error, ["prisma-cli app list-deploys"]);
|
|
@@ -483,10 +606,9 @@ async function runAppRollback(context, appName, deploymentId) {
|
|
|
483
606
|
nextSteps: ["prisma-cli app list-deploys", `prisma-cli app show-deploy ${targetDeployment.id}`]
|
|
484
607
|
};
|
|
485
608
|
}
|
|
486
|
-
async function runAppRemove(context, appName) {
|
|
609
|
+
async function runAppRemove(context, appName, projectRef) {
|
|
487
610
|
ensurePreviewAppMode(context);
|
|
488
|
-
const projectId = await
|
|
489
|
-
const provider = await requirePreviewAppProvider(context);
|
|
611
|
+
const { provider, projectId } = await requireProviderAndProjectContext(context, projectRef);
|
|
490
612
|
const selectedApp = await requireReleaseAppSelection(context, projectId, await listApps(context, provider, projectId), appName, "remove");
|
|
491
613
|
await confirmAppRemoval(context, selectedApp);
|
|
492
614
|
const removedApp = await provider.removeApp(selectedApp.id).catch((error) => {
|
|
@@ -527,7 +649,7 @@ async function resolveDeploySelection(context, projectId, apps, explicitAppName)
|
|
|
527
649
|
appId: matched.id,
|
|
528
650
|
useInteractiveSelection: false
|
|
529
651
|
};
|
|
530
|
-
if (!canPrompt(context)) throw usageError("Saved app selection is no longer available", "The locally selected app could not be found in the
|
|
652
|
+
if (!canPrompt(context)) throw usageError("Saved app selection is no longer available", "The locally selected app could not be found in the resolved project.", "Pass --app <name>, or rerun prisma-cli app deploy in a TTY to choose or create an app again.", ["prisma-cli app deploy"], "app");
|
|
531
653
|
}
|
|
532
654
|
if (!canPrompt(context)) throw usageError("App deploy requires an app selection in non-interactive mode", "This command cannot choose or create an app in the current mode.", "Pass --app <name>, or rerun prisma-cli app deploy in a TTY to choose or create an app.", ["prisma-cli app deploy --app hello-world"], "app");
|
|
533
655
|
return { useInteractiveSelection: true };
|
|
@@ -535,14 +657,14 @@ async function resolveDeploySelection(context, projectId, apps, explicitAppName)
|
|
|
535
657
|
async function resolveExistingAppSelection(context, projectId, apps, explicitAppName) {
|
|
536
658
|
if (explicitAppName) {
|
|
537
659
|
const matched = findAppByName(apps, explicitAppName);
|
|
538
|
-
if (!matched) throw usageError("Selected app does not exist in the
|
|
660
|
+
if (!matched) throw usageError("Selected app does not exist in the resolved project", `The app "${explicitAppName}" could not be found in resolved project "${projectId}".`, "Pass the name of an existing app, or rerun prisma-cli app list-deploys in a TTY to choose one.", ["prisma-cli app list-deploys"], "app");
|
|
539
661
|
return matched;
|
|
540
662
|
}
|
|
541
663
|
const savedSelection = await context.stateStore.readSelectedApp(projectId);
|
|
542
664
|
if (savedSelection) {
|
|
543
665
|
const matched = apps.find((app) => app.id === savedSelection.id) ?? findAppByName(apps, savedSelection.name);
|
|
544
666
|
if (matched) return matched;
|
|
545
|
-
if (!canPrompt(context)) throw usageError("Saved app selection is no longer available", "The locally selected app could not be found in the
|
|
667
|
+
if (!canPrompt(context)) throw usageError("Saved app selection is no longer available", "The locally selected app could not be found in the resolved project.", "Pass --app <name>, or rerun prisma-cli app list-deploys in a TTY to choose an available app.", ["prisma-cli app list-deploys"], "app");
|
|
546
668
|
}
|
|
547
669
|
if (apps.length === 0) return null;
|
|
548
670
|
if (!canPrompt(context)) throw usageError("App selection required in non-interactive mode", "This command cannot choose an app in the current mode.", "Pass --app <name>, or rerun prisma-cli app list-deploys in a TTY to choose an app.", ["prisma-cli app list-deploys"], "app");
|
|
@@ -558,7 +680,7 @@ async function resolveExistingAppSelection(context, projectId, apps, explicitApp
|
|
|
558
680
|
async function requireReleaseAppSelection(context, projectId, apps, explicitAppName, commandName) {
|
|
559
681
|
const selectedApp = await resolveExistingAppSelection(context, projectId, apps, explicitAppName);
|
|
560
682
|
if (selectedApp) return selectedApp;
|
|
561
|
-
throw usageError(`App ${commandName} requires an existing app`, "The
|
|
683
|
+
throw usageError(`App ${commandName} requires an existing app`, "The resolved project does not have an app that can be selected for this command.", `Deploy an app first, or rerun prisma-cli app ${commandName} with --app <name> after an app exists.`, ["prisma-cli app deploy", "prisma-cli app list-deploys"], "app");
|
|
562
684
|
}
|
|
563
685
|
async function confirmAppRemoval(context, app) {
|
|
564
686
|
if (context.flags.yes) return;
|
|
@@ -647,55 +769,94 @@ function resolveRollbackTarget(deployments, currentLiveDeploymentId) {
|
|
|
647
769
|
}
|
|
648
770
|
async function listApps(context, provider, projectId) {
|
|
649
771
|
return provider.listApps(projectId).then(sortApps).catch((error) => {
|
|
650
|
-
if (isMissingProjectError(error)) throw
|
|
651
|
-
|
|
652
|
-
"
|
|
653
|
-
"
|
|
654
|
-
|
|
772
|
+
if (isMissingProjectError(error)) throw new CliError({
|
|
773
|
+
code: "PROJECT_NOT_FOUND",
|
|
774
|
+
domain: "project",
|
|
775
|
+
summary: "Project not found",
|
|
776
|
+
why: `The resolved project "${projectId}" does not exist in the authenticated workspace or is no longer accessible.`,
|
|
777
|
+
fix: "Pass --project <id-or-name>, or run prisma-cli project show to inspect resolution for this directory.",
|
|
778
|
+
exitCode: 1,
|
|
779
|
+
nextSteps: ["prisma-cli project show", "prisma-cli app deploy --project <id-or-name>"]
|
|
780
|
+
});
|
|
655
781
|
throw deployFailedError("Failed to list apps", error, ["prisma-cli project show"]);
|
|
656
782
|
});
|
|
657
783
|
}
|
|
658
784
|
async function requirePreviewAppProvider(context) {
|
|
785
|
+
const { provider } = await requirePreviewAppProviderWithClient(context);
|
|
786
|
+
return provider;
|
|
787
|
+
}
|
|
788
|
+
async function requirePreviewAppProviderWithClient(context) {
|
|
659
789
|
const client = await requireComputeAuth(context.runtime.env);
|
|
660
790
|
if (!client) throw authRequiredError(["prisma-cli auth login"]);
|
|
661
|
-
return
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
if (!projectId) throw new CliError({
|
|
666
|
-
code: "PROJECT_NOT_LINKED",
|
|
667
|
-
domain: "project",
|
|
668
|
-
summary: "Project link required",
|
|
669
|
-
why: "This command needs a linked project for the current repo.",
|
|
670
|
-
fix: "Run prisma-cli project link before deploying or inspecting app deployments.",
|
|
671
|
-
exitCode: 1,
|
|
672
|
-
nextSteps: ["prisma-cli project link"]
|
|
673
|
-
});
|
|
674
|
-
return projectId;
|
|
791
|
+
return {
|
|
792
|
+
client,
|
|
793
|
+
provider: createPreviewAppProvider(client, createPreviewLogAuthOptions(context.runtime.env))
|
|
794
|
+
};
|
|
675
795
|
}
|
|
676
|
-
|
|
677
|
-
const
|
|
678
|
-
if (
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
796
|
+
function createPreviewLogAuthOptions(env) {
|
|
797
|
+
const rawToken = env[SERVICE_TOKEN_ENV_VAR]?.trim();
|
|
798
|
+
if (rawToken) return {
|
|
799
|
+
baseUrl: getApiBaseUrl(env),
|
|
800
|
+
getToken: async () => rawToken
|
|
801
|
+
};
|
|
802
|
+
const tokenStorage = new FileTokenStorage(env);
|
|
803
|
+
return {
|
|
804
|
+
baseUrl: getApiBaseUrl(env),
|
|
805
|
+
getToken: async () => {
|
|
806
|
+
const tokens = await tokenStorage.getTokens();
|
|
807
|
+
if (!tokens) throw new Error("Authentication token is no longer available. Run prisma-cli auth login and try again.");
|
|
808
|
+
return tokens.accessToken;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
691
811
|
}
|
|
692
|
-
async function
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
812
|
+
async function requireProviderAndProjectContext(context, explicitProject, options) {
|
|
813
|
+
const { client, provider } = await requirePreviewAppProviderWithClient(context);
|
|
814
|
+
const target = await resolveProjectContext(context, client, provider, explicitProject, options);
|
|
815
|
+
return {
|
|
816
|
+
client,
|
|
817
|
+
provider,
|
|
818
|
+
target,
|
|
819
|
+
projectId: target.project.id
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
async function resolveProjectContext(context, client, provider, explicitProject, options) {
|
|
823
|
+
const authState = await requireAuthenticatedAuthState(context);
|
|
824
|
+
if (!authState.workspace) throw workspaceRequiredError();
|
|
825
|
+
const resolved = await resolveProjectTarget({
|
|
826
|
+
context,
|
|
827
|
+
workspace: authState.workspace,
|
|
828
|
+
explicitProject,
|
|
829
|
+
listProjects: () => listRealWorkspaceProjects(client, authState.workspace),
|
|
830
|
+
createProject: options?.allowCreate ? async (name) => {
|
|
831
|
+
const project = await provider.createProject({ name }).catch((error) => {
|
|
832
|
+
throw deployFailedError("Failed to create project for first deploy", error, ["prisma-cli app deploy"]);
|
|
833
|
+
});
|
|
834
|
+
return {
|
|
835
|
+
id: project.id,
|
|
836
|
+
name: project.name,
|
|
837
|
+
workspace: authState.workspace
|
|
838
|
+
};
|
|
839
|
+
} : void 0,
|
|
840
|
+
allowCreate: options?.allowCreate,
|
|
841
|
+
prompt: createSelectPromptPort(context),
|
|
842
|
+
remember: true
|
|
843
|
+
});
|
|
844
|
+
const branchName = await context.stateStore.read().then((state) => state.branch.active);
|
|
845
|
+
return {
|
|
846
|
+
...resolved,
|
|
847
|
+
branch: {
|
|
848
|
+
name: branchName,
|
|
849
|
+
kind: toBranchKind(branchName)
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function toBranchKind(name) {
|
|
854
|
+
return name === "production" ? "production" : "preview";
|
|
855
|
+
}
|
|
856
|
+
async function readCurrentWorkspaceId(context) {
|
|
857
|
+
const state = await context.stateStore.read();
|
|
858
|
+
if (state.auth?.workspaceId) return state.auth.workspaceId;
|
|
859
|
+
return (await readAuthState(context.runtime.env)).workspace?.id ?? null;
|
|
699
860
|
}
|
|
700
861
|
function normalizeBuildType(requestedBuildType) {
|
|
701
862
|
if (!requestedBuildType) return "auto";
|
|
@@ -732,10 +893,7 @@ function parseDeployPortMapping(requestedPort) {
|
|
|
732
893
|
}
|
|
733
894
|
function ensurePreviewAppMode(context) {
|
|
734
895
|
if (isRealMode(context)) return;
|
|
735
|
-
throw featureUnavailableError("App commands are not available in fixture mode", "Preview app commands require live app deployment integration.", "Rerun without fixture mode enabled to use preview app deployment workflows.", ["prisma-cli auth login", "prisma-cli project
|
|
736
|
-
}
|
|
737
|
-
function blockedPreviewAppCommandError(summary, why) {
|
|
738
|
-
return featureUnavailableError(summary, why, "Use prisma-cli app show, prisma-cli app open, prisma-cli app deploy, or prisma-cli app list-deploys in the current preview.", ["prisma-cli app show", "prisma-cli app list-deploys"], "app");
|
|
896
|
+
throw featureUnavailableError("App commands are not available in fixture mode", "Preview app commands require live app deployment integration.", "Rerun without fixture mode enabled to use preview app deployment workflows.", ["prisma-cli auth login", "prisma-cli project show"], "app");
|
|
739
897
|
}
|
|
740
898
|
function deployFailedError(summary, error, nextSteps) {
|
|
741
899
|
return new CliError({
|
|
@@ -830,5 +988,21 @@ function sortApps(apps) {
|
|
|
830
988
|
function toOptionalEnvVars(envVars) {
|
|
831
989
|
return Object.keys(envVars).length > 0 ? envVars : void 0;
|
|
832
990
|
}
|
|
991
|
+
/**
|
|
992
|
+
* Emits a deprecation banner to stderr when the legacy single-shot
|
|
993
|
+
* env-var commands are invoked. The banner is suppressed in --json
|
|
994
|
+
* mode so machine consumers keep their JSON channel clean; --json
|
|
995
|
+
* users discover the deprecation via release notes and the new
|
|
996
|
+
* `prisma-cli project env` namespace's output anyway.
|
|
997
|
+
*
|
|
998
|
+
* Removal of these legacy commands is deliberately scoped out of the
|
|
999
|
+
* Public Beta — see the Compute Beta plan, sub-track 3B.1, where the
|
|
1000
|
+
* Terminal team picks an explicit removal milestone.
|
|
1001
|
+
*/
|
|
1002
|
+
function emitLegacyEnvDeprecationWarning(context, legacyCommand, replacement) {
|
|
1003
|
+
if (context.flags.json) return;
|
|
1004
|
+
const message = `[deprecation] \`prisma-cli ${legacyCommand}\` is deprecated. Use \`prisma-cli ${replacement}\` instead.`;
|
|
1005
|
+
context.runtime.stderr.write(`${message}\n`);
|
|
1006
|
+
}
|
|
833
1007
|
//#endregion
|
|
834
1008
|
export { runAppBuild, runAppDeploy, runAppListDeploys, runAppListEnv, runAppLogs, runAppOpen, runAppPromote, runAppRemove, runAppRollback, runAppRun, runAppShow, runAppShowDeploy, runAppUpdateEnv };
|
package/dist/controllers/auth.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { authRequiredError, usageError } from "../shell/errors.js";
|
|
2
2
|
import { canPrompt } from "../shell/runtime.js";
|
|
3
|
-
import {
|
|
3
|
+
import { performLogin, performLogout, readAuthState } from "../lib/auth/auth-ops.js";
|
|
4
4
|
import { createAuthUseCases } from "../use-cases/auth.js";
|
|
5
5
|
import { createCliUseCaseGateways } from "../use-cases/create-cli-gateways.js";
|
|
6
|
-
import {
|
|
6
|
+
import { createSelectPromptPort } from "./select-prompt-port.js";
|
|
7
7
|
//#region src/controllers/auth.ts
|
|
8
8
|
function isRealMode(context) {
|
|
9
9
|
return !context.runtime.fixturePath && !context.runtime.env.PRISMA_CLI_MOCK_FIXTURE_PATH;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { featureUnavailableError, usageError } from "../shell/errors.js";
|
|
2
2
|
import { canPrompt } from "../shell/runtime.js";
|
|
3
|
-
import { createSelectPromptPort } from "./select-prompt-port.js";
|
|
4
3
|
import { createCliUseCaseGateways } from "../use-cases/create-cli-gateways.js";
|
|
4
|
+
import { createSelectPromptPort } from "./select-prompt-port.js";
|
|
5
5
|
import { createBranchUseCases } from "../use-cases/branch.js";
|
|
6
6
|
//#region src/controllers/branch.ts
|
|
7
7
|
const PREVIEW_BRANCH_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|