@vercel/sandbox 1.8.0 → 2.0.0-beta.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/api-client.d.ts +319 -4
- package/dist/api-client/api-client.js +68 -1
- package/dist/api-client/api-client.js.map +1 -1
- package/dist/api-client/validators.d.ts +1271 -0
- package/dist/api-client/validators.js +37 -1
- package/dist/api-client/validators.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/sandbox.d.ts +277 -126
- package/dist/sandbox.js +262 -217
- package/dist/sandbox.js.map +1 -1
- package/dist/session.d.ts +369 -0
- package/dist/session.js +486 -0
- package/dist/session.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/dist/sandbox.js
CHANGED
|
@@ -1,74 +1,153 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Sandbox = void 0;
|
|
4
|
-
const promises_1 = require("stream/promises");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const promises_2 = require("fs/promises");
|
|
7
|
-
const path_1 = require("path");
|
|
8
4
|
const api_client_1 = require("./api-client");
|
|
9
|
-
const
|
|
5
|
+
const api_error_1 = require("./api-client/api-error");
|
|
10
6
|
const get_credentials_1 = require("./utils/get-credentials");
|
|
11
7
|
const types_1 = require("./utils/types");
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
8
|
+
const session_1 = require("./session");
|
|
9
|
+
const network_policy_1 = require("./utils/network-policy");
|
|
10
|
+
const promises_1 = require("node:timers/promises");
|
|
11
|
+
function isSandboxStoppedError(err) {
|
|
12
|
+
return err instanceof api_error_1.APIError && err.response.status === 410;
|
|
13
|
+
}
|
|
14
|
+
function isSandboxStoppingError(err) {
|
|
15
|
+
return (err instanceof api_error_1.APIError &&
|
|
16
|
+
err.response.status === 422 &&
|
|
17
|
+
err.json?.error?.code === "sandbox_stopping");
|
|
18
|
+
}
|
|
15
19
|
/**
|
|
16
|
-
* A Sandbox is
|
|
17
|
-
*
|
|
20
|
+
* A Sandbox is a persistent, isolated Linux MicroVMs to run commands in.
|
|
18
21
|
* Use {@link Sandbox.create} or {@link Sandbox.get} to construct.
|
|
19
22
|
* @hideconstructor
|
|
20
23
|
*/
|
|
21
24
|
class Sandbox {
|
|
22
25
|
/**
|
|
23
|
-
*
|
|
26
|
+
* The name of this sandbox.
|
|
24
27
|
*/
|
|
25
|
-
get
|
|
26
|
-
return this.
|
|
28
|
+
get name() {
|
|
29
|
+
return this.namedSandbox.name;
|
|
27
30
|
}
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Routes from ports to subdomains.
|
|
33
|
+
* @hidden
|
|
34
|
+
*/
|
|
35
|
+
get routes() {
|
|
36
|
+
return this.session.routes;
|
|
30
37
|
}
|
|
31
38
|
/**
|
|
32
|
-
*
|
|
39
|
+
* Whether this sandbox snapshots on shutdown.
|
|
33
40
|
*/
|
|
34
|
-
get
|
|
35
|
-
return this.
|
|
41
|
+
get snapshotOnShutdown() {
|
|
42
|
+
return this.namedSandbox.snapshotOnShutdown;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The region this sandbox runs in.
|
|
46
|
+
*/
|
|
47
|
+
get region() {
|
|
48
|
+
return this.namedSandbox.region;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Number of virtual CPUs allocated.
|
|
52
|
+
*/
|
|
53
|
+
get vcpus() {
|
|
54
|
+
return this.namedSandbox.vcpus;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Memory allocated in MB.
|
|
58
|
+
*/
|
|
59
|
+
get memory() {
|
|
60
|
+
return this.namedSandbox.memory;
|
|
61
|
+
}
|
|
62
|
+
/** Runtime identifier (e.g. "node24", "python3.13"). */
|
|
63
|
+
get runtime() {
|
|
64
|
+
return this.namedSandbox.runtime;
|
|
36
65
|
}
|
|
37
66
|
/**
|
|
38
|
-
*
|
|
67
|
+
* Cumulative egress bytes across all sessions.
|
|
68
|
+
*/
|
|
69
|
+
get totalEgressBytes() {
|
|
70
|
+
return this.namedSandbox.totalEgressBytes;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Cumulative ingress bytes across all sessions.
|
|
74
|
+
*/
|
|
75
|
+
get totalIngressBytes() {
|
|
76
|
+
return this.namedSandbox.totalIngressBytes;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Cumulative active CPU duration in milliseconds across all sessions.
|
|
80
|
+
*/
|
|
81
|
+
get totalActiveCpuDurationMs() {
|
|
82
|
+
return this.namedSandbox.totalActiveCpuDurationMs;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Cumulative wall-clock duration in milliseconds across all sessions.
|
|
86
|
+
*/
|
|
87
|
+
get totalDurationMs() {
|
|
88
|
+
return this.namedSandbox.totalDurationMs;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* When this sandbox was last updated.
|
|
92
|
+
*/
|
|
93
|
+
get updatedAt() {
|
|
94
|
+
return new Date(this.namedSandbox.updatedAt);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* When this sandbox was created.
|
|
39
98
|
*/
|
|
40
99
|
get createdAt() {
|
|
41
|
-
return new Date(this.
|
|
100
|
+
return new Date(this.namedSandbox.createdAt);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Interactive port.
|
|
104
|
+
*/
|
|
105
|
+
get interactivePort() {
|
|
106
|
+
return this.session.interactivePort;
|
|
42
107
|
}
|
|
43
108
|
/**
|
|
44
|
-
* The
|
|
109
|
+
* The status of the current session.
|
|
110
|
+
*/
|
|
111
|
+
get status() {
|
|
112
|
+
return this.session.status;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The default timeout of this sandbox in milliseconds.
|
|
45
116
|
*/
|
|
46
117
|
get timeout() {
|
|
47
|
-
return this.
|
|
118
|
+
return this.namedSandbox.timeout;
|
|
48
119
|
}
|
|
49
120
|
/**
|
|
50
|
-
* The network policy of
|
|
121
|
+
* The default network policy of this sandbox.
|
|
51
122
|
*/
|
|
52
123
|
get networkPolicy() {
|
|
53
|
-
return this.
|
|
124
|
+
return this.namedSandbox.networkPolicy
|
|
125
|
+
? (0, network_policy_1.fromAPINetworkPolicy)(this.namedSandbox.networkPolicy)
|
|
126
|
+
: undefined;
|
|
54
127
|
}
|
|
55
128
|
/**
|
|
56
|
-
* If the
|
|
129
|
+
* If the session was created from a snapshot, the ID of that snapshot.
|
|
57
130
|
*/
|
|
58
131
|
get sourceSnapshotId() {
|
|
59
|
-
return this.
|
|
132
|
+
return this.session.sourceSnapshotId;
|
|
60
133
|
}
|
|
61
134
|
/**
|
|
62
|
-
* The
|
|
135
|
+
* The current snapshot ID of this sandbox, if any.
|
|
136
|
+
*/
|
|
137
|
+
get currentSnapshotId() {
|
|
138
|
+
return this.namedSandbox.currentSnapshotId;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The amount of CPU used by the session. Only reported once the VM is stopped.
|
|
63
142
|
*/
|
|
64
143
|
get activeCpuUsageMs() {
|
|
65
|
-
return this.
|
|
144
|
+
return this.session.activeCpuUsageMs;
|
|
66
145
|
}
|
|
67
146
|
/**
|
|
68
|
-
* The amount of network data used by the
|
|
147
|
+
* The amount of network data used by the session. Only reported once the VM is stopped.
|
|
69
148
|
*/
|
|
70
149
|
get networkTransfer() {
|
|
71
|
-
return this.
|
|
150
|
+
return this.session.networkTransfer;
|
|
72
151
|
}
|
|
73
152
|
/**
|
|
74
153
|
* Allow to get a list of sandboxes for a team narrowed to the given params.
|
|
@@ -82,7 +161,7 @@ class Sandbox {
|
|
|
82
161
|
token: credentials.token,
|
|
83
162
|
fetch: params?.fetch,
|
|
84
163
|
});
|
|
85
|
-
return client.
|
|
164
|
+
return client.listNamedSandboxes({
|
|
86
165
|
...credentials,
|
|
87
166
|
...params,
|
|
88
167
|
});
|
|
@@ -107,7 +186,7 @@ class Sandbox {
|
|
|
107
186
|
fetch: params?.fetch,
|
|
108
187
|
});
|
|
109
188
|
const privateParams = (0, types_1.getPrivateParams)(params);
|
|
110
|
-
const
|
|
189
|
+
const response = await client.createSandbox({
|
|
111
190
|
source: params?.source,
|
|
112
191
|
projectId: credentials.projectId,
|
|
113
192
|
ports: params?.ports ?? [],
|
|
@@ -117,16 +196,20 @@ class Sandbox {
|
|
|
117
196
|
networkPolicy: params?.networkPolicy,
|
|
118
197
|
env: params?.env,
|
|
119
198
|
signal: params?.signal,
|
|
199
|
+
name: params?.name,
|
|
200
|
+
snapshotOnShutdown: params?.snapshotOnShutdown,
|
|
120
201
|
...privateParams,
|
|
121
202
|
});
|
|
122
203
|
return new DisposableSandbox({
|
|
123
204
|
client,
|
|
124
|
-
|
|
125
|
-
|
|
205
|
+
session: response.json.sandbox,
|
|
206
|
+
namedSandbox: response.json.namedSandbox,
|
|
207
|
+
routes: response.json.routes,
|
|
208
|
+
projectId: credentials.projectId,
|
|
126
209
|
});
|
|
127
210
|
}
|
|
128
211
|
/**
|
|
129
|
-
* Retrieve an existing sandbox.
|
|
212
|
+
* Retrieve an existing sandbox and resume its session.
|
|
130
213
|
*
|
|
131
214
|
* @param params - Get parameters and optional credentials.
|
|
132
215
|
* @returns A promise resolving to the {@link Sandbox}.
|
|
@@ -138,47 +221,93 @@ class Sandbox {
|
|
|
138
221
|
token: credentials.token,
|
|
139
222
|
fetch: params.fetch,
|
|
140
223
|
});
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
224
|
+
const response = await client.getNamedSandbox({
|
|
225
|
+
name: params.name,
|
|
226
|
+
projectId: credentials.projectId,
|
|
227
|
+
resume: params.resume,
|
|
144
228
|
signal: params.signal,
|
|
145
|
-
...privateParams,
|
|
146
229
|
});
|
|
147
230
|
return new Sandbox({
|
|
148
231
|
client,
|
|
149
|
-
|
|
150
|
-
|
|
232
|
+
session: response.json.sandbox,
|
|
233
|
+
namedSandbox: response.json.namedSandbox,
|
|
234
|
+
routes: response.json.routes,
|
|
235
|
+
projectId: credentials.projectId,
|
|
151
236
|
});
|
|
152
237
|
}
|
|
153
|
-
constructor({ client, routes,
|
|
238
|
+
constructor({ client, routes, session, namedSandbox, projectId, }) {
|
|
154
239
|
this.client = client;
|
|
155
|
-
this.
|
|
156
|
-
this.
|
|
240
|
+
this.session = new session_1.Session({ client, routes, session });
|
|
241
|
+
this.namedSandbox = namedSandbox;
|
|
242
|
+
this.projectId = projectId;
|
|
157
243
|
}
|
|
158
244
|
/**
|
|
159
|
-
* Get
|
|
245
|
+
* Get the current session (the running VM) for this sandbox.
|
|
160
246
|
*
|
|
161
|
-
* @
|
|
162
|
-
* @param opts - Optional parameters.
|
|
163
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
164
|
-
* @returns A {@link Command} instance representing the command
|
|
247
|
+
* @returns The {@link Session} instance.
|
|
165
248
|
*/
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
249
|
+
currentSession() {
|
|
250
|
+
return this.session;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Resume this sandbox by creating a new session via `getNamedSandbox`.
|
|
254
|
+
*/
|
|
255
|
+
async resume(signal) {
|
|
256
|
+
const response = await this.client.getNamedSandbox({
|
|
257
|
+
name: this.namedSandbox.name,
|
|
258
|
+
projectId: this.projectId,
|
|
259
|
+
resume: true,
|
|
260
|
+
signal,
|
|
171
261
|
});
|
|
172
|
-
|
|
262
|
+
this.session = new session_1.Session({
|
|
173
263
|
client: this.client,
|
|
174
|
-
|
|
175
|
-
|
|
264
|
+
routes: response.json.routes,
|
|
265
|
+
session: response.json.sandbox,
|
|
176
266
|
});
|
|
177
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Poll until the current session reaches a terminal state, then resume.
|
|
270
|
+
*/
|
|
271
|
+
async waitForStopAndResume(signal) {
|
|
272
|
+
const pollingInterval = 500;
|
|
273
|
+
let status = this.session.status;
|
|
274
|
+
while (status === "stopping" || status === "snapshotting") {
|
|
275
|
+
await (0, promises_1.setTimeout)(pollingInterval, undefined, { signal });
|
|
276
|
+
const poll = await this.client.getSandbox({
|
|
277
|
+
sandboxId: this.session.sessionId,
|
|
278
|
+
signal,
|
|
279
|
+
});
|
|
280
|
+
this.session = new session_1.Session({
|
|
281
|
+
client: this.client,
|
|
282
|
+
routes: poll.json.routes,
|
|
283
|
+
session: poll.json.sandbox,
|
|
284
|
+
});
|
|
285
|
+
status = poll.json.sandbox.status;
|
|
286
|
+
}
|
|
287
|
+
await this.resume(signal);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Execute `fn`, and if the session is stopped/stopping, resume and retry.
|
|
291
|
+
*/
|
|
292
|
+
async withResume(fn, signal) {
|
|
293
|
+
try {
|
|
294
|
+
return await fn();
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
if (isSandboxStoppedError(err)) {
|
|
298
|
+
await this.resume(signal);
|
|
299
|
+
return fn();
|
|
300
|
+
}
|
|
301
|
+
if (isSandboxStoppingError(err)) {
|
|
302
|
+
await this.waitForStopAndResume(signal);
|
|
303
|
+
return fn();
|
|
304
|
+
}
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
178
308
|
async runCommand(commandOrParams, args, opts) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
: this._runCommand(commandOrParams);
|
|
309
|
+
const signal = typeof commandOrParams === "string" ? opts?.signal : commandOrParams.signal;
|
|
310
|
+
return this.withResume(() => this.session.runCommand(commandOrParams, args, opts), signal);
|
|
182
311
|
}
|
|
183
312
|
/**
|
|
184
313
|
* Internal helper to start a command in the sandbox.
|
|
@@ -187,71 +316,8 @@ class Sandbox {
|
|
|
187
316
|
* @returns A {@link Command} or {@link CommandFinished}, depending on `detached`.
|
|
188
317
|
* @internal
|
|
189
318
|
*/
|
|
190
|
-
async
|
|
191
|
-
|
|
192
|
-
const getLogs = (command) => {
|
|
193
|
-
if (params.stdout || params.stderr) {
|
|
194
|
-
(async () => {
|
|
195
|
-
try {
|
|
196
|
-
for await (const log of command.logs({ signal: params.signal })) {
|
|
197
|
-
if (log.stream === "stdout") {
|
|
198
|
-
params.stdout?.write(log.data);
|
|
199
|
-
}
|
|
200
|
-
else if (log.stream === "stderr") {
|
|
201
|
-
params.stderr?.write(log.data);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
catch (err) {
|
|
206
|
-
if (params.signal?.aborted) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
throw err;
|
|
210
|
-
}
|
|
211
|
-
})();
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
if (wait) {
|
|
215
|
-
const commandStream = await this.client.runCommand({
|
|
216
|
-
sandboxId: this.sandbox.id,
|
|
217
|
-
command: params.cmd,
|
|
218
|
-
args: params.args ?? [],
|
|
219
|
-
cwd: params.cwd,
|
|
220
|
-
env: params.env ?? {},
|
|
221
|
-
sudo: params.sudo ?? false,
|
|
222
|
-
wait: true,
|
|
223
|
-
signal: params.signal,
|
|
224
|
-
});
|
|
225
|
-
const command = new command_1.Command({
|
|
226
|
-
client: this.client,
|
|
227
|
-
sandboxId: this.sandbox.id,
|
|
228
|
-
cmd: commandStream.command,
|
|
229
|
-
});
|
|
230
|
-
getLogs(command);
|
|
231
|
-
const finished = await commandStream.finished;
|
|
232
|
-
return new command_1.CommandFinished({
|
|
233
|
-
client: this.client,
|
|
234
|
-
sandboxId: this.sandbox.id,
|
|
235
|
-
cmd: finished,
|
|
236
|
-
exitCode: finished.exitCode ?? 0,
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
const commandResponse = await this.client.runCommand({
|
|
240
|
-
sandboxId: this.sandbox.id,
|
|
241
|
-
command: params.cmd,
|
|
242
|
-
args: params.args ?? [],
|
|
243
|
-
cwd: params.cwd,
|
|
244
|
-
env: params.env ?? {},
|
|
245
|
-
sudo: params.sudo ?? false,
|
|
246
|
-
signal: params.signal,
|
|
247
|
-
});
|
|
248
|
-
const command = new command_1.Command({
|
|
249
|
-
client: this.client,
|
|
250
|
-
sandboxId: this.sandbox.id,
|
|
251
|
-
cmd: commandResponse.json.command,
|
|
252
|
-
});
|
|
253
|
-
getLogs(command);
|
|
254
|
-
return command;
|
|
319
|
+
async getCommand(cmdId, opts) {
|
|
320
|
+
return this.withResume(() => this.session.getCommand(cmdId, opts), opts?.signal);
|
|
255
321
|
}
|
|
256
322
|
/**
|
|
257
323
|
* Create a directory in the filesystem of this sandbox.
|
|
@@ -261,11 +327,7 @@ class Sandbox {
|
|
|
261
327
|
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
262
328
|
*/
|
|
263
329
|
async mkDir(path, opts) {
|
|
264
|
-
|
|
265
|
-
sandboxId: this.sandbox.id,
|
|
266
|
-
path: path,
|
|
267
|
-
signal: opts?.signal,
|
|
268
|
-
});
|
|
330
|
+
return this.withResume(() => this.session.mkDir(path, opts), opts?.signal);
|
|
269
331
|
}
|
|
270
332
|
/**
|
|
271
333
|
* Read a file from the filesystem of this sandbox as a stream.
|
|
@@ -276,12 +338,7 @@ class Sandbox {
|
|
|
276
338
|
* @returns A promise that resolves to a ReadableStream containing the file contents, or null if file not found
|
|
277
339
|
*/
|
|
278
340
|
async readFile(file, opts) {
|
|
279
|
-
return this.
|
|
280
|
-
sandboxId: this.sandbox.id,
|
|
281
|
-
path: file.path,
|
|
282
|
-
cwd: file.cwd,
|
|
283
|
-
signal: opts?.signal,
|
|
284
|
-
});
|
|
341
|
+
return this.withResume(() => this.session.readFile(file, opts), opts?.signal);
|
|
285
342
|
}
|
|
286
343
|
/**
|
|
287
344
|
* Read a file from the filesystem of this sandbox as a Buffer.
|
|
@@ -292,16 +349,7 @@ class Sandbox {
|
|
|
292
349
|
* @returns A promise that resolves to the file contents as a Buffer, or null if file not found
|
|
293
350
|
*/
|
|
294
351
|
async readFileToBuffer(file, opts) {
|
|
295
|
-
|
|
296
|
-
sandboxId: this.sandbox.id,
|
|
297
|
-
path: file.path,
|
|
298
|
-
cwd: file.cwd,
|
|
299
|
-
signal: opts?.signal,
|
|
300
|
-
});
|
|
301
|
-
if (stream === null) {
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
304
|
-
return (0, consume_readable_1.consumeReadable)(stream);
|
|
352
|
+
return this.withResume(() => this.session.readFileToBuffer(file, opts), opts?.signal);
|
|
305
353
|
}
|
|
306
354
|
/**
|
|
307
355
|
* Download a file from the sandbox to the local filesystem.
|
|
@@ -314,34 +362,7 @@ class Sandbox {
|
|
|
314
362
|
* @returns The absolute path to the written file, or null if the source file was not found
|
|
315
363
|
*/
|
|
316
364
|
async downloadFile(src, dst, opts) {
|
|
317
|
-
|
|
318
|
-
throw new Error("downloadFile: source path is required");
|
|
319
|
-
}
|
|
320
|
-
if (!dst?.path) {
|
|
321
|
-
throw new Error("downloadFile: destination path is required");
|
|
322
|
-
}
|
|
323
|
-
const stream = await this.client.readFile({
|
|
324
|
-
sandboxId: this.sandbox.id,
|
|
325
|
-
path: src.path,
|
|
326
|
-
cwd: src.cwd,
|
|
327
|
-
signal: opts?.signal,
|
|
328
|
-
});
|
|
329
|
-
if (stream === null) {
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
try {
|
|
333
|
-
const dstPath = (0, path_1.resolve)(dst.cwd ?? "", dst.path);
|
|
334
|
-
if (opts?.mkdirRecursive) {
|
|
335
|
-
await (0, promises_2.mkdir)((0, path_1.dirname)(dstPath), { recursive: true });
|
|
336
|
-
}
|
|
337
|
-
await (0, promises_1.pipeline)(stream, (0, fs_1.createWriteStream)(dstPath), {
|
|
338
|
-
signal: opts?.signal,
|
|
339
|
-
});
|
|
340
|
-
return dstPath;
|
|
341
|
-
}
|
|
342
|
-
finally {
|
|
343
|
-
stream.destroy();
|
|
344
|
-
}
|
|
365
|
+
return this.withResume(() => this.session.downloadFile(src, dst, opts), opts?.signal);
|
|
345
366
|
}
|
|
346
367
|
/**
|
|
347
368
|
* Write files to the filesystem of this sandbox.
|
|
@@ -354,13 +375,7 @@ class Sandbox {
|
|
|
354
375
|
* @returns A promise that resolves when the files are written
|
|
355
376
|
*/
|
|
356
377
|
async writeFiles(files, opts) {
|
|
357
|
-
return this.
|
|
358
|
-
sandboxId: this.sandbox.id,
|
|
359
|
-
cwd: this.sandbox.cwd,
|
|
360
|
-
extractDir: "/",
|
|
361
|
-
files: files,
|
|
362
|
-
signal: opts?.signal,
|
|
363
|
-
});
|
|
378
|
+
return this.withResume(() => this.session.writeFiles(files, opts), opts?.signal);
|
|
364
379
|
}
|
|
365
380
|
/**
|
|
366
381
|
* Get the public domain of a port of this sandbox.
|
|
@@ -370,13 +385,7 @@ class Sandbox {
|
|
|
370
385
|
* @throws If the port has no associated route
|
|
371
386
|
*/
|
|
372
387
|
domain(p) {
|
|
373
|
-
|
|
374
|
-
if (route) {
|
|
375
|
-
return `https://${route.subdomain}.vercel.run`;
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
throw new Error(`No route for port ${p}`);
|
|
379
|
-
}
|
|
388
|
+
return this.session.domain(p);
|
|
380
389
|
}
|
|
381
390
|
/**
|
|
382
391
|
* Stop the sandbox.
|
|
@@ -387,13 +396,7 @@ class Sandbox {
|
|
|
387
396
|
* @returns The sandbox metadata at the time the stop was acknowledged, or after fully stopped if `blocking` is true.
|
|
388
397
|
*/
|
|
389
398
|
async stop(opts) {
|
|
390
|
-
|
|
391
|
-
sandboxId: this.sandbox.id,
|
|
392
|
-
signal: opts?.signal,
|
|
393
|
-
blocking: opts?.blocking,
|
|
394
|
-
});
|
|
395
|
-
this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
|
|
396
|
-
return this.sandbox;
|
|
399
|
+
return this.session.stop(opts);
|
|
397
400
|
}
|
|
398
401
|
/**
|
|
399
402
|
* Update the network policy for this sandbox.
|
|
@@ -427,14 +430,7 @@ class Sandbox {
|
|
|
427
430
|
* await sandbox.updateNetworkPolicy("deny-all");
|
|
428
431
|
*/
|
|
429
432
|
async updateNetworkPolicy(networkPolicy, opts) {
|
|
430
|
-
|
|
431
|
-
sandboxId: this.sandbox.id,
|
|
432
|
-
networkPolicy: networkPolicy,
|
|
433
|
-
signal: opts?.signal,
|
|
434
|
-
});
|
|
435
|
-
// Update the internal sandbox metadata with the new timeout value
|
|
436
|
-
this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
|
|
437
|
-
return this.sandbox.networkPolicy;
|
|
433
|
+
return this.withResume(() => this.session.updateNetworkPolicy(networkPolicy, opts), opts?.signal);
|
|
438
434
|
}
|
|
439
435
|
/**
|
|
440
436
|
* Extend the timeout of the sandbox by the specified duration.
|
|
@@ -453,13 +449,7 @@ class Sandbox {
|
|
|
453
449
|
* await sandbox.extendTimeout(ms('5m'));
|
|
454
450
|
*/
|
|
455
451
|
async extendTimeout(duration, opts) {
|
|
456
|
-
|
|
457
|
-
sandboxId: this.sandbox.id,
|
|
458
|
-
duration,
|
|
459
|
-
signal: opts?.signal,
|
|
460
|
-
});
|
|
461
|
-
// Update the internal sandbox metadata with the new timeout value
|
|
462
|
-
this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
|
|
452
|
+
return this.withResume(() => this.session.extendTimeout(duration, opts), opts?.signal);
|
|
463
453
|
}
|
|
464
454
|
/**
|
|
465
455
|
* Create a snapshot from this currently running sandbox. New sandboxes can
|
|
@@ -473,15 +463,70 @@ class Sandbox {
|
|
|
473
463
|
* @returns A promise that resolves to the Snapshot instance
|
|
474
464
|
*/
|
|
475
465
|
async snapshot(opts) {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
466
|
+
return this.withResume(() => this.session.snapshot(opts), opts?.signal);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Update the named sandbox configuration. Only provided fields are modified.
|
|
470
|
+
*
|
|
471
|
+
* @param params - Fields to update.
|
|
472
|
+
* @param opts - Optional abort signal.
|
|
473
|
+
*/
|
|
474
|
+
async update(params, opts) {
|
|
475
|
+
const response = await this.client.updateNamedSandbox({
|
|
476
|
+
name: this.namedSandbox.name,
|
|
477
|
+
projectId: this.projectId,
|
|
478
|
+
resources: params.resources,
|
|
479
|
+
runtime: params.runtime,
|
|
480
|
+
timeout: params.timeout,
|
|
481
|
+
networkPolicy: params.networkPolicy,
|
|
479
482
|
signal: opts?.signal,
|
|
480
483
|
});
|
|
481
|
-
this.
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
484
|
+
this.namedSandbox = response.json.namedSandbox;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Delete this named sandbox.
|
|
488
|
+
*
|
|
489
|
+
* After deletion the instance becomes inert — all further API calls will
|
|
490
|
+
* throw immediately.
|
|
491
|
+
*/
|
|
492
|
+
async delete(opts) {
|
|
493
|
+
await this.client.deleteNamedSandbox({
|
|
494
|
+
name: this.namedSandbox.name,
|
|
495
|
+
projectId: this.projectId,
|
|
496
|
+
preserveSnapshots: opts?.preserveSnapshots,
|
|
497
|
+
signal: opts?.signal,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* List sessions (VMs) that have been created for this named sandbox.
|
|
502
|
+
*
|
|
503
|
+
* @param params - Optional pagination parameters.
|
|
504
|
+
* @returns The list of sessions and pagination metadata.
|
|
505
|
+
*/
|
|
506
|
+
async listSessions(params) {
|
|
507
|
+
return this.client.listSandboxes({
|
|
508
|
+
projectId: this.projectId,
|
|
509
|
+
name: this.namedSandbox.name,
|
|
510
|
+
limit: params?.limit,
|
|
511
|
+
since: params?.since,
|
|
512
|
+
until: params?.until,
|
|
513
|
+
signal: params?.signal,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* List snapshots that belong to this named sandbox.
|
|
518
|
+
*
|
|
519
|
+
* @param params - Optional pagination parameters.
|
|
520
|
+
* @returns The list of snapshots and pagination metadata.
|
|
521
|
+
*/
|
|
522
|
+
async listSnapshots(params) {
|
|
523
|
+
return this.client.listSnapshots({
|
|
524
|
+
projectId: this.projectId,
|
|
525
|
+
name: this.namedSandbox.name,
|
|
526
|
+
limit: params?.limit,
|
|
527
|
+
since: params?.since,
|
|
528
|
+
until: params?.until,
|
|
529
|
+
signal: params?.signal,
|
|
485
530
|
});
|
|
486
531
|
}
|
|
487
532
|
}
|