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 CHANGED
@@ -1,8 +1,7 @@
1
1
  # Vercel Sandbox CLI
2
2
 
3
- Command line interface for Vercel Sandbox.
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 create # Create a new 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.1.0";
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$13 = /* @__PURE__ */ __toESM(require_cjs());
7398
+ var import_cjs$15 = /* @__PURE__ */ __toESM(require_cjs());
7577
7399
  init_source();
7578
- const sandboxId = import_cjs$13.extendType(import_cjs$13.string, {
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$12 = /* @__PURE__ */ __toESM(require_cjs());
11392
+ var import_cjs$14 = /* @__PURE__ */ __toESM(require_cjs());
11571
11393
  init_source();
11572
- const KeyValuePair = import_cjs$12.extendType(import_cjs$12.string, {
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$12.extendType(import_cjs$12.array(KeyValuePair), { async from(input) {
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$11 = /* @__PURE__ */ __toESM(require_cjs());
11422
+ var import_cjs$13 = /* @__PURE__ */ __toESM(require_cjs());
11601
11423
  init_source();
11602
- const args$2 = {
11424
+ const args$3 = {
11603
11425
  scope,
11604
- sandbox: import_cjs$11.positional({ type: sandboxId }),
11605
- asSudo: import_cjs$11.flag({
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$11.positional({
11431
+ command: import_cjs$13.positional({
11610
11432
  displayName: "command",
11611
11433
  description: "The executable to invoke"
11612
11434
  }),
11613
- args: import_cjs$11.rest({
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$11.option({
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$11.optional(import_cjs$11.string)
11443
+ type: import_cjs$13.optional(import_cjs$13.string)
11622
11444
  }),
11623
- interactive: import_cjs$11.flag({
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$11.extendType(import_cjs$11.boolean, {
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$11.flag({
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$11.multioption({
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$11.flag({
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$11.command({
11475
+ const exec = import_cjs$13.command({
11654
11476
  name: "exec",
11655
11477
  description: "Execute a command in an existing sandbox",
11656
- args: args$2,
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$3,
11711
- ...omit(args$2, "sandbox"),
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/ssh.ts
11818
+ //#region src/commands/connect.ts
11816
11819
  var import_cjs$8 = /* @__PURE__ */ __toESM(require_cjs());
11817
- const ssh = import_cjs$8.command({
11818
- name: "ssh",
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$2, "command", "args", "interactive", "tty"),
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
- ssh,
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-DtmaeGtx.mjs.map
14523
+ //# sourceMappingURL=app-BNIol84k.mjs.map