@pocketenv/cli 0.2.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import relativeTime from 'dayjs/plugin/relativeTime.js';
22
22
  import { password, editor, input } from '@inquirer/prompts';
23
23
  import sodium from 'libsodium-wrappers';
24
24
 
25
- var version = "0.2.5";
25
+ var version = "0.3.0";
26
26
 
27
27
  async function getAccessToken() {
28
28
  const tokenPath = path.join(os.homedir(), ".pocketenv", "token.json");
@@ -480,6 +480,17 @@ async function whoami() {
480
480
  );
481
481
  }
482
482
 
483
+ const c = {
484
+ primary: (s) => chalk.rgb(0, 232, 198)(s),
485
+ secondary: (s) => chalk.rgb(0, 198, 232)(s),
486
+ accent: (s) => chalk.rgb(130, 100, 255)(s),
487
+ highlight: (s) => chalk.rgb(100, 232, 130)(s),
488
+ muted: (s) => chalk.rgb(200, 210, 220)(s),
489
+ link: (s) => chalk.rgb(255, 160, 100)(s),
490
+ sky: (s) => chalk.rgb(0, 210, 255)(s),
491
+ error: (s) => chalk.rgb(255, 100, 100)(s)
492
+ };
493
+
483
494
  dayjs.extend(relativeTime);
