inngest 4.19.0 → 4.20.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/CHANGELOG.md +8 -0
- package/components/realtime/types.d.cts +3 -3
- package/components/realtime/types.d.cts.map +1 -1
- package/components/realtime/types.d.ts +3 -3
- package/components/realtime/types.d.ts.map +1 -1
- package/components/sandbox/client.cjs +243 -29
- package/components/sandbox/client.cjs.map +1 -1
- package/components/sandbox/client.js +239 -31
- package/components/sandbox/client.js.map +1 -1
- package/components/sandbox/durable.cjs +158 -1
- package/components/sandbox/durable.cjs.map +1 -1
- package/components/sandbox/durable.js +160 -3
- package/components/sandbox/durable.js.map +1 -1
- package/components/sandbox/middleware.cjs +1 -0
- package/components/sandbox/middleware.cjs.map +1 -1
- package/components/sandbox/middleware.d.cts.map +1 -1
- package/components/sandbox/middleware.d.ts.map +1 -1
- package/components/sandbox/middleware.js +1 -0
- package/components/sandbox/middleware.js.map +1 -1
- package/components/sandbox/protocol.cjs +100 -4
- package/components/sandbox/protocol.cjs.map +1 -1
- package/components/sandbox/protocol.js +101 -5
- package/components/sandbox/protocol.js.map +1 -1
- package/components/sandbox/types.cjs +2 -0
- package/components/sandbox/types.cjs.map +1 -1
- package/components/sandbox/types.d.cts +100 -15
- package/components/sandbox/types.d.cts.map +1 -1
- package/components/sandbox/types.d.ts +100 -15
- package/components/sandbox/types.d.ts.map +1 -1
- package/components/sandbox/types.js +2 -0
- package/components/sandbox/types.js.map +1 -1
- package/components/sandbox/validation.cjs +75 -3
- package/components/sandbox/validation.cjs.map +1 -1
- package/components/sandbox/validation.js +71 -4
- package/components/sandbox/validation.js.map +1 -1
- package/experimental.d.cts +2 -2
- package/experimental.d.ts +2 -2
- package/package.json +1 -1
- package/react.d.cts +1 -1
- package/react.d.ts +1 -1
- package/types.d.cts +8 -8
- package/types.d.ts +8 -8
- package/version.cjs +1 -1
- package/version.cjs.map +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SandboxError, SandboxValidationError } from "./types.js";
|
|
2
|
-
import { canonicalUuidSchema, decodeBase64, decodeOutputChunk, decodeUtf8, normalizeFileDownloadOptions, normalizeFileUploadOptions, normalizeSandboxCommandOptions, normalizeSandboxCreateOptions, normalizeSandboxListOptions, normalizeSandboxProcessListOptions, normalizeSandboxProcessOutputOptions, normalizeSandboxProcessSignalOptions, normalizeSandboxProcessStartOptions, normalizeSandboxProcessWaitOptions, normalizeSandboxWaitUntilRunningOptions, parseWithSchema, restOutputChunkSchema, sandboxProcessRefFromResource, sandboxProcessRefSchema, sandboxRefFromResource, sandboxRefSchema } from "./validation.js";
|
|
2
|
+
import { canonicalUuidSchema, decodeBase64, decodeOutputChunk, decodeUtf8, normalizeFileDownloadOptions, normalizeFileUploadOptions, normalizeSandboxCommandOptions, normalizeSandboxCreateOptions, normalizeSandboxListOptions, normalizeSandboxProcessListOptions, normalizeSandboxProcessOutputOptions, normalizeSandboxProcessSignalOptions, normalizeSandboxProcessStartOptions, normalizeSandboxProcessWaitOptions, normalizeSandboxSnapshotCreateOptions, normalizeSandboxSnapshotListOptions, normalizeSandboxWaitUntilRunningOptions, parseWithSchema, restOutputChunkSchema, sandboxProcessRefFromResource, sandboxProcessRefSchema, sandboxRefFromResource, sandboxRefSchema, sandboxSnapshotRefFromResource, sandboxSnapshotRefSchema } from "./validation.js";
|
|
3
3
|
import { z } from "zod/v3";
|
|
4
4
|
|
|
5
5
|
//#region src/components/sandbox/client.ts
|
|
@@ -57,6 +57,8 @@ const waitProcessSchema = z.object({
|
|
|
57
57
|
const safeRepeatActions = new Set([
|
|
58
58
|
"create",
|
|
59
59
|
"destroy",
|
|
60
|
+
"pause",
|
|
61
|
+
"resume",
|
|
60
62
|
"file.upload",
|
|
61
63
|
"list",
|
|
62
64
|
"get",
|
|
@@ -67,7 +69,11 @@ const safeRepeatActions = new Set([
|
|
|
67
69
|
"process.output",
|
|
68
70
|
"process.stream",
|
|
69
71
|
"logs.stream",
|
|
70
|
-
"file.download"
|
|
72
|
+
"file.download",
|
|
73
|
+
"snapshot.list",
|
|
74
|
+
"snapshot.get",
|
|
75
|
+
"snapshot.waitUntilReady",
|
|
76
|
+
"snapshot.delete"
|
|
71
77
|
]);
|
|
72
78
|
const sandboxTransportFailureMessage = (action) => {
|
|
73
79
|
switch (action) {
|
|
@@ -77,6 +83,8 @@ const sandboxTransportFailureMessage = (action) => {
|
|
|
77
83
|
case "exec": return "The sandbox command may have run. Inspect its external effects before running it again";
|
|
78
84
|
case "process.start": return "A sandbox process may be running. List processes and reconcile before starting another";
|
|
79
85
|
case "process.signal": return "The sandbox process signal may have been delivered. Get or wait for the process before sending another";
|
|
86
|
+
case "snapshot.create": return "Snapshot creation may have started and a retry may create a second snapshot. Check snapshots.list() before creating another";
|
|
87
|
+
case "snapshot.delete": return "Snapshot deletion may have started. Repeating Delete is safe";
|
|
80
88
|
default: return "Compute is temporarily unavailable. Retry this operation";
|
|
81
89
|
}
|
|
82
90
|
};
|
|
@@ -93,11 +101,13 @@ var SandboxRestTransport = class {
|
|
|
93
101
|
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
94
102
|
headers: options.body === void 0 ? void 0 : { "Content-Type": "application/json" },
|
|
95
103
|
sandboxId: options.sandboxId,
|
|
96
|
-
processId: options.processId
|
|
104
|
+
processId: options.processId,
|
|
105
|
+
snapshotId: options.snapshotId,
|
|
106
|
+
signal: options.signal
|
|
97
107
|
});
|
|
98
|
-
if (!options.statuses.includes(response.status)) await this.throwResponseError(action, response, options.sandboxId, options.processId);
|
|
108
|
+
if (!options.statuses.includes(response.status)) await this.throwResponseError(action, response, options.sandboxId, options.processId, options.snapshotId);
|
|
99
109
|
if (response.status === 204) return { status: response.status };
|
|
100
|
-
const raw = await this.readResponseJSON(action, response, options.sandboxId, options.processId);
|
|
110
|
+
const raw = await this.readResponseJSON(action, response, options.sandboxId, options.processId, options.snapshotId);
|
|
101
111
|
return {
|
|
102
112
|
status: response.status,
|
|
103
113
|
envelope: parseWithSchema(responseEnvelopeSchema, raw, "sandbox API response")
|
|
@@ -105,11 +115,11 @@ var SandboxRestTransport = class {
|
|
|
105
115
|
}
|
|
106
116
|
async raw(action, method, path, options) {
|
|
107
117
|
const response = await this.send(action, method, path, options);
|
|
108
|
-
if (!response.ok) await this.throwResponseError(action, response, options.sandboxId, options.processId);
|
|
118
|
+
if (!response.ok) await this.throwResponseError(action, response, options.sandboxId, options.processId, options.snapshotId);
|
|
109
119
|
return response;
|
|
110
120
|
}
|
|
111
|
-
async readResponseEnvelope(action, response, sandboxId, processId) {
|
|
112
|
-
return parseWithSchema(responseEnvelopeSchema, await this.readResponseJSON(action, response, sandboxId, processId), "sandbox API response");
|
|
121
|
+
async readResponseEnvelope(action, response, sandboxId, processId, snapshotId) {
|
|
122
|
+
return parseWithSchema(responseEnvelopeSchema, await this.readResponseJSON(action, response, sandboxId, processId, snapshotId), "sandbox API response");
|
|
113
123
|
}
|
|
114
124
|
async stream(action, path, sandboxId, processId) {
|
|
115
125
|
const abortController = new AbortController();
|
|
@@ -187,17 +197,17 @@ var SandboxRestTransport = class {
|
|
|
187
197
|
try {
|
|
188
198
|
return await this.config.fetch()(new URL(path, this.config.baseUrl()), requestInit);
|
|
189
199
|
} catch (error) {
|
|
190
|
-
throw this.transportFailure(action, error, options.sandboxId, options.processId);
|
|
200
|
+
throw this.transportFailure(action, error, options.sandboxId, options.processId, options.snapshotId);
|
|
191
201
|
}
|
|
192
202
|
}
|
|
193
|
-
async readResponseJSON(action, response, sandboxId, processId) {
|
|
203
|
+
async readResponseJSON(action, response, sandboxId, processId, snapshotId) {
|
|
194
204
|
try {
|
|
195
205
|
return await response.json();
|
|
196
206
|
} catch (error) {
|
|
197
|
-
throw this.transportFailure(action, error, sandboxId, processId);
|
|
207
|
+
throw this.transportFailure(action, error, sandboxId, processId, snapshotId);
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
|
-
transportFailure(action, cause, sandboxId, processId) {
|
|
210
|
+
transportFailure(action, cause, sandboxId, processId, snapshotId) {
|
|
201
211
|
const safeToRepeat = safeRepeatActions.has(action);
|
|
202
212
|
return new SandboxError({
|
|
203
213
|
action,
|
|
@@ -205,22 +215,23 @@ var SandboxRestTransport = class {
|
|
|
205
215
|
message: sandboxTransportFailureMessage(action),
|
|
206
216
|
sandboxId,
|
|
207
217
|
processId,
|
|
218
|
+
snapshotId,
|
|
208
219
|
ambiguous: !safeToRepeat,
|
|
209
220
|
retryable: safeToRepeat,
|
|
210
221
|
details: [],
|
|
211
222
|
cause
|
|
212
223
|
});
|
|
213
224
|
}
|
|
214
|
-
async throwResponseError(action, response, sandboxId, processId) {
|
|
225
|
+
async throwResponseError(action, response, sandboxId, processId, snapshotId) {
|
|
215
226
|
const raw = await response.json().catch(() => void 0);
|
|
216
227
|
const parsed = errorEnvelopeSchema.safeParse(raw);
|
|
217
228
|
const item = parsed.success ? parsed.data.errors[0] : {
|
|
218
229
|
code: "internal_error",
|
|
219
230
|
message: `Sandbox API returned HTTP ${response.status}`
|
|
220
231
|
};
|
|
221
|
-
throw this.errorFromItem(action, response.status, item, sandboxId, processId, response.headers.get("x-request-id") ?? void 0, parsed.success ? parsed.data.errors : []);
|
|
232
|
+
throw this.errorFromItem(action, response.status, item, sandboxId, processId, snapshotId, response.headers.get("x-request-id") ?? void 0, parsed.success ? parsed.data.errors : []);
|
|
222
233
|
}
|
|
223
|
-
errorFromItem(action, status, item, sandboxId, processId, requestId, details = []) {
|
|
234
|
+
errorFromItem(action, status, item, sandboxId, processId, snapshotId, requestId, details = []) {
|
|
224
235
|
const ambiguous = item.code === "operation_ambiguous" || item.code === "sandbox_exec_output_too_large" || item.code === "sandbox_exec_timed_out";
|
|
225
236
|
const availability = item.code === "compute_unavailable" || item.code === "rate_limited" || status === 429 || status === 503;
|
|
226
237
|
return new SandboxError({
|
|
@@ -230,6 +241,7 @@ var SandboxRestTransport = class {
|
|
|
230
241
|
status,
|
|
231
242
|
sandboxId,
|
|
232
243
|
processId,
|
|
244
|
+
snapshotId,
|
|
233
245
|
ambiguous,
|
|
234
246
|
retryable: !ambiguous && availability,
|
|
235
247
|
requestId,
|
|
@@ -241,6 +253,18 @@ const processPath = (sandboxId, processId) => `/v2/sandboxes/${encodeURIComponen
|
|
|
241
253
|
const sandboxStartingStatuses = new Set(["PENDING", "STARTING"]);
|
|
242
254
|
const sandboxRunningPollIntervalMs = 1e3;
|
|
243
255
|
const delay = async (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
256
|
+
const lifecycleTimeout = (options) => normalizeSandboxWaitUntilRunningOptions({ timeout: options?.timeout ?? 5 * 6e4 }).timeoutMs;
|
|
257
|
+
const abortableDelay = (milliseconds, signal) => new Promise((resolve, reject) => {
|
|
258
|
+
if (signal?.aborted) {
|
|
259
|
+
reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const timer = setTimeout(resolve, milliseconds);
|
|
263
|
+
signal?.addEventListener("abort", () => {
|
|
264
|
+
clearTimeout(timer);
|
|
265
|
+
reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
266
|
+
}, { once: true });
|
|
267
|
+
});
|
|
244
268
|
const sandboxStartFailedError = (action, sandbox) => new SandboxError({
|
|
245
269
|
action,
|
|
246
270
|
code: "sandbox_start_failed",
|
|
@@ -319,6 +343,48 @@ const runSandboxCommandForOperation = (sandbox, command, options) => {
|
|
|
319
343
|
if (!run) throw new SandboxValidationError("Sandbox commands can only run on an SDK sandbox resource");
|
|
320
344
|
return run(command, options);
|
|
321
345
|
};
|
|
346
|
+
const pollSandboxStatus = async (initial, target, action, transport, options) => {
|
|
347
|
+
const timeoutMs = lifecycleTimeout(options);
|
|
348
|
+
const deadline = Date.now() + timeoutMs;
|
|
349
|
+
let current = initial;
|
|
350
|
+
while (current.status !== target) {
|
|
351
|
+
if (["FAILED", "TERMINATED"].includes(current.status)) throw new SandboxError({
|
|
352
|
+
action,
|
|
353
|
+
code: "invalid_request",
|
|
354
|
+
message: `Sandbox entered ${current.status} before reaching ${target}`,
|
|
355
|
+
sandboxId: current.id
|
|
356
|
+
});
|
|
357
|
+
const remaining = deadline - Date.now();
|
|
358
|
+
if (remaining <= 0) throw new SandboxError({
|
|
359
|
+
action,
|
|
360
|
+
code: "sandbox_start_timed_out",
|
|
361
|
+
message: `Sandbox did not reach ${target} within ${timeoutMs} milliseconds`,
|
|
362
|
+
sandboxId: current.id
|
|
363
|
+
});
|
|
364
|
+
await abortableDelay(Math.min(1e3, remaining), options?.signal);
|
|
365
|
+
const { envelope } = await transport.json(action, "GET", `/v2/sandboxes/${encodeURIComponent(current.id)}`, {
|
|
366
|
+
statuses: [200],
|
|
367
|
+
sandboxId: current.id,
|
|
368
|
+
signal: options?.signal
|
|
369
|
+
});
|
|
370
|
+
current = sandboxRefFromResource(envelope?.data);
|
|
371
|
+
if (current.id !== initial.id || current.name !== initial.name) throw new SandboxValidationError("Sandbox lifecycle operation returned an unrelated sandbox");
|
|
372
|
+
}
|
|
373
|
+
return createDirectSandboxFacade(current, transport);
|
|
374
|
+
};
|
|
375
|
+
const createDirectSnapshotFacade = (rawRef, transport) => {
|
|
376
|
+
const ref = sandboxSnapshotRefFromResource(rawRef);
|
|
377
|
+
return Object.freeze({
|
|
378
|
+
...ref,
|
|
379
|
+
resources: Object.freeze({ ...ref.resources }),
|
|
380
|
+
clone: async (options, waitOptions) => createSandbox(transport, {
|
|
381
|
+
name: options.name,
|
|
382
|
+
snapshotId: ref.id,
|
|
383
|
+
runningTimeout: options.runningTimeout ?? waitOptions?.timeout
|
|
384
|
+
}),
|
|
385
|
+
delete: async () => deleteSandboxSnapshot(transport, ref.id)
|
|
386
|
+
});
|
|
387
|
+
};
|
|
322
388
|
const createDirectSandboxFacade = (rawRef, transport) => {
|
|
323
389
|
const ref = parseWithSchema(sandboxRefSchema, rawRef, "sandbox reference");
|
|
324
390
|
const basePath = `/v2/sandboxes/${encodeURIComponent(ref.id)}`;
|
|
@@ -424,6 +490,34 @@ const createDirectSandboxFacade = (rawRef, transport) => {
|
|
|
424
490
|
}
|
|
425
491
|
}),
|
|
426
492
|
waitUntilRunning: async (options) => waitUntilSandboxRunning(ref, normalizeSandboxWaitUntilRunningOptions(options).timeoutMs, transport, "waitUntilRunning"),
|
|
493
|
+
pause: async (options) => {
|
|
494
|
+
const { envelope } = await transport.json("pause", "POST", `${basePath}/pause`, {
|
|
495
|
+
statuses: [
|
|
496
|
+
200,
|
|
497
|
+
201,
|
|
498
|
+
202
|
|
499
|
+
],
|
|
500
|
+
sandboxId: ref.id,
|
|
501
|
+
signal: options?.signal
|
|
502
|
+
});
|
|
503
|
+
return pollSandboxStatus(envelope?.data === void 0 ? ref : sandboxRefFromResource(envelope.data), "PAUSED", "pause", transport, options);
|
|
504
|
+
},
|
|
505
|
+
resume: async (options) => {
|
|
506
|
+
const { envelope } = await transport.json("resume", "POST", `${basePath}/resume`, {
|
|
507
|
+
statuses: [
|
|
508
|
+
200,
|
|
509
|
+
201,
|
|
510
|
+
202
|
|
511
|
+
],
|
|
512
|
+
sandboxId: ref.id,
|
|
513
|
+
signal: options?.signal
|
|
514
|
+
});
|
|
515
|
+
return pollSandboxStatus(envelope?.data === void 0 ? ref : sandboxRefFromResource(envelope.data), "RUNNING", "resume", transport, options);
|
|
516
|
+
},
|
|
517
|
+
snapshot: async (options = {}, waitOptions) => {
|
|
518
|
+
normalizeSandboxSnapshotCreateOptions(options);
|
|
519
|
+
return createDirectSnapshotFacade(await waitUntilSandboxSnapshotReady(transport, await createSandboxSnapshot(transport, ref.id, waitOptions?.signal), lifecycleTimeout(waitOptions), waitOptions?.signal), transport);
|
|
520
|
+
},
|
|
427
521
|
destroy: async () => {
|
|
428
522
|
const { status, envelope } = await transport.json("destroy", "DELETE", basePath, {
|
|
429
523
|
statuses: [202, 204],
|
|
@@ -480,23 +574,123 @@ const transportForClient = (client) => {
|
|
|
480
574
|
*/
|
|
481
575
|
const sandboxForOperation = (client, ref) => createDirectSandboxFacade(ref, transportForClient(client));
|
|
482
576
|
const sandboxProcessForOperation = (client, ref) => createDirectProcessFacade(ref, transportForClient(client));
|
|
577
|
+
const getSnapshotForOperation = async (transport, snapshotId, action) => {
|
|
578
|
+
try {
|
|
579
|
+
const { envelope } = await transport.json(action, "GET", `/v2/snapshots/${encodeURIComponent(snapshotId)}`, {
|
|
580
|
+
statuses: [200],
|
|
581
|
+
snapshotId
|
|
582
|
+
});
|
|
583
|
+
return sandboxSnapshotRefFromResource(envelope?.data);
|
|
584
|
+
} catch (error) {
|
|
585
|
+
if (error instanceof SandboxError && error.code === "sandbox_snapshot_not_found") return null;
|
|
586
|
+
throw error;
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
const createSandboxSnapshot = async (transport, sandboxId, signal) => {
|
|
590
|
+
const { status, envelope } = await transport.json("snapshot.create", "POST", `/v2/sandboxes/${encodeURIComponent(sandboxId)}/snapshots`, {
|
|
591
|
+
body: {},
|
|
592
|
+
statuses: [201, 202],
|
|
593
|
+
sandboxId,
|
|
594
|
+
signal
|
|
595
|
+
});
|
|
596
|
+
const snapshot = sandboxSnapshotRefFromResource(envelope?.data);
|
|
597
|
+
if (status === 201 && snapshot.status !== "READY" || status === 202 && snapshot.status !== "CREATING") throw new SandboxValidationError(`Sandbox snapshot Create returned HTTP ${status} with status ${snapshot.status}`);
|
|
598
|
+
return snapshot;
|
|
599
|
+
};
|
|
600
|
+
const listSandboxSnapshots = async (transport, options) => {
|
|
601
|
+
const normalized = normalizeSandboxSnapshotListOptions(options);
|
|
602
|
+
const query = new URLSearchParams({ limit: `${normalized.limit}` });
|
|
603
|
+
if (normalized.cursor !== void 0) query.set("cursor", normalized.cursor);
|
|
604
|
+
const { envelope } = await transport.json("snapshot.list", "GET", `/v2/snapshots?${query}`, { statuses: [200] });
|
|
605
|
+
const resources = parseWithSchema(z.array(z.unknown()), envelope?.data, "sandbox snapshot list");
|
|
606
|
+
const page = parseWithSchema(sandboxPageSchema, envelope?.page, "sandbox snapshot list page");
|
|
607
|
+
const metadata = parseWithSchema(metadataSchema, envelope?.metadata, "sandbox snapshot list metadata");
|
|
608
|
+
return {
|
|
609
|
+
items: resources.map(sandboxSnapshotRefFromResource),
|
|
610
|
+
page: {
|
|
611
|
+
hasMore: page.hasMore,
|
|
612
|
+
limit: page.limit,
|
|
613
|
+
...page.cursor != null && { cursor: page.cursor }
|
|
614
|
+
},
|
|
615
|
+
fetchedAt: metadata.fetchedAt
|
|
616
|
+
};
|
|
617
|
+
};
|
|
618
|
+
const createSandboxSnapshotForOperation = async (client, sandboxId) => createSandboxSnapshot(transportForClient(client), sandboxId);
|
|
619
|
+
const listSandboxSnapshotsForOperation = async (client, options) => listSandboxSnapshots(transportForClient(client), options);
|
|
620
|
+
const getSandboxSnapshotForOperation = async (client, snapshotId) => getSnapshotForOperation(transportForClient(client), snapshotId, "snapshot.get");
|
|
621
|
+
const snapshotNotReadyError = (snapshot) => new SandboxError({
|
|
622
|
+
action: "snapshot.waitUntilReady",
|
|
623
|
+
code: "sandbox_snapshot_not_ready",
|
|
624
|
+
message: `Snapshot entered ${snapshot.status} before reaching READY`,
|
|
625
|
+
snapshotId: snapshot.id,
|
|
626
|
+
retryable: false,
|
|
627
|
+
details: [{ status: snapshot.status }]
|
|
628
|
+
});
|
|
629
|
+
const snapshotWaitTimedOutError = (snapshot, timeoutMs) => new SandboxError({
|
|
630
|
+
action: "snapshot.waitUntilReady",
|
|
631
|
+
code: "sandbox_snapshot_wait_timed_out",
|
|
632
|
+
message: `Snapshot did not reach READY within ${timeoutMs} milliseconds`,
|
|
633
|
+
snapshotId: snapshot.id,
|
|
634
|
+
retryable: false,
|
|
635
|
+
details: [{
|
|
636
|
+
status: snapshot.status,
|
|
637
|
+
timeoutMs
|
|
638
|
+
}]
|
|
639
|
+
});
|
|
640
|
+
const waitUntilSandboxSnapshotReady = async (transport, initialSnapshot, timeoutMs, signal) => {
|
|
641
|
+
let snapshot = parseWithSchema(sandboxSnapshotRefSchema, initialSnapshot, "sandbox snapshot reference");
|
|
642
|
+
if (snapshot.status === "READY") return snapshot;
|
|
643
|
+
if (snapshot.status !== "CREATING") throw snapshotNotReadyError(snapshot);
|
|
644
|
+
const deadline = Date.now() + timeoutMs;
|
|
645
|
+
for (;;) {
|
|
646
|
+
if (deadline - Date.now() <= 0) throw snapshotWaitTimedOutError(snapshot, timeoutMs);
|
|
647
|
+
try {
|
|
648
|
+
const current = await getSnapshotForOperation(transport, snapshot.id, "snapshot.waitUntilReady");
|
|
649
|
+
if (!current) throw new SandboxError({
|
|
650
|
+
action: "snapshot.waitUntilReady",
|
|
651
|
+
code: "sandbox_snapshot_not_found",
|
|
652
|
+
message: "Snapshot not found",
|
|
653
|
+
snapshotId: snapshot.id,
|
|
654
|
+
retryable: false
|
|
655
|
+
});
|
|
656
|
+
snapshot = current;
|
|
657
|
+
} catch (error) {
|
|
658
|
+
if (!(error instanceof SandboxError && error.retryable)) throw error;
|
|
659
|
+
}
|
|
660
|
+
if (snapshot.status === "READY") return snapshot;
|
|
661
|
+
if (snapshot.status !== "CREATING") throw snapshotNotReadyError(snapshot);
|
|
662
|
+
const remainingMs = deadline - Date.now();
|
|
663
|
+
if (remainingMs <= 0) throw snapshotWaitTimedOutError(snapshot, timeoutMs);
|
|
664
|
+
await abortableDelay(Math.min(sandboxRunningPollIntervalMs, remainingMs), signal);
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
const waitUntilSandboxSnapshotReadyForOperation = async (client, initialSnapshot, timeoutMs) => waitUntilSandboxSnapshotReady(transportForClient(client), initialSnapshot, timeoutMs);
|
|
668
|
+
const deleteSandboxSnapshot = async (transport, snapshotId) => {
|
|
669
|
+
await transport.json("snapshot.delete", "DELETE", `/v2/snapshots/${encodeURIComponent(snapshotId)}`, {
|
|
670
|
+
statuses: [204],
|
|
671
|
+
snapshotId
|
|
672
|
+
});
|
|
673
|
+
};
|
|
674
|
+
const deleteSandboxSnapshotForOperation = async (client, snapshotId) => deleteSandboxSnapshot(transportForClient(client), snapshotId);
|
|
675
|
+
const createSandbox = async (transport, options) => {
|
|
676
|
+
const { runningTimeoutMs, ...body } = normalizeSandboxCreateOptions(options);
|
|
677
|
+
const { status, envelope } = await transport.json("create", "POST", "/v2/sandboxes", {
|
|
678
|
+
body,
|
|
679
|
+
statuses: [
|
|
680
|
+
200,
|
|
681
|
+
201,
|
|
682
|
+
202
|
|
683
|
+
]
|
|
684
|
+
});
|
|
685
|
+
const sandbox = sandboxRefFromResource(envelope?.data);
|
|
686
|
+
if (status === 201 && sandbox.status !== "RUNNING" || status === 202 && sandbox.status !== "STARTING") throw new SandboxValidationError(`Sandbox Create returned HTTP ${status} with status ${sandbox.status}`);
|
|
687
|
+
return runningTimeoutMs === false ? createDirectSandboxFacade(sandbox, transport) : waitUntilSandboxRunning(sandbox, runningTimeoutMs, transport, "create");
|
|
688
|
+
};
|
|
689
|
+
const createSandboxForOperation = async (client, options) => createSandbox(transportForClient(client), options);
|
|
483
690
|
const createSandboxClient = (config) => {
|
|
484
691
|
const transport = new SandboxRestTransport(config);
|
|
485
692
|
const client = {
|
|
486
|
-
create: async (options) =>
|
|
487
|
-
const { runningTimeoutMs, ...body } = normalizeSandboxCreateOptions(options);
|
|
488
|
-
const { status, envelope } = await transport.json("create", "POST", "/v2/sandboxes", {
|
|
489
|
-
body,
|
|
490
|
-
statuses: [
|
|
491
|
-
200,
|
|
492
|
-
201,
|
|
493
|
-
202
|
|
494
|
-
]
|
|
495
|
-
});
|
|
496
|
-
const sandbox = sandboxRefFromResource(envelope?.data);
|
|
497
|
-
if (status === 201 && sandbox.status !== "RUNNING" || status === 202 && sandbox.status !== "STARTING") throw new SandboxValidationError(`Sandbox Create returned HTTP ${status} with status ${sandbox.status}`);
|
|
498
|
-
return runningTimeoutMs === false ? createDirectSandboxFacade(sandbox, transport) : waitUntilSandboxRunning(sandbox, runningTimeoutMs, transport, "create");
|
|
499
|
-
},
|
|
693
|
+
create: async (options) => createSandbox(transport, options),
|
|
500
694
|
list: async (options) => {
|
|
501
695
|
const normalized = normalizeSandboxListOptions(options);
|
|
502
696
|
const query = new URLSearchParams({ limit: `${normalized.limit}` });
|
|
@@ -527,12 +721,26 @@ const createSandboxClient = (config) => {
|
|
|
527
721
|
if (error instanceof SandboxError && error.code === "sandbox_not_found") return null;
|
|
528
722
|
throw error;
|
|
529
723
|
}
|
|
530
|
-
}
|
|
724
|
+
},
|
|
725
|
+
snapshots: Object.freeze({
|
|
726
|
+
list: async (options) => {
|
|
727
|
+
const result = await listSandboxSnapshots(transport, options);
|
|
728
|
+
return {
|
|
729
|
+
items: result.items.map((snapshot) => createDirectSnapshotFacade(snapshot, transport)),
|
|
730
|
+
page: { ...result.page },
|
|
731
|
+
fetchedAt: result.fetchedAt
|
|
732
|
+
};
|
|
733
|
+
},
|
|
734
|
+
get: async (snapshotId) => {
|
|
735
|
+
const snapshot = await getSnapshotForOperation(transport, parseWithSchema(canonicalUuidSchema, snapshotId, "sandbox snapshot ID"), "snapshot.get");
|
|
736
|
+
return snapshot ? createDirectSnapshotFacade(snapshot, transport) : null;
|
|
737
|
+
}
|
|
738
|
+
})
|
|
531
739
|
};
|
|
532
740
|
sandboxClientTransports.set(client, transport);
|
|
533
741
|
return client;
|
|
534
742
|
};
|
|
535
743
|
|
|
536
744
|
//#endregion
|
|
537
|
-
export { createSandboxClient, runSandboxCommandForOperation, sandboxForOperation, sandboxProcessForOperation };
|
|
745
|
+
export { createSandboxClient, createSandboxForOperation, createSandboxSnapshotForOperation, deleteSandboxSnapshotForOperation, getSandboxSnapshotForOperation, listSandboxSnapshotsForOperation, runSandboxCommandForOperation, sandboxForOperation, sandboxProcessForOperation, waitUntilSandboxSnapshotReadyForOperation };
|
|
538
746
|
//# sourceMappingURL=client.js.map
|