@prisma/compute-sdk 0.28.0 → 0.30.0

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.
Files changed (106) hide show
  1. package/dist/api-client.d.ts +38 -38
  2. package/dist/api-client.d.ts.map +1 -1
  3. package/dist/api-client.js +44 -43
  4. package/dist/api-client.js.map +1 -1
  5. package/dist/astro-build.d.ts +2 -0
  6. package/dist/astro-build.d.ts.map +1 -1
  7. package/dist/astro-build.js +31 -39
  8. package/dist/astro-build.js.map +1 -1
  9. package/dist/build-settings.d.ts +3 -0
  10. package/dist/build-settings.d.ts.map +1 -1
  11. package/dist/build-settings.js +13 -0
  12. package/dist/build-settings.js.map +1 -1
  13. package/dist/build-strategy.d.ts +20 -0
  14. package/dist/build-strategy.d.ts.map +1 -1
  15. package/dist/build-strategy.js +33 -1
  16. package/dist/build-strategy.js.map +1 -1
  17. package/dist/build.d.ts +2 -1
  18. package/dist/build.d.ts.map +1 -1
  19. package/dist/build.js +16 -4
  20. package/dist/build.js.map +1 -1
  21. package/dist/bun-build.d.ts +1 -1
  22. package/dist/bun-build.d.ts.map +1 -1
  23. package/dist/bun-build.js +25 -9
  24. package/dist/bun-build.js.map +1 -1
  25. package/dist/callbacks.d.ts +33 -33
  26. package/dist/callbacks.d.ts.map +1 -1
  27. package/dist/compute-client.d.ts +66 -66
  28. package/dist/compute-client.d.ts.map +1 -1
  29. package/dist/compute-client.js +274 -272
  30. package/dist/compute-client.js.map +1 -1
  31. package/dist/config/frameworks.d.ts +4 -8
  32. package/dist/config/frameworks.d.ts.map +1 -1
  33. package/dist/config/frameworks.js +17 -5
  34. package/dist/config/frameworks.js.map +1 -1
  35. package/dist/config/normalize.d.ts +6 -0
  36. package/dist/config/normalize.d.ts.map +1 -1
  37. package/dist/config/normalize.js +53 -12
  38. package/dist/config/normalize.js.map +1 -1
  39. package/dist/config/types.d.ts +3 -1
  40. package/dist/config/types.d.ts.map +1 -1
  41. package/dist/config/types.js +1 -0
  42. package/dist/config/types.js.map +1 -1
  43. package/dist/configured-artifact.d.ts +20 -0
  44. package/dist/configured-artifact.d.ts.map +1 -0
  45. package/dist/configured-artifact.js +104 -0
  46. package/dist/configured-artifact.js.map +1 -0
  47. package/dist/custom-build.d.ts +20 -0
  48. package/dist/custom-build.d.ts.map +1 -0
  49. package/dist/custom-build.js +53 -0
  50. package/dist/custom-build.js.map +1 -0
  51. package/dist/errors.d.ts +28 -28
  52. package/dist/errors.d.ts.map +1 -1
  53. package/dist/errors.js +12 -12
  54. package/dist/errors.js.map +1 -1
  55. package/dist/index.d.ts +6 -5
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +2 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/log-stream.d.ts +1 -1
  60. package/dist/log-stream.d.ts.map +1 -1
  61. package/dist/log-stream.js +1 -1
  62. package/dist/log-stream.js.map +1 -1
  63. package/dist/nestjs-build.d.ts.map +1 -1
  64. package/dist/nestjs-build.js +28 -29
  65. package/dist/nestjs-build.js.map +1 -1
  66. package/dist/nextjs-build.d.ts +1 -1
  67. package/dist/nextjs-build.d.ts.map +1 -1
  68. package/dist/nextjs-build.js +25 -14
  69. package/dist/nextjs-build.js.map +1 -1
  70. package/dist/nuxt-build.d.ts +2 -0
  71. package/dist/nuxt-build.d.ts.map +1 -1
  72. package/dist/nuxt-build.js +31 -39
  73. package/dist/nuxt-build.js.map +1 -1
  74. package/dist/polling.d.ts +4 -4
  75. package/dist/polling.d.ts.map +1 -1
  76. package/dist/polling.js +15 -15
  77. package/dist/polling.js.map +1 -1
  78. package/dist/tanstack-start-build.d.ts +1 -1
  79. package/dist/tanstack-start-build.d.ts.map +1 -1
  80. package/dist/tanstack-start-build.js +26 -47
  81. package/dist/tanstack-start-build.js.map +1 -1
  82. package/dist/types.d.ts +8 -8
  83. package/dist/types.d.ts.map +1 -1
  84. package/package.json +2 -2
  85. package/src/api-client.ts +57 -63
  86. package/src/astro-build.ts +39 -46
  87. package/src/build-settings.ts +16 -0
  88. package/src/build-strategy.ts +56 -1
  89. package/src/build.ts +16 -4
  90. package/src/bun-build.ts +39 -10
  91. package/src/callbacks.ts +34 -34
  92. package/src/compute-client.ts +433 -413
  93. package/src/config/frameworks.ts +18 -5
  94. package/src/config/normalize.ts +74 -13
  95. package/src/config/types.ts +3 -0
  96. package/src/configured-artifact.ts +169 -0
  97. package/src/custom-build.ts +73 -0
  98. package/src/errors.ts +42 -38
  99. package/src/index.ts +27 -26
  100. package/src/log-stream.ts +2 -2
  101. package/src/nestjs-build.ts +36 -33
  102. package/src/nextjs-build.ts +31 -14
  103. package/src/nuxt-build.ts +39 -46
  104. package/src/polling.ts +19 -18
  105. package/src/tanstack-start-build.ts +31 -53
  106. package/src/types.ts +8 -8