484
495
  async function listSandboxes() {
485
496
  const token = await getAccessToken();
@@ -503,10 +514,10 @@ async function listSandboxes() {
503
514
  );
504
515
  const table = new Table({
505
516
  head: [
506
- chalk.cyan("NAME"),
507
- chalk.cyan("BASE"),
508
- chalk.cyan("STATUS"),
509
- chalk.cyan("CREATED AT")
517
+ c.primary("NAME"),
518
+ c.primary("BASE"),
519
+ c.primary("STATUS"),
520
+ c.primary("CREATED AT")
510
521
  ],
511
522
  chars: {
512
523
  top: "",
@@ -532,9 +543,9 @@ async function listSandboxes() {
532
543
  });
533
544
  for (const sandbox of response.data.sandboxes) {
534
545
  table.push([
535
- chalk.greenBright(sandbox.name),
546
+ c.secondary(sandbox.name),
536
547
  sandbox.baseSandbox,
537
- sandbox.status === "RUNNING" ? chalk.greenBright(sandbox.status) : sandbox.status,
548
+ sandbox.status === "RUNNING" ? c.highlight(sandbox.status) : sandbox.status,
538
549
  dayjs(sandbox.createdAt).fromNow()
539
550
  ]);
540
551
  }
@@ -566,7 +577,7 @@ async function createSandbox(name, {
566
577
  const token = await getAccessToken();
567
578
  if (["deno", "vercel", "daytona"].includes(provider || "")) {
568
579
  consola.error(
569
- `This Sandbox Runtime is temporarily disabled. ${chalk.greenBright(provider ?? "")}`
580
+ `This Sandbox Runtime is temporarily disabled. ${c.primary(provider ?? "")}`
570
581
  );
571
582
  process.exit(1);
572
583
  }
@@ -586,7 +597,7 @@ async function createSandbox(name, {
586
597
  );
587
598
  if (!ssh$1) {
588
599
  consola.success(
589
- `Sandbox created successfully: ${chalk.greenBright(sandbox.data.name)}`
600
+ `Sandbox created successfully: ${c.primary(sandbox.data.name)}`
590
601
  );
591
602
  return;
592
603
  }
@@ -662,7 +673,7 @@ async function listSecrets(sandbox) {
662
673
  }
663
674
  );
664
675
  const table = new Table({
665
- head: [chalk.cyan("ID"), chalk.cyan("NAME"), chalk.cyan("CREATED AT")],
676
+ head: [c.primary("ID"), c.primary("NAME"), c.primary("CREATED AT")],
666
677
  chars: {
667
678
  top: "",
668
679
  "top-mid": "",
@@ -687,8 +698,8 @@ async function listSecrets(sandbox) {
687
698
  });
688
699
  for (const secret of response.data.secrets) {
689
700
  table.push([
690
- chalk.greenBright(secret.id),
691
- chalk.greenBright(secret.name),
701
+ c.secondary(secret.id),
702
+ c.highlight(secret.name),
692
703
  dayjs(secret.createdAt).fromNow()
693
704
  ]);
694
705
  }
@@ -696,7 +707,13 @@ async function listSecrets(sandbox) {
696
707
  }
697
708
  async function putSecret(sandbox, key) {
698
709
  const token = await getAccessToken();
699
- const value = await password({ message: "Enter secret value" });
710
+ const isStdinPiped = !process.stdin.isTTY;
711
+ const value = isStdinPiped ? await new Promise((resolve) => {
712
+ let data2 = "";
713
+ process.stdin.setEncoding("utf8");
714
+ process.stdin.on("data", (chunk) => data2 += chunk);
715
+ process.stdin.on("end", () => resolve(data2.trimEnd()));
716
+ }) : await password({ message: "Enter secret value" });
700
717
  const { data } = await client.get("/xrpc/io.pocketenv.sandbox.getSandbox", {
701
718
  params: {
702
719
  id: sandbox
@@ -709,21 +726,26 @@ async function putSecret(sandbox, key) {
709
726
  consola.error(`Sandbox not found: ${chalk.greenBright(sandbox)}`);
710
727
  process.exit(1);
711
728
  }
712
- await client.post(
713
- "/xrpc/io.pocketenv.secret.addSecret",
714
- {
715
- secret: {
716
- sandboxId: data.sandbox.id,
717
- name: key,
718
- value: await encrypt(value)
719
- }
720
- },
721
- {
722
- headers: {
723
- Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
729
+ try {
730
+ await client.post(
731
+ "/xrpc/io.pocketenv.secret.addSecret",
732
+ {
733
+ secret: {
734
+ sandboxId: data.sandbox.id,
735
+ name: key,
736
+ value: await encrypt(value)
737
+ }
738
+ },
739
+ {
740
+ headers: {
741
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
742
+ }
724
743
  }
725
- }
726
- );
744
+ );
745
+ consola.success("Secret added successfully");
746
+ } catch (error) {
747
+ consola.error("Failed to add secret:", error);
748
+ }
727
749
  }
728
750
  async function deleteSecret(id) {
729
751
  const token = await getAccessToken();
@@ -737,8 +759,8 @@ async function deleteSecret(id) {
737
759
  }
738
760
  });
739
761
  consola.success("Secret deleted successfully");
740
- } catch {
741
- consola.error("Failed to delete secret");
762
+ } catch (error) {
763
+ consola.error("Failed to delete secret:", error);
742
764
  }
743
765
  }
744
766
 
@@ -756,7 +778,7 @@ async function listEnvs(sandbox) {
756
778
  }
757
779
  );
758
780
  if (!data.sandbox) {
759
- consola.error(`Sandbox not found: ${chalk.greenBright(sandbox)}`);
781
+ consola.error(`Sandbox not found: ${c.primary(sandbox)}`);
760
782
  process.exit(1);
761
783
  }
762
784
  const response = await client.get(
@@ -774,10 +796,10 @@ async function listEnvs(sandbox) {
774
796
  );
775
797
  const table = new Table({
776
798
  head: [
777
- chalk.cyan("ID"),
778
- chalk.cyan("NAME"),
779
- chalk.cyan("VALUE"),
780
- chalk.cyan("CREATED AT")
799
+ c.primary("ID"),
800
+ c.primary("NAME"),
801
+ c.primary("VALUE"),
802
+ c.primary("CREATED AT")
781
803
  ],
782
804
  chars: {
783
805
  top: "",
@@ -803,8 +825,8 @@ async function listEnvs(sandbox) {
803
825
  });
804
826
  for (const variable of response.data.variables) {
805
827
  table.push([
806
- chalk.greenBright(variable.id),
807
- chalk.greenBright(variable.name),
828
+ c.secondary(variable.id),
829
+ c.highlight(variable.name),
808
830
  variable.value,
809
831
  dayjs(variable.createdAt).fromNow()
810
832
  ]);
@@ -1100,7 +1122,7 @@ async function putAuthKey(sandbox) {
1100
1122
  }
1101
1123
  );
1102
1124
  if (!data.sandbox) {
1103
- consola.error(`Sandbox not found: ${chalk.greenBright(sandbox)}`);
1125
+ consola.error(`Sandbox not found: ${c.primary(sandbox)}`);
1104
1126
  process.exit(1);
1105
1127
  }
1106
1128
  const redacted = authKey.length > 14 ? authKey.slice(0, 11) + "*".repeat(authKey.length - 14) + authKey.slice(-3) : authKey;
@@ -1119,7 +1141,7 @@ async function putAuthKey(sandbox) {
1119
1141
  );
1120
1142
  consola.success(redacted);
1121
1143
  consola.success(
1122
- `Tailscale auth key saved for sandbox: ${chalk.greenBright(sandbox)}`
1144
+ `Tailscale auth key saved for sandbox: ${c.primary(sandbox)}`
1123
1145
  );
1124
1146
  }
1125
1147
  async function getTailscaleAuthKey(sandbox) {
@@ -1136,7 +1158,7 @@ async function getTailscaleAuthKey(sandbox) {
1136
1158
  }
1137
1159
  );
1138
1160
  if (!data.sandbox) {
1139
- consola.error(`Sandbox not found: ${chalk.greenBright(sandbox)}`);
1161
+ consola.error(`Sandbox not found: ${c.primary(sandbox)}`);
1140
1162
  process.exit(1);
1141
1163
  }
1142
1164
  try {
@@ -1151,24 +1173,349 @@ async function getTailscaleAuthKey(sandbox) {
1151
1173
  }
1152
1174
  }
1153
1175
  );
1154
- consola.info(`Tailscale auth key: ${chalk.greenBright(tailscale.authKey)}`);
1176
+ consola.info(`Tailscale auth key: ${c.primary(tailscale.authKey)}`);
1155
1177
  } catch {
1156
1178
  consola.error(
1157
- `No Tailscale Auth Key found for sandbox: ${chalk.greenBright(sandbox)}`
1179
+ `No Tailscale Auth Key found for sandbox: ${c.primary(sandbox)}`
1158
1180
  );
1159
1181
  process.exit(1);
1160
1182
  }
1161
1183
  }
1162
1184
 
1163
- const c = {
1164
- primary: (s) => chalk.rgb(0, 232, 198)(s),
1165
- secondary: (s) => chalk.rgb(0, 198, 232)(s),
1166
- accent: (s) => chalk.rgb(130, 100, 255)(s),
1167
- highlight: (s) => chalk.rgb(100, 232, 130)(s),
1168
- muted: (s) => chalk.rgb(200, 210, 220)(s),
1169
- link: (s) => chalk.rgb(255, 160, 100)(s),
1170
- sky: (s) => chalk.rgb(0, 210, 255)(s)
1171
- };
1185
+ async function exposePort(sandbox, port, description) {
1186
+ const token = await getAccessToken();
1187
+ try {
1188
+ const response = await client.post(
1189
+ `/xrpc/io.pocketenv.sandbox.exposePort`,
1190
+ { port, description },
1191
+ {
1192
+ params: {
1193
+ id: sandbox
1194
+ },
1195
+ headers: {
1196
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1197
+ }
1198
+ }
1199
+ );
1200
+ consola.success(
1201
+ `Port ${c.primary(port)} exposed for sandbox ${c.primary(sandbox)}`
1202
+ );
1203
+ if (response.data.previewUrl) {
1204
+ consola.success(`Preview URL: ${c.secondary(response.data.previewUrl)}`);
1205
+ }
1206
+ } catch (error) {
1207
+ consola.error("Failed to expose port:", error);
1208
+ process.exit(1);
1209
+ }
1210
+ }
1211
+
1212
+ async function unexposePort(sandbox, port) {
1213
+ const token = await getAccessToken();
1214
+ try {
1215
+ await client.post(
1216
+ `/xrpc/io.pocketenv.sandbox.unexposePort`,
1217
+ { port },
1218
+ {
1219
+ params: {
1220
+ id: sandbox
1221
+ },
1222
+ headers: {
1223
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1224
+ }
1225
+ }
1226
+ );
1227
+ consola.success(
1228
+ `Port ${c.primary(port)} unexposed for sandbox ${c.primary(sandbox)}`
1229
+ );
1230
+ } catch (error) {
1231
+ consola.error(`Failed to unexpose port: ${error}`);
1232
+ process.exit(1);
1233
+ }
1234
+ }
1235
+
1236
+ dayjs.extend(relativeTime);
1237
+ async function listVolumes(sandboxId) {
1238
+ const token = await getAccessToken();
1239
+ const response = await client.get(
1240
+ "/xrpc/io.pocketenv.volume.getVolumes",
1241
+ {
1242
+ params: {
1243
+ sandboxId
1244
+ },
1245
+ headers: {
1246
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1247
+ }
1248
+ }
1249
+ );
1250
+ const table = new Table({
1251
+ head: [
1252
+ c.primary("ID"),
1253
+ c.primary("NAME"),
1254
+ c.primary("PATH"),
1255
+ c.primary("CREATED AT")
1256
+ ],
1257
+ chars: {
1258
+ top: "",
1259
+ "top-mid": "",
1260
+ "top-left": "",
1261
+ "top-right": "",
1262
+ bottom: "",
1263
+ "bottom-mid": "",
1264
+ "bottom-left": "",
1265
+ "bottom-right": "",
1266
+ left: "",
1267
+ "left-mid": "",
1268
+ mid: "",
1269
+ "mid-mid": "",
1270
+ right: "",
1271
+ "right-mid": "",
1272
+ middle: " "
1273
+ },
1274
+ style: {
1275
+ border: [],
1276
+ head: []
1277
+ }
1278
+ });
1279
+ for (const volume of response.data.volumes) {
1280
+ table.push([
1281
+ c.secondary(volume.id),
1282
+ volume.name,
1283
+ volume.path,
1284
+ dayjs(volume.createdAt).fromNow()
1285
+ ]);
1286
+ }
1287
+ consola.log(table.toString());
1288
+ }
1289
+ async function createVolume(sandbox, name, path) {
1290
+ const token = await getAccessToken();
1291
+ try {
1292
+ await client.post(
1293
+ "/xrpc/io.pocketenv.volume.addVolume",
1294
+ {
1295
+ volume: {
1296
+ sandboxId: sandbox,
1297
+ name,
1298
+ path
1299
+ }
1300
+ },
1301
+ {
1302
+ headers: {
1303
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1304
+ }
1305
+ }
1306
+ );
1307
+ consola.success(
1308
+ `Volume ${chalk.rgb(0, 232, 198)(name)} successfully mounted in sandbox ${chalk.rgb(0, 232, 198)(sandbox)} at path ${chalk.rgb(0, 232, 198)(path)}`
1309
+ );
1310
+ } catch (error) {
1311
+ consola.error("Failed to create volume:", error);
1312
+ }
1313
+ }
1314
+ async function deleteVolume(id) {
1315
+ const token = await getAccessToken();
1316
+ try {
1317
+ await client.post(`/xrpc/io.pocketenv.volume.deleteVolume`, void 0, {
1318
+ params: {
1319
+ id
1320
+ },
1321
+ headers: {
1322
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1323
+ }
1324
+ });
1325
+ } catch (error) {
1326
+ consola.error(`Failed to delete volume: ${error}`);
1327
+ return;
1328
+ }
1329
+ consola.success(
1330
+ `Volume ${chalk.rgb(0, 232, 198)(id)} successfully deleted from sandbox`
1331
+ );
1332
+ }
1333
+
1334
+ dayjs.extend(relativeTime);
1335
+ async function putFile(sandbox, remotePath, localPath) {
1336
+ const token = await getAccessToken();
1337
+ let content;
1338
+ if (!process.stdin.isTTY) {
1339
+ const chunks = [];
1340
+ for await (const chunk of process.stdin) chunks.push(chunk);
1341
+ content = Buffer.concat(chunks).toString().trim();
1342
+ } else if (localPath) {
1343
+ const resolvedPath = path.resolve(localPath);
1344
+ try {
1345
+ await fs.access(resolvedPath);
1346
+ } catch (err) {
1347
+ consola.error(`No such file: ${c.error(localPath)}`);
1348
+ process.exit(1);
1349
+ }
1350
+ content = await fs.readFile(resolvedPath, "utf-8");
1351
+ } else {
1352
+ content = (await editor({
1353
+ message: "File content (opens in $EDITOR):",
1354
+ waitForUserInput: false
1355
+ })).trim();
1356
+ }
1357
+ try {
1358
+ await client.post(
1359
+ "/xrpc/io.pocketenv.file.addFile",
1360
+ {
1361
+ file: {
1362
+ sandboxId: sandbox,
1363
+ path: remotePath,
1364
+ content: await encrypt(content)
1365
+ }
1366
+ },
1367
+ {
1368
+ headers: {
1369
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1370
+ }
1371
+ }
1372
+ );
1373
+ consola.success(
1374
+ `File ${c.primary(remotePath)} successfully created in sandbox ${c.primary(sandbox)}`
1375
+ );
1376
+ } catch (error) {
1377
+ consola.error(`Failed to create file: ${error}`);
1378
+ }
1379
+ }
1380
+ async function listFiles(sandboxId) {
1381
+ const token = await getAccessToken();
1382
+ const response = await client.get(
1383
+ "/xrpc/io.pocketenv.file.getFiles",
1384
+ {
1385
+ params: {
1386
+ sandboxId
1387
+ },
1388
+ headers: {
1389
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1390
+ }
1391
+ }
1392
+ );
1393
+ const table = new Table({
1394
+ head: [c.primary("ID"), c.primary("PATH"), c.primary("CREATED AT")],
1395
+ chars: {
1396
+ top: "",
1397
+ "top-mid": "",
1398
+ "top-left": "",
1399
+ "top-right": "",
1400
+ bottom: "",
1401
+ "bottom-mid": "",
1402
+ "bottom-left": "",
1403
+ "bottom-right": "",
1404
+ left: "",
1405
+ "left-mid": "",
1406
+ mid: "",
1407
+ "mid-mid": "",
1408
+ right: "",
1409
+ "right-mid": "",
1410
+ middle: " "
1411
+ },
1412
+ style: {
1413
+ border: [],
1414
+ head: []
1415
+ }
1416
+ });
1417
+ for (const file of response.data.files) {
1418
+ table.push([
1419
+ c.secondary(file.id),
1420
+ file.path,
1421
+ dayjs(file.createdAt).fromNow()
1422
+ ]);
1423
+ }
1424
+ consola.log(table.toString());
1425
+ }
1426
+ async function deleteFile(id) {
1427
+ const token = await getAccessToken();
1428
+ try {
1429
+ await client.post(`/xrpc/io.pocketenv.file.deleteFile`, void 0, {
1430
+ params: {
1431
+ id
1432
+ },
1433
+ headers: {
1434
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1435
+ }
1436
+ });
1437
+ consola.success(`File ${c.primary(id)} successfully deleted from sandbox`);
1438
+ } catch (error) {
1439
+ consola.error(`Failed to delete file: ${error}`);
1440
+ }
1441
+ }
1442
+
1443
+ async function listPorts(sandbox) {
1444
+ const token = await getAccessToken();
1445
+ const response = await client.get(
1446
+ "/xrpc/io.pocketenv.sandbox.getExposedPorts",
1447
+ {
1448
+ params: {
1449
+ id: sandbox
1450
+ },
1451
+ headers: {
1452
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1453
+ }
1454
+ }
1455
+ );
1456
+ const table = new Table({
1457
+ head: [
1458
+ c.primary("PORT"),
1459
+ c.primary("DESCRIPTION"),
1460
+ c.primary("PREVIEW URL")
1461
+ ],
1462
+ chars: {
1463
+ top: "",
1464
+ "top-mid": "",
1465
+ "top-left": "",
1466
+ "top-right": "",
1467
+ bottom: "",
1468
+ "bottom-mid": "",
1469
+ "bottom-left": "",
1470
+ "bottom-right": "",
1471
+ left: "",
1472
+ "left-mid": "",
1473
+ mid: "",
1474
+ "mid-mid": "",
1475
+ right: "",
1476
+ "right-mid": "",
1477
+ middle: " "
1478
+ },
1479
+ style: {
1480
+ border: [],
1481
+ head: []
1482
+ }
1483
+ });
1484
+ for (const port of response.data.ports) {
1485
+ table.push([
1486
+ c.secondary(port.port),
1487
+ port.description || "-",
1488
+ c.link(port.previewUrl || "-")
1489
+ ]);
1490
+ }
1491
+ consola.log(table.toString());
1492
+ }
1493
+
1494
+ async function exposeVscode(sandbox) {
1495
+ const token = await getAccessToken();
1496
+ try {
1497
+ const response = await client.post(
1498
+ `/xrpc/io.pocketenv.sandbox.exposeVscode`,
1499
+ void 0,
1500
+ {
1501
+ params: {
1502
+ id: sandbox
1503
+ },
1504
+ headers: {
1505
+ Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
1506
+ }
1507
+ }
1508
+ );
1509
+ consola.success(`VS Code Server exposed for sandbox ${c.primary(sandbox)}`);
1510
+ if (response.data.previewUrl) {
1511
+ consola.success(`Preview URL: ${c.secondary(response.data.previewUrl)}`);
1512
+ }
1513
+ } catch (error) {
1514
+ consola.error("Failed to expose VS Code:", error);
1515
+ process.exit(1);
1516
+ }
1517
+ }
1518
+
1172
1519
  const program = new Command();
1173
1520
  program.name("pocketenv").description(
1174
1521
  `${chalk.bold.rgb(0, 232, 198)(`pocketenv v${version}`)} ${c.muted("\u2500")} ${c.muted("Open, interoperable sandbox platform for agents and humans")}`
@@ -1203,6 +1550,34 @@ program.command("create").aliases(["new"]).option("--provider, -p <provider>", "
1203
1550
  ).option("--ssh, -s", "connect to the Sandbox and automatically open a shell").argument("[name]", "the name of the sandbox to create").description("create a new sandbox").action(createSandbox);
1204
1551
  program.command("logout").description("logout (removes session token)").action(logout);
1205
1552
  program.command("rm").aliases(["delete", "remove"]).argument("<sandbox>", "the sandbox to delete").description("delete the given sandbox").action(deleteSandbox);
1553
+ program.command("vscode").argument("<sandbox>", "the sandbox to expose VS Code for").description(
1554
+ "expose a VS Code Server instance running in the given sandbox to the internet"
1555
+ ).action(exposeVscode);
1556
+ program.command("expose").argument("<sandbox>", "the sandbox to expose a port for").argument("<port>", "the port to expose", (val) => {
1557
+ const port = parseInt(val, 10);
1558
+ if (isNaN(port)) {
1559
+ consola.error(`port must be a number, got: ${val}`);
1560
+ process.exit(1);
1561
+ }
1562
+ return port;
1563
+ }).argument("[description]", "an optional description for the exposed port").description("expose a port from the given sandbox to the internet").action(exposePort);
1564
+ program.command("unexpose").argument("<sandbox>", "the sandbox to unexpose a port for").argument("<port>", "the port to unexpose", (val) => {
1565
+ const port = parseInt(val, 10);
1566
+ if (isNaN(port)) {
1567
+ consola.error(`port must be a number, got: ${val}`);
1568
+ process.exit(1);
1569
+ }
1570
+ return port;
1571
+ }).description("unexpose a port from the given sandbox").action(unexposePort);
1572
+ const volume = program.command("volume").description("manage volumes");
1573
+ volume.command("put").argument("<sandbox>", "the sandbox to put the volume in").argument("<name>", "the name of the volume").argument("<path>", "the path to mount the volume at").description("put a volume in the given sandbox").action(createVolume);
1574
+ volume.command("list").aliases(["ls"]).argument("<sandbox>", "the sandbox to list volumes for").description("list volumes in the given sandbox").action(listVolumes);
1575
+ volume.command("delete").aliases(["rm", "remove"]).argument("<id>", "the ID of the volume to delete").description("delete a volume").action(deleteVolume);
1576
+ const file = program.command("file").description("manage files");
1577
+ file.command("put").argument("<sandbox>", "the sandbox to put the file in").argument("<path>", "the remote path to upload the file to").argument("[localPath]", "the local path of the file to upload").description("upload a file to the given sandbox").action(putFile);
1578
+ file.command("list").aliases(["ls"]).argument("<sandbox>", "the sandbox to list files for").description("list files in the given sandbox").action(listFiles);
1579
+ file.command("delete").aliases(["rm", "remove"]).argument("<id>", "the ID of the file to delete").description("delete a file").action(deleteFile);
1580
+ program.command("ports").argument("<sandbox>", "the sandbox to list exposed ports for").description("list exposed ports for a sandbox").action(listPorts);
1206
1581
  const secret = program.command("secret").description("manage secrets");
1207
1582
  secret.command("put").argument("<sandbox>", "the sandbox to put the secret in").argument("<key>", "the key of the secret").description("put a secret in the given sandbox").action(putSecret);
1208
1583
  secret.command("list").aliases(["ls"]).argument("<sandbox>", "the sandbox to list secrets for").description("list secrets in the given sandbox").action(listSecrets);
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "bin": {
5
5
  "pocketenv": "dist/index.js"
6
6
  },
7
- "version": "0.2.5",
7
+ "version": "0.3.0",
8
8
  "type": "module",
9
9
  "keywords": [
10
10
  "sandbox",
package/src/cmd/create.ts CHANGED
@@ -2,8 +2,8 @@ import consola from "consola";
2
2
  import { client } from "../client";
3
3
  import getAccessToken from "../lib/getAccessToken";
4
4
  import type { Sandbox } from "../types/sandbox";
5
- import chalk from "chalk";
6
5
  import connectToSandbox from "./ssh";
6
+ import { c } from "../theme";
7
7
 
8
8
  async function createSandbox(
9
9
  name: string,
@@ -21,7 +21,7 @@ async function createSandbox(
21
21
 
22
22
  if (["deno", "vercel", "daytona"].includes(provider || "")) {
23
23
  consola.error(
24
- `This Sandbox Runtime is temporarily disabled. ${chalk.greenBright(provider ?? "")}`,
24
+ `This Sandbox Runtime is temporarily disabled. ${c.primary(provider ?? "")}`,
25
25
  );
26
26
  process.exit(1);
27
27
  }
@@ -43,7 +43,7 @@ async function createSandbox(
43
43
  );
44
44
  if (!ssh) {
45
45
  consola.success(
46
- `Sandbox created successfully: ${chalk.greenBright(sandbox.data.name)}`,
46
+ `Sandbox created successfully: ${c.primary(sandbox.data.name)}`,
47
47
  );
48
48
  return;
49
49
  }
package/src/cmd/env.ts CHANGED
@@ -2,11 +2,11 @@ import { client } from "../client";
2
2
  import getAccessToken from "../lib/getAccessToken";
3
3
  import type { Sandbox } from "../types/sandbox";
4
4
  import type { Variable } from "../types/variable";
5
- import chalk from "chalk";
6
5
  import dayjs from "dayjs";
7
6
  import consola from "consola";
8
7
  import Table from "cli-table3";
9
8
  import { env } from "../lib/env";
9
+ import { c } from "../theme";
10
10
 
11
11
  export async function listEnvs(sandbox: string) {
12
12
  const token = await getAccessToken();
@@ -23,7 +23,7 @@ export async function listEnvs(sandbox: string) {
23
23
  );
24
24
 
25
25
  if (!data.sandbox) {
26
- consola.error(`Sandbox not found: ${chalk.greenBright(sandbox)}`);
26
+ consola.error(`Sandbox not found: ${c.primary(sandbox)}`);
27
27
  process.exit(1);
28
28
  }
29
29
 
@@ -43,10 +43,10 @@ export async function listEnvs(sandbox: string) {
43
43
 
44
44
  const table = new Table({
45
45
  head: [
46
- chalk.cyan("ID"),
47
- chalk.cyan("NAME"),
48
- chalk.cyan("VALUE"),
49
- chalk.cyan("CREATED AT"),
46
+ c.primary("ID"),
47
+ c.primary("NAME"),
48
+ c.primary("VALUE"),
49
+ c.primary("CREATED AT"),
50
50
  ],
51
51
  chars: {
52
52
  top: "",
@@ -73,8 +73,8 @@ export async function listEnvs(sandbox: string) {
73
73
 
74
74
  for (const variable of response.data.variables) {
75
75
  table.push([
76
- chalk.greenBright(variable.id),
77
- chalk.greenBright(variable.name),
76
+ c.secondary(variable.id),
77
+ c.highlight(variable.name),
78
78
  variable.value,
79
79
  dayjs(variable.createdAt).fromNow(),
80
80
  ]);