@jango-blockchained/hoox-shared 1.0.8 → 1.0.9

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 (61) hide show
  1. package/dist/analytics.d.ts +0 -1
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/colors.d.ts +0 -1
  4. package/dist/colors.d.ts.map +1 -1
  5. package/dist/colors.js +0 -1
  6. package/dist/cron-handler.d.ts +34 -0
  7. package/dist/cron-handler.d.ts.map +1 -0
  8. package/dist/cron-handler.js +48 -0
  9. package/dist/d1/index.js +49 -6
  10. package/dist/d1/repository.d.ts +5 -0
  11. package/dist/d1/repository.d.ts.map +1 -1
  12. package/dist/errors.d.ts +1 -0
  13. package/dist/errors.d.ts.map +1 -1
  14. package/dist/errors.js +48 -5
  15. package/dist/exchanges/base-exchange-client.d.ts +68 -0
  16. package/dist/exchanges/base-exchange-client.d.ts.map +1 -0
  17. package/dist/exchanges/index.d.ts +3 -0
  18. package/dist/exchanges/index.d.ts.map +1 -0
  19. package/dist/exchanges/index.js +120 -0
  20. package/dist/exchanges/types.d.ts +19 -0
  21. package/dist/exchanges/types.d.ts.map +1 -0
  22. package/dist/health.js +48 -5
  23. package/dist/index.d.ts +11 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +480 -15
  26. package/dist/kvUtils.js +48 -5
  27. package/dist/middleware/auth.d.ts +6 -3
  28. package/dist/middleware/auth.d.ts.map +1 -1
  29. package/dist/middleware/index.js +193 -18
  30. package/dist/middleware/logger.d.ts +2 -1
  31. package/dist/middleware/logger.d.ts.map +1 -1
  32. package/dist/middleware/rate-limit.d.ts +3 -1
  33. package/dist/middleware/rate-limit.d.ts.map +1 -1
  34. package/dist/path-utils.d.ts +147 -0
  35. package/dist/path-utils.d.ts.map +1 -0
  36. package/dist/path-utils.js +101 -0
  37. package/dist/queue-handler.d.ts +43 -0
  38. package/dist/queue-handler.d.ts.map +1 -0
  39. package/dist/queue-handler.js +46 -0
  40. package/dist/router.d.ts +1 -1
  41. package/dist/router.d.ts.map +1 -1
  42. package/dist/router.js +15 -8
  43. package/dist/service-bindings.d.ts +5 -28
  44. package/dist/service-bindings.d.ts.map +1 -1
  45. package/dist/service-bindings.js +3 -1
  46. package/dist/session.d.ts +9 -5
  47. package/dist/session.d.ts.map +1 -1
  48. package/dist/session.js +83 -3
  49. package/dist/sse.js +1 -1
  50. package/dist/stores/service-store.d.ts +50 -1
  51. package/dist/stores/service-store.d.ts.map +1 -1
  52. package/dist/stores/service-store.js +67 -3
  53. package/dist/test-utils.d.ts +132 -0
  54. package/dist/test-utils.d.ts.map +1 -0
  55. package/dist/test-utils.js +128 -0
  56. package/dist/types/router.d.ts +18 -8
  57. package/dist/types/router.d.ts.map +1 -1
  58. package/dist/types.d.ts +59 -5
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/wizard/engine.d.ts.map +1 -1
  61. package/package.json +11 -3
@@ -8,7 +8,6 @@
8
8
  */
9
9
  export interface AnalyticsEnv {
10
10
  ANALYTICS_SERVICE?: Fetcher;
11
- [key: string]: unknown;
12
11
  }
