@rollupdate/hctl 0.0.0-stage → 3.1.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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1071 -2
  3. package/dist/auction/cache.d.ts +6 -0
  4. package/dist/auction/cache.js +55 -0
  5. package/dist/auction/client.d.ts +24 -0
  6. package/dist/auction/client.js +236 -0
  7. package/dist/auction/commands.d.ts +2 -0
  8. package/dist/auction/commands.js +440 -0
  9. package/dist/auction/diff-formatter.d.ts +3 -0
  10. package/dist/auction/diff-formatter.js +61 -0
  11. package/dist/auction/diff.d.ts +11 -0
  12. package/dist/auction/diff.js +28 -0
  13. package/dist/auction/formatter.d.ts +21 -0
  14. package/dist/auction/formatter.js +182 -0
  15. package/dist/auction/store.d.ts +24 -0
  16. package/dist/auction/store.js +177 -0
  17. package/dist/auction/types.d.ts +74 -0
  18. package/dist/auction/types.js +5 -0
  19. package/dist/cli.d.ts +2 -0
  20. package/dist/cli.js +74 -0
  21. package/dist/client.d.ts +2 -0
  22. package/dist/client.js +4 -0
  23. package/dist/cloud/browser-bootstrap.d.ts +28 -0
  24. package/dist/cloud/browser-bootstrap.js +480 -0
  25. package/dist/cloud/client.d.ts +520 -0
  26. package/dist/cloud/client.js +755 -0
  27. package/dist/cloud/commands/certificate.d.ts +2 -0
  28. package/dist/cloud/commands/certificate.js +108 -0
  29. package/dist/cloud/commands/context.d.ts +2 -0
  30. package/dist/cloud/commands/context.js +133 -0
  31. package/dist/cloud/commands/datacenter.d.ts +2 -0
  32. package/dist/cloud/commands/datacenter.js +24 -0
  33. package/dist/cloud/commands/firewall.d.ts +2 -0
  34. package/dist/cloud/commands/firewall.js +142 -0
  35. package/dist/cloud/commands/floating-ip.d.ts +2 -0
  36. package/dist/cloud/commands/floating-ip.js +138 -0
  37. package/dist/cloud/commands/image.d.ts +2 -0
  38. package/dist/cloud/commands/image.js +98 -0
  39. package/dist/cloud/commands/index.d.ts +2 -0
  40. package/dist/cloud/commands/index.js +47 -0
  41. package/dist/cloud/commands/inventory.d.ts +2 -0
  42. package/dist/cloud/commands/inventory.js +13 -0
  43. package/dist/cloud/commands/iso.d.ts +2 -0
  44. package/dist/cloud/commands/iso.js +27 -0
  45. package/dist/cloud/commands/load-balancer-type.d.ts +2 -0
  46. package/dist/cloud/commands/load-balancer-type.js +24 -0
  47. package/dist/cloud/commands/load-balancer.d.ts +2 -0
  48. package/dist/cloud/commands/load-balancer.js +269 -0
  49. package/dist/cloud/commands/location.d.ts +2 -0
  50. package/dist/cloud/commands/location.js +24 -0
  51. package/dist/cloud/commands/network.d.ts +2 -0
  52. package/dist/cloud/commands/network.js +157 -0
  53. package/dist/cloud/commands/placement-group.d.ts +2 -0
  54. package/dist/cloud/commands/placement-group.js +79 -0
  55. package/dist/cloud/commands/pricing.d.ts +2 -0
  56. package/dist/cloud/commands/pricing.js +15 -0
  57. package/dist/cloud/commands/primary-ip.d.ts +2 -0
  58. package/dist/cloud/commands/primary-ip.js +139 -0
  59. package/dist/cloud/commands/server-type.d.ts +2 -0
  60. package/dist/cloud/commands/server-type.js +24 -0
  61. package/dist/cloud/commands/server.d.ts +2 -0
  62. package/dist/cloud/commands/server.js +346 -0
  63. package/dist/cloud/commands/ssh-key.d.ts +2 -0
  64. package/dist/cloud/commands/ssh-key.js +94 -0
  65. package/dist/cloud/commands/volume.d.ts +2 -0
  66. package/dist/cloud/commands/volume.js +138 -0
  67. package/dist/cloud/context.d.ts +34 -0
  68. package/dist/cloud/context.js +215 -0
  69. package/dist/cloud/formatter.d.ts +40 -0
  70. package/dist/cloud/formatter.js +824 -0
  71. package/dist/cloud/helpers.d.ts +27 -0
  72. package/dist/cloud/helpers.js +67 -0
  73. package/dist/cloud/inventory.d.ts +100 -0
  74. package/dist/cloud/inventory.js +229 -0
  75. package/dist/cloud/pricing.d.ts +27 -0
  76. package/dist/cloud/pricing.js +103 -0
  77. package/dist/cloud/token-instructions.d.ts +2 -0
  78. package/dist/cloud/token-instructions.js +21 -0
  79. package/dist/cloud/types.d.ts +437 -0
  80. package/dist/cloud/types.js +5 -0
  81. package/dist/config.d.ts +1 -0
  82. package/dist/config.js +2 -0
  83. package/dist/formatter.d.ts +3 -0
  84. package/dist/formatter.js +6 -0
  85. package/dist/index.d.ts +12 -0
  86. package/dist/index.js +21 -0
  87. package/dist/robot/client.d.ts +256 -0
  88. package/dist/robot/client.js +745 -0
  89. package/dist/robot/commands/auth.d.ts +2 -0
  90. package/dist/robot/commands/auth.js +54 -0
  91. package/dist/robot/commands/boot.d.ts +2 -0
  92. package/dist/robot/commands/boot.js +76 -0
  93. package/dist/robot/commands/cancel.d.ts +2 -0
  94. package/dist/robot/commands/cancel.js +37 -0
  95. package/dist/robot/commands/failover.d.ts +2 -0
  96. package/dist/robot/commands/failover.js +46 -0
  97. package/dist/robot/commands/firewall.d.ts +2 -0
  98. package/dist/robot/commands/firewall.js +72 -0
  99. package/dist/robot/commands/index.d.ts +2 -0
  100. package/dist/robot/commands/index.js +36 -0
  101. package/dist/robot/commands/interactive.d.ts +2 -0
  102. package/dist/robot/commands/interactive.js +152 -0
  103. package/dist/robot/commands/ip.d.ts +2 -0
  104. package/dist/robot/commands/ip.js +55 -0
  105. package/dist/robot/commands/key.d.ts +2 -0
  106. package/dist/robot/commands/key.js +68 -0
  107. package/dist/robot/commands/order.d.ts +2 -0
  108. package/dist/robot/commands/order.js +33 -0
  109. package/dist/robot/commands/rdns.d.ts +2 -0
  110. package/dist/robot/commands/rdns.js +41 -0
  111. package/dist/robot/commands/reset.d.ts +2 -0
  112. package/dist/robot/commands/reset.js +77 -0
  113. package/dist/robot/commands/server.d.ts +2 -0
  114. package/dist/robot/commands/server.js +32 -0
  115. package/dist/robot/commands/storagebox.d.ts +2 -0
  116. package/dist/robot/commands/storagebox.js +126 -0
  117. package/dist/robot/commands/subnet.d.ts +2 -0
  118. package/dist/robot/commands/subnet.js +24 -0
  119. package/dist/robot/commands/traffic.d.ts +2 -0
  120. package/dist/robot/commands/traffic.js +23 -0
  121. package/dist/robot/commands/vswitch.d.ts +2 -0
  122. package/dist/robot/commands/vswitch.js +81 -0
  123. package/dist/robot/commands/wol.d.ts +2 -0
  124. package/dist/robot/commands/wol.js +20 -0
  125. package/dist/robot/formatter.d.ts +57 -0
  126. package/dist/robot/formatter.js +582 -0
  127. package/dist/robot/types.d.ts +359 -0
  128. package/dist/robot/types.js +5 -0
  129. package/dist/shared/config.d.ts +86 -0
  130. package/dist/shared/config.js +289 -0
  131. package/dist/shared/formatter.d.ts +29 -0
  132. package/dist/shared/formatter.js +121 -0
  133. package/dist/shared/helpers.d.ts +39 -0
  134. package/dist/shared/helpers.js +86 -0
  135. package/dist/shared/init.d.ts +2 -0
  136. package/dist/shared/init.js +107 -0
  137. package/dist/shared/reference.d.ts +5 -0
  138. package/dist/shared/reference.js +689 -0
  139. package/dist/shared/schemas.d.ts +1 -0
  140. package/dist/shared/schemas.js +1031 -0
  141. package/dist/types.d.ts +2 -0
  142. package/dist/types.js +2 -0
  143. package/package.json +127 -4
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerAuthCommands(parent: Command): void;
@@ -0,0 +1,54 @@
1
+ import { clearConfig, getCredentials, promptLogin, } from "../../shared/config.js";
2
+ import { info, success, warning } from "../../shared/formatter.js";
3
+ import { asyncAction } from "../../shared/helpers.js";
4
+ export function registerAuthCommands(parent) {
5
+ const auth = parent.command("auth").description("Authentication management");
6
+ auth
7
+ .command("login")
8
+ .description("Interactively configure credentials")
9
+ .action(async () => {
10
+ try {
11
+ await promptLogin();
12
+ console.log("");
13
+ console.log(success("Authentication configured successfully."));
14
+ }
15
+ catch (error) {
16
+ if (error instanceof Error && error.name === "ExitPromptError") {
17
+ process.exit(0);
18
+ }
19
+ throw error;
20
+ }
21
+ });
22
+ auth
23
+ .command("logout")
24
+ .description("Clear saved credentials")
25
+ .action(async () => {
26
+ await clearConfig();
27
+ console.log(success("Credentials cleared."));
28
+ });
29
+ auth
30
+ .command("status")
31
+ .description("Check authentication status")
32
+ .action(async () => {
33
+ const creds = await getCredentials();
34
+ if (creds) {
35
+ console.log(success(`Authenticated as: ${creds.user}`));
36
+ const sourceLabels = {
37
+ environment: "environment variables",
38
+ keychain: "keychain",
39
+ file: "config file",
40
+ };
41
+ console.log(info(`Stored in: ${sourceLabels[creds.source ?? ""] ?? "unknown"}`));
42
+ }
43
+ else {
44
+ console.log(warning("Not authenticated. Run: hctl auth login"));
45
+ }
46
+ });
47
+ auth
48
+ .command("test")
49
+ .description("Test API credentials")
50
+ .action(asyncAction(async (client) => {
51
+ const servers = await client.listServers();
52
+ console.log(success(`Authenticated successfully. Found ${servers.length} server(s).`));
53
+ }));
54
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerBootCommands(parent: Command): void;
@@ -0,0 +1,76 @@
1
+ import { heading, info, success } from "../../shared/formatter.js";
2
+ import { asyncAction, output, } from "../../shared/helpers.js";
3
+ import { formatBootConfig, formatLinuxActivation, formatRescueActivation, } from "../formatter.js";
4
+ export function registerBootCommands(parent) {
5
+ const boot = parent
6
+ .command("boot")
7
+ .description("Boot configuration (rescue, linux, vnc, windows)");
8
+ boot
9
+ .command("status <server>")
10
+ .description("Show boot configuration status")
11
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
12
+ const { boot: bootConfig } = await client.getBootConfig(serverIdOrIp);
13
+ output(bootConfig, (b) => formatBootConfig(b, Number.parseInt(serverIdOrIp, 10) || 0), options);
14
+ }));
15
+ const rescue = boot.command("rescue").description("Rescue system management");
16
+ rescue
17
+ .command("activate <server>")
18
+ .description("Activate rescue system")
19
+ .option("-o, --os <os>", "Operating system (linux, linuxold, vkvm)", "linux")
20
+ .option("-a, --arch <arch>", "Architecture (64 or 32)", "64")
21
+ .option("-k, --keys <fingerprints...>", "SSH key fingerprints")
22
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
23
+ const { rescue: rsc } = await client.activateRescue(serverIdOrIp, options.os, Number.parseInt(options.arch, 10), options.keys);
24
+ console.log(formatRescueActivation(rsc));
25
+ }));
26
+ rescue
27
+ .command("deactivate <server>")
28
+ .description("Deactivate rescue system")
29
+ .action(asyncAction(async (client, serverIdOrIp) => {
30
+ await client.deactivateRescue(serverIdOrIp);
31
+ console.log(success("Rescue system deactivated."));
32
+ }));
33
+ rescue
34
+ .command("last <server>")
35
+ .description("Show last rescue activation details")
36
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
37
+ const { rescue: rsc } = await client.getLastRescue(serverIdOrIp);
38
+ output(rsc, formatRescueActivation, options);
39
+ }));
40
+ const linux = boot
41
+ .command("linux")
42
+ .description("Linux installation management");
43
+ linux
44
+ .command("activate <server>")
45
+ .description("Activate Linux installation")
46
+ .requiredOption("-d, --dist <dist>", "Distribution (e.g., Debian-1210-bookworm-amd64-base)")
47
+ .option("-a, --arch <arch>", "Architecture (64 or 32)", "64")
48
+ .option("-l, --lang <lang>", "Language", "en")
49
+ .option("-k, --keys <fingerprints...>", "SSH key fingerprints")
50
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
51
+ const { linux: lnx } = await client.activateLinux(serverIdOrIp, options.dist, Number.parseInt(options.arch, 10), options.lang, options.keys);
52
+ console.log(formatLinuxActivation(lnx));
53
+ }));
54
+ linux
55
+ .command("deactivate <server>")
56
+ .description("Deactivate Linux installation")
57
+ .action(asyncAction(async (client, serverIdOrIp) => {
58
+ await client.deactivateLinux(serverIdOrIp);
59
+ console.log(success("Linux installation deactivated."));
60
+ }));
61
+ linux
62
+ .command("options <server>")
63
+ .description("Show available Linux distributions")
64
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
65
+ const { linux: lnx } = await client.getLinux(serverIdOrIp);
66
+ output(lnx, (l) => {
67
+ const lines = [heading("Available Linux Distributions"), ""];
68
+ for (const dist of l.dist) {
69
+ lines.push(` ${dist}`);
70
+ }
71
+ lines.push("", info(`Languages: ${l.lang.join(", ")}`));
72
+ lines.push(info(`Architectures: ${l.arch.join(", ")}-bit`));
73
+ return lines.join("\n");
74
+ }, options);
75
+ }));
76
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerCancelCommands(parent: Command): void;
@@ -0,0 +1,37 @@
1
+ import { success, warning } from "../../shared/formatter.js";
2
+ import { asyncAction, confirmAction, output, } from "../../shared/helpers.js";
3
+ import { formatCancellation } from "../formatter.js";
4
+ export function registerCancelCommands(parent) {
5
+ const cancel = parent.command("cancel").description("Server cancellation");
6
+ cancel
7
+ .command("status <server>")
8
+ .description("Get cancellation status")
9
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
10
+ const { cancellation } = await client.getCancellation(serverIdOrIp);
11
+ output(cancellation, formatCancellation, options);
12
+ }));
13
+ cancel
14
+ .command("request <server>")
15
+ .description("Request server cancellation")
16
+ .option("--date <date>", "Cancellation date (YYYY-MM-DD)")
17
+ .option("--reason <reasons...>", "Cancellation reasons")
18
+ .option("-y, --yes", "Skip confirmation")
19
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
20
+ if (!options.yes) {
21
+ console.log(warning("This will cancel your server!"));
22
+ }
23
+ if (!(await confirmAction("Are you sure you want to cancel this server?", options))) {
24
+ return;
25
+ }
26
+ const { cancellation } = await client.cancelServer(serverIdOrIp, options.date, options.reason);
27
+ console.log(success("Cancellation requested."));
28
+ console.log(formatCancellation(cancellation));
29
+ }));
30
+ cancel
31
+ .command("revoke <server>")
32
+ .description("Revoke server cancellation")
33
+ .action(asyncAction(async (client, serverIdOrIp) => {
34
+ await client.revokeCancellation(serverIdOrIp);
35
+ console.log(success("Cancellation revoked."));
36
+ }));
37
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerFailoverCommands(parent: Command): void;
@@ -0,0 +1,46 @@
1
+ import { success } from "../../shared/formatter.js";
2
+ import { asyncAction, confirmAction, output, } from "../../shared/helpers.js";
3
+ import { formatFailoverList, formatFailoverSwitch } from "../formatter.js";
4
+ export function registerFailoverCommands(parent) {
5
+ const failover = parent
6
+ .command("failover")
7
+ .description("Failover IP management");
8
+ failover
9
+ .command("list")
10
+ .alias("ls")
11
+ .description("List all failover IPs")
12
+ .action(asyncAction(async (client, options) => {
13
+ const failovers = await client.listFailovers();
14
+ output(failovers, formatFailoverList, options);
15
+ }));
16
+ failover
17
+ .command("get <ip>")
18
+ .alias("show")
19
+ .description("Get failover IP details")
20
+ .action(asyncAction(async (client, failoverIp, options) => {
21
+ const { failover: fo } = await client.getFailover(failoverIp);
22
+ output(fo, (f) => formatFailoverList([{ failover: f }]), options);
23
+ }));
24
+ failover
25
+ .command("switch <failover-ip> <target-server-ip>")
26
+ .description("Switch failover IP routing to another server")
27
+ .option("-y, --yes", "Skip confirmation")
28
+ .action(asyncAction(async (client, failoverIp, targetServerIp, options) => {
29
+ if (!(await confirmAction(`Route ${failoverIp} to ${targetServerIp}?`, options, true))) {
30
+ return;
31
+ }
32
+ const { failover: fo } = await client.switchFailover(failoverIp, targetServerIp);
33
+ console.log(formatFailoverSwitch(fo));
34
+ }));
35
+ failover
36
+ .command("delete <ip>")
37
+ .description("Delete failover IP routing")
38
+ .option("-y, --yes", "Skip confirmation")
39
+ .action(asyncAction(async (client, failoverIp, options) => {
40
+ if (!(await confirmAction(`Delete routing for ${failoverIp}?`, options))) {
41
+ return;
42
+ }
43
+ await client.deleteFailoverRouting(failoverIp);
44
+ console.log(success("Failover routing deleted."));
45
+ }));
46
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerFirewallCommands(parent: Command): void;
@@ -0,0 +1,72 @@
1
+ import { success } from "../../shared/formatter.js";
2
+ import { asyncAction, confirmAction, output, } from "../../shared/helpers.js";
3
+ import { formatFirewall, formatFirewallTemplateList } from "../formatter.js";
4
+ export function registerFirewallCommands(parent) {
5
+ const firewall = parent
6
+ .command("firewall")
7
+ .description("Firewall management");
8
+ firewall
9
+ .command("get <server>")
10
+ .alias("show")
11
+ .description("Get firewall configuration")
12
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
13
+ const { firewall: fw } = await client.getFirewall(serverIdOrIp);
14
+ output(fw, formatFirewall, options);
15
+ }));
16
+ firewall
17
+ .command("enable <server>")
18
+ .description("Enable firewall")
19
+ .action(asyncAction(async (client, serverIdOrIp) => {
20
+ await client.updateFirewall(serverIdOrIp, "active");
21
+ console.log(success("Firewall enabled."));
22
+ }));
23
+ firewall
24
+ .command("disable <server>")
25
+ .description("Disable firewall")
26
+ .action(asyncAction(async (client, serverIdOrIp) => {
27
+ await client.updateFirewall(serverIdOrIp, "disabled");
28
+ console.log(success("Firewall disabled."));
29
+ }));
30
+ firewall
31
+ .command("delete <server>")
32
+ .description("Delete all firewall rules")
33
+ .option("-y, --yes", "Skip confirmation")
34
+ .action(asyncAction(async (client, serverIdOrIp, options) => {
35
+ if (!(await confirmAction("Delete all firewall rules?", options))) {
36
+ return;
37
+ }
38
+ await client.deleteFirewall(serverIdOrIp);
39
+ console.log(success("Firewall rules deleted."));
40
+ }));
41
+ const fwTemplate = firewall
42
+ .command("template")
43
+ .description("Firewall template management");
44
+ fwTemplate
45
+ .command("list")
46
+ .alias("ls")
47
+ .description("List firewall templates")
48
+ .action(asyncAction(async (client, options) => {
49
+ const templates = await client.listFirewallTemplates();
50
+ output(templates, formatFirewallTemplateList, options);
51
+ }));
52
+ fwTemplate
53
+ .command("get <id>")
54
+ .alias("show")
55
+ .description("Get firewall template details")
56
+ .action(asyncAction(async (client, templateId, options) => {
57
+ const { firewall_template: tmpl } = await client.getFirewallTemplate(Number.parseInt(templateId, 10));
58
+ output(tmpl, (t) => formatFirewallTemplateList([{ firewall_template: t }]), options);
59
+ }));
60
+ fwTemplate
61
+ .command("delete <id>")
62
+ .alias("rm")
63
+ .description("Delete firewall template")
64
+ .option("-y, --yes", "Skip confirmation")
65
+ .action(asyncAction(async (client, templateId, options) => {
66
+ if (!(await confirmAction(`Delete firewall template ${templateId}?`, options))) {
67
+ return;
68
+ }
69
+ await client.deleteFirewallTemplate(Number.parseInt(templateId, 10));
70
+ console.log(success("Firewall template deleted."));
71
+ }));
72
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerRobotCommands(parent: Command): void;
@@ -0,0 +1,36 @@
1
+ import { registerAuthCommands } from "./auth.js";
2
+ import { registerBootCommands } from "./boot.js";
3
+ import { registerCancelCommands } from "./cancel.js";
4
+ import { registerFailoverCommands } from "./failover.js";
5
+ import { registerFirewallCommands } from "./firewall.js";
6
+ import { registerInteractiveCommands } from "./interactive.js";
7
+ import { registerIpCommands } from "./ip.js";
8
+ import { registerKeyCommands } from "./key.js";
9
+ import { registerOrderCommands } from "./order.js";
10
+ import { registerRdnsCommands } from "./rdns.js";
11
+ import { registerResetCommands } from "./reset.js";
12
+ import { registerServerCommands } from "./server.js";
13
+ import { registerStorageBoxCommands } from "./storagebox.js";
14
+ import { registerSubnetCommands } from "./subnet.js";
15
+ import { registerTrafficCommands } from "./traffic.js";
16
+ import { registerVSwitchCommands } from "./vswitch.js";
17
+ import { registerWolCommands } from "./wol.js";
18
+ export function registerRobotCommands(parent) {
19
+ registerAuthCommands(parent);
20
+ registerServerCommands(parent);
21
+ registerResetCommands(parent);
22
+ registerBootCommands(parent);
23
+ registerIpCommands(parent);
24
+ registerSubnetCommands(parent);
25
+ registerFailoverCommands(parent);
26
+ registerRdnsCommands(parent);
27
+ registerKeyCommands(parent);
28
+ registerFirewallCommands(parent);
29
+ registerVSwitchCommands(parent);
30
+ registerStorageBoxCommands(parent);
31
+ registerTrafficCommands(parent);
32
+ registerWolCommands(parent);
33
+ registerCancelCommands(parent);
34
+ registerOrderCommands(parent);
35
+ registerInteractiveCommands(parent);
36
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerInteractiveCommands(parent: Command): void;
@@ -0,0 +1,152 @@
1
+ import { checkbox, confirm, select } from "@inquirer/prompts";
2
+ import { error as fmtError, info } from "../../shared/formatter.js";
3
+ import { asyncAction } from "../../shared/helpers.js";
4
+ import { formatFailoverSwitch, formatRescueActivation, formatResetResult, formatServerList, formatSshKeyList, } from "../formatter.js";
5
+ async function handleServers(client) {
6
+ const servers = await client.listServers();
7
+ console.log("");
8
+ console.log(formatServerList(servers));
9
+ console.log("");
10
+ }
11
+ async function handleReset(client) {
12
+ const servers = await client.listServers();
13
+ if (servers.length === 0) {
14
+ console.log(info("No servers found."));
15
+ return false;
16
+ }
17
+ const selected = await checkbox({
18
+ message: "Select servers to reset:",
19
+ choices: servers.map(({ server }) => ({
20
+ value: server.server_ip,
21
+ name: `${server.server_number} - ${server.server_ip} (${server.server_name || "unnamed"})`,
22
+ })),
23
+ });
24
+ if (selected.length === 0) {
25
+ console.log("No servers selected.");
26
+ return false;
27
+ }
28
+ const resetType = (await select({
29
+ message: "Select reset type:",
30
+ choices: [
31
+ { value: "sw", name: "Software reset (ACPI)" },
32
+ { value: "hw", name: "Hardware reset (forced)" },
33
+ { value: "power", name: "Power cycle" },
34
+ ],
35
+ }));
36
+ const confirmed = await confirm({
37
+ message: `Reset ${selected.length} server(s) with ${resetType}?`,
38
+ default: false,
39
+ });
40
+ if (confirmed) {
41
+ for (const srv of selected) {
42
+ try {
43
+ const { reset: rst } = await client.resetServer(srv, resetType);
44
+ console.log(formatResetResult(rst, resetType));
45
+ }
46
+ catch (err) {
47
+ console.log(fmtError(`Failed to reset ${srv}: ${err instanceof Error ? err.message : "Unknown"}`));
48
+ }
49
+ }
50
+ }
51
+ return true;
52
+ }
53
+ async function handleRescue(client) {
54
+ const servers = await client.listServers();
55
+ if (servers.length === 0) {
56
+ console.log(info("No servers found."));
57
+ return false;
58
+ }
59
+ const serverIp = await select({
60
+ message: "Select server:",
61
+ choices: servers.map(({ server }) => ({
62
+ value: server.server_ip,
63
+ name: `${server.server_number} - ${server.server_ip} (${server.server_name || "unnamed"})`,
64
+ })),
65
+ });
66
+ const os = await select({
67
+ message: "Select rescue OS:",
68
+ choices: [
69
+ { value: "linux", name: "Linux (64-bit)" },
70
+ { value: "linuxold", name: "Linux (32-bit)" },
71
+ { value: "vkvm", name: "vKVM" },
72
+ ],
73
+ });
74
+ const { rescue } = await client.activateRescue(serverIp, os, 64);
75
+ console.log("");
76
+ console.log(formatRescueActivation(rescue));
77
+ return true;
78
+ }
79
+ async function handleFailover(client) {
80
+ const failovers = await client.listFailovers();
81
+ if (failovers.length === 0) {
82
+ console.log(info("No failover IPs found."));
83
+ return false;
84
+ }
85
+ const failoverIp = await select({
86
+ message: "Select failover IP:",
87
+ choices: failovers.map(({ failover }) => ({
88
+ value: failover.ip,
89
+ name: `${failover.ip} -> ${failover.active_server_ip}`,
90
+ })),
91
+ });
92
+ const servers = await client.listServers();
93
+ const targetIp = await select({
94
+ message: "Route to server:",
95
+ choices: servers.map(({ server }) => ({
96
+ value: server.server_ip,
97
+ name: `${server.server_number} - ${server.server_ip}`,
98
+ })),
99
+ });
100
+ const { failover: fo } = await client.switchFailover(failoverIp, targetIp);
101
+ console.log("");
102
+ console.log(formatFailoverSwitch(fo));
103
+ return true;
104
+ }
105
+ async function handleKeys(client) {
106
+ const keys = await client.listSshKeys();
107
+ console.log("");
108
+ console.log(formatSshKeyList(keys));
109
+ console.log("");
110
+ }
111
+ export function registerInteractiveCommands(parent) {
112
+ parent
113
+ .command("interactive")
114
+ .alias("i")
115
+ .description("Interactive mode for common operations")
116
+ .action(asyncAction(async (client) => {
117
+ while (true) {
118
+ const action = await select({
119
+ message: "What would you like to do?",
120
+ choices: [
121
+ { value: "servers", name: "List servers" },
122
+ { value: "reset", name: "Reset a server" },
123
+ { value: "rescue", name: "Activate rescue mode" },
124
+ { value: "failover", name: "Switch failover IP" },
125
+ { value: "keys", name: "Manage SSH keys" },
126
+ { value: "exit", name: "Exit" },
127
+ ],
128
+ pageSize: 10,
129
+ });
130
+ if (action === "exit") {
131
+ console.log("Goodbye!");
132
+ break;
133
+ }
134
+ if (action === "servers") {
135
+ await handleServers(client);
136
+ }
137
+ else if (action === "reset") {
138
+ await handleReset(client);
139
+ }
140
+ else if (action === "rescue") {
141
+ await handleRescue(client);
142
+ }
143
+ else if (action === "failover") {
144
+ await handleFailover(client);
145
+ }
146
+ else if (action === "keys") {
147
+ await handleKeys(client);
148
+ }
149
+ console.log("");
150
+ }
151
+ }));
152
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerIpCommands(parent: Command): void;
@@ -0,0 +1,55 @@
1
+ import { success } from "../../shared/formatter.js";
2
+ import { asyncAction, output, } from "../../shared/helpers.js";
3
+ import { formatIpDetails, formatIpList } from "../formatter.js";
4
+ export function registerIpCommands(parent) {
5
+ const ip = parent
6
+ .command("ip")
7
+ .alias("ips")
8
+ .description("IP address management");
9
+ ip.command("list")
10
+ .alias("ls")
11
+ .description("List all IPs")
12
+ .action(asyncAction(async (client, options) => {
13
+ const ips = await client.listIps();
14
+ output(ips, formatIpList, options);
15
+ }));
16
+ ip.command("get <ip>")
17
+ .alias("show")
18
+ .description("Get IP details")
19
+ .action(asyncAction(async (client, ipAddr, options) => {
20
+ const { ip: ipData } = await client.getIp(ipAddr);
21
+ output(ipData, formatIpDetails, options);
22
+ }));
23
+ ip.command("update <ip>")
24
+ .description("Update IP traffic warning settings")
25
+ .option("--warnings <enabled>", "Enable/disable traffic warnings (true/false)")
26
+ .option("--hourly <mb>", "Hourly traffic limit in MB")
27
+ .option("--daily <mb>", "Daily traffic limit in MB")
28
+ .option("--monthly <gb>", "Monthly traffic limit in GB")
29
+ .action(asyncAction(async (client, ipAddr, options) => {
30
+ await client.updateIp(ipAddr, options.warnings ? options.warnings === "true" : undefined, options.hourly ? Number.parseInt(options.hourly, 10) : undefined, options.daily ? Number.parseInt(options.daily, 10) : undefined, options.monthly ? Number.parseInt(options.monthly, 10) : undefined);
31
+ console.log(success(`IP ${ipAddr} updated.`));
32
+ }));
33
+ const mac = ip.command("mac").description("MAC address management");
34
+ mac
35
+ .command("get <ip>")
36
+ .description("Get separate MAC address for IP")
37
+ .action(asyncAction(async (client, ipAddr, options) => {
38
+ const { mac: macData } = await client.getIpMac(ipAddr);
39
+ output(macData, (m) => `IP: ${m.ip}\nMAC: ${m.mac}`, options);
40
+ }));
41
+ mac
42
+ .command("generate <ip>")
43
+ .description("Generate separate MAC address for IP")
44
+ .action(asyncAction(async (client, ipAddr) => {
45
+ const { mac: macData } = await client.generateIpMac(ipAddr);
46
+ console.log(success(`Generated MAC: ${macData.mac}`));
47
+ }));
48
+ mac
49
+ .command("delete <ip>")
50
+ .description("Delete separate MAC address")
51
+ .action(asyncAction(async (client, ipAddr) => {
52
+ await client.deleteIpMac(ipAddr);
53
+ console.log(success("MAC address deleted."));
54
+ }));
55
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerKeyCommands(parent: Command): void;
@@ -0,0 +1,68 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { input } from "@inquirer/prompts";
3
+ import { success } from "../../shared/formatter.js";
4
+ import { asyncAction, confirmAction, output, } from "../../shared/helpers.js";
5
+ import { formatSshKeyDetails, formatSshKeyList } from "../formatter.js";
6
+ export function registerKeyCommands(parent) {
7
+ const key = parent
8
+ .command("key")
9
+ .alias("keys")
10
+ .description("SSH key management");
11
+ key
12
+ .command("list")
13
+ .alias("ls")
14
+ .description("List all SSH keys")
15
+ .action(asyncAction(async (client, options) => {
16
+ const keys = await client.listSshKeys();
17
+ output(keys, formatSshKeyList, options);
18
+ }));
19
+ key
20
+ .command("get <fingerprint>")
21
+ .alias("show")
22
+ .description("Get SSH key details")
23
+ .action(asyncAction(async (client, fingerprint, options) => {
24
+ const { key: keyData } = await client.getSshKey(fingerprint);
25
+ output(keyData, formatSshKeyDetails, options);
26
+ }));
27
+ key
28
+ .command("add <name>")
29
+ .description("Add a new SSH key")
30
+ .option("-f, --file <path>", "Path to public key file")
31
+ .option("-d, --data <key>", "Public key data")
32
+ .action(asyncAction(async (client, name, options) => {
33
+ let keyData;
34
+ if (options.file) {
35
+ keyData = readFileSync(options.file, "utf-8").trim();
36
+ }
37
+ else if (options.data) {
38
+ keyData = options.data;
39
+ }
40
+ else {
41
+ keyData = await input({
42
+ message: "Paste public key:",
43
+ validate: (v) => v.length > 0 || "Key data is required",
44
+ });
45
+ }
46
+ const { key: newKey } = await client.createSshKey(name, keyData);
47
+ console.log(success(`SSH key added: ${newKey.fingerprint}`));
48
+ }));
49
+ key
50
+ .command("rename <fingerprint> <name>")
51
+ .description("Rename an SSH key")
52
+ .action(asyncAction(async (client, fingerprint, name) => {
53
+ await client.updateSshKey(fingerprint, name);
54
+ console.log(success(`SSH key renamed to: ${name}`));
55
+ }));
56
+ key
57
+ .command("delete <fingerprint>")
58
+ .alias("rm")
59
+ .description("Delete an SSH key")
60
+ .option("-y, --yes", "Skip confirmation")
61
+ .action(asyncAction(async (client, fingerprint, options) => {
62
+ if (!(await confirmAction(`Delete SSH key ${fingerprint}?`, options))) {
63
+ return;
64
+ }
65
+ await client.deleteSshKey(fingerprint);
66
+ console.log(success("SSH key deleted."));
67
+ }));
68
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerOrderCommands(parent: Command): void;