@jango-blockchained/hoox-shared 1.0.9 → 1.1.0

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 (74) hide show
  1. package/README.md +17 -0
  2. package/dist/analytics.d.ts +23 -1
  3. package/dist/analytics.d.ts.map +1 -1
  4. package/dist/analytics.js +14 -3
  5. package/dist/api-client.d.ts +12 -2
  6. package/dist/api-client.d.ts.map +1 -1
  7. package/dist/api-client.js +74 -7
  8. package/dist/colors.d.ts +63 -24
  9. package/dist/colors.d.ts.map +1 -1
  10. package/dist/colors.js +60 -19
  11. package/dist/config.d.ts +34 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +61 -6
  14. package/dist/cron-handler.d.ts +2 -2
  15. package/dist/cron-handler.d.ts.map +1 -1
  16. package/dist/d1/index.js +1 -0
  17. package/dist/d1/repository.js +297 -0
  18. package/dist/d1/schemas.js +81 -0
  19. package/dist/exchanges/base-exchange-client.js +120 -0
  20. package/dist/exchanges/types.js +1 -0
  21. package/dist/index.d.ts +21 -11
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +580 -60
  24. package/dist/middleware/auth.d.ts +42 -6
  25. package/dist/middleware/auth.d.ts.map +1 -1
  26. package/dist/middleware/auth.js +151 -0
  27. package/dist/middleware/cors.d.ts +28 -2
  28. package/dist/middleware/cors.d.ts.map +1 -1
  29. package/dist/middleware/cors.js +77 -0
  30. package/dist/middleware/index.d.ts +2 -2
  31. package/dist/middleware/index.d.ts.map +1 -1
  32. package/dist/middleware/index.js +192 -107
  33. package/dist/middleware/logger.js +202 -0
  34. package/dist/middleware/rate-limit.d.ts.map +1 -1
  35. package/dist/middleware/rate-limit.js +181 -0
  36. package/dist/middleware/security-headers.js +58 -0
  37. package/dist/middleware/validate.js +56 -0
  38. package/dist/operator-transport.d.ts +61 -0
  39. package/dist/operator-transport.d.ts.map +1 -0
  40. package/dist/operator-transport.js +87 -0
  41. package/dist/path-utils.d.ts +59 -1
  42. package/dist/path-utils.d.ts.map +1 -1
  43. package/dist/path-utils.js +89 -2
  44. package/dist/queue-handler.d.ts +3 -3
  45. package/dist/queue-handler.d.ts.map +1 -1
  46. package/dist/router.d.ts +2 -2
  47. package/dist/router.d.ts.map +1 -1
  48. package/dist/schemas/index.js +7 -4
  49. package/dist/schemas/registry.js +387 -0
  50. package/dist/schemas/types.js +1 -0
  51. package/dist/schemas/validators.d.ts.map +1 -1
  52. package/dist/schemas/validators.js +290 -0
  53. package/dist/service-bindings.d.ts +65 -0
  54. package/dist/service-bindings.d.ts.map +1 -1
  55. package/dist/service-bindings.js +216 -1
  56. package/dist/session.d.ts.map +1 -1
  57. package/dist/session.js +97 -2
  58. package/dist/sse.d.ts +12 -3
  59. package/dist/sse.d.ts.map +1 -1
  60. package/dist/sse.js +70 -7
  61. package/dist/stores/config-store.d.ts.map +1 -1
  62. package/dist/stores/config-store.js +129 -6
  63. package/dist/stores/service-store.d.ts.map +1 -1
  64. package/dist/stores/service-store.js +96 -25
  65. package/dist/types.d.ts +66 -1
  66. package/dist/types.d.ts.map +1 -1
  67. package/dist/types.js +11 -0
  68. package/dist/wizard/engine.js +501 -0
  69. package/dist/wizard/index.js +2 -1
  70. package/dist/wizard/persistence.js +31 -0
  71. package/dist/wizard/presets.js +199 -0
  72. package/dist/wizard/provisioner.js +1 -0
  73. package/dist/wizard/types.js +1 -0
  74. package/package.json +38 -12
