@alibaba-group/opensandbox 0.1.4 → 0.1.5
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/README.md +76 -33
- package/dist/{chunk-OYTPXLWE.js → chunk-XHEWHFQ6.js} +139 -29
- package/dist/chunk-XHEWHFQ6.js.map +1 -0
- package/dist/cjs/index.cjs +260 -42
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/internal.cjs +137 -28
- package/dist/cjs/internal.cjs.map +1 -1
- package/dist/index.d.ts +32 -7
- package/dist/index.js +123 -14
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +290 -14
- package/dist/internal.js +1 -1
- package/dist/{sandboxes-Dc0G4ShU.d.ts → sandboxes-DL9uUHGR.d.ts} +232 -158
- package/package.json +3 -2
- package/src/adapters/commandsAdapter.ts +189 -27
- package/src/adapters/egressAdapter.ts +46 -0
- package/src/adapters/sandboxesAdapter.ts +8 -3
- package/src/api/egress.ts +184 -0
- package/src/api/execd.ts +216 -1
- package/src/api/lifecycle.ts +57 -12
- package/src/core/constants.ts +2 -1
- package/src/core/exceptions.ts +5 -4
- package/src/factory/adapterFactory.ts +13 -1
- package/src/factory/defaultAdapterFactory.ts +27 -2
- package/src/index.ts +3 -1
- package/src/models/execd.ts +12 -0
- package/src/models/execution.ts +2 -1
- package/src/models/sandboxes.ts +50 -7
- package/src/openapi/egressClient.ts +45 -0
- package/src/sandbox.ts +82 -12
- package/src/services/egress.ts +27 -0
- package/src/services/execdCommands.ts +24 -1
- package/src/services/sandboxes.ts +1 -1
- package/dist/chunk-OYTPXLWE.js.map +0 -1
package/README.md
CHANGED
|
@@ -55,7 +55,10 @@ try {
|
|
|
55
55
|
await sandbox.close();
|
|
56
56
|
} catch (err) {
|
|
57
57
|
if (err instanceof SandboxException) {
|
|
58
|
-
console.error(
|
|
58
|
+
console.error(
|
|
59
|
+
`Sandbox Error: [${err.error.code}] ${err.error.message ?? ""}`,
|
|
60
|
+
);
|
|
61
|
+
console.error(`Request ID: ${err.requestId ?? "N/A"}`);
|
|
59
62
|
} else {
|
|
60
63
|
console.error(err);
|
|
61
64
|
}
|
|
@@ -72,7 +75,7 @@ Manage the sandbox lifecycle, including renewal, pausing, and resuming.
|
|
|
72
75
|
const info = await sandbox.getInfo();
|
|
73
76
|
console.log("State:", info.status.state);
|
|
74
77
|
console.log("Created:", info.createdAt);
|
|
75
|
-
console.log("Expires:", info.expiresAt);
|
|
78
|
+
console.log("Expires:", info.expiresAt); // null when manual cleanup mode is used
|
|
76
79
|
|
|
77
80
|
await sandbox.pause();
|
|
78
81
|
|
|
@@ -83,6 +86,16 @@ const resumed = await sandbox.resume();
|
|
|
83
86
|
await resumed.renew(30 * 60);
|
|
84
87
|
```
|
|
85
88
|
|
|
89
|
+
Create a non-expiring sandbox by passing `timeoutSeconds: null`:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const manual = await Sandbox.create({
|
|
93
|
+
connectionConfig: config,
|
|
94
|
+
image: "ubuntu",
|
|
95
|
+
timeoutSeconds: null,
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
86
99
|
### 2. Custom Health Check
|
|
87
100
|
|
|
88
101
|
Define custom logic to determine whether the sandbox is ready/healthy. This overrides the default ping check used during readiness checks.
|
|
@@ -109,7 +122,8 @@ import type { ExecutionHandlers } from "@alibaba-group/opensandbox";
|
|
|
109
122
|
const handlers: ExecutionHandlers = {
|
|
110
123
|
onStdout: (m) => console.log("STDOUT:", m.text),
|
|
111
124
|
onStderr: (m) => console.error("STDERR:", m.text),
|
|
112
|
-
onExecutionComplete: (c) =>
|
|
125
|
+
onExecutionComplete: (c) =>
|
|
126
|
+
console.log("Finished in", c.executionTimeMs, "ms"),
|
|
113
127
|
};
|
|
114
128
|
|
|
115
129
|
await sandbox.commands.run(
|
|
@@ -124,16 +138,19 @@ await sandbox.commands.run(
|
|
|
124
138
|
Manage files and directories, including read, write, list/search, and delete.
|
|
125
139
|
|
|
126
140
|
```ts
|
|
127
|
-
await sandbox.files.createDirectories([{ path: "/tmp/demo", mode:
|
|
141
|
+
await sandbox.files.createDirectories([{ path: "/tmp/demo", mode: 755 }]);
|
|
128
142
|
|
|
129
143
|
await sandbox.files.writeFiles([
|
|
130
|
-
{ path: "/tmp/demo/hello.txt", data: "Hello World", mode:
|
|
144
|
+
{ path: "/tmp/demo/hello.txt", data: "Hello World", mode: 644 },
|
|
131
145
|
]);
|
|
132
146
|
|
|
133
147
|
const content = await sandbox.files.readFile("/tmp/demo/hello.txt");
|
|
134
148
|
console.log("Content:", content);
|
|
135
149
|
|
|
136
|
-
const files = await sandbox.files.search({
|
|
150
|
+
const files = await sandbox.files.search({
|
|
151
|
+
path: "/tmp/demo",
|
|
152
|
+
pattern: "*.txt",
|
|
153
|
+
});
|
|
137
154
|
console.log(files.map((f) => f.path));
|
|
138
155
|
|
|
139
156
|
await sandbox.files.deleteDirectories(["/tmp/demo"]);
|
|
@@ -156,7 +173,10 @@ Use `SandboxManager` for administrative tasks and finding existing sandboxes.
|
|
|
156
173
|
import { SandboxManager } from "@alibaba-group/opensandbox";
|
|
157
174
|
|
|
158
175
|
const manager = SandboxManager.create({ connectionConfig: config });
|
|
159
|
-
const list = await manager.listSandboxInfos({
|
|
176
|
+
const list = await manager.listSandboxInfos({
|
|
177
|
+
states: ["Running"],
|
|
178
|
+
pageSize: 10,
|
|
179
|
+
});
|
|
160
180
|
console.log(list.items.map((s) => s.id));
|
|
161
181
|
await manager.close();
|
|
162
182
|
```
|
|
@@ -168,18 +188,19 @@ await manager.close();
|
|
|
168
188
|
The `ConnectionConfig` class manages API server connection settings.
|
|
169
189
|
|
|
170
190
|
Runtime notes:
|
|
191
|
+
|
|
171
192
|
- In browsers, the SDK uses the global `fetch` implementation.
|
|
172
193
|
- In Node.js, every `Sandbox` and `SandboxManager` clones the base `ConnectionConfig` via `withTransportIfMissing()`, so each instance gets an isolated `undici` keep-alive pool. Call `sandbox.close()` or `manager.close()` when you are done so the SDK can release the associated agent.
|
|
173
194
|
|
|
174
|
-
| Parameter
|
|
175
|
-
|
|
|
176
|
-
| `apiKey`
|
|
177
|
-
| `domain`
|
|
178
|
-
| `protocol`
|
|
179
|
-
| `requestTimeoutSeconds` | Request timeout applied to SDK HTTP calls
|
|
180
|
-
| `debug`
|
|
181
|
-
| `headers`
|
|
182
|
-
| `useServerProxy`
|
|
195
|
+
| Parameter | Description | Default | Environment Variable |
|
|
196
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------- | ---------------------- |
|
|
197
|
+
| `apiKey` | API key for authentication | Optional | `OPEN_SANDBOX_API_KEY` |
|
|
198
|
+
| `domain` | Sandbox service domain (`host[:port]`) | `localhost:8080` | `OPEN_SANDBOX_DOMAIN` |
|
|
199
|
+
| `protocol` | HTTP protocol (`http`/`https`) | `http` | - |
|
|
200
|
+
| `requestTimeoutSeconds` | Request timeout applied to SDK HTTP calls | `30` | - |
|
|
201
|
+
| `debug` | Enable basic HTTP debug logging | `false` | - |
|
|
202
|
+
| `headers` | Extra headers applied to every request | `{}` | - |
|
|
203
|
+
| `useServerProxy` | Use sandbox server as proxy for execd/endpoint requests (e.g. when client cannot reach the sandbox directly) | `false` | - |
|
|
183
204
|
|
|
184
205
|
```ts
|
|
185
206
|
import { ConnectionConfig } from "@alibaba-group/opensandbox";
|
|
@@ -203,20 +224,23 @@ const config2 = new ConnectionConfig({
|
|
|
203
224
|
|
|
204
225
|
`Sandbox.create()` allows configuring the sandbox environment.
|
|
205
226
|
|
|
206
|
-
| Parameter
|
|
207
|
-
|
|
|
208
|
-
| `image`
|
|
209
|
-
| `timeoutSeconds`
|
|
210
|
-
| `entrypoint`
|
|
211
|
-
| `resource`
|
|
212
|
-
| `env`
|
|
213
|
-
| `metadata`
|
|
214
|
-
| `networkPolicy`
|
|
215
|
-
| `extensions`
|
|
216
|
-
| `skipHealthCheck`
|
|
217
|
-
| `healthCheck`
|
|
218
|
-
| `readyTimeoutSeconds`
|
|
219
|
-
| `healthCheckPollingInterval` | Poll interval while waiting (milliseconds)
|
|
227
|
+
| Parameter | Description | Default |
|
|
228
|
+
| ---------------------------- | ------------------------------------------------ | ---------------------------- |
|
|
229
|
+
| `image` | Docker image to use | Required |
|
|
230
|
+
| `timeoutSeconds` | Automatic termination timeout (server-side TTL) | 10 minutes |
|
|
231
|
+
| `entrypoint` | Container entrypoint command | `["tail","-f","/dev/null"]` |
|
|
232
|
+
| `resource` | CPU and memory limits (string map) | `{"cpu":"1","memory":"2Gi"}` |
|
|
233
|
+
| `env` | Environment variables | `{}` |
|
|
234
|
+
| `metadata` | Custom metadata tags | `{}` |
|
|
235
|
+
| `networkPolicy` | Optional outbound network policy (egress) | - |
|
|
236
|
+
| `extensions` | Extra server-defined fields | `{}` |
|
|
237
|
+
| `skipHealthCheck` | Skip readiness checks (`Running` + health check) | `false` |
|
|
238
|
+
| `healthCheck` | Custom readiness check | - |
|
|
239
|
+
| `readyTimeoutSeconds` | Max time to wait for readiness | 30 seconds |
|
|
240
|
+
| `healthCheckPollingInterval` | Poll interval while waiting (milliseconds) | 200 ms |
|
|
241
|
+
|
|
242
|
+
Note: metadata keys under `opensandbox.io/` are reserved for system-managed
|
|
243
|
+
labels and will be rejected by the server.
|
|
220
244
|
|
|
221
245
|
```ts
|
|
222
246
|
const sandbox = await Sandbox.create({
|
|
@@ -229,16 +253,35 @@ const sandbox = await Sandbox.create({
|
|
|
229
253
|
});
|
|
230
254
|
```
|
|
231
255
|
|
|
232
|
-
### 3.
|
|
256
|
+
### 3. Runtime Egress Policy Updates
|
|
257
|
+
|
|
258
|
+
Runtime egress reads and patches go directly to the sandbox egress sidecar.
|
|
259
|
+
The SDK first resolves the sandbox endpoint on port `18080`, then calls the sidecar `/policy` API.
|
|
260
|
+
|
|
261
|
+
Patch uses merge semantics:
|
|
262
|
+
- Incoming rules take priority over existing rules with the same `target`.
|
|
263
|
+
- Existing rules for other targets remain unchanged.
|
|
264
|
+
- Within a single patch payload, the first rule for a `target` wins.
|
|
265
|
+
- The current `defaultAction` is preserved.
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
const policy = await sandbox.getEgressPolicy();
|
|
269
|
+
|
|
270
|
+
await sandbox.patchEgressRules([
|
|
271
|
+
{ action: "allow", target: "www.github.com" },
|
|
272
|
+
{ action: "deny", target: "pypi.org" },
|
|
273
|
+
]);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 4. Resource cleanup
|
|
233
277
|
|
|
234
278
|
Both `Sandbox` and `SandboxManager` own a scoped HTTP agent when running on Node.js
|
|
235
279
|
so you can safely reuse the same `ConnectionConfig`. Once you are finished interacting
|
|
236
280
|
with the sandbox or administration APIs, call `sandbox.close()` / `manager.close()` to
|
|
237
|
-
release the underlying agent.
|
|
281
|
+
release the underlying agent.
|
|
238
282
|
|
|
239
283
|
## Browser Notes
|
|
240
284
|
|
|
241
285
|
- The SDK can run in browsers, but **streaming file uploads are Node-only**.
|
|
242
286
|
- If you pass `ReadableStream` or `AsyncIterable` for `writeFiles`, the browser will fall back to **buffering in memory** before upload.
|
|
243
287
|
- Reason: browsers do not support streaming `multipart/form-data` bodies with custom boundaries (required by the execd upload API).
|
|
244
|
-
|
|
@@ -14,25 +14,26 @@ var SandboxException = class extends Error {
|
|
|
14
14
|
name = "SandboxException";
|
|
15
15
|
error;
|
|
16
16
|
cause;
|
|
17
|
+
requestId;
|
|
17
18
|
constructor(opts = {}) {
|
|
18
19
|
super(opts.message);
|
|
19
20
|
this.cause = opts.cause;
|
|
20
21
|
this.error = opts.error ?? new SandboxError(SandboxError.INTERNAL_UNKNOWN_ERROR);
|
|
22
|
+
this.requestId = opts.requestId;
|
|
21
23
|
}
|
|
22
24
|
};
|
|
23
25
|
var SandboxApiException = class extends SandboxException {
|
|
24
26
|
name = "SandboxApiException";
|
|
25
27
|
statusCode;
|
|
26
|
-
requestId;
|
|
27
28
|
rawBody;
|
|
28
29
|
constructor(opts) {
|
|
29
30
|
super({
|
|
30
31
|
message: opts.message,
|
|
31
32
|
cause: opts.cause,
|
|
32
|
-
error: opts.error ?? new SandboxError(SandboxError.UNEXPECTED_RESPONSE, opts.message)
|
|
33
|
+
error: opts.error ?? new SandboxError(SandboxError.UNEXPECTED_RESPONSE, opts.message),
|
|
34
|
+
requestId: opts.requestId
|
|
33
35
|
});
|
|
34
36
|
this.statusCode = opts.statusCode;
|
|
35
|
-
this.requestId = opts.requestId;
|
|
36
37
|
this.rawBody = opts.rawBody;
|
|
37
38
|
}
|
|
38
39
|
};
|
|
@@ -267,6 +268,9 @@ function joinUrl(baseUrl, pathname) {
|
|
|
267
268
|
return `${base}${path}`;
|
|
268
269
|
}
|
|
269
270
|
function toRunCommandRequest(command, opts) {
|
|
271
|
+
if (opts?.gid != null && opts.uid == null) {
|
|
272
|
+
throw new Error("uid is required when gid is provided");
|
|
273
|
+
}
|
|
270
274
|
const body = {
|
|
271
275
|
command,
|
|
272
276
|
cwd: opts?.workingDirectory,
|
|
@@ -275,8 +279,39 @@ function toRunCommandRequest(command, opts) {
|
|
|
275
279
|
if (opts?.timeoutSeconds != null) {
|
|
276
280
|
body.timeout = Math.round(opts.timeoutSeconds * 1e3);
|
|
277
281
|
}
|
|
282
|
+
if (opts?.uid != null) {
|
|
283
|
+
body.uid = opts.uid;
|
|
284
|
+
}
|
|
285
|
+
if (opts?.gid != null) {
|
|
286
|
+
body.gid = opts.gid;
|
|
287
|
+
}
|
|
288
|
+
if (opts?.envs != null) {
|
|
289
|
+
body.envs = opts.envs;
|
|
290
|
+
}
|
|
291
|
+
return body;
|
|
292
|
+
}
|
|
293
|
+
function toRunInSessionRequest(command, opts) {
|
|
294
|
+
const body = {
|
|
295
|
+
command
|
|
296
|
+
};
|
|
297
|
+
if (opts?.workingDirectory != null) {
|
|
298
|
+
body.cwd = opts.workingDirectory;
|
|
299
|
+
}
|
|
300
|
+
if (opts?.timeout != null) {
|
|
301
|
+
body.timeout = opts.timeout;
|
|
302
|
+
}
|
|
278
303
|
return body;
|
|
279
304
|
}
|
|
305
|
+
function inferForegroundExitCode(execution) {
|
|
306
|
+
const errorValue = execution.error?.value?.trim();
|
|
307
|
+
const parsedExitCode = errorValue && /^-?\d+$/.test(errorValue) ? Number(errorValue) : Number.NaN;
|
|
308
|
+
return execution.error != null ? Number.isFinite(parsedExitCode) ? parsedExitCode : null : execution.complete ? 0 : null;
|
|
309
|
+
}
|
|
310
|
+
function assertNonBlank(value, field) {
|
|
311
|
+
if (!value.trim()) {
|
|
312
|
+
throw new Error(`${field} cannot be empty`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
280
315
|
function parseOptionalDate(value, field) {
|
|
281
316
|
if (value == null) return void 0;
|
|
282
317
|
if (value instanceof Date) return value;
|
|
@@ -296,6 +331,58 @@ var CommandsAdapter = class {
|
|
|
296
331
|
this.fetch = opts.fetch ?? fetch;
|
|
297
332
|
}
|
|
298
333
|
fetch;
|
|
334
|
+
buildRunStreamSpec(command, opts) {
|
|
335
|
+
assertNonBlank(command, "command");
|
|
336
|
+
return {
|
|
337
|
+
pathname: "/command",
|
|
338
|
+
body: toRunCommandRequest(command, opts),
|
|
339
|
+
fallbackErrorMessage: "Run command failed"
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
buildRunInSessionStreamSpec(sessionId, command, opts) {
|
|
343
|
+
assertNonBlank(sessionId, "sessionId");
|
|
344
|
+
assertNonBlank(command, "command");
|
|
345
|
+
return {
|
|
346
|
+
pathname: `/session/${encodeURIComponent(sessionId)}/run`,
|
|
347
|
+
body: toRunInSessionRequest(command, opts),
|
|
348
|
+
fallbackErrorMessage: "Run in session failed"
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
async *streamExecution(spec, signal) {
|
|
352
|
+
const url = joinUrl(this.opts.baseUrl, spec.pathname);
|
|
353
|
+
const res = await this.fetch(url, {
|
|
354
|
+
method: "POST",
|
|
355
|
+
headers: {
|
|
356
|
+
accept: "text/event-stream",
|
|
357
|
+
"content-type": "application/json",
|
|
358
|
+
...this.opts.headers ?? {}
|
|
359
|
+
},
|
|
360
|
+
body: JSON.stringify(spec.body),
|
|
361
|
+
signal
|
|
362
|
+
});
|
|
363
|
+
for await (const ev of parseJsonEventStream(res, {
|
|
364
|
+
fallbackErrorMessage: spec.fallbackErrorMessage
|
|
365
|
+
})) {
|
|
366
|
+
yield ev;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
async consumeExecutionStream(stream, handlers, inferExitCode = false) {
|
|
370
|
+
const execution = {
|
|
371
|
+
logs: { stdout: [], stderr: [] },
|
|
372
|
+
result: []
|
|
373
|
+
};
|
|
374
|
+
const dispatcher = new ExecutionEventDispatcher(execution, handlers);
|
|
375
|
+
for await (const ev of stream) {
|
|
376
|
+
if (ev.type === "init" && (ev.text ?? "") === "" && execution.id) {
|
|
377
|
+
ev.text = execution.id;
|
|
378
|
+
}
|
|
379
|
+
await dispatcher.dispatch(ev);
|
|
380
|
+
}
|
|
381
|
+
if (inferExitCode) {
|
|
382
|
+
execution.exitCode = inferForegroundExitCode(execution);
|
|
383
|
+
}
|
|
384
|
+
return execution;
|
|
385
|
+
}
|
|
299
386
|
async interrupt(sessionId) {
|
|
300
387
|
const { error, response } = await this.client.DELETE("/command", {
|
|
301
388
|
params: { query: { id: sessionId } }
|
|
@@ -339,35 +426,53 @@ var CommandsAdapter = class {
|
|
|
339
426
|
};
|
|
340
427
|
}
|
|
341
428
|
async *runStream(command, opts, signal) {
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
const res = await this.fetch(url, {
|
|
345
|
-
method: "POST",
|
|
346
|
-
headers: {
|
|
347
|
-
"accept": "text/event-stream",
|
|
348
|
-
"content-type": "application/json",
|
|
349
|
-
...this.opts.headers ?? {}
|
|
350
|
-
},
|
|
351
|
-
body,
|
|
429
|
+
for await (const ev of this.streamExecution(
|
|
430
|
+
this.buildRunStreamSpec(command, opts),
|
|
352
431
|
signal
|
|
353
|
-
|
|
354
|
-
for await (const ev of parseJsonEventStream(res, { fallbackErrorMessage: "Run command failed" })) {
|
|
432
|
+
)) {
|
|
355
433
|
yield ev;
|
|
356
434
|
}
|
|
357
435
|
}
|
|
358
436
|
async run(command, opts, handlers, signal) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
437
|
+
return this.consumeExecutionStream(
|
|
438
|
+
this.runStream(command, opts, signal),
|
|
439
|
+
handlers,
|
|
440
|
+
!opts?.background
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
async createSession(options) {
|
|
444
|
+
const body = options?.workingDirectory != null ? { cwd: options.workingDirectory } : {};
|
|
445
|
+
const { data, error, response } = await this.client.POST("/session", {
|
|
446
|
+
body
|
|
447
|
+
});
|
|
448
|
+
throwOnOpenApiFetchError({ error, response }, "Create session failed");
|
|
449
|
+
const ok = data;
|
|
450
|
+
if (!ok || typeof ok.session_id !== "string") {
|
|
451
|
+
throw new Error("Create session failed: unexpected response shape");
|
|
369
452
|
}
|
|
370
|
-
return
|
|
453
|
+
return ok.session_id;
|
|
454
|
+
}
|
|
455
|
+
async *runInSessionStream(sessionId, command, opts, signal) {
|
|
456
|
+
for await (const ev of this.streamExecution(
|
|
457
|
+
this.buildRunInSessionStreamSpec(sessionId, command, opts),
|
|
458
|
+
signal
|
|
459
|
+
)) {
|
|
460
|
+
yield ev;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
async runInSession(sessionId, command, options, handlers, signal) {
|
|
464
|
+
return this.consumeExecutionStream(
|
|
465
|
+
this.runInSessionStream(sessionId, command, options, signal),
|
|
466
|
+
handlers,
|
|
467
|
+
true
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
async deleteSession(sessionId) {
|
|
471
|
+
const { error, response } = await this.client.DELETE(
|
|
472
|
+
"/session/{sessionId}",
|
|
473
|
+
{ params: { path: { sessionId } } }
|
|
474
|
+
);
|
|
475
|
+
throwOnOpenApiFetchError({ error, response }, "Delete session failed");
|
|
371
476
|
}
|
|
372
477
|
};
|
|
373
478
|
|
|
@@ -856,11 +961,15 @@ var SandboxesAdapter = class {
|
|
|
856
961
|
}
|
|
857
962
|
return d;
|
|
858
963
|
}
|
|
964
|
+
parseOptionalIsoDate(field, v) {
|
|
965
|
+
if (v == null) return null;
|
|
966
|
+
return this.parseIsoDate(field, v);
|
|
967
|
+
}
|
|
859
968
|
mapSandboxInfo(raw) {
|
|
860
969
|
return {
|
|
861
970
|
...raw ?? {},
|
|
862
971
|
createdAt: this.parseIsoDate("createdAt", raw?.createdAt),
|
|
863
|
-
expiresAt: this.
|
|
972
|
+
expiresAt: this.parseOptionalIsoDate("expiresAt", raw?.expiresAt)
|
|
864
973
|
};
|
|
865
974
|
}
|
|
866
975
|
async createSandbox(req) {
|
|
@@ -876,7 +985,7 @@ var SandboxesAdapter = class {
|
|
|
876
985
|
return {
|
|
877
986
|
...raw ?? {},
|
|
878
987
|
createdAt: this.parseIsoDate("createdAt", raw?.createdAt),
|
|
879
|
-
expiresAt: this.
|
|
988
|
+
expiresAt: this.parseOptionalIsoDate("expiresAt", raw?.expiresAt)
|
|
880
989
|
};
|
|
881
990
|
}
|
|
882
991
|
async getSandbox(sandboxId) {
|
|
@@ -970,6 +1079,7 @@ export {
|
|
|
970
1079
|
InvalidArgumentException,
|
|
971
1080
|
createExecdClient,
|
|
972
1081
|
createLifecycleClient,
|
|
1082
|
+
throwOnOpenApiFetchError,
|
|
973
1083
|
ExecutionEventDispatcher,
|
|
974
1084
|
CommandsAdapter,
|
|
975
1085
|
FilesystemAdapter,
|
|
@@ -977,4 +1087,4 @@ export {
|
|
|
977
1087
|
MetricsAdapter,
|
|
978
1088
|
SandboxesAdapter
|
|
979
1089
|
};
|
|
980
|
-
//# sourceMappingURL=chunk-
|
|
1090
|
+
//# sourceMappingURL=chunk-XHEWHFQ6.js.map
|