@jango-blockchained/hoox-cli 0.5.2 → 0.5.7

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 +32989 -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,324 +0,0 @@
1
- /**
2
- * Unit tests for the deploy command.
3
- *
4
- * Stubs ConfigService and CloudflareService prototypes to verify the deploy
5
- * command logic in isolation. Uses Commander's exitOverride to suppress
6
- * process exits during test runs.
7
- *
8
- * Subcommand actions are async — we use parseAsync() and then inspect mocks
9
- * to confirm correct service calls.
10
- */
11
- import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
12
- import { Command } from "commander";
13
- import { ConfigService } from "../../services/config/config-service.js";
14
- import { CloudflareService } from "../../services/cloudflare/cloudflare-service.js";
15
-
16
- // We import at the top level — the deploy command module also imports
17
- // @clack/prompts, which outputs to stdout during tests (fine).
18
-
19
- // ---------------------------------------------------------------------------
20
- // Stub variables — reassigned in beforeEach
21
- // ---------------------------------------------------------------------------
22
-
23
- let deployMock: ReturnType<typeof mock>;
24
- let loadMock: ReturnType<typeof mock>;
25
- let listEnabledWorkersMock: ReturnType<typeof mock>;
26
- let getWorkerMock: ReturnType<typeof mock>;
27
-
28
- // Preserve originals so we can restore them after tests
29
- const origLoad = ConfigService.prototype
30
- .load as typeof ConfigService.prototype.load;
31
- const origListEnabled = ConfigService.prototype
32
- .listEnabledWorkers as typeof ConfigService.prototype.listEnabledWorkers;
33
- const origGetWorker = ConfigService.prototype
34
- .getWorker as typeof ConfigService.prototype.getWorker;
35
- const origDeploy = CloudflareService.prototype
36
- .deploy as typeof CloudflareService.prototype.deploy;
37
-
38
- beforeEach(() => {
39
- mock.restore();
40
-
41
- // Reset process.exitCode between tests
42
- process.exitCode = undefined;
43
-
44
- // Reset prototypes to originals (in case a previous test didn't restore)
45
- (ConfigService.prototype as unknown as Record<string, unknown>).load =
46
- origLoad;
47
- (
48
- ConfigService.prototype as unknown as Record<string, unknown>
49
- ).listEnabledWorkers = origListEnabled;
50
- (ConfigService.prototype as unknown as Record<string, unknown>).getWorker =
51
- origGetWorker;
52
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
53
- origDeploy;
54
-
55
- // Fresh mocks
56
- deployMock = mock(async (_path: string, _env?: string) => ({
57
- ok: true as const,
58
- value: { url: "https://test-worker.cryptolinx.workers.dev", rawOutput: "" },
59
- }));
60
-
61
- loadMock = mock(async () => ({}));
62
- listEnabledWorkersMock = mock(() => ["d1-worker", "hoox", "trade-worker"]);
63
- getWorkerMock = mock((_name: string) => ({
64
- enabled: true,
65
- path: "workers/test-worker",
66
- }));
67
-
68
- // Install mocks on prototypes
69
- (ConfigService.prototype as unknown as Record<string, unknown>).load =
70
- loadMock;
71
- (
72
- ConfigService.prototype as unknown as Record<string, unknown>
73
- ).listEnabledWorkers = listEnabledWorkersMock;
74
- (ConfigService.prototype as unknown as Record<string, unknown>).getWorker =
75
- getWorkerMock;
76
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
77
- deployMock;
78
- });
79
-
80
- afterEach(() => {
81
- mock.restore();
82
-
83
- // Restore originals
84
- (ConfigService.prototype as unknown as Record<string, unknown>).load =
85
- origLoad;
86
- (
87
- ConfigService.prototype as unknown as Record<string, unknown>
88
- ).listEnabledWorkers = origListEnabled;
89
- (ConfigService.prototype as unknown as Record<string, unknown>).getWorker =
90
- origGetWorker;
91
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
92
- origDeploy;
93
- });
94
-
95
- // ---------------------------------------------------------------------------
96
- // Dynamic import — load the deploy command after stubs are in place
97
- // ---------------------------------------------------------------------------
98
-
99
- async function importDeployCommand(): Promise<{
100
- registerDeployCommand: typeof import("./deploy-command.js").registerDeployCommand;
101
- }> {
102
- return import("./deploy-command.js");
103
- }
104
-
105
- /**
106
- * Create a fresh Commander program with the deploy command registered.
107
- */
108
- async function createProgram(): Promise<Command> {
109
- const { registerDeployCommand } = await importDeployCommand();
110
- const program = new Command().name("hoox-test").exitOverride(() => {
111
- // Suppress Commander's own exit during tests
112
- });
113
- registerDeployCommand(program);
114
- return program;
115
- }
116
-
117
- /** Make deployMock return a failure for all subsequent calls. */
118
- function makeDeployFail(error: string): void {
119
- deployMock = mock(async () => ({ ok: false as const, error }));
120
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
121
- deployMock;
122
- }
123
-
124
- // ---------------------------------------------------------------------------
125
- // Tests
126
- // ---------------------------------------------------------------------------
127
-
128
- describe("registerDeployCommand", () => {
129
- // -- Command registration -------------------------------------------------
130
-
131
- it("registers 'deploy' as a command on the program", async () => {
132
- const program = await createProgram();
133
- const deployCmd = program.commands.find((c) => c.name() === "deploy");
134
- expect(deployCmd).toBeDefined();
135
- });
136
-
137
- it("registers 'deploy all' subcommand", async () => {
138
- const program = await createProgram();
139
- const deployCmd = program.commands.find((c) => c.name() === "deploy")!;
140
- const allCmd = deployCmd.commands.find((c) => c.name() === "all");
141
- expect(allCmd).toBeDefined();
142
- expect(allCmd!.description()).toContain("Deploy all enabled workers");
143
- });
144
-
145
- it("registers 'deploy workers' subcommand", async () => {
146
- const program = await createProgram();
147
- const deployCmd = program.commands.find((c) => c.name() === "deploy")!;
148
- const workersCmd = deployCmd.commands.find((c) => c.name() === "workers");
149
- expect(workersCmd).toBeDefined();
150
- expect(workersCmd!.description()).toContain("Deploy all enabled workers");
151
- });
152
-
153
- it("registers 'deploy worker <name>' subcommand with argument", async () => {
154
- const program = await createProgram();
155
- const deployCmd = program.commands.find((c) => c.name() === "deploy")!;
156
- const workerCmd = deployCmd.commands.find((c) => c.name() === "worker");
157
- expect(workerCmd).toBeDefined();
158
- const args = workerCmd!.registeredArguments;
159
- expect(args.some((a) => a.name() === "name")).toBe(true);
160
- });
161
-
162
- it("registers 'deploy dashboard' subcommand", async () => {
163
- const program = await createProgram();
164
- const deployCmd = program.commands.find((c) => c.name() === "deploy")!;
165
- const dashboardCmd = deployCmd.commands.find(
166
- (c) => c.name() === "dashboard"
167
- );
168
- expect(dashboardCmd).toBeDefined();
169
- expect(dashboardCmd!.description()).toContain("dashboard");
170
- });
171
-
172
- // -- deploy workers -------------------------------------------------------
173
-
174
- describe("deploy workers", () => {
175
- it("calls listEnabledWorkers and deploys each", async () => {
176
- listEnabledWorkersMock = mock(() => [
177
- "d1-worker",
178
- "hoox",
179
- "trade-worker",
180
- ]);
181
- (
182
- ConfigService.prototype as unknown as Record<string, unknown>
183
- ).listEnabledWorkers = listEnabledWorkersMock;
184
-
185
- const program = await createProgram();
186
- await program.parseAsync(["deploy", "workers"], { from: "user" });
187
-
188
- expect(listEnabledWorkersMock).toHaveBeenCalled();
189
- expect(deployMock).toHaveBeenCalledTimes(3);
190
- });
191
-
192
- it("handles no enabled workers gracefully", async () => {
193
- listEnabledWorkersMock = mock(() => []);
194
- (
195
- ConfigService.prototype as unknown as Record<string, unknown>
196
- ).listEnabledWorkers = listEnabledWorkersMock;
197
-
198
- const program = await createProgram();
199
- await program.parseAsync(["deploy", "workers"], { from: "user" });
200
-
201
- expect(deployMock).toHaveBeenCalledTimes(0);
202
- });
203
-
204
- it("continues deploying remaining workers on partial failure", async () => {
205
- listEnabledWorkersMock = mock(() => ["a", "b", "c"]);
206
- (
207
- ConfigService.prototype as unknown as Record<string, unknown>
208
- ).listEnabledWorkers = listEnabledWorkersMock;
209
-
210
- let calls = 0;
211
- deployMock = mock(async () => {
212
- calls++;
213
- if (calls === 2) {
214
- return { ok: false as const, error: "deploy error" };
215
- }
216
- return {
217
- ok: true as const,
218
- value: { url: "https://x.workers.dev", rawOutput: "" },
219
- };
220
- });
221
- (
222
- CloudflareService.prototype as unknown as Record<string, unknown>
223
- ).deploy = deployMock;
224
-
225
- const program = await createProgram();
226
- await program.parseAsync(["deploy", "workers"], { from: "user" });
227
-
228
- expect(deployMock).toHaveBeenCalledTimes(3);
229
- expect(calls).toBe(3);
230
- });
231
-
232
- it("passes --env to deploy", async () => {
233
- listEnabledWorkersMock = mock(() => ["single-worker"]);
234
- (
235
- ConfigService.prototype as unknown as Record<string, unknown>
236
- ).listEnabledWorkers = listEnabledWorkersMock;
237
-
238
- const program = await createProgram();
239
- await program.parseAsync(["deploy", "workers", "--env", "staging"], {
240
- from: "user",
241
- });
242
-
243
- expect(deployMock).toHaveBeenCalledTimes(1);
244
- const calls = (
245
- deployMock as unknown as { mock: { calls: Array<unknown[]> } }
246
- ).mock.calls;
247
- expect(calls[0][1]).toBe("staging");
248
- });
249
- });
250
-
251
- // -- deploy worker <name> -------------------------------------------------
252
-
253
- describe("deploy worker <name>", () => {
254
- it("deploys the specified worker successfully", async () => {
255
- const program = await createProgram();
256
- await program.parseAsync(["deploy", "worker", "hoox"], { from: "user" });
257
-
258
- expect(deployMock).toHaveBeenCalledTimes(1);
259
- const calls = (
260
- deployMock as unknown as { mock: { calls: Array<unknown[]> } }
261
- ).mock.calls;
262
- expect(calls[0][0]).toContain("test-worker");
263
- });
264
-
265
- it("passes --env to deploy", async () => {
266
- const program = await createProgram();
267
- await program.parseAsync(
268
- ["deploy", "worker", "hoox", "--env", "production"],
269
- { from: "user" }
270
- );
271
-
272
- const calls = (
273
- deployMock as unknown as { mock: { calls: Array<unknown[]> } }
274
- ).mock.calls;
275
- expect(calls[0][1]).toBe("production");
276
- });
277
-
278
- it("handles deploy failure (sets exitCode to 1)", async () => {
279
- makeDeployFail("authentication error");
280
- getWorkerMock = mock(() => ({
281
- enabled: true,
282
- path: "workers/hoox",
283
- }));
284
- (
285
- ConfigService.prototype as unknown as Record<string, unknown>
286
- ).getWorker = getWorkerMock;
287
-
288
- const program = await createProgram();
289
- await program.parseAsync(["deploy", "worker", "hoox"], { from: "user" });
290
-
291
- expect(process.exitCode).toBe(1);
292
- });
293
-
294
- it("handles unknown worker name without calling deploy", async () => {
295
- getWorkerMock = mock(() => undefined);
296
- (
297
- ConfigService.prototype as unknown as Record<string, unknown>
298
- ).getWorker = getWorkerMock;
299
-
300
- const program = await createProgram();
301
- await program.parseAsync(["deploy", "worker", "nonexistent"], {
302
- from: "user",
303
- });
304
-
305
- expect(deployMock).toHaveBeenCalledTimes(0);
306
- expect(process.exitCode).toBe(1);
307
- });
308
- });
309
-
310
- // -- config loading errors ------------------------------------------------
311
-
312
- it("handles config load failure gracefully", async () => {
313
- loadMock = mock(async () => {
314
- throw new Error("Config file not found");
315
- });
316
- (ConfigService.prototype as unknown as Record<string, unknown>).load =
317
- loadMock;
318
-
319
- const program = await createProgram();
320
- await program.parseAsync(["deploy", "workers"], { from: "user" });
321
-
322
- expect(process.exitCode).toBe(1);
323
- });
324
- });