@vercel/sandbox 1.9.0 → 1.9.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.
Files changed (190) hide show
  1. package/README.md +8 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/api-client/api-client.cjs +375 -0
  4. package/dist/api-client/api-client.cjs.map +1 -0
  5. package/dist/api-client/api-client.d.cts +403 -0
  6. package/dist/api-client/api-client.d.ts +397 -392
  7. package/dist/api-client/api-client.js +365 -405
  8. package/dist/api-client/api-client.js.map +1 -1
  9. package/dist/api-client/api-error.cjs +31 -0
  10. package/dist/api-client/api-error.cjs.map +1 -0
  11. package/dist/api-client/api-error.d.cts +27 -0
  12. package/dist/api-client/api-error.d.ts +19 -16
  13. package/dist/api-client/api-error.js +27 -32
  14. package/dist/api-client/api-error.js.map +1 -1
  15. package/dist/api-client/base-client.cjs +113 -0
  16. package/dist/api-client/base-client.cjs.map +1 -0
  17. package/dist/api-client/base-client.d.cts +38 -0
  18. package/dist/api-client/base-client.d.ts +31 -36
  19. package/dist/api-client/base-client.js +101 -118
  20. package/dist/api-client/base-client.js.map +1 -1
  21. package/dist/api-client/file-writer.cjs +62 -0
  22. package/dist/api-client/file-writer.cjs.map +1 -0
  23. package/dist/api-client/file-writer.d.cts +66 -0
  24. package/dist/api-client/file-writer.d.ts +56 -52
  25. package/dist/api-client/file-writer.js +57 -61
  26. package/dist/api-client/file-writer.js.map +1 -1
  27. package/dist/api-client/index.cjs +2 -0
  28. package/dist/api-client/index.d.ts +2 -2
  29. package/dist/api-client/index.js +4 -21
  30. package/dist/api-client/validators.cjs +149 -0
  31. package/dist/api-client/validators.cjs.map +1 -0
  32. package/dist/api-client/validators.d.cts +1677 -0
  33. package/dist/api-client/validators.d.ts +1501 -2412
  34. package/dist/api-client/validators.js +124 -154
  35. package/dist/api-client/validators.js.map +1 -1
  36. package/dist/api-client/with-retry.cjs +89 -0
  37. package/dist/api-client/with-retry.cjs.map +1 -0
  38. package/dist/api-client/with-retry.d.cts +10 -0
  39. package/dist/api-client/with-retry.d.ts +9 -13
  40. package/dist/api-client/with-retry.js +81 -102
  41. package/dist/api-client/with-retry.js.map +1 -1
  42. package/dist/auth/api.cjs +29 -0
  43. package/dist/auth/api.cjs.map +1 -0
  44. package/dist/auth/api.js +26 -25
  45. package/dist/auth/api.js.map +1 -1
  46. package/dist/auth/error.cjs +13 -0
  47. package/dist/auth/error.cjs.map +1 -0
  48. package/dist/auth/error.js +11 -11
  49. package/dist/auth/error.js.map +1 -1
  50. package/dist/auth/file.cjs +64 -0
  51. package/dist/auth/file.cjs.map +1 -0
  52. package/dist/auth/file.d.cts +26 -0
  53. package/dist/auth/file.d.ts +19 -15
  54. package/dist/auth/file.js +49 -64
  55. package/dist/auth/file.js.map +1 -1
  56. package/dist/auth/index.cjs +12 -0
  57. package/dist/auth/index.d.cts +5 -0
  58. package/dist/auth/index.d.ts +5 -6
  59. package/dist/auth/index.js +6 -27
  60. package/dist/auth/linked-project.cjs +38 -0
  61. package/dist/auth/linked-project.cjs.map +1 -0
  62. package/dist/auth/linked-project.js +30 -64
  63. package/dist/auth/linked-project.js.map +1 -1
  64. package/dist/auth/oauth.cjs +205 -0
  65. package/dist/auth/oauth.cjs.map +1 -0
  66. package/dist/auth/oauth.d.cts +135 -0
  67. package/dist/auth/oauth.d.ts +113 -109
  68. package/dist/auth/oauth.js +185 -252
  69. package/dist/auth/oauth.js.map +1 -1
  70. package/dist/auth/poll-for-token.cjs +82 -0
  71. package/dist/auth/poll-for-token.cjs.map +1 -0
  72. package/dist/auth/poll-for-token.d.cts +28 -0
  73. package/dist/auth/poll-for-token.d.ts +23 -15
  74. package/dist/auth/poll-for-token.js +79 -64
  75. package/dist/auth/poll-for-token.js.map +1 -1
  76. package/dist/auth/project.cjs +80 -0
  77. package/dist/auth/project.cjs.map +1 -0
  78. package/dist/auth/project.d.cts +44 -0
  79. package/dist/auth/project.d.ts +12 -8
  80. package/dist/auth/project.js +70 -72
  81. package/dist/auth/project.js.map +1 -1
  82. package/dist/auth/zod.cjs +22 -0
  83. package/dist/auth/zod.cjs.map +1 -0
  84. package/dist/auth/zod.js +18 -17
  85. package/dist/auth/zod.js.map +1 -1
  86. package/dist/command.cjs +326 -0
  87. package/dist/command.cjs.map +1 -0
  88. package/dist/command.d.cts +289 -0
  89. package/dist/command.d.ts +265 -171
  90. package/dist/command.js +321 -226
  91. package/dist/command.js.map +1 -1
  92. package/dist/constants.d.cts +5 -0
  93. package/dist/constants.d.ts +5 -1
  94. package/dist/index.cjs +11 -0
  95. package/dist/index.d.cts +6 -0
  96. package/dist/index.d.ts +6 -5
  97. package/dist/index.js +6 -15
  98. package/dist/network-policy.d.cts +100 -0
  99. package/dist/network-policy.d.ts +32 -28
  100. package/dist/sandbox.cjs +543 -0
  101. package/dist/sandbox.cjs.map +1 -0
  102. package/dist/sandbox.d.cts +538 -0
  103. package/dist/sandbox.d.ts +521 -479
  104. package/dist/sandbox.js +539 -512
  105. package/dist/sandbox.js.map +1 -1
  106. package/dist/snapshot.cjs +116 -0
  107. package/dist/snapshot.cjs.map +1 -0
  108. package/dist/snapshot.d.cts +109 -0
  109. package/dist/snapshot.d.ts +100 -92
  110. package/dist/snapshot.js +114 -114
  111. package/dist/snapshot.js.map +1 -1
  112. package/dist/utils/array.cjs +17 -0
  113. package/dist/utils/array.cjs.map +1 -0
  114. package/dist/utils/array.js +12 -15
  115. package/dist/utils/array.js.map +1 -1
  116. package/dist/utils/consume-readable.cjs +18 -0
  117. package/dist/utils/consume-readable.cjs.map +1 -0
  118. package/dist/utils/consume-readable.js +13 -12
  119. package/dist/utils/consume-readable.js.map +1 -1
  120. package/dist/utils/decode-base64-url.cjs +15 -0
  121. package/dist/utils/decode-base64-url.cjs.map +1 -0
  122. package/dist/utils/decode-base64-url.js +10 -9
  123. package/dist/utils/decode-base64-url.js.map +1 -1
  124. package/dist/utils/dev-credentials.cjs +142 -0
  125. package/dist/utils/dev-credentials.cjs.map +1 -0
  126. package/dist/utils/dev-credentials.js +126 -184
  127. package/dist/utils/dev-credentials.js.map +1 -1
  128. package/dist/utils/get-credentials.cjs +123 -0
  129. package/dist/utils/get-credentials.cjs.map +1 -0
  130. package/dist/utils/get-credentials.d.cts +21 -0
  131. package/dist/utils/get-credentials.d.ts +19 -61
  132. package/dist/utils/get-credentials.js +106 -140
  133. package/dist/utils/get-credentials.js.map +1 -1
  134. package/dist/utils/log.cjs +25 -0
  135. package/dist/utils/log.cjs.map +1 -0
  136. package/dist/utils/log.js +15 -17
  137. package/dist/utils/log.js.map +1 -1
  138. package/dist/utils/network-policy.cjs +65 -0
  139. package/dist/utils/network-policy.cjs.map +1 -0
  140. package/dist/utils/network-policy.js +58 -77
  141. package/dist/utils/network-policy.js.map +1 -1
  142. package/dist/utils/normalizePath.cjs +27 -0
  143. package/dist/utils/normalizePath.cjs.map +1 -0
  144. package/dist/utils/normalizePath.js +21 -28
  145. package/dist/utils/normalizePath.js.map +1 -1
  146. package/dist/utils/resolveSignal.cjs +20 -0
  147. package/dist/utils/resolveSignal.cjs.map +1 -0
  148. package/dist/utils/resolveSignal.d.cts +15 -0
  149. package/dist/utils/resolveSignal.d.ts +12 -10
  150. package/dist/utils/resolveSignal.js +14 -17
  151. package/dist/utils/resolveSignal.js.map +1 -1
  152. package/dist/utils/sandbox-snapshot.cjs +14 -0
  153. package/dist/utils/sandbox-snapshot.cjs.map +1 -0
  154. package/dist/utils/sandbox-snapshot.d.cts +10 -0
  155. package/dist/utils/sandbox-snapshot.d.ts +11 -0
  156. package/dist/utils/sandbox-snapshot.js +14 -0
  157. package/dist/utils/sandbox-snapshot.js.map +1 -0
  158. package/dist/utils/types.cjs +13 -0
  159. package/dist/utils/types.cjs.map +1 -0
  160. package/dist/utils/types.d.cts +11 -0
  161. package/dist/utils/types.d.ts +5 -7
  162. package/dist/utils/types.js +8 -8
  163. package/dist/utils/types.js.map +1 -1
  164. package/dist/version.cjs +7 -0
  165. package/dist/version.cjs.map +1 -0
  166. package/dist/version.js +5 -5
  167. package/dist/version.js.map +1 -1
  168. package/package.json +23 -3
  169. package/dist/api-client/index.js.map +0 -1
  170. package/dist/auth/api.d.ts +0 -6
  171. package/dist/auth/error.d.ts +0 -11
  172. package/dist/auth/index.js.map +0 -1
  173. package/dist/auth/linked-project.d.ts +0 -10
  174. package/dist/auth/zod.d.ts +0 -5
  175. package/dist/constants.js +0 -3
  176. package/dist/constants.js.map +0 -1
  177. package/dist/index.js.map +0 -1
  178. package/dist/network-policy.js +0 -3
  179. package/dist/network-policy.js.map +0 -1
  180. package/dist/utils/array.d.ts +0 -9
  181. package/dist/utils/consume-readable.d.ts +0 -5
  182. package/dist/utils/convert-sandbox.d.ts +0 -6
  183. package/dist/utils/convert-sandbox.js +0 -14
  184. package/dist/utils/convert-sandbox.js.map +0 -1
  185. package/dist/utils/decode-base64-url.d.ts +0 -7
  186. package/dist/utils/dev-credentials.d.ts +0 -37
  187. package/dist/utils/log.d.ts +0 -2
  188. package/dist/utils/network-policy.d.ts +0 -7
  189. package/dist/utils/normalizePath.d.ts +0 -17
  190. package/dist/version.d.ts +0 -1
