@jango-blockchained/hoox-cli 0.5.1 → 0.5.2

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 (42) hide show
  1. package/package.json +1 -1
  2. package/src/commands/check/check-command.ts +8 -65
  3. package/src/commands/check/prerequisites-command.ts +7 -6
  4. package/src/commands/clone/clone-command.test.ts +8 -10
  5. package/src/commands/config/config-command.test.ts +4 -4
  6. package/src/commands/config/config-command.ts +10 -11
  7. package/src/commands/config/env-command.test.ts +2 -2
  8. package/src/commands/config/env-command.ts +40 -43
  9. package/src/commands/config/kv-command.ts +60 -60
  10. package/src/commands/dashboard/dashboard-command.ts +32 -30
  11. package/src/commands/db/db-command.ts +79 -80
  12. package/src/commands/deploy/deploy-command.test.ts +54 -34
  13. package/src/commands/deploy/deploy-command.ts +3 -84
  14. package/src/commands/dev/dev-command.test.ts +84 -62
  15. package/src/commands/disclaimer/disclaimer-command.ts +21 -0
  16. package/src/commands/disclaimer/index.ts +1 -0
  17. package/src/commands/init/init-command.test.ts +69 -91
  18. package/src/commands/init/init-command.ts +19 -15
  19. package/src/commands/logs/logs-command.test.ts +0 -1
  20. package/src/commands/monitor/monitor-command.test.ts +37 -29
  21. package/src/commands/repair/repair-command.test.ts +60 -41
  22. package/src/commands/repair/repair-service.ts +26 -0
  23. package/src/commands/schema/index.ts +1 -0
  24. package/src/commands/schema/schema-command.ts +137 -0
  25. package/src/commands/test/test-command.test.ts +2 -3
  26. package/src/commands/update/update-command.ts +6 -65
  27. package/src/commands/waf/waf-command.ts +56 -59
  28. package/src/index.ts +5 -13
  29. package/src/services/config/config-service.ts +1 -6
  30. package/src/services/db/db-service.test.ts +13 -1
  31. package/src/services/env/env-service.test.ts +41 -18
  32. package/src/services/env/env-service.ts +45 -59
  33. package/src/services/kv/kv-sync-service.ts +14 -5
  34. package/src/services/schema/index.ts +1 -0
  35. package/src/services/schema/schema-service.ts +99 -0
  36. package/src/services/secrets/secrets-service.test.ts +42 -35
  37. package/src/services/secrets/types.ts +1 -1
  38. package/src/ui/menu.ts +1 -1
  39. package/src/utils/error-handler.ts +62 -0
  40. package/src/utils/errors.ts +1 -0
  41. package/src/utils/git.ts +134 -0
  42. package/src/utils/theme.ts +0 -2
@@ -14,11 +14,8 @@ import type { Command } from "commander";
14
14
  import { CloudflareService } from "../../services/cloudflare/cloudflare-service.js";
15
15
  import type { WranglerResult } from "../../services/cloudflare/types.js";
16
16
  import { CLIError, ExitCode } from "../../utils/errors.js";
17
- import {
18
- formatSuccess,
19
- formatError,
20
- formatTable,
21
- } from "../../utils/formatters.js";
17
+ import { formatSuccess, formatTable } from "../../utils/formatters.js";
18
+ import { withErrorHandling } from "../../utils/error-handler.js";
22
19
  import { theme, icons } from "../../utils/theme.js";
23
20
  import type { FormatOptions } from "../../utils/formatters.js";
24
21
  import type { WafStatus, WafRule, WafRuleInput } from "./types.js";
