@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.
- 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/astro-build.d.ts +2 -0
- package/dist/astro-build.d.ts.map +1 -1
- package/dist/astro-build.js +31 -39
- package/dist/astro-build.js.map +1 -1
- package/dist/build-settings.d.ts +3 -0
- package/dist/build-settings.d.ts.map +1 -1
- package/dist/build-settings.js +13 -0
- package/dist/build-settings.js.map +1 -1
- package/dist/build-strategy.d.ts +20 -0
- package/dist/build-strategy.d.ts.map +1 -1
- package/dist/build-strategy.js +33 -1
- package/dist/build-strategy.js.map +1 -1
- package/dist/build.d.ts +2 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +16 -4
- package/dist/build.js.map +1 -1
- package/dist/bun-build.d.ts +1 -1
- package/dist/bun-build.d.ts.map +1 -1
- package/dist/bun-build.js +25 -9
- package/dist/bun-build.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/frameworks.d.ts +4 -8
- package/dist/config/frameworks.d.ts.map +1 -1
- package/dist/config/frameworks.js +17 -5
- package/dist/config/frameworks.js.map +1 -1
- package/dist/config/normalize.d.ts +6 -0
- package/dist/config/normalize.d.ts.map +1 -1
- package/dist/config/normalize.js +53 -12
- package/dist/config/normalize.js.map +1 -1
- package/dist/config/types.d.ts +3 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/configured-artifact.d.ts +20 -0
- package/dist/configured-artifact.d.ts.map +1 -0
- package/dist/configured-artifact.js +104 -0
- package/dist/configured-artifact.js.map +1 -0
- package/dist/custom-build.d.ts +20 -0
- package/dist/custom-build.d.ts.map +1 -0
- package/dist/custom-build.js +53 -0
- package/dist/custom-build.js.map +1 -0
- 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 +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -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/nestjs-build.d.ts.map +1 -1
- package/dist/nestjs-build.js +28 -29
- package/dist/nestjs-build.js.map +1 -1
- package/dist/nextjs-build.d.ts +1 -1
- package/dist/nextjs-build.d.ts.map +1 -1
- package/dist/nextjs-build.js +25 -14
- package/dist/nextjs-build.js.map +1 -1
- package/dist/nuxt-build.d.ts +2 -0
- package/dist/nuxt-build.d.ts.map +1 -1
- package/dist/nuxt-build.js +31 -39
- package/dist/nuxt-build.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/tanstack-start-build.d.ts +1 -1
- package/dist/tanstack-start-build.d.ts.map +1 -1
- package/dist/tanstack-start-build.js +26 -47
- package/dist/tanstack-start-build.js.map +1 -1
- package/dist/types.d.ts +8 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/api-client.ts +57 -63
- package/src/astro-build.ts +39 -46
- package/src/build-settings.ts +16 -0
- package/src/build-strategy.ts +56 -1
- package/src/build.ts +16 -4
- package/src/bun-build.ts +39 -10
- package/src/callbacks.ts +34 -34
- package/src/compute-client.ts +433 -413
- package/src/config/frameworks.ts +18 -5
- package/src/config/normalize.ts +74 -13
- package/src/config/types.ts +3 -0
- package/src/configured-artifact.ts +169 -0
- package/src/custom-build.ts +73 -0
- package/src/errors.ts +42 -38
- package/src/index.ts +27 -26
- package/src/log-stream.ts +2 -2
- package/src/nestjs-build.ts +36 -33
- package/src/nextjs-build.ts +31 -14
- package/src/nuxt-build.ts +39 -46
- package/src/polling.ts +19 -18
- package/src/tanstack-start-build.ts +31 -53
- package/src/types.ts +8 -8
package/src/compute-client.ts
CHANGED
|
@@ -11,9 +11,9 @@ import type { BuildStrategy } from "./build-strategy.ts";
|
|
|
11
11
|
import type {
|
|
12
12
|
DeployInteraction,
|
|
13
13
|
DeployProgress,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
DestroyAppProgress,
|
|
15
|
+
DestroyDeploymentInteraction,
|
|
16
|
+
DestroyDeploymentProgress,
|
|
17
17
|
PromoteProgress,
|
|
18
18
|
UpdateEnvProgress,
|
|
19
19
|
} from "./callbacks.ts";
|
|
@@ -25,40 +25,40 @@ import {
|
|
|
25
25
|
BuildError,
|
|
26
26
|
CancelledError,
|
|
27
27
|
type DeployError,
|
|
28
|
+
type DeploymentOperationError,
|
|
28
29
|
DestroyAggregateError,
|
|
29
|
-
type
|
|
30
|
-
type
|
|
30
|
+
type DestroyAppError,
|
|
31
|
+
type DestroyDeploymentError,
|
|
31
32
|
InvalidOptionsError,
|
|
32
33
|
MissingArgumentError,
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
NoDeploymentsFoundError,
|
|
35
|
+
NoExistingDeploymentError,
|
|
35
36
|
type PromoteError,
|
|
36
37
|
type UpdateEnvError,
|
|
37
|
-
type VersionOperationError,
|
|
38
38
|
} from "./errors.ts";
|
|
39
|
-
import {
|
|
39
|
+
import { pollDeploymentStatus } from "./polling.ts";
|
|
40
40
|
import type {
|
|
41
|
+
AppDetail,
|
|
42
|
+
AppInfo,
|
|
41
43
|
CreateProjectResult,
|
|
44
|
+
DeploymentDetail,
|
|
45
|
+
DeploymentInfo,
|
|
42
46
|
PortMapping,
|
|
43
47
|
ProjectInfo,
|
|
44
48
|
ResolvedConfig,
|
|
45
|
-
ServiceDetail,
|
|
46
|
-
ServiceInfo,
|
|
47
|
-
VersionDetail,
|
|
48
|
-
VersionInfo,
|
|
49
49
|
} from "./types.ts";
|
|
50
50
|
import { REGIONS } from "./types.ts";
|
|
51
51
|
import { uploadArtifact } from "./upload-artifact.ts";
|
|
52
52
|
|
|
53
|
-
type
|
|
54
|
-
Awaited<ReturnType<InternalApiClient["
|
|
53
|
+
type DeploymentDetailData = InferOk<
|
|
54
|
+
Awaited<ReturnType<InternalApiClient["getDeployment"]>>
|
|
55
55
|
>;
|
|
56
56
|
|
|
57
57
|
export interface DeployOptions {
|
|
58
58
|
strategy: BuildStrategy;
|
|
59
59
|
projectId?: string;
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
appId?: string;
|
|
61
|
+
appName?: string;
|
|
62
62
|
region?: string;
|
|
63
63
|
envVars?: Record<string, string | null>;
|
|
64
64
|
portMapping?: PortMapping;
|
|
@@ -68,12 +68,12 @@ export interface DeployOptions {
|
|
|
68
68
|
interaction?: DeployInteraction;
|
|
69
69
|
progress?: DeployProgress;
|
|
70
70
|
skipPromote?: boolean;
|
|
71
|
-
|
|
71
|
+
destroyOldDeployment?: boolean;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export interface UpdateEnvOptions {
|
|
75
75
|
projectId?: string;
|
|
76
|
-
|
|
76
|
+
appId?: string;
|
|
77
77
|
envVars?: Record<string, string | null>;
|
|
78
78
|
portMapping?: PortMapping;
|
|
79
79
|
timeoutSeconds?: number;
|
|
@@ -83,45 +83,45 @@ export interface UpdateEnvOptions {
|
|
|
83
83
|
progress?: UpdateEnvProgress;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
export interface
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
export interface DestroyDeploymentOptions {
|
|
87
|
+
deploymentId?: string;
|
|
88
|
+
appId?: string;
|
|
89
89
|
projectId?: string;
|
|
90
90
|
timeoutSeconds?: number;
|
|
91
91
|
pollIntervalMs?: number;
|
|
92
92
|
signal?: AbortSignal;
|
|
93
|
-
interaction?:
|
|
94
|
-
progress?:
|
|
93
|
+
interaction?: DestroyDeploymentInteraction;
|
|
94
|
+
progress?: DestroyDeploymentProgress;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
export interface
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
export interface DestroyAppOptions {
|
|
98
|
+
appId: string;
|
|
99
|
+
keepApp?: boolean;
|
|
100
100
|
timeoutSeconds?: number;
|
|
101
101
|
pollIntervalMs?: number;
|
|
102
102
|
signal?: AbortSignal;
|
|
103
|
-
progress?:
|
|
103
|
+
progress?: DestroyAppProgress;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
export interface
|
|
106
|
+
export interface ListAppsOptions {
|
|
107
107
|
projectId: string;
|
|
108
108
|
signal?: AbortSignal;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
export interface
|
|
111
|
+
export interface CreateAppOptions {
|
|
112
112
|
projectId: string;
|
|
113
|
-
|
|
113
|
+
appName: string;
|
|
114
114
|
region: string;
|
|
115
115
|
signal?: AbortSignal;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
export interface
|
|
119
|
-
|
|
118
|
+
export interface ShowAppOptions {
|
|
119
|
+
appId: string;
|
|
120
120
|
signal?: AbortSignal;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
export interface
|
|
124
|
-
|
|
123
|
+
export interface DeleteAppOptions {
|
|
124
|
+
appId: string;
|
|
125
125
|
signal?: AbortSignal;
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -136,81 +136,81 @@ export interface ListProjectsOptions {
|
|
|
136
136
|
signal?: AbortSignal;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
export interface
|
|
140
|
-
|
|
139
|
+
export interface ListDeploymentsOptions {
|
|
140
|
+
appId: string;
|
|
141
141
|
signal?: AbortSignal;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
export interface
|
|
145
|
-
|
|
144
|
+
export interface ShowDeploymentOptions {
|
|
145
|
+
deploymentId: string;
|
|
146
146
|
signal?: AbortSignal;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
export interface
|
|
150
|
-
|
|
149
|
+
export interface StartDeploymentOptions {
|
|
150
|
+
deploymentId: string;
|
|
151
151
|
signal?: AbortSignal;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
export interface
|
|
155
|
-
|
|
154
|
+
export interface StopDeploymentOptions {
|
|
155
|
+
deploymentId: string;
|
|
156
156
|
signal?: AbortSignal;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
export interface
|
|
160
|
-
|
|
159
|
+
export interface DeleteDeploymentOptions {
|
|
160
|
+
deploymentId: string;
|
|
161
161
|
signal?: AbortSignal;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
export interface PromoteOptions {
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
appId: string;
|
|
166
|
+
deploymentId?: string;
|
|
167
167
|
timeoutSeconds?: number;
|
|
168
168
|
pollIntervalMs?: number;
|
|
169
169
|
signal?: AbortSignal;
|
|
170
|
-
interaction?:
|
|
170
|
+
interaction?: DestroyDeploymentInteraction;
|
|
171
171
|
progress?: PromoteProgress;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
export interface DeployResult {
|
|
175
175
|
projectId: string;
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
appId: string;
|
|
177
|
+
appName: string;
|
|
178
178
|
region: string;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
deploymentId: string;
|
|
180
|
+
deploymentEndpointDomain: string;
|
|
181
|
+
appEndpointDomain: string | null;
|
|
182
182
|
promoted: boolean;
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
previousDeploymentId: string | null;
|
|
184
|
+
previousDeploymentAction: "stopped" | "destroyed" | "still-active" | null;
|
|
185
185
|
resolvedConfig: ResolvedConfig;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
export interface PromoteResult {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
appId: string;
|
|
190
|
+
deploymentId: string;
|
|
191
|
+
appEndpointDomain: string;
|
|
192
|
+
deploymentStarted: boolean;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
export interface UpdateEnvResult {
|
|
196
196
|
projectId: string;
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
appId: string;
|
|
198
|
+
deploymentId: string;
|
|
199
199
|
deploymentUrl: string;
|
|
200
200
|
resolvedConfig: ResolvedConfig;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
export interface
|
|
204
|
-
|
|
203
|
+
export interface DestroyDeploymentResult {
|
|
204
|
+
deploymentId: string;
|
|
205
205
|
previousStatus: string;
|
|
206
206
|
stopped: boolean;
|
|
207
207
|
deleted: boolean;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
export interface
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
export interface DestroyAppResult {
|
|
211
|
+
appId: string;
|
|
212
|
+
deletedDeploymentIds: string[];
|
|
213
|
+
appDeleted: boolean;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
const DEFAULT_TIMEOUT_SECONDS = 120;
|
|
@@ -226,11 +226,11 @@ export class ComputeClient {
|
|
|
226
226
|
async deploy(
|
|
227
227
|
options: DeployOptions,
|
|
228
228
|
): Promise<Result<DeployResult, DeployError>> {
|
|
229
|
-
if (options.skipPromote && options.
|
|
229
|
+
if (options.skipPromote && options.destroyOldDeployment) {
|
|
230
230
|
return Result.err(
|
|
231
231
|
new InvalidOptionsError({
|
|
232
232
|
message:
|
|
233
|
-
"
|
|
233
|
+
"destroyOldDeployment cannot be combined with skipPromote — the old deployment stays active when promotion is skipped",
|
|
234
234
|
}),
|
|
235
235
|
);
|
|
236
236
|
}
|
|
@@ -281,7 +281,7 @@ export class ComputeClient {
|
|
|
281
281
|
|
|
282
282
|
const portMapping =
|
|
283
283
|
options.portMapping ??
|
|
284
|
-
(target.
|
|
284
|
+
(target.isNewApp && artifact.defaultPortMapping
|
|
285
285
|
? artifact.defaultPortMapping
|
|
286
286
|
: undefined);
|
|
287
287
|
|
|
@@ -295,19 +295,19 @@ export class ComputeClient {
|
|
|
295
295
|
);
|
|
296
296
|
|
|
297
297
|
const createResponse = yield* Result.await(
|
|
298
|
-
self.#api.
|
|
299
|
-
target.
|
|
298
|
+
self.#api.createAppDeployment(
|
|
299
|
+
target.appId,
|
|
300
300
|
portMapping ? { portMapping } : {},
|
|
301
301
|
options.signal,
|
|
302
302
|
),
|
|
303
303
|
);
|
|
304
|
-
options.progress?.
|
|
304
|
+
options.progress?.onDeploymentCreated?.(createResponse.id);
|
|
305
305
|
|
|
306
306
|
const uploadUrl = readUploadUrl(createResponse);
|
|
307
307
|
if (!uploadUrl) {
|
|
308
308
|
return Result.err(
|
|
309
309
|
new ArtifactError({
|
|
310
|
-
message: "
|
|
310
|
+
message: "Deployment creation did not return an upload URL",
|
|
311
311
|
}),
|
|
312
312
|
);
|
|
313
313
|
}
|
|
@@ -322,18 +322,18 @@ export class ComputeClient {
|
|
|
322
322
|
|
|
323
323
|
yield* self.#checkAborted(options.signal);
|
|
324
324
|
|
|
325
|
-
const
|
|
326
|
-
self.#api.
|
|
325
|
+
const app = yield* Result.await(
|
|
326
|
+
self.#api.getApp(target.appId, options.signal),
|
|
327
327
|
);
|
|
328
|
-
const
|
|
328
|
+
const previousDeploymentId = app.latestDeploymentId ?? null;
|
|
329
329
|
|
|
330
330
|
options.progress?.onStartRequested?.();
|
|
331
331
|
yield* Result.await(
|
|
332
|
-
self.#api.
|
|
332
|
+
self.#api.startDeployment(createResponse.id, options.signal),
|
|
333
333
|
);
|
|
334
334
|
|
|
335
335
|
const pollResult = yield* Result.await(
|
|
336
|
-
|
|
336
|
+
pollDeploymentStatus(self.#api, createResponse.id, {
|
|
337
337
|
targetStatus: "running",
|
|
338
338
|
timeoutSeconds: options.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
|
|
339
339
|
pollIntervalMs: options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
@@ -342,29 +342,31 @@ export class ComputeClient {
|
|
|
342
342
|
}),
|
|
343
343
|
);
|
|
344
344
|
|
|
345
|
-
const
|
|
346
|
-
|
|
345
|
+
const deploymentEndpointDomain = toDeploymentUrl(
|
|
346
|
+
pollResult.previewDomain,
|
|
347
|
+
);
|
|
348
|
+
options.progress?.onRunning?.(deploymentEndpointDomain);
|
|
347
349
|
|
|
348
350
|
const resolvedConfig: ResolvedConfig = {
|
|
349
351
|
projectId: target.projectId,
|
|
350
|
-
|
|
351
|
-
|
|
352
|
+
appId: target.appId,
|
|
353
|
+
appName: target.appName,
|
|
352
354
|
region: target.region,
|
|
353
|
-
portMapping
|
|
355
|
+
portMapping,
|
|
354
356
|
};
|
|
355
357
|
|
|
356
358
|
if (options.skipPromote) {
|
|
357
359
|
return Result.ok({
|
|
358
360
|
projectId: target.projectId,
|
|
359
|
-
|
|
360
|
-
|
|
361
|
+
appId: target.appId,
|
|
362
|
+
appName: target.appName,
|
|
361
363
|
region: target.region,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
deploymentId: createResponse.id,
|
|
365
|
+
deploymentEndpointDomain,
|
|
366
|
+
appEndpointDomain: null,
|
|
365
367
|
promoted: false,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
+
previousDeploymentId,
|
|
369
|
+
previousDeploymentAction: previousDeploymentId
|
|
368
370
|
? ("still-active" as const)
|
|
369
371
|
: null,
|
|
370
372
|
resolvedConfig,
|
|
@@ -373,10 +375,10 @@ export class ComputeClient {
|
|
|
373
375
|
|
|
374
376
|
const switchoverResult = yield* Result.await(
|
|
375
377
|
self.#promoteAndSwitchover(
|
|
376
|
-
target.
|
|
378
|
+
target.appId,
|
|
377
379
|
createResponse.id,
|
|
378
|
-
|
|
379
|
-
options.
|
|
380
|
+
previousDeploymentId,
|
|
381
|
+
options.destroyOldDeployment ?? false,
|
|
380
382
|
options.signal,
|
|
381
383
|
options.progress,
|
|
382
384
|
),
|
|
@@ -384,15 +386,15 @@ export class ComputeClient {
|
|
|
384
386
|
|
|
385
387
|
return Result.ok({
|
|
386
388
|
projectId: target.projectId,
|
|
387
|
-
|
|
388
|
-
|
|
389
|
+
appId: target.appId,
|
|
390
|
+
appName: target.appName,
|
|
389
391
|
region: target.region,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
392
|
+
deploymentId: createResponse.id,
|
|
393
|
+
deploymentEndpointDomain,
|
|
394
|
+
appEndpointDomain: switchoverResult.appEndpointDomain,
|
|
393
395
|
promoted: true,
|
|
394
|
-
|
|
395
|
-
|
|
396
|
+
previousDeploymentId: switchoverResult.previousDeploymentId,
|
|
397
|
+
previousDeploymentAction: switchoverResult.previousDeploymentAction,
|
|
396
398
|
resolvedConfig,
|
|
397
399
|
});
|
|
398
400
|
} finally {
|
|
@@ -410,12 +412,12 @@ export class ComputeClient {
|
|
|
410
412
|
|
|
411
413
|
const target = yield* Result.await(self.#resolveDeployTarget(options));
|
|
412
414
|
|
|
413
|
-
const
|
|
414
|
-
self.#api.
|
|
415
|
+
const deployments = yield* Result.await(
|
|
416
|
+
self.#api.listAppDeployments(target.appId, options.signal),
|
|
415
417
|
);
|
|
416
|
-
if (
|
|
418
|
+
if (deployments.length === 0) {
|
|
417
419
|
return Result.err(
|
|
418
|
-
new
|
|
420
|
+
new NoExistingDeploymentError({ appId: target.appId }),
|
|
419
421
|
);
|
|
420
422
|
}
|
|
421
423
|
|
|
@@ -432,8 +434,8 @@ export class ComputeClient {
|
|
|
432
434
|
yield* self.#checkAborted(options.signal);
|
|
433
435
|
|
|
434
436
|
const createResponse = yield* Result.await(
|
|
435
|
-
self.#api.
|
|
436
|
-
target.
|
|
437
|
+
self.#api.createAppDeployment(
|
|
438
|
+
target.appId,
|
|
437
439
|
{
|
|
438
440
|
...(options.portMapping !== undefined
|
|
439
441
|
? { portMapping: options.portMapping }
|
|
@@ -443,17 +445,17 @@ export class ComputeClient {
|
|
|
443
445
|
options.signal,
|
|
444
446
|
),
|
|
445
447
|
);
|
|
446
|
-
options.progress?.
|
|
448
|
+
options.progress?.onDeploymentCreated?.(createResponse.id);
|
|
447
449
|
|
|
448
450
|
yield* self.#checkAborted(options.signal);
|
|
449
451
|
|
|
450
452
|
options.progress?.onStartRequested?.();
|
|
451
453
|
yield* Result.await(
|
|
452
|
-
self.#api.
|
|
454
|
+
self.#api.startDeployment(createResponse.id, options.signal),
|
|
453
455
|
);
|
|
454
456
|
|
|
455
457
|
const pollResult = yield* Result.await(
|
|
456
|
-
|
|
458
|
+
pollDeploymentStatus(self.#api, createResponse.id, {
|
|
457
459
|
targetStatus: "running",
|
|
458
460
|
timeoutSeconds: options.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
|
|
459
461
|
pollIntervalMs: options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
@@ -467,13 +469,13 @@ export class ComputeClient {
|
|
|
467
469
|
|
|
468
470
|
return Result.ok({
|
|
469
471
|
projectId: target.projectId,
|
|
470
|
-
|
|
471
|
-
|
|
472
|
+
appId: target.appId,
|
|
473
|
+
deploymentId: createResponse.id,
|
|
472
474
|
deploymentUrl,
|
|
473
475
|
resolvedConfig: {
|
|
474
476
|
projectId: target.projectId,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
+
appId: target.appId,
|
|
478
|
+
appName: target.appName,
|
|
477
479
|
region: target.region,
|
|
478
480
|
portMapping: options.portMapping,
|
|
479
481
|
},
|
|
@@ -481,74 +483,83 @@ export class ComputeClient {
|
|
|
481
483
|
});
|
|
482
484
|
}
|
|
483
485
|
|
|
484
|
-
async
|
|
485
|
-
options:
|
|
486
|
-
): Promise<Result<
|
|
486
|
+
async destroyDeployment(
|
|
487
|
+
options: DestroyDeploymentOptions,
|
|
488
|
+
): Promise<Result<DestroyDeploymentResult, DestroyDeploymentError>> {
|
|
487
489
|
const self = this;
|
|
488
490
|
return Result.gen(async function* () {
|
|
489
491
|
yield* self.#checkAborted(options.signal);
|
|
490
492
|
|
|
491
|
-
let
|
|
492
|
-
let
|
|
493
|
+
let deploymentId = options.deploymentId;
|
|
494
|
+
let deploymentDetailsCache: Map<string, DeploymentDetailData> | undefined;
|
|
493
495
|
|
|
494
|
-
if (!
|
|
495
|
-
const
|
|
496
|
-
if (!
|
|
497
|
-
return Result.err(
|
|
496
|
+
if (!deploymentId) {
|
|
497
|
+
const appId = options.appId;
|
|
498
|
+
if (!appId) {
|
|
499
|
+
return Result.err(
|
|
500
|
+
new MissingArgumentError({ field: "deploymentId" }),
|
|
501
|
+
);
|
|
498
502
|
}
|
|
499
503
|
|
|
500
|
-
const
|
|
501
|
-
self.#api.
|
|
504
|
+
const deployments = yield* Result.await(
|
|
505
|
+
self.#api.listAppDeployments(appId, options.signal),
|
|
502
506
|
);
|
|
503
|
-
const
|
|
504
|
-
|
|
507
|
+
const deploymentDetailResults = await Promise.all(
|
|
508
|
+
deployments.map((d) => self.#api.getDeployment(d.id, options.signal)),
|
|
505
509
|
);
|
|
506
510
|
|
|
507
|
-
const details:
|
|
508
|
-
for (const result of
|
|
511
|
+
const details: DeploymentDetailData[] = [];
|
|
512
|
+
for (const result of deploymentDetailResults) {
|
|
509
513
|
if (result.isErr()) return result;
|
|
510
514
|
details.push(result.value);
|
|
511
515
|
}
|
|
512
516
|
|
|
513
|
-
|
|
517
|
+
deploymentDetailsCache = new Map(details.map((d) => [d.id, d]));
|
|
514
518
|
|
|
515
|
-
const
|
|
519
|
+
const deploymentInfos = details
|
|
516
520
|
.map(
|
|
517
|
-
(
|
|
518
|
-
id:
|
|
519
|
-
status:
|
|
520
|
-
createdAt:
|
|
521
|
-
previewDomain:
|
|
521
|
+
(d): DeploymentInfo => ({
|
|
522
|
+
id: d.id,
|
|
523
|
+
status: d.status,
|
|
524
|
+
createdAt: d.createdAt,
|
|
525
|
+
previewDomain: d.previewDomain,
|
|
522
526
|
}),
|
|
523
527
|
)
|
|
524
|
-
.sort(
|
|
528
|
+
.sort(deploymentSortComparator);
|
|
525
529
|
|
|
526
|
-
if (
|
|
527
|
-
return Result.err(new
|
|
530
|
+
if (deploymentInfos.length === 0) {
|
|
531
|
+
return Result.err(new NoDeploymentsFoundError({ appId }));
|
|
528
532
|
}
|
|
529
533
|
|
|
530
|
-
if (!options.interaction?.
|
|
531
|
-
return Result.err(
|
|
534
|
+
if (!options.interaction?.selectDeployment) {
|
|
535
|
+
return Result.err(
|
|
536
|
+
new MissingArgumentError({ field: "deploymentId" }),
|
|
537
|
+
);
|
|
532
538
|
}
|
|
533
539
|
|
|
534
|
-
|
|
540
|
+
deploymentId =
|
|
541
|
+
await options.interaction.selectDeployment(deploymentInfos);
|
|
535
542
|
}
|
|
536
543
|
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
(yield* Result.await(
|
|
544
|
+
const deployment =
|
|
545
|
+
deploymentDetailsCache?.get(deploymentId) ??
|
|
546
|
+
(yield* Result.await(
|
|
547
|
+
self.#api.getDeployment(deploymentId, options.signal),
|
|
548
|
+
));
|
|
540
549
|
|
|
541
|
-
const previousStatus =
|
|
550
|
+
const previousStatus = deployment.status ?? "unknown";
|
|
542
551
|
const shouldStop =
|
|
543
|
-
|
|
552
|
+
deployment.status === "running" || deployment.status === "provisioning";
|
|
544
553
|
let stopped = false;
|
|
545
554
|
|
|
546
555
|
if (shouldStop) {
|
|
547
|
-
options.progress?.onStopRequested?.(
|
|
548
|
-
yield* Result.await(
|
|
556
|
+
options.progress?.onStopRequested?.(deploymentId);
|
|
557
|
+
yield* Result.await(
|
|
558
|
+
self.#api.stopDeployment(deploymentId, options.signal),
|
|
559
|
+
);
|
|
549
560
|
|
|
550
561
|
yield* Result.await(
|
|
551
|
-
|
|
562
|
+
pollDeploymentStatus(self.#api, deploymentId, {
|
|
552
563
|
targetStatus: "stopped",
|
|
553
564
|
timeoutSeconds: options.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
|
|
554
565
|
pollIntervalMs: options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
@@ -556,14 +567,16 @@ export class ComputeClient {
|
|
|
556
567
|
}),
|
|
557
568
|
);
|
|
558
569
|
stopped = true;
|
|
559
|
-
options.progress?.onStopped?.(
|
|
570
|
+
options.progress?.onStopped?.(deploymentId);
|
|
560
571
|
}
|
|
561
572
|
|
|
562
|
-
yield* Result.await(
|
|
563
|
-
|
|
573
|
+
yield* Result.await(
|
|
574
|
+
self.#api.deleteDeployment(deploymentId, options.signal),
|
|
575
|
+
);
|
|
576
|
+
options.progress?.onDeleted?.(deploymentId);
|
|
564
577
|
|
|
565
578
|
return Result.ok({
|
|
566
|
-
|
|
579
|
+
deploymentId,
|
|
567
580
|
previousStatus,
|
|
568
581
|
stopped,
|
|
569
582
|
deleted: true,
|
|
@@ -571,9 +584,9 @@ export class ComputeClient {
|
|
|
571
584
|
});
|
|
572
585
|
}
|
|
573
586
|
|
|
574
|
-
async
|
|
575
|
-
options:
|
|
576
|
-
): Promise<Result<
|
|
587
|
+
async destroyApp(
|
|
588
|
+
options: DestroyAppOptions,
|
|
589
|
+
): Promise<Result<DestroyAppResult, DestroyAppError>> {
|
|
577
590
|
const self = this;
|
|
578
591
|
return Result.gen(async function* () {
|
|
579
592
|
yield* self.#checkAborted(options.signal);
|
|
@@ -581,57 +594,57 @@ export class ComputeClient {
|
|
|
581
594
|
const timeoutSeconds = options.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
|
|
582
595
|
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
583
596
|
|
|
584
|
-
const
|
|
585
|
-
self.#api.
|
|
597
|
+
const deployments = yield* Result.await(
|
|
598
|
+
self.#api.listAppDeployments(options.appId, options.signal),
|
|
586
599
|
);
|
|
587
|
-
const
|
|
588
|
-
|
|
600
|
+
const deploymentDetailResults = await Promise.all(
|
|
601
|
+
deployments.map((d) => self.#api.getDeployment(d.id, options.signal)),
|
|
589
602
|
);
|
|
590
603
|
|
|
591
|
-
const
|
|
592
|
-
for (const result of
|
|
604
|
+
const deploymentDetails: DeploymentDetailData[] = [];
|
|
605
|
+
for (const result of deploymentDetailResults) {
|
|
593
606
|
if (result.isErr()) return result;
|
|
594
|
-
|
|
607
|
+
deploymentDetails.push(result.value);
|
|
595
608
|
}
|
|
596
609
|
|
|
597
|
-
const
|
|
598
|
-
(
|
|
610
|
+
const activeDeployments = deploymentDetails.filter(
|
|
611
|
+
(d) => d.status === "running" || d.status === "provisioning",
|
|
599
612
|
);
|
|
600
613
|
|
|
601
614
|
const succeededIds: string[] = [];
|
|
602
615
|
const failures: Array<{
|
|
603
|
-
|
|
604
|
-
error:
|
|
616
|
+
deploymentId: string;
|
|
617
|
+
error: DeploymentOperationError;
|
|
605
618
|
}> = [];
|
|
606
619
|
|
|
607
|
-
if (
|
|
608
|
-
const activeIds =
|
|
609
|
-
options.progress?.
|
|
620
|
+
if (activeDeployments.length > 0) {
|
|
621
|
+
const activeIds = activeDeployments.map((d) => d.id);
|
|
622
|
+
options.progress?.onStoppingDeployments?.(activeIds);
|
|
610
623
|
|
|
611
624
|
const stopResults = await Promise.all(
|
|
612
|
-
|
|
613
|
-
self.#api.
|
|
625
|
+
activeDeployments.map((d) =>
|
|
626
|
+
self.#api.stopDeployment(d.id, options.signal),
|
|
614
627
|
),
|
|
615
628
|
);
|
|
616
629
|
|
|
617
|
-
const stoppedCandidates: typeof
|
|
630
|
+
const stoppedCandidates: typeof activeDeployments = [];
|
|
618
631
|
for (const [i, result] of stopResults.entries()) {
|
|
619
632
|
// biome-ignore lint/style/noNonNullAssertion: both lists have the same length
|
|
620
|
-
const
|
|
633
|
+
const activeDeployment = activeDeployments[i]!;
|
|
621
634
|
if (result.isErr()) {
|
|
622
635
|
failures.push({
|
|
623
|
-
|
|
636
|
+
deploymentId: activeDeployment.id,
|
|
624
637
|
error: result.error,
|
|
625
638
|
});
|
|
626
639
|
} else {
|
|
627
|
-
stoppedCandidates.push(
|
|
640
|
+
stoppedCandidates.push(activeDeployment);
|
|
628
641
|
}
|
|
629
642
|
}
|
|
630
643
|
|
|
631
644
|
if (stoppedCandidates.length > 0) {
|
|
632
645
|
const pollResults = await Promise.all(
|
|
633
|
-
stoppedCandidates.map((
|
|
634
|
-
|
|
646
|
+
stoppedCandidates.map((d) =>
|
|
647
|
+
pollDeploymentStatus(self.#api, d.id, {
|
|
635
648
|
targetStatus: "stopped",
|
|
636
649
|
timeoutSeconds,
|
|
637
650
|
pollIntervalMs,
|
|
@@ -642,14 +655,14 @@ export class ComputeClient {
|
|
|
642
655
|
|
|
643
656
|
for (const [i, result] of pollResults.entries()) {
|
|
644
657
|
// biome-ignore lint/style/noNonNullAssertion: both lists have the same length
|
|
645
|
-
const
|
|
658
|
+
const stoppedDeployment = stoppedCandidates[i]!;
|
|
646
659
|
if (result.isErr()) {
|
|
647
660
|
failures.push({
|
|
648
|
-
|
|
661
|
+
deploymentId: stoppedDeployment.id,
|
|
649
662
|
error: result.error,
|
|
650
663
|
});
|
|
651
664
|
} else {
|
|
652
|
-
options.progress?.
|
|
665
|
+
options.progress?.onDeploymentStopped?.(stoppedDeployment.id);
|
|
653
666
|
}
|
|
654
667
|
}
|
|
655
668
|
}
|
|
@@ -657,64 +670,64 @@ export class ComputeClient {
|
|
|
657
670
|
if (failures.length > 0) {
|
|
658
671
|
return Result.err(
|
|
659
672
|
new DestroyAggregateError({
|
|
660
|
-
|
|
673
|
+
succeededDeploymentIds: succeededIds,
|
|
661
674
|
failures,
|
|
662
|
-
|
|
675
|
+
appDeleted: false,
|
|
663
676
|
}),
|
|
664
677
|
);
|
|
665
678
|
}
|
|
666
679
|
|
|
667
|
-
options.progress?.
|
|
680
|
+
options.progress?.onAllDeploymentsStopped?.();
|
|
668
681
|
}
|
|
669
682
|
|
|
670
|
-
if (
|
|
671
|
-
const
|
|
672
|
-
options.progress?.
|
|
683
|
+
if (deployments.length > 0) {
|
|
684
|
+
const deploymentIds = deployments.map((d) => d.id);
|
|
685
|
+
options.progress?.onDeletingDeployments?.(deploymentIds);
|
|
673
686
|
|
|
674
687
|
const deleteResults = await Promise.all(
|
|
675
|
-
|
|
688
|
+
deployments.map((d) =>
|
|
689
|
+
self.#api.deleteDeployment(d.id, options.signal),
|
|
690
|
+
),
|
|
676
691
|
);
|
|
677
692
|
|
|
678
693
|
for (const [i, result] of deleteResults.entries()) {
|
|
679
694
|
// biome-ignore lint/style/noNonNullAssertion: both lists have the same length
|
|
680
|
-
const
|
|
695
|
+
const deployment = deployments[i]!;
|
|
681
696
|
if (result.isErr()) {
|
|
682
697
|
failures.push({
|
|
683
|
-
|
|
698
|
+
deploymentId: deployment.id,
|
|
684
699
|
error: result.error,
|
|
685
700
|
});
|
|
686
701
|
} else {
|
|
687
|
-
succeededIds.push(
|
|
688
|
-
options.progress?.
|
|
702
|
+
succeededIds.push(deployment.id);
|
|
703
|
+
options.progress?.onDeploymentDeleted?.(deployment.id);
|
|
689
704
|
}
|
|
690
705
|
}
|
|
691
706
|
|
|
692
707
|
if (failures.length > 0) {
|
|
693
708
|
return Result.err(
|
|
694
709
|
new DestroyAggregateError({
|
|
695
|
-
|
|
710
|
+
succeededDeploymentIds: succeededIds,
|
|
696
711
|
failures,
|
|
697
|
-
|
|
712
|
+
appDeleted: false,
|
|
698
713
|
}),
|
|
699
714
|
);
|
|
700
715
|
}
|
|
701
716
|
|
|
702
|
-
options.progress?.
|
|
717
|
+
options.progress?.onAllDeploymentsDeleted?.();
|
|
703
718
|
}
|
|
704
719
|
|
|
705
|
-
let
|
|
706
|
-
if (!options.
|
|
707
|
-
yield* Result.await(
|
|
708
|
-
|
|
709
|
-
);
|
|
710
|
-
serviceDeleted = true;
|
|
711
|
-
options.progress?.onServiceDeleted?.(options.serviceId);
|
|
720
|
+
let appDeleted = false;
|
|
721
|
+
if (!options.keepApp) {
|
|
722
|
+
yield* Result.await(self.#api.deleteApp(options.appId, options.signal));
|
|
723
|
+
appDeleted = true;
|
|
724
|
+
options.progress?.onAppDeleted?.(options.appId);
|
|
712
725
|
}
|
|
713
726
|
|
|
714
727
|
return Result.ok({
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
728
|
+
appId: options.appId,
|
|
729
|
+
deletedDeploymentIds: succeededIds,
|
|
730
|
+
appDeleted,
|
|
718
731
|
});
|
|
719
732
|
});
|
|
720
733
|
}
|
|
@@ -779,39 +792,39 @@ export class ComputeClient {
|
|
|
779
792
|
});
|
|
780
793
|
}
|
|
781
794
|
|
|
782
|
-
async
|
|
783
|
-
options:
|
|
784
|
-
): Promise<Result<
|
|
795
|
+
async listApps(
|
|
796
|
+
options: ListAppsOptions,
|
|
797
|
+
): Promise<Result<AppInfo[], ApiRequestError>> {
|
|
785
798
|
const self = this;
|
|
786
799
|
return Result.gen(async function* () {
|
|
787
800
|
yield* self.#checkAborted(options.signal);
|
|
788
|
-
const
|
|
789
|
-
self.#api.
|
|
801
|
+
const apps = yield* Result.await(
|
|
802
|
+
self.#api.listProjectApps(options.projectId, options.signal),
|
|
790
803
|
);
|
|
791
804
|
return Result.ok(
|
|
792
|
-
|
|
793
|
-
(
|
|
794
|
-
id:
|
|
795
|
-
name:
|
|
796
|
-
region:
|
|
797
|
-
projectId:
|
|
805
|
+
apps.map(
|
|
806
|
+
(a): AppInfo => ({
|
|
807
|
+
id: a.id,
|
|
808
|
+
name: a.name,
|
|
809
|
+
region: a.region.id,
|
|
810
|
+
projectId: a.projectId,
|
|
798
811
|
}),
|
|
799
812
|
),
|
|
800
813
|
);
|
|
801
814
|
});
|
|
802
815
|
}
|
|
803
816
|
|
|
804
|
-
async
|
|
805
|
-
options:
|
|
806
|
-
): Promise<Result<
|
|
817
|
+
async createApp(
|
|
818
|
+
options: CreateAppOptions,
|
|
819
|
+
): Promise<Result<AppInfo, ApiRequestError>> {
|
|
807
820
|
const self = this;
|
|
808
821
|
return Result.gen(async function* () {
|
|
809
822
|
yield* self.#checkAborted(options.signal);
|
|
810
823
|
const response = yield* Result.await(
|
|
811
|
-
self.#api.
|
|
824
|
+
self.#api.createProjectApp(
|
|
812
825
|
options.projectId,
|
|
813
826
|
{
|
|
814
|
-
displayName: options.
|
|
827
|
+
displayName: options.appName,
|
|
815
828
|
regionId: options.region,
|
|
816
829
|
},
|
|
817
830
|
options.signal,
|
|
@@ -826,56 +839,54 @@ export class ComputeClient {
|
|
|
826
839
|
});
|
|
827
840
|
}
|
|
828
841
|
|
|
829
|
-
async
|
|
830
|
-
options:
|
|
831
|
-
): Promise<Result<
|
|
842
|
+
async showApp(
|
|
843
|
+
options: ShowAppOptions,
|
|
844
|
+
): Promise<Result<AppDetail, ApiRequestError>> {
|
|
832
845
|
const self = this;
|
|
833
846
|
return Result.gen(async function* () {
|
|
834
847
|
yield* self.#checkAborted(options.signal);
|
|
835
|
-
const
|
|
836
|
-
self.#api.
|
|
848
|
+
const a = yield* Result.await(
|
|
849
|
+
self.#api.getApp(options.appId, options.signal),
|
|
837
850
|
);
|
|
838
851
|
return Result.ok({
|
|
839
|
-
id:
|
|
840
|
-
name:
|
|
841
|
-
region:
|
|
842
|
-
projectId:
|
|
843
|
-
|
|
844
|
-
|
|
852
|
+
id: a.id,
|
|
853
|
+
name: a.name,
|
|
854
|
+
region: a.region.id,
|
|
855
|
+
projectId: a.projectId,
|
|
856
|
+
latestDeploymentId: a.latestDeploymentId,
|
|
857
|
+
appEndpointDomain: a.appEndpointDomain,
|
|
845
858
|
});
|
|
846
859
|
});
|
|
847
860
|
}
|
|
848
861
|
|
|
849
|
-
async
|
|
850
|
-
options:
|
|
862
|
+
async deleteApp(
|
|
863
|
+
options: DeleteAppOptions,
|
|
851
864
|
): Promise<Result<void, ApiRequestError>> {
|
|
852
865
|
const self = this;
|
|
853
866
|
return Result.gen(async function* () {
|
|
854
867
|
yield* self.#checkAborted(options.signal);
|
|
855
|
-
yield* Result.await(
|
|
856
|
-
self.#api.deleteService(options.serviceId, options.signal),
|
|
857
|
-
);
|
|
868
|
+
yield* Result.await(self.#api.deleteApp(options.appId, options.signal));
|
|
858
869
|
return Result.ok();
|
|
859
870
|
});
|
|
860
871
|
}
|
|
861
872
|
|
|
862
|
-
async
|
|
863
|
-
options:
|
|
864
|
-
): Promise<Result<
|
|
873
|
+
async listDeployments(
|
|
874
|
+
options: ListDeploymentsOptions,
|
|
875
|
+
): Promise<Result<DeploymentInfo[], ApiRequestError>> {
|
|
865
876
|
const self = this;
|
|
866
877
|
return Result.gen(async function* () {
|
|
867
878
|
yield* self.#checkAborted(options.signal);
|
|
868
|
-
const
|
|
869
|
-
self.#api.
|
|
879
|
+
const deployments = yield* Result.await(
|
|
880
|
+
self.#api.listAppDeployments(options.appId, options.signal),
|
|
870
881
|
);
|
|
871
882
|
const detailResults = await Promise.all(
|
|
872
|
-
|
|
883
|
+
deployments.map((d) => self.#api.getDeployment(d.id, options.signal)),
|
|
873
884
|
);
|
|
874
|
-
const details:
|
|
885
|
+
const details: DeploymentDetailData[] = [];
|
|
875
886
|
for (const result of detailResults) {
|
|
876
887
|
if (result.isErr()) {
|
|
877
|
-
//
|
|
878
|
-
// and can't be fetched using
|
|
888
|
+
// listAppDeployments returns deployments that have previously been deleted
|
|
889
|
+
// and can't be fetched using getDeployment so we need to filter those out.
|
|
879
890
|
if (ApiError.is(result.error) && result.error.statusCode === 404)
|
|
880
891
|
continue;
|
|
881
892
|
return result;
|
|
@@ -884,70 +895,70 @@ export class ComputeClient {
|
|
|
884
895
|
}
|
|
885
896
|
return Result.ok(
|
|
886
897
|
details.map(
|
|
887
|
-
(
|
|
888
|
-
id:
|
|
889
|
-
status:
|
|
890
|
-
createdAt:
|
|
891
|
-
previewDomain:
|
|
898
|
+
(d): DeploymentInfo => ({
|
|
899
|
+
id: d.id,
|
|
900
|
+
status: d.status,
|
|
901
|
+
createdAt: d.createdAt,
|
|
902
|
+
previewDomain: d.previewDomain,
|
|
892
903
|
}),
|
|
893
904
|
),
|
|
894
905
|
);
|
|
895
906
|
});
|
|
896
907
|
}
|
|
897
908
|
|
|
898
|
-
async
|
|
899
|
-
options:
|
|
900
|
-
): Promise<Result<
|
|
909
|
+
async showDeployment(
|
|
910
|
+
options: ShowDeploymentOptions,
|
|
911
|
+
): Promise<Result<DeploymentDetail, ApiRequestError>> {
|
|
901
912
|
const self = this;
|
|
902
913
|
return Result.gen(async function* () {
|
|
903
914
|
yield* self.#checkAborted(options.signal);
|
|
904
|
-
const
|
|
905
|
-
self.#api.
|
|
915
|
+
const d = yield* Result.await(
|
|
916
|
+
self.#api.getDeployment(options.deploymentId, options.signal),
|
|
906
917
|
);
|
|
907
918
|
return Result.ok({
|
|
908
|
-
id:
|
|
909
|
-
status:
|
|
910
|
-
createdAt:
|
|
911
|
-
previewDomain:
|
|
912
|
-
envVars:
|
|
919
|
+
id: d.id,
|
|
920
|
+
status: d.status,
|
|
921
|
+
createdAt: d.createdAt,
|
|
922
|
+
previewDomain: d.previewDomain,
|
|
923
|
+
envVars: d.envVars ?? undefined,
|
|
913
924
|
});
|
|
914
925
|
});
|
|
915
926
|
}
|
|
916
927
|
|
|
917
|
-
async
|
|
918
|
-
options:
|
|
928
|
+
async startDeployment(
|
|
929
|
+
options: StartDeploymentOptions,
|
|
919
930
|
): Promise<Result<void, ApiRequestError>> {
|
|
920
931
|
const self = this;
|
|
921
932
|
return Result.gen(async function* () {
|
|
922
933
|
yield* self.#checkAborted(options.signal);
|
|
923
934
|
yield* Result.await(
|
|
924
|
-
self.#api.
|
|
935
|
+
self.#api.startDeployment(options.deploymentId, options.signal),
|
|
925
936
|
);
|
|
926
937
|
return Result.ok();
|
|
927
938
|
});
|
|
928
939
|
}
|
|
929
940
|
|
|
930
|
-
async
|
|
931
|
-
options:
|
|
941
|
+
async stopDeployment(
|
|
942
|
+
options: StopDeploymentOptions,
|
|
932
943
|
): Promise<Result<void, ApiRequestError>> {
|
|
933
944
|
const self = this;
|
|
934
945
|
return Result.gen(async function* () {
|
|
935
946
|
yield* self.#checkAborted(options.signal);
|
|
936
947
|
yield* Result.await(
|
|
937
|
-
self.#api.
|
|
948
|
+
self.#api.stopDeployment(options.deploymentId, options.signal),
|
|
938
949
|
);
|
|
939
950
|
return Result.ok();
|
|
940
951
|
});
|
|
941
952
|
}
|
|
942
953
|
|
|
943
|
-
async
|
|
944
|
-
options:
|
|
954
|
+
async deleteDeployment(
|
|
955
|
+
options: DeleteDeploymentOptions,
|
|
945
956
|
): Promise<Result<void, ApiRequestError>> {
|
|
946
957
|
const self = this;
|
|
947
958
|
return Result.gen(async function* () {
|
|
948
959
|
yield* self.#checkAborted(options.signal);
|
|
949
960
|
yield* Result.await(
|
|
950
|
-
self.#api.
|
|
961
|
+
self.#api.deleteDeployment(options.deploymentId, options.signal),
|
|
951
962
|
);
|
|
952
963
|
return Result.ok();
|
|
953
964
|
});
|
|
@@ -960,16 +971,16 @@ export class ComputeClient {
|
|
|
960
971
|
return Result.gen(async function* () {
|
|
961
972
|
yield* self.#checkAborted(options.signal);
|
|
962
973
|
|
|
963
|
-
let
|
|
974
|
+
let deploymentId = options.deploymentId;
|
|
964
975
|
|
|
965
|
-
if (!
|
|
966
|
-
const
|
|
967
|
-
self.#api.
|
|
976
|
+
if (!deploymentId) {
|
|
977
|
+
const deployments = yield* Result.await(
|
|
978
|
+
self.#api.listAppDeployments(options.appId, options.signal),
|
|
968
979
|
);
|
|
969
980
|
const detailResults = await Promise.all(
|
|
970
|
-
|
|
981
|
+
deployments.map((d) => self.#api.getDeployment(d.id, options.signal)),
|
|
971
982
|
);
|
|
972
|
-
const details:
|
|
983
|
+
const details: DeploymentDetailData[] = [];
|
|
973
984
|
for (const result of detailResults) {
|
|
974
985
|
if (result.isErr()) {
|
|
975
986
|
if (ApiError.is(result.error) && result.error.statusCode === 404)
|
|
@@ -979,42 +990,45 @@ export class ComputeClient {
|
|
|
979
990
|
details.push(result.value);
|
|
980
991
|
}
|
|
981
992
|
|
|
982
|
-
const
|
|
993
|
+
const deploymentInfos = details
|
|
983
994
|
.map(
|
|
984
|
-
(
|
|
985
|
-
id:
|
|
986
|
-
status:
|
|
987
|
-
createdAt:
|
|
988
|
-
previewDomain:
|
|
995
|
+
(d): DeploymentInfo => ({
|
|
996
|
+
id: d.id,
|
|
997
|
+
status: d.status,
|
|
998
|
+
createdAt: d.createdAt,
|
|
999
|
+
previewDomain: d.previewDomain,
|
|
989
1000
|
}),
|
|
990
1001
|
)
|
|
991
|
-
.sort(
|
|
1002
|
+
.sort(deploymentSortComparator);
|
|
992
1003
|
|
|
993
|
-
if (
|
|
1004
|
+
if (deploymentInfos.length === 0) {
|
|
994
1005
|
return Result.err(
|
|
995
|
-
new
|
|
1006
|
+
new NoDeploymentsFoundError({ appId: options.appId }),
|
|
996
1007
|
);
|
|
997
1008
|
}
|
|
998
1009
|
|
|
999
|
-
if (!options.interaction?.
|
|
1000
|
-
return Result.err(
|
|
1010
|
+
if (!options.interaction?.selectDeployment) {
|
|
1011
|
+
return Result.err(
|
|
1012
|
+
new MissingArgumentError({ field: "deploymentId" }),
|
|
1013
|
+
);
|
|
1001
1014
|
}
|
|
1002
1015
|
|
|
1003
|
-
|
|
1016
|
+
deploymentId =
|
|
1017
|
+
await options.interaction.selectDeployment(deploymentInfos);
|
|
1004
1018
|
}
|
|
1005
1019
|
|
|
1006
|
-
const
|
|
1007
|
-
self.#api.
|
|
1020
|
+
const deployment = yield* Result.await(
|
|
1021
|
+
self.#api.getDeployment(deploymentId, options.signal),
|
|
1008
1022
|
);
|
|
1009
|
-
let
|
|
1023
|
+
let deploymentStarted = false;
|
|
1010
1024
|
|
|
1011
|
-
if (
|
|
1012
|
-
options.progress?.
|
|
1025
|
+
if (deployment.status !== "running") {
|
|
1026
|
+
options.progress?.onDeploymentStarting?.(deploymentId);
|
|
1013
1027
|
|
|
1014
|
-
if (
|
|
1015
|
-
options.progress?.
|
|
1016
|
-
const startResult = await self.#api.
|
|
1017
|
-
|
|
1028
|
+
if (deployment.status !== "provisioning") {
|
|
1029
|
+
options.progress?.onDeploymentStartRequested?.();
|
|
1030
|
+
const startResult = await self.#api.startDeployment(
|
|
1031
|
+
deploymentId,
|
|
1018
1032
|
options.signal,
|
|
1019
1033
|
);
|
|
1020
1034
|
if (startResult.isErr()) {
|
|
@@ -1023,7 +1037,7 @@ export class ComputeClient {
|
|
|
1023
1037
|
}
|
|
1024
1038
|
}
|
|
1025
1039
|
|
|
1026
|
-
const pollResult = await
|
|
1040
|
+
const pollResult = await pollDeploymentStatus(self.#api, deploymentId, {
|
|
1027
1041
|
targetStatus: "running",
|
|
1028
1042
|
timeoutSeconds: options.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
|
|
1029
1043
|
pollIntervalMs: options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
@@ -1034,75 +1048,82 @@ export class ComputeClient {
|
|
|
1034
1048
|
options.progress?.onPromoteFailed?.(pollResult.error);
|
|
1035
1049
|
return pollResult;
|
|
1036
1050
|
}
|
|
1037
|
-
|
|
1038
|
-
options.progress?.
|
|
1051
|
+
deploymentStarted = true;
|
|
1052
|
+
options.progress?.onDeploymentRunning?.();
|
|
1039
1053
|
}
|
|
1040
1054
|
|
|
1041
1055
|
options.progress?.onPromoteStart?.();
|
|
1042
|
-
const promoteResult = await self.#api.
|
|
1043
|
-
options.
|
|
1044
|
-
{
|
|
1056
|
+
const promoteResult = await self.#api.promoteApp(
|
|
1057
|
+
options.appId,
|
|
1058
|
+
{ deploymentId },
|
|
1045
1059
|
options.signal,
|
|
1046
1060
|
);
|
|
1047
1061
|
if (promoteResult.isErr()) {
|
|
1048
1062
|
options.progress?.onPromoteFailed?.(promoteResult.error);
|
|
1049
1063
|
return promoteResult;
|
|
1050
1064
|
}
|
|
1051
|
-
options.progress?.onPromoted?.(promoteResult.value.
|
|
1065
|
+
options.progress?.onPromoted?.(promoteResult.value.appEndpointDomain);
|
|
1052
1066
|
|
|
1053
1067
|
return Result.ok({
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1068
|
+
appId: options.appId,
|
|
1069
|
+
deploymentId,
|
|
1070
|
+
appEndpointDomain: promoteResult.value.appEndpointDomain,
|
|
1071
|
+
deploymentStarted,
|
|
1058
1072
|
});
|
|
1059
1073
|
});
|
|
1060
1074
|
}
|
|
1061
1075
|
|
|
1062
1076
|
async #promoteAndSwitchover(
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1077
|
+
appId: string,
|
|
1078
|
+
newDeploymentId: string,
|
|
1079
|
+
previousDeploymentId: string | null,
|
|
1080
|
+
destroyOldDeployment: boolean,
|
|
1067
1081
|
signal?: AbortSignal,
|
|
1068
1082
|
progress?: DeployProgress,
|
|
1069
1083
|
): Promise<
|
|
1070
1084
|
Result<
|
|
1071
1085
|
{
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1086
|
+
appEndpointDomain: string;
|
|
1087
|
+
previousDeploymentId: string | null;
|
|
1088
|
+
previousDeploymentAction: "stopped" | "destroyed" | null;
|
|
1075
1089
|
},
|
|
1076
1090
|
DeployError
|
|
1077
1091
|
>
|
|
1078
1092
|
> {
|
|
1079
1093
|
progress?.onPromoteStart?.();
|
|
1080
|
-
const promoteResult = await this.#api.
|
|
1081
|
-
|
|
1082
|
-
{
|
|
1094
|
+
const promoteResult = await this.#api.promoteApp(
|
|
1095
|
+
appId,
|
|
1096
|
+
{ deploymentId: newDeploymentId },
|
|
1083
1097
|
signal,
|
|
1084
1098
|
);
|
|
1085
1099
|
|
|
1086
1100
|
if (promoteResult.isErr()) {
|
|
1087
1101
|
progress?.onPromoteFailed?.(promoteResult.error);
|
|
1088
|
-
progress?.
|
|
1089
|
-
await this.#
|
|
1102
|
+
progress?.onCleanupDanglingDeployment?.(newDeploymentId);
|
|
1103
|
+
await this.#cleanupDanglingDeployment(
|
|
1104
|
+
newDeploymentId,
|
|
1105
|
+
undefined,
|
|
1106
|
+
progress,
|
|
1107
|
+
);
|
|
1090
1108
|
return promoteResult;
|
|
1091
1109
|
}
|
|
1092
1110
|
|
|
1093
|
-
const
|
|
1094
|
-
progress?.onPromoted?.(
|
|
1111
|
+
const appEndpointDomain = promoteResult.value.appEndpointDomain;
|
|
1112
|
+
progress?.onPromoted?.(appEndpointDomain);
|
|
1095
1113
|
|
|
1096
|
-
let
|
|
1114
|
+
let previousDeploymentAction: "stopped" | "destroyed" | null = null;
|
|
1097
1115
|
|
|
1098
|
-
if (
|
|
1099
|
-
progress?.
|
|
1100
|
-
const stopResult = await this.#api.
|
|
1116
|
+
if (previousDeploymentId && previousDeploymentId !== newDeploymentId) {
|
|
1117
|
+
progress?.onOldDeploymentStopping?.(previousDeploymentId);
|
|
1118
|
+
const stopResult = await this.#api.stopDeployment(
|
|
1119
|
+
previousDeploymentId,
|
|
1120
|
+
signal,
|
|
1121
|
+
);
|
|
1101
1122
|
|
|
1102
1123
|
if (stopResult.isOk()) {
|
|
1103
|
-
const pollResult = await
|
|
1124
|
+
const pollResult = await pollDeploymentStatus(
|
|
1104
1125
|
this.#api,
|
|
1105
|
-
|
|
1126
|
+
previousDeploymentId,
|
|
1106
1127
|
{
|
|
1107
1128
|
targetStatus: "stopped",
|
|
1108
1129
|
timeoutSeconds: 30,
|
|
@@ -1112,66 +1133,66 @@ export class ComputeClient {
|
|
|
1112
1133
|
);
|
|
1113
1134
|
|
|
1114
1135
|
if (pollResult.isOk()) {
|
|
1115
|
-
|
|
1116
|
-
progress?.
|
|
1136
|
+
previousDeploymentAction = "stopped";
|
|
1137
|
+
progress?.onOldDeploymentStopped?.(previousDeploymentId);
|
|
1117
1138
|
|
|
1118
|
-
if (
|
|
1119
|
-
progress?.
|
|
1120
|
-
const deleteResult = await this.#api.
|
|
1121
|
-
|
|
1139
|
+
if (destroyOldDeployment) {
|
|
1140
|
+
progress?.onOldDeploymentDeleting?.(previousDeploymentId);
|
|
1141
|
+
const deleteResult = await this.#api.deleteDeployment(
|
|
1142
|
+
previousDeploymentId,
|
|
1122
1143
|
signal,
|
|
1123
1144
|
);
|
|
1124
1145
|
if (deleteResult.isOk()) {
|
|
1125
|
-
|
|
1126
|
-
progress?.
|
|
1146
|
+
previousDeploymentAction = "destroyed";
|
|
1147
|
+
progress?.onOldDeploymentDeleted?.(previousDeploymentId);
|
|
1127
1148
|
} else {
|
|
1128
|
-
progress?.
|
|
1149
|
+
progress?.onOldDeploymentDeleteFailed?.(previousDeploymentId);
|
|
1129
1150
|
}
|
|
1130
1151
|
}
|
|
1131
1152
|
} else {
|
|
1132
|
-
progress?.
|
|
1153
|
+
progress?.onOldDeploymentStopFailed?.(previousDeploymentId);
|
|
1133
1154
|
}
|
|
1134
1155
|
} else {
|
|
1135
|
-
progress?.
|
|
1156
|
+
progress?.onOldDeploymentStopFailed?.(previousDeploymentId);
|
|
1136
1157
|
}
|
|
1137
1158
|
}
|
|
1138
1159
|
|
|
1139
1160
|
return Result.ok({
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1161
|
+
appEndpointDomain,
|
|
1162
|
+
previousDeploymentId,
|
|
1163
|
+
previousDeploymentAction,
|
|
1143
1164
|
});
|
|
1144
1165
|
}
|
|
1145
1166
|
|
|
1146
|
-
async #
|
|
1147
|
-
|
|
1167
|
+
async #cleanupDanglingDeployment(
|
|
1168
|
+
deploymentId: string,
|
|
1148
1169
|
signal?: AbortSignal,
|
|
1149
1170
|
progress?: DeployProgress,
|
|
1150
1171
|
): Promise<void> {
|
|
1151
|
-
const stopResult = await this.#api.
|
|
1172
|
+
const stopResult = await this.#api.stopDeployment(deploymentId, signal);
|
|
1152
1173
|
if (stopResult.isErr()) {
|
|
1153
|
-
progress?.
|
|
1174
|
+
progress?.onCleanupDanglingDeploymentFailed?.(deploymentId);
|
|
1154
1175
|
return;
|
|
1155
1176
|
}
|
|
1156
1177
|
|
|
1157
|
-
const pollResult = await
|
|
1178
|
+
const pollResult = await pollDeploymentStatus(this.#api, deploymentId, {
|
|
1158
1179
|
targetStatus: "stopped",
|
|
1159
1180
|
timeoutSeconds: 30,
|
|
1160
1181
|
pollIntervalMs: 1000,
|
|
1161
1182
|
signal,
|
|
1162
1183
|
});
|
|
1163
1184
|
if (pollResult.isErr()) {
|
|
1164
|
-
progress?.
|
|
1185
|
+
progress?.onCleanupDanglingDeploymentFailed?.(deploymentId);
|
|
1165
1186
|
return;
|
|
1166
1187
|
}
|
|
1167
1188
|
|
|
1168
|
-
const deleteResult = await this.#api.
|
|
1189
|
+
const deleteResult = await this.#api.deleteDeployment(deploymentId, signal);
|
|
1169
1190
|
if (deleteResult.isErr()) {
|
|
1170
|
-
progress?.
|
|
1191
|
+
progress?.onCleanupDanglingDeploymentFailed?.(deploymentId);
|
|
1171
1192
|
return;
|
|
1172
1193
|
}
|
|
1173
1194
|
|
|
1174
|
-
progress?.
|
|
1195
|
+
progress?.onCleanupDanglingDeploymentComplete?.(deploymentId);
|
|
1175
1196
|
}
|
|
1176
1197
|
|
|
1177
1198
|
#checkAborted(signal?: AbortSignal): Result<void, CancelledError> {
|
|
@@ -1185,8 +1206,8 @@ export class ComputeClient {
|
|
|
1185
1206
|
|
|
1186
1207
|
async #resolveDeployTarget(options: {
|
|
1187
1208
|
projectId?: string;
|
|
1188
|
-
|
|
1189
|
-
|
|
1209
|
+
appId?: string;
|
|
1210
|
+
appName?: string;
|
|
1190
1211
|
region?: string;
|
|
1191
1212
|
signal?: AbortSignal;
|
|
1192
1213
|
interaction?: DeployInteraction;
|
|
@@ -1194,11 +1215,11 @@ export class ComputeClient {
|
|
|
1194
1215
|
Result<
|
|
1195
1216
|
{
|
|
1196
1217
|
projectId: string;
|
|
1197
|
-
|
|
1198
|
-
|
|
1218
|
+
appId: string;
|
|
1219
|
+
appName: string;
|
|
1199
1220
|
region: string;
|
|
1200
1221
|
branchId: string | null;
|
|
1201
|
-
|
|
1222
|
+
isNewApp: boolean;
|
|
1202
1223
|
},
|
|
1203
1224
|
| MissingArgumentError
|
|
1204
1225
|
| CancelledError
|
|
@@ -1209,32 +1230,32 @@ export class ComputeClient {
|
|
|
1209
1230
|
> {
|
|
1210
1231
|
const self = this;
|
|
1211
1232
|
return Result.gen(async function* () {
|
|
1212
|
-
if (options.
|
|
1213
|
-
const
|
|
1214
|
-
self.#api.
|
|
1233
|
+
if (options.appId) {
|
|
1234
|
+
const app = yield* Result.await(
|
|
1235
|
+
self.#api.getApp(options.appId, options.signal),
|
|
1215
1236
|
);
|
|
1216
|
-
if (!
|
|
1237
|
+
if (!app.projectId) {
|
|
1217
1238
|
return Result.err(new MissingArgumentError({ field: "projectId" }));
|
|
1218
1239
|
}
|
|
1219
1240
|
const requestedProjectId = options.projectId?.replace(/^proj_/, "");
|
|
1220
|
-
const
|
|
1241
|
+
const appProjectId = app.projectId.replace(/^proj_/, "");
|
|
1221
1242
|
if (
|
|
1222
1243
|
requestedProjectId !== undefined &&
|
|
1223
|
-
requestedProjectId !==
|
|
1244
|
+
requestedProjectId !== appProjectId
|
|
1224
1245
|
) {
|
|
1225
1246
|
return Result.err(
|
|
1226
1247
|
new InvalidOptionsError({
|
|
1227
|
-
message: `
|
|
1248
|
+
message: `App ${app.id} belongs to project ${app.projectId}, but project ${options.projectId} was provided`,
|
|
1228
1249
|
}),
|
|
1229
1250
|
);
|
|
1230
1251
|
}
|
|
1231
1252
|
return Result.ok({
|
|
1232
|
-
projectId:
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
region:
|
|
1236
|
-
branchId:
|
|
1237
|
-
|
|
1253
|
+
projectId: app.projectId,
|
|
1254
|
+
appId: app.id,
|
|
1255
|
+
appName: app.name ?? app.id,
|
|
1256
|
+
region: app.region.id,
|
|
1257
|
+
branchId: app.branchId ?? null,
|
|
1258
|
+
isNewApp: false,
|
|
1238
1259
|
});
|
|
1239
1260
|
}
|
|
1240
1261
|
|
|
@@ -1258,12 +1279,12 @@ export class ComputeClient {
|
|
|
1258
1279
|
projectId = await options.interaction.selectProject(projectInfos);
|
|
1259
1280
|
}
|
|
1260
1281
|
|
|
1261
|
-
if (options.
|
|
1282
|
+
if (options.appName && options.region) {
|
|
1262
1283
|
const response = yield* Result.await(
|
|
1263
|
-
self.#api.
|
|
1284
|
+
self.#api.createProjectApp(
|
|
1264
1285
|
projectId,
|
|
1265
1286
|
{
|
|
1266
|
-
displayName: options.
|
|
1287
|
+
displayName: options.appName,
|
|
1267
1288
|
regionId: options.region,
|
|
1268
1289
|
},
|
|
1269
1290
|
options.signal,
|
|
@@ -1271,58 +1292,54 @@ export class ComputeClient {
|
|
|
1271
1292
|
);
|
|
1272
1293
|
return Result.ok({
|
|
1273
1294
|
projectId,
|
|
1274
|
-
|
|
1275
|
-
|
|
1295
|
+
appId: response.id,
|
|
1296
|
+
appName: response.name,
|
|
1276
1297
|
region: response.region.id,
|
|
1277
1298
|
branchId: response.branchId ?? null,
|
|
1278
|
-
|
|
1299
|
+
isNewApp: true,
|
|
1279
1300
|
});
|
|
1280
1301
|
}
|
|
1281
1302
|
|
|
1282
|
-
const
|
|
1283
|
-
self.#api.
|
|
1303
|
+
const apps = yield* Result.await(
|
|
1304
|
+
self.#api.listProjectApps(projectId, options.signal),
|
|
1284
1305
|
);
|
|
1285
|
-
const
|
|
1286
|
-
(
|
|
1287
|
-
id:
|
|
1288
|
-
name:
|
|
1289
|
-
region:
|
|
1290
|
-
projectId:
|
|
1306
|
+
const appInfos = apps.map(
|
|
1307
|
+
(a): AppInfo => ({
|
|
1308
|
+
id: a.id,
|
|
1309
|
+
name: a.name,
|
|
1310
|
+
region: a.region.id,
|
|
1311
|
+
projectId: a.projectId,
|
|
1291
1312
|
}),
|
|
1292
1313
|
);
|
|
1293
1314
|
|
|
1294
|
-
if (!options.interaction?.
|
|
1295
|
-
return Result.err(new MissingArgumentError({ field: "
|
|
1315
|
+
if (!options.interaction?.selectApp) {
|
|
1316
|
+
return Result.err(new MissingArgumentError({ field: "appId" }));
|
|
1296
1317
|
}
|
|
1297
1318
|
|
|
1298
|
-
const
|
|
1299
|
-
await options.interaction.selectService(serviceInfos);
|
|
1319
|
+
const selectedAppId = await options.interaction.selectApp(appInfos);
|
|
1300
1320
|
|
|
1301
|
-
if (
|
|
1302
|
-
const selected =
|
|
1303
|
-
invariant(
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
);
|
|
1307
|
-
const service = yield* Result.await(
|
|
1308
|
-
self.#api.getService(selectedServiceId, options.signal),
|
|
1321
|
+
if (selectedAppId !== null) {
|
|
1322
|
+
const selected = apps.find((a) => a.id === selectedAppId);
|
|
1323
|
+
invariant(selected, "selectApp returned app ID not in the list");
|
|
1324
|
+
const app = yield* Result.await(
|
|
1325
|
+
self.#api.getApp(selectedAppId, options.signal),
|
|
1309
1326
|
);
|
|
1310
1327
|
return Result.ok({
|
|
1311
1328
|
projectId,
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
region:
|
|
1315
|
-
branchId:
|
|
1316
|
-
|
|
1329
|
+
appId: selectedAppId,
|
|
1330
|
+
appName: app.name ?? selected.name,
|
|
1331
|
+
region: app.region.id,
|
|
1332
|
+
branchId: app.branchId ?? null,
|
|
1333
|
+
isNewApp: false,
|
|
1317
1334
|
});
|
|
1318
1335
|
}
|
|
1319
1336
|
|
|
1320
|
-
let
|
|
1321
|
-
if (!
|
|
1322
|
-
if (!options.interaction?.
|
|
1323
|
-
return Result.err(new MissingArgumentError({ field: "
|
|
1337
|
+
let appName = options.appName;
|
|
1338
|
+
if (!appName) {
|
|
1339
|
+
if (!options.interaction?.provideAppName) {
|
|
1340
|
+
return Result.err(new MissingArgumentError({ field: "appName" }));
|
|
1324
1341
|
}
|
|
1325
|
-
|
|
1342
|
+
appName = await options.interaction.provideAppName();
|
|
1326
1343
|
}
|
|
1327
1344
|
|
|
1328
1345
|
let region = options.region;
|
|
@@ -1334,10 +1351,10 @@ export class ComputeClient {
|
|
|
1334
1351
|
}
|
|
1335
1352
|
|
|
1336
1353
|
const response = yield* Result.await(
|
|
1337
|
-
self.#api.
|
|
1354
|
+
self.#api.createProjectApp(
|
|
1338
1355
|
projectId,
|
|
1339
1356
|
{
|
|
1340
|
-
displayName:
|
|
1357
|
+
displayName: appName,
|
|
1341
1358
|
regionId: region,
|
|
1342
1359
|
},
|
|
1343
1360
|
options.signal,
|
|
@@ -1346,11 +1363,11 @@ export class ComputeClient {
|
|
|
1346
1363
|
|
|
1347
1364
|
return Result.ok({
|
|
1348
1365
|
projectId,
|
|
1349
|
-
|
|
1350
|
-
|
|
1366
|
+
appId: response.id,
|
|
1367
|
+
appName: response.name,
|
|
1351
1368
|
region: response.region.id,
|
|
1352
1369
|
branchId: response.branchId ?? null,
|
|
1353
|
-
|
|
1370
|
+
isNewApp: true,
|
|
1354
1371
|
});
|
|
1355
1372
|
});
|
|
1356
1373
|
}
|
|
@@ -1458,9 +1475,12 @@ export class ComputeClient {
|
|
|
1458
1475
|
}
|
|
1459
1476
|
|
|
1460
1477
|
/**
|
|
1461
|
-
* Sort
|
|
1478
|
+
* Sort deployments: running/provisioning first, then by createdAt descending.
|
|
1462
1479
|
*/
|
|
1463
|
-
function
|
|
1480
|
+
function deploymentSortComparator(
|
|
1481
|
+
a: DeploymentInfo,
|
|
1482
|
+
b: DeploymentInfo,
|
|
1483
|
+
): number {
|
|
1464
1484
|
const statusPriority = (s: string) =>
|
|
1465
1485
|
s === "running" ? 0 : s === "provisioning" ? 1 : 2;
|
|
1466
1486
|
const aPriority = statusPriority(a.status);
|