@vercel/sandbox 1.1.9 → 1.2.1
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 +18 -13
- package/dist/api-client/api-client.js +46 -0
- package/dist/api-client/api-client.js.map +1 -1
- package/dist/api-client/validators.d.ts +1 -0
- package/dist/api-client/validators.js.map +1 -1
- package/dist/sandbox.d.ts +39 -5
- package/dist/sandbox.js +111 -23
- package/dist/sandbox.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -1
- package/.turbo/turbo-build.log +0 -4
- package/.turbo/turbo-test.log +0 -24
- package/.turbo/turbo-typecheck.log +0 -4
- package/CHANGELOG.md +0 -267
- package/__mocks__/picocolors.ts +0 -13
- package/scripts/inject-version.ts +0 -11
- package/src/api-client/api-client.test.ts +0 -176
- package/src/api-client/api-client.ts +0 -520
- package/src/api-client/api-error.ts +0 -46
- package/src/api-client/base-client.ts +0 -171
- package/src/api-client/file-writer.ts +0 -90
- package/src/api-client/index.ts +0 -2
- package/src/api-client/validators.ts +0 -144
- package/src/api-client/with-retry.ts +0 -131
- package/src/auth/api.ts +0 -31
- package/src/auth/error.ts +0 -8
- package/src/auth/file.ts +0 -69
- package/src/auth/index.ts +0 -9
- package/src/auth/infer-scope.test.ts +0 -178
- package/src/auth/linked-project.test.ts +0 -86
- package/src/auth/linked-project.ts +0 -40
- package/src/auth/oauth.ts +0 -333
- package/src/auth/poll-for-token.ts +0 -89
- package/src/auth/project.ts +0 -92
- package/src/auth/zod.ts +0 -16
- package/src/command.test.ts +0 -103
- package/src/command.ts +0 -287
- package/src/constants.ts +0 -1
- package/src/index.ts +0 -4
- package/src/sandbox.test.ts +0 -93
- package/src/sandbox.ts +0 -572
- package/src/snapshot.ts +0 -110
- package/src/utils/array.ts +0 -15
- package/src/utils/consume-readable.ts +0 -12
- package/src/utils/decode-base64-url.ts +0 -14
- package/src/utils/dev-credentials.test.ts +0 -217
- package/src/utils/dev-credentials.ts +0 -196
- package/src/utils/get-credentials.test.ts +0 -20
- package/src/utils/get-credentials.ts +0 -183
- package/src/utils/jwt-expiry.test.ts +0 -125
- package/src/utils/jwt-expiry.ts +0 -105
- package/src/utils/log.ts +0 -20
- package/src/utils/normalizePath.test.ts +0 -114
- package/src/utils/normalizePath.ts +0 -33
- package/src/utils/resolveSignal.ts +0 -24
- package/src/utils/types.test.js +0 -7
- package/src/utils/types.ts +0 -23
- package/src/version.ts +0 -2
- package/test-utils/mock-response.ts +0 -12
- package/tsconfig.json +0 -16
- package/turbo.json +0 -9
- package/typedoc.json +0 -13
- package/vercel.json +0 -9
- package/vitest.config.ts +0 -9
- package/vitest.setup.ts +0 -4
package/src/sandbox.ts
DELETED
|
@@ -1,572 +0,0 @@
|
|
|
1
|
-
import type { SandboxMetaData, SandboxRouteData } from "./api-client";
|
|
2
|
-
import type { Writable } from "stream";
|
|
3
|
-
import { APIClient } from "./api-client";
|
|
4
|
-
import { Command, type CommandFinished } from "./command";
|
|
5
|
-
import { type Credentials, getCredentials } from "./utils/get-credentials";
|
|
6
|
-
import { getPrivateParams, WithPrivate } from "./utils/types";
|
|
7
|
-
import { WithFetchOptions } from "./api-client/api-client";
|
|
8
|
-
import { RUNTIMES } from "./constants";
|
|
9
|
-
import { Snapshot } from "./snapshot";
|
|
10
|
-
|
|
11
|
-
/** @inline */
|
|
12
|
-
export interface BaseCreateSandboxParams {
|
|
13
|
-
/**
|
|
14
|
-
* The source of the sandbox.
|
|
15
|
-
*
|
|
16
|
-
* Omit this parameter start a sandbox without a source.
|
|
17
|
-
*
|
|
18
|
-
* For git sources:
|
|
19
|
-
* - `depth`: Creates shallow clones with limited commit history (minimum: 1)
|
|
20
|
-
* - `revision`: Clones and checks out a specific commit, branch, or tag
|
|
21
|
-
*/
|
|
22
|
-
source?:
|
|
23
|
-
| {
|
|
24
|
-
type: "git";
|
|
25
|
-
url: string;
|
|
26
|
-
depth?: number;
|
|
27
|
-
revision?: string;
|
|
28
|
-
}
|
|
29
|
-
| {
|
|
30
|
-
type: "git";
|
|
31
|
-
url: string;
|
|
32
|
-
username: string;
|
|
33
|
-
password: string;
|
|
34
|
-
depth?: number;
|
|
35
|
-
revision?: string;
|
|
36
|
-
}
|
|
37
|
-
| { type: "tarball"; url: string };
|
|
38
|
-
/**
|
|
39
|
-
* Array of port numbers to expose from the sandbox. Sandboxes can
|
|
40
|
-
* expose up to 4 ports.
|
|
41
|
-
*/
|
|
42
|
-
ports?: number[];
|
|
43
|
-
/**
|
|
44
|
-
* Timeout in milliseconds before the sandbox auto-terminates.
|
|
45
|
-
*/
|
|
46
|
-
timeout?: number;
|
|
47
|
-
/**
|
|
48
|
-
* Resources to allocate to the sandbox.
|
|
49
|
-
*
|
|
50
|
-
* Your sandbox will get the amount of vCPUs you specify here and
|
|
51
|
-
* 2048 MB of memory per vCPU.
|
|
52
|
-
*/
|
|
53
|
-
resources?: { vcpus: number };
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* The runtime of the sandbox, currently only `node24`, `node22` and `python3.13` are supported.
|
|
57
|
-
* If not specified, the default runtime `node24` will be used.
|
|
58
|
-
*/
|
|
59
|
-
runtime?: RUNTIMES | (string & {});
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* An AbortSignal to cancel sandbox creation.
|
|
63
|
-
*/
|
|
64
|
-
signal?: AbortSignal;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export type CreateSandboxParams =
|
|
68
|
-
| BaseCreateSandboxParams
|
|
69
|
-
| (Omit<BaseCreateSandboxParams, "runtime" | "source"> & {
|
|
70
|
-
source: { type: "snapshot"; snapshotId: string };
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
/** @inline */
|
|
74
|
-
interface GetSandboxParams {
|
|
75
|
-
/**
|
|
76
|
-
* Unique identifier of the sandbox.
|
|
77
|
-
*/
|
|
78
|
-
sandboxId: string;
|
|
79
|
-
/**
|
|
80
|
-
* An AbortSignal to cancel the operation.
|
|
81
|
-
*/
|
|
82
|
-
signal?: AbortSignal;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** @inline */
|
|
86
|
-
interface RunCommandParams {
|
|
87
|
-
/**
|
|
88
|
-
* The command to execute
|
|
89
|
-
*/
|
|
90
|
-
cmd: string;
|
|
91
|
-
/**
|
|
92
|
-
* Arguments to pass to the command
|
|
93
|
-
*/
|
|
94
|
-
args?: string[];
|
|
95
|
-
/**
|
|
96
|
-
* Working directory to execute the command in
|
|
97
|
-
*/
|
|
98
|
-
cwd?: string;
|
|
99
|
-
/**
|
|
100
|
-
* Environment variables to set for this command
|
|
101
|
-
*/
|
|
102
|
-
env?: Record<string, string>;
|
|
103
|
-
/**
|
|
104
|
-
* If true, execute this command with root privileges. Defaults to false.
|
|
105
|
-
*/
|
|
106
|
-
sudo?: boolean;
|
|
107
|
-
/**
|
|
108
|
-
* If true, the command will return without waiting for `exitCode`
|
|
109
|
-
*/
|
|
110
|
-
detached?: boolean;
|
|
111
|
-
/**
|
|
112
|
-
* A `Writable` stream where `stdout` from the command will be piped
|
|
113
|
-
*/
|
|
114
|
-
stdout?: Writable;
|
|
115
|
-
/**
|
|
116
|
-
* A `Writable` stream where `stderr` from the command will be piped
|
|
117
|
-
*/
|
|
118
|
-
stderr?: Writable;
|
|
119
|
-
/**
|
|
120
|
-
* An AbortSignal to cancel the command execution
|
|
121
|
-
*/
|
|
122
|
-
signal?: AbortSignal;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* A Sandbox is an isolated Linux MicroVM to run commands in.
|
|
127
|
-
*
|
|
128
|
-
* Use {@link Sandbox.create} or {@link Sandbox.get} to construct.
|
|
129
|
-
* @hideconstructor
|
|
130
|
-
*/
|
|
131
|
-
export class Sandbox {
|
|
132
|
-
private readonly client: APIClient;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Routes from ports to subdomains.
|
|
136
|
-
/* @hidden
|
|
137
|
-
*/
|
|
138
|
-
public readonly routes: SandboxRouteData[];
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Unique ID of this sandbox.
|
|
142
|
-
*/
|
|
143
|
-
public get sandboxId(): string {
|
|
144
|
-
return this.sandbox.id;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
public get interactivePort(): number | undefined {
|
|
148
|
-
return this.sandbox.interactivePort ?? undefined;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* The status of the sandbox.
|
|
153
|
-
*/
|
|
154
|
-
public get status(): SandboxMetaData["status"] {
|
|
155
|
-
return this.sandbox.status;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* The creation date of the sandbox.
|
|
160
|
-
*/
|
|
161
|
-
public get createdAt(): Date {
|
|
162
|
-
return new Date(this.sandbox.createdAt);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* The timeout of the sandbox in milliseconds.
|
|
167
|
-
*/
|
|
168
|
-
public get timeout(): number {
|
|
169
|
-
return this.sandbox.timeout;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* If the sandbox was created from a snapshot, the ID of that snapshot.
|
|
174
|
-
*/
|
|
175
|
-
public get sourceSnapshotId(): string | undefined {
|
|
176
|
-
return this.sandbox.sourceSnapshotId;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Internal metadata about this sandbox.
|
|
181
|
-
*/
|
|
182
|
-
private sandbox: SandboxMetaData;
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Allow to get a list of sandboxes for a team narrowed to the given params.
|
|
186
|
-
* It returns both the sandboxes and the pagination metadata to allow getting
|
|
187
|
-
* the next page of results.
|
|
188
|
-
*/
|
|
189
|
-
static async list(
|
|
190
|
-
params?: Partial<Parameters<APIClient["listSandboxes"]>[0]> &
|
|
191
|
-
Partial<Credentials> &
|
|
192
|
-
WithFetchOptions,
|
|
193
|
-
) {
|
|
194
|
-
const credentials = await getCredentials(params);
|
|
195
|
-
const client = new APIClient({
|
|
196
|
-
teamId: credentials.teamId,
|
|
197
|
-
token: credentials.token,
|
|
198
|
-
fetch: params?.fetch,
|
|
199
|
-
});
|
|
200
|
-
return client.listSandboxes({
|
|
201
|
-
...credentials,
|
|
202
|
-
...params,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Create a new sandbox.
|
|
208
|
-
*
|
|
209
|
-
* @param params - Creation parameters and optional credentials.
|
|
210
|
-
* @returns A promise resolving to the created {@link Sandbox}.
|
|
211
|
-
* @example
|
|
212
|
-
* <caption>Create a sandbox and drop it in the end of the block</caption>
|
|
213
|
-
* async function fn() {
|
|
214
|
-
* await using const sandbox = await Sandbox.create();
|
|
215
|
-
* // Sandbox automatically stopped at the end of the lexical scope
|
|
216
|
-
* }
|
|
217
|
-
*/
|
|
218
|
-
static async create(
|
|
219
|
-
params?: WithPrivate<
|
|
220
|
-
CreateSandboxParams | (CreateSandboxParams & Credentials)
|
|
221
|
-
> &
|
|
222
|
-
WithFetchOptions,
|
|
223
|
-
): Promise<Sandbox & AsyncDisposable> {
|
|
224
|
-
const credentials = await getCredentials(params);
|
|
225
|
-
const client = new APIClient({
|
|
226
|
-
teamId: credentials.teamId,
|
|
227
|
-
token: credentials.token,
|
|
228
|
-
fetch: params?.fetch,
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
const privateParams = getPrivateParams(params);
|
|
232
|
-
const sandbox = await client.createSandbox({
|
|
233
|
-
source: params?.source,
|
|
234
|
-
projectId: credentials.projectId,
|
|
235
|
-
ports: params?.ports ?? [],
|
|
236
|
-
timeout: params?.timeout,
|
|
237
|
-
resources: params?.resources,
|
|
238
|
-
runtime: params && "runtime" in params ? params?.runtime : undefined,
|
|
239
|
-
signal: params?.signal,
|
|
240
|
-
...privateParams,
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
return new DisposableSandbox({
|
|
244
|
-
client,
|
|
245
|
-
sandbox: sandbox.json.sandbox,
|
|
246
|
-
routes: sandbox.json.routes,
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Retrieve an existing sandbox.
|
|
252
|
-
*
|
|
253
|
-
* @param params - Get parameters and optional credentials.
|
|
254
|
-
* @returns A promise resolving to the {@link Sandbox}.
|
|
255
|
-
*/
|
|
256
|
-
static async get(
|
|
257
|
-
params: WithPrivate<GetSandboxParams | (GetSandboxParams & Credentials)> &
|
|
258
|
-
WithFetchOptions,
|
|
259
|
-
): Promise<Sandbox> {
|
|
260
|
-
const credentials = await getCredentials(params);
|
|
261
|
-
const client = new APIClient({
|
|
262
|
-
teamId: credentials.teamId,
|
|
263
|
-
token: credentials.token,
|
|
264
|
-
fetch: params.fetch,
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const privateParams = getPrivateParams(params);
|
|
268
|
-
const sandbox = await client.getSandbox({
|
|
269
|
-
sandboxId: params.sandboxId,
|
|
270
|
-
signal: params.signal,
|
|
271
|
-
...privateParams,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
return new Sandbox({
|
|
275
|
-
client,
|
|
276
|
-
sandbox: sandbox.json.sandbox,
|
|
277
|
-
routes: sandbox.json.routes,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Create a new Sandbox instance.
|
|
283
|
-
*
|
|
284
|
-
* @param client - API client used to communicate with the backend
|
|
285
|
-
* @param routes - Port-to-subdomain mappings for exposed ports
|
|
286
|
-
* @param sandboxId - Unique identifier for the sandbox
|
|
287
|
-
*/
|
|
288
|
-
constructor({
|
|
289
|
-
client,
|
|
290
|
-
routes,
|
|
291
|
-
sandbox,
|
|
292
|
-
}: {
|
|
293
|
-
client: APIClient;
|
|
294
|
-
routes: SandboxRouteData[];
|
|
295
|
-
sandbox: SandboxMetaData;
|
|
296
|
-
}) {
|
|
297
|
-
this.client = client;
|
|
298
|
-
this.routes = routes;
|
|
299
|
-
this.sandbox = sandbox;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Get a previously run command by its ID.
|
|
304
|
-
*
|
|
305
|
-
* @param cmdId - ID of the command to retrieve
|
|
306
|
-
* @param opts - Optional parameters.
|
|
307
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
308
|
-
* @returns A {@link Command} instance representing the command
|
|
309
|
-
*/
|
|
310
|
-
async getCommand(
|
|
311
|
-
cmdId: string,
|
|
312
|
-
opts?: { signal?: AbortSignal },
|
|
313
|
-
): Promise<Command> {
|
|
314
|
-
const command = await this.client.getCommand({
|
|
315
|
-
sandboxId: this.sandbox.id,
|
|
316
|
-
cmdId,
|
|
317
|
-
signal: opts?.signal,
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
return new Command({
|
|
321
|
-
client: this.client,
|
|
322
|
-
sandboxId: this.sandbox.id,
|
|
323
|
-
cmd: command.json.command,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Start executing a command in this sandbox.
|
|
329
|
-
*
|
|
330
|
-
* @param command - The command to execute.
|
|
331
|
-
* @param args - Arguments to pass to the command.
|
|
332
|
-
* @param opts - Optional parameters.
|
|
333
|
-
* @param opts.signal - An AbortSignal to cancel the command execution.
|
|
334
|
-
* @returns A {@link CommandFinished} result once execution is done.
|
|
335
|
-
*/
|
|
336
|
-
async runCommand(
|
|
337
|
-
command: string,
|
|
338
|
-
args?: string[],
|
|
339
|
-
opts?: { signal?: AbortSignal },
|
|
340
|
-
): Promise<CommandFinished>;
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Start executing a command in detached mode.
|
|
344
|
-
*
|
|
345
|
-
* @param params - The command parameters.
|
|
346
|
-
* @returns A {@link Command} instance for the running command.
|
|
347
|
-
*/
|
|
348
|
-
async runCommand(
|
|
349
|
-
params: RunCommandParams & { detached: true },
|
|
350
|
-
): Promise<Command>;
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Start executing a command in this sandbox.
|
|
354
|
-
*
|
|
355
|
-
* @param params - The command parameters.
|
|
356
|
-
* @returns A {@link CommandFinished} result once execution is done.
|
|
357
|
-
*/
|
|
358
|
-
async runCommand(params: RunCommandParams): Promise<CommandFinished>;
|
|
359
|
-
|
|
360
|
-
async runCommand(
|
|
361
|
-
commandOrParams: string | RunCommandParams,
|
|
362
|
-
args?: string[],
|
|
363
|
-
opts?: { signal?: AbortSignal },
|
|
364
|
-
): Promise<Command | CommandFinished> {
|
|
365
|
-
return typeof commandOrParams === "string"
|
|
366
|
-
? this._runCommand({ cmd: commandOrParams, args, signal: opts?.signal })
|
|
367
|
-
: this._runCommand(commandOrParams);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Internal helper to start a command in the sandbox.
|
|
372
|
-
*
|
|
373
|
-
* @param params - Command execution parameters.
|
|
374
|
-
* @returns A {@link Command} or {@link CommandFinished}, depending on `detached`.
|
|
375
|
-
* @internal
|
|
376
|
-
*/
|
|
377
|
-
async _runCommand(params: RunCommandParams) {
|
|
378
|
-
const commandResponse = await this.client.runCommand({
|
|
379
|
-
sandboxId: this.sandbox.id,
|
|
380
|
-
command: params.cmd,
|
|
381
|
-
args: params.args ?? [],
|
|
382
|
-
cwd: params.cwd,
|
|
383
|
-
env: params.env ?? {},
|
|
384
|
-
sudo: params.sudo ?? false,
|
|
385
|
-
signal: params.signal,
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
const command = new Command({
|
|
389
|
-
client: this.client,
|
|
390
|
-
sandboxId: this.sandbox.id,
|
|
391
|
-
cmd: commandResponse.json.command,
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
if (params.stdout || params.stderr) {
|
|
395
|
-
(async () => {
|
|
396
|
-
try {
|
|
397
|
-
for await (const log of command.logs({ signal: params.signal })) {
|
|
398
|
-
if (log.stream === "stdout") {
|
|
399
|
-
params.stdout?.write(log.data);
|
|
400
|
-
} else if (log.stream === "stderr") {
|
|
401
|
-
params.stderr?.write(log.data);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
} catch (err) {
|
|
405
|
-
if (params.signal?.aborted) {
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
throw err;
|
|
409
|
-
}
|
|
410
|
-
})();
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return params.detached ? command : command.wait({ signal: params.signal });
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Create a directory in the filesystem of this sandbox.
|
|
418
|
-
*
|
|
419
|
-
* @param path - Path of the directory to create
|
|
420
|
-
* @param opts - Optional parameters.
|
|
421
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
422
|
-
*/
|
|
423
|
-
async mkDir(path: string, opts?: { signal?: AbortSignal }): Promise<void> {
|
|
424
|
-
await this.client.mkDir({
|
|
425
|
-
sandboxId: this.sandbox.id,
|
|
426
|
-
path: path,
|
|
427
|
-
signal: opts?.signal,
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Read a file from the filesystem of this sandbox.
|
|
433
|
-
*
|
|
434
|
-
* @param file - File to read, with path and optional cwd
|
|
435
|
-
* @param opts - Optional parameters.
|
|
436
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
437
|
-
* @returns A promise that resolves to a ReadableStream containing the file contents
|
|
438
|
-
*/
|
|
439
|
-
async readFile(
|
|
440
|
-
file: { path: string; cwd?: string },
|
|
441
|
-
opts?: { signal?: AbortSignal },
|
|
442
|
-
) {
|
|
443
|
-
return this.client.readFile({
|
|
444
|
-
sandboxId: this.sandbox.id,
|
|
445
|
-
path: file.path,
|
|
446
|
-
cwd: file.cwd,
|
|
447
|
-
signal: opts?.signal,
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* Write files to the filesystem of this sandbox.
|
|
453
|
-
* Defaults to writing to /vercel/sandbox unless an absolute path is specified.
|
|
454
|
-
* Writes files using the `vercel-sandbox` user.
|
|
455
|
-
*
|
|
456
|
-
* @param files - Array of files with path and stream/buffer contents
|
|
457
|
-
* @param opts - Optional parameters.
|
|
458
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
459
|
-
* @returns A promise that resolves when the files are written
|
|
460
|
-
*/
|
|
461
|
-
async writeFiles(
|
|
462
|
-
files: { path: string; content: Buffer }[],
|
|
463
|
-
opts?: { signal?: AbortSignal },
|
|
464
|
-
) {
|
|
465
|
-
return this.client.writeFiles({
|
|
466
|
-
sandboxId: this.sandbox.id,
|
|
467
|
-
cwd: this.sandbox.cwd,
|
|
468
|
-
extractDir: "/",
|
|
469
|
-
files: files,
|
|
470
|
-
signal: opts?.signal,
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Get the public domain of a port of this sandbox.
|
|
476
|
-
*
|
|
477
|
-
* @param p - Port number to resolve
|
|
478
|
-
* @returns A full domain (e.g. `https://subdomain.vercel.run`)
|
|
479
|
-
* @throws If the port has no associated route
|
|
480
|
-
*/
|
|
481
|
-
domain(p: number): string {
|
|
482
|
-
const route = this.routes.find(({ port }) => port == p);
|
|
483
|
-
if (route) {
|
|
484
|
-
return `https://${route.subdomain}.vercel.run`;
|
|
485
|
-
} else {
|
|
486
|
-
throw new Error(`No route for port ${p}`);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* Stop the sandbox.
|
|
492
|
-
*
|
|
493
|
-
* @param opts - Optional parameters.
|
|
494
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
495
|
-
* @returns A promise that resolves when the sandbox is stopped
|
|
496
|
-
*/
|
|
497
|
-
async stop(opts?: { signal?: AbortSignal }) {
|
|
498
|
-
await this.client.stopSandbox({
|
|
499
|
-
sandboxId: this.sandbox.id,
|
|
500
|
-
signal: opts?.signal,
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Extend the timeout of the sandbox by the specified duration.
|
|
506
|
-
*
|
|
507
|
-
* This allows you to extend the lifetime of a sandbox up until the maximum
|
|
508
|
-
* execution timeout for your plan.
|
|
509
|
-
*
|
|
510
|
-
* @param duration - The duration in milliseconds to extend the timeout by
|
|
511
|
-
* @param opts - Optional parameters.
|
|
512
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
513
|
-
* @returns A promise that resolves when the timeout is extended
|
|
514
|
-
*
|
|
515
|
-
* @example
|
|
516
|
-
* const sandbox = await Sandbox.create({ timeout: ms('10m') });
|
|
517
|
-
* // Extends timeout by 5 minutes, to a total of 15 minutes.
|
|
518
|
-
* await sandbox.extendTimeout(ms('5m'));
|
|
519
|
-
*/
|
|
520
|
-
async extendTimeout(
|
|
521
|
-
duration: number,
|
|
522
|
-
opts?: { signal?: AbortSignal },
|
|
523
|
-
): Promise<void> {
|
|
524
|
-
const response = await this.client.extendTimeout({
|
|
525
|
-
sandboxId: this.sandbox.id,
|
|
526
|
-
duration,
|
|
527
|
-
signal: opts?.signal,
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
// Update the internal sandbox metadata with the new timeout value
|
|
531
|
-
this.sandbox = response.json.sandbox;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* Create a snapshot from this currently running sandbox. New sandboxes can
|
|
536
|
-
* then be created from this snapshot using {@link Sandbox.createFromSnapshot}.
|
|
537
|
-
*
|
|
538
|
-
* Note: this sandbox will be stopped as part of the snapshot creation process.
|
|
539
|
-
*
|
|
540
|
-
* @param opts - Optional parameters.
|
|
541
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
542
|
-
* @returns A promise that resolves to the Snapshot instance
|
|
543
|
-
*/
|
|
544
|
-
async snapshot(opts?: { signal?: AbortSignal }): Promise<Snapshot> {
|
|
545
|
-
const response = await this.client.createSnapshot({
|
|
546
|
-
sandboxId: this.sandbox.id,
|
|
547
|
-
signal: opts?.signal,
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
this.sandbox = response.json.sandbox;
|
|
551
|
-
|
|
552
|
-
return new Snapshot({
|
|
553
|
-
client: this.client,
|
|
554
|
-
snapshot: response.json.snapshot,
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* A {@link Sandbox} that can automatically be disposed using a `await using` statement.
|
|
561
|
-
*
|
|
562
|
-
* @example
|
|
563
|
-
* {
|
|
564
|
-
* await using const sandbox = await Sandbox.create();
|
|
565
|
-
* }
|
|
566
|
-
* // Sandbox is automatically stopped here
|
|
567
|
-
*/
|
|
568
|
-
class DisposableSandbox extends Sandbox implements AsyncDisposable {
|
|
569
|
-
async [Symbol.asyncDispose]() {
|
|
570
|
-
await this.stop();
|
|
571
|
-
}
|
|
572
|
-
}
|
package/src/snapshot.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import type { SnapshotMetadata } from "./api-client";
|
|
2
|
-
import { APIClient } from "./api-client";
|
|
3
|
-
import { Credentials, getCredentials } from "./utils/get-credentials";
|
|
4
|
-
|
|
5
|
-
/** @inline */
|
|
6
|
-
interface GetSnapshotParams {
|
|
7
|
-
/**
|
|
8
|
-
* Unique identifier of the snapshot.
|
|
9
|
-
*/
|
|
10
|
-
snapshotId: string;
|
|
11
|
-
/**
|
|
12
|
-
* An AbortSignal to cancel the operation.
|
|
13
|
-
*/
|
|
14
|
-
signal?: AbortSignal;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* A Snapshot is a saved state of a Sandbox that can be used to create new Sandboxes
|
|
19
|
-
*
|
|
20
|
-
* Use {@link Sandbox.snapshot} or {@link Snapshot.get} to construct.
|
|
21
|
-
* @hideconstructor
|
|
22
|
-
*/
|
|
23
|
-
export class Snapshot {
|
|
24
|
-
private readonly client: APIClient;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Unique ID of this snapshot.
|
|
28
|
-
*/
|
|
29
|
-
public get snapshotId(): string {
|
|
30
|
-
return this.snapshot.id;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The ID the sandbox from which this snapshot was created.
|
|
35
|
-
*/
|
|
36
|
-
public get sourceSandboxId(): string {
|
|
37
|
-
return this.snapshot.sourceSandboxId;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The status of the snapshot.
|
|
42
|
-
*/
|
|
43
|
-
public get status(): SnapshotMetadata["status"] {
|
|
44
|
-
return this.snapshot.status;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Internal metadata about this snapshot.
|
|
49
|
-
*/
|
|
50
|
-
private snapshot: SnapshotMetadata;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Create a new Snapshot instance.
|
|
54
|
-
*
|
|
55
|
-
* @param client - API client used to communicate with the backend
|
|
56
|
-
* @param snapshot - Snapshot metadata
|
|
57
|
-
*/
|
|
58
|
-
constructor({
|
|
59
|
-
client,
|
|
60
|
-
snapshot,
|
|
61
|
-
}: {
|
|
62
|
-
client: APIClient;
|
|
63
|
-
snapshot: SnapshotMetadata;
|
|
64
|
-
}) {
|
|
65
|
-
this.client = client;
|
|
66
|
-
this.snapshot = snapshot;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Retrieve an existing snapshot.
|
|
71
|
-
*
|
|
72
|
-
* @param params - Get parameters and optional credentials.
|
|
73
|
-
* @returns A promise resolving to the {@link Sandbox}.
|
|
74
|
-
*/
|
|
75
|
-
static async get(
|
|
76
|
-
params: GetSnapshotParams | (GetSnapshotParams & Credentials),
|
|
77
|
-
): Promise<Snapshot> {
|
|
78
|
-
const credentials = await getCredentials(params);
|
|
79
|
-
const client = new APIClient({
|
|
80
|
-
teamId: credentials.teamId,
|
|
81
|
-
token: credentials.token,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const sandbox = await client.getSnapshot({
|
|
85
|
-
snapshotId: params.snapshotId,
|
|
86
|
-
signal: params.signal,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
return new Snapshot({
|
|
90
|
-
client,
|
|
91
|
-
snapshot: sandbox.json.snapshot,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Delete this snapshot.
|
|
97
|
-
*
|
|
98
|
-
* @param opts - Optional parameters.
|
|
99
|
-
* @param opts.signal - An AbortSignal to cancel the operation.
|
|
100
|
-
* @returns A promise that resolves once the snapshot has been deleted.
|
|
101
|
-
*/
|
|
102
|
-
async delete(opts?: { signal?: AbortSignal }): Promise<void> {
|
|
103
|
-
const response = await this.client.deleteSnapshot({
|
|
104
|
-
snapshotId: this.snapshot.id,
|
|
105
|
-
signal: opts?.signal,
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
this.snapshot = response.json.snapshot;
|
|
109
|
-
}
|
|
110
|
-
}
|
package/src/utils/array.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns an array from the given item. If the item is an array it will be
|
|
3
|
-
* returned as a it is, otherwise it will be returned as a single item array.
|
|
4
|
-
* If the item is undefined or null an empty array will be returned.
|
|
5
|
-
*
|
|
6
|
-
* @param item The item to convert to an array.
|
|
7
|
-
* @returns An array.
|
|
8
|
-
*/
|
|
9
|
-
export function array<T>(item?: null | T | T[]): T[] {
|
|
10
|
-
return item !== undefined && item !== null
|
|
11
|
-
? Array.isArray(item)
|
|
12
|
-
? item
|
|
13
|
-
: [item]
|
|
14
|
-
: [];
|
|
15
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Consumes a readable entirely concatenating all content in a single Buffer
|
|
3
|
-
* @param readable A Readable stream
|
|
4
|
-
*/
|
|
5
|
-
export function consumeReadable(readable: NodeJS.ReadableStream) {
|
|
6
|
-
return new Promise<Buffer>((resolve, reject) => {
|
|
7
|
-
const chunks: Buffer[] = [];
|
|
8
|
-
readable.on("error", (err) => reject(err));
|
|
9
|
-
readable.on("data", (chunk) => chunks.push(chunk));
|
|
10
|
-
readable.on("end", () => resolve(Buffer.concat(chunks)));
|
|
11
|
-
});
|
|
12
|
-
}
|