package/dist/sandbox.js CHANGED
@@ -1,515 +1,542 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
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
- const api_client_1 = require("./api-client");
9
- const command_1 = require("./command");
10
- const get_credentials_1 = require("./utils/get-credentials");
11
- const types_1 = require("./utils/types");
12
- const snapshot_1 = require("./snapshot");
13
- const consume_readable_1 = require("./utils/consume-readable");
14
- const convert_sandbox_1 = require("./utils/convert-sandbox");
1
+ import { consumeReadable } from "./utils/consume-readable.js";
2
+ import { getPrivateParams } from "./utils/types.js";
3
+ import { APIClient } from "./api-client/api-client.js";
4
+ import "./api-client/index.js";
5
+ import { getCredentials } from "./utils/get-credentials.js";
6
+ import { Command, CommandFinished } from "./command.js";
7
+ import { Snapshot } from "./snapshot.js";
8
+ import { toSandboxSnapshot } from "./utils/sandbox-snapshot.js";
9
+ import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from "@workflow/serde";
10
+ import { createWriteStream } from "fs";
11
+ import { mkdir } from "fs/promises";
12
+ import { dirname, resolve } from "path";
13
+ import { pipeline } from "stream/promises";
14
+
15
+ //#region src/sandbox.ts
15
16
  /**
16
- * A Sandbox is an isolated Linux MicroVM to run commands in.
17
- *
18
- * Use {@link Sandbox.create} or {@link Sandbox.get} to construct.
19
- * @hideconstructor
20
- */
21
- class Sandbox {
22
- /**
23
- * Unique ID of this sandbox.
24
- */
25
- get sandboxId() {
26
- return this.sandbox.id;
27
- }
28
- get interactivePort() {
29
- return this.sandbox.interactivePort ?? undefined;
30
- }
31
- /**
32
- * The status of the sandbox.
33
- */
34
- get status() {
35
- return this.sandbox.status;
36
- }
37
- /**
38
- * The creation date of the sandbox.
39
- */
40
- get createdAt() {
41
- return new Date(this.sandbox.createdAt);
42
- }
43
- /**
44
- * The timeout of the sandbox in milliseconds.
45
- */
46
- get timeout() {
47
- return this.sandbox.timeout;
48
- }
49
- /**
50
- * The network policy of the sandbox.
51
- */
52
- get networkPolicy() {
53
- return this.sandbox.networkPolicy;
54
- }
55
- /**
56
- * If the sandbox was created from a snapshot, the ID of that snapshot.
57
- */
58
- get sourceSnapshotId() {
59
- return this.sandbox.sourceSnapshotId;
60
- }
61
- /**
62
- * The amount of CPU used by the sandbox. Only reported once the VM is stopped.
63
- */
64
- get activeCpuUsageMs() {
65
- return this.sandbox.activeCpuDurationMs;
66
- }
67
- /**
68
- * The amount of network data used by the sandbox. Only reported once the VM is stopped.
69
- */
70
- get networkTransfer() {
71
- return this.sandbox.networkTransfer;
72
- }
73
- /**
74
- * Allow to get a list of sandboxes for a team narrowed to the given params.
75
- * It returns both the sandboxes and the pagination metadata to allow getting
76
- * the next page of results.
77
- */
78
- static async list(params) {
79
- const credentials = await (0, get_credentials_1.getCredentials)(params);
80
- const client = new api_client_1.APIClient({
81
- teamId: credentials.teamId,
82
- token: credentials.token,
83
- fetch: params?.fetch,
84
- });
85
- return client.listSandboxes({
86
- ...credentials,
87
- ...params,
88
- });
89
- }
90
- /**
91
- * Create a new sandbox.
92
- *
93
- * @param params - Creation parameters and optional credentials.
94
- * @returns A promise resolving to the created {@link Sandbox}.
95
- * @example
96
- * <caption>Create a sandbox and drop it in the end of the block</caption>
97
- * async function fn() {
98
- * await using const sandbox = await Sandbox.create();
99
- * // Sandbox automatically stopped at the end of the lexical scope
100
- * }
101
- */
102
- static async create(params) {
103
- const credentials = await (0, get_credentials_1.getCredentials)(params);
104
- const client = new api_client_1.APIClient({
105
- teamId: credentials.teamId,
106
- token: credentials.token,
107
- fetch: params?.fetch,
108
- });
109
- const privateParams = (0, types_1.getPrivateParams)(params);
110
- const sandbox = await client.createSandbox({
111
- source: params?.source,
112
- projectId: credentials.projectId,
113
- ports: params?.ports ?? [],
114
- timeout: params?.timeout,
115
- resources: params?.resources,
116
- runtime: params && "runtime" in params ? params?.runtime : undefined,
117
- networkPolicy: params?.networkPolicy,
118
- env: params?.env,
119
- signal: params?.signal,
120
- ...privateParams,
121
- });
122
- return new DisposableSandbox({
123
- client,
124
- sandbox: sandbox.json.sandbox,
125
- routes: sandbox.json.routes,
126
- });
127
- }
128
- /**
129
- * Retrieve an existing sandbox.
130
- *
131
- * @param params - Get parameters and optional credentials.
132
- * @returns A promise resolving to the {@link Sandbox}.
133
- */
134
- static async get(params) {
135
- const credentials = await (0, get_credentials_1.getCredentials)(params);
136
- const client = new api_client_1.APIClient({
137
- teamId: credentials.teamId,
138
- token: credentials.token,
139
- fetch: params.fetch,
140
- });
141
- const privateParams = (0, types_1.getPrivateParams)(params);
142
- const sandbox = await client.getSandbox({
143
- sandboxId: params.sandboxId,
144
- signal: params.signal,
145
- ...privateParams,
146
- });
147
- return new Sandbox({
148
- client,
149
- sandbox: sandbox.json.sandbox,
150
- routes: sandbox.json.routes,
151
- });
152
- }
153
- constructor({ client, routes, sandbox, }) {
154
- this.client = client;
155
- this.routes = routes;
156
- this.sandbox = (0, convert_sandbox_1.convertSandbox)(sandbox);
157
- }
158
- /**
159
- * Get a previously run command by its ID.
160
- *
161
- * @param cmdId - ID of the command to retrieve
162
- * @param opts - Optional parameters.
163
- * @param opts.signal - An AbortSignal to cancel the operation.
164
- * @returns A {@link Command} instance representing the command
165
- */
166
- async getCommand(cmdId, opts) {
167
- const command = await this.client.getCommand({
168
- sandboxId: this.sandbox.id,
169
- cmdId,
170
- signal: opts?.signal,
171
- });
172
- return new command_1.Command({
173
- client: this.client,
174
- sandboxId: this.sandbox.id,
175
- cmd: command.json.command,
176
- });
177
- }
178
- async runCommand(commandOrParams, args, opts) {
179
- return typeof commandOrParams === "string"
180
- ? this._runCommand({ cmd: commandOrParams, args, signal: opts?.signal })
181
- : this._runCommand(commandOrParams);
182
- }
183
- /**
184
- * Internal helper to start a command in the sandbox.
185
- *
186
- * @param params - Command execution parameters.
187
- * @returns A {@link Command} or {@link CommandFinished}, depending on `detached`.
188
- * @internal
189
- */
190
- async _runCommand(params) {
191
- const wait = params.detached ? false : true;
192
- const pipeLogs = async (command) => {
193
- if (!params.stdout && !params.stderr) {
194
- return;
195
- }
196
- try {
197
- for await (const log of command.logs({ signal: params.signal })) {
198
- if (log.stream === "stdout") {
199
- params.stdout?.write(log.data);
200
- }
201
- else if (log.stream === "stderr") {
202
- params.stderr?.write(log.data);
203
- }
204
- }
205
- }
206
- catch (err) {
207
- if (params.signal?.aborted) {
208
- return;
209
- }
210
- throw err;
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
- const [finished] = await Promise.all([
230
- commandStream.finished,
231
- pipeLogs(command),
232
- ]);
233
- return new command_1.CommandFinished({
234
- client: this.client,
235
- sandboxId: this.sandbox.id,
236
- cmd: finished,
237
- exitCode: finished.exitCode ?? 0,
238
- });
239
- }
240
- const commandResponse = await this.client.runCommand({
241
- sandboxId: this.sandbox.id,
242
- command: params.cmd,
243
- args: params.args ?? [],
244
- cwd: params.cwd,
245
- env: params.env ?? {},
246
- sudo: params.sudo ?? false,
247
- signal: params.signal,
248
- });
249
- const command = new command_1.Command({
250
- client: this.client,
251
- sandboxId: this.sandbox.id,
252
- cmd: commandResponse.json.command,
253
- });
254
- void pipeLogs(command).catch((err) => {
255
- if (params.signal?.aborted) {
256
- return;
257
- }
258
- (params.stderr ?? params.stdout)?.emit('error', err);
259
- });
260
- return command;
261
- }
262
- /**
263
- * Create a directory in the filesystem of this sandbox.
264
- *
265
- * @param path - Path of the directory to create
266
- * @param opts - Optional parameters.
267
- * @param opts.signal - An AbortSignal to cancel the operation.
268
- */
269
- async mkDir(path, opts) {
270
- await this.client.mkDir({
271
- sandboxId: this.sandbox.id,
272
- path: path,
273
- signal: opts?.signal,
274
- });
275
- }
276
- /**
277
- * Read a file from the filesystem of this sandbox as a stream.
278
- *
279
- * @param file - File to read, with path and optional cwd
280
- * @param opts - Optional parameters.
281
- * @param opts.signal - An AbortSignal to cancel the operation.
282
- * @returns A promise that resolves to a ReadableStream containing the file contents, or null if file not found
283
- */
284
- async readFile(file, opts) {
285
- return this.client.readFile({
286
- sandboxId: this.sandbox.id,
287
- path: file.path,
288
- cwd: file.cwd,
289
- signal: opts?.signal,
290
- });
291
- }
292
- /**
293
- * Read a file from the filesystem of this sandbox as a Buffer.
294
- *
295
- * @param file - File to read, with path and optional cwd
296
- * @param opts - Optional parameters.
297
- * @param opts.signal - An AbortSignal to cancel the operation.
298
- * @returns A promise that resolves to the file contents as a Buffer, or null if file not found
299
- */
300
- async readFileToBuffer(file, opts) {
301
- const stream = await this.client.readFile({
302
- sandboxId: this.sandbox.id,
303
- path: file.path,
304
- cwd: file.cwd,
305
- signal: opts?.signal,
306
- });
307
- if (stream === null) {
308
- return null;
309
- }
310
- return (0, consume_readable_1.consumeReadable)(stream);
311
- }
312
- /**
313
- * Download a file from the sandbox to the local filesystem.
314
- *
315
- * @param src - Source file on the sandbox, with path and optional cwd
316
- * @param dst - Destination file on the local machine, with path and optional cwd
317
- * @param opts - Optional parameters.
318
- * @param opts.mkdirRecursive - If true, create parent directories for the destination if they don't exist.
319
- * @param opts.signal - An AbortSignal to cancel the operation.
320
- * @returns The absolute path to the written file, or null if the source file was not found
321
- */
322
- async downloadFile(src, dst, opts) {
323
- if (!src?.path) {
324
- throw new Error("downloadFile: source path is required");
325
- }
326
- if (!dst?.path) {
327
- throw new Error("downloadFile: destination path is required");
328
- }
329
- const stream = await this.client.readFile({
330
- sandboxId: this.sandbox.id,
331
- path: src.path,
332
- cwd: src.cwd,
333
- signal: opts?.signal,
334
- });
335
- if (stream === null) {
336
- return null;
337
- }
338
- try {
339
- const dstPath = (0, path_1.resolve)(dst.cwd ?? "", dst.path);
340
- if (opts?.mkdirRecursive) {
341
- await (0, promises_2.mkdir)((0, path_1.dirname)(dstPath), { recursive: true });
342
- }
343
- await (0, promises_1.pipeline)(stream, (0, fs_1.createWriteStream)(dstPath), {
344
- signal: opts?.signal,
345
- });
346
- return dstPath;
347
- }
348
- finally {
349
- stream.destroy();
350
- }
351
- }
352
- /**
353
- * Write files to the filesystem of this sandbox.
354
- * Defaults to writing to /vercel/sandbox unless an absolute path is specified.
355
- * Writes files using the `vercel-sandbox` user.
356
- *
357
- * @param files - Array of files with path, content, and optional mode (permissions)
358
- * @param opts - Optional parameters.
359
- * @param opts.signal - An AbortSignal to cancel the operation.
360
- * @returns A promise that resolves when the files are written
361
- *
362
- * @example
363
- * // Write an executable script
364
- * await sandbox.writeFiles([
365
- * { path: "/usr/local/bin/myscript", content: Buffer.from("#!/bin/bash\necho hello"), mode: 0o755 }
366
- * ]);
367
- */
368
- async writeFiles(files, opts) {
369
- return this.client.writeFiles({
370
- sandboxId: this.sandbox.id,
371
- cwd: this.sandbox.cwd,
372
- extractDir: "/",
373
- files: files,
374
- signal: opts?.signal,
375
- });
376
- }
377
- /**
378
- * Get the public domain of a port of this sandbox.
379
- *
380
- * @param p - Port number to resolve
381
- * @returns A full domain (e.g. `https://subdomain.vercel.run`)
382
- * @throws If the port has no associated route
383
- */
384
- domain(p) {
385
- const route = this.routes.find(({ port }) => port == p);
386
- if (route) {
387
- return `https://${route.subdomain}.vercel.run`;
388
- }
389
- else {
390
- throw new Error(`No route for port ${p}`);
391
- }
392
- }
393
- /**
394
- * Stop the sandbox.
395
- *
396
- * @param opts - Optional parameters.
397
- * @param opts.signal - An AbortSignal to cancel the operation.
398
- * @param opts.blocking - If true, poll until the sandbox has fully stopped and return the final state.
399
- * @returns The sandbox metadata at the time the stop was acknowledged, or after fully stopped if `blocking` is true.
400
- */
401
- async stop(opts) {
402
- const response = await this.client.stopSandbox({
403
- sandboxId: this.sandbox.id,
404
- signal: opts?.signal,
405
- blocking: opts?.blocking,
406
- });
407
- this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
408
- return this.sandbox;
409
- }
410
- /**
411
- * Update the network policy for this sandbox.
412
- *
413
- * @param networkPolicy - The new network policy to apply.
414
- * @param opts - Optional parameters.
415
- * @param opts.signal - An AbortSignal to cancel the operation.
416
- * @returns A promise that resolves when the network policy is updated.
417
- *
418
- * @example
419
- * // Restrict to specific domains
420
- * await sandbox.updateNetworkPolicy({
421
- * allow: ["*.npmjs.org", "github.com"],
422
- * });
423
- *
424
- * @example
425
- * // Inject credentials with per-domain transformers
426
- * await sandbox.updateNetworkPolicy({
427
- * allow: {
428
- * "ai-gateway.vercel.sh": [{
429
- * transform: [{
430
- * headers: { authorization: "Bearer ..." }
431
- * }]
432
- * }],
433
- * "*": []
434
- * }
435
- * });
436
- *
437
- * @example
438
- * // Deny all network access
439
- * await sandbox.updateNetworkPolicy("deny-all");
440
- */
441
- async updateNetworkPolicy(networkPolicy, opts) {
442
- const response = await this.client.updateNetworkPolicy({
443
- sandboxId: this.sandbox.id,
444
- networkPolicy: networkPolicy,
445
- signal: opts?.signal,
446
- });
447
- // Update the internal sandbox metadata with the new timeout value
448
- this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
449
- return this.sandbox.networkPolicy;
450
- }
451
- /**
452
- * Extend the timeout of the sandbox by the specified duration.
453
- *
454
- * This allows you to extend the lifetime of a sandbox up until the maximum
455
- * execution timeout for your plan.
456
- *
457
- * @param duration - The duration in milliseconds to extend the timeout by
458
- * @param opts - Optional parameters.
459
- * @param opts.signal - An AbortSignal to cancel the operation.
460
- * @returns A promise that resolves when the timeout is extended
461
- *
462
- * @example
463
- * const sandbox = await Sandbox.create({ timeout: ms('10m') });
464
- * // Extends timeout by 5 minutes, to a total of 15 minutes.
465
- * await sandbox.extendTimeout(ms('5m'));
466
- */
467
- async extendTimeout(duration, opts) {
468
- const response = await this.client.extendTimeout({
469
- sandboxId: this.sandbox.id,
470
- duration,
471
- signal: opts?.signal,
472
- });
473
- // Update the internal sandbox metadata with the new timeout value
474
- this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
475
- }
476
- /**
477
- * Create a snapshot from this currently running sandbox. New sandboxes can
478
- * then be created from this snapshot using {@link Sandbox.createFromSnapshot}.
479
- *
480
- * Note: this sandbox will be stopped as part of the snapshot creation process.
481
- *
482
- * @param opts - Optional parameters.
483
- * @param opts.expiration - Optional expiration time in milliseconds. Use 0 for no expiration at all.
484
- * @param opts.signal - An AbortSignal to cancel the operation.
485
- * @returns A promise that resolves to the Snapshot instance
486
- */
487
- async snapshot(opts) {
488
- const response = await this.client.createSnapshot({
489
- sandboxId: this.sandbox.id,
490
- expiration: opts?.expiration,
491
- signal: opts?.signal,
492
- });
493
- this.sandbox = (0, convert_sandbox_1.convertSandbox)(response.json.sandbox);
494
- return new snapshot_1.Snapshot({
495
- client: this.client,
496
- snapshot: response.json.snapshot,
497
- });
498
- }
499
- }
500
- exports.Sandbox = Sandbox;
17
+ * A Sandbox is an isolated Linux MicroVM to run commands in.
18
+ *
19
+ * Use {@link Sandbox.create} or {@link Sandbox.get} to construct.
20
+ * @hideconstructor
21
+ */
22
+ var Sandbox = class Sandbox {
23
+ /**
24
+ * Lazily resolve credentials and construct an API client.
25
+ * This is used in step contexts where the Sandbox was deserialized
26
+ * without a client (e.g. when crossing workflow/step boundaries).
27
+ * Uses getCredentials() which resolves from OIDC or env vars.
28
+ * @internal
29
+ */
30
+ async ensureClient() {
31
+ "use step";
32
+ if (this._client) return this._client;
33
+ const credentials = await getCredentials();
34
+ this._client = new APIClient({
35
+ teamId: credentials.teamId,
36
+ token: credentials.token
37
+ });
38
+ return this._client;
39
+ }
40
+ /**
41
+ * Unique ID of this sandbox.
42
+ */
43
+ get sandboxId() {
44
+ return this.sandbox.id;
45
+ }
46
+ get interactivePort() {
47
+ return this.sandbox.interactivePort ?? void 0;
48
+ }
49
+ /**
50
+ * The status of the sandbox.
51
+ */
52
+ get status() {
53
+ return this.sandbox.status;
54
+ }
55
+ /**
56
+ * The creation date of the sandbox.
57
+ */
58
+ get createdAt() {
59
+ return new Date(this.sandbox.createdAt);
60
+ }
61
+ /**
62
+ * The timeout of the sandbox in milliseconds.
63
+ */
64
+ get timeout() {
65
+ return this.sandbox.timeout;
66
+ }
67
+ /**
68
+ * The network policy of the sandbox.
69
+ */
70
+ get networkPolicy() {
71
+ return this.sandbox.networkPolicy;
72
+ }
73
+ /**
74
+ * If the sandbox was created from a snapshot, the ID of that snapshot.
75
+ */
76
+ get sourceSnapshotId() {
77
+ return this.sandbox.sourceSnapshotId;
78
+ }
79
+ /**
80
+ * The amount of CPU used by the sandbox. Only reported once the VM is stopped.
81
+ */
82
+ get activeCpuUsageMs() {
83
+ return this.sandbox.activeCpuDurationMs;
84
+ }
85
+ /**
86
+ * The amount of network data used by the sandbox. Only reported once the VM is stopped.
87
+ */
88
+ get networkTransfer() {
89
+ return this.sandbox.networkTransfer;
90
+ }
91
+ /**
92
+ * Allow to get a list of sandboxes for a team narrowed to the given params.
93
+ * It returns both the sandboxes and the pagination metadata to allow getting
94
+ * the next page of results.
95
+ */
96
+ static async list(params) {
97
+ "use step";
98
+ const credentials = await getCredentials(params);
99
+ return new APIClient({
100
+ teamId: credentials.teamId,
101
+ token: credentials.token,
102
+ fetch: params?.fetch
103
+ }).listSandboxes({
104
+ ...credentials,
105
+ ...params
106
+ });
107
+ }
108
+ /**
109
+ * Serialize a Sandbox instance to plain data for @workflow/serde.
110
+ *
111
+ * @param instance - The Sandbox instance to serialize
112
+ * @returns A plain object containing sandbox metadata and routes
113
+ */
114
+ static [WORKFLOW_SERIALIZE](instance) {
115
+ return {
116
+ metadata: instance.sandbox,
117
+ routes: instance.routes
118
+ };
119
+ }
120
+ /**
121
+ * Deserialize a Sandbox from serialized snapshot data.
122
+ *
123
+ * The deserialized instance uses the serialized metadata synchronously and
124
+ * lazily creates an API client only when methods perform API requests.
125
+ *
126
+ * @param data - The serialized sandbox data
127
+ * @returns The reconstructed Sandbox instance
128
+ */
129
+ static [WORKFLOW_DESERIALIZE](data) {
130
+ return new Sandbox({
131
+ sandbox: data.metadata,
132
+ routes: data.routes
133
+ });
134
+ }
135
+ /**
136
+ * Create a new sandbox.
137
+ *
138
+ * @param params - Creation parameters and optional credentials.
139
+ * @returns A promise resolving to the created {@link Sandbox}.
140
+ * @example
141
+ * <caption>Create a sandbox and drop it in the end of the block</caption>
142
+ * async function fn() {
143
+ * await using const sandbox = await Sandbox.create();
144
+ * // Sandbox automatically stopped at the end of the lexical scope
145
+ * }
146
+ */
147
+ static async create(params) {
148
+ "use step";
149
+ const credentials = await getCredentials(params);
150
+ const client = new APIClient({
151
+ teamId: credentials.teamId,
152
+ token: credentials.token,
153
+ fetch: params?.fetch
154
+ });
155
+ const privateParams = getPrivateParams(params);
156
+ const sandbox = await client.createSandbox({
157
+ source: params?.source,
158
+ projectId: credentials.projectId,
159
+ ports: params?.ports ?? [],
160
+ timeout: params?.timeout,
161
+ resources: params?.resources,
162
+ runtime: params && "runtime" in params ? params?.runtime : void 0,
163
+ networkPolicy: params?.networkPolicy,
164
+ env: params?.env,
165
+ signal: params?.signal,
166
+ ...privateParams
167
+ });
168
+ return new DisposableSandbox({
169
+ client,
170
+ sandbox: toSandboxSnapshot(sandbox.json.sandbox),
171
+ routes: sandbox.json.routes
172
+ });
173
+ }
174
+ /**
175
+ * Retrieve an existing sandbox.
176
+ *
177
+ * @param params - Get parameters and optional credentials.
178
+ * @returns A promise resolving to the {@link Sandbox}.
179
+ */
180
+ static async get(params) {
181
+ "use step";
182
+ const credentials = await getCredentials(params);
183
+ const client = new APIClient({
184
+ teamId: credentials.teamId,
185
+ token: credentials.token,
186
+ fetch: params.fetch
187
+ });
188
+ const privateParams = getPrivateParams(params);
189
+ const sandbox = await client.getSandbox({
190
+ sandboxId: params.sandboxId,
191
+ signal: params.signal,
192
+ ...privateParams
193
+ });
194
+ return new Sandbox({
195
+ client,
196
+ sandbox: toSandboxSnapshot(sandbox.json.sandbox),
197
+ routes: sandbox.json.routes
198
+ });
199
+ }
200
+ /**
201
+ * Create a new Sandbox instance.
202
+ *
203
+ * @param params.client - Optional API client. If not provided, will be lazily created using global credentials.
204
+ * @param params.routes - Port-to-subdomain mappings for exposed ports
205
+ * @param params.sandbox - Sandbox snapshot metadata
206
+ */
207
+ constructor({ client, routes, sandbox }) {
208
+ this._client = null;
209
+ this._client = client ?? null;
210
+ this.routes = routes;
211
+ this.sandbox = sandbox;
212
+ }
213
+ /**
214
+ * Get a previously run command by its ID.
215
+ *
216
+ * @param cmdId - ID of the command to retrieve
217
+ * @param opts - Optional parameters.
218
+ * @param opts.signal - An AbortSignal to cancel the operation.
219
+ * @returns A {@link Command} instance representing the command
220
+ */
221
+ async getCommand(cmdId, opts) {
222
+ "use step";
223
+ const client = await this.ensureClient();
224
+ const command = await client.getCommand({
225
+ sandboxId: this.sandbox.id,
226
+ cmdId,
227
+ signal: opts?.signal
228
+ });
229
+ return new Command({
230
+ client,
231
+ sandboxId: this.sandbox.id,
232
+ cmd: command.json.command
233
+ });
234
+ }
235
+ async runCommand(commandOrParams, args, opts) {
236
+ "use step";
237
+ const client = await this.ensureClient();
238
+ const params = typeof commandOrParams === "string" ? {
239
+ cmd: commandOrParams,
240
+ args,
241
+ signal: opts?.signal
242
+ } : commandOrParams;
243
+ const wait = params.detached ? false : true;
244
+ const pipeLogs = async (command$1) => {
245
+ if (!params.stdout && !params.stderr) return;
246
+ try {
247
+ for await (const log of command$1.logs({ signal: params.signal })) if (log.stream === "stdout") params.stdout?.write(log.data);
248
+ else if (log.stream === "stderr") params.stderr?.write(log.data);
249
+ } catch (err) {
250
+ if (params.signal?.aborted) return;
251
+ throw err;
252
+ }
253
+ };
254
+ if (wait) {
255
+ const commandStream = await client.runCommand({
256
+ sandboxId: this.sandbox.id,
257
+ command: params.cmd,
258
+ args: params.args ?? [],
259
+ cwd: params.cwd,
260
+ env: params.env ?? {},
261
+ sudo: params.sudo ?? false,
262
+ wait: true,
263
+ signal: params.signal
264
+ });
265
+ const command$1 = new Command({
266
+ client,
267
+ sandboxId: this.sandbox.id,
268
+ cmd: commandStream.command
269
+ });
270
+ const [finished] = await Promise.all([commandStream.finished, pipeLogs(command$1)]);
271
+ return new CommandFinished({
272
+ client,
273
+ sandboxId: this.sandbox.id,
274
+ cmd: finished,
275
+ exitCode: finished.exitCode ?? 0
276
+ });
277
+ }
278
+ const commandResponse = await client.runCommand({
279
+ sandboxId: this.sandbox.id,
280
+ command: params.cmd,
281
+ args: params.args ?? [],
282
+ cwd: params.cwd,
283
+ env: params.env ?? {},
284
+ sudo: params.sudo ?? false,
285
+ signal: params.signal
286
+ });
287
+ const command = new Command({
288
+ client,
289
+ sandboxId: this.sandbox.id,
290
+ cmd: commandResponse.json.command
291
+ });
292
+ pipeLogs(command).catch((err) => {
293
+ if (params.signal?.aborted) return;
294
+ (params.stderr ?? params.stdout)?.emit("error", err);
295
+ });
296
+ return command;
297
+ }
298
+ /**
299
+ * Create a directory in the filesystem of this sandbox.
300
+ *
301
+ * @param path - Path of the directory to create
302
+ * @param opts - Optional parameters.
303
+ * @param opts.signal - An AbortSignal to cancel the operation.
304
+ */
305
+ async mkDir(path$1, opts) {
306
+ "use step";
307
+ await (await this.ensureClient()).mkDir({
308
+ sandboxId: this.sandbox.id,
309
+ path: path$1,
310
+ signal: opts?.signal
311
+ });
312
+ }
313
+ /**
314
+ * Read a file from the filesystem of this sandbox as a stream.
315
+ *
316
+ * @param file - File to read, with path and optional cwd
317
+ * @param opts - Optional parameters.
318
+ * @param opts.signal - An AbortSignal to cancel the operation.
319
+ * @returns A promise that resolves to a ReadableStream containing the file contents, or null if file not found
320
+ */
321
+ async readFile(file, opts) {
322
+ "use step";
323
+ return (await this.ensureClient()).readFile({
324
+ sandboxId: this.sandbox.id,
325
+ path: file.path,
326
+ cwd: file.cwd,
327
+ signal: opts?.signal
328
+ });
329
+ }
330
+ /**
331
+ * Read a file from the filesystem of this sandbox as a Buffer.
332
+ *
333
+ * @param file - File to read, with path and optional cwd
334
+ * @param opts - Optional parameters.
335
+ * @param opts.signal - An AbortSignal to cancel the operation.
336
+ * @returns A promise that resolves to the file contents as a Buffer, or null if file not found
337
+ */
338
+ async readFileToBuffer(file, opts) {
339
+ "use step";
340
+ const stream = await (await this.ensureClient()).readFile({
341
+ sandboxId: this.sandbox.id,
342
+ path: file.path,
343
+ cwd: file.cwd,
344
+ signal: opts?.signal
345
+ });
346
+ if (stream === null) return null;
347
+ return consumeReadable(stream);
348
+ }
349
+ /**
350
+ * Download a file from the sandbox to the local filesystem.
351
+ *
352
+ * @param src - Source file on the sandbox, with path and optional cwd
353
+ * @param dst - Destination file on the local machine, with path and optional cwd
354
+ * @param opts - Optional parameters.
355
+ * @param opts.mkdirRecursive - If true, create parent directories for the destination if they don't exist.
356
+ * @param opts.signal - An AbortSignal to cancel the operation.
357
+ * @returns The absolute path to the written file, or null if the source file was not found
358
+ */
359
+ async downloadFile(src, dst, opts) {
360
+ "use step";
361
+ const client = await this.ensureClient();
362
+ if (!src?.path) throw new Error("downloadFile: source path is required");
363
+ if (!dst?.path) throw new Error("downloadFile: destination path is required");
364
+ const stream = await client.readFile({
365
+ sandboxId: this.sandbox.id,
366
+ path: src.path,
367
+ cwd: src.cwd,
368
+ signal: opts?.signal
369
+ });
370
+ if (stream === null) return null;
371
+ try {
372
+ const dstPath = resolve(dst.cwd ?? "", dst.path);
373
+ if (opts?.mkdirRecursive) await mkdir(dirname(dstPath), { recursive: true });
374
+ await pipeline(stream, createWriteStream(dstPath), { signal: opts?.signal });
375
+ return dstPath;
376
+ } finally {
377
+ stream.destroy();
378
+ }
379
+ }
380
+ /**
381
+ * Write files to the filesystem of this sandbox.
382
+ * Defaults to writing to /vercel/sandbox unless an absolute path is specified.
383
+ * Writes files using the `vercel-sandbox` user.
384
+ *
385
+ * @param files - Array of files with path, content, and optional mode (permissions)
386
+ * @param opts - Optional parameters.
387
+ * @param opts.signal - An AbortSignal to cancel the operation.
388
+ * @returns A promise that resolves when the files are written
389
+ *
390
+ * @example
391
+ * // Write an executable script
392
+ * await sandbox.writeFiles([
393
+ * { path: "/usr/local/bin/myscript", content: "#!/bin/bash\necho hello", mode: 0o755 }
394
+ * ]);
395
+ */
396
+ async writeFiles(files, opts) {
397
+ "use step";
398
+ return (await this.ensureClient()).writeFiles({
399
+ sandboxId: this.sandbox.id,
400
+ cwd: this.sandbox.cwd,
401
+ extractDir: "/",
402
+ files,
403
+ signal: opts?.signal
404
+ });
405
+ }
406
+ /**
407
+ * Get the public domain of a port of this sandbox.
408
+ *
409
+ * @param p - Port number to resolve
410
+ * @returns A full domain (e.g. `https://subdomain.vercel.run`)
411
+ * @throws If the port has no associated route
412
+ */
413
+ domain(p) {
414
+ const route = this.routes.find(({ port }) => port == p);
415
+ if (route) return `https://${route.subdomain}.vercel.run`;
416
+ else throw new Error(`No route for port ${p}`);
417
+ }
418
+ /**
419
+ * Stop the sandbox.
420
+ *
421
+ * @param opts - Optional parameters.
422
+ * @param opts.signal - An AbortSignal to cancel the operation.
423
+ * @param opts.blocking - If true, poll until the sandbox has fully stopped and return the final state.
424
+ * @returns The sandbox metadata at the time the stop was acknowledged, or after fully stopped if `blocking` is true.
425
+ */
426
+ async stop(opts) {
427
+ "use step";
428
+ this.sandbox = toSandboxSnapshot((await (await this.ensureClient()).stopSandbox({
429
+ sandboxId: this.sandbox.id,
430
+ signal: opts?.signal,
431
+ blocking: opts?.blocking
432
+ })).json.sandbox);
433
+ return this.sandbox;
434
+ }
435
+ /**
436
+ * Update the network policy for this sandbox.
437
+ *
438
+ * @param networkPolicy - The new network policy to apply.
439
+ * @param opts - Optional parameters.
440
+ * @param opts.signal - An AbortSignal to cancel the operation.
441
+ * @returns A promise that resolves when the network policy is updated.
442
+ *
443
+ * @example
444
+ * // Restrict to specific domains
445
+ * await sandbox.updateNetworkPolicy({
446
+ * allow: ["*.npmjs.org", "github.com"],
447
+ * });
448
+ *
449
+ * @example
450
+ * // Inject credentials with per-domain transformers
451
+ * await sandbox.updateNetworkPolicy({
452
+ * allow: {
453
+ * "ai-gateway.vercel.sh": [{
454
+ * transform: [{
455
+ * headers: { authorization: "Bearer ..." }
456
+ * }]
457
+ * }],
458
+ * "*": []
459
+ * }
460
+ * });
461
+ *
462
+ * @example
463
+ * // Deny all network access
464
+ * await sandbox.updateNetworkPolicy("deny-all");
465
+ */
466
+ async updateNetworkPolicy(networkPolicy, opts) {
467
+ "use step";
468
+ this.sandbox = toSandboxSnapshot((await (await this.ensureClient()).updateNetworkPolicy({
469
+ sandboxId: this.sandbox.id,
470
+ networkPolicy,
471
+ signal: opts?.signal
472
+ })).json.sandbox);
473
+ return this.sandbox.networkPolicy;
474
+ }
475
+ /**
476
+ * Extend the timeout of the sandbox by the specified duration.
477
+ *
478
+ * This allows you to extend the lifetime of a sandbox up until the maximum
479
+ * execution timeout for your plan.
480
+ *
481
+ * @param duration - The duration in milliseconds to extend the timeout by
482
+ * @param opts - Optional parameters.
483
+ * @param opts.signal - An AbortSignal to cancel the operation.
484
+ * @returns A promise that resolves when the timeout is extended
485
+ *
486
+ * @example
487
+ * const sandbox = await Sandbox.create({ timeout: ms('10m') });
488
+ * // Extends timeout by 5 minutes, to a total of 15 minutes.
489
+ * await sandbox.extendTimeout(ms('5m'));
490
+ */
491
+ async extendTimeout(duration, opts) {
492
+ "use step";
493
+ this.sandbox = toSandboxSnapshot((await (await this.ensureClient()).extendTimeout({
494
+ sandboxId: this.sandbox.id,
495
+ duration,
496
+ signal: opts?.signal
497
+ })).json.sandbox);
498
+ }
499
+ /**
500
+ * Create a snapshot from this currently running sandbox. New sandboxes can
501
+ * then be created from this snapshot using {@link Sandbox.createFromSnapshot}.
502
+ *
503
+ * Note: this sandbox will be stopped as part of the snapshot creation process.
504
+ *
505
+ * @param opts - Optional parameters.
506
+ * @param opts.expiration - Optional expiration time in milliseconds. Use 0 for no expiration at all.
507
+ * @param opts.signal - An AbortSignal to cancel the operation.
508
+ * @returns A promise that resolves to the Snapshot instance
509
+ */
510
+ async snapshot(opts) {
511
+ "use step";
512
+ const client = await this.ensureClient();
513
+ const response = await client.createSnapshot({
514
+ sandboxId: this.sandbox.id,
515
+ expiration: opts?.expiration,
516
+ signal: opts?.signal
517
+ });
518
+ this.sandbox = toSandboxSnapshot(response.json.sandbox);
519
+ return new Snapshot({
520
+ client,
521
+ snapshot: response.json.snapshot
522
+ });
523
+ }
524
+ };
501
525
  /**
502
- * A {@link Sandbox} that can automatically be disposed using a `await using` statement.
503
- *
504
- * @example
505
- * {
506
- * await using const sandbox = await Sandbox.create();
507
- * }
508
- * // Sandbox is automatically stopped here
509
- */
510
- class DisposableSandbox extends Sandbox {
511
- async [Symbol.asyncDispose]() {
512
- await this.stop();
513
- }
514
- }
526
+ * A {@link Sandbox} that can automatically be disposed using a `await using` statement.
527
+ *
528
+ * @example
529
+ * {
530
+ * await using const sandbox = await Sandbox.create();
531
+ * }
532
+ * // Sandbox is automatically stopped here
533
+ */
534
+ var DisposableSandbox = class extends Sandbox {
535
+ async [Symbol.asyncDispose]() {
536
+ await this.stop();
537
+ }
538
+ };
539
+
540
+ //#endregion
541
+ export { Sandbox };
515
542
  //# sourceMappingURL=sandbox.js.map