@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.
- 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 -1087
- 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 -97
- package/src/commands/check/types.ts +0 -103
- package/src/commands/clone/clone-command.test.ts +0 -440
- 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 -896
- package/src/commands/config/env-command.test.ts +0 -43
- package/src/commands/config/env-command.ts +0 -292
- 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 -130
- 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 -311
- package/src/commands/db/index.ts +0 -1
- package/src/commands/deploy/deploy-command.test.ts +0 -324
- package/src/commands/deploy/deploy-command.ts +0 -1054
- 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 -405
- package/src/commands/dev/dev-command.ts +0 -398
- package/src/commands/dev/index.ts +0 -1
- package/src/commands/disclaimer/disclaimer-command.ts +0 -21
- package/src/commands/disclaimer/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 -854
- package/src/commands/init/init-command.ts +0 -597
- 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 -293
- 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 -271
- 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 -243
- package/src/commands/repair/repair-command.ts +0 -220
- package/src/commands/repair/repair-service.ts +0 -164
- package/src/commands/repair/types.ts +0 -13
- package/src/commands/schema/index.ts +0 -1
- package/src/commands/schema/schema-command.ts +0 -137
- package/src/commands/test/index.ts +0 -2
- package/src/commands/test/test-command.test.ts +0 -318
- 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 -109
- 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 -545
- package/src/index.ts +0 -261
- 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 -202
- 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 -63
- 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 -259
- package/src/services/env/env-service.ts +0 -372
- 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 -243
- 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/schema/index.ts +0 -1
- package/src/services/schema/schema-service.ts +0 -99
- package/src/services/secrets/index.ts +0 -11
- package/src/services/secrets/secrets-service.test.ts +0 -502
- 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/error-handler.ts +0 -62
- package/src/utils/errors.test.ts +0 -69
- package/src/utils/errors.ts +0 -24
- package/src/utils/formatters.test.ts +0 -180
- package/src/utils/formatters.ts +0 -269
- package/src/utils/git.ts +0 -134
- 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
|
-
});
|