@jango-blockchained/hoox-cli 0.5.1 → 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.
- package/bin/hoox.js +3 -4
- package/dist/index.js +32545 -0
- package/package.json +10 -15
- package/src/commands/check/check-command.test.ts +0 -476
- package/src/commands/check/check-command.ts +0 -1144
- package/src/commands/check/index.ts +0 -10
- package/src/commands/check/prerequisites-command.test.ts +0 -19
- package/src/commands/check/prerequisites-command.ts +0 -96
- package/src/commands/check/types.ts +0 -103
- package/src/commands/clone/clone-command.test.ts +0 -442
- package/src/commands/clone/clone-command.ts +0 -431
- package/src/commands/clone/index.ts +0 -1
- package/src/commands/config/config-command.test.ts +0 -583
- package/src/commands/config/config-command.ts +0 -897
- package/src/commands/config/env-command.test.ts +0 -43
- package/src/commands/config/env-command.ts +0 -295
- package/src/commands/config/index.ts +0 -3
- package/src/commands/config/kv-command.test.ts +0 -14
- package/src/commands/config/kv-command.ts +0 -290
- package/src/commands/dashboard/dashboard-command.test.ts +0 -47
- package/src/commands/dashboard/dashboard-command.ts +0 -128
- package/src/commands/dashboard/index.ts +0 -1
- package/src/commands/db/db-command.test.ts +0 -21
- package/src/commands/db/db-command.ts +0 -312
- package/src/commands/db/index.ts +0 -1
- package/src/commands/deploy/deploy-command.test.ts +0 -304
- package/src/commands/deploy/deploy-command.ts +0 -1135
- package/src/commands/deploy/index.ts +0 -2
- package/src/commands/deploy/telegram-service.ts +0 -76
- package/src/commands/deploy/types.ts +0 -34
- package/src/commands/dev/dev-command.test.ts +0 -383
- package/src/commands/dev/dev-command.ts +0 -398
- package/src/commands/dev/index.ts +0 -1
- package/src/commands/infra/index.ts +0 -5
- package/src/commands/infra/infra-command.test.ts +0 -719
- package/src/commands/infra/infra-command.ts +0 -974
- package/src/commands/infra/types.ts +0 -23
- package/src/commands/init/__tests__/cli-provisioner.test.ts +0 -17
- package/src/commands/init/cli-provisioner.ts +0 -71
- package/src/commands/init/index.ts +0 -1
- package/src/commands/init/init-command.test.ts +0 -876
- package/src/commands/init/init-command.ts +0 -593
- package/src/commands/init/types.ts +0 -23
- package/src/commands/logs/index.ts +0 -1
- package/src/commands/logs/logs-command.test.ts +0 -294
- package/src/commands/logs/logs-command.ts +0 -452
- package/src/commands/monitor/index.ts +0 -2
- package/src/commands/monitor/monitor-command.test.ts +0 -263
- package/src/commands/monitor/monitor-command.ts +0 -269
- package/src/commands/monitor/monitor-service.ts +0 -65
- package/src/commands/monitor/types.ts +0 -13
- package/src/commands/repair/index.ts +0 -2
- package/src/commands/repair/repair-command.test.ts +0 -224
- package/src/commands/repair/repair-command.ts +0 -220
- package/src/commands/repair/repair-service.ts +0 -138
- package/src/commands/repair/types.ts +0 -13
- package/src/commands/test/index.ts +0 -2
- package/src/commands/test/test-command.test.ts +0 -319
- package/src/commands/test/test-command.ts +0 -406
- package/src/commands/tui/index.ts +0 -1
- package/src/commands/tui/tui-command.ts +0 -87
- package/src/commands/update/index.ts +0 -1
- package/src/commands/update/update-command.ts +0 -168
- package/src/commands/waf/index.ts +0 -2
- package/src/commands/waf/types.ts +0 -48
- package/src/commands/waf/waf-command.test.ts +0 -506
- package/src/commands/waf/waf-command.ts +0 -548
- package/src/index.ts +0 -269
- package/src/services/cloudflare/cloudflare-service.test.ts +0 -658
- package/src/services/cloudflare/cloudflare-service.ts +0 -433
- package/src/services/cloudflare/index.ts +0 -2
- package/src/services/cloudflare/types.ts +0 -30
- package/src/services/config/config-service.test.ts +0 -395
- package/src/services/config/config-service.ts +0 -207
- package/src/services/config/index.ts +0 -9
- package/src/services/config/types.ts +0 -66
- package/src/services/db/db-service.test.ts +0 -51
- package/src/services/db/db-service.ts +0 -131
- package/src/services/db/index.ts +0 -1
- package/src/services/docker/docker-service.ts +0 -155
- package/src/services/docker/index.ts +0 -1
- package/src/services/env/env-service.test.ts +0 -236
- package/src/services/env/env-service.ts +0 -386
- package/src/services/env/index.ts +0 -1
- package/src/services/kv/index.ts +0 -1
- package/src/services/kv/kv-sync-service.test.ts +0 -38
- package/src/services/kv/kv-sync-service.ts +0 -234
- package/src/services/prerequisites/index.ts +0 -1
- package/src/services/prerequisites/prerequisites-service.test.ts +0 -89
- package/src/services/prerequisites/prerequisites-service.ts +0 -377
- package/src/services/prerequisites/types.ts +0 -48
- package/src/services/secrets/index.ts +0 -11
- package/src/services/secrets/secrets-service.test.ts +0 -495
- package/src/services/secrets/secrets-service.ts +0 -287
- package/src/services/secrets/types.ts +0 -50
- package/src/services/update/index.ts +0 -2
- package/src/services/update/update-service.test.ts +0 -76
- package/src/services/update/update-service.ts +0 -193
- package/src/ui/banner.ts +0 -141
- package/src/ui/index.ts +0 -8
- package/src/ui/menu.ts +0 -490
- package/src/utils/errors.test.ts +0 -69
- package/src/utils/errors.ts +0 -23
- package/src/utils/formatters.test.ts +0 -180
- package/src/utils/formatters.ts +0 -269
- package/src/utils/theme.ts +0 -94
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
/**
|
|
3
|
-
* Unit tests for the logs command.
|
|
4
|
-
*
|
|
5
|
-
* Mocks Bun.spawn (for wrangler tail), ConfigService, and stream readers
|
|
6
|
-
* to verify command logic in isolation. Uses the actual registerLogsCommand
|
|
7
|
-
* function but intercepts the action handlers by stubbing dependencies.
|
|
8
|
-
*
|
|
9
|
-
* IMPORTANT: Saves and restores all prototype modifications in afterEach
|
|
10
|
-
* to prevent cross-test pollution (no mock.module usage).
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
|
|
14
|
-
import { Command } from "commander";
|
|
15
|
-
import { ConfigService } from "../../services/config/config-service.js";
|
|
16
|
-
import { registerLogsCommand } from "./logs-command.js";
|
|
17
|
-
import { ExitCode } from "../../utils/errors.js";
|
|
18
|
-
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Mock setup — stub Bun.spawn and ConfigService
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
// Preserve originals for restoration in afterEach
|
|
24
|
-
const origLoad = ConfigService.prototype.load;
|
|
25
|
-
const origListEnabled = ConfigService.prototype.listEnabledWorkers;
|
|
26
|
-
const origBunSpawn = Bun.spawn;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Creates a mock ReadableStream that emits the given chunks and then closes.
|
|
30
|
-
* This simulates the stdout of a wrangler tail process.
|
|
31
|
-
*/
|
|
32
|
-
function createMockReader(
|
|
33
|
-
chunks: string[],
|
|
34
|
-
delayMs = 0
|
|
35
|
-
): ReadableStreamDefaultReader<Uint8Array> {
|
|
36
|
-
const encoder = new TextEncoder();
|
|
37
|
-
let chunkIndex = 0;
|
|
38
|
-
|
|
39
|
-
const stream = new ReadableStream<Uint8Array>({
|
|
40
|
-
async start(controller) {
|
|
41
|
-
for (const chunk of chunks) {
|
|
42
|
-
if (delayMs > 0) {
|
|
43
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
44
|
-
}
|
|
45
|
-
controller.enqueue(encoder.encode(chunk));
|
|
46
|
-
chunkIndex++;
|
|
47
|
-
}
|
|
48
|
-
controller.close();
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
return stream.getReader();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Creates a mock Bun.spawn return value that simulates a clean exit.
|
|
57
|
-
*/
|
|
58
|
-
function createMockSpawn(chunks: string[], exitCode = 0) {
|
|
59
|
-
const reader = createMockReader(chunks);
|
|
60
|
-
return {
|
|
61
|
-
stdout: {
|
|
62
|
-
getReader: () => reader,
|
|
63
|
-
},
|
|
64
|
-
stderr: {
|
|
65
|
-
getReader: () => createMockReader([]),
|
|
66
|
-
},
|
|
67
|
-
exited: Promise.resolve(exitCode),
|
|
68
|
-
killed: false,
|
|
69
|
-
kill: mock(() => {}),
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let spawnMock: ReturnType<typeof mock>;
|
|
74
|
-
let loadMock: ReturnType<typeof mock>;
|
|
75
|
-
let listEnabledWorkersMock: ReturnType<typeof mock>;
|
|
76
|
-
|
|
77
|
-
beforeEach(() => {
|
|
78
|
-
mock.restore();
|
|
79
|
-
|
|
80
|
-
// Restore ConfigService prototypes to originals first
|
|
81
|
-
ConfigService.prototype.load = origLoad;
|
|
82
|
-
ConfigService.prototype.listEnabledWorkers = origListEnabled;
|
|
83
|
-
|
|
84
|
-
// Restore Bun.spawn
|
|
85
|
-
(Bun as unknown as Record<string, unknown>).spawn = origBunSpawn;
|
|
86
|
-
|
|
87
|
-
// Mock Bun.spawn
|
|
88
|
-
spawnMock = mock((_args: string[], _options?: unknown) => {
|
|
89
|
-
return createMockSpawn(["Test log line\n"]);
|
|
90
|
-
});
|
|
91
|
-
(Bun as unknown as Record<string, unknown>).spawn = spawnMock;
|
|
92
|
-
|
|
93
|
-
// Stub ConfigService prototype methods
|
|
94
|
-
loadMock = mock(async () => ({}));
|
|
95
|
-
listEnabledWorkersMock = mock(() => ["d1-worker", "hoox", "trade-worker"]);
|
|
96
|
-
|
|
97
|
-
ConfigService.prototype.load = loadMock;
|
|
98
|
-
ConfigService.prototype.listEnabledWorkers = listEnabledWorkersMock;
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
afterEach(() => {
|
|
102
|
-
mock.restore();
|
|
103
|
-
|
|
104
|
-
// Restore ConfigService prototypes
|
|
105
|
-
ConfigService.prototype.load = origLoad;
|
|
106
|
-
ConfigService.prototype.listEnabledWorkers = origListEnabled;
|
|
107
|
-
|
|
108
|
-
// Restore Bun.spawn (individual property assignment — NOT globalThis.Bun)
|
|
109
|
-
(Bun as unknown as Record<string, unknown>).spawn = origBunSpawn;
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// ---------------------------------------------------------------------------
|
|
113
|
-
// Helpers
|
|
114
|
-
// ---------------------------------------------------------------------------
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Create a fresh Commander program with the logs command registered.
|
|
118
|
-
* Uses a custom name and exitOverride to prevent process exits during tests.
|
|
119
|
-
*/
|
|
120
|
-
function createProgram(): Command {
|
|
121
|
-
const program = new Command().name("hoox-test").exitOverride(() => {
|
|
122
|
-
// Suppress Commander's own exit during tests
|
|
123
|
-
});
|
|
124
|
-
registerLogsCommand(program);
|
|
125
|
-
return program;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// ---------------------------------------------------------------------------
|
|
129
|
-
// Tests
|
|
130
|
-
// ---------------------------------------------------------------------------
|
|
131
|
-
|
|
132
|
-
describe("registerLogsCommand", () => {
|
|
133
|
-
// -- Command registration -------------------------------------------------
|
|
134
|
-
|
|
135
|
-
it("registers 'logs' as a command on the program", () => {
|
|
136
|
-
const program = createProgram();
|
|
137
|
-
const logsCmd = program.commands.find((c) => c.name() === "logs");
|
|
138
|
-
expect(logsCmd).toBeDefined();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("registers 'logs worker <name>' subcommand", () => {
|
|
142
|
-
const program = createProgram();
|
|
143
|
-
const logsCmd = program.commands.find((c) => c.name() === "logs");
|
|
144
|
-
expect(logsCmd).toBeDefined();
|
|
145
|
-
const workerCmd = logsCmd!.commands.find((c) => c.name() === "worker");
|
|
146
|
-
expect(workerCmd).toBeDefined();
|
|
147
|
-
expect(workerCmd!.description()).toContain("Tail logs for a specific");
|
|
148
|
-
// The argument should be <name>
|
|
149
|
-
const args = workerCmd!.registeredArguments;
|
|
150
|
-
expect(args.some((a) => a.name() === "name")).toBe(true);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("registers 'logs all' subcommand", () => {
|
|
154
|
-
const program = createProgram();
|
|
155
|
-
const logsCmd = program.commands.find((c) => c.name() === "logs");
|
|
156
|
-
expect(logsCmd).toBeDefined();
|
|
157
|
-
const allCmd = logsCmd!.commands.find((c) => c.name() === "all");
|
|
158
|
-
expect(allCmd).toBeDefined();
|
|
159
|
-
expect(allCmd!.description()).toContain("all enabled workers");
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it("'logs worker' has --level, --follow, --json options", () => {
|
|
163
|
-
const program = createProgram();
|
|
164
|
-
const logsCmd = program.commands.find((c) => c.name() === "logs");
|
|
165
|
-
const workerCmd = logsCmd!.commands.find((c) => c.name() === "worker");
|
|
166
|
-
expect(workerCmd).toBeDefined();
|
|
167
|
-
|
|
168
|
-
const optionNames = workerCmd!.options.map((o) => o.long);
|
|
169
|
-
expect(optionNames).toContain("--level");
|
|
170
|
-
expect(optionNames).toContain("--follow");
|
|
171
|
-
expect(optionNames).toContain("--json");
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("'logs all' has --level, --follow, --json options", () => {
|
|
175
|
-
const program = createProgram();
|
|
176
|
-
const logsCmd = program.commands.find((c) => c.name() === "logs");
|
|
177
|
-
const allCmd = logsCmd!.commands.find((c) => c.name() === "all");
|
|
178
|
-
expect(allCmd).toBeDefined();
|
|
179
|
-
|
|
180
|
-
const optionNames = allCmd!.options.map((o) => o.long);
|
|
181
|
-
expect(optionNames).toContain("--level");
|
|
182
|
-
expect(optionNames).toContain("--follow");
|
|
183
|
-
expect(optionNames).toContain("--json");
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// -- logs worker <name> ---------------------------------------------------
|
|
187
|
-
|
|
188
|
-
describe("logs worker <name>", () => {
|
|
189
|
-
it("spawns wrangler tail for the specified worker", async () => {
|
|
190
|
-
const program = createProgram();
|
|
191
|
-
await program.parseAsync(["logs", "worker", "hoox"], { from: "user" });
|
|
192
|
-
|
|
193
|
-
// Verify wrangler tail was called with the worker name
|
|
194
|
-
expect(spawnMock).toHaveBeenCalled();
|
|
195
|
-
const callArgs = (
|
|
196
|
-
spawnMock as unknown as { mock: { calls: Array<unknown[]> } }
|
|
197
|
-
).mock.calls[0];
|
|
198
|
-
const spawnArgs = callArgs[0] as string[];
|
|
199
|
-
expect(spawnArgs).toContain("wrangler");
|
|
200
|
-
expect(spawnArgs).toContain("tail");
|
|
201
|
-
expect(spawnArgs).toContain("hoox");
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("passes --format json to wrangler when --json flag is set", async () => {
|
|
205
|
-
const program = createProgram();
|
|
206
|
-
await program.parseAsync(["logs", "worker", "hoox", "--json"], {
|
|
207
|
-
from: "user",
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const callArgs = (
|
|
211
|
-
spawnMock as unknown as { mock: { calls: Array<unknown[]> } }
|
|
212
|
-
).mock.calls[0];
|
|
213
|
-
const spawnArgs = callArgs[0] as string[];
|
|
214
|
-
expect(spawnArgs).toContain("--format");
|
|
215
|
-
expect(spawnArgs).toContain("json");
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("passes --format json to wrangler when --level is set to non-all", async () => {
|
|
219
|
-
const program = createProgram();
|
|
220
|
-
await program.parseAsync(["logs", "worker", "hoox", "--level", "error"], {
|
|
221
|
-
from: "user",
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
const callArgs = (
|
|
225
|
-
spawnMock as unknown as { mock: { calls: Array<unknown[]> } }
|
|
226
|
-
).mock.calls[0];
|
|
227
|
-
const spawnArgs = callArgs[0] as string[];
|
|
228
|
-
expect(spawnArgs).toContain("--format");
|
|
229
|
-
expect(spawnArgs).toContain("json");
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("does NOT pass --format json when --level is all and --json not set", async () => {
|
|
233
|
-
const program = createProgram();
|
|
234
|
-
await program.parseAsync(["logs", "worker", "hoox"], { from: "user" });
|
|
235
|
-
|
|
236
|
-
const callArgs = (
|
|
237
|
-
spawnMock as unknown as { mock: { calls: Array<unknown[]> } }
|
|
238
|
-
).mock.calls[0];
|
|
239
|
-
const spawnArgs = callArgs[0] as string[];
|
|
240
|
-
expect(spawnArgs).not.toContain("--format");
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("handles spawn failure gracefully", async () => {
|
|
244
|
-
spawnMock = mock(() => {
|
|
245
|
-
throw new Error("wrangler not found");
|
|
246
|
-
});
|
|
247
|
-
(Bun as unknown as Record<string, unknown>).spawn = spawnMock;
|
|
248
|
-
|
|
249
|
-
const program = createProgram();
|
|
250
|
-
await program.parseAsync(["logs", "worker", "hoox"], { from: "user" });
|
|
251
|
-
|
|
252
|
-
expect(process.exitCode).toBe(ExitCode.ERROR);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
// -- logs all -------------------------------------------------------------
|
|
257
|
-
|
|
258
|
-
describe("logs all", () => {
|
|
259
|
-
it("calls ConfigService.listEnabledWorkers and spawns tail for each", async () => {
|
|
260
|
-
listEnabledWorkersMock = mock(() => ["hoox", "trade-worker"]);
|
|
261
|
-
ConfigService.prototype.listEnabledWorkers = listEnabledWorkersMock;
|
|
262
|
-
|
|
263
|
-
const program = createProgram();
|
|
264
|
-
await program.parseAsync(["logs", "all"], { from: "user" });
|
|
265
|
-
|
|
266
|
-
expect(listEnabledWorkersMock).toHaveBeenCalled();
|
|
267
|
-
// Should spawn two processes (one for each worker)
|
|
268
|
-
expect(spawnMock).toHaveBeenCalledTimes(2);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it("handles no enabled workers gracefully", async () => {
|
|
272
|
-
listEnabledWorkersMock = mock(() => []);
|
|
273
|
-
ConfigService.prototype.listEnabledWorkers = listEnabledWorkersMock;
|
|
274
|
-
|
|
275
|
-
const program = createProgram();
|
|
276
|
-
await program.parseAsync(["logs", "all"], { from: "user" });
|
|
277
|
-
|
|
278
|
-
// Should NOT spawn any processes
|
|
279
|
-
expect(spawnMock).toHaveBeenCalledTimes(0);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("handles config load failure gracefully", async () => {
|
|
283
|
-
loadMock = mock(async () => {
|
|
284
|
-
throw new Error("Config file not found");
|
|
285
|
-
});
|
|
286
|
-
ConfigService.prototype.load = loadMock;
|
|
287
|
-
|
|
288
|
-
const program = createProgram();
|
|
289
|
-
await program.parseAsync(["logs", "all"], { from: "user" });
|
|
290
|
-
|
|
291
|
-
expect(process.exitCode).toBe(ExitCode.ERROR);
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
});
|