@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,431 +0,0 @@
1
- /**
2
- * `hoox clone` command — clone worker repos as git submodules.
3
- *
4
- * Modes:
5
- * hoox clone — List workers with clone status (cloned / not cloned)
6
- * hoox clone --all — Clone all workers from wrangler.jsonc
7
- * hoox clone <name> — Clone a specific worker by name
8
- *
9
- * Repo URLs are derived from: https://github.com/<org>/<worker-name>.git
10
- * The org is auto-detected from `git remote get-url origin` or set via --org.
11
- *
12
- * Uses @clack/prompts spinner for progress feedback.
13
- */
14
- import { Command } from "commander";
15
- import { spinner } from "@clack/prompts";
16
- import { ConfigService } from "../../services/config/index.js";
17
- import { icons } from "../../utils/theme.js";
18
- import {
19
- formatSuccess,
20
- formatError,
21
- formatTable,
22
- formatJson,
23
- getFormatOptions,
24
- } from "../../utils/formatters.js";
25
- import { CLIError, ExitCode } from "../../utils/errors.js";
26
-
27
- // ---------------------------------------------------------------------------
28
- // Types
29
- // ---------------------------------------------------------------------------
30
-
31
- /** Per-worker clone status entry. */
32
- interface CloneStatus {
33
- worker: string;
34
- path: string;
35
- cloned: boolean;
36
- repo?: string;
37
- error?: string;
38
- }
39
-
40
- /**
41
- * Resolve the base GitHub URL for worker repos.
42
- * Tries `git remote get-url origin` first, falls back to a sensible default.
43
- *
44
- * Examples:
45
- * https://github.com/org/repo.git → https://github.com/org
46
- * git@github.com:org/repo.git → https://github.com/org
47
- */
48
- async function resolveRepoBase(): Promise<string> {
49
- try {
50
- const proc = Bun.spawn(["git", "remote", "get-url", "origin"], {
51
- stdout: "pipe",
52
- stderr: "pipe",
53
- });
54
- const exitCode = await proc.exited;
55
- if (exitCode === 0) {
56
- const url = (await new Response(proc.stdout).text()).trim();
57
- const match = url.match(/github\.com[:/]([^/]+)\/.+?(?:\.git)?$/);
58
- if (match) {
59
- return `https://github.com/${match[1]}`;
60
- }
61
- }
62
- } catch {
63
- // Fall through to default
64
- }
65
- return "https://github.com/jango-blockchained";
66
- }
67
-
68
- /** Build a repo URL from the org base and worker name. */
69
- function getRepoUrl(orgBase: string, workerName: string): string {
70
- return `${orgBase}/${workerName}.git`;
71
- }
72
-
73
- /**
74
- * Check whether a worker is already cloned (has a `.git` entry).
75
- * For git submodules this is a file (not a directory) pointing to the
76
- * superproject's modules directory.
77
- */
78
- async function isWorkerCloned(workerPath: string): Promise<boolean> {
79
- const dotGit = Bun.file(`${workerPath}/.git`);
80
- return dotGit.exists();
81
- }
82
-
83
- /**
84
- * Run `git submodule add <repo> <path>` to clone a single worker.
85
- * Returns a CloneStatus with the outcome.
86
- */
87
- async function cloneWorker(
88
- repoUrl: string,
89
- targetPath: string,
90
- name: string,
91
- cwd: string
92
- ): Promise<CloneStatus> {
93
- const proc = Bun.spawn(["git", "submodule", "add", repoUrl, targetPath], {
94
- cwd,
95
- stdout: "pipe",
96
- stderr: "pipe",
97
- });
98
-
99
- const exitCode = await proc.exited;
100
-
101
- if (exitCode !== 0) {
102
- const stderr = await new Response(proc.stderr).text();
103
- return {
104
- worker: name,
105
- path: targetPath,
106
- cloned: false,
107
- repo: repoUrl,
108
- error:
109
- stderr.trim() || `git submodule add failed with exit code ${exitCode}`,
110
- };
111
- }
112
-
113
- return {
114
- worker: name,
115
- path: targetPath,
116
- cloned: true,
117
- repo: repoUrl,
118
- };
119
- }
120
-
121
- /** Run `git submodule update --init --recursive`. */
122
- async function updateSubmodules(cwd: string): Promise<void> {
123
- const proc = Bun.spawn(
124
- ["git", "submodule", "update", "--init", "--recursive"],
125
- {
126
- cwd,
127
- stdout: "pipe",
128
- stderr: "pipe",
129
- }
130
- );
131
-
132
- const exitCode = await proc.exited;
133
-
134
- if (exitCode !== 0) {
135
- const stderr = await new Response(proc.stderr).text();
136
- throw new Error(
137
- stderr.trim() || `git submodule update failed with exit code ${exitCode}`
138
- );
139
- }
140
- }
141
-
142
- /**
143
- * Build the list of worker clone statuses, checking the filesystem for
144
- * whether each worker has already been cloned.
145
- */
146
- async function buildStatusList(
147
- configService: ConfigService,
148
- repoBase: string
149
- ): Promise<CloneStatus[]> {
150
- const workers = configService.listWorkers();
151
- const statuses: CloneStatus[] = [];
152
-
153
- for (const name of workers) {
154
- const workerConfig = configService.getWorker(name);
155
- if (!workerConfig) continue;
156
-
157
- const cloned = await isWorkerCloned(workerConfig.path);
158
- statuses.push({
159
- worker: name,
160
- path: workerConfig.path,
161
- cloned,
162
- repo: getRepoUrl(repoBase, name),
163
- });
164
- }
165
-
166
- return statuses;
167
- }
168
-
169
- // ---------------------------------------------------------------------------
170
- // Command registration
171
- // ---------------------------------------------------------------------------
172
-
173
- /**
174
- * Register the `hoox clone` command on the given commander program.
175
- *
176
- * @example
177
- * ```ts
178
- * import { registerCloneCommand } from "./commands/clone/index.js";
179
- * registerCloneCommand(program);
180
- * ```
181
- */
182
- export function registerCloneCommand(program: Command): void {
183
- program
184
- .command("clone")
185
- .summary("Clone worker repositories as git submodules")
186
- .description(
187
- `Clone worker repositories from GitHub as git submodules.
188
-
189
- Workers in the Hoox monorepo are stored as git submodules. This command helps you clone them.
190
-
191
- MODES:
192
- hoox clone List clone status of all workers
193
- hoox clone --all Clone all workers
194
- hoox clone <name> Clone a specific worker
195
-
196
- OPTIONS:
197
- --all Clone all worker repositories
198
- --org <org> GitHub organization (auto-detected from git remote by default)
199
-
200
- ARGUMENTS:
201
- name Optional worker name to clone (e.g., trade-worker, agent-worker)
202
-
203
- EXAMPLES:
204
- hoox clone List all workers' clone status
205
- hoox clone --all Clone all workers
206
- hoox clone trade-worker Clone specific worker
207
- hoox clone --org my-org Clone from specific org`
208
- )
209
- .option("--all", "Clone all worker repositories")
210
- .option(
211
- "--org <org>",
212
- "GitHub organization (derived from git remote by default)"
213
- )
214
- .argument("[name]", "Worker name to clone (omit to list status)")
215
- .action(
216
- async (
217
- name: string | undefined,
218
- options: { all?: boolean; org?: string }
219
- ) => {
220
- const fmt = getFormatOptions(program);
221
-
222
- try {
223
- const configService = new ConfigService();
224
- await configService.load();
225
-
226
- const workers = configService.listWorkers();
227
-
228
- // -------------------------------------------------------------------
229
- // Mode 1: No name, no --all → list clone status
230
- // -------------------------------------------------------------------
231
- if (!options.all && !name) {
232
- const repoBase = options.org
233
- ? `https://github.com/${options.org}`
234
- : await resolveRepoBase();
235
-
236
- const statuses = await buildStatusList(configService, repoBase);
237
-
238
- if (fmt.json) {
239
- formatJson(statuses, fmt);
240
- return;
241
- }
242
-
243
- if (fmt.quiet) {
244
- for (const s of statuses) {
245
- process.stdout.write(
246
- `${s.worker}: ${s.cloned ? "cloned" : "not cloned"}\n`
247
- );
248
- }
249
- return;
250
- }
251
-
252
- const rows = statuses.map((s) => ({
253
- Worker: s.worker,
254
- Status: s.cloned ? "cloned" : "not cloned",
255
- Repo: s.repo ?? "-",
256
- }));
257
- formatTable(rows, fmt);
258
- return;
259
- }
260
-
261
- // -------------------------------------------------------------------
262
- // Mode 2: --all
263
- // -------------------------------------------------------------------
264
- if (options.all) {
265
- if (workers.length === 0) {
266
- formatSuccess("No workers defined in wrangler.jsonc", fmt);
267
- return;
268
- }
269
-
270
- const repoBase = options.org
271
- ? `https://github.com/${options.org}`
272
- : await resolveRepoBase();
273
-
274
- const s = spinner();
275
- s.start(`Cloning ${workers.length} worker(s)...`);
276
-
277
- const results: CloneStatus[] = [];
278
-
279
- for (let i = 0; i < workers.length; i++) {
280
- const name = workers[i];
281
- const workerConfig = configService.getWorker(name);
282
- if (!workerConfig) continue;
283
-
284
- // Skip already cloned workers
285
- const alreadyCloned = await isWorkerCloned(workerConfig.path);
286
- if (alreadyCloned) {
287
- s.message(
288
- `[${i + 1}/${workers.length}] ${icons.info} ${name} already cloned — skipping`
289
- );
290
- results.push({
291
- worker: name,
292
- path: workerConfig.path,
293
- cloned: true,
294
- repo: getRepoUrl(repoBase, name),
295
- });
296
- continue;
297
- }
298
-
299
- s.message(`[${i + 1}/${workers.length}] Cloning ${name}...`);
300
-
301
- const result = await cloneWorker(
302
- getRepoUrl(repoBase, name),
303
- workerConfig.path,
304
- name,
305
- process.cwd()
306
- );
307
- results.push(result);
308
-
309
- if (result.cloned) {
310
- s.message(
311
- `[${i + 1}/${workers.length}] ${icons.success} ${name} cloned`
312
- );
313
- } else {
314
- s.message(
315
- `[${i + 1}/${workers.length}] ${icons.error} ${name} failed: ${result.error}`
316
- );
317
- }
318
- }
319
-
320
- // Run submodule update after all clones
321
- try {
322
- s.message("Updating submodules...");
323
- await updateSubmodules(process.cwd());
324
- } catch (updateErr) {
325
- const msg =
326
- updateErr instanceof Error
327
- ? updateErr.message
328
- : String(updateErr);
329
- s.message(`Warning: submodule update failed: ${msg}`);
330
- }
331
-
332
- const succeeded = results.filter((r) => r.cloned).length;
333
- const failed = results.filter((r) => !r.cloned).length;
334
-
335
- if (failed > 0) {
336
- s.stop(
337
- `Clone complete: ${succeeded} succeeded, ${failed} failed`
338
- );
339
- process.exitCode = ExitCode.ERROR;
340
- } else {
341
- s.stop(`All ${succeeded} worker(s) cloned successfully`);
342
- }
343
-
344
- // Print summary table (unless quiet)
345
- if (!fmt.quiet) {
346
- const rows = results.map((r) => ({
347
- Worker: r.worker,
348
- Status: r.cloned ? "cloned" : "failed",
349
- Repo: r.repo ?? "-",
350
- }));
351
- formatTable(rows, { json: fmt.json, quiet: false });
352
- }
353
-
354
- return;
355
- }
356
-
357
- // -------------------------------------------------------------------
358
- // Mode 3: <name> — clone a single worker
359
- // -------------------------------------------------------------------
360
- if (name) {
361
- const workerConfig = configService.getWorker(name);
362
-
363
- if (!workerConfig) {
364
- formatError(
365
- new CLIError(
366
- `Worker "${name}" not found in wrangler.jsonc`,
367
- ExitCode.ERROR
368
- ),
369
- fmt
370
- );
371
- process.exitCode = ExitCode.ERROR;
372
- return;
373
- }
374
-
375
- // Already cloned → early exit with success
376
- const alreadyCloned = await isWorkerCloned(workerConfig.path);
377
- if (alreadyCloned) {
378
- formatSuccess(
379
- `Worker "${name}" is already cloned at ${workerConfig.path}`,
380
- fmt
381
- );
382
- return;
383
- }
384
-
385
- const repoBase = options.org
386
- ? `https://github.com/${options.org}`
387
- : await resolveRepoBase();
388
-
389
- const s = spinner();
390
- s.start(`Cloning ${name}...`);
391
-
392
- const result = await cloneWorker(
393
- getRepoUrl(repoBase, name),
394
- workerConfig.path,
395
- name,
396
- process.cwd()
397
- );
398
-
399
- if (result.cloned) {
400
- // Update submodules after single clone too
401
- try {
402
- s.message("Updating submodules...");
403
- await updateSubmodules(process.cwd());
404
- } catch {
405
- // Non-fatal — the clone itself succeeded
406
- }
407
-
408
- s.stop(`Successfully cloned ${name}`);
409
- formatSuccess(`Cloned ${name} from ${result.repo}`, fmt);
410
- } else {
411
- s.stop(`Failed to clone ${name}`);
412
- formatError(
413
- new CLIError(
414
- `Failed to clone "${name}": ${result.error}`,
415
- ExitCode.ERROR
416
- ),
417
- fmt
418
- );
419
- process.exitCode = ExitCode.ERROR;
420
- }
421
-
422
- return;
423
- }
424
- } catch (err) {
425
- const message = err instanceof Error ? err.message : String(err);
426
- formatError(message, fmt);
427
- process.exitCode = ExitCode.ERROR;
428
- }
429
- }
430
- );
431
- }
@@ -1 +0,0 @@
1
- export { registerCloneCommand } from "./clone-command.js";