@@ -13,6 +13,7 @@ export type FrameworkBuildType =
13
13
  | "astro"
14
14
  | "nestjs"
15
15
  | "tanstack-start"
16
+ | "custom"
16
17
  | "bun";
17
18
 
18
19
  export interface FrameworkDescriptor {
@@ -138,6 +139,18 @@ export const FRAMEWORKS: readonly FrameworkDescriptor[] = [
138
139
  hasLocalDevServer: false,
139
140
  defaultHttpPort: 3000,
140
141
  },
142
+ {
143
+ key: "custom",
144
+ displayName: "Custom",
145
+ buildType: "custom",
146
+ aliases: ["custom"],
147
+ detectPackages: [],
148
+ detectConfigFiles: [],
149
+ usesEntrypoint: false,
150
+ defaultEntrypoint: null,
151
+ hasLocalDevServer: false,
152
+ defaultHttpPort: 3000,
153
+ },
141
154
  {
142
155
  key: "bun",
143
156
  displayName: "Bun",
@@ -154,14 +167,14 @@ export const FRAMEWORKS: readonly FrameworkDescriptor[] = [
154
167
 
155
168
  export const FRAMEWORK_KEYS = FRAMEWORKS.map((framework) => framework.key);
156
169
 
157
- /**
158
- * Build types whose preview build consumes committed build settings. The
159
- * others (nuxt, astro) run their framework CLI and stage fixed output, so a
160
- * config `build` block has nothing to apply to.
161
- */
170
+ /** Build types whose preview build consumes committed build settings. */
162
171
  export const CONFIG_BACKED_BUILD_TYPES = [
163
172
  "nextjs",
173
+ "nuxt",
174
+ "astro",
175
+ "nestjs",
164
176
  "tanstack-start",
177
+ "custom",
165
178
  "bun",
166
179
  ] as const satisfies readonly FrameworkBuildType[];
167
180
 
@@ -2,7 +2,7 @@ import path from "node:path";
2
2
 
3
3
  import { Result, TaggedError } from "better-result";
4
4
 
5
- import { frameworkByKey, isConfigBackedBuildType } from "./frameworks.ts";
5
+ import { frameworkByKey } from "./frameworks.ts";
6
6
  import { COMPUTE_FRAMEWORKS, type ComputeFramework } from "./types.ts";
7
7
 
8
8
  export interface ComputeDeployTargetBuild {
@@ -10,6 +10,11 @@ export interface ComputeDeployTargetBuild {
10
10
  command: string | null | undefined;
11
11
  /** Normalized output path relative to the app root, undefined when not configured. */
12
12
  outputDirectory: string | undefined;
13
+ /**
14
+ * Normalized configured entrypoint. With outputDirectory it is relative to
15
+ * that output directory; otherwise it is relative to the app root.
16
+ */
17
+ entrypoint: string | undefined;
13
18
  }
14
19
 
15
20
  export interface ComputeDeployTarget {
@@ -19,6 +24,7 @@ export interface ComputeDeployTarget {
19
24
  /** Normalized app directory relative to the config file, or null for the config directory. */
20
25
  root: string | null;
21
26
  framework: ComputeFramework | null;
27
+ /** Runtime/source entrypoint normalized from `entry` or an entrypoint-backed `build.entrypoint`. */
22
28
  entry: string | null;
23
29
  httpPort: number | null;
24
30
  /** Env inputs in deploy order: dotenv file paths first, then NAME=VALUE assignments. */
@@ -104,7 +110,7 @@ const KNOWN_APP_KEYS = [
104
110
  "build",
105
111
  ] as const;
106
112
  const KNOWN_ENV_KEYS = ["file", "vars"] as const;
107
- const KNOWN_BUILD_KEYS = ["command", "outputDirectory"] as const;
113
+ const KNOWN_BUILD_KEYS = ["command", "outputDirectory", "entrypoint"] as const;
108
114
 
109
115
  /**
110
116
  * Validates and normalizes a config module's default export. Reports every
@@ -343,7 +349,8 @@ function normalizeAppEntry(
343
349
  }
344
350
  }
345
351
 
346
- if (entry && framework && !frameworkByKey(framework).usesEntrypoint) {
352
+ const frameworkDescriptor = framework ? frameworkByKey(framework) : null;
353
+ if (entry && frameworkDescriptor && !frameworkDescriptor.usesEntrypoint) {
347
354
  issues.push(
348
355
  `\`${label}.entry\` is not supported with the ${framework} framework; it derives its entrypoint from build output.`,
349
356
  );
@@ -367,22 +374,53 @@ function normalizeAppEntry(
367
374
 
368
375
  const envInputs = normalizeEnvConfig(value.env, `${label}.env`, issues);
369
376
  const build = normalizeBuildConfig(value.build, `${label}.build`, issues);
377
+ if (framework === "custom") {
378
+ if (!build) {
379
+ issues.push(
380
+ `\`${label}.build\` is required with the custom framework and must set \`outputDirectory\` and \`entrypoint\`.`,
381
+ );
382
+ } else {
383
+ if (!build.outputDirectory) {
384
+ issues.push(
385
+ `\`${label}.build.outputDirectory\` is required with the custom framework.`,
386
+ );
387
+ }
388
+ if (!build.entrypoint) {
389
+ issues.push(
390
+ `\`${label}.build.entrypoint\` is required with the custom framework.`,
391
+ );
392
+ }
393
+ }
394
+ } else if (
395
+ build?.outputDirectory &&
396
+ build.outputDirectory !== "." &&
397
+ !build.entrypoint &&
398
+ frameworkDescriptor?.usesEntrypoint
399
+ ) {
400
+ issues.push(
401
+ `\`${label}.build.entrypoint\` is required when \`${label}.build.outputDirectory\` is set with the ${framework} framework.`,
402
+ );
403
+ }
370
404
  if (
371
- build &&
372
- framework &&
373
- !isConfigBackedBuildType(frameworkByKey(framework).buildType)
405
+ entry &&
406
+ build?.entrypoint &&
407
+ frameworkDescriptor?.usesEntrypoint &&
408
+ entry !== build.entrypoint
374
409
  ) {
375
410
  issues.push(
376
- `\`${label}.build\` is not supported with the ${framework} framework; its build runs automatically during deploy.`,
411
+ `\`${label}.entry\` and \`${label}.build.entrypoint\` both configure the runtime entrypoint; set only one, or make them match.`,
377
412
  );
378
413
  }
379
-
380
414
  return {
381
415
  key,
382
416
  name,
383
417
  root,
384
418
  framework,
385
- entry,
419
+ entry:
420
+ entry ??
421
+ (frameworkDescriptor?.usesEntrypoint || !frameworkDescriptor
422
+ ? (build?.entrypoint ?? null)
423
+ : null),
386
424
  httpPort,
387
425
  envInputs,
388
426
  build,
@@ -400,7 +438,7 @@ function normalizeBuildConfig(
400
438
 
401
439
  if (!isPlainObject(value)) {
402
440
  issues.push(
403
- `\`${label}\` must be an object with \`command\` and/or \`outputDirectory\`.`,
441
+ `\`${label}\` must be an object with \`command\`, \`outputDirectory\`, and/or \`entrypoint\`.`,
404
442
  );
405
443
  return null;
406
444
  }
@@ -444,14 +482,37 @@ function normalizeBuildConfig(
444
482
  }
445
483
  }
446
484
 
447
- if (command === undefined && outputDirectory === undefined) {
485
+ let entrypoint: string | undefined;
486
+ if (value.entrypoint !== undefined) {
487
+ const normalized =
488
+ typeof value.entrypoint === "string"
489
+ ? normalizeRelativePath(value.entrypoint)
490
+ : undefined;
491
+ if (!normalized) {
492
+ issues.push(
493
+ `\`${label}.entrypoint\` must be a relative path that stays inside its base directory.`,
494
+ );
495
+ } else if (normalized === ".") {
496
+ issues.push(
497
+ `\`${label}.entrypoint\` must be a relative file path inside its base directory.`,
498
+ );
499
+ } else {
500
+ entrypoint = normalized;
501
+ }
502
+ }
503
+
504
+ if (
505
+ command === undefined &&
506
+ outputDirectory === undefined &&
507
+ entrypoint === undefined
508
+ ) {
448
509
  issues.push(
449
- `\`${label}\` must set \`command\` and/or \`outputDirectory\`.`,
510
+ `\`${label}\` must set \`command\`, \`outputDirectory\`, and/or \`entrypoint\`.`,
450
511
  );
451
512
  return null;
452
513
  }
453
514
 
454
- return { command, outputDirectory };
515
+ return { command, outputDirectory, entrypoint };
455
516
  }
456
517
 
457
518
  function normalizeEnvConfig(
@@ -13,6 +13,7 @@ export const COMPUTE_FRAMEWORKS = [
13
13
  "hono",
14
14
  "nestjs",
15
15
  "tanstack-start",
16
+ "custom",
16
17
  "bun",
17
18
  ] as const;
18
19
 
@@ -34,6 +35,8 @@ export interface ComputeBuildConfig {
34
35
  command?: string | null;
35
36
  /** Framework output path relative to the app root, e.g. ".next/standalone". */
36
37
  outputDirectory?: string;
38
+ /** Entrypoint for the built artifact, relative to `outputDirectory` when one is set. */
39
+ entrypoint?: string;
37
40
  }
38
41
 
39
42
  export interface ComputeAppConfig {
@@ -0,0 +1,169 @@
1
+ import { cp, mkdtemp, realpath, rm, stat } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+
5
+ import { normalizeArtifactSymlinks } from "./artifact-postprocess.ts";
6
+ import type { BuildArtifact } from "./build-strategy.ts";
7
+ import {
8
+ defaultHttpPortForBuildType,
9
+ type FrameworkBuildType,
10
+ } from "./config/frameworks.ts";
11
+
12
+ export async function stageConfiguredArtifact(options: {
13
+ appPath: string;
14
+ outputDirectory: string;
15
+ entrypoint: string;
16
+ buildType: FrameworkBuildType;
17
+ label: string;
18
+ missingEntrypointMessage?: string;
19
+ signal?: AbortSignal;
20
+ }): Promise<BuildArtifact> {
21
+ options.signal?.throwIfAborted();
22
+ const outputDir = resolvePathInside(
23
+ options.appPath,
24
+ options.outputDirectory,
25
+ `${options.label} build output directory must be a relative path inside the app directory`,
26
+ );
27
+ const outputStat = await stat(outputDir).catch(() => null);
28
+ if (!outputStat?.isDirectory()) {
29
+ throw new Error(
30
+ `${options.label} build output directory does not exist: ${options.outputDirectory}`,
31
+ );
32
+ }
33
+
34
+ const [realAppPath, realOutputDir] = await Promise.all([
35
+ realpath(path.resolve(options.appPath)),
36
+ realpath(outputDir),
37
+ ]);
38
+ if (!isPathWithin(realAppPath, realOutputDir)) {
39
+ throw new Error(
40
+ `${options.label} build output directory must stay inside the app directory`,
41
+ );
42
+ }
43
+
44
+ const entrypoint = await resolveConfiguredArtifactEntrypoint({
45
+ directory: realOutputDir,
46
+ entrypoint: options.entrypoint,
47
+ label: options.label,
48
+ displayDirectory: options.outputDirectory,
49
+ missingEntrypointMessage: options.missingEntrypointMessage,
50
+ });
51
+
52
+ const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
53
+ try {
54
+ const artifactDir = path.join(outDir, "app");
55
+ await cp(realOutputDir, artifactDir, {
56
+ recursive: true,
57
+ verbatimSymlinks: true,
58
+ });
59
+ await normalizeArtifactSymlinks(
60
+ artifactDir,
61
+ options.appPath,
62
+ options.signal,
63
+ );
64
+
65
+ return {
66
+ directory: artifactDir,
67
+ entrypoint,
68
+ defaultPortMapping: {
69
+ http: defaultHttpPortForBuildType(options.buildType),
70
+ },
71
+ cleanup: () => rm(outDir, { recursive: true, force: true }),
72
+ };
73
+ } catch (error) {
74
+ await rm(outDir, { recursive: true, force: true });
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ export async function resolveConfiguredArtifactEntrypoint(options: {
80
+ directory: string;
81
+ entrypoint: string;
82
+ label: string;
83
+ displayDirectory?: string;
84
+ missingEntrypointMessage?: string;
85
+ }): Promise<string> {
86
+ const entrypoint = normalizeConfiguredArtifactEntrypoint(
87
+ options.entrypoint,
88
+ options.label,
89
+ );
90
+ const entryPath = path.join(options.directory, entrypoint);
91
+ const entryStat = await stat(entryPath).catch(() => null);
92
+ if (!entryStat?.isFile()) {
93
+ if (options.missingEntrypointMessage) {
94
+ throw new Error(options.missingEntrypointMessage);
95
+ }
96
+ const directory = options.displayDirectory ?? options.directory;
97
+ throw new Error(
98
+ `${options.label} build entrypoint does not exist: ${directory}/${entrypoint}`,
99
+ );
100
+ }
101
+ return entrypoint;
102
+ }
103
+
104
+ export function normalizeConfiguredArtifactEntrypoint(
105
+ entrypoint: string,
106
+ label: string,
107
+ ): string {
108
+ const normalized = path.posix.normalize(
109
+ entrypoint.trim().replace(/\\/g, "/"),
110
+ );
111
+ if (
112
+ normalized.length === 0 ||
113
+ normalized === "." ||
114
+ normalized === ".." ||
115
+ normalized.startsWith("../") ||
116
+ normalized.includes("/../") ||
117
+ path.win32.isAbsolute(entrypoint) ||
118
+ path.posix.isAbsolute(normalized) ||
119
+ /^[A-Za-z]:/.test(normalized)
120
+ ) {
121
+ throw new Error(
122
+ `${label} build entrypoint must be a relative path inside the output directory`,
123
+ );
124
+ }
125
+
126
+ return normalized;
127
+ }
128
+
129
+ function resolvePathInside(
130
+ root: string,
131
+ relativePath: string,
132
+ errorMessage: string,
133
+ ): string {
134
+ const raw = relativePath.trim().replace(/\\/g, "/");
135
+ const normalized = path.posix.normalize(raw);
136
+ if (
137
+ raw.length === 0 ||
138
+ normalized === ".." ||
139
+ normalized.startsWith("../") ||
140
+ normalized.includes("/../") ||
141
+ path.win32.isAbsolute(relativePath) ||
142
+ path.posix.isAbsolute(normalized) ||
143
+ /^[A-Za-z]:/.test(normalized)
144
+ ) {
145
+ throw new Error(errorMessage);
146
+ }
147
+
148
+ const resolved = path.resolve(root, normalized);
149
+ const relative = path.relative(root, resolved);
150
+ if (
151
+ relative === ".." ||
152
+ relative.startsWith(`..${path.sep}`) ||
153
+ path.isAbsolute(relative)
154
+ ) {
155
+ throw new Error(errorMessage);
156
+ }
157
+
158
+ return resolved;
159
+ }
160
+
161
+ function isPathWithin(root: string, candidate: string): boolean {
162
+ const relative = path.relative(root, candidate);
163
+ return (
164
+ relative === "" ||
165
+ (!relative.startsWith(`..${path.sep}`) &&
166
+ relative !== ".." &&
167
+ !path.isAbsolute(relative))
168
+ );
169
+ }
@@ -0,0 +1,73 @@
1
+ import { type BuildSettings, resolveBuildSettings } from "./build-settings.ts";
2
+ import {
3
+ type BuildArtifact,
4
+ type BuildStrategy,
5
+ runBuildSettingsCommand,
6
+ } from "./build-strategy.ts";
7
+ import {
8
+ normalizeConfiguredArtifactEntrypoint,
9
+ stageConfiguredArtifact,
10
+ } from "./configured-artifact.ts";
11
+ import type { BuildCommandIo } from "./workspace.ts";
12
+
13
+ /**
14
+ * Generic artifact strategy for frameworks the SDK does not know about yet.
15
+ * Runs an optional command, stages a configured output directory as-is, and
16
+ * starts the configured entrypoint from inside that artifact.
17
+ */
18
+ export class CustomBuild implements BuildStrategy {
19
+ readonly #appPath: string;
20
+ readonly #entrypoint?: string;
21
+ readonly #buildSettings?: BuildSettings;
22
+ readonly #io?: BuildCommandIo;
23
+
24
+ constructor(options: {
25
+ appPath: string;
26
+ entrypoint?: string;
27
+ buildSettings?: BuildSettings;
28
+ io?: BuildCommandIo;
29
+ }) {
30
+ this.#appPath = options.appPath;
31
+ this.#entrypoint = options.entrypoint;
32
+ this.#buildSettings = options.buildSettings;
33
+ this.#io = options.io;
34
+ }
35
+
36
+ async canBuild(_signal?: AbortSignal): Promise<boolean> {
37
+ return Boolean(this.#entrypoint ?? this.#buildSettings?.entrypoint);
38
+ }
39
+
40
+ async execute(signal?: AbortSignal): Promise<BuildArtifact> {
41
+ signal?.throwIfAborted();
42
+ const settings =
43
+ this.#buildSettings ??
44
+ (await resolveBuildSettings({
45
+ appPath: this.#appPath,
46
+ buildType: "custom",
47
+ signal,
48
+ }));
49
+
50
+ const entrypoint = this.#entrypoint ?? settings.entrypoint;
51
+ if (!entrypoint) {
52
+ throw new Error("Custom build entrypoint is required");
53
+ }
54
+ normalizeConfiguredArtifactEntrypoint(entrypoint, "Custom");
55
+
56
+ await runBuildSettingsCommand({
57
+ appPath: this.#appPath,
58
+ settings,
59
+ failurePrefix: "Custom",
60
+ io: this.#io,
61
+ signal,
62
+ });
63
+
64
+ return stageConfiguredArtifact({
65
+ appPath: this.#appPath,
66
+ outputDirectory: settings.outputDirectory,
67
+ entrypoint,
68
+ buildType: "custom",
69
+ label: "Custom",
70
+ signal,
71
+ });
72
+ }
73
+ }
package/src/errors.ts CHANGED
@@ -37,57 +37,61 @@ export class ArtifactError extends TaggedError("ArtifactError")<{
37
37
  }>() {}
38
38
 
39
39
  export class TimeoutError extends TaggedError("TimeoutError")<{
40
- versionId: string;
40
+ deploymentId: string;
41
41
  elapsedMs: number;
42
42
  lastStatus: string;
43
43
  message: string;
44
44
  }>() {
45
45
  constructor(args: {
46
- versionId: string;
46
+ deploymentId: string;
47
47
  elapsedMs: number;
48
48
  lastStatus: string;
49
49
  }) {
50
50
  super({
51
51
  ...args,
52
- message: `Timed out waiting for version ${args.versionId} to reach target state (last status: ${args.lastStatus}, elapsed: ${Math.round(args.elapsedMs / 1000)}s)`,
52
+ message: `Timed out waiting for deployment ${args.deploymentId} to reach target state (last status: ${args.lastStatus}, elapsed: ${Math.round(args.elapsedMs / 1000)}s)`,
53
53
  });
54
54
  }
55
55
  }
56
56
 
57
- export class VersionFailedError extends TaggedError("VersionFailedError")<{
58
- versionId: string;
57
+ export class DeploymentFailedError extends TaggedError(
58
+ "DeploymentFailedError",
59
+ )<{
60
+ deploymentId: string;
59
61
  message: string;
60
62
  }>() {
61
- constructor(args: { versionId: string }) {
63
+ constructor(args: { deploymentId: string }) {
62
64
  super({
63
- versionId: args.versionId,
64
- message: `Version ${args.versionId} transitioned to failed status`,
65
+ deploymentId: args.deploymentId,
66
+ message: `Deployment ${args.deploymentId} transitioned to failed status`,
65
67
  });
66
68
  }
67
69
  }
68
70
 
69
- export class NoExistingVersionError extends TaggedError(
70
- "NoExistingVersionError",
71
+ export class NoExistingDeploymentError extends TaggedError(
72
+ "NoExistingDeploymentError",
71
73
  )<{
72
- serviceId: string;
74
+ appId: string;
73
75
  message: string;
74
76
  }>() {
75
- constructor(args: { serviceId: string }) {
77
+ constructor(args: { appId: string }) {
76
78
  super({
77
- serviceId: args.serviceId,
78
- message: `Service ${args.serviceId} has no existing versions. Environment-only updates require at least one prior deployment.`,
79
+ appId: args.appId,
80
+ message: `App ${args.appId} has no existing deployments. Environment-only updates require at least one prior deployment.`,
79
81
  });
80
82
  }
81
83
  }
82
84
 
83
- export class NoVersionsFoundError extends TaggedError("NoVersionsFoundError")<{
84
- serviceId: string;
85
+ export class NoDeploymentsFoundError extends TaggedError(
86
+ "NoDeploymentsFoundError",
87
+ )<{
88
+ appId: string;
85
89
  message: string;
86
90
  }>() {
87
- constructor(args: { serviceId: string }) {
91
+ constructor(args: { appId: string }) {
88
92
  super({
89
- serviceId: args.serviceId,
90
- message: `Service ${args.serviceId} has no versions`,
93
+ appId: args.appId,
94
+ message: `App ${args.appId} has no deployments`,
91
95
  });
92
96
  }
93
97
  }
@@ -104,19 +108,19 @@ export class DestroyAggregateError extends TaggedError(
104
108
  "DestroyAggregateError",
105
109
  )<{
106
110
  message: string;
107
- succeededVersionIds: string[];
108
- failures: Array<{ versionId: string; error: VersionOperationError }>;
109
- serviceDeleted: boolean;
111
+ succeededDeploymentIds: string[];
112
+ failures: Array<{ deploymentId: string; error: DeploymentOperationError }>;
113
+ appDeleted: boolean;
110
114
  }>() {
111
115
  constructor(args: {
112
- succeededVersionIds: string[];
113
- failures: Array<{ versionId: string; error: VersionOperationError }>;
114
- serviceDeleted: boolean;
116
+ succeededDeploymentIds: string[];
117
+ failures: Array<{ deploymentId: string; error: DeploymentOperationError }>;
118
+ appDeleted: boolean;
115
119
  }) {
116
- const failedIds = args.failures.map((f) => f.versionId).join(", ");
120
+ const failedIds = args.failures.map((f) => f.deploymentId).join(", ");
117
121
  super({
118
122
  ...args,
119
- message: `Failed to destroy ${args.failures.length} version(s): ${failedIds}`,
123
+ message: `Failed to destroy ${args.failures.length} deployment(s): ${failedIds}`,
120
124
  });
121
125
  }
122
126
  }
@@ -138,7 +142,7 @@ export type DeployError =
138
142
  | BuildError
139
143
  | ArtifactError
140
144
  | TimeoutError
141
- | VersionFailedError
145
+ | DeploymentFailedError
142
146
  | CancelledError;
143
147
 
144
148
  export type UpdateEnvError =
@@ -146,21 +150,21 @@ export type UpdateEnvError =
146
150
  | ApiError
147
151
  | MissingArgumentError
148
152
  | InvalidOptionsError
149
- | NoExistingVersionError
153
+ | NoExistingDeploymentError
150
154
  | TimeoutError
151
- | VersionFailedError
155
+ | DeploymentFailedError
152
156
  | CancelledError;
153
157
 
154
- export type DestroyVersionError =
158
+ export type DestroyDeploymentError =
155
159
  | CancelledError
156
160
  | MissingArgumentError
157
- | NoVersionsFoundError
161
+ | NoDeploymentsFoundError
158
162
  | AuthenticationError
159
163
  | ApiError
160
164
  | TimeoutError
161
- | VersionFailedError;
165
+ | DeploymentFailedError;
162
166
 
163
- export type DestroyServiceError =
167
+ export type DestroyAppError =
164
168
  | CancelledError
165
169
  | AuthenticationError
166
170
  | ApiError
@@ -170,16 +174,16 @@ export type PromoteError =
170
174
  | AuthenticationError
171
175
  | ApiError
172
176
  | MissingArgumentError
173
- | NoVersionsFoundError
177
+ | NoDeploymentsFoundError
174
178
  | TimeoutError
175
- | VersionFailedError
179
+ | DeploymentFailedError
176
180
  | CancelledError;
177
181
 
178
182
  export type ApiRequestError = CancelledError | AuthenticationError | ApiError;
179
183
 
180
- export type VersionOperationError =
184
+ export type DeploymentOperationError =
181
185
  | CancelledError
182
186
  | AuthenticationError
183
187
  | ApiError
184
188
  | TimeoutError
185
- | VersionFailedError;
189
+ | DeploymentFailedError;