@@ -461,15 +458,15 @@ export function registerWafCommand(program: Command): void {
461
458
  .description(
462
459
  "Show WAF status (enabled/disabled, active rules, recent blocks)"
463
460
  )
464
- .action(async (_, cmd: Command) => {
465
- const opts: FormatOptions = cmd.parent!.parent!.opts();
466
- try {
467
- await handleStatus(opts);
468
- } catch (err) {
469
- formatError(err instanceof Error ? err : String(err), opts);
470
- process.exit(err instanceof CLIError ? err.code : ExitCode.ERROR);
471
- }
472
- });
461
+ .action(
462
+ withErrorHandling(
463
+ async (_, cmd: Command) => {
464
+ const opts: FormatOptions = cmd.parent!.parent!.opts();
465
+ await handleStatus(opts);
466
+ },
467
+ { service: "waf" }
468
+ )
469
+ );
473
470
 
474
471
  // -- waf rules -------------------------------------------------------------
475
472
  const rules = waf.command("rules").description("Manage WAF firewall rules");
@@ -477,43 +474,43 @@ export function registerWafCommand(program: Command): void {
477
474
  rules
478
475
  .command("list")
479
476
  .description("List all WAF firewall rules")
480
- .action(async (_, cmd: Command) => {
481
- const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
482
- try {
483
- await handleRulesList(opts);
484
- } catch (err) {
485
- formatError(err instanceof Error ? err : String(err), opts);
486
- process.exit(err instanceof CLIError ? err.code : ExitCode.ERROR);
487
- }
488
- });
477
+ .action(
478
+ withErrorHandling(
479
+ async (_, cmd: Command) => {
480
+ const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
481
+ await handleRulesList(opts);
482
+ },
483
+ { service: "waf" }
484
+ )
485
+ );
489
486
 
490
487
  rules
491
488
  .command("add <type> <value>")
492
489
  .description(
493
490
  "Add a WAF rule. Types: ip-allowlist, ip-blocklist, rate-limit, custom"
494
491
  )
495
- .action(async (type: string, value: string, _, cmd: Command) => {
496
- const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
497
- try {
498
- await handleRulesAdd(type, value, opts);
499
- } catch (err) {
500
- formatError(err instanceof Error ? err : String(err), opts);
501
- process.exit(err instanceof CLIError ? err.code : ExitCode.ERROR);
502
- }
503
- });
492
+ .action(
493
+ withErrorHandling(
494
+ async (type: string, value: string, _, cmd: Command) => {
495
+ const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
496
+ await handleRulesAdd(type, value, opts);
497
+ },
498
+ { service: "waf" }
499
+ )
500
+ );
504
501
 
505
502
  rules
506
503
  .command("remove <ruleId>")
507
504
  .description("Remove a WAF rule by ID")
508
- .action(async (ruleId: string, _, cmd: Command) => {
509
- const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
510
- try {
511
- await handleRulesRemove(ruleId, opts);
512
- } catch (err) {
513
- formatError(err instanceof Error ? err : String(err), opts);
514
- process.exit(err instanceof CLIError ? err.code : ExitCode.ERROR);
515
- }
516
- });
505
+ .action(
506
+ withErrorHandling(
507
+ async (ruleId: string, _, cmd: Command) => {
508
+ const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
509
+ await handleRulesRemove(ruleId, opts);
510
+ },
511
+ { service: "waf" }
512
+ )
513
+ );
517
514
 
518
515
  // -- waf mode --------------------------------------------------------------
519
516
  const mode = waf
@@ -523,26 +520,26 @@ export function registerWafCommand(program: Command): void {
523
520
  mode
524
521
  .command("enable")
525
522
  .description("Enable WAF protection on the zone")
526
- .action(async (_, cmd: Command) => {
527
- const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
528
- try {
529
- await handleMode("on", opts);
530
- } catch (err) {
531
- formatError(err instanceof Error ? err : String(err), opts);
532
- process.exit(err instanceof CLIError ? err.code : ExitCode.ERROR);
533
- }
534
- });
523
+ .action(
524
+ withErrorHandling(
525
+ async (_, cmd: Command) => {
526
+ const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
527
+ await handleMode("on", opts);
528
+ },
529
+ { service: "waf" }
530
+ )
531
+ );
535
532
 
536
533
  mode
537
534
  .command("disable")
538
535
  .description("Disable WAF protection on the zone")
539
- .action(async (_, cmd: Command) => {
540
- const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
541
- try {
542
- await handleMode("off", opts);
543
- } catch (err) {
544
- formatError(err instanceof Error ? err : String(err), opts);
545
- process.exit(err instanceof CLIError ? err.code : ExitCode.ERROR);
546
- }
547
- });
536
+ .action(
537
+ withErrorHandling(
538
+ async (_, cmd: Command) => {
539
+ const opts: FormatOptions = cmd.parent!.parent!.parent!.opts();
540
+ await handleMode("off", opts);
541
+ },
542
+ { service: "waf" }
543
+ )
544
+ );
548
545
  }
package/src/index.ts CHANGED
@@ -7,10 +7,7 @@
7
7
 
8
8
  import { Command } from "commander";
9
9
  import { toError } from "@jango-blockchained/hoox-shared";
10
- import {
11
- FULL_LEGAL_NOTICE,
12
- COPYRIGHT,
13
- } from "@jango-blockchained/hoox-shared/legal";
10
+ import { COPYRIGHT } from "@jango-blockchained/hoox-shared/legal";
14
11
  import { CLIError, ExitCode } from "./utils/errors.js";
15
12
  import { formatError } from "./utils/formatters.js";
16
13
  import { theme } from "./utils/theme.js";
@@ -146,18 +143,11 @@ import { registerDbCommand } from "./commands/db/index.js";
146
143
  import { registerMonitorCommand } from "./commands/monitor/index.js";
147
144
  import { registerRepairCommand } from "./commands/repair/index.js";
148
145
  import { registerUpdateCommand } from "./commands/update/index.js";
146
+ import { registerSchemaCommand } from "./commands/schema/index.js";
149
147
  import { registerTUICommand } from "./commands/tui/index.js";
148
+ import { registerDisclaimerCommand } from "./commands/disclaimer/index.js";
150
149
  import { runInteractiveTUI } from "./ui/index.js";
151
150
 
152
- // ── Legal / Disclaimer command ──────────────────────────────────────────
153
-
154
- program
155
- .command("disclaimer")
156
- .description("Display legal disclaimers and trademark information")
157
- .action(() => {
158
- console.log(FULL_LEGAL_NOTICE);
159
- });
160
-
161
151
  // ── Command registration ────────────────────────────────────────────────
162
152
 
163
153
  registerInitCommand(program);
@@ -174,8 +164,10 @@ registerDashboardCommand(program);
174
164
  registerDbCommand(program);
175
165
  registerMonitorCommand(program);
176
166
  registerRepairCommand(program);
167
+ registerSchemaCommand(program);
177
168
  registerUpdateCommand(program);
178
169
  registerTUICommand(program);
170
+ registerDisclaimerCommand(program);
179
171
 
180
172
  // ---------------------------------------------------------------------------
181
173
  // preAction hooks — auto-check wrangler version before dev/deploy
@@ -1,11 +1,6 @@
1
1
  import { parse, printParseErrorCode } from "jsonc-parser";
2
2
  import type { ParseError } from "jsonc-parser";
3
- import type {
4
- HooxConfig,
5
- WorkerConfig,
6
- GlobalConfig,
7
- DevConfig,
8
- } from "./types";
3
+ import type { HooxConfig, WorkerConfig, GlobalConfig } from "./types";
9
4
 
10
5
  /**
11
6
  * Loads, parses, and validates the central wrangler.jsonc configuration.
@@ -1,5 +1,12 @@
1
- import { describe, expect, it } from "bun:test";
1
+ import { describe, expect, it, mock, afterEach } from "bun:test";
2
2
  import { DbService } from "./db-service.js";
3
+ import { ConfigService } from "../config/config-service.js";
4
+
5
+ const origLoad = ConfigService.prototype.load;
6
+
7
+ afterEach(() => {
8
+ ConfigService.prototype.load = origLoad;
9
+ });
3
10
 
4
11
  describe("DbService", () => {
5
12
  describe("resolveDbName", () => {
@@ -10,6 +17,11 @@ describe("DbService", () => {
10
17
  });
11
18
 
12
19
  it("falls back to default when no config exists", async () => {
20
+ // Mock ConfigService.load to throw (simulating no config)
21
+ ConfigService.prototype.load = mock(async () => {
22
+ throw new Error("Config file not found");
23
+ }) as typeof ConfigService.prototype.load;
24
+
13
25
  const svc = new DbService();
14
26
  const name = await svc.resolveDbName();
15
27
  expect(name).toBe("my-database");
@@ -5,7 +5,7 @@ describe("EnvService", () => {
5
5
  describe("getDefinitions", () => {
6
6
  it("returns all known env var definitions", () => {
7
7
  const defs = EnvService.getDefinitions();
8
- expect(defs.length).toBe(31);
8
+ expect(defs.length).toBe(28);
9
9
  expect(defs.some((d) => d.name === "CLOUDFLARE_API_TOKEN")).toBe(true);
10
10
  });
11
11
 
@@ -50,17 +50,26 @@ describe("EnvService", () => {
50
50
  describe("getWorkerDevVars", () => {
51
51
  it("maps vars to correct workers", () => {
52
52
  const vars = {
53
- AGENT_OPENAI_KEY: "sk-123",
54
- TELEGRAM_BOT_TOKEN: "tg-456",
55
- D1_INTERNAL_KEY: "d1-789",
53
+ AGENT_INTERNAL_KEY: "sk-123",
54
+ TG_BOT_TOKEN_BINDING: "tg-456",
55
+ INTERNAL_KEY_BINDING: "d1-789",
56
+ DASHBOARD_USER: "admin",
57
+ DASHBOARD_PASS: "pass",
58
+ TELEGRAM_INTERNAL_KEY: "tg-int-key",
56
59
  };
57
60
  const result = EnvService.getWorkerDevVars(vars);
58
61
  expect(result["workers/agent-worker"]).toBeDefined();
59
- expect(result["workers/agent-worker"].AGENT_OPENAI_KEY).toBe("sk-123");
62
+ expect(result["workers/agent-worker"].AGENT_INTERNAL_KEY).toBe("sk-123");
60
63
  expect(result["workers/telegram-worker"]).toBeDefined();
61
- expect(result["workers/telegram-worker"].TELEGRAM_BOT_TOKEN).toBe(
64
+ expect(result["workers/telegram-worker"].TG_BOT_TOKEN_BINDING).toBe(
62
65
  "tg-456"
63
66
  );
67
+ expect(result["workers/dashboard"]).toBeDefined();
68
+ expect(result["workers/dashboard"].DASHBOARD_USER).toBe("admin");
69
+ expect(result["workers/dashboard"].DASHBOARD_PASS).toBe("pass");
70
+ expect(result["workers/dashboard"].TELEGRAM_INTERNAL_KEY).toBe(
71
+ "tg-int-key"
72
+ );
64
73
  });
65
74
 
66
75
  it("omits workers with no matching vars", () => {
@@ -69,7 +78,7 @@ describe("EnvService", () => {
69
78
  });
70
79
 
71
80
  it("omits empty-string vars", () => {
72
- const result = EnvService.getWorkerDevVars({ D1_INTERNAL_KEY: "" });
81
+ const result = EnvService.getWorkerDevVars({ INTERNAL_KEY_BINDING: "" });
73
82
  expect(Object.keys(result).length).toBe(0);
74
83
  });
75
84
 
@@ -77,14 +86,18 @@ describe("EnvService", () => {
77
86
  const vars = {
78
87
  WEBHOOK_API_KEY_BINDING: "webhook-key",
79
88
  HA_TOKEN_BINDING: "ha-token",
80
- API_SERVICE_KEY: "api-key",
89
+ API_SERVICE_KEY_BINDING: "api-key",
81
90
  TELEGRAM_SECRET_TOKEN: "tg-secret",
82
91
  WALLET_MNEMONIC_SECRET: "mnemonic",
83
92
  WALLET_PK_SECRET: "pk",
84
- EMAIL_HOST: "imap.example.com",
85
- EMAIL_USER: "user",
86
- EMAIL_PASS: "pass",
87
- INTERNAL_KEY: "int-key",
93
+ EMAIL_HOST_BINDING: "imap.example.com",
94
+ EMAIL_USER_BINDING: "user",
95
+ EMAIL_PASS_BINDING: "pass",
96
+ INTERNAL_KEY_BINDING: "int-key",
97
+ DASHBOARD_USER: "admin",
98
+ DASHBOARD_PASS: "pass",
99
+ SESSION_SECRET: "secret-32-char-min-for-session",
100
+ TELEGRAM_INTERNAL_KEY: "tg-int-key",
88
101
  };
89
102
  const result = EnvService.getWorkerDevVars(vars);
90
103
  expect(result["workers/hoox"]).toBeDefined();
@@ -92,7 +105,9 @@ describe("EnvService", () => {
92
105
  "webhook-key"
93
106
  );
94
107
  expect(result["workers/hoox"].HA_TOKEN_BINDING).toBe("ha-token");
95
- expect(result["workers/trade-worker"].API_SERVICE_KEY).toBe("api-key");
108
+ expect(result["workers/trade-worker"].API_SERVICE_KEY_BINDING).toBe(
109
+ "api-key"
110
+ );
96
111
  expect(result["workers/telegram-worker"].TELEGRAM_SECRET_TOKEN).toBe(
97
112
  "tg-secret"
98
113
  );
@@ -101,9 +116,18 @@ describe("EnvService", () => {
101
116
  "mnemonic"
102
117
  );
103
118
  expect(result["workers/email-worker"]).toBeDefined();
104
- expect(result["workers/email-worker"].EMAIL_HOST).toBe(
119
+ expect(result["workers/email-worker"].EMAIL_HOST_BINDING).toBe(
105
120
  "imap.example.com"
106
121
  );
122
+ expect(result["workers/dashboard"]).toBeDefined();
123
+ expect(result["workers/dashboard"].DASHBOARD_USER).toBe("admin");
124
+ expect(result["workers/dashboard"].DASHBOARD_PASS).toBe("pass");
125
+ expect(result["workers/dashboard"].SESSION_SECRET).toBe(
126
+ "secret-32-char-min-for-session"
127
+ );
128
+ expect(result["workers/dashboard"].TELEGRAM_INTERNAL_KEY).toBe(
129
+ "tg-int-key"
130
+ );
107
131
  });
108
132
  });
109
133
 
@@ -133,12 +157,12 @@ describe("EnvService", () => {
133
157
  CLOUDFLARE_API_TOKEN: "cfut_xxx",
134
158
  CLOUDFLARE_ACCOUNT_ID: "abc123",
135
159
  SUBDOMAIN_PREFIX: "myapp",
136
- D1_INTERNAL_KEY: "d1-key",
137
160
  TRADE_INTERNAL_KEY: "trade-key",
138
161
  AGENT_INTERNAL_KEY: "agent-key",
139
162
  WEBHOOK_API_KEY_BINDING: "webhook-key",
140
163
  INTERNAL_KEY_BINDING: "int-key",
141
- API_SERVICE_KEY: "api-key",
164
+ API_SERVICE_KEY_BINDING: "api-key",
165
+ TELEGRAM_INTERNAL_KEY: "tg-key",
142
166
  DASHBOARD_USER: "admin",
143
167
  DASHBOARD_PASS: "pass123",
144
168
  SESSION_SECRET: "a".repeat(32),
@@ -152,12 +176,11 @@ describe("EnvService", () => {
152
176
  CLOUDFLARE_API_TOKEN: "tok",
153
177
  CLOUDFLARE_ACCOUNT_ID: "id",
154
178
  SUBDOMAIN_PREFIX: "p",
155
- D1_INTERNAL_KEY: "k",
156
179
  TRADE_INTERNAL_KEY: "k",
157
180
  AGENT_INTERNAL_KEY: "k",
158
181
  WEBHOOK_API_KEY_BINDING: "wk",
159
182
  INTERNAL_KEY_BINDING: "ik",
160
- API_SERVICE_KEY: "ak",
183
+ API_SERVICE_KEY_BINDING: "ak",
161
184
  DASHBOARD_USER: "u",
162
185
  DASHBOARD_PASS: "p",
163
186
  SESSION_SECRET: "short",
@@ -52,7 +52,7 @@ export class EnvService {
52
52
  hint: "Prefix for worker URLs",
53
53
  },
54
54
  {
55
- name: "D1_INTERNAL_KEY",
55
+ name: "INTERNAL_KEY_BINDING",
56
56
  required: true,
57
57
  secret: true,
58
58
  section: "Internal Auth",
@@ -87,12 +87,19 @@ export class EnvService {
87
87
  hint: "Shared internal auth key for inter-worker communication",
88
88
  },
89
89
  {
90
- name: "API_SERVICE_KEY",
90
+ name: "API_SERVICE_KEY_BINDING",
91
91
  required: true,
92
92
  secret: true,
93
93
  section: "Internal Auth",
94
94
  hint: "API service key for trade-worker",
95
95
  },
96
+ {
97
+ name: "TELEGRAM_INTERNAL_KEY",
98
+ required: true,
99
+ secret: true,
100
+ section: "Internal Auth",
101
+ hint: "Internal key for telegram worker auth",
102
+ },
96
103
  {
97
104
  name: "HA_TOKEN_BINDING",
98
105
  required: false,
@@ -101,7 +108,7 @@ export class EnvService {
101
108
  hint: "Home Assistant token for hoox",
102
109
  },
103
110
  {
104
- name: "TELEGRAM_BOT_TOKEN",
111
+ name: "TG_BOT_TOKEN_BINDING",
105
112
  required: false,
106
113
  secret: true,
107
114
  section: "Telegram",
@@ -114,64 +121,44 @@ export class EnvService {
114
121
  section: "Telegram",
115
122
  hint: "Telegram webhook secret token",
116
123
  },
124
+ // AI provider keys consolidated into AGENT_INTERNAL_KEY (above)
117
125
  {
118
- name: "AGENT_OPENAI_KEY",
119
- required: false,
120
- secret: true,
121
- section: "AI Providers",
122
- hint: "OpenAI API key",
123
- },
124
- {
125
- name: "AGENT_ANTHROPIC_KEY",
126
- required: false,
127
- secret: true,
128
- section: "AI Providers",
129
- hint: "Anthropic API key",
130
- },
131
- {
132
- name: "AGENT_GOOGLE_KEY",
133
- required: false,
134
- secret: true,
135
- section: "AI Providers",
136
- hint: "Google AI API key",
137
- },
138
- {
139
- name: "BINANCE_API_KEY",
126
+ name: "BINANCE_KEY_BINDING",
140
127
  required: false,
141
128
  secret: true,
142
129
  section: "Exchanges",
143
130
  hint: "Binance API key",
144
131
  },
145
132
  {
146
- name: "BINANCE_API_SECRET",
133
+ name: "BINANCE_SECRET_BINDING",
147
134
  required: false,
148
135
  secret: true,
149
136
  section: "Exchanges",
150
137
  hint: "Binance API secret",
151
138
  },
152
139
  {
153
- name: "MEXC_API_KEY",
140
+ name: "MEXC_KEY_BINDING",
154
141
  required: false,
155
142
  secret: true,
156
143
  section: "Exchanges",
157
144
  hint: "MEXC API key",
158
145
  },
159
146
  {
160
- name: "MEXC_API_SECRET",
147
+ name: "MEXC_SECRET_BINDING",
161
148
  required: false,
162
149
  secret: true,
163
150
  section: "Exchanges",
164
151
  hint: "MEXC API secret",
165
152
  },
166
153
  {
167
- name: "BYBIT_API_KEY",
154
+ name: "BYBIT_KEY_BINDING",
168
155
  required: false,
169
156
  secret: true,
170
157
  section: "Exchanges",
171
158
  hint: "Bybit API key",
172
159
  },
173
160
  {
174
- name: "BYBIT_API_SECRET",
161
+ name: "BYBIT_SECRET_BINDING",
175
162
  required: false,
176
163
  secret: true,
177
164
  section: "Exchanges",
@@ -179,33 +166,27 @@ export class EnvService {
179
166
  },
180
167
  // Email
181
168
  {
182
- name: "EMAIL_HOST",
169
+ name: "EMAIL_HOST_BINDING",
183
170
  required: false,
184
171
  secret: true,
185
172
  section: "Email",
186
173
  hint: "Email IMAP server host",
187
174
  },
188
175
  {
189
- name: "EMAIL_USER",
176
+ name: "EMAIL_USER_BINDING",
190
177
  required: false,
191
178
  secret: true,
192
179
  section: "Email",
193
180
  hint: "Email IMAP username",
194
181
  },
195
182
  {
196
- name: "EMAIL_PASS",
183
+ name: "EMAIL_PASS_BINDING",
197
184
  required: false,
198
185
  secret: true,
199
186
  section: "Email",
200
187
  hint: "Email IMAP password",
201
188
  },
202
- {
203
- name: "INTERNAL_KEY",
204
- required: false,
205
- secret: true,
206
- section: "Email",
207
- hint: "Internal auth key for email-worker",
208
- },
189
+ // INTERNAL_KEY_BINDING consolidated into INTERNAL_KEY_BINDING (above)
209
190
  // Wallet
210
191
  {
211
192
  name: "WALLET_MNEMONIC_SECRET",
@@ -322,24 +303,19 @@ export class EnvService {
322
303
  "HA_TOKEN_BINDING",
323
304
  ],
324
305
  "workers/trade-worker": [
325
- "API_SERVICE_KEY",
306
+ "API_SERVICE_KEY_BINDING",
326
307
  "INTERNAL_KEY_BINDING",
327
- "BINANCE_API_KEY",
328
- "BINANCE_API_SECRET",
329
- "MEXC_API_KEY",
330
- "MEXC_API_SECRET",
331
- "BYBIT_API_KEY",
332
- "BYBIT_API_SECRET",
333
- ],
334
- "workers/agent-worker": [
335
- "AGENT_INTERNAL_KEY",
336
- "AGENT_OPENAI_KEY",
337
- "AGENT_ANTHROPIC_KEY",
338
- "AGENT_GOOGLE_KEY",
308
+ "BINANCE_KEY_BINDING",
309
+ "BINANCE_SECRET_BINDING",
310
+ "MEXC_KEY_BINDING",
311
+ "MEXC_SECRET_BINDING",
312
+ "BYBIT_KEY_BINDING",
313
+ "BYBIT_SECRET_BINDING",
339
314
  ],
340
- "workers/d1-worker": ["D1_INTERNAL_KEY"],
315
+ "workers/agent-worker": ["AGENT_INTERNAL_KEY"],
316
+ "workers/d1-worker": ["INTERNAL_KEY_BINDING"],
341
317
  "workers/telegram-worker": [
342
- "TELEGRAM_BOT_TOKEN",
318
+ "TG_BOT_TOKEN_BINDING",
343
319
  "TELEGRAM_SECRET_TOKEN",
344
320
  ],
345
321
  "workers/web3-wallet-worker": [
@@ -347,12 +323,22 @@ export class EnvService {
347
323
  "WALLET_PK_SECRET",
348
324
  ],
349
325
  "workers/email-worker": [
350
- "EMAIL_HOST",
351
- "EMAIL_USER",
352
- "EMAIL_PASS",
353
- "INTERNAL_KEY",
326
+ "EMAIL_HOST_BINDING",
327
+ "EMAIL_USER_BINDING",
328
+ "EMAIL_PASS_BINDING",
329
+ "INTERNAL_KEY_BINDING",
354
330
  ],
355
331
  "workers/analytics-worker": ["CLOUDFLARE_API_TOKEN"],
332
+ "workers/dashboard": [
333
+ "DASHBOARD_USER",
334
+ "DASHBOARD_PASS",
335
+ "SESSION_SECRET",
336
+ "INTERNAL_KEY_BINDING",
337
+ "AGENT_INTERNAL_KEY",
338
+ "TRADE_INTERNAL_KEY",
339
+ "TELEGRAM_INTERNAL_KEY",
340
+ "API_SERVICE_KEY_BINDING",
341
+ ],
356
342
  };
357
343
  const result: Record<string, Record<string, string>> = {};
358
344
  for (const [workerPath, varNames] of Object.entries(workerMap)) {
@@ -16,7 +16,7 @@ export class KvSyncService {
16
16
  if (namespaceId) return namespaceId;
17
17
 
18
18
  try {
19
- const proc = Bun.spawn(["wrangler", "kv:namespace", "list"], {
19
+ const proc = Bun.spawn(["wrangler", "kv", "namespace", "list"], {
20
20
  stdout: "pipe",
21
21
  stderr: "pipe",
22
22
  });
@@ -46,7 +46,7 @@ export class KvSyncService {
46
46
 
47
47
  async list(namespaceId: string): Promise<Array<{ name: string }>> {
48
48
  const proc = Bun.spawn(
49
- ["wrangler", "kv:key", "list", "--namespace-id", namespaceId],
49
+ ["wrangler", "kv", "key", "list", "--namespace-id", namespaceId],
50
50
  { stdout: "pipe", stderr: "pipe" }
51
51
  );
52
52
  const stdout = await new Response(proc.stdout).text();
@@ -71,7 +71,7 @@ export class KvSyncService {
71
71
 
72
72
  async get(namespaceId: string, key: string): Promise<string | null> {
73
73
  const proc = Bun.spawn(
74
- ["wrangler", "kv:key", "get", "--namespace-id", namespaceId, key],
74
+ ["wrangler", "kv", "key", "get", "--namespace-id", namespaceId, key],
75
75
  { stdout: "pipe", stderr: "pipe" }
76
76
  );
77
77
  const stdout = await new Response(proc.stdout).text();
@@ -90,7 +90,16 @@ export class KvSyncService {
90
90
 
91
91
  async set(namespaceId: string, key: string, value: string): Promise<void> {
92
92
  const proc = Bun.spawn(
93
- ["wrangler", "kv:key", "put", "--namespace-id", namespaceId, key, value],
93
+ [
94
+ "wrangler",
95
+ "kv",
96
+ "key",
97
+ "put",
98
+ "--namespace-id",
99
+ namespaceId,
100
+ key,
101
+ value,
102
+ ],
94
103
  { stdout: "pipe", stderr: "pipe" }
95
104
  );
96
105
  const exitCode = await proc.exited;
@@ -105,7 +114,7 @@ export class KvSyncService {
105
114
 
106
115
  async delete(namespaceId: string, key: string): Promise<void> {
107
116
  const proc = Bun.spawn(
108
- ["wrangler", "kv:key", "delete", "--namespace-id", namespaceId, key],
117
+ ["wrangler", "kv", "key", "delete", "--namespace-id", namespaceId, key],
109
118
  { stdout: "pipe", stderr: "pipe" }
110
119
  );
111
120
  const exitCode = await proc.exited;
@@ -0,0 +1 @@
1
+ export { SchemaService } from "./schema-service.js";