@tonbo/cli 0.10.1 → 0.11.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 (2) hide show
  1. package/dist/bin/tonbo.js +38 -7
  2. package/package.json +1 -1
package/dist/bin/tonbo.js CHANGED
@@ -3507,6 +3507,7 @@ var MACHINE_WAKE_BLOCKED_HINTS = {
3507
3507
  capacity: "No host had room for its shape; the next request tries again.",
3508
3508
  region_closed: "Machines are closed in its region for now; the next request after they reopen wakes it."
3509
3509
  };
3510
+ var MACHINE_ACCOUNT_EGRESS_BLOCKED_HINT = "If this is the free egress cap: 10 GiB a month without purchased credit; buy credit at <billing> to lift it.";
3510
3511
  function conditionText(name, condition, billing) {
3511
3512
  switch (condition.type) {
3512
3513
  case "wake_blocked": {
@@ -3518,8 +3519,10 @@ function conditionText(name, condition, billing) {
3518
3519
  return `still creating since ${condition.since}, longer than usual; Tonbo's operators are alerted, and creation goes on until it is active or failed.`;
3519
3520
  case "node_unreachable":
3520
3521
  return `its host is unreachable since ${condition.since}`;
3521
- case "egress_blocked":
3522
- return `outbound access blocked for the ${condition.scope} since ${condition.since}${condition.until ? ` until ${condition.until}` : ""}`;
3522
+ case "egress_blocked": {
3523
+ const blocked = `outbound access blocked for the ${condition.scope} since ${condition.since}${condition.until ? ` until ${condition.until}` : ""}`;
3524
+ return condition.scope === "account" && condition.until ? `${blocked}. ${MACHINE_ACCOUNT_EGRESS_BLOCKED_HINT.replaceAll("<billing>", billing)}` : blocked;
3525
+ }
3523
3526
  case "volume_purged":
3524
3527
  return `its Volume ${condition.volume} was purged (${condition.reason.replaceAll("_", " ")}) since ${condition.since}; its data is gone and it boots without it. Bind another with \`tonbo machine update ${name} --volume <volume>:<path>\`, or none with \`--no-volume\`.`;
3525
3528
  default:
@@ -3592,6 +3595,7 @@ function machineFields(machine, billing, etag = null, lastEnd = null) {
3592
3595
  ["Env", Object.keys(machine.env).sort().join(", ") || "none"],
3593
3596
  ["Stop grace", `${machine.stop_grace_seconds} s`],
3594
3597
  ["Volume", volumeText(machine)],
3598
+ ...deleteFields(machine),
3595
3599
  ["Database", `${machine.database.name} (${machine.database.url})`],
3596
3600
  ["Logs", machine.logs.url],
3597
3601
  ["Durability", DURABILITY_LINK],
@@ -3602,6 +3606,17 @@ function machineFields(machine, billing, etag = null, lastEnd = null) {
3602
3606
  ["Updated", machine.updated_at]
3603
3607
  ]);
3604
3608
  }
3609
+ function deleteFields(machine) {
3610
+ const seconds = machine.delete_after_seconds;
3611
+ if (seconds === void 0 || seconds === null) return [];
3612
+ const at = machine.status.delete_at;
3613
+ return [
3614
+ [
3615
+ "Deletes",
3616
+ at ? `at ${at}, after ${seconds} s asleep` : `${seconds} s after this activation ends`
3617
+ ]
3618
+ ];
3619
+ }
3605
3620
  function volumeText(machine) {
3606
3621
  const binding = machine.volumes?.[0];
3607
3622
  return binding ? `${binding.volume} at ${binding.path}` : "none";
@@ -3702,6 +3717,10 @@ async function waitForMachine(deps, key, name, firstWait, every, timeout, settle
3702
3717
  wait = every;
3703
3718
  }
3704
3719
  }
3720
+ function deleteAfterSeconds(option) {
3721
+ if (typeof option === "number") return option;
3722
+ return option === false ? null : void 0;
3723
+ }
3705
3724
  async function machineListCommand(deps, options = {}) {
3706
3725
  await machineCommand(async () => {
3707
3726
  const page = await deps.api.listMachines(await deps.auth.apiKey(), {
@@ -3852,7 +3871,8 @@ async function machineCreateCommand(deps, name, command, options = {}) {
3852
3871
  sleep_after_seconds: options.sleepAfter,
3853
3872
  idle_action: options.idleAction,
3854
3873
  stop_grace_seconds: options.stopGrace,
3855
- ...bound ? { volumes: [bound.binding] } : {}
3874
+ ...bound ? { volumes: [bound.binding] } : {},
3875
+ delete_after_seconds: deleteAfterSeconds(options.deleteAfter)
3856
3876
  },
3857
3877
  options.idempotencyKey ?? randomUUID4()
3858
3878
  );
@@ -3942,6 +3962,10 @@ function appliesText(name, change) {
3942
3962
  const lines = [];
3943
3963
  if (change.ports !== void 0 || change.sleep_after_seconds !== void 0)
3944
3964
  lines.push("Ports and sleep-after apply now.");
3965
+ if (change.delete_after_seconds !== void 0)
3966
+ lines.push(
3967
+ change.delete_after_seconds === null ? "The Machine is no longer deleted for being asleep." : "Delete-after applies now; `tonbo machine show` says when."
3968
+ );
3945
3969
  const later = [change.image, change.command, change.shape, change.env, change.volumes].some(
3946
3970
  (field) => field !== void 0
3947
3971
  );
@@ -3974,7 +3998,8 @@ async function machineUpdateCommand(deps, name, command, options = {}) {
3974
3998
  command: options.imageCommand ? null : command.length ? command : void 0,
3975
3999
  sleep_after_seconds: options.sleepAfter,
3976
4000
  idle_action: options.idleAction,
3977
- stop_grace_seconds: options.stopGrace
4001
+ stop_grace_seconds: options.stopGrace,
4002
+ delete_after_seconds: deleteAfterSeconds(options.deleteAfter)
3978
4003
  };
3979
4004
  if (options.clearPorts) change.ports = [];
3980
4005
  else if (options.port?.length) {
@@ -4471,7 +4496,8 @@ var COMMAND_HELP = {
4471
4496
  "--default-port": "the first --port",
4472
4497
  "--region": "the --volume's region, else the account's default region",
4473
4498
  "--idempotency-key": "a new UUID",
4474
- "--timeout": String(DEFAULT_WAIT_SECONDS)
4499
+ "--timeout": String(DEFAULT_WAIT_SECONDS),
4500
+ "--delete-after": "never"
4475
4501
  }
4476
4502
  },
4477
4503
  "tonbo machine show": {
@@ -4485,7 +4511,8 @@ var COMMAND_HELP = {
4485
4511
  "tonbo machine update": {
4486
4512
  about: [
4487
4513
  "Changes only what its options name. It reads the Machine and sends the ETag it read, or `--if-match`'s, so a change someone made in between is refused with `precondition_failed` rather than overwritten; a Machine whose creation failed is refused with `machine_failed`. `--env` and `--unset-env` change single variables; `--port` replaces every port, and the current default port stays the default while it is still listed.",
4488
- "Ports and `--sleep-after` apply at once. The image, command, shape and env apply at the next boot, and the command says how to apply them now: `tonbo machine sleep`, after which the next request boots the new spec. Naming the same tag again resolves its digest again."
4514
+ "Ports and `--sleep-after` apply at once. The image, command, shape and env apply at the next boot, and the command says how to apply them now: `tonbo machine sleep`, after which the next request boots the new spec. Naming the same tag again resolves its digest again.",
4515
+ "`--delete-after` applies at once and keeps the clock, which counts from the end of the Machine's last activation (or its creation), so a lower value can delete a Machine that has already slept that long; `--no-delete-after` turns it off. `tonbo machine show` prints when it will be deleted."
4489
4516
  ],
4490
4517
  examples: ["tonbo machine update web --env MODE=staging --sleep-after 300"],
4491
4518
  arguments: {
@@ -4739,6 +4766,10 @@ function machineSpecOptions(command, update) {
4739
4766
  ).option(
4740
4767
  "--volume <name:path>",
4741
4768
  `mount the Volume <name> (see tonbo volume list) at <path>; a Machine has at most one, of its own region${update ? "; applies at the next boot" : ""}`
4769
+ ).option(
4770
+ "--delete-after <seconds>",
4771
+ `delete the Machine once it has been asleep, never woken or failed this long (3600 to 7776000)${update ? "; applies at once, from its last activation's end" : ""}`,
4772
+ parseWhole
4742
4773
  );
4743
4774
  }
4744
4775
  function parseExpiresIn(value) {
@@ -5031,7 +5062,7 @@ function createProgram(dependencies = createDependencies) {
5031
5062
  machineSpecOptions(
5032
5063
  machine.command("update <name> [command...]").description(
5033
5064
  "change a Machine; [command...] after -- replaces its command at the next boot"
5034
- ).option("--image <reference>", "a new image, named as for create; applies at the next boot").option("--image-command", "run the image's own CMD again at the next boot").option("--unset-env <KEY>", "remove an environment variable; repeat for several", repeated).option("--clear-ports", "remove every port").option("--if-match <etag>", ifMatchHelp("change")).option("--discard-snapshot", "apply a change that discards the Machine's snapshot").option("--no-volume", "remove the Machine's Volume at the next boot; the Volume is kept"),
5065
+ ).option("--image <reference>", "a new image, named as for create; applies at the next boot").option("--image-command", "run the image's own CMD again at the next boot").option("--unset-env <KEY>", "remove an environment variable; repeat for several", repeated).option("--clear-ports", "remove every port").option("--if-match <etag>", ifMatchHelp("change")).option("--discard-snapshot", "apply a change that discards the Machine's snapshot").option("--no-volume", "remove the Machine's Volume at the next boot; the Volume is kept").option("--no-delete-after", "never delete the Machine for being asleep"),
5035
5066
  true
5036
5067
  ),
5037
5068
  "updateMachine"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonbo/cli",
3
- "version": "0.10.1",
3
+ "version": "0.11.1",
4
4
  "description": "The Tonbo CLI: sign in and manage account resources from the command line.",
5
5
  "homepage": "https://tonbo.dev",
6
6
  "bugs": {