@brimble/sandbox 0.1.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/CODEX.md +188 -0
- package/PLAN.md +364 -0
- package/README.md +147 -0
- package/dist/package.json +23 -0
- package/dist/src/client.d.ts +23 -0
- package/dist/src/client.js +46 -0
- package/dist/src/constants.d.ts +14 -0
- package/dist/src/constants.js +21 -0
- package/dist/src/enums/code-language.d.ts +4 -0
- package/dist/src/enums/code-language.js +8 -0
- package/dist/src/enums/destroy-reason.d.ts +8 -0
- package/dist/src/enums/destroy-reason.js +12 -0
- package/dist/src/enums/destroy-timeout.d.ts +8 -0
- package/dist/src/enums/destroy-timeout.js +12 -0
- package/dist/src/enums/index.d.ts +7 -0
- package/dist/src/enums/index.js +17 -0
- package/dist/src/enums/sandbox-status.d.ts +9 -0
- package/dist/src/enums/sandbox-status.js +13 -0
- package/dist/src/enums/snapshot-mode.d.ts +4 -0
- package/dist/src/enums/snapshot-mode.js +8 -0
- package/dist/src/enums/snapshot-status.d.ts +5 -0
- package/dist/src/enums/snapshot-status.js +9 -0
- package/dist/src/enums/volume-type.d.ts +3 -0
- package/dist/src/enums/volume-type.js +7 -0
- package/dist/src/errors/index.d.ts +2 -0
- package/dist/src/errors/index.js +9 -0
- package/dist/src/errors/sandbox-api-error.d.ts +29 -0
- package/dist/src/errors/sandbox-api-error.js +48 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +40 -0
- package/dist/src/resources/exec.d.ts +19 -0
- package/dist/src/resources/exec.js +45 -0
- package/dist/src/resources/files.d.ts +16 -0
- package/dist/src/resources/files.js +41 -0
- package/dist/src/resources/index.d.ts +8 -0
- package/dist/src/resources/index.js +20 -0
- package/dist/src/resources/path.d.ts +7 -0
- package/dist/src/resources/path.js +19 -0
- package/dist/src/resources/sandbox-handle.d.ts +78 -0
- package/dist/src/resources/sandbox-handle.js +151 -0
- package/dist/src/resources/sandboxes.d.ts +64 -0
- package/dist/src/resources/sandboxes.js +224 -0
- package/dist/src/resources/scoped-sandbox.d.ts +39 -0
- package/dist/src/resources/scoped-sandbox.js +51 -0
- package/dist/src/resources/snapshots.d.ts +26 -0
- package/dist/src/resources/snapshots.js +88 -0
- package/dist/src/resources/stats.d.ts +11 -0
- package/dist/src/resources/stats.js +26 -0
- package/dist/src/resources/volumes.d.ts +21 -0
- package/dist/src/resources/volumes.js +80 -0
- package/dist/src/transport/auth.d.ts +2 -0
- package/dist/src/transport/auth.js +7 -0
- package/dist/src/transport/http.d.ts +73 -0
- package/dist/src/transport/http.js +354 -0
- package/dist/src/transport/pagination.d.ts +3 -0
- package/dist/src/transport/pagination.js +11 -0
- package/dist/src/types/exec.d.ts +34 -0
- package/dist/src/types/exec.js +2 -0
- package/dist/src/types/files.d.ts +1 -0
- package/dist/src/types/files.js +2 -0
- package/dist/src/types/index.d.ts +9 -0
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/pagination.d.ts +14 -0
- package/dist/src/types/pagination.js +2 -0
- package/dist/src/types/region.d.ts +17 -0
- package/dist/src/types/region.js +2 -0
- package/dist/src/types/sandbox.d.ts +90 -0
- package/dist/src/types/sandbox.js +2 -0
- package/dist/src/types/snapshot.d.ts +15 -0
- package/dist/src/types/snapshot.js +2 -0
- package/dist/src/types/stats.d.ts +31 -0
- package/dist/src/types/stats.js +2 -0
- package/dist/src/types/template.d.ts +5 -0
- package/dist/src/types/template.js +2 -0
- package/dist/src/types/volume.d.ts +24 -0
- package/dist/src/types/volume.js +2 -0
- package/package.json +26 -0
- package/src/client.ts +61 -0
- package/src/constants.ts +17 -0
- package/src/enums/code-language.ts +4 -0
- package/src/enums/destroy-reason.ts +8 -0
- package/src/enums/destroy-timeout.ts +8 -0
- package/src/enums/index.ts +7 -0
- package/src/enums/sandbox-status.ts +9 -0
- package/src/enums/snapshot-mode.ts +4 -0
- package/src/enums/snapshot-status.ts +5 -0
- package/src/enums/volume-type.ts +3 -0
- package/src/errors/index.ts +2 -0
- package/src/errors/sandbox-api-error.ts +54 -0
- package/src/index.ts +71 -0
- package/src/resources/exec.ts +56 -0
- package/src/resources/files.ts +46 -0
- package/src/resources/index.ts +8 -0
- package/src/resources/path.ts +16 -0
- package/src/resources/sandbox-handle.ts +215 -0
- package/src/resources/sandboxes.ts +297 -0
- package/src/resources/scoped-sandbox.ts +65 -0
- package/src/resources/snapshots.ts +104 -0
- package/src/resources/stats.ts +30 -0
- package/src/resources/volumes.ts +95 -0
- package/src/transport/auth.ts +4 -0
- package/src/transport/http.ts +501 -0
- package/src/transport/pagination.ts +10 -0
- package/src/types/exec.ts +42 -0
- package/src/types/files.ts +1 -0
- package/src/types/index.ts +23 -0
- package/src/types/pagination.ts +16 -0
- package/src/types/region.ts +19 -0
- package/src/types/sandbox.ts +103 -0
- package/src/types/snapshot.ts +17 -0
- package/src/types/stats.ts +35 -0
- package/src/types/template.ts +5 -0
- package/src/types/volume.ts +26 -0
- package/test/integration/sandbox.integration.test.ts +269 -0
- package/test/unit/client.test.ts +87 -0
- package/test/unit/sandboxes.test.ts +69 -0
- package/test/unit/transport.test.ts +126 -0
- package/test/unit/volumes.test.ts +122 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +12 -0
- package/vitest.integration.config.ts +15 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExecResource = void 0;
|
|
4
|
+
class ExecResource {
|
|
5
|
+
transport;
|
|
6
|
+
sandboxId;
|
|
7
|
+
/** @internal Create the exec/code runner wrapper for one sandbox. */
|
|
8
|
+
constructor(transport, sandboxId) {
|
|
9
|
+
this.transport = transport;
|
|
10
|
+
this.sandboxId = sandboxId;
|
|
11
|
+
}
|
|
12
|
+
exec(input, options) {
|
|
13
|
+
if (input.stream === true) {
|
|
14
|
+
return this.transport.requestJsonStream({
|
|
15
|
+
endpoint: `/sandboxes/${this.sandboxId}/exec`,
|
|
16
|
+
method: 'POST',
|
|
17
|
+
body: input,
|
|
18
|
+
...options,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return this.transport.requestJson({
|
|
22
|
+
endpoint: `/sandboxes/${this.sandboxId}/exec`,
|
|
23
|
+
method: 'POST',
|
|
24
|
+
body: input,
|
|
25
|
+
...options,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
runCode(input, options) {
|
|
29
|
+
if (input.stream === true) {
|
|
30
|
+
return this.transport.requestJsonStream({
|
|
31
|
+
endpoint: `/sandboxes/${this.sandboxId}/code`,
|
|
32
|
+
method: 'POST',
|
|
33
|
+
body: input,
|
|
34
|
+
...options,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return this.transport.requestJson({
|
|
38
|
+
endpoint: `/sandboxes/${this.sandboxId}/code`,
|
|
39
|
+
method: 'POST',
|
|
40
|
+
body: input,
|
|
41
|
+
...options,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.ExecResource = ExecResource;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FileUploadBody } from '../types';
|
|
2
|
+
import type { RequestOptions } from '../transport/http';
|
|
3
|
+
import { HttpTransport } from '../transport/http';
|
|
4
|
+
export declare class FilesResource {
|
|
5
|
+
private readonly transport;
|
|
6
|
+
private readonly sandboxId;
|
|
7
|
+
/** @internal Create the files wrapper for one sandbox. */
|
|
8
|
+
constructor(transport: HttpTransport, sandboxId: string);
|
|
9
|
+
/**
|
|
10
|
+
* Upload file bytes to a path inside the sandbox.
|
|
11
|
+
* Tip: pass a Buffer/Uint8Array when you can so Content-Length is set automatically.
|
|
12
|
+
*/
|
|
13
|
+
put(path: string, body: FileUploadBody, options?: RequestOptions): Promise<void>;
|
|
14
|
+
/** Download a file from the sandbox as a stream. */
|
|
15
|
+
get(path: string, options?: RequestOptions): Promise<ReadableStream<Uint8Array>>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FilesResource = void 0;
|
|
4
|
+
const path_1 = require("./path");
|
|
5
|
+
class FilesResource {
|
|
6
|
+
transport;
|
|
7
|
+
sandboxId;
|
|
8
|
+
/** @internal Create the files wrapper for one sandbox. */
|
|
9
|
+
constructor(transport, sandboxId) {
|
|
10
|
+
this.transport = transport;
|
|
11
|
+
this.sandboxId = sandboxId;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Upload file bytes to a path inside the sandbox.
|
|
15
|
+
* Tip: pass a Buffer/Uint8Array when you can so Content-Length is set automatically.
|
|
16
|
+
*/
|
|
17
|
+
async put(path, body, options) {
|
|
18
|
+
const headers = {
|
|
19
|
+
'content-type': 'application/octet-stream',
|
|
20
|
+
};
|
|
21
|
+
if (Buffer.isBuffer(body) || body instanceof Uint8Array) {
|
|
22
|
+
headers['content-length'] = String(body.byteLength);
|
|
23
|
+
}
|
|
24
|
+
await this.transport.requestBinary({
|
|
25
|
+
endpoint: `/sandboxes/${this.sandboxId}/files/${(0, path_1.encodeFilePath)(path)}`,
|
|
26
|
+
method: 'PUT',
|
|
27
|
+
body,
|
|
28
|
+
headers,
|
|
29
|
+
...options,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Download a file from the sandbox as a stream. */
|
|
33
|
+
get(path, options) {
|
|
34
|
+
return this.transport.requestStream({
|
|
35
|
+
endpoint: `/sandboxes/${this.sandboxId}/files/${(0, path_1.encodeFilePath)(path)}`,
|
|
36
|
+
method: 'GET',
|
|
37
|
+
...options,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.FilesResource = FilesResource;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { ExecResource } from './exec';
|
|
2
|
+
export { FilesResource } from './files';
|
|
3
|
+
export { SandboxHandle } from './sandbox-handle';
|
|
4
|
+
export { SandboxesResource } from './sandboxes';
|
|
5
|
+
export { ScopedSandboxResource } from './scoped-sandbox';
|
|
6
|
+
export { SnapshotScopeResource, SnapshotsResource } from './snapshots';
|
|
7
|
+
export { StatsResource } from './stats';
|
|
8
|
+
export { VolumesResource } from './volumes';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VolumesResource = exports.StatsResource = exports.SnapshotsResource = exports.SnapshotScopeResource = exports.ScopedSandboxResource = exports.SandboxesResource = exports.SandboxHandle = exports.FilesResource = exports.ExecResource = void 0;
|
|
4
|
+
var exec_1 = require("./exec");
|
|
5
|
+
Object.defineProperty(exports, "ExecResource", { enumerable: true, get: function () { return exec_1.ExecResource; } });
|
|
6
|
+
var files_1 = require("./files");
|
|
7
|
+
Object.defineProperty(exports, "FilesResource", { enumerable: true, get: function () { return files_1.FilesResource; } });
|
|
8
|
+
var sandbox_handle_1 = require("./sandbox-handle");
|
|
9
|
+
Object.defineProperty(exports, "SandboxHandle", { enumerable: true, get: function () { return sandbox_handle_1.SandboxHandle; } });
|
|
10
|
+
var sandboxes_1 = require("./sandboxes");
|
|
11
|
+
Object.defineProperty(exports, "SandboxesResource", { enumerable: true, get: function () { return sandboxes_1.SandboxesResource; } });
|
|
12
|
+
var scoped_sandbox_1 = require("./scoped-sandbox");
|
|
13
|
+
Object.defineProperty(exports, "ScopedSandboxResource", { enumerable: true, get: function () { return scoped_sandbox_1.ScopedSandboxResource; } });
|
|
14
|
+
var snapshots_1 = require("./snapshots");
|
|
15
|
+
Object.defineProperty(exports, "SnapshotScopeResource", { enumerable: true, get: function () { return snapshots_1.SnapshotScopeResource; } });
|
|
16
|
+
Object.defineProperty(exports, "SnapshotsResource", { enumerable: true, get: function () { return snapshots_1.SnapshotsResource; } });
|
|
17
|
+
var stats_1 = require("./stats");
|
|
18
|
+
Object.defineProperty(exports, "StatsResource", { enumerable: true, get: function () { return stats_1.StatsResource; } });
|
|
19
|
+
var volumes_1 = require("./volumes");
|
|
20
|
+
Object.defineProperty(exports, "VolumesResource", { enumerable: true, get: function () { return volumes_1.VolumesResource; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Encode a single path segment safely for URL usage. */
|
|
2
|
+
export declare function encodePathSegment(value: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Encode a sandbox file path without encoding forward slashes.
|
|
5
|
+
* Example: `tmp/my file.txt` -> `tmp/my%20file.txt`
|
|
6
|
+
*/
|
|
7
|
+
export declare function encodeFilePath(path: string): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.encodePathSegment = encodePathSegment;
|
|
4
|
+
exports.encodeFilePath = encodeFilePath;
|
|
5
|
+
/** Encode a single path segment safely for URL usage. */
|
|
6
|
+
function encodePathSegment(value) {
|
|
7
|
+
return encodeURIComponent(value);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Encode a sandbox file path without encoding forward slashes.
|
|
11
|
+
* Example: `tmp/my file.txt` -> `tmp/my%20file.txt`
|
|
12
|
+
*/
|
|
13
|
+
function encodeFilePath(path) {
|
|
14
|
+
return path
|
|
15
|
+
.split('/')
|
|
16
|
+
.filter((segment) => segment.length > 0)
|
|
17
|
+
.map(encodePathSegment)
|
|
18
|
+
.join('/');
|
|
19
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SandboxStatus } from '../enums';
|
|
2
|
+
import type { RequestOptions } from '../transport/http';
|
|
3
|
+
import type { AckMessage, CodeInput, CreateSandboxResult, CreateSnapshotInput, ExecInput, ExecResult, FileUploadBody, Paginated, Pagination, Sandbox, SandboxRuntimeOptions, Snapshot, Stats, StatsQuery, WaitUntilReadyOptions } from '../types';
|
|
4
|
+
import type { SandboxesResource } from './sandboxes';
|
|
5
|
+
export declare class SandboxHandle {
|
|
6
|
+
private readonly sandboxes;
|
|
7
|
+
private readonly scope;
|
|
8
|
+
private sandboxState;
|
|
9
|
+
/** Snapshot operations grouped under a dedicated namespace. */
|
|
10
|
+
readonly snapshots: {
|
|
11
|
+
create: (input: CreateSnapshotInput, options?: RequestOptions) => Promise<Snapshot>;
|
|
12
|
+
list: (query?: Pagination, options?: RequestOptions) => Promise<Paginated<Snapshot>>;
|
|
13
|
+
};
|
|
14
|
+
/** @internal Create a sandbox handle from create/get responses. */
|
|
15
|
+
constructor(sandboxes: SandboxesResource, state: Sandbox | CreateSandboxResult);
|
|
16
|
+
/** Current sandbox id. */
|
|
17
|
+
get id(): string;
|
|
18
|
+
/** Current cached sandbox status. */
|
|
19
|
+
get status(): SandboxStatus;
|
|
20
|
+
/** Current cached sandbox payload. */
|
|
21
|
+
get data(): Sandbox | CreateSandboxResult;
|
|
22
|
+
/** Refresh sandbox details from the API and update local state. */
|
|
23
|
+
refresh(options?: RequestOptions): Promise<Sandbox>;
|
|
24
|
+
/** Destroy this sandbox (idempotent). */
|
|
25
|
+
destroy(options?: RequestOptions): Promise<void>;
|
|
26
|
+
/** Request pause for this sandbox and refresh cached state. */
|
|
27
|
+
pause(options?: RequestOptions): Promise<AckMessage | undefined>;
|
|
28
|
+
/** Request resume for this sandbox and refresh cached state. */
|
|
29
|
+
resume(options?: RequestOptions): Promise<AckMessage | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* Poll sandbox status until it becomes `ready`.
|
|
32
|
+
* Throws on timeout or when `signal` is aborted.
|
|
33
|
+
*/
|
|
34
|
+
waitUntilReady(options?: WaitUntilReadyOptions): Promise<Sandbox>;
|
|
35
|
+
/**
|
|
36
|
+
* Run a shell command in this sandbox.
|
|
37
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
38
|
+
*/
|
|
39
|
+
exec(input: ExecInput & {
|
|
40
|
+
stream: true;
|
|
41
|
+
}, options?: SandboxRuntimeOptions): Promise<ReadableStream<Uint8Array>>;
|
|
42
|
+
exec(input: ExecInput, options?: SandboxRuntimeOptions): Promise<ExecResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Run a code snippet in this sandbox.
|
|
45
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
46
|
+
*/
|
|
47
|
+
runCode(input: CodeInput & {
|
|
48
|
+
stream: true;
|
|
49
|
+
}, options?: SandboxRuntimeOptions): Promise<ReadableStream<Uint8Array>>;
|
|
50
|
+
runCode(input: CodeInput, options?: SandboxRuntimeOptions): Promise<ExecResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Upload a file into this sandbox.
|
|
53
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
54
|
+
*/
|
|
55
|
+
putFile(path: string, body: FileUploadBody, options?: SandboxRuntimeOptions): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Download a file from this sandbox.
|
|
58
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
59
|
+
*/
|
|
60
|
+
getFile(path: string, options?: SandboxRuntimeOptions): Promise<ReadableStream<Uint8Array>>;
|
|
61
|
+
/**
|
|
62
|
+
* Fetch usage stats for this sandbox.
|
|
63
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
64
|
+
*/
|
|
65
|
+
stats(query?: StatsQuery, options?: SandboxRuntimeOptions): Promise<Stats>;
|
|
66
|
+
/**
|
|
67
|
+
* Create a snapshot for this sandbox.
|
|
68
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
69
|
+
*/
|
|
70
|
+
createSnapshot(input: CreateSnapshotInput, options?: SandboxRuntimeOptions): Promise<Snapshot>;
|
|
71
|
+
/**
|
|
72
|
+
* List snapshots for this sandbox.
|
|
73
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
74
|
+
*/
|
|
75
|
+
listSnapshots(query?: Pagination, options?: SandboxRuntimeOptions): Promise<Paginated<Snapshot>>;
|
|
76
|
+
private ensureReady;
|
|
77
|
+
private assertReady;
|
|
78
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SandboxHandle = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const enums_1 = require("../enums");
|
|
6
|
+
function delay(ms) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
setTimeout(resolve, ms);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
class SandboxHandle {
|
|
12
|
+
sandboxes;
|
|
13
|
+
scope;
|
|
14
|
+
sandboxState;
|
|
15
|
+
/** Snapshot operations grouped under a dedicated namespace. */
|
|
16
|
+
snapshots;
|
|
17
|
+
/** @internal Create a sandbox handle from create/get responses. */
|
|
18
|
+
constructor(sandboxes, state) {
|
|
19
|
+
this.sandboxes = sandboxes;
|
|
20
|
+
this.sandboxState = state;
|
|
21
|
+
this.scope = this.sandboxes.use(state.id);
|
|
22
|
+
this.snapshots = {
|
|
23
|
+
create: (input, options) => this.createSnapshot(input, options),
|
|
24
|
+
list: (query = {}, options) => this.listSnapshots(query, options),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Current sandbox id. */
|
|
28
|
+
get id() {
|
|
29
|
+
return this.sandboxState.id;
|
|
30
|
+
}
|
|
31
|
+
/** Current cached sandbox status. */
|
|
32
|
+
get status() {
|
|
33
|
+
return this.sandboxState.status;
|
|
34
|
+
}
|
|
35
|
+
/** Current cached sandbox payload. */
|
|
36
|
+
get data() {
|
|
37
|
+
return this.sandboxState;
|
|
38
|
+
}
|
|
39
|
+
/** Refresh sandbox details from the API and update local state. */
|
|
40
|
+
async refresh(options) {
|
|
41
|
+
const sandbox = await this.sandboxes.getData(this.id, options);
|
|
42
|
+
this.sandboxState = sandbox;
|
|
43
|
+
return sandbox;
|
|
44
|
+
}
|
|
45
|
+
/** Destroy this sandbox (idempotent). */
|
|
46
|
+
async destroy(options) {
|
|
47
|
+
await this.sandboxes.destroy(this.id, options);
|
|
48
|
+
}
|
|
49
|
+
/** Request pause for this sandbox and refresh cached state. */
|
|
50
|
+
async pause(options) {
|
|
51
|
+
const response = await this.sandboxes.pause(this.id, options);
|
|
52
|
+
await this.refresh(options);
|
|
53
|
+
return response;
|
|
54
|
+
}
|
|
55
|
+
/** Request resume for this sandbox and refresh cached state. */
|
|
56
|
+
async resume(options) {
|
|
57
|
+
const response = await this.sandboxes.resume(this.id, options);
|
|
58
|
+
await this.refresh(options);
|
|
59
|
+
return response;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Poll sandbox status until it becomes `ready`.
|
|
63
|
+
* Throws on timeout or when `signal` is aborted.
|
|
64
|
+
*/
|
|
65
|
+
async waitUntilReady(options = {}) {
|
|
66
|
+
const timeoutMs = options.timeoutMs ?? constants_1.DEFAULT_SANDBOX_READY_TIMEOUT_MS;
|
|
67
|
+
const pollIntervalMs = options.pollIntervalMs ?? constants_1.DEFAULT_SANDBOX_READY_POLL_INTERVAL_MS;
|
|
68
|
+
const deadline = Date.now() + timeoutMs;
|
|
69
|
+
while (true) {
|
|
70
|
+
if (options.signal?.aborted) {
|
|
71
|
+
throw new Error('waitUntilReady aborted by signal');
|
|
72
|
+
}
|
|
73
|
+
const sandbox = await this.refresh({ signal: options.signal });
|
|
74
|
+
if (sandbox.status === enums_1.SandboxStatus.Ready) {
|
|
75
|
+
return sandbox;
|
|
76
|
+
}
|
|
77
|
+
if (Date.now() >= deadline) {
|
|
78
|
+
throw new Error(`Sandbox ${this.id} did not become ready within ${timeoutMs}ms`);
|
|
79
|
+
}
|
|
80
|
+
await delay(pollIntervalMs);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async exec(input, options = {}) {
|
|
84
|
+
await this.ensureReady(options.waitUntilReady);
|
|
85
|
+
return this.scope.exec(input, options);
|
|
86
|
+
}
|
|
87
|
+
async runCode(input, options = {}) {
|
|
88
|
+
await this.ensureReady(options.waitUntilReady);
|
|
89
|
+
return this.scope.runCode(input, options);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Upload a file into this sandbox.
|
|
93
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
94
|
+
*/
|
|
95
|
+
async putFile(path, body, options = {}) {
|
|
96
|
+
await this.ensureReady(options.waitUntilReady);
|
|
97
|
+
await this.scope.putFile(path, body, options);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Download a file from this sandbox.
|
|
101
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
102
|
+
*/
|
|
103
|
+
async getFile(path, options = {}) {
|
|
104
|
+
await this.ensureReady(options.waitUntilReady);
|
|
105
|
+
return this.scope.getFile(path, options);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Fetch usage stats for this sandbox.
|
|
109
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
110
|
+
*/
|
|
111
|
+
async stats(query = {}, options = {}) {
|
|
112
|
+
await this.ensureReady(options.waitUntilReady);
|
|
113
|
+
return this.scope.stats(query, options);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Create a snapshot for this sandbox.
|
|
117
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
118
|
+
*/
|
|
119
|
+
async createSnapshot(input, options = {}) {
|
|
120
|
+
await this.ensureReady(options.waitUntilReady);
|
|
121
|
+
return this.scope.createSnapshot(input, options);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* List snapshots for this sandbox.
|
|
125
|
+
* By default this throws when not ready; set `waitUntilReady` to auto-wait.
|
|
126
|
+
*/
|
|
127
|
+
async listSnapshots(query = {}, options = {}) {
|
|
128
|
+
await this.ensureReady(options.waitUntilReady);
|
|
129
|
+
return this.scope.listSnapshots(query, options);
|
|
130
|
+
}
|
|
131
|
+
async ensureReady(waitUntilReady) {
|
|
132
|
+
if (this.status === enums_1.SandboxStatus.Ready) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (waitUntilReady) {
|
|
136
|
+
if (typeof waitUntilReady === 'object') {
|
|
137
|
+
await this.waitUntilReady(waitUntilReady);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
await this.waitUntilReady();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this.assertReady();
|
|
144
|
+
}
|
|
145
|
+
assertReady() {
|
|
146
|
+
if (this.status !== enums_1.SandboxStatus.Ready) {
|
|
147
|
+
throw new Error(`Sandbox ${this.id} is ${this.status}. Call waitUntilReady() or refresh() before runtime operations.`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.SandboxHandle = SandboxHandle;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { RequestOptions } from '../transport/http';
|
|
2
|
+
import { HttpTransport } from '../transport/http';
|
|
3
|
+
import type { AckMessage, CreateSandboxRequest, CreateSandboxWithVolumeInput, CreateVolumeInput, Paginated, Sandbox, SandboxReadyRequestOptions, SandboxRegionsResult, SandboxTemplate, TeamScopedPagination, Volume, WaitPreference } from '../types';
|
|
4
|
+
import { SandboxHandle } from './sandbox-handle';
|
|
5
|
+
import { ScopedSandboxResource } from './scoped-sandbox';
|
|
6
|
+
export type QuickstartSandboxInput = Omit<CreateSandboxRequest, 'template' | 'persistent' | 'persistentDiskGB'> & {
|
|
7
|
+
template?: string;
|
|
8
|
+
persistentDiskGB?: number;
|
|
9
|
+
waitUntilReady?: WaitPreference;
|
|
10
|
+
};
|
|
11
|
+
export declare class SandboxesResource {
|
|
12
|
+
private readonly transport;
|
|
13
|
+
private readonly volumes;
|
|
14
|
+
/** @internal Create the sandboxes resource wrapper. */
|
|
15
|
+
constructor(transport: HttpTransport);
|
|
16
|
+
/**
|
|
17
|
+
* Create a new sandbox.
|
|
18
|
+
* Region is optional; when omitted this SDK picks the first available region.
|
|
19
|
+
* The sandbox starts asynchronously, so fetch it until `status` is `ready`
|
|
20
|
+
* before running commands or file operations.
|
|
21
|
+
*/
|
|
22
|
+
create(input: CreateSandboxRequest, options?: RequestOptions): Promise<SandboxHandle>;
|
|
23
|
+
/** Create a sandbox and wait until it is `ready` before returning it. */
|
|
24
|
+
createReady(input: CreateSandboxRequest, options?: SandboxReadyRequestOptions): Promise<SandboxHandle>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a volume and then create a sandbox attached to that volume.
|
|
27
|
+
* This is the one-call helper for persistent sandbox workflows.
|
|
28
|
+
*/
|
|
29
|
+
withVolume(input: CreateSandboxWithVolumeInput, options?: RequestOptions): Promise<SandboxHandle>;
|
|
30
|
+
/** Create a sandbox-scoped volume with package-level defaults and validation. */
|
|
31
|
+
createVolume(input: CreateVolumeInput, options?: RequestOptions): Promise<Volume>;
|
|
32
|
+
/** List your sandboxes with pagination. */
|
|
33
|
+
list(query?: TeamScopedPagination, options?: RequestOptions): Promise<Paginated<SandboxHandle>>;
|
|
34
|
+
/** Iterate over all sandbox handles across paginated results. */
|
|
35
|
+
iterate(query?: TeamScopedPagination, options?: RequestOptions): AsyncGenerator<SandboxHandle>;
|
|
36
|
+
/** Fetch one sandbox handle by id. */
|
|
37
|
+
get(sandboxId: string, options?: RequestOptions): Promise<SandboxHandle>;
|
|
38
|
+
/** Fetch one sandbox and wait for `ready` before returning the handle. */
|
|
39
|
+
getReady(sandboxId: string, options?: SandboxReadyRequestOptions): Promise<SandboxHandle>;
|
|
40
|
+
/** @internal Fetch raw sandbox payload by id. */
|
|
41
|
+
getData(sandboxId: string, options?: RequestOptions): Promise<Sandbox>;
|
|
42
|
+
/** @internal Fetch raw paginated sandbox payload. */
|
|
43
|
+
listData(query?: TeamScopedPagination, options?: RequestOptions): Promise<Paginated<Sandbox>>;
|
|
44
|
+
/** List regions where sandboxes can be provisioned. */
|
|
45
|
+
listRegions(options?: RequestOptions): Promise<SandboxRegionsResult>;
|
|
46
|
+
/** List sandbox templates available for create operations. */
|
|
47
|
+
listTemplates(options?: RequestOptions): Promise<SandboxTemplate[]>;
|
|
48
|
+
/** Fetch one template by name from the template catalog. */
|
|
49
|
+
getTemplate(templateName: string, options?: RequestOptions): Promise<SandboxTemplate | undefined>;
|
|
50
|
+
/** Destroy a sandbox (idempotent). */
|
|
51
|
+
destroy(sandboxId: string, options?: RequestOptions): Promise<void>;
|
|
52
|
+
/** Request sandbox pause. */
|
|
53
|
+
pause(sandboxId: string, options?: RequestOptions): Promise<AckMessage | undefined>;
|
|
54
|
+
/** Request sandbox resume. */
|
|
55
|
+
resume(sandboxId: string, options?: RequestOptions): Promise<AckMessage | undefined>;
|
|
56
|
+
/** Use runtime operations for a specific sandbox id. */
|
|
57
|
+
use(sandboxId: string): ScopedSandboxResource;
|
|
58
|
+
/** Opinionated Node.js quickstart (persistent sandbox + optional wait). */
|
|
59
|
+
quickstartNode(input?: QuickstartSandboxInput, options?: RequestOptions): Promise<SandboxHandle>;
|
|
60
|
+
/** Opinionated Python quickstart (persistent sandbox + optional wait). */
|
|
61
|
+
quickstartPython(input?: QuickstartSandboxInput, options?: RequestOptions): Promise<SandboxHandle>;
|
|
62
|
+
private quickstart;
|
|
63
|
+
private resolveRegionId;
|
|
64
|
+
}
|