@vercel/sandbox 1.7.1 → 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 +320 -4
- package/dist/api-client/api-client.js +69 -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 +290 -126
- package/dist/sandbox.js +263 -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 ?? [],
|
|
@@ -115,17 +194,22 @@ class Sandbox {
|
|
|
115
194
|
resources: params?.resources,
|
|
116
195
|
runtime: params && "runtime" in params ? params?.runtime : undefined,
|
|
117
196
|
networkPolicy: params?.networkPolicy,
|
|
197
|
+
env: params?.env,
|
|
118
198
|
signal: params?.signal,
|
|
199
|
+
name: params?.name,
|
|
200
|
+
snapshotOnShutdown: params?.snapshotOnShutdown,
|
|
119
201
|
...privateParams,
|
|
120
202
|
});
|
|
121
203
|
return new DisposableSandbox({
|
|
122
204
|
client,
|
|
123
|
-
|
|
124
|
-
|
|
205
|
+
session: response.json.sandbox,
|
|
206
|
+
namedSandbox: response.json.namedSandbox,
|
|
207
|
+
routes: response.json.routes,
|
|
208
|
+
projectId: credentials.projectId,
|
|
125
209
|
});
|
|
126
210
|
}
|
|
127
211
|
/**
|
|
128
|
-
* Retrieve an existing sandbox.
|
|
212
|
+
* Retrieve an existing sandbox and resume its session.
|
|
129
213
|
*
|
|
130
214
|
* @param params - Get parameters and optional credentials.
|
|
131
215
|
* @returns A promise resolving to the {@link Sandbox}.
|
|
@@ -137,47 +221,93 @@ class Sandbox {
|
|
|
137
221
|
token: credentials.token,
|
|
138
222
|
fetch: params.fetch,
|
|
139
223
|
});
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
224
|
+
const response = await client.getNamedSandbox({
|
|
225
|
+
name: params.name,
|
|
226
|
+
projectId: credentials.projectId,
|
|
227
|
+
resume: params.resume,
|
|
143
228
|
signal: params.signal,
|
|
144
|
-
...privateParams,
|
|
145
229
|
});
|
|
146
230
|
return new Sandbox({
|
|
147
231
|
client,
|
|
148
|
-
|
|
149
|
-
|
|
232
|
+
session: response.json.sandbox,
|
|
233
|
+
namedSandbox: response.json.namedSandbox,
|
|
234
|
+
routes: response.json.routes,
|
|
235
|
+
projectId: credentials.projectId,
|
|
150
236
|
});
|
|
151
237
|
}
|
|
152
|
-
constructor({ client, routes,
|
|
238
|
+
constructor({ client, routes, session, namedSandbox, projectId, }) {
|
|
153
239
|
this.client = client;
|
|
154
|
-
this.
|
|
155
|
-
this.
|
|
240
|
+
this.session = new session_1.Session({ client, routes, session });
|
|
241
|
+
this.namedSandbox = namedSandbox;
|
|
242
|
+
this.projectId = projectId;
|
|
156
243
|
}
|
|
157
244
|
/**
|
|
158
|
-
* Get
|
|
245
|
+
* Get the current session (the running VM) for this sandbox.
|
|
159
246
|
*
|
|
160
|
-
* @
|
|
161
|
-
* @param opts - Optional parameters.
|
|
162
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
163
|
-
* @returns A {@link Command} instance representing the command
|
|
247
|
+
* @returns The {@link Session} instance.
|
|
164
248
|
*/
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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,
|
|
170
261
|
});
|
|
171
|
-
|
|
262
|
+
this.session = new session_1.Session({
|
|
172
263
|
client: this.client,
|
|
173
|
-
|
|
174
|
-
|
|
264
|
+
routes: response.json.routes,
|
|
265
|
+
session: response.json.sandbox,
|
|
175
266
|
});
|
|
176
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
|
+
}
|
|
177
308
|
async runCommand(commandOrParams, args, opts) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
: this._runCommand(commandOrParams);
|
|
309
|
+
const signal = typeof commandOrParams === "string" ? opts?.signal : commandOrParams.signal;
|
|
310
|
+
return this.withResume(() => this.session.runCommand(commandOrParams, args, opts), signal);
|
|
181
311
|
}
|
|
182
312
|
/**
|
|
183
313
|
* Internal helper to start a command in the sandbox.
|
|
@@ -186,71 +316,8 @@ class Sandbox {
|
|
|
186
316
|
* @returns A {@link Command} or {@link CommandFinished}, depending on `detached`.
|
|
187
317
|
* @internal
|
|
188
318
|
*/
|
|
189
|
-
async
|
|
190
|
-
|
|
191
|
-
const getLogs = (command) => {
|
|
192
|
-
if (params.stdout || params.stderr) {
|
|
193
|
-
(async () => {
|
|
194
|
-
try {
|
|
195
|
-
for await (const log of command.logs({ signal: params.signal })) {
|
|
196
|
-
if (log.stream === "stdout") {
|
|
197
|
-
params.stdout?.write(log.data);
|
|
198
|
-
}
|
|
199
|
-
else if (log.stream === "stderr") {
|
|
200
|
-
params.stderr?.write(log.data);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
catch (err) {
|
|
205
|
-
if (params.signal?.aborted) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
throw err;
|
|
209
|
-
}
|
|
210
|
-
})();
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
if (wait) {
|
|
214
|
-
const commandStream = await this.client.runCommand({
|
|
215
|
-
sandboxId: this.sandbox.id,
|
|
216
|
-
command: params.cmd,
|
|
217
|
-
args: params.args ?? [],
|
|
218
|
-
cwd: params.cwd,
|
|
219
|
-
env: params.env ?? {},
|
|
220
|
-
sudo: params.sudo ?? false,
|
|
221
|
-
wait: true,
|
|
222
|
-
signal: params.signal,
|
|
223
|
-
});
|
|
224
|
-
const command = new command_1.Command({
|
|
225
|
-
client: this.client,
|
|
226
|
-
sandboxId: this.sandbox.id,
|
|
227
|
-
cmd: commandStream.command,
|
|
228
|
-
});
|
|
229
|
-
getLogs(command);
|
|
230
|
-
const finished = await commandStream.finished;
|
|
231
|
-
return new command_1.CommandFinished({
|
|
232
|
-
client: this.client,
|
|
233
|
-
sandboxId: this.sandbox.id,
|
|
234
|
-
cmd: finished,
|
|
235
|
-
exitCode: finished.exitCode ?? 0,
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
const commandResponse = await this.client.runCommand({
|
|
239
|
-
sandboxId: this.sandbox.id,
|
|
240
|
-
command: params.cmd,
|
|
241
|
-
args: params.args ?? [],
|
|
242
|
-
cwd: params.cwd,
|
|
243
|
-
env: params.env ?? {},
|
|
244
|
-
sudo: params.sudo ?? false,
|
|
245
|
-
signal: params.signal,
|
|
246
|
-
});
|
|
247
|
-
const command = new command_1.Command({
|
|
248
|
-
client: this.client,
|
|
249
|
-
sandboxId: this.sandbox.id,
|
|
250
|
-
cmd: commandResponse.json.command,
|
|
251
|
-
});
|
|
252
|
-
getLogs(command);
|
|
253
|
-
return command;
|
|
319
|
+
async getCommand(cmdId, opts) {
|
|
320
|
+
return this.withResume(() => this.session.getCommand(cmdId, opts), opts?.signal);
|
|
254
321
|
}
|
|
255
322
|
/**
|
|
256
323
|
* Create a directory in the filesystem of this sandbox.
|
|
@@ -260,11 +327,7 @@ class Sandbox {
|
|
|
260
327
|
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
261
328
|
*/
|
|
262
329
|
async mkDir(path, opts) {
|
|
263
|
-
|
|
264
|
-
sandboxId: this.sandbox.id,
|
|
265
|
-
path: path,
|
|
266
|
-
signal: opts?.signal,
|
|
267
|
-
});
|
|
330
|
+
return this.withResume(() => this.session.mkDir(path, opts), opts?.signal);
|
|
268
331
|
}
|
|
269
332
|
/**
|
|
270
333
|
* Read a file from the filesystem of this sandbox as a stream.
|
|
@@ -275,12 +338,7 @@ class Sandbox {
|
|
|
275
338
|
* @returns A promise that resolves to a ReadableStream containing the file contents, or null if file not found
|
|
276
339
|
*/
|
|
277
340
|
async readFile(file, opts) {
|
|
278
|
-
return this.
|
|
279
|
-
sandboxId: this.sandbox.id,
|
|
280
|
-
path: file.path,
|
|
281
|
-
cwd: file.cwd,
|
|
282
|
-
signal: opts?.signal,
|
|
283
|
-
});
|
|
341
|
+
return this.withResume(() => this.session.readFile(file, opts), opts?.signal);
|
|
284
342
|
}
|
|
285
343
|
/**
|
|
286
344
|
* Read a file from the filesystem of this sandbox as a Buffer.
|
|
@@ -291,16 +349,7 @@ class Sandbox {
|
|
|
291
349
|
* @returns A promise that resolves to the file contents as a Buffer, or null if file not found
|
|
292
350
|
*/
|
|
293
351
|
async readFileToBuffer(file, opts) {
|
|
294
|
-
|
|
295
|
-
sandboxId: this.sandbox.id,
|
|
296
|
-
path: file.path,
|
|
297
|
-
cwd: file.cwd,
|
|
298
|
-
signal: opts?.signal,
|
|
299
|
-
});
|
|
300
|
-
if (stream === null) {
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
return (0, consume_readable_1.consumeReadable)(stream);
|
|
352
|
+
return this.withResume(() => this.session.readFileToBuffer(file, opts), opts?.signal);
|
|
304
353
|
}
|
|
305
354
|
/**
|
|
306
355
|
* Download a file from the sandbox to the local filesystem.
|
|
@@ -313,34 +362,7 @@ class Sandbox {
|
|
|
313
362
|
* @returns The absolute path to the written file, or null if the source file was not found
|
|
314
363
|
*/
|
|
315
364
|
async downloadFile(src, dst, opts) {
|
|
316
|
-
|
|
317
|
-
throw new Error("downloadFile: source path is required");
|
|
318
|
-
}
|
|
319
|
-
if (!dst?.path) {
|
|
320
|
-
throw new Error("downloadFile: destination path is required");
|
|
321
|
-
}
|
|
322
|
-
const stream = await this.client.readFile({
|
|
323
|
-
sandboxId: this.sandbox.id,
|
|
324
|
-
path: src.path,
|
|
325
|
-
cwd: src.cwd,
|
|
326
|
-
signal: opts?.signal,
|
|
327
|
-
});
|
|
328
|
-
if (stream === null) {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
try {
|
|
332
|
-
const dstPath = (0, path_1.resolve)(dst.cwd ?? "", dst.path);
|
|
333
|
-
if (opts?.mkdirRecursive) {
|
|
334
|
-
await (0, promises_2.mkdir)((0, path_1.dirname)(dstPath), { recursive: true });
|
|
335
|
-
}
|
|
336
|
-
await (0, promises_1.pipeline)(stream, (0, fs_1.createWriteStream)(dstPath), {
|
|
337
|
-
signal: opts?.signal,
|
|
338
|
-
});
|
|
339
|
-
return dstPath;
|
|
340
|
-
}
|
|
341
|
-
finally {
|
|
342
|
-
stream.destroy();
|
|
343
|
-
}
|
|
365
|
+
return this.withResume(() => this.session.downloadFile(src, dst, opts), opts?.signal);
|
|
344
366
|
}
|
|
345
367
|
/**
|
|
346
368
|
* Write files to the filesystem of this sandbox.
|
|
@@ -353,13 +375,7 @@ class Sandbox {
|
|
|
353
375
|
* @returns A promise that resolves when the files are written
|
|
354
376
|
*/
|
|
355
377
|
async writeFiles(files, opts) {
|
|
356
|
-
return this.
|
|
357
|
-
sandboxId: this.sandbox.id,
|
|
358
|
-
cwd: this.sandbox.cwd,
|
|
359
|
-
extractDir: "/",
|
|
360
|
-
files: files,
|
|
361
|
-
signal: opts?.signal,
|
|
362
|
-
});
|
|
378
|
+
return this.withResume(() => this.session.writeFiles(files, opts), opts?.signal);
|
|
363
379
|
}
|
|
364
380
|
/**
|
|
365
381
|
* Get the public domain of a port of this sandbox.
|
|
@@ -369,13 +385,7 @@ class Sandbox {
|
|
|
369
385
|
* @throws If the port has no associated route
|
|
370
386
|
*/
|
|
371
387
|
domain(p) {
|
|
372
|
-
|
|
373
|
-
if (route) {
|
|
374
|
-
return `https://${route.subdomain}.vercel.run`;
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
throw new Error(`No route for port ${p}`);
|
|
378
|
-
}
|
|
388
|
+
return this.session.domain(p);
|
|
379
389
|
}
|
|
380
390
|
/**
|
|
381
391
|
* Stop the sandbox.
|
|
@@ -386,13 +396,7 @@ class Sandbox {
|
|
|
386
396
|
* @returns The sandbox metadata at the time the stop was acknowledged, or after fully stopped if `blocking` is true.
|
|
387
397
|
*/
|
|
388
398
|
async stop(opts) {
|
|
389
|
-
|
|
390
|
-
sandboxId: this.sandbox.id,
|
|
391
|
-
signal: opts?.signal,
|
|
392
|
-
blocking: opts?.blocking,
|
|
393
|
-
});
|
|
394
|
-
this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
|
|
395
|
-
return this.sandbox;
|
|
399
|
+
return this.session.stop(opts);
|
|
396
400
|
}
|
|
397
401
|
/**
|
|
398
402
|
* Update the network policy for this sandbox.
|
|
@@ -426,14 +430,7 @@ class Sandbox {
|
|
|
426
430
|
* await sandbox.updateNetworkPolicy("deny-all");
|
|
427
431
|
*/
|
|
428
432
|
async updateNetworkPolicy(networkPolicy, opts) {
|
|
429
|
-
|
|
430
|
-
sandboxId: this.sandbox.id,
|
|
431
|
-
networkPolicy: networkPolicy,
|
|
432
|
-
signal: opts?.signal,
|
|
433
|
-
});
|
|
434
|
-
// Update the internal sandbox metadata with the new timeout value
|
|
435
|
-
this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
|
|
436
|
-
return this.sandbox.networkPolicy;
|
|
433
|
+
return this.withResume(() => this.session.updateNetworkPolicy(networkPolicy, opts), opts?.signal);
|
|
437
434
|
}
|
|
438
435
|
/**
|
|
439
436
|
* Extend the timeout of the sandbox by the specified duration.
|
|
@@ -452,13 +449,7 @@ class Sandbox {
|
|
|
452
449
|
* await sandbox.extendTimeout(ms('5m'));
|
|
453
450
|
*/
|
|
454
451
|
async extendTimeout(duration, opts) {
|
|
455
|
-
|
|
456
|
-
sandboxId: this.sandbox.id,
|
|
457
|
-
duration,
|
|
458
|
-
signal: opts?.signal,
|
|
459
|
-
});
|
|
460
|
-
// Update the internal sandbox metadata with the new timeout value
|
|
461
|
-
this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
|
|
452
|
+
return this.withResume(() => this.session.extendTimeout(duration, opts), opts?.signal);
|
|
462
453
|
}
|
|
463
454
|
/**
|
|
464
455
|
* Create a snapshot from this currently running sandbox. New sandboxes can
|
|
@@ -472,15 +463,70 @@ class Sandbox {
|
|
|
472
463
|
* @returns A promise that resolves to the Snapshot instance
|
|
473
464
|
*/
|
|
474
465
|
async snapshot(opts) {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
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,
|
|
478
482
|
signal: opts?.signal,
|
|
479
483
|
});
|
|
480
|
-
this.
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
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,
|
|
484
530
|
});
|
|
485
531
|
}
|
|
486
532
|
}
|