@jango-blockchained/hoox-cli 0.5.2 → 0.5.6

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 (114) hide show
  1. package/bin/hoox.js +3 -4
  2. package/dist/index.js +32545 -0
  3. package/package.json +10 -15
  4. package/src/commands/check/check-command.test.ts +0 -476
  5. package/src/commands/check/check-command.ts +0 -1087
  6. package/src/commands/check/index.ts +0 -10
  7. package/src/commands/check/prerequisites-command.test.ts +0 -19
  8. package/src/commands/check/prerequisites-command.ts +0 -97
  9. package/src/commands/check/types.ts +0 -103
  10. package/src/commands/clone/clone-command.test.ts +0 -440
  11. package/src/commands/clone/clone-command.ts +0 -431
  12. package/src/commands/clone/index.ts +0 -1
  13. package/src/commands/config/config-command.test.ts +0 -583
  14. package/src/commands/config/config-command.ts +0 -896
  15. package/src/commands/config/env-command.test.ts +0 -43
  16. package/src/commands/config/env-command.ts +0 -292
  17. package/src/commands/config/index.ts +0 -3
  18. package/src/commands/config/kv-command.test.ts +0 -14
  19. package/src/commands/config/kv-command.ts +0 -290
  20. package/src/commands/dashboard/dashboard-command.test.ts +0 -47
  21. package/src/commands/dashboard/dashboard-command.ts +0 -130
  22. package/src/commands/dashboard/index.ts +0 -1
  23. package/src/commands/db/db-command.test.ts +0 -21
  24. package/src/commands/db/db-command.ts +0 -311
  25. package/src/commands/db/index.ts +0 -1
  26. package/src/commands/deploy/deploy-command.test.ts +0 -324
  27. package/src/commands/deploy/deploy-command.ts +0 -1054
  28. package/src/commands/deploy/index.ts +0 -2
  29. package/src/commands/deploy/telegram-service.ts +0 -76
  30. package/src/commands/deploy/types.ts +0 -34
  31. package/src/commands/dev/dev-command.test.ts +0 -405
  32. package/src/commands/dev/dev-command.ts +0 -398
  33. package/src/commands/dev/index.ts +0 -1
  34. package/src/commands/disclaimer/disclaimer-command.ts +0 -21
  35. package/src/commands/disclaimer/index.ts +0 -1
  36. package/src/commands/infra/index.ts +0 -5
  37. package/src/commands/infra/infra-command.test.ts +0 -719
  38. package/src/commands/infra/infra-command.ts +0 -974
  39. package/src/commands/infra/types.ts +0 -23
  40. package/src/commands/init/__tests__/cli-provisioner.test.ts +0 -17
  41. package/src/commands/init/cli-provisioner.ts +0 -71
  42. package/src/commands/init/index.ts +0 -1
  43. package/src/commands/init/init-command.test.ts +0 -854
  44. package/src/commands/init/init-command.ts +0 -597
  45. package/src/commands/init/types.ts +0 -23
  46. package/src/commands/logs/index.ts +0 -1
  47. package/src/commands/logs/logs-command.test.ts +0 -293
  48. package/src/commands/logs/logs-command.ts +0 -452
  49. package/src/commands/monitor/index.ts +0 -2
  50. package/src/commands/monitor/monitor-command.test.ts +0 -271
  51. package/src/commands/monitor/monitor-command.ts +0 -269
  52. package/src/commands/monitor/monitor-service.ts +0 -65
  53. package/src/commands/monitor/types.ts +0 -13
  54. package/src/commands/repair/index.ts +0 -2
  55. package/src/commands/repair/repair-command.test.ts +0 -243
  56. package/src/commands/repair/repair-command.ts +0 -220
  57. package/src/commands/repair/repair-service.ts +0 -164
  58. package/src/commands/repair/types.ts +0 -13
  59. package/src/commands/schema/index.ts +0 -1
  60. package/src/commands/schema/schema-command.ts +0 -137
  61. package/src/commands/test/index.ts +0 -2
  62. package/src/commands/test/test-command.test.ts +0 -318
  63. package/src/commands/test/test-command.ts +0 -406
  64. package/src/commands/tui/index.ts +0 -1
  65. package/src/commands/tui/tui-command.ts +0 -87
  66. package/src/commands/update/index.ts +0 -1
  67. package/src/commands/update/update-command.ts +0 -109
  68. package/src/commands/waf/index.ts +0 -2
  69. package/src/commands/waf/types.ts +0 -48
  70. package/src/commands/waf/waf-command.test.ts +0 -506
  71. package/src/commands/waf/waf-command.ts +0 -545
  72. package/src/index.ts +0 -261
  73. package/src/services/cloudflare/cloudflare-service.test.ts +0 -658
  74. package/src/services/cloudflare/cloudflare-service.ts +0 -433
  75. package/src/services/cloudflare/index.ts +0 -2
  76. package/src/services/cloudflare/types.ts +0 -30
  77. package/src/services/config/config-service.test.ts +0 -395
  78. package/src/services/config/config-service.ts +0 -202
  79. package/src/services/config/index.ts +0 -9
  80. package/src/services/config/types.ts +0 -66
  81. package/src/services/db/db-service.test.ts +0 -63
  82. package/src/services/db/db-service.ts +0 -131
  83. package/src/services/db/index.ts +0 -1
  84. package/src/services/docker/docker-service.ts +0 -155
  85. package/src/services/docker/index.ts +0 -1
  86. package/src/services/env/env-service.test.ts +0 -259
  87. package/src/services/env/env-service.ts +0 -372
  88. package/src/services/env/index.ts +0 -1
  89. package/src/services/kv/index.ts +0 -1
  90. package/src/services/kv/kv-sync-service.test.ts +0 -38
  91. package/src/services/kv/kv-sync-service.ts +0 -243
  92. package/src/services/prerequisites/index.ts +0 -1
  93. package/src/services/prerequisites/prerequisites-service.test.ts +0 -89
  94. package/src/services/prerequisites/prerequisites-service.ts +0 -377
  95. package/src/services/prerequisites/types.ts +0 -48
  96. package/src/services/schema/index.ts +0 -1
  97. package/src/services/schema/schema-service.ts +0 -99
  98. package/src/services/secrets/index.ts +0 -11
  99. package/src/services/secrets/secrets-service.test.ts +0 -502
  100. package/src/services/secrets/secrets-service.ts +0 -287
  101. package/src/services/secrets/types.ts +0 -50
  102. package/src/services/update/index.ts +0 -2
  103. package/src/services/update/update-service.test.ts +0 -76
  104. package/src/services/update/update-service.ts +0 -193
  105. package/src/ui/banner.ts +0 -141
  106. package/src/ui/index.ts +0 -8
  107. package/src/ui/menu.ts +0 -490
  108. package/src/utils/error-handler.ts +0 -62
  109. package/src/utils/errors.test.ts +0 -69
  110. package/src/utils/errors.ts +0 -24
  111. package/src/utils/formatters.test.ts +0 -180
  112. package/src/utils/formatters.ts +0 -269
  113. package/src/utils/git.ts +0 -134
  114. package/src/utils/theme.ts +0 -92