@@ -0,0 +1,501 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
+
18
+ // src/wizard/presets.ts
19
+ var PRESETS = [
20
+ {
21
+ name: "minimal",
22
+ label: "Minimal",
23
+ description: "Gateway + D1 database \u2014 webhook processing only",
24
+ workers: ["hoox", "d1-worker", "analytics-worker"],
25
+ integrations: []
26
+ },
27
+ {
28
+ name: "standard",
29
+ label: "Standard",
30
+ description: "Trading + analytics + Telegram notifications",
31
+ workers: [
32
+ "hoox",
33
+ "d1-worker",
34
+ "trade-worker",
35
+ "analytics-worker",
36
+ "telegram-worker"
37
+ ],
38
+ integrations: ["binance", "telegram"]
39
+ },
40
+ {
41
+ name: "full",
42
+ label: "Full",
43
+ description: "All workers + AI agent + DeFi + email",
44
+ workers: [
45
+ "hoox",
46
+ "d1-worker",
47
+ "trade-worker",
48
+ "agent-worker",
49
+ "telegram-worker",
50
+ "analytics-worker",
51
+ "email-worker",
52
+ "web3-wallet-worker"
53
+ ],
54
+ integrations: ["binance", "bybit", "mexc", "telegram", "openai", "wallet"]
55
+ }
56
+ ];
57
+ var WORKER_DEPENDENCIES = {
58
+ "trade-worker": ["d1-worker"],
59
+ "agent-worker": ["d1-worker"],
60
+ "email-worker": ["d1-worker"],
61
+ "analytics-worker": ["d1-worker"],
62
+ "web3-wallet-worker": ["d1-worker", "hoox"]
63
+ };
64
+ function resolveDependencies(selected) {
65
+ const result = new Set(selected);
66
+ let changed = true;
67
+ while (changed) {
68
+ changed = false;
69
+ for (const worker of [...result]) {
70
+ const deps = WORKER_DEPENDENCIES[worker];
71
+ if (deps) {
72
+ for (const dep of deps) {
73
+ if (!result.has(dep)) {
74
+ result.add(dep);
75
+ changed = true;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ return [...result];
82
+ }
83
+ var INTEGRATIONS = [
84
+ {
85
+ key: "binance",
86
+ label: "Binance Exchange",
87
+ workerName: "trade-worker",
88
+ secrets: {
89
+ BINANCE_KEY_BINDING: "Binance API Key",
90
+ BINANCE_SECRET_BINDING: "Binance API Secret"
91
+ }
92
+ },
93
+ {
94
+ key: "mexc",
95
+ label: "MEXC Exchange",
96
+ workerName: "trade-worker",
97
+ secrets: {
98
+ MEXC_KEY_BINDING: "MEXC API Key",
99
+ MEXC_SECRET_BINDING: "MEXC API Secret"
100
+ }
101
+ },
102
+ {
103
+ key: "bybit",
104
+ label: "Bybit Exchange",
105
+ workerName: "trade-worker",
106
+ secrets: {
107
+ BYBIT_KEY_BINDING: "Bybit API Key",
108
+ BYBIT_SECRET_BINDING: "Bybit API Secret"
109
+ }
110
+ },
111
+ {
112
+ key: "wallet",
113
+ label: "Web3 Wallet (on-chain execution)",
114
+ workerName: "web3-wallet-worker",
115
+ secrets: {
116
+ WALLET_MNEMONIC_SECRET: "Wallet Mnemonic Phrase",
117
+ WALLET_PK_SECRET: "Wallet Private Key"
118
+ }
119
+ },
120
+ {
121
+ key: "email",
122
+ label: "Email Signal Parsing",
123
+ workerName: "email-worker",
124
+ secrets: {
125
+ INTERNAL_KEY_BINDING: "Internal Auth Key",
126
+ EMAIL_HOST_BINDING: "Email Host (IMAP server)",
127
+ EMAIL_USER_BINDING: "Email Username",
128
+ EMAIL_PASS_BINDING: "Email Password"
129
+ },
130
+ vars: { USE_IMAP: "false" }
131
+ },
132
+ {
133
+ key: "telegram",
134
+ label: "Telegram Notifications",
135
+ workerName: "telegram-worker",
136
+ secrets: {
137
+ TG_BOT_TOKEN_BINDING: "Telegram Bot Token"
138
+ }
139
+ },
140
+ {
141
+ key: "openai",
142
+ label: "OpenAI (AI Agent)",
143
+ workerName: "agent-worker",
144
+ secrets: {
145
+ AGENT_INTERNAL_KEY: "OpenAI API Key"
146
+ }
147
+ },
148
+ {
149
+ key: "anthropic",
150
+ label: "Anthropic (AI Agent)",
151
+ workerName: "agent-worker",
152
+ secrets: {
153
+ AGENT_INTERNAL_KEY: "Anthropic API Key"
154
+ }
155
+ },
156
+ {
157
+ key: "google-ai",
158
+ label: "Google AI (AI Agent)",
159
+ workerName: "agent-worker",
160
+ secrets: {
161
+ AGENT_INTERNAL_KEY: "Google AI API Key"
162
+ }
163
+ },
164
+ {
165
+ key: "home-assistant",
166
+ label: "Home Assistant (Smart Home)",
167
+ workerName: "hoox",
168
+ secrets: {
169
+ HA_TOKEN_BINDING: "Home Assistant Token"
170
+ }
171
+ }
172
+ ];
173
+ var BASE_WORKERS = {
174
+ "d1-worker": {
175
+ enabled: true,
176
+ path: "workers/d1-worker",
177
+ vars: { database_name: "hoox-db" }
178
+ },
179
+ hoox: { enabled: true, path: "workers/hoox-worker", vars: {} },
180
+ "agent-worker": { enabled: true, path: "workers/agent-worker", vars: {} },
181
+ "analytics-worker": {
182
+ enabled: true,
183
+ path: "workers/analytics-worker",
184
+ vars: {}
185
+ }
186
+ };
187
+ var BASE_SECRETS = {
188
+ hoox: ["WEBHOOK_API_KEY_BINDING"],
189
+ "agent-worker": ["AGENT_INTERNAL_KEY", "INTERNAL_KEY_BINDING"],
190
+ "analytics-worker": ["CLOUDFLARE_API_TOKEN"]
191
+ };
192
+
193
+ // src/wizard/engine.ts
194
+ var STEPS = [
195
+ {
196
+ id: "PREREQUISITES",
197
+ label: "System Prerequisites",
198
+ canGoBack: false,
199
+ optional: false,
200
+ validate: validatePrerequisites
201
+ },
202
+ {
203
+ id: "CLOUDFLARE_CONFIG",
204
+ label: "Cloudflare Configuration",
205
+ canGoBack: true,
206
+ optional: false,
207
+ validate: validateCloudflareConfig
208
+ },
209
+ {
210
+ id: "WORKER_SELECTION",
211
+ label: "Worker Selection",
212
+ canGoBack: true,
213
+ optional: false,
214
+ validate: validateWorkerSelection
215
+ },
216
+ {
217
+ id: "PROVISIONING",
218
+ label: "Infrastructure Provisioning",
219
+ canGoBack: true,
220
+ optional: true,
221
+ validate: () => []
222
+ },
223
+ {
224
+ id: "SECRETS",
225
+ label: "Secrets Configuration",
226
+ canGoBack: true,
227
+ optional: false,
228
+ validate: validateSecrets
229
+ },
230
+ {
231
+ id: "CONFIG_WRITE",
232
+ label: "Configuration Write",
233
+ canGoBack: true,
234
+ optional: false,
235
+ validate: () => []
236
+ },
237
+ {
238
+ id: "DEPLOY",
239
+ label: "Deploy",
240
+ canGoBack: false,
241
+ optional: true,
242
+ validate: () => []
243
+ },
244
+ {
245
+ id: "DONE",
246
+ label: "Complete",
247
+ canGoBack: false,
248
+ optional: false,
249
+ validate: () => []
250
+ }
251
+ ];
252
+ var STEP_ORDER = STEPS.map((s) => s.id);
253
+ function createInitialState() {
254
+ return {
255
+ step: "PREREQUISITES",
256
+ completedSteps: [],
257
+ selectedWorkers: [],
258
+ selectedIntegrations: [],
259
+ secrets: {},
260
+ startedAt: Date.now(),
261
+ updatedAt: Date.now()
262
+ };
263
+ }
264
+ function validatePrerequisites(_state, input) {
265
+ const errors = [];
266
+ if (!input.checksPassed) {
267
+ errors.push("System prerequisite checks must pass before continuing");
268
+ }
269
+ return errors;
270
+ }
271
+ function validateCloudflareConfig(_state, input) {
272
+ const errors = [];
273
+ const token = input.apiToken;
274
+ const accountId = input.accountId;
275
+ if (!token || String(token).trim().length === 0) {
276
+ errors.push("Cloudflare API token is required");
277
+ }
278
+ if (!accountId || String(accountId).trim().length === 0) {
279
+ errors.push("Cloudflare Account ID is required");
280
+ }
281
+ return errors;
282
+ }
283
+ function validateWorkerSelection(_state, input) {
284
+ const errors = [];
285
+ const preset = input.preset;
286
+ const customWorkers = input.workers;
287
+ if (preset === "custom" && (!customWorkers || customWorkers.length === 0)) {
288
+ errors.push("At least one worker must be selected");
289
+ }
290
+ return errors;
291
+ }
292
+ function validateSecrets(state, input) {
293
+ const errors = [];
294
+ const secrets = input.secrets;
295
+ if (!secrets || Object.keys(secrets).length === 0) {
296
+ return [];
297
+ }
298
+ for (const integrationKey of state.selectedIntegrations) {
299
+ const integration = INTEGRATIONS.find((i) => i.key === integrationKey);
300
+ if (!integration)
301
+ continue;
302
+ const integrationSecrets = secrets[integrationKey];
303
+ if (integrationSecrets) {
304
+ for (const secretName of Object.keys(integration.secrets)) {
305
+ const val = integrationSecrets[secretName];
306
+ if (!val || String(val).trim().length === 0) {
307
+ errors.push(`Secret "${integration.secrets[secretName]}" is required for ${integration.label}`);
308
+ }
309
+ }
310
+ }
311
+ }
312
+ return errors;
313
+ }
314
+
315
+ class WizardEngine {
316
+ state;
317
+ constructor(initialState) {
318
+ this.state = { ...createInitialState(), ...initialState };
319
+ }
320
+ getState() {
321
+ return { ...this.state };
322
+ }
323
+ getCurrentStep() {
324
+ return STEPS.find((s) => s.id === this.state.step) ?? STEPS[0];
325
+ }
326
+ getCompletedSteps() {
327
+ return [...this.state.completedSteps];
328
+ }
329
+ canProceed() {
330
+ const step = this.getCurrentStep();
331
+ return step.optional || this.state.completedSteps.includes(step.id);
332
+ }
333
+ canGoBack() {
334
+ return this.getCurrentStep().canGoBack;
335
+ }
336
+ execute(input) {
337
+ const currentStep = this.getCurrentStep();
338
+ const errors = currentStep.validate(this.state, input);
339
+ if (errors.length > 0) {
340
+ return errors;
341
+ }
342
+ this.applyInput(input);
343
+ if (!this.state.completedSteps.includes(this.state.step)) {
344
+ this.state.completedSteps.push(this.state.step);
345
+ }
346
+ const currentIdx = STEP_ORDER.indexOf(this.state.step);
347
+ if (currentIdx < STEP_ORDER.length - 1) {
348
+ this.state.step = STEP_ORDER[currentIdx + 1];
349
+ }
350
+ this.state.updatedAt = Date.now();
351
+ return [];
352
+ }
353
+ goBack() {
354
+ if (!this.canGoBack())
355
+ return;
356
+ const currentIdx = STEP_ORDER.indexOf(this.state.step);
357
+ if (currentIdx > 0) {
358
+ const previousStep = STEP_ORDER[currentIdx - 1];
359
+ this.state.step = previousStep;
360
+ this.state.completedSteps = this.state.completedSteps.filter((s) => s !== this.state.step || STEP_ORDER.indexOf(s) <= STEP_ORDER.indexOf(previousStep));
361
+ }
362
+ this.state.updatedAt = Date.now();
363
+ }
364
+ reset() {
365
+ this.state = createInitialState();
366
+ }
367
+ buildConfig() {
368
+ const cf = this.state.cloudflareConfig;
369
+ const workers = {};
370
+ for (const [name, baseCfg] of Object.entries(BASE_WORKERS)) {
371
+ workers[name] = {
372
+ enabled: true,
373
+ path: baseCfg.path,
374
+ vars: { ...baseCfg.vars },
375
+ secrets: [...BASE_SECRETS[name] ?? []]
376
+ };
377
+ }
378
+ for (const key of this.state.selectedIntegrations) {
379
+ const integration = INTEGRATIONS.find((i) => i.key === key);
380
+ if (!integration)
381
+ continue;
382
+ const workerName = integration.workerName;
383
+ if (!workers[workerName]) {
384
+ workers[workerName] = {
385
+ enabled: true,
386
+ path: `workers/${workerName}`,
387
+ vars: {},
388
+ secrets: []
389
+ };
390
+ }
391
+ if (integration.vars) {
392
+ Object.assign(workers[workerName].vars, integration.vars);
393
+ }
394
+ for (const secretName of Object.keys(integration.secrets)) {
395
+ if (!workers[workerName].secrets.includes(secretName)) {
396
+ workers[workerName].secrets.push(secretName);
397
+ }
398
+ }
399
+ }
400
+ for (const workerName of this.state.selectedWorkers) {
401
+ if (!workers[workerName]) {
402
+ workers[workerName] = {
403
+ enabled: true,
404
+ path: `workers/${workerName}`,
405
+ vars: {},
406
+ secrets: []
407
+ };
408
+ }
409
+ }
410
+ return {
411
+ global: {
412
+ cloudflare_api_token: cf?.apiToken ?? "",
413
+ cloudflare_account_id: cf?.accountId ?? "",
414
+ cloudflare_secret_store_id: cf?.secretStoreId ?? "",
415
+ subdomain_prefix: cf?.subdomain ?? ""
416
+ },
417
+ workers
418
+ };
419
+ }
420
+ getProvisioningPlan() {
421
+ const plan = {
422
+ d1Databases: [],
423
+ kvNamespaces: [],
424
+ r2Buckets: [],
425
+ queues: []
426
+ };
427
+ const allWorkers = [
428
+ ...Object.keys(BASE_WORKERS),
429
+ ...this.state.selectedWorkers,
430
+ ...this.state.selectedIntegrations.map((k) => {
431
+ const i = INTEGRATIONS.find((i2) => i2.key === k);
432
+ return i?.workerName ?? "";
433
+ }).filter(Boolean)
434
+ ];
435
+ const workerSet = new Set(allWorkers);
436
+ if (workerSet.has("d1-worker")) {
437
+ plan.d1Databases.push("hoox-db");
438
+ }
439
+ if (workerSet.has("hoox") || workerSet.has("analytics-worker")) {
440
+ plan.kvNamespaces.push("CONFIG_KV");
441
+ }
442
+ if (workerSet.has("web3-wallet-worker")) {
443
+ plan.kvNamespaces.push("WEB3_CACHE_KV");
444
+ }
445
+ plan.d1Databases = [...new Set(plan.d1Databases)];
446
+ plan.kvNamespaces = [...new Set(plan.kvNamespaces)];
447
+ return plan;
448
+ }
449
+ applyInput(input) {
450
+ const step = this.state.step;
451
+ switch (step) {
452
+ case "PREREQUISITES":
453
+ break;
454
+ case "CLOUDFLARE_CONFIG":
455
+ this.state.cloudflareConfig = {
456
+ apiToken: String(input.apiToken ?? ""),
457
+ accountId: String(input.accountId ?? ""),
458
+ secretStoreId: String(input.secretStoreId ?? ""),
459
+ subdomain: String(input.subdomain ?? "cryptolinx")
460
+ };
461
+ break;
462
+ case "WORKER_SELECTION": {
463
+ const preset = input.preset;
464
+ this.state.preset = preset;
465
+ if (preset && preset !== "custom") {
466
+ const presetDef = PRESETS.find((p) => p.name === preset);
467
+ if (presetDef) {
468
+ const resolved = resolveDependencies(presetDef.workers);
469
+ this.state.selectedWorkers = resolved;
470
+ this.state.selectedIntegrations = presetDef.integrations;
471
+ }
472
+ } else {
473
+ const workers = input.workers;
474
+ const integrations = input.integrations;
475
+ if (workers) {
476
+ this.state.selectedWorkers = resolveDependencies(workers);
477
+ }
478
+ if (integrations) {
479
+ this.state.selectedIntegrations = integrations;
480
+ }
481
+ }
482
+ break;
483
+ }
484
+ case "SECRETS":
485
+ this.state.secrets = input.secrets ?? {};
486
+ break;
487
+ case "PROVISIONING":
488
+ if (input.provisioningResults) {
489
+ this.state.provisioningResults = input.provisioningResults;
490
+ }
491
+ break;
492
+ case "CONFIG_WRITE":
493
+ case "DEPLOY":
494
+ case "DONE":
495
+ break;
496
+ }
497
+ }
498
+ }
499
+ export {
500
+ WizardEngine
501
+ };
@@ -176,7 +176,7 @@ var BASE_WORKERS = {
176
176
  path: "workers/d1-worker",
177
177
  vars: { database_name: "hoox-db" }
178
178
  },
179
- hoox: { enabled: true, path: "workers/hoox", vars: {} },
179
+ hoox: { enabled: true, path: "workers/hoox-worker", vars: {} },
180
180
  "agent-worker": { enabled: true, path: "workers/agent-worker", vars: {} },
181
181
  "analytics-worker": {
182
182
  enabled: true,
@@ -496,6 +496,7 @@ class WizardEngine {
496
496
  }
497
497
  }
498
498
  }
499
+
499
500
  // src/wizard/persistence.ts
500
501
  function serializeState(state) {
501
502
  return JSON.stringify(state, null, 2);
@@ -0,0 +1,31 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
+
18
+ // src/wizard/persistence.ts
19
+ function serializeState(state) {
20
+ return JSON.stringify(state, null, 2);
21
+ }
22
+ function deserializeState(json) {
23
+ const parsed = JSON.parse(json);
24
+ return parsed;
25
+ }
26
+ var WIZARD_STATE_PATH = ".wizard-state.json";
27
+ export {
28
+ serializeState,
29
+ deserializeState,
30
+ WIZARD_STATE_PATH
31
+ };