@prisma/cli 3.0.0-dev.88.1 → 3.0.0-dev.91.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import { usageError } from "../../shell/errors.js";
2
+ import { APP_BUILD_TYPES } from "../../lib/app/build.js";
2
3
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
3
4
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
4
5
  import { configureRuntimeCommand } from "../../shell/runtime.js";
5
- import { PREVIEW_BUILD_TYPES } from "../../lib/app/preview-build.js";
6
6
  import { runAppBuild, runAppDeploy, runAppDomainAdd, runAppDomainRemove, runAppDomainRetry, runAppDomainShow, runAppDomainWait, runAppListDeploys, runAppLogs, runAppOpen, runAppPromote, runAppRemove, runAppRollback, runAppRun, runAppShow, runAppShowDeploy } from "../../controllers/app.js";
7
7
  import { isAppDeployAllResult, renderAppBuild, renderAppDeploy, renderAppDeployAll, renderAppDomainAdd, renderAppDomainRemove, renderAppDomainRetry, renderAppDomainShow, renderAppListDeploys, renderAppOpen, renderAppPromote, renderAppRemove, renderAppRollback, renderAppRun, renderAppShow, renderAppShowDeploy, serializeAppBuild, serializeAppDeploy, serializeAppDeployAll, serializeAppDomainAdd, serializeAppDomainRemove, serializeAppDomainRetry, serializeAppDomainShow, serializeAppListDeploys, serializeAppOpen, serializeAppPromote, serializeAppRemove, serializeAppRollback, serializeAppRun, serializeAppShow, serializeAppShowDeploy } from "../../presenters/app.js";
8
8
  import { runCommand, runStreamingCommand } from "../../shell/command-runner.js";
@@ -28,7 +28,7 @@ function createAppCommand(runtime) {
28
28
  }