13
12
  /**
14
13
  * Track an analytics event by forwarding to the analytics worker.
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,YAAY,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CAaf"}
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,YAAY,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CAaf"}
package/dist/colors.d.ts CHANGED
@@ -25,7 +25,6 @@ export declare const Colors: {
25
25
  readonly info: "#4488FF";
26
26
  readonly text: "#EEEEEE";
27
27
  readonly "text-muted": "#A0A0A0";
28
- readonly "text-dim": "#6E6E6E";
29
28
  readonly panel: "#1C1C1F";
30
29
  readonly divider: "#484848";
31
30
  readonly highlight: "#E8780A";
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;CA2BT,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;CA0BT,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAC"}
package/dist/colors.js CHANGED
@@ -32,7 +32,6 @@ var Colors = {
32
32
  info: "#4488FF",
33
33
  text: "#EEEEEE",
34
34
  "text-muted": "#A0A0A0",
35
- "text-dim": "#6E6E6E",
36
35
  panel: "#1C1C1F",
37
36
  divider: "#484848",
38
37
  highlight: "#E8780A"
@@ -0,0 +1,34 @@
1
+ import type { ScheduledEvent } from "@cloudflare/workers-types";
2
+ export interface CronHandlerOptions<Env = unknown> {
3
+ /** Name of the worker for logging context */
4
+ name: string;
5
+ /** Handler function to execute */
6
+ handler: (event: ScheduledEvent, env: Env, ctx: ExecutionContext) => Promise<void> | void;
7
+ /** Optional logger instance */
8
+ logger?: {
9
+ info(message: string, data?: Record<string, any>): void;
10
+ error(message: string, data?: Record<string, any>): void;
11
+ };
12
+ }
13
+ /**
14
+ * Creates a standardized cron handler with consistent logging and error handling.
15
+ *
16
+ * Usage:
17
+ * ```typescript
18
+ * const cronHandler = createCronHandler({
19
+ * name: "agent-worker",
20
+ * handler: async (event, env, ctx) => {
21
+ * await runAgentRoutine(env);
22
+ * },
23
+ * logger: createLogger({ service: "agent-worker" })
24
+ * });
25
+ *
26
+ * export default {
27
+ * async scheduled(event, env, ctx) {
28
+ * return await cronHandler(event, env, ctx);
29
+ * }
30
+ * };
31
+ * ```
32
+ */
33
+ export declare function createCronHandler<Env = unknown>(options: CronHandlerOptions<Env>): (event: ScheduledEvent, env: Env, ctx: ExecutionContext) => Promise<void>;
34
+ //# sourceMappingURL=cron-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-handler.d.ts","sourceRoot":"","sources":["../src/cron-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE,MAAM,WAAW,kBAAkB,CAAC,GAAG,GAAG,OAAO;IAC/C,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,OAAO,EAAE,CACP,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,gBAAgB,KAClB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,+BAA+B;IAC/B,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;QACxD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;KAC1D,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAG,OAAO,EAC7C,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,IAK9B,OAAO,cAAc,EACrB,KAAK,GAAG,EACR,KAAK,gBAAgB,KACpB,OAAO,CAAC,IAAI,CAAC,CA6BjB"}
@@ -0,0 +1,48 @@
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/cron-handler.ts
19
+ function createCronHandler(options) {
20
+ const { name, handler, logger } = options;
21
+ return async (event, env, ctx) => {
22
+ const startTime = Date.now();
23
+ logger?.info(`${name} cron triggered`, {
24
+ cron: event.cron,
25
+ scheduledTime: event.scheduledTime
26
+ });
27
+ try {
28
+ await handler(event, env, ctx);
29
+ const durationMs = Date.now() - startTime;
30
+ logger?.info(`${name} cron handler completed successfully`, {
31
+ cron: event.cron,
32
+ durationMs
33
+ });
34
+ } catch (error) {
35
+ const durationMs = Date.now() - startTime;
36
+ const errorMsg = error instanceof Error ? error.message : String(error);
37
+ logger?.error(`${name} cron handler failed`, {
38
+ cron: event.cron,
39
+ durationMs,
40
+ error: errorMsg
41
+ });
42
+ throw error;
43
+ }
44
+ };
45
+ }
46
+ export {
47
+ createCronHandler
48
+ };
package/dist/d1/index.js CHANGED
@@ -32,22 +32,65 @@ function toError(err, fallback = "Unknown error") {
32
32
  return fallback;
33
33
  }
