@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.
Files changed (106) 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 -1144
  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 -96
  9. package/src/commands/check/types.ts +0 -103
  10. package/src/commands/clone/clone-command.test.ts +0 -442
  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 -897
  15. package/src/commands/config/env-command.test.ts +0 -43
  16. package/src/commands/config/env-command.ts +0 -295
  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 -128
  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 -312
  25. package/src/commands/db/index.ts +0 -1
  26. package/src/commands/deploy/deploy-command.test.ts +0 -304
  27. package/src/commands/deploy/deploy-command.ts +0 -1135
  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 -383
  32. package/src/commands/dev/dev-command.ts +0 -398
  33. package/src/commands/dev/index.ts +0 -1
  34. package/src/commands/infra/index.ts +0 -5
  35. package/src/commands/infra/infra-command.test.ts +0 -719
  36. package/src/commands/infra/infra-command.ts +0 -974
  37. package/src/commands/infra/types.ts +0 -23
  38. package/src/commands/init/__tests__/cli-provisioner.test.ts +0 -17
  39. package/src/commands/init/cli-provisioner.ts +0 -71
  40. package/src/commands/init/index.ts +0 -1
  41. package/src/commands/init/init-command.test.ts +0 -876
  42. package/src/commands/init/init-command.ts +0 -593
  43. package/src/commands/init/types.ts +0 -23
  44. package/src/commands/logs/index.ts +0 -1
  45. package/src/commands/logs/logs-command.test.ts +0 -294
  46. package/src/commands/logs/logs-command.ts +0 -452
  47. package/src/commands/monitor/index.ts +0 -2
  48. package/src/commands/monitor/monitor-command.test.ts +0 -263
  49. package/src/commands/monitor/monitor-command.ts +0 -269
  50. package/src/commands/monitor/monitor-service.ts +0 -65
  51. package/src/commands/monitor/types.ts +0 -13
  52. package/src/commands/repair/index.ts +0 -2
  53. package/src/commands/repair/repair-command.test.ts +0 -224
  54. package/src/commands/repair/repair-command.ts +0 -220
  55. package/src/commands/repair/repair-service.ts +0 -138
  56. package/src/commands/repair/types.ts +0 -13
  57. package/src/commands/test/index.ts +0 -2
  58. package/src/commands/test/test-command.test.ts +0 -319
  59. package/src/commands/test/test-command.ts +0 -406
  60. package/src/commands/tui/index.ts +0 -1
  61. package/src/commands/tui/tui-command.ts +0 -87
  62. package/src/commands/update/index.ts +0 -1
  63. package/src/commands/update/update-command.ts +0 -168
  64. package/src/commands/waf/index.ts +0 -2
  65. package/src/commands/waf/types.ts +0 -48
  66. package/src/commands/waf/waf-command.test.ts +0 -506
  67. package/src/commands/waf/waf-command.ts +0 -548
  68. package/src/index.ts +0 -269
  69. package/src/services/cloudflare/cloudflare-service.test.ts +0 -658
  70. package/src/services/cloudflare/cloudflare-service.ts +0 -433
  71. package/src/services/cloudflare/index.ts +0 -2
  72. package/src/services/cloudflare/types.ts +0 -30
  73. package/src/services/config/config-service.test.ts +0 -395
  74. package/src/services/config/config-service.ts +0 -207
  75. package/src/services/config/index.ts +0 -9
  76. package/src/services/config/types.ts +0 -66
  77. package/src/services/db/db-service.test.ts +0 -51
  78. package/src/services/db/db-service.ts +0 -131
  79. package/src/services/db/index.ts +0 -1
  80. package/src/services/docker/docker-service.ts +0 -155
  81. package/src/services/docker/index.ts +0 -1
  82. package/src/services/env/env-service.test.ts +0 -236
  83. package/src/services/env/env-service.ts +0 -386
  84. package/src/services/env/index.ts +0 -1
  85. package/src/services/kv/index.ts +0 -1
  86. package/src/services/kv/kv-sync-service.test.ts +0 -38
  87. package/src/services/kv/kv-sync-service.ts +0 -234
  88. package/src/services/prerequisites/index.ts +0 -1
  89. package/src/services/prerequisites/prerequisites-service.test.ts +0 -89
  90. package/src/services/prerequisites/prerequisites-service.ts +0 -377
  91. package/src/services/prerequisites/types.ts +0 -48
  92. package/src/services/secrets/index.ts +0 -11
  93. package/src/services/secrets/secrets-service.test.ts +0 -495
  94. package/src/services/secrets/secrets-service.ts +0 -287
  95. package/src/services/secrets/types.ts +0 -50
  96. package/src/services/update/index.ts +0 -2
  97. package/src/services/update/update-service.test.ts +0 -76
  98. package/src/services/update/update-service.ts +0 -193
  99. package/src/ui/banner.ts +0 -141
  100. package/src/ui/index.ts +0 -8
  101. package/src/ui/menu.ts +0 -490
  102. package/src/utils/errors.test.ts +0 -69
  103. package/src/utils/errors.ts +0 -23
  104. package/src/utils/formatters.test.ts +0 -180
  105. package/src/utils/formatters.ts +0 -269
  106. package/src/utils/theme.ts +0 -94
@@ -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";