29
29
  function createBuildCommand(runtime) {
30
30
  const command = attachCommandDescriptor(configureRuntimeCommand(new Command("build"), runtime), "app.build");
31
- command.argument("[app]", "App target from prisma.compute.ts when the config defines multiple apps").addOption(new Option("--entry <path>", "Entrypoint path for Bun or auto builds")).addOption(new Option("--build-type <type>", "Local build type").choices([...PREVIEW_BUILD_TYPES]).default("auto"));
31
+ command.argument("[app]", "App target from prisma.compute.ts when the config defines multiple apps").addOption(new Option("--entry <path>", "Entrypoint path for Bun or auto builds")).addOption(new Option("--build-type <type>", "Local build type").choices([...APP_BUILD_TYPES]).default("auto"));
32
32
  addGlobalFlags(command);
33
33
  command.action(async (configTarget, options) => {
34
34
  const entry = options.entry;
@@ -1,7 +1,7 @@
1
1
  import { CliError, authRequiredError, usageError, workspaceRequiredError } from "../shell/errors.js";
2
- import { projectResolutionErrorToCliError, resolveProjectTarget } from "../lib/project/resolution.js";
3
2
  import { formatScopeLabel, parseKeyValuePositional, resolveEnvScope } from "../lib/app/env-config.js";
4
3
  import { readEnvFileAssignments } from "../lib/app/env-file.js";
4
+ import { projectResolutionErrorToCliError, resolveProjectTarget } from "../lib/project/resolution.js";
5
5
  import { requireComputeAuth } from "../lib/auth/guard.js";
6
6
  import { readLocalGitBranch } from "../lib/git/local-branch.js";
7
7
  import { requireAuthenticatedAuthState } from "./auth.js";
@@ -2,6 +2,11 @@ import { SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "../lib/auth/client.js";
2
2
  import { FileTokenStorage } from "../adapters/token-storage.js";
3
3
  import { CliError, authRequiredError, featureUnavailableError, usageError, workspaceRequiredError } from "../shell/errors.js";
4
4
  import { confirmPrompt, selectPrompt, textPrompt } from "../shell/prompt.js";
5
+ import { DEFAULT_REGION } from "../lib/app/app-interaction.js";
6
+ import { PRISMA_APP_CONFIG_FILENAME, detectLegacyBuildSettings, resolveConfiguredAppBuildSettings, resolveInferredAppBuildSettings } from "../lib/app/build-settings.js";
7
+ import { APP_BUILD_TYPES, RESOLVED_APP_BUILD_TYPES, executeAppBuild } from "../lib/app/build.js";
8
+ import { envVarNames, parseEnvInputs } from "../lib/app/env-vars.js";
9
+ import { DomainApiError, createAppProvider } from "../lib/app/app-provider.js";
5
10
  import { renderCommandHeader } from "../shell/ui.js";
6
11
  import { canPrompt } from "../shell/runtime.js";
7
12
  import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH, readLocalResolutionPin } from "../lib/project/local-pin.js";
@@ -13,15 +18,11 @@ import { readBunPackageEntrypoint, readBunPackageJson } from "../lib/app/bun-pro
13
18
  import { COMPUTE_CONFIG_FILENAME as COMPUTE_CONFIG_FILENAME$1, ComputeConfigTargetRequiredError, computeConfigErrorToCliError, computeFrameworkToBuildType, computeTargetAppDir, inferComputeTargetFromCwd, loadComputeConfig as loadComputeConfig$1, mergeComputeDeployInputs, mergeComputeLocalInputs, selectComputeDeployTarget } from "../lib/app/compute-config.js";
14
19
  import { renderDeployOutputRows, renderDeploySettingsPreview } from "../lib/app/deploy-output.js";
15
20
  import { describeDeployAllFailure, perAppInputsForDeployAll, planAppDeploy } from "../lib/app/deploy-plan.js";
21
+ import { createDeployProgress, createDeployProgressState, createPromoteProgress } from "../lib/app/deploy-progress.js";
16
22
  import { formatDomainFailureFix } from "../lib/app/domain-guidance.js";
17
- import { envVarNames, parseEnvInputs } from "../lib/app/env-vars.js";
18
23
  import { DEFAULT_LOCAL_DEV_PORT, runLocalApp } from "../lib/app/local-dev.js";
19
- import { PRISMA_APP_CONFIG_FILENAME, detectLegacyBuildSettings, resolveConfiguredPreviewBuildSettings, resolveInferredPreviewBuildSettings } from "../lib/app/preview-build-settings.js";
20
- import { PREVIEW_BUILD_TYPES, RESOLVED_PREVIEW_BUILD_TYPES, executePreviewBuild } from "../lib/app/preview-build.js";
21
- import { PREVIEW_DEFAULT_REGION } from "../lib/app/preview-interaction.js";
22
- import { createPreviewDeployProgress, createPreviewDeployProgressState, createPreviewPromoteProgress } from "../lib/app/preview-progress.js";
23
- import { PreviewDomainApiError, createPreviewAppProvider } from "../lib/app/preview-provider.js";
24
24
  import { enforceProductionDeployGate } from "../lib/app/production-deploy-gate.js";
25
+ import { resolveReadBranch } from "../lib/app/read-branch.js";
25
26
  import { requireComputeAuth } from "../lib/auth/guard.js";
26
27
  import { readAuthState } from "../lib/auth/auth-ops.js";
27
28
  import { readLocalGitBranch } from "../lib/git/local-branch.js";
@@ -60,7 +61,7 @@ async function runAppBuild(context, options) {
60
61
  }
61
62
  assertSupportedEntrypoint(buildType, merged.entrypoint, "build");
62
63
  if (compute.target?.build && buildType !== "auto") assertConfigBackedBuildSettings(buildType);
63
- const buildSettings = compute.config && compute.target?.build && isConfigBackedBuildType(buildType) ? (await resolveConfiguredPreviewBuildSettings({
64
+ const buildSettings = compute.config && compute.target?.build && isConfigBackedBuildType(buildType) ? (await resolveConfiguredAppBuildSettings({
64
65
  appPath: appDir,
65
66
  buildType,
66
67
  configured: compute.target.build,
@@ -68,7 +69,7 @@ async function runAppBuild(context, options) {
68
69
  signal: context.runtime.signal
69
70
  })).settings : void 0;
70
71
  try {
71
- const { artifact, buildType: actualBuildType } = await executePreviewBuild({
72
+ const { artifact, buildType: actualBuildType } = await executeAppBuild({
72
73
  appPath: appDir,
73
74
  entrypoint: merged.entrypoint,
74
75
  buildType,
@@ -86,7 +87,7 @@ async function runAppBuild(context, options) {
86
87
  nextSteps: ["prisma-cli app deploy"]
87
88
  };
88
89
  } catch (error) {
89
- if (buildType === "auto" && isAutoBuildDetectionError(error)) throw usageError("App build requires an explicit framework when detection is ambiguous", `This preview auto-detects clear project shapes for ${RESOLVED_PREVIEW_BUILD_TYPES.map(formatBuildTypeName).join(", ")}.`, "Pass a supported --build-type value, or pass --entry <path> for a Bun app.", getBuildTypeExamples("build"), "app");
90
+ if (buildType === "auto" && isAutoBuildDetectionError(error)) throw usageError("App build requires an explicit framework when detection is ambiguous", `This preview auto-detects clear project shapes for ${RESOLVED_APP_BUILD_TYPES.map(formatBuildTypeName).join(", ")}.`, "Pass a supported --build-type value, or pass --entry <path> for a Bun app.", getBuildTypeExamples("build"), "app");
90
91
  throw buildFailedError("Local app build failed", error);
91
92
  }
92
93
  }
@@ -328,13 +329,13 @@ async function runSingleAppDeploy(context, appName, options, preloadedConfig) {
328
329
  assertSupportedEntrypoint(buildType, merged.entrypoint?.value, "deploy");
329
330
  const entrypoint = await resolveDeployEntrypoint(appDir, framework, merged.entrypoint?.value, context.runtime.signal);
330
331
  if (computeConfig.target?.build) assertConfigBackedBuildSettings(buildType);
331
- const buildSettingsResolution = computeConfig.config && computeConfig.target?.build && isConfigBackedBuildType(buildType) ? await resolveConfiguredPreviewBuildSettings({
332
+ const buildSettingsResolution = computeConfig.config && computeConfig.target?.build && isConfigBackedBuildType(buildType) ? await resolveConfiguredAppBuildSettings({
332
333
  appPath: appDir,
333
334
  buildType,
334
335
  configured: computeConfig.target.build,
335
336
  configPath: computeConfig.config.configPath,
336
337
  signal: context.runtime.signal
337
- }) : await resolveInferredPreviewBuildSettings({
338
+ }) : await resolveInferredAppBuildSettings({
338
339
  appPath: appDir,
339
340
  buildType,
340
341
  signal: context.runtime.signal
@@ -348,7 +349,7 @@ async function runSingleAppDeploy(context, appName, options, preloadedConfig) {
348
349
  firstProductionDeploy: productionDeployGate.firstProductionDeploy,
349
350
  projectDir
350
351
  });
351
- const progressState = createPreviewDeployProgressState();
352
+ const progressState = createDeployProgressState();
352
353
  const deployStartedAt = Date.now();
353
354
  const deployResult = await provider.deployApp({
354
355
  cwd: appDir,
@@ -364,7 +365,7 @@ async function runSingleAppDeploy(context, appName, options, preloadedConfig) {
364
365
  envVars,
365
366
  interaction: void 0,
366
367
  signal: context.runtime.signal,
367
- progress: createPreviewDeployProgress(context.output.stderr, context.ui, !context.flags.json && !context.flags.quiet, progressState)
368
+ progress: createDeployProgress(context.output.stderr, context.ui, !context.flags.json && !context.flags.quiet, progressState)
368
369
  }).catch((error) => {
369
370
  throw appDeployFailedError(error, progressState);
370
371
  });
@@ -866,7 +867,7 @@ async function runAppPromote(context, deploymentId, appName, projectRef, configT
866
867
  appId: selectedApp.id,
867
868
  deploymentId: targetDeployment.id,
868
869
  signal: context.runtime.signal,
869
- progress: createPreviewPromoteProgress(context.output.stderr, !context.flags.json && !context.flags.quiet)
870
+ progress: createPromoteProgress(context.output.stderr, !context.flags.json && !context.flags.quiet)
870
871
  }).catch((error) => {
871
872
  throw deployFailedError("Failed to promote deployment", error, ["prisma-cli app list-deploys"]);
872
873
  });
@@ -914,7 +915,7 @@ async function runAppRollback(context, appName, deploymentId, projectRef, config
914
915
  appId: selectedApp.id,
915
916
  deploymentId: targetDeployment.id,
916
917
  signal: context.runtime.signal,
917
- progress: createPreviewPromoteProgress(context.output.stderr, !context.flags.json && !context.flags.quiet)
918
+ progress: createPromoteProgress(context.output.stderr, !context.flags.json && !context.flags.quiet)
918
919
  }).catch((error) => {
919
920
  throw deployFailedError("Failed to roll back deployment", error, ["prisma-cli app list-deploys"]);
920
921
  });
@@ -1106,7 +1107,7 @@ async function confirmDomainRemoval(context, target, hostname) {
1106
1107
  })) throw usageError("Custom domain removal canceled", "The command was canceled before the domain was detached.", "Rerun the command and confirm removal, or pass --yes.", [`prisma-cli app domain remove ${hostname} --app ${target.app.name} --yes`], "app");
1107
1108
  }
1108
1109
  function domainCommandError(command, error, hostname) {
1109
- if (error instanceof PreviewDomainApiError) {
1110
+ if (error instanceof DomainApiError) {
1110
1111
  if (command === "add" && (error.status === 400 || error.status === 422) && isDomainDnsError(error)) return domainDnsNotConfiguredError(hostname, error);
1111
1112
  if (command === "add" && error.status === 400) return new CliError({
1112
1113
  code: "DOMAIN_HOSTNAME_INVALID",
@@ -1287,7 +1288,7 @@ async function resolveDeployAppSelection(context, projectId, apps, options) {
1287
1288
  };
1288
1289
  return {
1289
1290
  appName: options.explicitAppName,
1290
- region: PREVIEW_DEFAULT_REGION,
1291
+ region: DEFAULT_REGION,
1291
1292
  displayName: options.explicitAppName,
1292
1293
  annotation: "set by --app",
1293
1294
  firstDeploy: options.firstDeploy
@@ -1316,7 +1317,7 @@ async function resolveDeployAppSelection(context, projectId, apps, options) {
1316
1317
  };
1317
1318
  return {
1318
1319
  appName: configName.value,
1319
- region: PREVIEW_DEFAULT_REGION,
1320
+ region: DEFAULT_REGION,
1320
1321
  displayName: configName.value,
1321
1322
  annotation: configName.annotation,
1322
1323
  firstDeploy: options.firstDeploy
@@ -1334,7 +1335,7 @@ async function resolveDeployAppSelection(context, projectId, apps, options) {
1334
1335
  };
1335
1336
  return {
1336
1337
  appName: inferredName.name,
1337
- region: PREVIEW_DEFAULT_REGION,
1338
+ region: DEFAULT_REGION,
1338
1339
  displayName: inferredName.name,
1339
1340
  annotation: inferredName.source === "package-name" ? "created from package.json" : "created from directory name",
1340
1341
  firstDeploy: options.firstDeploy
@@ -1366,7 +1367,7 @@ async function resolveAmbiguousDeployApp(context, matches, targetName, firstDepl
1366
1367
  if (selected === cancel) throw usageError("App selection canceled", "The command was canceled before an app was selected.", "Re-run the command and choose an app, or pass --app <name>.", ["prisma-cli app deploy --app <name>"], "app");
1367
1368
  if (selected === createNew) return {
1368
1369
  appName: targetName,
1369
- region: PREVIEW_DEFAULT_REGION,
1370
+ region: DEFAULT_REGION,
1370
1371
  displayName: targetName,
1371
1372
  annotation: "created from package.json",
1372
1373
  firstDeploy
@@ -1531,7 +1532,7 @@ async function requirePreviewAppProviderWithClient(context) {
1531
1532
  if (!client) throw authRequiredError(["prisma-cli auth login"]);
1532
1533
  return {
1533
1534
  client,
1534
- provider: createPreviewAppProvider(client, createPreviewLogAuthOptions(context.runtime.env, context.runtime.signal))
1535
+ provider: createAppProvider(client, createPreviewLogAuthOptions(context.runtime.env, context.runtime.signal))
1535
1536
  };
1536
1537
  }
1537
1538
  function createPreviewLogAuthOptions(env, signal) {
@@ -1584,13 +1585,18 @@ async function resolveProjectContext(context, client, explicitProject, options)
1584
1585
  });
1585
1586
  if (resolvedResult.isErr()) throw projectResolutionErrorToCliError(resolvedResult.error);
1586
1587
  const resolved = resolvedResult.value;
1587
- const branch = options?.branch ?? await resolveDeployBranch(context, void 0);
1588
+ const requested = options?.branch ?? await resolveDeployBranch(context, void 0);
1589
+ const remoteBranch = options?.branch ? null : await resolveReadBranch(client, {
1590
+ projectId: resolved.project.id,
1591
+ branchName: requested.name,
1592
+ signal: context.runtime.signal
1593
+ });
1588
1594
  return {
1589
1595
  ...resolved,
1590
- branch: {
1596
+ branch: remoteBranch ?? {
1591
1597
  id: null,
1592
- name: branch.name,
1593
- kind: toBranchKind(branch.name)
1598
+ name: requested.name,
1599
+ kind: toBranchKind(requested.name)
1594
1600
  }
1595
1601
  };
1596
1602
  }
@@ -2139,13 +2145,13 @@ async function readCurrentWorkspaceId(context) {
2139
2145
  function normalizeBuildType(requestedBuildType) {
2140
2146
  if (!requestedBuildType) return "auto";
2141
2147
  if (isPreviewBuildType(requestedBuildType)) return requestedBuildType;
2142
- throw usageError(`Unsupported build type "${requestedBuildType}"`, `Only ${PREVIEW_BUILD_TYPES.join(", ")} are supported in the current preview.`, "Pass a supported --build-type value.", getBuildTypeExamples("build"), "app");
2148
+ throw usageError(`Unsupported build type "${requestedBuildType}"`, `Only ${APP_BUILD_TYPES.join(", ")} are supported in the current preview.`, "Pass a supported --build-type value.", getBuildTypeExamples("build"), "app");
2143
2149
  }
2144
2150
  function isPreviewBuildType(value) {
2145
- return PREVIEW_BUILD_TYPES.includes(value);
2151
+ return APP_BUILD_TYPES.includes(value);
2146
2152
  }
2147
2153
  function getBuildTypeExamples(commandName) {
2148
- return RESOLVED_PREVIEW_BUILD_TYPES.map((buildType) => {
2154
+ return RESOLVED_APP_BUILD_TYPES.map((buildType) => {
2149
2155
  return `prisma-cli app ${commandName} --build-type ${buildType}${buildType === "bun" ? " --entry server.ts" : ""}`;
2150
2156
  });
2151
2157
  }
@@ -2389,6 +2395,7 @@ function formatBuildTypeName(buildType) {
2389
2395
  case "nextjs": return "Next.js";
2390
2396
  case "nuxt": return "Nuxt";
2391
2397
  case "astro": return "Astro";
2398
+ case "nestjs": return "NestJS";
2392
2399
  case "tanstack-start": return "TanStack Start";
2393
2400
  case "bun": return "Bun";
2394
2401
  case "auto": return "Auto";
@@ -1,11 +1,11 @@
1
1
  import { CliError, authRequiredError, featureUnavailableError, usageError, workspaceRequiredError } from "../shell/errors.js";
2
+ import { createAppProvider } from "../lib/app/app-provider.js";
2
3
  import { renderSummaryLine } from "../shell/ui.js";
3
4
  import { canPrompt } from "../shell/runtime.js";
4
5
  import { readLocalResolutionPin } from "../lib/project/local-pin.js";
5
6
  import { formatCommandArgument } from "../shell/command-arguments.js";
6
7
  import { buildProjectSetupNextActions, inferTargetName, inspectProjectBinding, projectResolutionErrorToCliError, resolveProjectTarget, sortProjects } from "../lib/project/resolution.js";
7
8
  import { bindProjectToDirectory, isValidProjectSetupName, projectCreateFailedError, projectDirectoryBindingErrorToCliError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary } from "../lib/project/setup.js";
8
- import { createPreviewAppProvider } from "../lib/app/preview-provider.js";
9
9
  import { requireComputeAuth } from "../lib/auth/guard.js";
10
10
  import { promptForProjectSetupChoice } from "../lib/project/interactive-setup.js";
11
11
  import { createCliUseCaseGateways } from "../use-cases/create-cli-gateways.js";
@@ -104,7 +104,7 @@ async function runProjectCreate(context, projectName) {
104
104
  if (!isRealMode(context)) throw featureUnavailableError("Project create is not available in fixture mode", "Creating Projects requires live platform integration.", "Rerun without fixture mode enabled to create a Project.", ["prisma-cli auth login"], "project");
105
105
  const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
106
106
  if (!client) throw authRequiredError();
107
- const provider = createPreviewAppProvider(client);
107
+ const provider = createAppProvider(client);
108
108
  const name = projectName.trim();
109
109
  const created = await provider.createProject({
110
110
  name,
@@ -136,7 +136,7 @@ async function runProjectLink(context, projectRef) {
136
136
  if (isRealMode(context)) {
137
137
  const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
138
138
  if (!client) throw authRequiredError();
139
- provider = createPreviewAppProvider(client);
139
+ provider = createAppProvider(client);
140
140
  projects = await listRealWorkspaceProjects(client, workspace, context.runtime.signal);
141
141
  } else projects = listFixtureWorkspaceProjects(context, workspace);
142
142
  let result;
@@ -0,0 +1,5 @@
1
+ import "../../shell/prompt.js";
2
+ //#region src/lib/app/app-interaction.ts
3
+ const DEFAULT_REGION = "eu-central-1";
4
+ //#endregion
5
+ export { DEFAULT_REGION };
@@ -1,22 +1,22 @@
1
+ import { createBranchDatabase, createEnvironmentVariable, deleteBranchDatabase, deleteEnvironmentVariable, listEnvironmentVariables, updateEnvironmentVariable } from "./branch-database-api.js";
2
+ import { AppBuildStrategy } from "./build.js";
1
3
  import { envVarNames } from "./env-vars.js";
2
- import { PreviewBuildStrategy } from "./preview-build.js";
3
- import { createBranchDatabase, createEnvironmentVariable, deleteBranchDatabase, deleteEnvironmentVariable, listEnvironmentVariables, updateEnvironmentVariable } from "./preview-branch-database.js";
4
4
  import path from "node:path";
5
5
  import { ApiError, CancelledError, ComputeClient, streamLogs } from "@prisma/compute-sdk";
6
- //#region src/lib/app/preview-provider.ts
7
- var PreviewDomainApiError = class extends Error {
6
+ //#region src/lib/app/app-provider.ts
7
+ var DomainApiError = class extends Error {
8
8
  status;
9
9
  code;
10
10
  hint;
11
11
  constructor(options) {
12
12
  super(`${options.summary}: ${options.message}${options.hint ? ` ${options.hint}` : ""}`);
13
- this.name = "PreviewDomainApiError";
13
+ this.name = "DomainApiError";
14
14
  this.status = options.status;
15
15
  this.code = options.code ?? null;
16
16
  this.hint = options.hint ?? null;
17
17
  }
18
18
  };
19
- function createPreviewAppProvider(client, options) {
19
+ function createAppProvider(client, options) {
20
20
  const sdk = new ComputeClient(client);
21
21
  return {
22
22
  async createProject(options) {
@@ -161,7 +161,7 @@ function createPreviewAppProvider(client, options) {
161
161
  region: options.region
162
162
  };
163
163
  const deployResult = await sdk.deploy({
164
- strategy: new PreviewBuildStrategy({
164
+ strategy: new AppBuildStrategy({
165
165
  appPath: path.resolve(options.cwd),
166
166
  entrypoint: options.entrypoint,
167
167
  buildType: options.buildType,
@@ -491,7 +491,7 @@ function apiCallError(summary, response, error) {
491
491
  return /* @__PURE__ */ new Error(`${summary}: ${message}${hint}`);
492
492
  }
493
493
  function domainApiCallError(summary, response, error) {
494
- return new PreviewDomainApiError({
494
+ return new DomainApiError({
495
495
  summary,
496
496
  status: response.status,
497
497
  code: error.error?.code ?? null,
@@ -541,4 +541,4 @@ function toAbsoluteUrl(url) {
541
541
  return url.startsWith("https://") || url.startsWith("http://") ? url : `https://${url}`;
542
542
  }
543
543
  //#endregion
544
- export { PreviewDomainApiError, createPreviewAppProvider };
544
+ export { DomainApiError, createAppProvider };
@@ -1,4 +1,4 @@
1
- //#region src/lib/app/preview-branch-database.ts
1
+ //#region src/lib/app/branch-database-api.ts
2
2
  async function createBranchDatabase(client, options) {
3
3
  const result = await client.POST("/v1/databases", {
4
4
  body: {
@@ -0,0 +1,93 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolveBuildSettings, resolveConfiguredBuildSettings } from "@prisma/compute-sdk";
4
+ //#region src/lib/app/build-settings.ts
5
+ /** Legacy build-settings file: no longer read or written, only detected for migration. */
6
+ const PRISMA_APP_CONFIG_FILENAME = "prisma.app.json";
7
+ /**
8
+ * Detects a leftover `prisma.app.json`. The file is no longer used: one that
9
+ * matches the effective settings is reported for deletion, one with custom
10
+ * values must be migrated to the compute config so builds never silently
11
+ * change.
12
+ */
13
+ async function detectLegacyBuildSettings(options) {
14
+ const configPath = path.join(options.appPath, PRISMA_APP_CONFIG_FILENAME);
15
+ let content;
16
+ try {
17
+ options.signal?.throwIfAborted();
18
+ content = await readFile(configPath, {
19
+ encoding: "utf8",
20
+ signal: options.signal
21
+ });
22
+ } catch (error) {
23
+ if (options.signal?.aborted) throw error;
24
+ return { kind: "absent" };
25
+ }
26
+ let legacy;
27
+ try {
28
+ const parsed = JSON.parse(content);
29
+ const buildCommand = parsed.buildCommand === null || typeof parsed.buildCommand === "string" ? typeof parsed.buildCommand === "string" ? parsed.buildCommand.trim() || null : null : void 0;
30
+ const outputDirectory = typeof parsed.outputDirectory === "string" ? normalizeRelativePath(parsed.outputDirectory) : void 0;
31
+ if (buildCommand === void 0 || !outputDirectory) return {
32
+ kind: "invalid",
33
+ configPath
34
+ };
35
+ legacy = {
36
+ buildCommand,
37
+ outputDirectory
38
+ };
39
+ } catch {
40
+ return {
41
+ kind: "invalid",
42
+ configPath
43
+ };
44
+ }
45
+ return legacy.buildCommand === options.effective.buildCommand && legacy.outputDirectory === options.effective.outputDirectory ? {
46
+ kind: "matching",
47
+ configPath
48
+ } : {
49
+ kind: "custom",
50
+ configPath,
51
+ ...legacy
52
+ };
53
+ }
54
+ /** Resolves build settings purely from framework inference; nothing is read or written. */
55
+ async function resolveInferredAppBuildSettings(options) {
56
+ return {
57
+ status: "inferred",
58
+ configPath: null,
59
+ relativeConfigPath: null,
60
+ settings: await resolveBuildSettings(options)
61
+ };
62
+ }
63
+ /**
64
+ * Resolves build settings when the compute config owns them: configured
65
+ * fields win, omitted fields fall back to framework defaults.
66
+ */
67
+ async function resolveConfiguredAppBuildSettings(options) {
68
+ const configFilename = path.basename(options.configPath);
69
+ const settings = await resolveConfiguredBuildSettings({
70
+ appPath: options.appPath,
71
+ buildType: options.buildType,
72
+ configured: options.configured,
73
+ source: `set by ${configFilename}`,
74
+ signal: options.signal
75
+ });
76
+ return {
77
+ status: "config",
78
+ configPath: options.configPath,
79
+ relativeConfigPath: configFilename,
80
+ settings
81
+ };
82
+ }
83
+ function normalizeRelativePath(value) {
84
+ const raw = value.trim().replace(/\\/g, "/");
85
+ if (raw.length === 0 || raw.split("/").includes("..")) return;
86
+ if (/^[A-Za-z]:/.test(raw)) return;
87
+ const normalized = path.posix.normalize(raw);
88
+ const segments = normalized.split("/");
89
+ if (path.win32.isAbsolute(value) || path.posix.isAbsolute(normalized) || segments.includes("..")) return;
90
+ return normalized === "." ? "." : normalized;
91
+ }
92
+ //#endregion
93
+ export { PRISMA_APP_CONFIG_FILENAME, detectLegacyBuildSettings, resolveConfiguredAppBuildSettings, resolveInferredAppBuildSettings };
@@ -0,0 +1,80 @@
1
+ import "./build-settings.js";
2
+ import "node:fs/promises";
3
+ import "node:path";
4
+ import { normalizeArtifactSymlinks, resolveBuildStrategy } from "@prisma/compute-sdk";
5
+ //#region src/lib/app/build.ts
6
+ const APP_BUILD_TYPES = [
7
+ "auto",
8
+ "bun",
9
+ "nextjs",
10
+ "nuxt",
11
+ "astro",
12
+ "nestjs",
13
+ "tanstack-start"
14
+ ];
15
+ const RESOLVED_APP_BUILD_TYPES = APP_BUILD_TYPES.filter((buildType) => buildType !== "auto");
16
+ var AppBuildStrategy = class {
17
+ #appPath;
18
+ #entrypoint;
19
+ #buildType;
20
+ #signal;
21
+ #buildSettings;
22
+ constructor(options) {
23
+ this.#appPath = options.appPath;
24
+ this.#entrypoint = options.entrypoint;
25
+ this.#buildType = options.buildType ?? "auto";
26
+ this.#signal = options.signal;
27
+ this.#buildSettings = options.buildSettings;
28
+ }
29
+ async canBuild(signal = this.#signal) {
30
+ const { strategy } = await resolveAppBuildStrategy({
31
+ appPath: this.#appPath,
32
+ entrypoint: this.#entrypoint,
33
+ buildType: this.#buildType,
34
+ signal,
35
+ buildSettings: this.#buildSettings
36
+ });
37
+ return strategy.canBuild(signal);
38
+ }
39
+ async execute(signal = this.#signal) {
40
+ const { artifact } = await executeAppBuild({
41
+ appPath: this.#appPath,
42
+ entrypoint: this.#entrypoint,
43
+ buildType: this.#buildType,
44
+ signal,
45
+ buildSettings: this.#buildSettings
46
+ });
47
+ return artifact;
48
+ }
49
+ };
50
+ async function executeAppBuild(options) {
51
+ const { strategy, buildType } = await resolveAppBuildStrategy({
52
+ appPath: options.appPath,
53
+ entrypoint: options.entrypoint,
54
+ buildType: options.buildType ?? "auto",
55
+ signal: options.signal,
56
+ buildSettings: options.buildSettings
57
+ });
58
+ const artifact = await strategy.execute(options.signal);
59
+ try {
60
+ await normalizeArtifactSymlinks(artifact.directory, options.appPath, options.signal);
61
+ return {
62
+ artifact,
63
+ buildType
64
+ };
65
+ } catch (error) {
66
+ await artifact.cleanup?.().catch(() => void 0);
67
+ throw error;
68
+ }
69
+ }
70
+ async function resolveAppBuildStrategy(options) {
71
+ return resolveBuildStrategy({
72
+ appPath: options.appPath,
73
+ buildType: options.buildType,
74
+ entrypoint: options.entrypoint,
75
+ buildSettings: options.buildSettings,
76
+ signal: options.signal
77
+ });
78
+ }
79
+ //#endregion
80
+ export { APP_BUILD_TYPES, AppBuildStrategy, RESOLVED_APP_BUILD_TYPES, executeAppBuild };
@@ -21,13 +21,12 @@ async function readBunPackageJson(appPath, signal) {
21
21
  }
22
22
  }
23
23
  function readBunPackageEntrypoint(packageJson) {
24
- if (typeof packageJson?.main === "string") return packageJson.main;
25
- if (typeof packageJson?.module === "string") return packageJson.module;
24
+ return typeof packageJson?.main === "string" ? packageJson.main : void 0;
26
25
  }
27
26
  async function resolveBunEntrypoint(appPath, explicitEntrypoint, signal) {
28
27
  const packageJson = await readBunPackageJson(appPath, signal);
29
28
  const candidate = explicitEntrypoint ?? readBunPackageEntrypoint(packageJson);
30
- if (!candidate) throw new Error("Entrypoint is required. Pass --entry or define package.json main or module.");
29
+ if (!candidate) throw new Error("Entrypoint is required. Pass --entry or define package.json main.");
31
30
  if (path.isAbsolute(candidate)) throw new Error("Entrypoint must be a relative path.");
32
31
  const normalized = path.normalize(candidate);
33
32
  if (normalized.startsWith("..") || path.isAbsolute(normalized) || normalized.includes(`${path.sep}..${path.sep}`)) throw new Error("Entrypoint must not escape the app directory.");
@@ -1,6 +1,6 @@
1
1
  import { renderDeployOutputRows } from "./deploy-output.js";
2
- //#region src/lib/app/preview-progress.ts
3
- function createPreviewDeployProgressState() {
2
+ //#region src/lib/app/deploy-progress.ts
3
+ function createDeployProgressState() {
4
4
  return {
5
5
  buildStarted: false,
6
6
  buildCompleted: false,
@@ -13,7 +13,7 @@ function createPreviewDeployProgressState() {
13
13
  promotedUrl: null
14
14
  };
15
15
  }
16
- function createPreviewDeployProgress(output, ui, enabled, state = createPreviewDeployProgressState()) {
16
+ function createDeployProgress(output, ui, enabled, state = createDeployProgressState()) {
17
17
  const write = (line) => {
18
18
  if (!enabled) return;
19
19
  output.write(`${line}\n`);
@@ -63,7 +63,7 @@ function createPreviewDeployProgress(output, ui, enabled, state = createPreviewD
63
63
  function formatArtifactSize(byteLength) {
64
64
  return `${(byteLength / 1024 / 1024).toFixed(1)} MB`;
65
65
  }
66
- function createPreviewPromoteProgress(output, enabled) {
66
+ function createPromoteProgress(output, enabled) {
67
67
  if (!enabled) return;
68
68
  const write = (line) => {
69
69
  output.write(`${line}\n`);
@@ -97,4 +97,4 @@ function createPreviewPromoteProgress(output, enabled) {
97
97
  };
98
98
  }
99
99
  //#endregion
100
- export { createPreviewDeployProgress, createPreviewDeployProgressState, createPreviewPromoteProgress };
100
+ export { createDeployProgress, createDeployProgressState, createPromoteProgress };
@@ -0,0 +1,30 @@
1
+ //#region src/lib/app/read-branch.ts
2
+ /**
3
+ * Resolves the branch an app management command should read from, without ever
4
+ * creating one. Returns the branch whose `gitName` matches `branchName`, else
5
+ * the project's default branch, else null when the project has no branches.
6
+ */
7
+ async function resolveReadBranch(client, options) {
8
+ const branches = [];
9
+ let cursor;
10
+ do {
11
+ const result = await client.GET("/v1/projects/{projectId}/branches", {
12
+ params: {
13
+ path: { projectId: options.projectId },
14
+ query: { cursor }
15
+ },
16
+ signal: options.signal
17
+ });
18
+ if (result.error || !result.data) throw new Error(`Failed to list branches for project ${options.projectId}: ${JSON.stringify(result.error)}`);
19
+ branches.push(...result.data.data);
20
+ cursor = result.data.pagination.hasMore ? result.data.pagination.nextCursor ?? void 0 : void 0;
21
+ } while (cursor);
22
+ const chosen = branches.find((branch) => branch.gitName === options.branchName) ?? branches.find((branch) => branch.isDefault) ?? null;
23
+ return chosen ? {
24
+ id: chosen.id,
25
+ name: chosen.gitName,
26
+ kind: chosen.role
27
+ } : null;
28
+ }
29
+ //#endregion
30
+ export { resolveReadBranch };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/cli",
3
- "version": "3.0.0-dev.88.1",
3
+ "version": "3.0.0-dev.91.1",
4
4
  "description": "Command-line interface for the Prisma Developer Platform.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@clack/prompts": "^1.5.0",
47
- "@prisma/compute-sdk": "^0.23.0",
47
+ "@prisma/compute-sdk": "^0.28.0",
48
48
  "@prisma/credentials-store": "^7.8.0",
49
49
  "@prisma/management-api-sdk": "^1.37.0",
50
50
  "better-result": "^2.9.2",