34
34
  }
35
+ var SENSITIVE_FIELDS = new Set([
36
+ "password",
37
+ "token",
38
+ "secret",
39
+ "api_key",
40
+ "apiKey",
41
+ "authorization"
42
+ ]);
43
+ function hasSensitiveFields(obj) {
44
+ for (const key of Object.keys(obj)) {
45
+ if (SENSITIVE_FIELDS.has(key))
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ function hasErrorValues(obj) {
51
+ for (const v of Object.values(obj)) {
52
+ if (v instanceof Error)
53
+ return true;
54
+ }
55
+ return false;
56
+ }
35
57
  function sanitizeOutput(data) {
58
+ if (data === null || data === undefined)
59
+ return data;
60
+ const t = typeof data;
61
+ if (t === "string" || t === "number" || t === "boolean")
62
+ return data;
36
63
  if (data instanceof Error) {
37
64
  return { name: data.name, message: data.message };
38
65
  }
39
- if (data && typeof data === "object" && !Array.isArray(data)) {
66
+ if (Array.isArray(data)) {
67
+ return data.map(sanitizeOutput);
68
+ }
69
+ if (t === "object") {
70
+ const obj = data;
71
+ const keys = Object.keys(obj);
72
+ if (keys.length < 10) {
73
+ const sanitized2 = {};
74
+ for (const k of keys) {
75
+ if (k === "stack" || k === "cause")
76
+ continue;
77
+ const v = obj[k];
78
+ sanitized2[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
79
+ }
80
+ return sanitized2;
81
+ }
82
+ if (!hasSensitiveFields(obj) && !hasErrorValues(obj)) {
83
+ return obj;
84
+ }
40
85
  const sanitized = {};
41
- for (const [k, v] of Object.entries(data)) {
86
+ for (const k of keys) {
42
87
  if (k === "stack" || k === "cause")
43
88
  continue;
89
+ const v = obj[k];
44
90
  sanitized[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
45
91
  }
46
92
  return sanitized;
47
93
  }
48
- if (Array.isArray(data)) {
49
- return data.map(sanitizeOutput);
50
- }
51
94
  return data;
52
95
  }
53
96
  function createJsonResponse(data, status = 200) {
@@ -143,7 +186,7 @@ class D1Repository {
143
186
  async batch(statements) {
144
187
  try {
145
188
  const prepared = statements.map((s) => s.params && s.params.length > 0 ? this.db.prepare(s.query).bind(...s.params) : this.db.prepare(s.query));
146
- const results = await this.db.batch(...prepared);
189
+ const results = await this.db.batch(prepared);
147
190
  return results.map((r) => ({
148
191
  success: r.success,
149
192
  meta: r.meta ? { last_row_id: r.meta.last_row_id, changes: r.meta.changes } : undefined,
@@ -1,3 +1,8 @@
1
+ /**
2
+ * @deprecated D1Repository is no longer used by any worker.
3
+ * All D1 operations are now handled directly via route handlers in workers/d1-worker.
4
+ * This file is kept for reference but will be removed in a future cleanup pass.
5
+ */
1
6
  import type { D1Database, D1PreparedStatement } from "@cloudflare/workers-types";
2
7
  import type { TradeRecord, PositionRecord, BalanceRecord, SystemLogRecord, TradeSignalRecord, D1QueryResult } from "./schemas";
3
8
  export interface BatchStatement {
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/d1/repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,mBAAmB,EACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,aAAa,EACd,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,UAAU;IAE3C;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAiB5B;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAqB1E;;OAEG;IACG,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAuBnE;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB;IAMzC;;OAEG;IACG,SAAS,CACb,KAAK,GAAE,MAAW,EAClB,MAAM,GAAE,MAAU,GACjB,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAOtC;;OAEG;IACG,WAAW,CACf,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,YAAY,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9D,OAAO,CAAC,aAAa,CAAC;IAmBzB;;OAEG;IACG,YAAY,CAChB,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GACzB,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IAYzC;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAqBtE;;OAEG;IACG,eAAe,CACnB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAU5C;;OAEG;IACG,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAe1E;;OAEG;IACG,aAAa,CACjB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IAO1C;;OAEG;IACG,eAAe,CACnB,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC,GAAG;QAC5D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,GACA,OAAO,CAAC,aAAa,CAAC;IAazB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAYhE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAQtC"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/d1/repository.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,UAAU,EAEV,mBAAmB,EACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,aAAa,EACd,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,UAAU;IAE3C;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAiB5B;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAqB1E;;OAEG;IACG,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAuBnE;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB;IAMzC;;OAEG;IACG,SAAS,CACb,KAAK,GAAE,MAAW,EAClB,MAAM,GAAE,MAAU,GACjB,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAOtC;;OAEG;IACG,WAAW,CACf,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,YAAY,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9D,OAAO,CAAC,aAAa,CAAC;IAmBzB;;OAEG;IACG,YAAY,CAChB,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GACzB,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IAYzC;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAqBtE;;OAEG;IACG,eAAe,CACnB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAU5C;;OAEG;IACG,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAe1E;;OAEG;IACG,aAAa,CACjB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IAO1C;;OAEG;IACG,eAAe,CACnB,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC,GAAG;QAC5D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,GACA,OAAO,CAAC,aAAa,CAAC;IAazB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAYhE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAQtC"}
package/dist/errors.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * Centralizes error response creation across the monorepo
4
4
  */
5
5
  import type { AppError } from "./types/errors";
6
+ export type { AppError };
6
7
  /**
7
8
  * Safely extract an error message from any caught value.
8
9
  * Eliminates the duplicated `error instanceof Error ? error.message : String(error)`
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,gBAAgB,CAAC;AAE9D;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,SAAkB,GAAG,MAAM,CAkBxE;AA+BD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,QAAQ,CAKxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAEhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,GAAG,MAAM,EACxB,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CAcV;AAED;;GAEG;AACH,eAAO,MAAM,MAAM;0BACK,MAAM;;;;;+BAUD,MAAM;qBAShB,OAAO;CAUzB,CAAC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,SAAkB,GAAG,MAAM,CAkBxE;AA4FD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,QAAQ,CAKxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAEhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,GAAG,MAAM,EACxB,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CAcV;AAED;;GAEG;AACH,eAAO,MAAM,MAAM;0BACK,MAAM;;;;;+BAUD,MAAM;qBAShB,OAAO;CAUzB,CAAC"}
package/dist/errors.js CHANGED
@@ -32,22 +32,65 @@ function toError(err, fallback = "Unknown error") {
32
32
  return fallback;
33
33
  }
34
34
  }
35
+ var SENSITIVE_FIELDS = new Set([
36
+ "password",
37
+ "token",
38
+ "secret",
39
+ "api_key",
40
+ "apiKey",
41
+ "authorization"
42
+ ]);
43
+ function hasSensitiveFields(obj) {
44
+ for (const key of Object.keys(obj)) {
45
+ if (SENSITIVE_FIELDS.has(key))
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ function hasErrorValues(obj) {
51
+ for (const v of Object.values(obj)) {
52
+ if (v instanceof Error)
53
+ return true;
54
+ }
55
+ return false;
56
+ }
35
57
  function sanitizeOutput(data) {
58
+ if (data === null || data === undefined)
59
+ return data;
60
+ const t = typeof data;
61
+ if (t === "string" || t === "number" || t === "boolean")
62
+ return data;
36
63
  if (data instanceof Error) {
37
64
  return { name: data.name, message: data.message };
38
65
  }
39
- if (data && typeof data === "object" && !Array.isArray(data)) {
66
+ if (Array.isArray(data)) {
67
+ return data.map(sanitizeOutput);
68
+ }
69
+ if (t === "object") {
70
+ const obj = data;
71
+ const keys = Object.keys(obj);
72
+ if (keys.length < 10) {
73
+ const sanitized2 = {};
74
+ for (const k of keys) {
75
+ if (k === "stack" || k === "cause")
76
+ continue;
77
+ const v = obj[k];
78
+ sanitized2[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
79
+ }
80
+ return sanitized2;
81
+ }
82
+ if (!hasSensitiveFields(obj) && !hasErrorValues(obj)) {
83
+ return obj;
84
+ }
40
85
  const sanitized = {};
41
- for (const [k, v] of Object.entries(data)) {
86
+ for (const k of keys) {
42
87
  if (k === "stack" || k === "cause")
43
88
  continue;
89
+ const v = obj[k];
44
90
  sanitized[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
45
91
  }
46
92
  return sanitized;
47
93
  }
48
- if (Array.isArray(data)) {
49
- return data.map(sanitizeOutput);
50
- }
51
94
  return data;
52
95
  }
53
96
  function createJsonResponse(data, status = 200) {
@@ -0,0 +1,68 @@
1
+ export interface ExchangeConfig {
2
+ apiKey: string;
3
+ apiSecret: string;
4
+ baseUrl?: string;
5
+ testnet?: boolean;
6
+ }
7
+ export interface TradeParams {
8
+ symbol: string;
9
+ side: string;
10
+ orderType?: string;
11
+ quantity: number;
12
+ price?: number;
13
+ reduceOnly?: boolean;
14
+ leverage?: number;
15
+ }
16
+ export interface OrderResponse {
17
+ orderId: string;
18
+ symbol: string;
19
+ status: string;
20
+ executedQty?: string;
21
+ price?: string;
22
+ }
23
+ export interface Position {
24
+ symbol: string;
25
+ side: "long" | "short";
26
+ quantity: number;
27
+ entryPrice: number;
28
+ unrealizedPnl?: number;
29
+ }
30
+ /**
31
+ * Base class for exchange clients. All exchange implementations must extend this.
32
+ * Provides common functionality for exchange API clients including signature generation,
33
+ * HTTP requests, and trade execution helpers.
34
+ */
35
+ export declare abstract class BaseExchangeClient {
36
+ protected readonly apiKey: string;
37
+ protected readonly apiSecret: string;
38
+ protected readonly baseUrl: string;
39
+ protected readonly isTestnet: boolean;
40
+ protected readonly importedKeyPromise: Promise<CryptoKey>;
41
+ constructor(apiKey: string, apiSecret: string);
42
+ /**
43
+ * Returns the error message prefix for this client.
44
+ * Subclasses can override to customize error messages.
45
+ */
46
+ protected getErrorMessagePrefix(): string;
47
+ protected abstract getDefaultBaseUrl(): string;
48
+ protected generateSignature(_params: Record<string, string | number | boolean>): Promise<string>;
49
+ protected buildHeaders(_method: string, _path: string, _params?: Record<string, string | number | boolean>): Headers;
50
+ /**
51
+ * Imports the API secret as a CryptoKey for HMAC-SHA256 signing.
52
+ */
53
+ private importKey;
54
+ /**
55
+ * Signs data using HMAC-SHA256 with the API secret.
56
+ */
57
+ protected cryptoSign(data: string): Promise<string>;
58
+ protected fetch<T>(method: string, path: string, params?: Record<string, string | number | boolean>): Promise<T>;
59
+ setLeverage(_symbol: string, _leverage: number): Promise<void>;
60
+ executeTrade(_params: TradeParams): Promise<OrderResponse>;
61
+ getAccountInfo(): Promise<Record<string, unknown>>;
62
+ getPositions(_symbol?: string): Promise<Position[]>;
63
+ openLong(symbol: string, quantity: number, price?: number, orderType?: string): Promise<OrderResponse>;
64
+ openShort(symbol: string, quantity: number, price?: number, orderType?: string): Promise<OrderResponse>;
65
+ closeLong(symbol: string, quantity: number): Promise<OrderResponse>;
66
+ closeShort(symbol: string, quantity: number): Promise<OrderResponse>;
67
+ }
68
+ //# sourceMappingURL=base-exchange-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-exchange-client.d.ts","sourceRoot":"","sources":["../../src/exchanges/base-exchange-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { BaseExchangeClient, type ExchangeConfig, type TradeParams, type OrderResponse, type Position, } from "./base-exchange-client";
2
+ export type { SupportedExchange } from "./types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exchanges/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,120 @@
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/exchanges/base-exchange-client.ts
19
+ class BaseExchangeClient {
20
+ apiKey;
21
+ apiSecret;
22
+ baseUrl;
23
+ isTestnet;
24
+ importedKeyPromise;
25
+ constructor(apiKey, apiSecret) {
26
+ if (!apiKey || !apiSecret) {
27
+ throw new Error(this.getErrorMessagePrefix() + "API key and secret are required.");
28
+ }
29
+ this.apiKey = apiKey;
30
+ this.apiSecret = apiSecret;
31
+ this.baseUrl = this.getDefaultBaseUrl();
32
+ this.isTestnet = false;
33
+ this.importedKeyPromise = this.importKey();
34
+ }
35
+ getErrorMessagePrefix() {
36
+ return "";
37
+ }
38
+ generateSignature(_params) {
39
+ throw new Error("generateSignature must be implemented by subclass");
40
+ }
41
+ buildHeaders(_method, _path, _params) {
42
+ return new Headers;
43
+ }
44
+ async importKey() {
45
+ const encoder = new TextEncoder;
46
+ return crypto.subtle.importKey("raw", encoder.encode(this.apiSecret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
47
+ }
48
+ async cryptoSign(data) {
49
+ const encoder = new TextEncoder;
50
+ const key = await this.importedKeyPromise;
51
+ const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(data));
52
+ return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
53
+ }
54
+ async fetch(method, path, params) {
55
+ const url = `${this.baseUrl}${path}`;
56
+ const headers = this.buildHeaders(method, path, params);
57
+ const body = params ? new URLSearchParams(params).toString() : undefined;
58
+ const response = await fetch(url, {
59
+ method,
60
+ headers,
61
+ body: method !== "GET" ? body : undefined
62
+ });
63
+ if (!response.ok) {
64
+ const error = await response.text();
65
+ throw new Error(`Exchange API error: ${response.status} - ${error}`);
66
+ }
67
+ return response.json();
68
+ }
69
+ setLeverage(_symbol, _leverage) {
70
+ throw new Error("setLeverage must be implemented by subclass");
71
+ }
72
+ executeTrade(_params) {
73
+ throw new Error("executeTrade must be implemented by subclass");
74
+ }
75
+ getAccountInfo() {
76
+ throw new Error("getAccountInfo must be implemented by subclass");
77
+ }
78
+ getPositions(_symbol) {
79
+ throw new Error("getPositions must be implemented by subclass");
80
+ }
81
+ async openLong(symbol, quantity, price, orderType = "MARKET") {
82
+ return this.executeTrade({
83
+ symbol,
84
+ side: "BUY",
85
+ orderType,
86
+ quantity,
87
+ price
88
+ });
89
+ }
90
+ async openShort(symbol, quantity, price, orderType = "MARKET") {
91
+ return this.executeTrade({
92
+ symbol,
93
+ side: "SELL",
94
+ orderType,
95
+ quantity,
96
+ price
97
+ });
98
+ }
99
+ async closeLong(symbol, quantity) {
100
+ return this.executeTrade({
101
+ symbol,
102
+ side: "SELL",
103
+ orderType: "MARKET",
104
+ quantity,
105
+ reduceOnly: true
106
+ });
107
+ }
108
+ async closeShort(symbol, quantity) {
109
+ return this.executeTrade({
110
+ symbol,
111
+ side: "BUY",
112
+ orderType: "MARKET",
113
+ quantity,
114
+ reduceOnly: true
115
+ });
116
+ }
117
+ }
118
+ export {
119
+ BaseExchangeClient
120
+ };
@@ -0,0 +1,19 @@
1
+ export type SupportedExchange = "binance" | "bybit" | "mexc";
2
+ export interface ExchangeOrder {
3
+ orderId: string;
4
+ symbol: string;
5
+ side: "BUY" | "SELL";
6
+ quantity: number;
7
+ price?: number;
8
+ leverage?: number;
9
+ status: "PENDING" | "FILLED" | "CANCELED" | "FAILED";
10
+ }
11
+ export interface ExchangePosition {
12
+ symbol: string;
13
+ quantity: number;
14
+ leverage: number;
15
+ markPrice: number;
16
+ unrealizedPnl: number;
17
+ side: "LONG" | "SHORT";
18
+ }
19
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/exchanges/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;CACtD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
package/dist/health.js CHANGED
@@ -32,22 +32,65 @@ function toError(err, fallback = "Unknown error") {
32
32
  return fallback;
33
33
  }
34
34
  }
35
+ var SENSITIVE_FIELDS = new Set([
36
+ "password",
37
+ "token",
38
+ "secret",
39
+ "api_key",
40
+ "apiKey",
41
+ "authorization"
42
+ ]);
43
+ function hasSensitiveFields(obj) {
44
+ for (const key of Object.keys(obj)) {
45
+ if (SENSITIVE_FIELDS.has(key))
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ function hasErrorValues(obj) {
51
+ for (const v of Object.values(obj)) {
52
+ if (v instanceof Error)
53
+ return true;
54
+ }
55
+ return false;
56
+ }
35
57
  function sanitizeOutput(data) {
58
+ if (data === null || data === undefined)
59
+ return data;
60
+ const t = typeof data;
61
+ if (t === "string" || t === "number" || t === "boolean")
62
+ return data;
36
63
  if (data instanceof Error) {
37
64
  return { name: data.name, message: data.message };
38
65
  }
39
- if (data && typeof data === "object" && !Array.isArray(data)) {
66
+ if (Array.isArray(data)) {
67
+ return data.map(sanitizeOutput);
68
+ }
69
+ if (t === "object") {
70
+ const obj = data;
71
+ const keys = Object.keys(obj);
72
+ if (keys.length < 10) {
73
+ const sanitized2 = {};
74
+ for (const k of keys) {
75
+ if (k === "stack" || k === "cause")
76
+ continue;
77
+ const v = obj[k];
78
+ sanitized2[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
79
+ }
80
+ return sanitized2;
81
+ }
82
+ if (!hasSensitiveFields(obj) && !hasErrorValues(obj)) {
83
+ return obj;
84
+ }
40
85
  const sanitized = {};
41
- for (const [k, v] of Object.entries(data)) {
86
+ for (const k of keys) {
42
87
  if (k === "stack" || k === "cause")
43
88
  continue;
89
+ const v = obj[k];
44
90
  sanitized[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
45
91
  }
46
92
  return sanitized;
47
93
  }
48
- if (Array.isArray(data)) {
49
- return data.map(sanitizeOutput);
50
- }
51
94
  return data;
52
95
  }
53
96
  function createJsonResponse(data, status = 200) {
package/dist/index.d.ts CHANGED
@@ -9,17 +9,24 @@ export { TradeActionSchema, WebhookPayloadSchema, TradeSignalSchema, PositionSch
9
9
  export type { TradeAction, WebhookPayload, TradeSignal } from "./types";
10
10
  export { KVKeys } from "./kvKeys";
11
11
  export { toError, Errors, createJsonResponse, createSuccessResponse, createErrorResponse, } from "./errors";
12
- export { BaseExchangeClient, ExchangeRouter } from "./exchange-client";
12
+ export { ExchangeRouter } from "./exchange-client";
13
13
  export type { ExchangeName, ExchangeConfig, TradeParams, OrderResponse, Position, IExchangeProvider, } from "./exchange-client";
14
+ export { BaseExchangeClient } from "./exchanges";
15
+ export type { SupportedExchange } from "./exchanges";
14
16
  export { logKvTimestamp, headersToObject } from "./kvUtils";
15
17
  export type { EnvWithKV } from "./kvUtils";
16
18
  export { trackAnalytics } from "./analytics";
17
19
  export type { AnalyticsEnv } from "./analytics";
18
20
  export { healthCheck } from "./health";
19
21
  export type { HealthCheckOptions } from "./health";
22
+ export { createQueueHandler } from "./queue-handler";
23
+ export type { QueueHandlerOptions } from "./queue-handler";
24
+ export { createCronHandler } from "./cron-handler";
25
+ export type { CronHandlerOptions } from "./cron-handler";
20
26
  export { D1Repository } from "./d1/index";
21
27
  export { serviceFetch } from "./service-bindings";
22
28
  export type { TradeRecord, PositionRecord, BalanceRecord, SystemLogRecord, TradeSignalRecord, D1QueryResult, BatchStatement, } from "./d1/index";
29
+ export * from "./test-utils";
23
30
  export { Colors } from "./colors";
24
31
  export type { ColorKey } from "./colors";
25
32
  export { formatNumber, formatCurrency, formatCompactCurrency, formatDuration, formatDurationCompact, formatTimestamp, formatRelativeTime, formatPercent, formatUptime, formatLatency, formatRequests, formatMemory, formatCpu, } from "./formatters";
@@ -31,7 +38,9 @@ export type { SSECallback, SSEStatusCallback } from "./sse";
31
38
  export { restoreSession, saveSession } from "./session";
32
39
  export type { SessionState } from "./session";
33
40
  export { formatRelativeTime as formatRelativeTimeFromTime } from "./format-time";
34
- export type { ViewId, ModalState, WorkerStatus, WorkerInfo, TradeSide, Trade, AlertSeverity, Alert, LogLevel, LogEntry, SystemMetrics, ConnectionStatus, LogFilter, NotificationPreferences, } from "./types";
41
+ export type { ViewId, ModalState, WorkerStatus, WorkerInfo, TradeSide, Trade, AlertSeverity, Alert, LogLevel, LogEntry, SystemMetrics, ConnectionStatus, LogFilter, NotificationPreferences, CliErrorType, CliErrorDetails, } from "./types";
42
+ export { getHooxHome, resolveHooxPath, isWithinHooxHome, getRelativeHooxPath, getHooxRepoPath, getHooxConfigDir, getHooxDataDir, getHooxWranglerPath, getHooxStatePath, } from "./path-utils";
43
+ export type { HooxPath } from "./path-utils";
35
44
  export type { StepId, WorkerPresetName, WorkerPreset, WorkerConfig, WorkersJsonConfig, IntegratedService, ProvisioningPlan, ProvisionResult, WizardCloudflareConfig, WizardState, StepDefinition, } from "./wizard";
36
45
  export type { Provisioner } from "./wizard";
37
46
  export { WizardEngine, PRESETS, WORKER_DEPENDENCIES, INTEGRATIONS, resolveDependencies, serializeState, deserializeState, WIZARD_STATE_PATH, } from "./wizard";