sandbox 2.1.0 → 2.2.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/README.md +6 -4
- package/dist/{app-DtmaeGtx.mjs → app-BNIol84k.mjs} +233 -230
- package/dist/app-BNIol84k.mjs.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/pty-server-linux-x86_64 +0 -0
- package/dist/sandbox.mjs +12 -2
- package/dist/sandbox.mjs.map +1 -1
- package/package.json +10 -4
- package/dist/app-DtmaeGtx.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Vercel Sandbox CLI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Read the full documentation at [vercel.com/docs/vercel-sandbox/cli-reference](https://vercel.com/docs/vercel-sandbox/cli-reference).
|
|
3
|
+
Vercel Sandbox allows you to run arbitrary code in isolated, ephemeral Linux
|
|
4
|
+
VMs. View the documentation [here](https://vercel.com/docs/vercel-sandbox).
|
|
6
5
|
|
|
7
6
|
## Packages
|
|
8
7
|
|
|
@@ -18,7 +17,10 @@ pnpm i -g sandbox
|
|
|
18
17
|
## Usage
|
|
19
18
|
|
|
20
19
|
```bash
|
|
21
|
-
sandbox
|
|
20
|
+
sandbox login # If you are not already logged in with the Vercel CLI
|
|
21
|
+
sandbox create --connect # Create a new sandbox and open an interactive shell
|
|
22
22
|
sandbox ls # List your sandboxes
|
|
23
23
|
sandbox --help # View all commands
|
|
24
24
|
```
|
|
25
|
+
|
|
26
|
+
Learn more about the CLI in the [documentation](https://vercel.com/docs/vercel-sandbox/cli-reference).
|
|
@@ -7046,7 +7046,7 @@ const token = import_cjs$18.option({
|
|
|
7046
7046
|
if (!auth || !auth.token) throw new Error([
|
|
7047
7047
|
`Failed to retrieve authentication token.`,
|
|
7048
7048
|
`${source_default.bold("hint:")} Try logging in again with \`sandbox login\`.`,
|
|
7049
|
-
"╰▶ Docs: https://vercel.com/docs/sandbox"
|
|
7049
|
+
"╰▶ Docs: https://vercel.com/docs/vercel-sandbox/cli-reference#authentication"
|
|
7050
7050
|
].join("\n"));
|
|
7051
7051
|
return auth.token;
|
|
7052
7052
|
}
|
|
@@ -7292,7 +7292,7 @@ const scope = {
|
|
|
7292
7292
|
|
|
7293
7293
|
//#endregion
|
|
7294
7294
|
//#region package.json
|
|
7295
|
-
var version = "2.
|
|
7295
|
+
var version = "2.2.0";
|
|
7296
7296
|
|
|
7297
7297
|
//#endregion
|
|
7298
7298
|
//#region src/error.ts
|
|
@@ -7354,12 +7354,13 @@ async function handleApiError(error) {
|
|
|
7354
7354
|
const tmpPath = await writeResponseToTemp(error);
|
|
7355
7355
|
const status = error.response.status;
|
|
7356
7356
|
throw new StyledError([
|
|
7357
|
-
getErrorMessage(status),
|
|
7357
|
+
ApiErrorResponse.safeParse(error.json).data?.error.message ?? getErrorMessage(status),
|
|
7358
7358
|
`├▶ requested url: ${error.response.url}`,
|
|
7359
7359
|
`├▶ status code: ${status} ${error.response.statusText}`,
|
|
7360
7360
|
`╰▶ ${source_default.bold("hint:")} the full response buffer is stored in ${source_default.italic(tmpPath)}`
|
|
7361
7361
|
].join("\n"), error);
|
|
7362
7362
|
}
|
|
7363
|
+
const ApiErrorResponse = z$1.object({ error: z$1.object({ message: z$1.string() }) });
|
|
7363
7364
|
function getErrorMessage(status) {
|
|
7364
7365
|
if (status === 401 || status === 403) return "Sandbox API request failed due to authentication. Check your token or run `sandbox login`.";
|
|
7365
7366
|
if (status === 404) return "Sandbox API request failed: resource not found.";
|
|
@@ -7392,190 +7393,11 @@ const snapshotId = import_cjs$16.extendType(import_cjs$16.string, {
|
|
|
7392
7393
|
}
|
|
7393
7394
|
});
|
|
7394
7395
|
|
|
7395
|
-
//#endregion
|
|
7396
|
-
//#region src/args/network-policy.ts
|
|
7397
|
-
var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
|
|
7398
|
-
init_source();
|
|
7399
|
-
const networkPolicyMode = import_cjs$15.extendType(import_cjs$15.string, {
|
|
7400
|
-
displayName: "MODE",
|
|
7401
|
-
async from(value) {
|
|
7402
|
-
const validModes = [
|
|
7403
|
-
"internet-access",
|
|
7404
|
-
"no-access",
|
|
7405
|
-
"restricted"
|
|
7406
|
-
];
|
|
7407
|
-
if (!validModes.includes(value)) throw new Error([`Invalid network policy mode: ${value}.`, `${source_default.bold("hint:")} Valid modes are: ${validModes.join(", ")}`].join("\n"));
|
|
7408
|
-
return value;
|
|
7409
|
-
}
|
|
7410
|
-
});
|
|
7411
|
-
const networkPolicy = import_cjs$15.option({
|
|
7412
|
-
long: "network-policy",
|
|
7413
|
-
description: `Network policy mode: "internet-access", "no-access", or "restricted"
|
|
7414
|
-
|
|
7415
|
-
internet-access: sandbox can access any website/domain
|
|
7416
|
-
no-access: sandbox has no network access
|
|
7417
|
-
restricted: sandbox can only access websites and domains explicitly allowed`,
|
|
7418
|
-
type: import_cjs$15.optional(networkPolicyMode)
|
|
7419
|
-
});
|
|
7420
|
-
const allowedDomains = import_cjs$15.multioption({
|
|
7421
|
-
long: "allowed-domain",
|
|
7422
|
-
description: `Domain to allow traffic to (requires --network-policy=restricted)
|
|
7423
|
-
|
|
7424
|
-
Supports "*" for wildcards for a segment (e.g. '*.vercel.com', 'www.*.com')
|
|
7425
|
-
If used as the first segment, will match any subdomain.`,
|
|
7426
|
-
type: import_cjs$15.array(import_cjs$15.string)
|
|
7427
|
-
});
|
|
7428
|
-
const allowedCIDRs = import_cjs$15.multioption({
|
|
7429
|
-
long: "allowed-cidr",
|
|
7430
|
-
description: `CIDR to allow traffic to (requires --network-policy=restricted)
|
|
7431
|
-
|
|
7432
|
-
Takes precedence over 'allowed-domain'.
|
|
7433
|
-
`,
|
|
7434
|
-
type: import_cjs$15.array(import_cjs$15.string)
|
|
7435
|
-
});
|
|
7436
|
-
const deniedCIDRs = import_cjs$15.multioption({
|
|
7437
|
-
long: "denied-cidr",
|
|
7438
|
-
description: `CIDR to deny traffic to (requires --network-policy=restricted)
|
|
7439
|
-
|
|
7440
|
-
Takes precedence over allowed domains/CIDRs.`,
|
|
7441
|
-
type: import_cjs$15.array(import_cjs$15.string)
|
|
7442
|
-
});
|
|
7443
|
-
const networkPolicyArgs = {
|
|
7444
|
-
networkPolicy,
|
|
7445
|
-
allowedDomains,
|
|
7446
|
-
allowedCIDRs,
|
|
7447
|
-
deniedCIDRs
|
|
7448
|
-
};
|
|
7449
|
-
|
|
7450
|
-
//#endregion
|
|
7451
|
-
//#region src/util/network-policy.ts
|
|
7452
|
-
init_source();
|
|
7453
|
-
/**
|
|
7454
|
-
* Builds a NetworkPolicy from CLI arguments (optional mode for create).
|
|
7455
|
-
*/
|
|
7456
|
-
function buildNetworkPolicy(args$4) {
|
|
7457
|
-
const { networkPolicy: networkPolicy$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 } = args$4;
|
|
7458
|
-
if (!networkPolicy$1 || networkPolicy$1 !== "restricted") {
|
|
7459
|
-
if (allowedDomains$1.length > 0 || allowedCIDRs$1.length > 0 || deniedCIDRs$1.length > 0) throw new Error(["Network policy options require --network-policy to be set to restricted.", `${source_default.bold("hint:")} Use --network-policy=restricted to allow/deny specific domains or CIDRs.`].join("\n"));
|
|
7460
|
-
}
|
|
7461
|
-
switch (networkPolicy$1) {
|
|
7462
|
-
case void 0:
|
|
7463
|
-
case "internet-access": return { type: "internet-access" };
|
|
7464
|
-
case "no-access": return { type: "no-access" };
|
|
7465
|
-
case "restricted": return {
|
|
7466
|
-
type: "restricted",
|
|
7467
|
-
allowedDomains: allowedDomains$1.length > 0 ? allowedDomains$1 : void 0,
|
|
7468
|
-
allowedCIDRs: allowedCIDRs$1.length > 0 ? allowedCIDRs$1 : void 0,
|
|
7469
|
-
deniedCIDRs: deniedCIDRs$1.length > 0 ? deniedCIDRs$1 : void 0
|
|
7470
|
-
};
|
|
7471
|
-
}
|
|
7472
|
-
}
|
|
7473
|
-
|
|
7474
|
-
//#endregion
|
|
7475
|
-
//#region src/commands/create.ts
|
|
7476
|
-
var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
|
|
7477
|
-
var import_ms$1 = /* @__PURE__ */ __toESM(require_ms());
|
|
7478
|
-
init_source();
|
|
7479
|
-
const args$3 = {
|
|
7480
|
-
scope,
|
|
7481
|
-
runtime,
|
|
7482
|
-
timeout,
|
|
7483
|
-
ports: import_cjs$14.multioption({
|
|
7484
|
-
long: "publish-port",
|
|
7485
|
-
short: "p",
|
|
7486
|
-
description: "Publish sandbox port(s) to DOMAIN.vercel.run",
|
|
7487
|
-
type: import_cjs$14.array(import_cjs$14.extendType(import_cjs$14.number, {
|
|
7488
|
-
displayName: "PORT",
|
|
7489
|
-
async from(number) {
|
|
7490
|
-
if (number < 1024 || number > 65535) throw new Error([
|
|
7491
|
-
`Invalid port: ${number}.`,
|
|
7492
|
-
`${source_default.bold("hint:")} Ports must be between 1024-65535 (privileged ports 0-1023 are reserved).`,
|
|
7493
|
-
"╰▶ Examples: 3000, 8080, 8443"
|
|
7494
|
-
].join("\n"));
|
|
7495
|
-
return number;
|
|
7496
|
-
}
|
|
7497
|
-
}))
|
|
7498
|
-
}),
|
|
7499
|
-
silent: import_cjs$14.flag({
|
|
7500
|
-
long: "silent",
|
|
7501
|
-
description: "Don't write sandbox ID to stdout"
|
|
7502
|
-
}),
|
|
7503
|
-
snapshot: import_cjs$14.option({
|
|
7504
|
-
long: "snapshot",
|
|
7505
|
-
short: "s",
|
|
7506
|
-
description: "Start the sandbox from a snapshot ID",
|
|
7507
|
-
type: import_cjs$14.optional(snapshotId)
|
|
7508
|
-
}),
|
|
7509
|
-
...networkPolicyArgs
|
|
7510
|
-
};
|
|
7511
|
-
const create = import_cjs$14.command({
|
|
7512
|
-
name: "create",
|
|
7513
|
-
description: "Create a sandbox in the specified account and project.",
|
|
7514
|
-
args: args$3,
|
|
7515
|
-
async handler({ ports, scope: scope$1, runtime: runtime$1, timeout: timeout$1, silent, snapshot: snapshot$1, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
|
|
7516
|
-
const networkPolicy$1 = buildNetworkPolicy({
|
|
7517
|
-
networkPolicy: networkPolicyMode$1,
|
|
7518
|
-
allowedDomains: allowedDomains$1,
|
|
7519
|
-
allowedCIDRs: allowedCIDRs$1,
|
|
7520
|
-
deniedCIDRs: deniedCIDRs$1
|
|
7521
|
-
});
|
|
7522
|
-
const spinner = silent ? void 0 : ora("Creating sandbox...").start();
|
|
7523
|
-
const sandbox = snapshot$1 ? await sandboxClient.create({
|
|
7524
|
-
source: {
|
|
7525
|
-
type: "snapshot",
|
|
7526
|
-
snapshotId: snapshot$1
|
|
7527
|
-
},
|
|
7528
|
-
teamId: scope$1.team,
|
|
7529
|
-
projectId: scope$1.project,
|
|
7530
|
-
token: scope$1.token,
|
|
7531
|
-
ports,
|
|
7532
|
-
timeout: (0, import_ms$1.default)(timeout$1),
|
|
7533
|
-
networkPolicy: networkPolicy$1,
|
|
7534
|
-
__interactive: true
|
|
7535
|
-
}) : await sandboxClient.create({
|
|
7536
|
-
teamId: scope$1.team,
|
|
7537
|
-
projectId: scope$1.project,
|
|
7538
|
-
token: scope$1.token,
|
|
7539
|
-
ports,
|
|
7540
|
-
runtime: runtime$1,
|
|
7541
|
-
timeout: (0, import_ms$1.default)(timeout$1),
|
|
7542
|
-
networkPolicy: networkPolicy$1,
|
|
7543
|
-
__interactive: true
|
|
7544
|
-
});
|
|
7545
|
-
spinner?.stop();
|
|
7546
|
-
if (!sandbox.interactivePort) throw new Error([
|
|
7547
|
-
`Sandbox created but interactive port is missing.`,
|
|
7548
|
-
`${source_default.bold("hint:")} This is an internal error. Please try again.`,
|
|
7549
|
-
"╰▶ Report this issue: https://github.com/vercel/sandbox/issues"
|
|
7550
|
-
].join("\n"));
|
|
7551
|
-
const routes = sandbox.routes.filter((x) => x.port !== sandbox.interactivePort);
|
|
7552
|
-
if (!silent) {
|
|
7553
|
-
const teamDisplay = scope$1.teamSlug ?? scope$1.team;
|
|
7554
|
-
const projectDisplay = scope$1.projectSlug ?? scope$1.project;
|
|
7555
|
-
const hasPorts = routes.length > 0;
|
|
7556
|
-
process.stderr.write("✅ Sandbox ");
|
|
7557
|
-
process.stdout.write(source_default.cyan(sandbox.sandboxId));
|
|
7558
|
-
process.stderr.write(" created.\n");
|
|
7559
|
-
process.stderr.write(source_default.dim(" │ ") + "team: " + source_default.cyan(teamDisplay) + "\n");
|
|
7560
|
-
if (hasPorts) {
|
|
7561
|
-
process.stderr.write(source_default.dim(" │ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
|
|
7562
|
-
process.stderr.write(source_default.dim(" │ ") + "ports:\n");
|
|
7563
|
-
for (let i = 0; i < routes.length; i++) {
|
|
7564
|
-
const route = routes[i];
|
|
7565
|
-
const prefix$1 = i === routes.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
|
|
7566
|
-
process.stderr.write(prefix$1 + "• " + route.port + " -> " + source_default.cyan(route.url) + "\n");
|
|
7567
|
-
}
|
|
7568
|
-
} else process.stderr.write(source_default.dim(" ╰ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
|
|
7569
|
-
}
|
|
7570
|
-
return sandbox;
|
|
7571
|
-
}
|
|
7572
|
-
});
|
|
7573
|
-
|
|
7574
7396
|
//#endregion
|
|
7575
7397
|
//#region src/args/sandbox-id.ts
|
|
7576
|
-
var import_cjs$
|
|
7398
|
+
var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
|
|
7577
7399
|
init_source();
|
|
7578
|
-
const sandboxId = import_cjs$
|
|
7400
|
+
const sandboxId = import_cjs$15.extendType(import_cjs$15.string, {
|
|
7579
7401
|
displayName: "sandbox_id",
|
|
7580
7402
|
description: "The ID of the sandbox to execute the command in",
|
|
7581
7403
|
async from(s$1) {
|
|
@@ -11289,9 +11111,9 @@ function printCommand(command$1, args$4) {
|
|
|
11289
11111
|
|
|
11290
11112
|
//#endregion
|
|
11291
11113
|
//#region src/interactive-shell/extend-sandbox-timeout.ts
|
|
11292
|
-
var import_ms = /* @__PURE__ */ __toESM(require_ms());
|
|
11114
|
+
var import_ms$1 = /* @__PURE__ */ __toESM(require_ms());
|
|
11293
11115
|
const debug$2 = createDebugger("sandbox:timeout");
|
|
11294
|
-
const BUFFER = (0, import_ms.default)("10 seconds");
|
|
11116
|
+
const BUFFER = (0, import_ms$1.default)("10 seconds");
|
|
11295
11117
|
async function extendSandboxTimeoutPeriodically(sandbox, signal) {
|
|
11296
11118
|
const nextTick = sandbox.createdAt.getTime() + sandbox.timeout;
|
|
11297
11119
|
debug$2(`next tick: ${new Date(nextTick).toISOString()}`);
|
|
@@ -11301,7 +11123,7 @@ async function extendSandboxTimeoutPeriodically(sandbox, signal) {
|
|
|
11301
11123
|
debug$2(`sleeping for ${timeout$1}ms until next timeout extension`);
|
|
11302
11124
|
await setTimeout$1(timeout$1, null, { signal });
|
|
11303
11125
|
}
|
|
11304
|
-
await sandbox.extendTimeout((0, import_ms.default)("5 minutes"));
|
|
11126
|
+
await sandbox.extendTimeout((0, import_ms$1.default)("5 minutes"));
|
|
11305
11127
|
const nextTick$1 = sandbox.createdAt.getTime() + sandbox.timeout;
|
|
11306
11128
|
debug$2(`extended sandbox timeout by 5 minutes. next tick: ${new Date(nextTick$1).toISOString()}`);
|
|
11307
11129
|
}
|
|
@@ -11434,7 +11256,7 @@ async function startInteractiveShell(options) {
|
|
|
11434
11256
|
listener.connection.then(() => {
|
|
11435
11257
|
waitForProcess.abort();
|
|
11436
11258
|
});
|
|
11437
|
-
connect(command$1, listener, waitForProcess.signal).catch(waitForProcess.ignoreInterruptions);
|
|
11259
|
+
connect$1(command$1, listener, waitForProcess.signal).catch(waitForProcess.ignoreInterruptions);
|
|
11438
11260
|
await Promise.all([throwIfCommandPrematurelyExited(command$1, waitForProcess.signal), attach({
|
|
11439
11261
|
sandbox: options.sandbox,
|
|
11440
11262
|
progress,
|
|
@@ -11530,7 +11352,7 @@ async function* messageReader(stream) {
|
|
|
11530
11352
|
/**
|
|
11531
11353
|
* Connects the command's logs to the listener's stdout and stderr streams.
|
|
11532
11354
|
*/
|
|
11533
|
-
async function connect(command$1, listener, signal) {
|
|
11355
|
+
async function connect$1(command$1, listener, signal) {
|
|
11534
11356
|
try {
|
|
11535
11357
|
var _usingCtx5 = _usingCtx();
|
|
11536
11358
|
const logs = _usingCtx5.u(command$1.logs({ signal }));
|
|
@@ -11567,9 +11389,9 @@ function getStderrStream() {
|
|
|
11567
11389
|
|
|
11568
11390
|
//#endregion
|
|
11569
11391
|
//#region src/args/key-value-pair.ts
|
|
11570
|
-
var import_cjs$
|
|
11392
|
+
var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
|
|
11571
11393
|
init_source();
|
|
11572
|
-
const KeyValuePair = import_cjs$
|
|
11394
|
+
const KeyValuePair = import_cjs$14.extendType(import_cjs$14.string, {
|
|
11573
11395
|
displayName: "key=value",
|
|
11574
11396
|
async from(input) {
|
|
11575
11397
|
if (!input.includes("=")) return {
|
|
@@ -11583,7 +11405,7 @@ const KeyValuePair = import_cjs$12.extendType(import_cjs$12.string, {
|
|
|
11583
11405
|
};
|
|
11584
11406
|
}
|
|
11585
11407
|
});
|
|
11586
|
-
const ObjectFromKeyValue = import_cjs$
|
|
11408
|
+
const ObjectFromKeyValue = import_cjs$14.extendType(import_cjs$14.array(KeyValuePair), { async from(input) {
|
|
11587
11409
|
const obj = Object.create(null);
|
|
11588
11410
|
const missingVars = [];
|
|
11589
11411
|
for (const { key, value } of input) if (value === void 0) missingVars.push(key);
|
|
@@ -11597,34 +11419,34 @@ const ObjectFromKeyValue = import_cjs$12.extendType(import_cjs$12.array(KeyValue
|
|
|
11597
11419
|
|
|
11598
11420
|
//#endregion
|
|
11599
11421
|
//#region src/commands/exec.ts
|
|
11600
|
-
var import_cjs$
|
|
11422
|
+
var import_cjs$13 = /* @__PURE__ */ __toESM(require_cjs());
|
|
11601
11423
|
init_source();
|
|
11602
|
-
const args$
|
|
11424
|
+
const args$3 = {
|
|
11603
11425
|
scope,
|
|
11604
|
-
sandbox: import_cjs$
|
|
11605
|
-
asSudo: import_cjs$
|
|
11426
|
+
sandbox: import_cjs$13.positional({ type: sandboxId }),
|
|
11427
|
+
asSudo: import_cjs$13.flag({
|
|
11606
11428
|
long: "sudo",
|
|
11607
11429
|
description: "Give extended privileges to the command."
|
|
11608
11430
|
}),
|
|
11609
|
-
command: import_cjs$
|
|
11431
|
+
command: import_cjs$13.positional({
|
|
11610
11432
|
displayName: "command",
|
|
11611
11433
|
description: "The executable to invoke"
|
|
11612
11434
|
}),
|
|
11613
|
-
args: import_cjs$
|
|
11435
|
+
args: import_cjs$13.rest({
|
|
11614
11436
|
displayName: "args",
|
|
11615
11437
|
description: "arguments to pass to the command"
|
|
11616
11438
|
}),
|
|
11617
|
-
cwd: import_cjs$
|
|
11439
|
+
cwd: import_cjs$13.option({
|
|
11618
11440
|
long: "workdir",
|
|
11619
11441
|
short: "w",
|
|
11620
11442
|
description: "The working directory to run the command in",
|
|
11621
|
-
type: import_cjs$
|
|
11443
|
+
type: import_cjs$13.optional(import_cjs$13.string)
|
|
11622
11444
|
}),
|
|
11623
|
-
interactive: import_cjs$
|
|
11445
|
+
interactive: import_cjs$13.flag({
|
|
11624
11446
|
long: "interactive",
|
|
11625
11447
|
short: "i",
|
|
11626
11448
|
description: "Run the command in a secure interactive shell",
|
|
11627
|
-
type: import_cjs$
|
|
11449
|
+
type: import_cjs$13.extendType(import_cjs$13.boolean, {
|
|
11628
11450
|
defaultValue() {
|
|
11629
11451
|
return false;
|
|
11630
11452
|
},
|
|
@@ -11634,26 +11456,26 @@ const args$2 = {
|
|
|
11634
11456
|
}
|
|
11635
11457
|
})
|
|
11636
11458
|
}),
|
|
11637
|
-
skipExtendingTimeout: import_cjs$
|
|
11459
|
+
skipExtendingTimeout: import_cjs$13.flag({
|
|
11638
11460
|
long: "no-extend-timeout",
|
|
11639
11461
|
description: "Do not extend the sandbox timeout while running an interactive command. Only affects interactive executions."
|
|
11640
11462
|
}),
|
|
11641
|
-
envVars: import_cjs$
|
|
11463
|
+
envVars: import_cjs$13.multioption({
|
|
11642
11464
|
long: "env",
|
|
11643
11465
|
short: "e",
|
|
11644
11466
|
type: ObjectFromKeyValue,
|
|
11645
11467
|
description: "Environment variables to set for the command"
|
|
11646
11468
|
}),
|
|
11647
|
-
tty: import_cjs$
|
|
11469
|
+
tty: import_cjs$13.flag({
|
|
11648
11470
|
long: "tty",
|
|
11649
11471
|
short: "t",
|
|
11650
11472
|
description: "Allocate a tty for an interactive command. This is a no-op."
|
|
11651
11473
|
})
|
|
11652
11474
|
};
|
|
11653
|
-
const exec = import_cjs$
|
|
11475
|
+
const exec = import_cjs$13.command({
|
|
11654
11476
|
name: "exec",
|
|
11655
11477
|
description: "Execute a command in an existing sandbox",
|
|
11656
|
-
args: args$
|
|
11478
|
+
args: args$3,
|
|
11657
11479
|
async handler({ command: command$1, cwd, args: args$4, asSudo, sandbox: sandboxId$1, scope: { token: token$1, team: team$1, project: project$1 }, interactive, envVars, skipExtendingTimeout }) {
|
|
11658
11480
|
const sandbox = typeof sandboxId$1 !== "string" ? sandboxId$1 : await sandboxClient.get({
|
|
11659
11481
|
sandboxId: sandboxId$1,
|
|
@@ -11695,6 +11517,201 @@ const exec = import_cjs$11.command({
|
|
|
11695
11517
|
}
|
|
11696
11518
|
});
|
|
11697
11519
|
|
|
11520
|
+
//#endregion
|
|
11521
|
+
//#region src/args/network-policy.ts
|
|
11522
|
+
var import_cjs$12 = /* @__PURE__ */ __toESM(require_cjs());
|
|
11523
|
+
init_source();
|
|
11524
|
+
const networkPolicyMode = import_cjs$12.extendType(import_cjs$12.string, {
|
|
11525
|
+
displayName: "MODE",
|
|
11526
|
+
async from(value) {
|
|
11527
|
+
const validModes = [
|
|
11528
|
+
"internet-access",
|
|
11529
|
+
"no-access",
|
|
11530
|
+
"restricted"
|
|
11531
|
+
];
|
|
11532
|
+
if (!validModes.includes(value)) throw new Error([`Invalid network policy mode: ${value}.`, `${source_default.bold("hint:")} Valid modes are: ${validModes.join(", ")}`].join("\n"));
|
|
11533
|
+
return value;
|
|
11534
|
+
}
|
|
11535
|
+
});
|
|
11536
|
+
const networkPolicy = import_cjs$12.option({
|
|
11537
|
+
long: "network-policy",
|
|
11538
|
+
description: `Network policy mode: "internet-access", "no-access", or "restricted"
|
|
11539
|
+
|
|
11540
|
+
internet-access: sandbox can access any website/domain
|
|
11541
|
+
no-access: sandbox has no network access
|
|
11542
|
+
restricted: sandbox can only access websites and domains explicitly allowed`,
|
|
11543
|
+
type: import_cjs$12.optional(networkPolicyMode)
|
|
11544
|
+
});
|
|
11545
|
+
const allowedDomains = import_cjs$12.multioption({
|
|
11546
|
+
long: "allowed-domain",
|
|
11547
|
+
description: `Domain to allow traffic to (requires --network-policy=restricted)
|
|
11548
|
+
|
|
11549
|
+
Supports "*" for wildcards for a segment (e.g. '*.vercel.com', 'www.*.com')
|
|
11550
|
+
If used as the first segment, will match any subdomain.`,
|
|
11551
|
+
type: import_cjs$12.array(import_cjs$12.string)
|
|
11552
|
+
});
|
|
11553
|
+
const allowedCIDRs = import_cjs$12.multioption({
|
|
11554
|
+
long: "allowed-cidr",
|
|
11555
|
+
description: `CIDR to allow traffic to (requires --network-policy=restricted)
|
|
11556
|
+
|
|
11557
|
+
Takes precedence over 'allowed-domain'.
|
|
11558
|
+
`,
|
|
11559
|
+
type: import_cjs$12.array(import_cjs$12.string)
|
|
11560
|
+
});
|
|
11561
|
+
const deniedCIDRs = import_cjs$12.multioption({
|
|
11562
|
+
long: "denied-cidr",
|
|
11563
|
+
description: `CIDR to deny traffic to (requires --network-policy=restricted)
|
|
11564
|
+
|
|
11565
|
+
Takes precedence over allowed domains/CIDRs.`,
|
|
11566
|
+
type: import_cjs$12.array(import_cjs$12.string)
|
|
11567
|
+
});
|
|
11568
|
+
const networkPolicyArgs = {
|
|
11569
|
+
networkPolicy,
|
|
11570
|
+
allowedDomains,
|
|
11571
|
+
allowedCIDRs,
|
|
11572
|
+
deniedCIDRs
|
|
11573
|
+
};
|
|
11574
|
+
|
|
11575
|
+
//#endregion
|
|
11576
|
+
//#region src/util/network-policy.ts
|
|
11577
|
+
init_source();
|
|
11578
|
+
/**
|
|
11579
|
+
* Builds a NetworkPolicy from CLI arguments (optional mode for create).
|
|
11580
|
+
*/
|
|
11581
|
+
function buildNetworkPolicy(args$4) {
|
|
11582
|
+
const { networkPolicy: networkPolicy$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 } = args$4;
|
|
11583
|
+
if (!networkPolicy$1 || networkPolicy$1 !== "restricted") {
|
|
11584
|
+
if (allowedDomains$1.length > 0 || allowedCIDRs$1.length > 0 || deniedCIDRs$1.length > 0) throw new Error(["Network policy options require --network-policy to be set to restricted.", `${source_default.bold("hint:")} Use --network-policy=restricted to allow/deny specific domains or CIDRs.`].join("\n"));
|
|
11585
|
+
}
|
|
11586
|
+
switch (networkPolicy$1) {
|
|
11587
|
+
case void 0:
|
|
11588
|
+
case "internet-access": return { type: "internet-access" };
|
|
11589
|
+
case "no-access": return { type: "no-access" };
|
|
11590
|
+
case "restricted": return {
|
|
11591
|
+
type: "restricted",
|
|
11592
|
+
allowedDomains: allowedDomains$1.length > 0 ? allowedDomains$1 : void 0,
|
|
11593
|
+
allowedCIDRs: allowedCIDRs$1.length > 0 ? allowedCIDRs$1 : void 0,
|
|
11594
|
+
deniedCIDRs: deniedCIDRs$1.length > 0 ? deniedCIDRs$1 : void 0
|
|
11595
|
+
};
|
|
11596
|
+
}
|
|
11597
|
+
}
|
|
11598
|
+
|
|
11599
|
+
//#endregion
|
|
11600
|
+
//#region src/commands/create.ts
|
|
11601
|
+
var import_cjs$11 = /* @__PURE__ */ __toESM(require_cjs());
|
|
11602
|
+
var import_ms = /* @__PURE__ */ __toESM(require_ms());
|
|
11603
|
+
init_source();
|
|
11604
|
+
const args$2 = {
|
|
11605
|
+
scope,
|
|
11606
|
+
runtime,
|
|
11607
|
+
timeout,
|
|
11608
|
+
ports: import_cjs$11.multioption({
|
|
11609
|
+
long: "publish-port",
|
|
11610
|
+
short: "p",
|
|
11611
|
+
description: "Publish sandbox port(s) to DOMAIN.vercel.run",
|
|
11612
|
+
type: import_cjs$11.array(import_cjs$11.extendType(import_cjs$11.number, {
|
|
11613
|
+
displayName: "PORT",
|
|
11614
|
+
async from(number) {
|
|
11615
|
+
if (number < 1024 || number > 65535) throw new Error([
|
|
11616
|
+
`Invalid port: ${number}.`,
|
|
11617
|
+
`${source_default.bold("hint:")} Ports must be between 1024-65535 (privileged ports 0-1023 are reserved).`,
|
|
11618
|
+
"╰▶ Examples: 3000, 8080, 8443"
|
|
11619
|
+
].join("\n"));
|
|
11620
|
+
return number;
|
|
11621
|
+
}
|
|
11622
|
+
}))
|
|
11623
|
+
}),
|
|
11624
|
+
silent: import_cjs$11.flag({
|
|
11625
|
+
long: "silent",
|
|
11626
|
+
description: "Don't write sandbox ID to stdout"
|
|
11627
|
+
}),
|
|
11628
|
+
snapshot: import_cjs$11.option({
|
|
11629
|
+
long: "snapshot",
|
|
11630
|
+
short: "s",
|
|
11631
|
+
description: "Start the sandbox from a snapshot ID",
|
|
11632
|
+
type: import_cjs$11.optional(snapshotId)
|
|
11633
|
+
}),
|
|
11634
|
+
connect: import_cjs$11.flag({
|
|
11635
|
+
long: "connect",
|
|
11636
|
+
description: "Start an interactive shell session after creating the sandbox"
|
|
11637
|
+
}),
|
|
11638
|
+
...networkPolicyArgs
|
|
11639
|
+
};
|
|
11640
|
+
const create = import_cjs$11.command({
|
|
11641
|
+
name: "create",
|
|
11642
|
+
description: "Create a sandbox in the specified account and project.",
|
|
11643
|
+
args: args$2,
|
|
11644
|
+
async handler({ ports, scope: scope$1, runtime: runtime$1, timeout: timeout$1, silent, snapshot: snapshot$1, connect: connect$2, networkPolicy: networkPolicyMode$1, allowedDomains: allowedDomains$1, allowedCIDRs: allowedCIDRs$1, deniedCIDRs: deniedCIDRs$1 }) {
|
|
11645
|
+
const networkPolicy$1 = buildNetworkPolicy({
|
|
11646
|
+
networkPolicy: networkPolicyMode$1,
|
|
11647
|
+
allowedDomains: allowedDomains$1,
|
|
11648
|
+
allowedCIDRs: allowedCIDRs$1,
|
|
11649
|
+
deniedCIDRs: deniedCIDRs$1
|
|
11650
|
+
});
|
|
11651
|
+
const spinner = silent ? void 0 : ora("Creating sandbox...").start();
|
|
11652
|
+
const sandbox = snapshot$1 ? await sandboxClient.create({
|
|
11653
|
+
source: {
|
|
11654
|
+
type: "snapshot",
|
|
11655
|
+
snapshotId: snapshot$1
|
|
11656
|
+
},
|
|
11657
|
+
teamId: scope$1.team,
|
|
11658
|
+
projectId: scope$1.project,
|
|
11659
|
+
token: scope$1.token,
|
|
11660
|
+
ports,
|
|
11661
|
+
timeout: (0, import_ms.default)(timeout$1),
|
|
11662
|
+
networkPolicy: networkPolicy$1,
|
|
11663
|
+
__interactive: true
|
|
11664
|
+
}) : await sandboxClient.create({
|
|
11665
|
+
teamId: scope$1.team,
|
|
11666
|
+
projectId: scope$1.project,
|
|
11667
|
+
token: scope$1.token,
|
|
11668
|
+
ports,
|
|
11669
|
+
runtime: runtime$1,
|
|
11670
|
+
timeout: (0, import_ms.default)(timeout$1),
|
|
11671
|
+
networkPolicy: networkPolicy$1,
|
|
11672
|
+
__interactive: true
|
|
11673
|
+
});
|
|
11674
|
+
spinner?.stop();
|
|
11675
|
+
if (!sandbox.interactivePort) throw new Error([
|
|
11676
|
+
`Sandbox created but interactive port is missing.`,
|
|
11677
|
+
`${source_default.bold("hint:")} This is an internal error. Please try again.`,
|
|
11678
|
+
"╰▶ Report this issue: https://github.com/vercel/sandbox/issues"
|
|
11679
|
+
].join("\n"));
|
|
11680
|
+
const routes = sandbox.routes.filter((x) => x.port !== sandbox.interactivePort);
|
|
11681
|
+
if (!silent) {
|
|
11682
|
+
const teamDisplay = scope$1.teamSlug ?? scope$1.team;
|
|
11683
|
+
const projectDisplay = scope$1.projectSlug ?? scope$1.project;
|
|
11684
|
+
const hasPorts = routes.length > 0;
|
|
11685
|
+
process.stderr.write("✅ Sandbox ");
|
|
11686
|
+
process.stdout.write(source_default.cyan(sandbox.sandboxId));
|
|
11687
|
+
process.stderr.write(" created.\n");
|
|
11688
|
+
process.stderr.write(source_default.dim(" │ ") + "team: " + source_default.cyan(teamDisplay) + "\n");
|
|
11689
|
+
if (hasPorts) {
|
|
11690
|
+
process.stderr.write(source_default.dim(" │ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
|
|
11691
|
+
process.stderr.write(source_default.dim(" │ ") + "ports:\n");
|
|
11692
|
+
for (let i = 0; i < routes.length; i++) {
|
|
11693
|
+
const route = routes[i];
|
|
11694
|
+
const prefix$1 = i === routes.length - 1 ? source_default.dim(" ╰ ") : source_default.dim(" │ ");
|
|
11695
|
+
process.stderr.write(prefix$1 + "• " + route.port + " -> " + source_default.cyan(route.url) + "\n");
|
|
11696
|
+
}
|
|
11697
|
+
} else process.stderr.write(source_default.dim(" ╰ ") + "project: " + source_default.cyan(projectDisplay) + "\n");
|
|
11698
|
+
}
|
|
11699
|
+
if (connect$2) await exec.handler({
|
|
11700
|
+
scope: scope$1,
|
|
11701
|
+
asSudo: false,
|
|
11702
|
+
args: [],
|
|
11703
|
+
cwd: void 0,
|
|
11704
|
+
skipExtendingTimeout: false,
|
|
11705
|
+
envVars: {},
|
|
11706
|
+
command: "sh",
|
|
11707
|
+
interactive: true,
|
|
11708
|
+
tty: true,
|
|
11709
|
+
sandbox
|
|
11710
|
+
});
|
|
11711
|
+
return sandbox;
|
|
11712
|
+
}
|
|
11713
|
+
});
|
|
11714
|
+
|
|
11698
11715
|
//#endregion
|
|
11699
11716
|
//#region src/util/omit.ts
|
|
11700
11717
|
function omit(obj, ...keys) {
|
|
@@ -11707,8 +11724,8 @@ function omit(obj, ...keys) {
|
|
|
11707
11724
|
//#region src/commands/run.ts
|
|
11708
11725
|
var import_cjs$10 = /* @__PURE__ */ __toESM(require_cjs());
|
|
11709
11726
|
const args$1 = {
|
|
11710
|
-
...args$
|
|
11711
|
-
...omit(args$
|
|
11727
|
+
...args$2,
|
|
11728
|
+
...omit(args$3, "sandbox"),
|
|
11712
11729
|
removeAfterUse: import_cjs$10.flag({
|
|
11713
11730
|
long: "rm",
|
|
11714
11731
|
description: "Automatically remove the sandbox when the command exits."
|
|
@@ -11730,20 +11747,6 @@ const run = import_cjs$10.command({
|
|
|
11730
11747
|
}
|
|
11731
11748
|
}
|
|
11732
11749
|
});
|
|
11733
|
-
const sh = import_cjs$10.command({
|
|
11734
|
-
name: "sh",
|
|
11735
|
-
description: "Create a sandbox and run an interactive shell.",
|
|
11736
|
-
aliases: ["shell"],
|
|
11737
|
-
args: omit(args$1, "command", "interactive", "tty"),
|
|
11738
|
-
async handler(args$4) {
|
|
11739
|
-
return run.handler({
|
|
11740
|
-
command: "sh",
|
|
11741
|
-
interactive: true,
|
|
11742
|
-
tty: true,
|
|
11743
|
-
...args$4
|
|
11744
|
-
});
|
|
11745
|
-
}
|
|
11746
|
-
});
|
|
11747
11750
|
|
|
11748
11751
|
//#endregion
|
|
11749
11752
|
//#region src/commands/list.ts
|
|
@@ -11812,12 +11815,13 @@ const SandboxStatusColor = new Map([
|
|
|
11812
11815
|
]);
|
|
11813
11816
|
|
|
11814
11817
|
//#endregion
|
|
11815
|
-
//#region src/commands/
|
|
11818
|
+
//#region src/commands/connect.ts
|
|
11816
11819
|
var import_cjs$8 = /* @__PURE__ */ __toESM(require_cjs());
|
|
11817
|
-
const
|
|
11818
|
-
name: "
|
|
11820
|
+
const connect = import_cjs$8.command({
|
|
11821
|
+
name: "connect",
|
|
11822
|
+
aliases: ["ssh", "shell"],
|
|
11819
11823
|
description: "Start an interactive shell in an existing sandbox",
|
|
11820
|
-
args: omit(args$
|
|
11824
|
+
args: omit(args$3, "command", "args", "interactive", "tty"),
|
|
11821
11825
|
async handler(args$4) {
|
|
11822
11826
|
return exec.handler({
|
|
11823
11827
|
command: "sh",
|
|
@@ -14502,10 +14506,9 @@ const app = (opts) => (0, import_cjs.subcommands)({
|
|
|
14502
14506
|
config,
|
|
14503
14507
|
copy: cp,
|
|
14504
14508
|
exec,
|
|
14505
|
-
|
|
14509
|
+
connect,
|
|
14506
14510
|
stop,
|
|
14507
14511
|
run,
|
|
14508
|
-
sh,
|
|
14509
14512
|
snapshot,
|
|
14510
14513
|
snapshots,
|
|
14511
14514
|
...!opts?.withoutAuth && {
|
|
@@ -14517,4 +14520,4 @@ const app = (opts) => (0, import_cjs.subcommands)({
|
|
|
14517
14520
|
|
|
14518
14521
|
//#endregion
|
|
14519
14522
|
export { StyledError as n, require_cjs as r, app as t };
|
|
14520
|
-
//# sourceMappingURL=app-
|
|
14523
|
+
//# sourceMappingURL=app-BNIol84k.mjs.map
|