@prisma/compute-sdk 0.29.0 → 0.31.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.
- package/dist/api-client.d.ts +38 -38
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +44 -43
- package/dist/api-client.js.map +1 -1
- package/dist/callbacks.d.ts +33 -33
- package/dist/callbacks.d.ts.map +1 -1
- package/dist/compute-client.d.ts +66 -66
- package/dist/compute-client.d.ts.map +1 -1
- package/dist/compute-client.js +274 -272
- package/dist/compute-client.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/normalize.d.ts +3 -1
- package/dist/config/normalize.d.ts.map +1 -1
- package/dist/config/normalize.js +24 -6
- package/dist/config/normalize.js.map +1 -1
- package/dist/config/serialize.d.ts.map +1 -1
- package/dist/config/serialize.js +26 -3
- package/dist/config/serialize.js.map +1 -1
- package/dist/config/types.d.ts +15 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +9 -0
- package/dist/config/types.js.map +1 -1
- package/dist/errors.d.ts +28 -28
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +12 -12
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/log-stream.d.ts +1 -1
- package/dist/log-stream.d.ts.map +1 -1
- package/dist/log-stream.js +1 -1
- package/dist/log-stream.js.map +1 -1
- package/dist/polling.d.ts +4 -4
- package/dist/polling.d.ts.map +1 -1
- package/dist/polling.js +15 -15
- package/dist/polling.js.map +1 -1
- package/dist/types.d.ts +9 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -8
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/api-client.ts +57 -63
- package/src/callbacks.ts +34 -34
- package/src/compute-client.ts +433 -413
- package/src/config/index.ts +3 -0
- package/src/config/normalize.ts +58 -5
- package/src/config/serialize.ts +39 -4
- package/src/config/types.ts +27 -2
- package/src/errors.ts +42 -38
- package/src/index.ts +27 -26
- package/src/log-stream.ts +2 -2
- package/src/polling.ts +19 -18
- package/src/types.ts +13 -17
package/src/config/index.ts
CHANGED
|
@@ -51,10 +51,13 @@ export { serializeComputeConfig } from "./serialize.ts";
|
|
|
51
51
|
export { resolveSourceRoot, sourceRootLineage } from "./source-root.ts";
|
|
52
52
|
export {
|
|
53
53
|
COMPUTE_FRAMEWORKS,
|
|
54
|
+
COMPUTE_REGIONS,
|
|
54
55
|
type ComputeAppConfig,
|
|
55
56
|
type ComputeBuildConfig,
|
|
56
57
|
type ComputeConfig,
|
|
58
|
+
type ComputeConfigDefaults,
|
|
57
59
|
type ComputeEnvConfig,
|
|
58
60
|
type ComputeFramework,
|
|
61
|
+
type ComputeRegion,
|
|
59
62
|
defineComputeConfig,
|
|
60
63
|
} from "./types.ts";
|
package/src/config/normalize.ts
CHANGED
|
@@ -3,7 +3,12 @@ import path from "node:path";
|
|
|
3
3
|
import { Result, TaggedError } from "better-result";
|
|
4
4
|
|
|
5
5
|
import { frameworkByKey } from "./frameworks.ts";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
COMPUTE_FRAMEWORKS,
|
|
8
|
+
COMPUTE_REGIONS,
|
|
9
|
+
type ComputeFramework,
|
|
10
|
+
type ComputeRegion,
|
|
11
|
+
} from "./types.ts";
|
|
7
12
|
|
|
8
13
|
export interface ComputeDeployTargetBuild {
|
|
9
14
|
/** Build command, null to skip the build step, undefined when not configured. */
|
|
@@ -21,6 +26,8 @@ export interface ComputeDeployTarget {
|
|
|
21
26
|
/** `apps` map key, or null for a single-app `app` config. */
|
|
22
27
|
key: string | null;
|
|
23
28
|
name: string | null;
|
|
29
|
+
/** Region used when creating a new app, or null to use the consumer default. */
|
|
30
|
+
region: ComputeRegion | null;
|
|
24
31
|
/** Normalized app directory relative to the config file, or null for the config directory. */
|
|
25
32
|
root: string | null;
|
|
26
33
|
framework: ComputeFramework | null;
|
|
@@ -102,6 +109,7 @@ export type ComputeConfigTargetError =
|
|
|
102
109
|
|
|
103
110
|
const KNOWN_APP_KEYS = [
|
|
104
111
|
"name",
|
|
112
|
+
"region",
|
|
105
113
|
"root",
|
|
106
114
|
"framework",
|
|
107
115
|
"entry",
|
|
@@ -109,6 +117,7 @@ const KNOWN_APP_KEYS = [
|
|
|
109
117
|
"env",
|
|
110
118
|
"build",
|
|
111
119
|
] as const;
|
|
120
|
+
const KNOWN_TOP_LEVEL_KEYS = ["app", "apps", "region"] as const;
|
|
112
121
|
const KNOWN_ENV_KEYS = ["file", "vars"] as const;
|
|
113
122
|
const KNOWN_BUILD_KEYS = ["command", "outputDirectory", "entrypoint"] as const;
|
|
114
123
|
|
|
@@ -123,6 +132,7 @@ export function normalizeComputeConfig(
|
|
|
123
132
|
const issues: string[] = [];
|
|
124
133
|
const targets: ComputeDeployTarget[] = [];
|
|
125
134
|
let kind: LoadedComputeConfig["kind"] = "single";
|
|
135
|
+
let projectRegion: ComputeRegion | null = null;
|
|
126
136
|
|
|
127
137
|
if (!isPlainObject(exported)) {
|
|
128
138
|
issues.push(
|
|
@@ -131,11 +141,16 @@ export function normalizeComputeConfig(
|
|
|
131
141
|
} else {
|
|
132
142
|
const hasApp = exported.app !== undefined;
|
|
133
143
|
const hasApps = exported.apps !== undefined;
|
|
144
|
+
projectRegion = readOptionalComputeRegion(
|
|
145
|
+
exported.region,
|
|
146
|
+
"region",
|
|
147
|
+
issues,
|
|
148
|
+
);
|
|
134
149
|
|
|
135
150
|
for (const key of Object.keys(exported)) {
|
|
136
|
-
if (
|
|
151
|
+
if (!(KNOWN_TOP_LEVEL_KEYS as readonly string[]).includes(key)) {
|
|
137
152
|
issues.push(
|
|
138
|
-
`Unknown top-level key "${key}". Expected
|
|
153
|
+
`Unknown top-level key "${key}". Expected one of: ${KNOWN_TOP_LEVEL_KEYS.join(", ")}.`,
|
|
139
154
|
);
|
|
140
155
|
}
|
|
141
156
|
}
|
|
@@ -145,7 +160,13 @@ export function normalizeComputeConfig(
|
|
|
145
160
|
"Use either `app` (single app) or `apps` (multi-app), not both.",
|
|
146
161
|
);
|
|
147
162
|
} else if (hasApp) {
|
|
148
|
-
const target = normalizeAppEntry(
|
|
163
|
+
const target = normalizeAppEntry(
|
|
164
|
+
exported.app,
|
|
165
|
+
"app",
|
|
166
|
+
null,
|
|
167
|
+
projectRegion,
|
|
168
|
+
issues,
|
|
169
|
+
);
|
|
149
170
|
if (target) {
|
|
150
171
|
targets.push(target);
|
|
151
172
|
}
|
|
@@ -163,7 +184,13 @@ export function normalizeComputeConfig(
|
|
|
163
184
|
issues.push("`apps` keys must be non-empty target names.");
|
|
164
185
|
continue;
|
|
165
186
|
}
|
|
166
|
-
const target = normalizeAppEntry(
|
|
187
|
+
const target = normalizeAppEntry(
|
|
188
|
+
value,
|
|
189
|
+
`apps.${key}`,
|
|
190
|
+
key,
|
|
191
|
+
projectRegion,
|
|
192
|
+
issues,
|
|
193
|
+
);
|
|
167
194
|
if (target) {
|
|
168
195
|
targets.push(target);
|
|
169
196
|
}
|
|
@@ -294,6 +321,7 @@ function normalizeAppEntry(
|
|
|
294
321
|
value: unknown,
|
|
295
322
|
label: string,
|
|
296
323
|
key: string | null,
|
|
324
|
+
projectRegion: ComputeRegion | null,
|
|
297
325
|
issues: string[],
|
|
298
326
|
): ComputeDeployTarget | null {
|
|
299
327
|
if (!isPlainObject(value)) {
|
|
@@ -310,6 +338,12 @@ function normalizeAppEntry(
|
|
|
310
338
|
}
|
|
311
339
|
|
|
312
340
|
const name = readOptionalNonEmptyString(value.name, `${label}.name`, issues);
|
|
341
|
+
const appRegion = readOptionalComputeRegion(
|
|
342
|
+
value.region,
|
|
343
|
+
`${label}.region`,
|
|
344
|
+
issues,
|
|
345
|
+
);
|
|
346
|
+
const region = appRegion ?? projectRegion;
|
|
313
347
|
const entry = readOptionalNonEmptyString(
|
|
314
348
|
value.entry,
|
|
315
349
|
`${label}.entry`,
|
|
@@ -414,6 +448,7 @@ function normalizeAppEntry(
|
|
|
414
448
|
return {
|
|
415
449
|
key,
|
|
416
450
|
name,
|
|
451
|
+
region,
|
|
417
452
|
root,
|
|
418
453
|
framework,
|
|
419
454
|
entry:
|
|
@@ -601,6 +636,24 @@ function readOptionalNonEmptyString(
|
|
|
601
636
|
return value.trim();
|
|
602
637
|
}
|
|
603
638
|
|
|
639
|
+
function readOptionalComputeRegion(
|
|
640
|
+
value: unknown,
|
|
641
|
+
label: string,
|
|
642
|
+
issues: string[],
|
|
643
|
+
): ComputeRegion | null {
|
|
644
|
+
if (value === undefined) {
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const region = typeof value === "string" ? value.trim() : "";
|
|
649
|
+
if (!(COMPUTE_REGIONS as readonly string[]).includes(region)) {
|
|
650
|
+
issues.push(`\`${label}\` must be one of: ${COMPUTE_REGIONS.join(", ")}.`);
|
|
651
|
+
return null;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return region as ComputeRegion;
|
|
655
|
+
}
|
|
656
|
+
|
|
604
657
|
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
605
658
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
606
659
|
}
|
package/src/config/serialize.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { ComputeAppConfig, ComputeConfig } from "./types.ts";
|
|
2
2
|
|
|
3
|
+
type SerializableComputeConfig = {
|
|
4
|
+
region?: ComputeConfig["region"];
|
|
5
|
+
app?: ComputeAppConfig;
|
|
6
|
+
apps?: Record<string, ComputeAppConfig>;
|
|
7
|
+
};
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Renders a `prisma.compute.ts` source file for a config — the scaffolding
|
|
5
11
|
* counterpart of `loadComputeConfig`. Output round-trips through
|
|
@@ -13,10 +19,7 @@ export function serializeComputeConfig(
|
|
|
13
19
|
},
|
|
14
20
|
): string {
|
|
15
21
|
const importFrom = options?.importFrom ?? "@prisma/compute-sdk/config";
|
|
16
|
-
const body =
|
|
17
|
-
"app" in config && config.app !== undefined
|
|
18
|
-
? `{\n app: ${renderValue(config.app, 1)},\n}`
|
|
19
|
-
: `{\n apps: ${renderValue((config as { apps: Record<string, ComputeAppConfig> }).apps, 1)},\n}`;
|
|
22
|
+
const body = renderValue(serializableComputeConfig(config), 0);
|
|
20
23
|
|
|
21
24
|
return [
|
|
22
25
|
`import { defineComputeConfig } from ${JSON.stringify(importFrom)};`,
|
|
@@ -26,6 +29,38 @@ export function serializeComputeConfig(
|
|
|
26
29
|
].join("\n");
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
function serializableComputeConfig(
|
|
33
|
+
config: ComputeConfig,
|
|
34
|
+
): SerializableComputeConfig {
|
|
35
|
+
const serializable: SerializableComputeConfig = {};
|
|
36
|
+
if (config.region !== undefined) {
|
|
37
|
+
serializable.region = config.region;
|
|
38
|
+
}
|
|
39
|
+
if ("app" in config && config.app !== undefined) {
|
|
40
|
+
serializable.app = serializableComputeAppConfig(config.app);
|
|
41
|
+
} else {
|
|
42
|
+
serializable.apps = Object.fromEntries(
|
|
43
|
+
Object.entries(
|
|
44
|
+
(config as { apps: Record<string, ComputeAppConfig> }).apps,
|
|
45
|
+
).map(([key, app]) => [key, serializableComputeAppConfig(app)]),
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return serializable;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function serializableComputeAppConfig(app: ComputeAppConfig): ComputeAppConfig {
|
|
52
|
+
return {
|
|
53
|
+
name: app.name,
|
|
54
|
+
region: app.region,
|
|
55
|
+
root: app.root,
|
|
56
|
+
framework: app.framework,
|
|
57
|
+
entry: app.entry,
|
|
58
|
+
httpPort: app.httpPort,
|
|
59
|
+
env: app.env,
|
|
60
|
+
build: app.build,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
29
64
|
const IDENTIFIER_KEY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
30
65
|
|
|
31
66
|
function renderValue(value: unknown, depth: number): string {
|
package/src/config/types.ts
CHANGED
|
@@ -19,6 +19,18 @@ export const COMPUTE_FRAMEWORKS = [
|
|
|
19
19
|
|
|
20
20
|
export type ComputeFramework = (typeof COMPUTE_FRAMEWORKS)[number];
|
|
21
21
|
|
|
22
|
+
/** Supported Compute region identifiers. */
|
|
23
|
+
export const COMPUTE_REGIONS = Object.freeze([
|
|
24
|
+
"us-east-1",
|
|
25
|
+
"us-west-1",
|
|
26
|
+
"eu-west-3",
|
|
27
|
+
"eu-central-1",
|
|
28
|
+
"ap-northeast-1",
|
|
29
|
+
"ap-southeast-1",
|
|
30
|
+
] as const);
|
|
31
|
+
|
|
32
|
+
export type ComputeRegion = (typeof COMPUTE_REGIONS)[number];
|
|
33
|
+
|
|
22
34
|
export interface ComputeEnvConfig {
|
|
23
35
|
/** Dotenv file path(s) resolved relative to the config file directory. */
|
|
24
36
|
file?: string | string[];
|
|
@@ -42,6 +54,8 @@ export interface ComputeBuildConfig {
|
|
|
42
54
|
export interface ComputeAppConfig {
|
|
43
55
|
/** Deployed app name. Defaults to the `apps` key, then consumer-side inference. */
|
|
44
56
|
name?: string;
|
|
57
|
+
/** App region override. Defaults to the project region, then consumer-side inference. */
|
|
58
|
+
region?: ComputeRegion;
|
|
45
59
|
/** App directory relative to the config file. Defaults to the config file directory. */
|
|
46
60
|
root?: string;
|
|
47
61
|
/** Framework to deploy. Defaults to detection from the app directory. */
|
|
@@ -56,6 +70,14 @@ export interface ComputeAppConfig {
|
|
|
56
70
|
build?: ComputeBuildConfig;
|
|
57
71
|
}
|
|
58
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Project-level defaults for every app in the config.
|
|
75
|
+
*/
|
|
76
|
+
export interface ComputeConfigDefaults {
|
|
77
|
+
/** Default region used when creating new apps. Existing apps keep their current region. */
|
|
78
|
+
region?: ComputeRegion;
|
|
79
|
+
}
|
|
80
|
+
|
|
59
81
|
/**
|
|
60
82
|
* `prisma.compute.ts` accepts exactly one of:
|
|
61
83
|
*
|
|
@@ -63,8 +85,11 @@ export interface ComputeAppConfig {
|
|
|
63
85
|
* - `apps` — a monorepo or multi-app repository, keyed by deploy target
|
|
64
86
|
*/
|
|
65
87
|
export type ComputeConfig =
|
|
66
|
-
| { app: ComputeAppConfig; apps?: never }
|
|
67
|
-
|
|
|
88
|
+
| (ComputeConfigDefaults & { app: ComputeAppConfig; apps?: never })
|
|
89
|
+
| (ComputeConfigDefaults & {
|
|
90
|
+
apps: Record<string, ComputeAppConfig>;
|
|
91
|
+
app?: never;
|
|
92
|
+
});
|
|
68
93
|
|
|
69
94
|
/**
|
|
70
95
|
* Identity helper that gives `prisma.compute.ts` full type checking:
|
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
|
-
|
|
40
|
+
deploymentId: string;
|
|
41
41
|
elapsedMs: number;
|
|
42
42
|
lastStatus: string;
|
|
43
43
|
message: string;
|
|
44
44
|
}>() {
|
|
45
45
|
constructor(args: {
|
|
46
|
-
|
|
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
|
|
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
|
|
58
|
-
|
|
57
|
+
export class DeploymentFailedError extends TaggedError(
|
|
58
|
+
"DeploymentFailedError",
|
|
59
|
+
)<{
|
|
60
|
+
deploymentId: string;
|
|
59
61
|
message: string;
|
|
60
62
|
}>() {
|
|
61
|
-
constructor(args: {
|
|
63
|
+
constructor(args: { deploymentId: string }) {
|
|
62
64
|
super({
|
|
63
|
-
|
|
64
|
-
message: `
|
|
65
|
+
deploymentId: args.deploymentId,
|
|
66
|
+
message: `Deployment ${args.deploymentId} transitioned to failed status`,
|
|
65
67
|
});
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
export class
|
|
70
|
-
"
|
|
71
|
+
export class NoExistingDeploymentError extends TaggedError(
|
|
72
|
+
"NoExistingDeploymentError",
|
|
71
73
|
)<{
|
|
72
|
-
|
|
74
|
+
appId: string;
|
|
73
75
|
message: string;
|
|
74
76
|
}>() {
|
|
75
|
-
constructor(args: {
|
|
77
|
+
constructor(args: { appId: string }) {
|
|
76
78
|
super({
|
|
77
|
-
|
|
78
|
-
message: `
|
|
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
|
|
84
|
-
|
|
85
|
+
export class NoDeploymentsFoundError extends TaggedError(
|
|
86
|
+
"NoDeploymentsFoundError",
|
|
87
|
+
)<{
|
|
88
|
+
appId: string;
|
|
85
89
|
message: string;
|
|
86
90
|
}>() {
|
|
87
|
-
constructor(args: {
|
|
91
|
+
constructor(args: { appId: string }) {
|
|
88
92
|
super({
|
|
89
|
-
|
|
90
|
-
message: `
|
|
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
|
-
|
|
108
|
-
failures: Array<{
|
|
109
|
-
|
|
111
|
+
succeededDeploymentIds: string[];
|
|
112
|
+
failures: Array<{ deploymentId: string; error: DeploymentOperationError }>;
|
|
113
|
+
appDeleted: boolean;
|
|
110
114
|
}>() {
|
|
111
115
|
constructor(args: {
|
|
112
|
-
|
|
113
|
-
failures: Array<{
|
|
114
|
-
|
|
116
|
+
succeededDeploymentIds: string[];
|
|
117
|
+
failures: Array<{ deploymentId: string; error: DeploymentOperationError }>;
|
|
118
|
+
appDeleted: boolean;
|
|
115
119
|
}) {
|
|
116
|
-
const failedIds = args.failures.map((f) => f.
|
|
120
|
+
const failedIds = args.failures.map((f) => f.deploymentId).join(", ");
|
|
117
121
|
super({
|
|
118
122
|
...args,
|
|
119
|
-
message: `Failed to destroy ${args.failures.length}
|
|
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
|
-
|
|
|
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
|
-
|
|
|
153
|
+
| NoExistingDeploymentError
|
|
150
154
|
| TimeoutError
|
|
151
|
-
|
|
|
155
|
+
| DeploymentFailedError
|
|
152
156
|
| CancelledError;
|
|
153
157
|
|
|
154
|
-
export type
|
|
158
|
+
export type DestroyDeploymentError =
|
|
155
159
|
| CancelledError
|
|
156
160
|
| MissingArgumentError
|
|
157
|
-
|
|
|
161
|
+
| NoDeploymentsFoundError
|
|
158
162
|
| AuthenticationError
|
|
159
163
|
| ApiError
|
|
160
164
|
| TimeoutError
|
|
161
|
-
|
|
|
165
|
+
| DeploymentFailedError;
|
|
162
166
|
|
|
163
|
-
export type
|
|
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
|
-
|
|
|
177
|
+
| NoDeploymentsFoundError
|
|
174
178
|
| TimeoutError
|
|
175
|
-
|
|
|
179
|
+
| DeploymentFailedError
|
|
176
180
|
| CancelledError;
|
|
177
181
|
|
|
178
182
|
export type ApiRequestError = CancelledError | AuthenticationError | ApiError;
|
|
179
183
|
|
|
180
|
-
export type
|
|
184
|
+
export type DeploymentOperationError =
|
|
181
185
|
| CancelledError
|
|
182
186
|
| AuthenticationError
|
|
183
187
|
| ApiError
|
|
184
188
|
| TimeoutError
|
|
185
|
-
|
|
|
189
|
+
| DeploymentFailedError;
|
package/src/index.ts
CHANGED
|
@@ -40,32 +40,32 @@ export { BunBuild } from "./bun-build.ts";
|
|
|
40
40
|
export type {
|
|
41
41
|
DeployInteraction,
|
|
42
42
|
DeployProgress,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
DestroyAppProgress,
|
|
44
|
+
DestroyDeploymentInteraction,
|
|
45
|
+
DestroyDeploymentProgress,
|
|
46
46
|
PromoteProgress,
|
|
47
47
|
UpdateEnvProgress,
|
|
48
48
|
} from "./callbacks.ts";
|
|
49
49
|
export type {
|
|
50
|
+
CreateAppOptions,
|
|
50
51
|
CreateProjectOptions,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
DeleteVersionOptions,
|
|
52
|
+
DeleteAppOptions,
|
|
53
|
+
DeleteDeploymentOptions,
|
|
54
54
|
DeployOptions,
|
|
55
55
|
DeployResult,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
DestroyAppOptions,
|
|
57
|
+
DestroyAppResult,
|
|
58
|
+
DestroyDeploymentOptions,
|
|
59
|
+
DestroyDeploymentResult,
|
|
60
|
+
ListAppsOptions,
|
|
61
|
+
ListDeploymentsOptions,
|
|
60
62
|
ListProjectsOptions,
|
|
61
|
-
ListServicesOptions,
|
|
62
|
-
ListVersionsOptions,
|
|
63
63
|
PromoteOptions,
|
|
64
64
|
PromoteResult,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
ShowAppOptions,
|
|
66
|
+
ShowDeploymentOptions,
|
|
67
|
+
StartDeploymentOptions,
|
|
68
|
+
StopDeploymentOptions,
|
|
69
69
|
UpdateEnvOptions,
|
|
70
70
|
UpdateEnvResult,
|
|
71
71
|
} from "./compute-client.ts";
|
|
@@ -83,11 +83,11 @@ export { detectAppSchema } from "./detect-schema.ts";
|
|
|
83
83
|
export type {
|
|
84
84
|
ApiRequestError,
|
|
85
85
|
DeployError,
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
DeploymentOperationError,
|
|
87
|
+
DestroyAppError,
|
|
88
|
+
DestroyDeploymentError,
|
|
88
89
|
PromoteError,
|
|
89
90
|
UpdateEnvError,
|
|
90
|
-
VersionOperationError,
|
|
91
91
|
} from "./errors.ts";
|
|
92
92
|
export {
|
|
93
93
|
ApiError,
|
|
@@ -95,14 +95,14 @@ export {
|
|
|
95
95
|
AuthenticationError,
|
|
96
96
|
BuildError,
|
|
97
97
|
CancelledError,
|
|
98
|
+
DeploymentFailedError,
|
|
98
99
|
DestroyAggregateError,
|
|
99
100
|
InvalidOptionsError,
|
|
100
101
|
LogStreamError,
|
|
101
102
|
MissingArgumentError,
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
NoDeploymentsFoundError,
|
|
104
|
+
NoExistingDeploymentError,
|
|
104
105
|
TimeoutError,
|
|
105
|
-
VersionFailedError,
|
|
106
106
|
} from "./errors.ts";
|
|
107
107
|
export type {
|
|
108
108
|
LogRecord,
|
|
@@ -118,16 +118,17 @@ export { NextjsBuild } from "./nextjs-build.ts";
|
|
|
118
118
|
export { NuxtBuild } from "./nuxt-build.ts";
|
|
119
119
|
export { TanstackStartBuild } from "./tanstack-start-build.ts";
|
|
120
120
|
export type {
|
|
121
|
+
AppDetail,
|
|
122
|
+
AppInfo,
|
|
123
|
+
ComputeRegion,
|
|
121
124
|
CreateProjectResult,
|
|
122
125
|
DatabaseInfo,
|
|
126
|
+
DeploymentDetail,
|
|
127
|
+
DeploymentInfo,
|
|
123
128
|
PortMapping,
|
|
124
129
|
ProjectInfo,
|
|
125
130
|
RegionInfo,
|
|
126
131
|
ResolvedConfig,
|
|
127
|
-
ServiceDetail,
|
|
128
|
-
ServiceInfo,
|
|
129
|
-
VersionDetail,
|
|
130
|
-
VersionInfo,
|
|
131
132
|
} from "./types.ts";
|
|
132
133
|
export { KNOWN_REGION_IDS, REGIONS } from "./types.ts";
|
|
133
134
|
export { uploadArtifact } from "./upload-artifact.ts";
|
package/src/log-stream.ts
CHANGED
|
@@ -27,7 +27,7 @@ export type StreamRecord = LogRecord | TerminalRecord;
|
|
|
27
27
|
export type LogStreamOptions = {
|
|
28
28
|
baseUrl: string;
|
|
29
29
|
token: string;
|
|
30
|
-
|
|
30
|
+
deploymentId: string;
|
|
31
31
|
tail?: number;
|
|
32
32
|
fromStart?: boolean;
|
|
33
33
|
cursor?: string;
|
|
@@ -71,7 +71,7 @@ function toError(value: unknown): Error {
|
|
|
71
71
|
|
|
72
72
|
function buildWebSocketUrl(options: LogStreamOptions): string {
|
|
73
73
|
const httpUrl = new URL(
|
|
74
|
-
`/v1/
|
|
74
|
+
`/v1/deployments/${encodeURIComponent(options.deploymentId)}/logs`,
|
|
75
75
|
options.baseUrl,
|
|
76
76
|
);
|
|
77
77
|
httpUrl.protocol = httpUrl.protocol === "https:" ? "wss:" : "ws:";
|
package/src/polling.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { ApiClientError, InternalApiClient } from "./api-client.ts";
|
|
|
3
3
|
import {
|
|
4
4
|
ApiError,
|
|
5
5
|
CancelledError,
|
|
6
|
+
DeploymentFailedError,
|
|
6
7
|
TimeoutError,
|
|
7
|
-
VersionFailedError,
|
|
8
8
|
} from "./errors.ts";
|
|
9
9
|
|
|
10
10
|
export type PollOptions = {
|
|
@@ -23,17 +23,17 @@ export type PollResult = {
|
|
|
23
23
|
export type PollError =
|
|
24
24
|
| CancelledError
|
|
25
25
|
| TimeoutError
|
|
26
|
-
|
|
|
26
|
+
| DeploymentFailedError
|
|
27
27
|
| ApiClientError;
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* Polls a
|
|
30
|
+
* Polls a deployment until it reaches the target status, fails, or times out.
|
|
31
31
|
*
|
|
32
32
|
* Returns a Result with the preview domain on success or a typed error.
|
|
33
33
|
*/
|
|
34
|
-
export async function
|
|
34
|
+
export async function pollDeploymentStatus(
|
|
35
35
|
api: InternalApiClient,
|
|
36
|
-
|
|
36
|
+
deploymentId: string,
|
|
37
37
|
options: PollOptions,
|
|
38
38
|
): Promise<Result<PollResult, PollError>> {
|
|
39
39
|
return Result.gen(async function* () {
|
|
@@ -45,34 +45,35 @@ export async function pollVersionStatus(
|
|
|
45
45
|
return Result.err(new CancelledError());
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const
|
|
49
|
-
api.
|
|
48
|
+
const deployment = yield* Result.await(
|
|
49
|
+
api.getDeployment(deploymentId, options.signal),
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
-
if (
|
|
53
|
-
lastStatus =
|
|
54
|
-
options.onStatusChange?.(
|
|
52
|
+
if (deployment.status !== lastStatus) {
|
|
53
|
+
lastStatus = deployment.status;
|
|
54
|
+
options.onStatusChange?.(deployment.status);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (
|
|
58
|
-
if (options.targetStatus === "running" && !
|
|
57
|
+
if (deployment.status === options.targetStatus) {
|
|
58
|
+
if (options.targetStatus === "running" && !deployment.previewDomain) {
|
|
59
59
|
return Result.err(
|
|
60
60
|
new ApiError({
|
|
61
61
|
statusCode: 0,
|
|
62
62
|
statusText: "",
|
|
63
|
-
message:
|
|
63
|
+
message:
|
|
64
|
+
"Deployment reached running state without a previewDomain",
|
|
64
65
|
traceHeaders: {},
|
|
65
66
|
}),
|
|
66
67
|
);
|
|
67
68
|
}
|
|
68
69
|
return Result.ok({
|
|
69
|
-
previewDomain:
|
|
70
|
-
lastStatus:
|
|
70
|
+
previewDomain: deployment.previewDomain ?? "",
|
|
71
|
+
lastStatus: deployment.status,
|
|
71
72
|
});
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
if (
|
|
75
|
-
return Result.err(new
|
|
75
|
+
if (deployment.status === "failed") {
|
|
76
|
+
return Result.err(new DeploymentFailedError({ deploymentId }));
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
await sleep(options.pollIntervalMs, options.signal);
|
|
@@ -80,7 +81,7 @@ export async function pollVersionStatus(
|
|
|
80
81
|
|
|
81
82
|
return Result.err(
|
|
82
83
|
new TimeoutError({
|
|
83
|
-
|
|
84
|
+
deploymentId,
|
|
84
85
|
elapsedMs: Date.now() - (deadline - options.timeoutSeconds * 1_000),
|
|
85
86
|
lastStatus,
|
|
86
87
|
}),
|