@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,243 +0,0 @@
1
- /**
2
- * Unit tests for the repair command.
3
- *
4
- * Stubs RepairService, CloudflareService, DbService, KvSyncService, and
5
- * SecretsService prototypes to verify repair command logic in isolation.
6
- * Uses Commander's exitOverride to suppress process exits during tests.
7
- */
8
- import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
9
- import { Command } from "commander";
10
- import { RepairService } from "./repair-service.js";
11
- import { CloudflareService } from "../../services/cloudflare/cloudflare-service.js";
12
- import { DbService } from "../../services/db/db-service.js";
13
- import { KvSyncService } from "../../services/kv/kv-sync-service.js";
14
-
15
- // Stubs
16
- let runSystemCheckMock: ReturnType<typeof mock>;
17
- let deployMock: ReturnType<typeof mock>;
18
-
19
- // Preserve originals
20
- const origRunSystemCheck = RepairService.prototype.runSystemCheck;
21
- const origDeploy = CloudflareService.prototype.deploy;
22
- const origD1List = CloudflareService.prototype.d1List;
23
- const origKvList = CloudflareService.prototype.kvList;
24
- const origR2List = CloudflareService.prototype.r2List;
25
- const origQueueList = CloudflareService.prototype.queueList;
26
- const origResolveDbName = DbService.prototype.resolveDbName;
27
- const origApply = DbService.prototype.apply;
28
- const origMigrate = DbService.prototype.migrate;
29
- const origExport = DbService.prototype.export;
30
- const origReset = DbService.prototype.reset;
31
- const origResolveNs = KvSyncService.prototype.resolveNamespaceId;
32
- const origKvSet = KvSyncService.prototype.set;
33
-
34
- beforeEach(() => {
35
- mock.restore();
36
- process.exitCode = 0;
37
-
38
- // Restore originals
39
- (
40
- RepairService.prototype as unknown as Record<string, unknown>
41
- ).runSystemCheck = origRunSystemCheck;
42
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
43
- origDeploy;
44
- (CloudflareService.prototype as unknown as Record<string, unknown>).d1List =
45
- origD1List;
46
- (CloudflareService.prototype as unknown as Record<string, unknown>).kvList =
47
- origKvList;
48
- (CloudflareService.prototype as unknown as Record<string, unknown>).r2List =
49
- origR2List;
50
- (
51
- CloudflareService.prototype as unknown as Record<string, unknown>
52
- ).queueList = origQueueList;
53
- (DbService.prototype as unknown as Record<string, unknown>).resolveDbName =
54
- origResolveDbName;
55
- (DbService.prototype as unknown as Record<string, unknown>).apply = origApply;
56
- (DbService.prototype as unknown as Record<string, unknown>).migrate =
57
- origMigrate;
58
- (DbService.prototype as unknown as Record<string, unknown>).export =
59
- origExport;
60
- (DbService.prototype as unknown as Record<string, unknown>).reset = origReset;
61
- (
62
- KvSyncService.prototype as unknown as Record<string, unknown>
63
- ).resolveNamespaceId = origResolveNs;
64
- (KvSyncService.prototype as unknown as Record<string, unknown>).set =
65
- origKvSet;
66
-
67
- // Fresh mocks
68
- runSystemCheckMock = mock(async () => ({
69
- steps: [
70
- { step: "Worker submodules", success: true, message: "All present" },
71
- { step: "Dependencies", success: true, message: "Installed" },
72
- { step: "TypeScript", success: true, message: "No errors" },
73
- { step: "Infrastructure", success: true, message: "All ok" },
74
- { step: "Secrets", success: true, message: "All present" },
75
- ],
76
- allPassed: true,
77
- passedCount: 5,
78
- failedCount: 0,
79
- }));
80
-
81
- deployMock = mock(async (_path: string, _env?: string) => ({
82
- ok: true as const,
83
- data: { url: "https://test-worker.cryptolinx.workers.dev" },
84
- }));
85
-
86
- (
87
- RepairService.prototype as unknown as Record<string, unknown>
88
- ).runSystemCheck = runSystemCheckMock;
89
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
90
- deployMock;
91
- });
92
-
93
- afterEach(() => {
94
- mock.restore();
95
- (
96
- RepairService.prototype as unknown as Record<string, unknown>
97
- ).runSystemCheck = origRunSystemCheck;
98
- (CloudflareService.prototype as unknown as Record<string, unknown>).deploy =
99
- origDeploy;
100
- (CloudflareService.prototype as unknown as Record<string, unknown>).d1List =
101
- origD1List;
102
- (CloudflareService.prototype as unknown as Record<string, unknown>).kvList =
103
- origKvList;
104
- (CloudflareService.prototype as unknown as Record<string, unknown>).r2List =
105
- origR2List;
106
- (
107
- CloudflareService.prototype as unknown as Record<string, unknown>
108
- ).queueList = origQueueList;
109
- (DbService.prototype as unknown as Record<string, unknown>).resolveDbName =
110
- origResolveDbName;
111
- (DbService.prototype as unknown as Record<string, unknown>).apply = origApply;
112
- (DbService.prototype as unknown as Record<string, unknown>).migrate =
113
- origMigrate;
114
- (DbService.prototype as unknown as Record<string, unknown>).export =
115
- origExport;
116
- (DbService.prototype as unknown as Record<string, unknown>).reset = origReset;
117
- (
118
- KvSyncService.prototype as unknown as Record<string, unknown>
119
- ).resolveNamespaceId = origResolveNs;
120
- (KvSyncService.prototype as unknown as Record<string, unknown>).set =
121
- origKvSet;
122
- });
123
-
124
- async function importRepairCommand(): Promise<{
125
- registerRepairCommand: typeof import("./repair-command.js").registerRepairCommand;
126
- }> {
127
- return import("./repair-command.js");
128
- }
129
-
130
- async function createProgram(): Promise<Command> {
131
- const { registerRepairCommand } = await importRepairCommand();
132
- const program = new Command().name("hoox-test").exitOverride(() => {});
133
- registerRepairCommand(program);
134
- return program;
135
- }
136
-
137
- describe("registerRepairCommand", () => {
138
- // -- Command registration -------------------------------------------------
139
-
140
- it("registers 'repair' as a command on the program", async () => {
141
- const program = await createProgram();
142
- const cmd = program.commands.find((c) => c.name() === "repair");
143
- expect(cmd).toBeDefined();
144
- });
145
-
146
- it("registers 'repair check' subcommand", async () => {
147
- const program = await createProgram();
148
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
149
- expect(repairCmd.commands.find((c) => c.name() === "check")).toBeDefined();
150
- });
151
-
152
- it("registers 'repair worker <name>' with argument", async () => {
153
- const program = await createProgram();
154
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
155
- const workerCmd = repairCmd.commands.find((c) => c.name() === "worker");
156
- expect(workerCmd).toBeDefined();
157
- expect(
158
- workerCmd!.registeredArguments.some((a) => a.name() === "name")
159
- ).toBe(true);
160
- });
161
-
162
- it("registers 'repair infra' subcommand", async () => {
163
- const program = await createProgram();
164
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
165
- expect(repairCmd.commands.find((c) => c.name() === "infra")).toBeDefined();
166
- });
167
-
168
- it("registers 'repair secrets' subcommand", async () => {
169
- const program = await createProgram();
170
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
171
- expect(
172
- repairCmd.commands.find((c) => c.name() === "secrets")
173
- ).toBeDefined();
174
- });
175
-
176
- it("registers 'repair kv' subcommand", async () => {
177
- const program = await createProgram();
178
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
179
- expect(repairCmd.commands.find((c) => c.name() === "kv")).toBeDefined();
180
- });
181
-
182
- it("registers 'repair db' subcommand", async () => {
183
- const program = await createProgram();
184
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
185
- expect(repairCmd.commands.find((c) => c.name() === "db")).toBeDefined();
186
- });
187
-
188
- it("registers 'repair rebuild' subcommand", async () => {
189
- const program = await createProgram();
190
- const repairCmd = program.commands.find((c) => c.name() === "repair")!;
191
- expect(
192
- repairCmd.commands.find((c) => c.name() === "rebuild")
193
- ).toBeDefined();
194
- });
195
-
196
- // -- repair check ---------------------------------------------------------
197
-
198
- describe("repair check", () => {
199
- it("calls runSystemCheck", async () => {
200
- const program = await createProgram();
201
- await program.parseAsync(["repair", "check"], { from: "user" });
202
- expect(runSystemCheckMock).toHaveBeenCalled();
203
- });
204
-
205
- it("exits cleanly on all passed", async () => {
206
- const program = await createProgram();
207
- await program.parseAsync(["repair", "check"], { from: "user" });
208
- expect(process.exitCode).toBe(0);
209
- });
210
-
211
- it("sets exitCode on failure", async () => {
212
- runSystemCheckMock = mock(async () => {
213
- throw new Error("Check failed");
214
- });
215
- (
216
- RepairService.prototype as unknown as Record<string, unknown>
217
- ).runSystemCheck = runSystemCheckMock;
218
-
219
- const program = await createProgram();
220
- await program.parseAsync(["repair", "check"], { from: "user" });
221
- expect(process.exitCode).toBe(1);
222
- });
223
- });
224
-
225
- // -- repair worker <name> --------------------------------------------------
226
-
227
- describe("repair worker <name>", () => {
228
- it("calls deploy for the specified worker", async () => {
229
- const program = await createProgram();
230
- await program.parseAsync(["repair", "worker", "hoox"], { from: "user" });
231
- expect(deployMock).toHaveBeenCalled();
232
- });
233
-
234
- it("handles unknown worker name", async () => {
235
- // Mock getWorker to return undefined
236
- const program = await createProgram();
237
- await program.parseAsync(["repair", "worker", "nonexistent"], {
238
- from: "user",
239
- });
240
- expect(process.exitCode).toBe(1);
241
- });
242
- });
243
- });
@@ -1,220 +0,0 @@
1
- import { Command } from "commander";
2
- import { RepairService } from "./repair-service.js";
3
- import { CloudflareService } from "../../services/cloudflare/index.js";
4
- import { DbService } from "../../services/db/index.js";
5
- import { KvSyncService } from "../../services/kv/kv-sync-service.js";
6
- import { SecretsService } from "../../services/secrets/index.js";
7
- import {
8
- formatError,
9
- formatSuccess,
10
- type FormatOptions,
11
- getFormatOptions,
12
- } from "../../utils/formatters.js";
13
- import { CLIError, ExitCode } from "../../utils/errors.js";
14
-
15
- async function handleCheck(fmt: FormatOptions): Promise<void> {
16
- try {
17
- const svc = new RepairService();
18
- const result = await svc.runSystemCheck();
19
- if (result.allPassed) {
20
- formatSuccess("All checks passed", fmt);
21
- } else {
22
- formatError(
23
- new CLIError(`${result.failedCount} check(s) failed`, ExitCode.ERROR),
24
- fmt
25
- );
26
- process.exitCode = ExitCode.ERROR;
27
- }
28
- } catch (err) {
29
- formatError(err instanceof Error ? err : String(err), fmt);
30
- process.exitCode = ExitCode.ERROR;
31
- }
32
- }
33
-
34
- async function handleWorker(name: string, fmt: FormatOptions): Promise<void> {
35
- try {
36
- const { ConfigService } = await import("../../services/config/index.js");
37
- const config = new ConfigService();
38
- await config.load();
39
- const workerConfig = config.getWorker(name);
40
- if (!workerConfig) {
41
- formatError(
42
- new CLIError(`Worker "${name}" not found`, ExitCode.ERROR),
43
- fmt
44
- );
45
- process.exitCode = ExitCode.ERROR;
46
- return;
47
- }
48
- const cf = new CloudflareService();
49
- const result = await cf.deploy(workerConfig.path);
50
- if (result.ok) {
51
- formatSuccess(`Worker "${name}" deployed — ${result.value.url}`, fmt);
52
- } else {
53
- formatError(
54
- new CLIError(
55
- `Failed to deploy "${name}": ${result.error}`,
56
- ExitCode.ERROR
57
- ),
58
- fmt
59
- );
60
- process.exitCode = ExitCode.ERROR;
61
- }
62
- } catch (err) {
63
- formatError(err instanceof Error ? err : String(err), fmt);
64
- process.exitCode = ExitCode.ERROR;
65
- }
66
- }
67
-
68
- async function handleInfra(fmt: FormatOptions): Promise<void> {
69
- try {
70
- const cf = new CloudflareService();
71
- const d1 = await cf.d1List();
72
- const kv = await cf.kvList();
73
- const r2 = await cf.r2List();
74
- const q = await cf.queueList();
75
- formatSuccess(
76
- `D1: ${d1.ok ? "ok" : "fail"}, KV: ${kv.ok ? "ok" : "fail"}, R2: ${r2.ok ? "ok" : "fail"}, Queues: ${q.ok ? "ok" : "fail"}`,
77
- fmt
78
- );
79
- } catch (err) {
80
- formatError(err instanceof Error ? err : String(err), fmt);
81
- process.exitCode = ExitCode.ERROR;
82
- }
83
- }
84
-
85
- async function handleSecrets(fmt: FormatOptions): Promise<void> {
86
- try {
87
- const secrets = await SecretsService.create();
88
- const allSecrets = secrets.listAllSecrets();
89
- let missing = 0;
90
- for (const name of Object.keys(allSecrets)) {
91
- const check = await secrets.checkLocalSecrets(name);
92
- missing += check.missing.length;
93
- }
94
- if (missing > 0) {
95
- formatError(
96
- new CLIError(`${missing} secret(s) missing`, ExitCode.ERROR),
97
- fmt
98
- );
99
- process.exitCode = ExitCode.ERROR;
100
- } else {
101
- formatSuccess("All secrets present", fmt);
102
- }
103
- } catch (err) {
104
- formatError(err instanceof Error ? err : String(err), fmt);
105
- process.exitCode = ExitCode.ERROR;
106
- }
107
- }
108
-
109
- async function handleKv(fmt: FormatOptions): Promise<void> {
110
- try {
111
- const kv = new KvSyncService();
112
- const nsId = await kv.resolveNamespaceId();
113
- formatSuccess(`KV namespace resolved: ${nsId}`, fmt);
114
- } catch (err) {
115
- formatError(err instanceof Error ? err : String(err), fmt);
116
- process.exitCode = ExitCode.ERROR;
117
- }
118
- }
119
-
120
- async function handleDb(fmt: FormatOptions): Promise<void> {
121
- try {
122
- const svc = new DbService();
123
- const dbName = await svc.resolveDbName();
124
- await svc.apply(dbName, false);
125
- formatSuccess(`DB "${dbName}" re-applied`, fmt);
126
- } catch (err) {
127
- formatError(err instanceof Error ? err : String(err), fmt);
128
- process.exitCode = ExitCode.ERROR;
129
- }
130
- }
131
-
132
- async function handleRebuild(fmt: FormatOptions): Promise<void> {
133
- try {
134
- const repair = new RepairService();
135
- await repair.runSystemCheck();
136
- const cf = new CloudflareService();
137
- const { ConfigService } = await import("../../services/config/index.js");
138
- const config = new ConfigService();
139
- await config.load();
140
- for (const worker of config.listEnabledWorkers()) {
141
- const cfg = config.getWorker(worker);
142
- if (cfg) {
143
- await cf.deploy(cfg.path);
144
- }
145
- }
146
- formatSuccess("Rebuild complete", fmt);
147
- } catch (err) {
148
- formatError(err instanceof Error ? err : String(err), fmt);
149
- process.exitCode = ExitCode.ERROR;
150
- }
151
- }
152
-
153
- export function registerRepairCommand(program: Command): void {
154
- const repairCmd = program
155
- .command("repair")
156
- .summary("Diagnose and repair the Hoox system")
157
- .description(
158
- "Run checks, deploy workers, or fix infrastructure, secrets, KV, and DB issues."
159
- );
160
-
161
- repairCmd
162
- .command("check")
163
- .description(
164
- "Run system diagnostics (workers, deps, types, infra, secrets)"
165
- )
166
- .action(async () => {
167
- const fmt = getFormatOptions(repairCmd);
168
- await handleCheck(fmt);
169
- });
170
-
171
- repairCmd
172
- .command("worker <name>")
173
- .description("Deploy a specific worker to fix it")
174
- .action(async (name: string) => {
175
- const fmt = getFormatOptions(repairCmd);
176
- await handleWorker(name, fmt);
177
- });
178
-
179
- repairCmd
180
- .command("infra")
181
- .description("Provision missing infrastructure (D1, KV, R2, Queues)")
182
- .action(async () => {
183
- const fmt = getFormatOptions(repairCmd);
184
- await handleInfra(fmt);
185
- });
186
-
187
- repairCmd
188
- .command("secrets")
189
- .description("Upload missing secrets to Cloudflare")
190
- .action(async () => {
191
- const fmt = getFormatOptions(repairCmd);
192
- await handleSecrets(fmt);
193
- });
194
-
195
- repairCmd
196
- .command("kv")
197
- .description("Re-sync KV namespace entries")
198
- .action(async () => {
199
- const fmt = getFormatOptions(repairCmd);
200
- await handleKv(fmt);
201
- });
202
-
203
- repairCmd
204
- .command("db")
205
- .description("Re-apply database schema")
206
- .action(async () => {
207
- const fmt = getFormatOptions(repairCmd);
208
- await handleDb(fmt);
209
- });
210
-
211
- repairCmd
212
- .command("rebuild")
213
- .description(
214
- "Full rebuild: check, deploy all workers, fix infra/secrets/db"
215
- )
216
- .action(async () => {
217
- const fmt = getFormatOptions(repairCmd);
218
- await handleRebuild(fmt);
219
- });
220
- }
@@ -1,164 +0,0 @@
1
- import { CloudflareService } from "../../services/cloudflare/index.js";
2
- import { SecretsService } from "../../services/secrets/index.js";
3
- import type { RepairStepResult, RepairCheckResult } from "./types.js";
4
-
5
- export class RepairService {
6
- async runSystemCheck(): Promise<RepairCheckResult> {
7
- const steps: RepairStepResult[] = [];
8
-
9
- // Step 1: Repository integrity (worker submodules)
10
- try {
11
- const proc = Bun.spawn(["bun", "run", "check:worker-submodules"], {
12
- stdout: "pipe",
13
- stderr: "pipe",
14
- });
15
- const exit = await proc.exited;
16
- steps.push({
17
- step: "Worker submodules",
18
- success: exit === 0,
19
- message: exit === 0 ? "All submodules present" : "Missing submodules",
20
- });
21
- } catch (err) {
22
- steps.push({
23
- step: "Worker submodules",
24
- success: false,
25
- error: String(err),
26
- });
27
- }
28
-
29
- // Step 2: Dependencies
30
- try {
31
- const proc = Bun.spawn(["bun", "install"], {
32
- stdout: "pipe",
33
- stderr: "pipe",
34
- });
35
- const exit = await proc.exited;
36
- steps.push({
37
- step: "Dependencies",
38
- success: exit === 0,
39
- message:
40
- exit === 0 ? "All dependencies installed" : "bun install failed",
41
- });
42
- } catch (err) {
43
- steps.push({ step: "Dependencies", success: false, error: String(err) });
44
- }
45
-
46
- // Step 3: TypeScript
47
- try {
48
- const proc = Bun.spawn(["bun", "run", "typecheck"], {
49
- stdout: "pipe",
50
- stderr: "pipe",
51
- });
52
- const exit = await proc.exited;
53
- steps.push({
54
- step: "TypeScript",
55
- success: exit === 0,
56
- message: exit === 0 ? "No type errors" : "TypeScript errors found",
57
- });
58
- } catch (err) {
59
- steps.push({ step: "TypeScript", success: false, error: String(err) });
60
- }
61
-
62
- // Step 4: Infrastructure
63
- try {
64
- const cf = new CloudflareService();
65
- const d1Result = await cf.d1List();
66
- const kvResult = await cf.kvList();
67
- const r2Result = await cf.r2List();
68
- const queueResult = await cf.queueList();
69
-
70
- let infraOk = true;
71
- const details: string[] = [];
72
- if (d1Result.ok) details.push("D1: ✓");
73
- else {
74
- infraOk = false;
75
- details.push("D1: ✗");
76
- }
77
- if (kvResult.ok) details.push("KV: ✓");
78
- else {
79
- infraOk = false;
80
- details.push("KV: ✗");
81
- }
82
- if (r2Result.ok) details.push("R2: ✓");
83
- else {
84
- infraOk = false;
85
- details.push("R2: ✗");
86
- }
87
- if (queueResult.ok) details.push("Queues: ✓");
88
- else {
89
- infraOk = false;
90
- details.push("Queues: ✗");
91
- }
92
-
93
- steps.push({
94
- step: "Infrastructure",
95
- success: infraOk,
96
- message: details.join(", "),
97
- });
98
- } catch (err) {
99
- steps.push({
100
- step: "Infrastructure",
101
- success: false,
102
- error: String(err),
103
- });
104
- }
105
-
106
- // Step 5: Secrets
107
- try {
108
- const secrets = await SecretsService.create();
109
- const allSecrets = secrets.listAllSecrets();
110
- let missingCount = 0;
111
- let totalSecrets = 0;
112
- for (const workerName of Object.keys(allSecrets)) {
113
- const check = await secrets.checkLocalSecrets(workerName);
114
- totalSecrets += check.secrets.length;
115
- missingCount += check.missing.length;
116
- }
117
- steps.push({
118
- step: "Secrets",
119
- success: missingCount === 0,
120
- message:
121
- missingCount === 0
122
- ? `All ${totalSecrets} secrets present`
123
- : `${missingCount}/${totalSecrets} missing`,
124
- });
125
- } catch (err) {
126
- steps.push({ step: "Secrets", success: false, error: String(err) });
127
- }
128
-
129
- // Step 6: Worker config schema validation
130
- try {
131
- const { SchemaService } =
132
- await import("../../services/schema/schema-service.js");
133
- const svc = new SchemaService();
134
- const results = svc.validateAll();
135
- const totalErrors = results.reduce(
136
- (sum, r) => sum + r.errors.filter((e) => e.severity === "error").length,
137
- 0
138
- );
139
- steps.push({
140
- step: "Worker config schema",
141
- success: totalErrors === 0,
142
- message:
143
- totalErrors === 0
144
- ? "All workers match manifest"
145
- : `${totalErrors} schema issue(s) found`,
146
- });
147
- } catch (err) {
148
- steps.push({
149
- step: "Worker config schema",
150
- success: false,
151
- error: String(err),
152
- });
153
- }
154
-
155
- const passed = steps.filter((s) => s.success).length;
156
- const failed = steps.filter((s) => !s.success).length;
157
- return {
158
- steps,
159
- allPassed: failed === 0,
160
- passedCount: passed,
161
- failedCount: failed,
162
- };
163
- }
164
- }
@@ -1,13 +0,0 @@
1
- export interface RepairStepResult {
2
- step: string;
3
- success: boolean;
4
- message?: string;
5
- error?: string;
6
- }
7
-
8
- export interface RepairCheckResult {
9
- steps: RepairStepResult[];
10
- allPassed: boolean;
11
- passedCount: number;
12
- failedCount: number;
13
- }
@@ -1 +0,0 @@
1
- export { registerSchemaCommand } from "./schema-command.js";