@@ -1,271 +0,0 @@
1
- /**
2
- * Unit tests for the monitor command.
3
- *
4
- * Stubs MonitorService, DbService, and KvSyncService prototypes to verify
5
- * the monitor command logic in isolation. Uses Commander's exitOverride to
6
- * suppress process exits during test runs.
7
- */
8
- import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
9
- import { Command } from "commander";
10
- import { MonitorService } from "./monitor-service.js";
11
- import { DbService } from "../../services/db/db-service.js";
12
- import { KvSyncService } from "../../services/kv/kv-sync-service.js";
13
-
14
- // Stub variables
15
- let checkAllWorkerHealthMock: ReturnType<typeof mock>;
16
- let resolveDbNameMock: ReturnType<typeof mock>;
17
- let queryMock: ReturnType<typeof mock>;
18
- let exportMock: ReturnType<typeof mock>;
19
- let resolveNamespaceIdMock: ReturnType<typeof mock>;
20
- let getMock: ReturnType<typeof mock>;
21
- let setMock: ReturnType<typeof mock>;
22
-
23
- // Preserve originals
24
- const origCheckAll = MonitorService.prototype.checkAllWorkerHealth;
25
- const origResolveDbName = DbService.prototype.resolveDbName;
26
- const origQuery = DbService.prototype.query;
27
- const origExport = DbService.prototype.export;
28
- const origResolveNs = KvSyncService.prototype.resolveNamespaceId;
29
- const origGet = KvSyncService.prototype.get;
30
- const origSet = KvSyncService.prototype.set;
31
-
32
- beforeEach(() => {
33
- mock.restore();
34
- process.exitCode = 0;
35
-
36
- // Restore originals
37
- (
38
- MonitorService.prototype as unknown as Record<string, unknown>
39
- ).checkAllWorkerHealth = origCheckAll;
40
- (DbService.prototype as unknown as Record<string, unknown>).resolveDbName =
41
- origResolveDbName;
42
- (DbService.prototype as unknown as Record<string, unknown>).query = origQuery;
43
- (DbService.prototype as unknown as Record<string, unknown>).export =
44
- origExport;
45
- (
46
- KvSyncService.prototype as unknown as Record<string, unknown>
47
- ).resolveNamespaceId = origResolveNs;
48
- (KvSyncService.prototype as unknown as Record<string, unknown>).get = origGet;
49
- (KvSyncService.prototype as unknown as Record<string, unknown>).set = origSet;
50
-
51
- // Fresh mocks
52
- checkAllWorkerHealthMock = mock(async () => ({
53
- workers: [
54
- { worker: "hoox", status: "healthy", statusCode: 200 },
55
- { worker: "trade-worker", status: "healthy", statusCode: 200 },
56
- ],
57
- healthyCount: 2,
58
- degradedCount: 0,
59
- unreachableCount: 0,
60
- }));
61
-
62
- resolveDbNameMock = mock(async () => "trade-data-db");
63
- queryMock = mock(
64
- async (_dbName: string, _sql: string, _remote: boolean) =>
65
- "[mock query result]"
66
- );
67
- exportMock = mock(async (_dbName: string) => "backup-2026-05-13.sql");
68
- resolveNamespaceIdMock = mock(async () => "ns-id-123");
69
- getMock = mock(async (_nsId: string, _key: string) => "false");
70
- setMock = mock(async (_nsId: string, _key: string, _value: string) => {});
71
-
72
- // Install mocks on prototypes
73
- (
74
- MonitorService.prototype as unknown as Record<string, unknown>
75
- ).checkAllWorkerHealth = checkAllWorkerHealthMock;
76
- (DbService.prototype as unknown as Record<string, unknown>).resolveDbName =
77
- resolveDbNameMock;
78
- (DbService.prototype as unknown as Record<string, unknown>).query = queryMock;
79
- (DbService.prototype as unknown as Record<string, unknown>).export =
80
- exportMock;
81
- (
82
- KvSyncService.prototype as unknown as Record<string, unknown>
83
- ).resolveNamespaceId = resolveNamespaceIdMock;
84
- (KvSyncService.prototype as unknown as Record<string, unknown>).get = getMock;
85
- (KvSyncService.prototype as unknown as Record<string, unknown>).set = setMock;
86
- });
87
-
88
- afterEach(() => {
89
- mock.restore();
90
- (
91
- MonitorService.prototype as unknown as Record<string, unknown>
92
- ).checkAllWorkerHealth = origCheckAll;
93
- (DbService.prototype as unknown as Record<string, unknown>).resolveDbName =
94
- origResolveDbName;
95
- (DbService.prototype as unknown as Record<string, unknown>).query = origQuery;
96
- (DbService.prototype as unknown as Record<string, unknown>).export =
97
- origExport;
98
- (
99
- KvSyncService.prototype as unknown as Record<string, unknown>
100
- ).resolveNamespaceId = origResolveNs;
101
- (KvSyncService.prototype as unknown as Record<string, unknown>).get = origGet;
102
- (KvSyncService.prototype as unknown as Record<string, unknown>).set = origSet;
103
- });
104
-
105
- async function importMonitorCommand(): Promise<{
106
- registerMonitorCommand: typeof import("./monitor-command.js").registerMonitorCommand;
107
- }> {
108
- return import("./monitor-command.js");
109
- }
110
-
111
- async function createProgram(): Promise<Command> {
112
- const { registerMonitorCommand } = await importMonitorCommand();
113
- const program = new Command().name("hoox-test").exitOverride(() => {});
114
- registerMonitorCommand(program);
115
- return program;
116
- }
117
-
118
- describe("registerMonitorCommand", () => {
119
- // -- Command registration -------------------------------------------------
120
-
121
- it("registers 'monitor' as a command on the program", async () => {
122
- const program = await createProgram();
123
- const cmd = program.commands.find((c) => c.name() === "monitor");
124
- expect(cmd).toBeDefined();
125
- });
126
-
127
- it("registers 'monitor status' subcommand", async () => {
128
- const program = await createProgram();
129
- const monitorCmd = program.commands.find((c) => c.name() === "monitor")!;
130
- const statusCmd = monitorCmd.commands.find((c) => c.name() === "status");
131
- expect(statusCmd).toBeDefined();
132
- });
133
-
134
- it("registers 'monitor trades' subcommand with argument", async () => {
135
- const program = await createProgram();
136
- const monitorCmd = program.commands.find((c) => c.name() === "monitor")!;
137
- const tradesCmd = monitorCmd.commands.find((c) => c.name() === "trades");
138
- expect(tradesCmd).toBeDefined();
139
- const args = tradesCmd!.registeredArguments;
140
- expect(args.some((a) => a.name() === "limit")).toBe(true);
141
- });
142
-
143
- it("registers 'monitor logs' subcommand with optional argument", async () => {
144
- const program = await createProgram();
145
- const monitorCmd = program.commands.find((c) => c.name() === "monitor")!;
146
- const logsCmd = monitorCmd.commands.find((c) => c.name() === "logs");
147
- expect(logsCmd).toBeDefined();
148
- });
149
-
150
- it("registers 'monitor kill-switch' with show/on/off subcommands", async () => {
151
- const program = await createProgram();
152
- const monitorCmd = program.commands.find((c) => c.name() === "monitor")!;
153
- const ksCmd = monitorCmd.commands.find((c) => c.name() === "kill-switch");
154
- expect(ksCmd).toBeDefined();
155
- expect(ksCmd!.commands.find((c) => c.name() === "show")).toBeDefined();
156
- expect(ksCmd!.commands.find((c) => c.name() === "on")).toBeDefined();
157
- expect(ksCmd!.commands.find((c) => c.name() === "off")).toBeDefined();
158
- });
159
-
160
- it("registers 'monitor queue-depth' subcommand", async () => {
161
- const program = await createProgram();
162
- const monitorCmd = program.commands.find((c) => c.name() === "monitor")!;
163
- const qCmd = monitorCmd.commands.find((c) => c.name() === "queue-depth");
164
- expect(qCmd).toBeDefined();
165
- });
166
-
167
- it("registers 'monitor backup' subcommand", async () => {
168
- const program = await createProgram();
169
- const monitorCmd = program.commands.find((c) => c.name() === "monitor")!;
170
- const backupCmd = monitorCmd.commands.find((c) => c.name() === "backup");
171
- expect(backupCmd).toBeDefined();
172
- });
173
-
174
- // -- monitor status -------------------------------------------------------
175
-
176
- describe("monitor status", () => {
177
- it("calls checkAllWorkerHealth", async () => {
178
- const program = await createProgram();
179
- await program.parseAsync(["monitor", "status"], { from: "user" });
180
- expect(checkAllWorkerHealthMock).toHaveBeenCalled();
181
- });
182
-
183
- it("exits cleanly on success", async () => {
184
- process.exitCode = 0;
185
- const program = await createProgram();
186
- process.exitCode = 0;
187
- await program.parseAsync(["monitor", "status"], { from: "user" });
188
- expect(process.exitCode).toBe(0);
189
- });
190
-
191
- it("sets exitCode on service failure", async () => {
192
- checkAllWorkerHealthMock = mock(async () => {
193
- throw new Error("Connection failed");
194
- });
195
- (
196
- MonitorService.prototype as unknown as Record<string, unknown>
197
- ).checkAllWorkerHealth = checkAllWorkerHealthMock;
198
-
199
- const program = await createProgram();
200
- await program.parseAsync(["monitor", "status"], { from: "user" });
201
- expect(process.exitCode).toBe(1);
202
- });
203
- });
204
-
205
- // -- monitor trades -------------------------------------------------------
206
-
207
- describe("monitor trades", () => {
208
- it("calls db.query with trades table", async () => {
209
- const program = await createProgram();
210
- await program.parseAsync(["monitor", "trades"], { from: "user" });
211
- expect(resolveDbNameMock).toHaveBeenCalled();
212
- expect(queryMock).toHaveBeenCalled();
213
- const sql = queryMock.mock.calls[0][1] as string;
214
- expect(sql).toContain("trades");
215
- expect(sql).toContain("ORDER BY timestamp DESC");
216
- });
217
-
218
- it("accepts custom limit", async () => {
219
- const program = await createProgram();
220
- await program.parseAsync(["monitor", "trades", "25"], { from: "user" });
221
- const sql = queryMock.mock.calls[0][1] as string;
222
- expect(sql).toContain("LIMIT 25");
223
- });
224
- });
225
-
226
- // -- monitor kill-switch --------------------------------------------------
227
-
228
- describe("monitor kill-switch", () => {
229
- it("shows kill switch status", async () => {
230
- const program = await createProgram();
231
- await program.parseAsync(["monitor", "kill-switch", "show"], {
232
- from: "user",
233
- });
234
- expect(getMock).toHaveBeenCalledWith("ns-id-123", "trade:kill_switch");
235
- });
236
-
237
- it("turns kill switch on", async () => {
238
- const program = await createProgram();
239
- await program.parseAsync(["monitor", "kill-switch", "on"], {
240
- from: "user",
241
- });
242
- expect(setMock).toHaveBeenCalledWith(
243
- "ns-id-123",
244
- "trade:kill_switch",
245
- "true"
246
- );
247
- });
248
-
249
- it("turns kill switch off", async () => {
250
- const program = await createProgram();
251
- await program.parseAsync(["monitor", "kill-switch", "off"], {
252
- from: "user",
253
- });
254
- expect(setMock).toHaveBeenCalledWith(
255
- "ns-id-123",
256
- "trade:kill_switch",
257
- "false"
258
- );
259
- });
260
- });
261
-
262
- // -- monitor backup -------------------------------------------------------
263
-
264
- describe("monitor backup", () => {
265
- it("calls db.export", async () => {
266
- const program = await createProgram();
267
- await program.parseAsync(["monitor", "backup"], { from: "user" });
268
- expect(exportMock).toHaveBeenCalled();
269
- });
270
- });
271
- });
@@ -1,269 +0,0 @@
1
- import { Command } from "commander";
2
- import { DbService } from "../../services/db/index.js";
3
- import { MonitorService } from "./monitor-service.js";
4
- import { KvSyncService } from "../../services/kv/kv-sync-service.js";
5
- import {
6
- formatSuccess,
7
- formatError,
8
- formatTable,
9
- getFormatOptions,
10
- } from "../../utils/formatters.js";
11
- import type { FormatOptions } from "../../utils/formatters.js";
12
- import { ExitCode } from "../../utils/errors.js";
13
- import { theme } from "../../utils/theme.js";
14
-
15
- async function doMonitorStatus(fmt: FormatOptions): Promise<void> {
16
- try {
17
- const monitor = new MonitorService();
18
- const result = await monitor.checkAllWorkerHealth();
19
-
20
- if (fmt.json) {
21
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
22
- return;
23
- }
24
-
25
- const rows = result.workers.map((w) => ({
26
- Worker: w.worker,
27
- Status: w.status,
28
- "Status Code": String(w.statusCode ?? "-"),
29
- Error: w.error ?? "-",
30
- }));
31
- formatTable(rows, fmt);
32
-
33
- process.stdout.write(
34
- `\n${theme.heading("Summary:")} ${result.healthyCount} healthy, ${result.degradedCount} degraded, ${result.unreachableCount} unreachable\n`
35
- );
36
- } catch (err) {
37
- formatError(err instanceof Error ? err.message : String(err), fmt);
38
- process.exitCode = ExitCode.ERROR;
39
- }
40
- }
41
-
42
- async function doMonitorTrades(
43
- limit: number,
44
- fmt: FormatOptions
45
- ): Promise<void> {
46
- try {
47
- const db = new DbService();
48
- const dbName = await db.resolveDbName();
49
- const sql = `SELECT * FROM trades ORDER BY timestamp DESC LIMIT ${Math.min(limit, 100)}`;
50
- const output = await db.query(dbName, sql, true);
51
- process.stdout.write(output + "\n");
52
- } catch (err) {
53
- formatError(err instanceof Error ? err.message : String(err), fmt);
54
- process.exitCode = ExitCode.ERROR;
55
- }
56
- }
57
-
58
- async function doMonitorLogs(
59
- workerName: string | undefined,
60
- fmt: FormatOptions
61
- ): Promise<void> {
62
- try {
63
- const db = new DbService();
64
- const dbName = await db.resolveDbName();
65
- let sql: string;
66
- if (workerName) {
67
- sql = `SELECT * FROM system_logs WHERE worker = '${workerName.replace(/'/g, "''")}' ORDER BY timestamp DESC LIMIT 20`;
68
- } else {
69
- sql = "SELECT * FROM system_logs ORDER BY timestamp DESC LIMIT 20";
70
- }
71
- const output = await db.query(dbName, sql, true);
72
- process.stdout.write(output + "\n");
73
- } catch (err) {
74
- formatError(err instanceof Error ? err.message : String(err), fmt);
75
- process.exitCode = ExitCode.ERROR;
76
- }
77
- }
78
-
79
- async function doMonitorKillSwitch(
80
- action: "show" | "on" | "off",
81
- fmt: FormatOptions
82
- ): Promise<void> {
83
- try {
84
- const kv = new KvSyncService();
85
- const namespaceId = await kv.resolveNamespaceId();
86
- const key = "trade:kill_switch";
87
-
88
- if (action === "show") {
89
- const value = await kv.get(namespaceId, key);
90
- const status =
91
- value === "true"
92
- ? "KILL SWITCH IS ON (trading halted)"
93
- : value === "false"
94
- ? "Kill switch is off (trading active)"
95
- : `Kill switch value: ${value ?? "(not set)"}`;
96
- process.stdout.write(`${theme.info(status)}\n`);
97
- } else {
98
- const newValue = action === "on" ? "true" : "false";
99
- await kv.set(namespaceId, key, newValue);
100
- formatSuccess(
101
- `Kill switch turned ${action === "on" ? "ON" : "OFF"}`,
102
- fmt
103
- );
104
- }
105
- } catch (err) {
106
- formatError(err instanceof Error ? err.message : String(err), fmt);
107
- process.exitCode = ExitCode.ERROR;
108
- }
109
- }
110
-
111
- async function doMonitorQueueDepth(fmt: FormatOptions): Promise<void> {
112
- try {
113
- const proc = Bun.spawn(["wrangler", "queues", "list"], {
114
- stdout: "pipe",
115
- stderr: "pipe",
116
- });
117
- const stdout = await new Response(proc.stdout).text();
118
- const stderr = await new Response(proc.stderr).text();
119
- const exitCode = await proc.exited;
120
-
121
- if (exitCode !== 0) {
122
- throw new Error(stderr.trim() || `wrangler exited with code ${exitCode}`);
123
- }
124
-
125
- process.stdout.write(stdout + "\n");
126
- } catch (err) {
127
- formatError(err instanceof Error ? err.message : String(err), fmt);
128
- process.exitCode = ExitCode.ERROR;
129
- }
130
- }
131
-
132
- async function doMonitorBackup(fmt: FormatOptions): Promise<void> {
133
- try {
134
- const db = new DbService();
135
- const dbName = await db.resolveDbName();
136
- const outputPath = await db.export(dbName);
137
- formatSuccess(`Database exported to ${outputPath}`, fmt);
138
- } catch (err) {
139
- formatError(err instanceof Error ? err.message : String(err), fmt);
140
- process.exitCode = ExitCode.ERROR;
141
- }
142
- }
143
-
144
- export function registerMonitorCommand(program: Command): void {
145
- const monitorCmd = program
146
- .command("monitor")
147
- .summary("Monitor and operate the trading system")
148
- .description(
149
- `Monitor worker health, trades, logs, and perform operational tasks.
150
-
151
- SUBCOMMANDS:
152
- status Check health of all workers
153
- trades [N] Show N most recent trades (default: 10)
154
- logs [worker] Show recent system logs from D1
155
- kill-switch Emergency stop/resume trading
156
- queue-depth List queues and pending messages
157
- backup Export D1 database to timestamped .sql file
158
-
159
- EXAMPLES:
160
- hoox monitor status Check all workers health
161
- hoox monitor trades 20 Show 20 recent trades
162
- hoox monitor logs hoox Show logs for hoox worker
163
- hoox monitor kill-switch show Check kill switch status
164
- hoox monitor kill-switch on Halt all trading
165
- hoox monitor kill-switch off Resume trading
166
- hoox monitor queue-depth Show queue info
167
- hoox monitor backup Export D1 database`
168
- );
169
-
170
- monitorCmd
171
- .command("status")
172
- .summary("Check health of all workers")
173
- .description("Probe each worker's /health endpoint and report status.")
174
- .action(async function (this: Command) {
175
- const fmt = getFormatOptions(this);
176
- await doMonitorStatus(fmt);
177
- });
178
-
179
- monitorCmd
180
- .command("trades")
181
- .summary("Show recent trades from D1")
182
- .description("Query the trades table for the most recent entries.")
183
- .argument(
184
- "[limit]",
185
- "Number of trades to show (default: 10, max: 100)",
186
- "10"
187
- )
188
- .action(async function (this: Command, limit: string) {
189
- const fmt = getFormatOptions(this);
190
- await doMonitorTrades(parseInt(limit, 10) || 10, fmt);
191
- });
192
-
193
- monitorCmd
194
- .command("logs")
195
- .summary("Show recent system logs from D1")
196
- .description(
197
- "Query the system_logs table. Optionally filter by worker name."
198
- )
199
- .argument("[worker]", "Worker name to filter (optional)")
200
- .action(async function (this: Command, worker?: string) {
201
- const fmt = getFormatOptions(this);
202
- await doMonitorLogs(worker, fmt);
203
- });
204
-
205
- const ksCmd = monitorCmd
206
- .command("kill-switch")
207
- .summary("Emergency stop or resume trading")
208
- .description(
209
- `Control the trade:kill_switch KV key.
210
-
211
- Commands:
212
- show Display current kill switch status
213
- on Halt all trading (set kill_switch=true)
214
- off Resume trading (set kill_switch=false)`
215
- );
216
-
217
- ksCmd
218
- .command("show")
219
- .summary("Show kill switch status")
220
- .description("Display whether trading is halted or active.")
221
- .action(async function (this: Command) {
222
- const fmt = getFormatOptions(this);
223
- await doMonitorKillSwitch("show", fmt);
224
- });
225
-
226
- ksCmd
227
- .command("on")
228
- .summary("Halt all trading")
229
- .description(
230
- "Set trade:kill_switch=true to stop all trading operations. WARNING: This halts ALL trading activity immediately."
231
- )
232
- .action(async function (this: Command) {
233
- const fmt = getFormatOptions(this);
234
- await doMonitorKillSwitch("on", fmt);
235
- });
236
-
237
- ksCmd
238
- .command("off")
239
- .summary("Resume trading")
240
- .description(
241
- "Set trade:kill_switch=false to resume normal trading operations."
242
- )
243
- .action(async function (this: Command) {
244
- const fmt = getFormatOptions(this);
245
- await doMonitorKillSwitch("off", fmt);
246
- });
247
-
248
- monitorCmd
249
- .command("queue-depth")
250
- .summary("Show queue details")
251
- .description(
252
- "List queues via wrangler queues list to show configured queues."
253
- )
254
- .action(async function (this: Command) {
255
- const fmt = getFormatOptions(this);
256
- await doMonitorQueueDepth(fmt);
257
- });
258
-
259
- monitorCmd
260
- .command("backup")
261
- .summary("Export D1 database to .sql file")
262
- .description(
263
- "Export the D1 database to a timestamped .sql backup file via wrangler d1 export."
264
- )
265
- .action(async function (this: Command) {
266
- const fmt = getFormatOptions(this);
267
- await doMonitorBackup(fmt);
268
- });
269
- }
@@ -1,65 +0,0 @@
1
- import { ConfigService } from "../../services/config/index.js";
2
- import type { WorkerHealthResult } from "./types.js";
3
-
4
- export class MonitorService {
5
- private configService: ConfigService;
6
-
7
- constructor(configService?: ConfigService) {
8
- this.configService = configService ?? new ConfigService();
9
- }
10
-
11
- async checkAllWorkerHealth(): Promise<{
12
- workers: WorkerHealthResult[];
13
- healthyCount: number;
14
- degradedCount: number;
15
- unreachableCount: number;
16
- }> {
17
- await this.configService.load();
18
- const global = this.configService.getGlobal();
19
- const prefix = global.subdomain_prefix ?? "hoox";
20
- const enabled = this.configService.listEnabledWorkers();
21
-
22
- const results: WorkerHealthResult[] = [];
23
- let healthy = 0;
24
- let degraded = 0;
25
- let unreachable = 0;
26
-
27
- for (const name of enabled) {
28
- const url = `https://${name}.${prefix}.workers.dev/health`;
29
- try {
30
- const response = await fetch(url, {
31
- signal: AbortSignal.timeout(5000),
32
- });
33
- if (response.ok) {
34
- results.push({
35
- worker: name,
36
- status: "healthy",
37
- statusCode: response.status,
38
- });
39
- healthy++;
40
- } else {
41
- results.push({
42
- worker: name,
43
- status: "degraded",
44
- statusCode: response.status,
45
- });
46
- degraded++;
47
- }
48
- } catch (err) {
49
- results.push({
50
- worker: name,
51
- status: "unreachable",
52
- error: err instanceof Error ? err.message : String(err),
53
- });
54
- unreachable++;
55
- }
56
- }
57
-
58
- return {
59
- workers: results,
60
- healthyCount: healthy,
61
- degradedCount: degraded,
62
- unreachableCount: unreachable,
63
- };
64
- }
65
- }
@@ -1,13 +0,0 @@
1
- export interface WorkerHealthResult {
2
- worker: string;
3
- status: "healthy" | "degraded" | "unreachable";
4
- statusCode?: number;
5
- error?: string;
6
- }
7
-
8
- export interface MonitorStatusResult {
9
- workers: WorkerHealthResult[];
10
- healthyCount: number;
11
- degradedCount: number;
12
- unreachableCount: number;
13
- }
@@ -1,2 +0,0 @@
1
- export { registerRepairCommand } from "./repair-command.js";
2
- export type { RepairStepResult, RepairCheckResult } from "./types.js";