@jango-blockchained/hoox-shared 1.0.8 → 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 (102) hide show
  1. package/README.md +17 -0
  2. package/dist/analytics.d.ts +23 -2
  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 -25
  9. package/dist/colors.d.ts.map +1 -1
  10. package/dist/colors.js +60 -20
  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 +34 -0
  15. package/dist/cron-handler.d.ts.map +1 -0
  16. package/dist/cron-handler.js +48 -0
  17. package/dist/d1/index.js +50 -6
  18. package/dist/d1/repository.d.ts +5 -0
  19. package/dist/d1/repository.d.ts.map +1 -1
  20. package/dist/d1/repository.js +297 -0
  21. package/dist/d1/schemas.js +81 -0
  22. package/dist/errors.d.ts +1 -0
  23. package/dist/errors.d.ts.map +1 -1
  24. package/dist/errors.js +48 -5
  25. package/dist/exchanges/base-exchange-client.d.ts +68 -0
  26. package/dist/exchanges/base-exchange-client.d.ts.map +1 -0
  27. package/dist/exchanges/base-exchange-client.js +120 -0
  28. package/dist/exchanges/index.d.ts +3 -0
  29. package/dist/exchanges/index.d.ts.map +1 -0
  30. package/dist/exchanges/index.js +120 -0
  31. package/dist/exchanges/types.d.ts +19 -0
  32. package/dist/exchanges/types.d.ts.map +1 -0
  33. package/dist/exchanges/types.js +1 -0
  34. package/dist/health.js +48 -5
  35. package/dist/index.d.ts +30 -11
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1058 -73
  38. package/dist/kvUtils.js +48 -5
  39. package/dist/middleware/auth.d.ts +46 -7
  40. package/dist/middleware/auth.d.ts.map +1 -1
  41. package/dist/middleware/auth.js +151 -0
  42. package/dist/middleware/cors.d.ts +28 -2
  43. package/dist/middleware/cors.d.ts.map +1 -1
  44. package/dist/middleware/cors.js +77 -0
  45. package/dist/middleware/index.d.ts +2 -2
  46. package/dist/middleware/index.d.ts.map +1 -1
  47. package/dist/middleware/index.js +361 -101
  48. package/dist/middleware/logger.d.ts +2 -1
  49. package/dist/middleware/logger.d.ts.map +1 -1
  50. package/dist/middleware/logger.js +202 -0
  51. package/dist/middleware/rate-limit.d.ts +3 -1
  52. package/dist/middleware/rate-limit.d.ts.map +1 -1
  53. package/dist/middleware/rate-limit.js +181 -0
  54. package/dist/middleware/security-headers.js +58 -0
  55. package/dist/middleware/validate.js +56 -0
  56. package/dist/operator-transport.d.ts +61 -0
  57. package/dist/operator-transport.d.ts.map +1 -0
  58. package/dist/operator-transport.js +87 -0
  59. package/dist/path-utils.d.ts +205 -0
  60. package/dist/path-utils.d.ts.map +1 -0
  61. package/dist/path-utils.js +188 -0
  62. package/dist/queue-handler.d.ts +43 -0
  63. package/dist/queue-handler.d.ts.map +1 -0
  64. package/dist/queue-handler.js +46 -0
  65. package/dist/router.d.ts +2 -2
  66. package/dist/router.d.ts.map +1 -1
  67. package/dist/router.js +15 -8
  68. package/dist/schemas/index.js +7 -4
  69. package/dist/schemas/registry.js +387 -0
  70. package/dist/schemas/types.js +1 -0
  71. package/dist/schemas/validators.d.ts.map +1 -1
  72. package/dist/schemas/validators.js +290 -0
  73. package/dist/service-bindings.d.ts +68 -26
  74. package/dist/service-bindings.d.ts.map +1 -1
  75. package/dist/service-bindings.js +219 -2
  76. package/dist/session.d.ts +9 -5
  77. package/dist/session.d.ts.map +1 -1
  78. package/dist/session.js +179 -4
  79. package/dist/sse.d.ts +12 -3
  80. package/dist/sse.d.ts.map +1 -1
  81. package/dist/sse.js +70 -7
  82. package/dist/stores/config-store.d.ts.map +1 -1
  83. package/dist/stores/config-store.js +129 -6
  84. package/dist/stores/service-store.d.ts +50 -1
  85. package/dist/stores/service-store.d.ts.map +1 -1
  86. package/dist/stores/service-store.js +162 -27
  87. package/dist/test-utils.d.ts +132 -0
  88. package/dist/test-utils.d.ts.map +1 -0
  89. package/dist/test-utils.js +128 -0
  90. package/dist/types/router.d.ts +18 -8
  91. package/dist/types/router.d.ts.map +1 -1
  92. package/dist/types.d.ts +124 -5
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/types.js +11 -0
  95. package/dist/wizard/engine.d.ts.map +1 -1
  96. package/dist/wizard/engine.js +501 -0
  97. package/dist/wizard/index.js +2 -1
  98. package/dist/wizard/persistence.js +31 -0
  99. package/dist/wizard/presets.js +199 -0
  100. package/dist/wizard/provisioner.js +1 -0
  101. package/dist/wizard/types.js +1 -0
  102. package/package.json +46 -12
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Path Resolution Service for Hoox
3
+ *
4
+ * Provides cross-OS utilities for resolving the $HOME/.hoox directory location
5
+ * and constructing type-safe paths within it.
6
+ *
7
+ * Supports macOS, Linux, and Windows with proper fallback handling.
8
+ *
9
+ * Runtime layout:
10
+ * $HOME/.hoox/ — getHooxHome() (override with HOOX_HOME)
11
+ * $HOME/.hoox/repo/ — managed clone of hoox-setup (getHooxRepoPath)
12
+ * $HOME/.hoox/config/ — user config
13
+ * $HOME/.hoox/data/ — persistent state
14
+ *
15
+ * Tool/runtime resolution (resolveHooxRuntimeRoot):
16
+ * 1. HOOX_REPO env (explicit monorepo path)
17
+ * 2. Walk up from cwd for a local hoox-setup checkout
18
+ * 3. $HOME/.hoox/repo (global managed clone)
19
+ */
20
+ /**
21
+ * Branded type for Hoox paths to prevent accidental string usage.
22
+ * This ensures type safety when working with paths.
23
+ */
24
+ export type HooxPath = string & {
25
+ readonly __brand: "HooxPath";
26
+ };
27
+ /** Where resolveHooxRuntimeRoot found (or failed to find) a setup monorepo. */
28
+ export type RuntimeRootSource = "env" | "cwd" | "global" | "none";
29
+ /** Result of resolveHooxRuntimeRoot(). */
30
+ export interface RuntimeRootResult {
31
+ /** Absolute monorepo root, or null if none found. */
32
+ root: string | null;
33
+ /** Which resolution step produced the result. */
34
+ source: RuntimeRootSource;
35
+ /** Paths inspected (for doctor / error messages). */
36
+ checked: {
37
+ env?: string;
38
+ cwd: string | null;
39
+ global: string;
40
+ };
41
+ }
42
+ /**
43
+ * Gets the Hoox home directory location: $HOME/.hoox
44
+ *
45
+ * Behavior:
46
+ * - HOOX_HOME env wins when set (absolute or relative, then resolved)
47
+ * - Else $HOME/.hoox on macOS, Linux, Windows
48
+ * - Falls back to current working directory if HOME is not available
49
+ * - Resolves to absolute path
50
+ *
51
+ * @returns Absolute path to $HOME/.hoox as a branded HooxPath
52
+ * @throws Never — always returns a valid path
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const hooxHome = getHooxHome();
57
+ * // Returns: "/Users/alice/.hoox" (macOS)
58
+ * // Returns: "/home/alice/.hoox" (Linux)
59
+ * // Returns: "C:\\Users\\alice\\.hoox" (Windows)
60
+ * ```
61
+ */
62
+ export declare function getHooxHome(): HooxPath;
63
+ /**
64
+ * True when `dir` looks like a hoox-setup monorepo root.
65
+ *
66
+ * Markers match CLI verifyRepoRoot: root wrangler.jsonc + packages/cli package.
67
+ */
68
+ export declare function isHooxSetupRoot(dir: string): boolean;
69
+ /**
70
+ * Walk up from `startDir` looking for a hoox-setup monorepo root.
71
+ *
72
+ * @returns Absolute root path, or null if not found
73
+ */
74
+ export declare function findHooxSetupRoot(startDir?: string): string | null;
75
+ /**
76
+ * Resolve the Hoox tool/runtime monorepo root (local checkout or global clone).
77
+ *
78
+ * Order:
79
+ * 1. HOOX_REPO — must pass isHooxSetupRoot or result is source "env" with root null
80
+ * 2. Walk up from cwd
81
+ * 3. getHooxRepoPath() ($HOME/.hoox/repo or $HOOX_HOME/repo)
82
+ *
83
+ * Project cwd and tool root are intentionally separate: a random project
84
+ * directory can still use the global runtime for TUI / templates.
85
+ */
86
+ export declare function resolveHooxRuntimeRoot(options?: {
87
+ cwd?: string;
88
+ env?: NodeJS.ProcessEnv;
89
+ }): RuntimeRootResult;
90
+ /**
91
+ * Candidate TUI entry files under a monorepo root (source first, then dist).
92
+ */
93
+ export declare function getTuiEntryCandidates(runtimeRoot: string): string[];
94
+ /**
95
+ * Resolves a relative path within the Hoox home directory.
96
+ *
97
+ * Behavior:
98
+ * - Joins the relative path with $HOME/.hoox
99
+ * - Resolves to absolute path
100
+ * - Prevents path traversal attacks (../ sequences)
101
+ *
102
+ * @param relativePath - Path relative to $HOME/.hoox (e.g., "repo", "config/wrangler.jsonc")
103
+ * @returns Absolute path as a branded HooxPath
104
+ * @throws Error if path contains suspicious traversal patterns
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const repoPath = resolveHooxPath("repo");
109
+ * // Returns: "/Users/alice/.hoox/repo"
110
+ *
111
+ * const configPath = resolveHooxPath("config/wrangler.jsonc");
112
+ * // Returns: "/Users/alice/.hoox/config/wrangler.jsonc"
113
+ * ```
114
+ */
115
+ export declare function resolveHooxPath(relativePath: string): HooxPath;
116
+ /**
117
+ * Checks if a given path is within the Hoox home directory.
118
+ *
119
+ * @param path - Path to check
120
+ * @returns true if path is within $HOME/.hoox, false otherwise
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * isWithinHooxHome("/Users/alice/.hoox/repo"); // true
125
+ * isWithinHooxHome("/Users/alice/other"); // false
126
+ * ```
127
+ */
128
+ export declare function isWithinHooxHome(path: string): boolean;
129
+ /**
130
+ * Gets the relative path from Hoox home directory.
131
+ *
132
+ * @param absolutePath - Absolute path to resolve
133
+ * @returns Relative path from $HOME/.hoox, or null if path is outside Hoox home
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * getRelativeHooxPath("/Users/alice/.hoox/repo/src");
138
+ * // Returns: "repo/src"
139
+ *
140
+ * getRelativeHooxPath("/Users/alice/other");
141
+ * // Returns: null
142
+ * ```
143
+ */
144
+ export declare function getRelativeHooxPath(absolutePath: string): string | null;
145
+ /**
146
+ * Constructs a path to the Hoox repository location.
147
+ *
148
+ * @returns Path to $HOME/.hoox/repo as a branded HooxPath
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const repoPath = getHooxRepoPath();
153
+ * // Returns: "/Users/alice/.hoox/repo"
154
+ * ```
155
+ */
156
+ export declare function getHooxRepoPath(): HooxPath;
157
+ /**
158
+ * Constructs a path to the Hoox configuration directory.
159
+ *
160
+ * @returns Path to $HOME/.hoox/config as a branded HooxPath
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const configDir = getHooxConfigDir();
165
+ * // Returns: "/Users/alice/.hoox/config"
166
+ * ```
167
+ */
168
+ export declare function getHooxConfigDir(): HooxPath;
169
+ /**
170
+ * Constructs a path to the Hoox data directory.
171
+ *
172
+ * @returns Path to $HOME/.hoox/data as a branded HooxPath
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * const dataDir = getHooxDataDir();
177
+ * // Returns: "/Users/alice/.hoox/data"
178
+ * ```
179
+ */
180
+ export declare function getHooxDataDir(): HooxPath;
181
+ /**
182
+ * Constructs a path to the Hoox wrangler configuration file.
183
+ *
184
+ * @returns Path to $HOME/.hoox/config/wrangler.jsonc as a branded HooxPath
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * const wranglerPath = getHooxWranglerPath();
189
+ * // Returns: "/Users/alice/.hoox/config/wrangler.jsonc"
190
+ * ```
191
+ */
192
+ export declare function getHooxWranglerPath(): HooxPath;
193
+ /**
194
+ * Constructs a path to the Hoox state file.
195
+ *
196
+ * @returns Path to $HOME/.hoox/data/state.json as a branded HooxPath
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const statePath = getHooxStatePath();
201
+ * // Returns: "/Users/alice/.hoox/data/state.json"
202
+ * ```
203
+ */
204
+ export declare function getHooxStatePath(): HooxPath;
205
+ //# sourceMappingURL=path-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAEjE,+EAA+E;AAC/E,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElE,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,qDAAqD;IACrD,OAAO,EAAE;QACP,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAUD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAgBtC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAWpD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,GAAE,MAAsB,GAC/B,MAAM,GAAG,IAAI,CAQf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,iBAAiB,CAoDpB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAOnE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAiC9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAStD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,QAAQ,CAE1C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,QAAQ,CAE3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAEzC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,QAAQ,CAE9C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,QAAQ,CAE3C"}
@@ -0,0 +1,188 @@
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/path-utils.ts
19
+ import { existsSync } from "fs";
20
+ import { homedir } from "os";
21
+ import { dirname, join, resolve } from "path";
22
+ function createHooxPath(path) {
23
+ return path;
24
+ }
25
+ function getHooxHome() {
26
+ try {
27
+ const override = process.env.HOOX_HOME?.trim();
28
+ if (override) {
29
+ return createHooxPath(resolve(override));
30
+ }
31
+ const home = homedir();
32
+ if (!home || home.length === 0) {
33
+ return createHooxPath(resolve(process.cwd(), ".hoox"));
34
+ }
35
+ return createHooxPath(join(home, ".hoox"));
36
+ } catch {
37
+ return createHooxPath(resolve(process.cwd(), ".hoox"));
38
+ }
39
+ }
40
+ function isHooxSetupRoot(dir) {
41
+ if (!dir)
42
+ return false;
43
+ try {
44
+ const root = resolve(dir);
45
+ return existsSync(join(root, "wrangler.jsonc")) && existsSync(join(root, "packages", "cli", "package.json"));
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+ function findHooxSetupRoot(startDir = process.cwd()) {
51
+ let dir = resolve(startDir);
52
+ for (;; ) {
53
+ if (isHooxSetupRoot(dir))
54
+ return dir;
55
+ const parent = dirname(dir);
56
+ if (parent === dir)
57
+ return null;
58
+ dir = parent;
59
+ }
60
+ }
61
+ function resolveHooxRuntimeRoot(options) {
62
+ const env = options?.env ?? process.env;
63
+ const cwd = resolve(options?.cwd ?? process.cwd());
64
+ const globalRepo = getHooxRepoPath();
65
+ const envRepo = env.HOOX_REPO?.trim();
66
+ if (envRepo) {
67
+ const resolved = resolve(envRepo);
68
+ if (isHooxSetupRoot(resolved)) {
69
+ return {
70
+ root: resolved,
71
+ source: "env",
72
+ checked: {
73
+ env: resolved,
74
+ cwd: findHooxSetupRoot(cwd),
75
+ global: globalRepo
76
+ }
77
+ };
78
+ }
79
+ return {
80
+ root: null,
81
+ source: "env",
82
+ checked: {
83
+ env: resolved,
84
+ cwd: findHooxSetupRoot(cwd),
85
+ global: globalRepo
86
+ }
87
+ };
88
+ }
89
+ const local = findHooxSetupRoot(cwd);
90
+ if (local) {
91
+ return {
92
+ root: local,
93
+ source: "cwd",
94
+ checked: { cwd: local, global: globalRepo }
95
+ };
96
+ }
97
+ if (isHooxSetupRoot(globalRepo)) {
98
+ return {
99
+ root: globalRepo,
100
+ source: "global",
101
+ checked: { cwd: null, global: globalRepo }
102
+ };
103
+ }
104
+ return {
105
+ root: null,
106
+ source: "none",
107
+ checked: { cwd: null, global: globalRepo }
108
+ };
109
+ }
110
+ function getTuiEntryCandidates(runtimeRoot) {
111
+ const root = resolve(runtimeRoot);
112
+ return [
113
+ join(root, "packages", "tui", "src", "main.tsx"),
114
+ join(root, "packages", "tui", "dist", "main.js"),
115
+ join(root, "packages", "tui", "src", "main.ts")
116
+ ];
117
+ }
118
+ function resolveHooxPath(relativePath) {
119
+ if (!relativePath || typeof relativePath !== "string") {
120
+ throw new Error("relativePath must be a non-empty string");
121
+ }
122
+ if (relativePath.includes("..")) {
123
+ throw new Error(`Path traversal detected in relativePath: "${relativePath}"`);
124
+ }
125
+ const normalizedPath = relativePath.replace(/\\/g, "/");
126
+ const hooxHome = getHooxHome();
127
+ const fullPath = join(hooxHome, normalizedPath);
128
+ const resolvedPath = resolve(fullPath);
129
+ const resolvedHome = resolve(hooxHome);
130
+ if (!resolvedPath.startsWith(resolvedHome)) {
131
+ throw new Error(`Resolved path "${resolvedPath}" is outside Hoox home directory`);
132
+ }
133
+ return createHooxPath(resolvedPath);
134
+ }
135
+ function isWithinHooxHome(path) {
136
+ try {
137
+ const hooxHome = getHooxHome();
138
+ const resolvedPath = resolve(path);
139
+ const resolvedHome = resolve(hooxHome);
140
+ return resolvedPath.startsWith(resolvedHome);
141
+ } catch {
142
+ return false;
143
+ }
144
+ }
145
+ function getRelativeHooxPath(absolutePath) {
146
+ try {
147
+ if (!isWithinHooxHome(absolutePath)) {
148
+ return null;
149
+ }
150
+ const hooxHome = getHooxHome();
151
+ const resolvedPath = resolve(absolutePath);
152
+ const resolvedHome = resolve(hooxHome);
153
+ const relativePath = resolvedPath.slice(resolvedHome.length);
154
+ return relativePath.startsWith("/") || relativePath.startsWith("\\") ? relativePath.slice(1) : relativePath;
155
+ } catch {
156
+ return null;
157
+ }
158
+ }
159
+ function getHooxRepoPath() {
160
+ return resolveHooxPath("repo");
161
+ }
162
+ function getHooxConfigDir() {
163
+ return resolveHooxPath("config");
164
+ }
165
+ function getHooxDataDir() {
166
+ return resolveHooxPath("data");
167
+ }
168
+ function getHooxWranglerPath() {
169
+ return resolveHooxPath("config/wrangler.jsonc");
170
+ }
171
+ function getHooxStatePath() {
172
+ return resolveHooxPath("data/state.json");
173
+ }
174
+ export {
175
+ resolveHooxRuntimeRoot,
176
+ resolveHooxPath,
177
+ isWithinHooxHome,
178
+ isHooxSetupRoot,
179
+ getTuiEntryCandidates,
180
+ getRelativeHooxPath,
181
+ getHooxWranglerPath,
182
+ getHooxStatePath,
183
+ getHooxRepoPath,
184
+ getHooxHome,
185
+ getHooxDataDir,
186
+ getHooxConfigDir,
187
+ findHooxSetupRoot
188
+ };
@@ -0,0 +1,43 @@
1
+ import type { MessageBatch } from "@cloudflare/workers-types";
2
+ export interface QueueHandlerOptions<T> {
3
+ /** Maximum number of retry attempts */
4
+ maxRetries: number;
5
+ /** Array of delay times in seconds for exponential backoff */
6
+ backoffDelays: number[];
7
+ /** Handler function called for each message */
8
+ onMessage: (message: T, attemptNumber: number) => Promise<unknown> | unknown;
9
+ /** Called when a message fails and will be retried */
10
+ onRetry?: (message: T, attemptNumber: number, error: string, delaySeconds: number) => void | Promise<void>;
11
+ /** Called when message is moved to DLQ (max retries exceeded) */
12
+ onDLQ?: (message: T, attemptNumber: number, error: string) => void | Promise<void>;
13
+ /** Logger function for debugging */
14
+ logger?: {
15
+ info(msg: string, data?: unknown): void;
16
+ error(msg: string, data?: unknown): void;
17
+ };
18
+ }
19
+ /**
20
+ * Creates a reusable queue handler with retry + exponential backoff logic.
21
+ *
22
+ * Usage:
23
+ * ```typescript
24
+ * const handler = createQueueHandler({
25
+ * maxRetries: 5,
26
+ * backoffDelays: [0, 30, 60, 300, 900],
27
+ * onMessage: async (msg) => {
28
+ * await executeTask(msg);
29
+ * },
30
+ * onDLQ: async (msg, attempts, error) => {
31
+ * await logFailedTask(msg, error);
32
+ * }
33
+ * });
34
+ *
35
+ * export default {
36
+ * async queue(batch, env, ctx) {
37
+ * return await handler(batch);
38
+ * }
39
+ * };
40
+ * ```
41
+ */
42
+ export declare function createQueueHandler<T>(options: QueueHandlerOptions<T>): (batch: MessageBatch<T>) => Promise<void>;
43
+ //# sourceMappingURL=queue-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-handler.d.ts","sourceRoot":"","sources":["../src/queue-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,+CAA+C;IAC/C,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7E,sDAAsD;IACtD,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,CAAC,EACV,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,KACjB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,iEAAiE;IACjE,KAAK,CAAC,EAAE,CACN,OAAO,EAAE,CAAC,EACV,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,KACV,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,oCAAoC;IACpC,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QACxC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;KAC1C,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,IAIrD,OAAO,YAAY,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC,CAmCrD"}
@@ -0,0 +1,46 @@
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/queue-handler.ts
19
+ function createQueueHandler(options) {
20
+ const { maxRetries, backoffDelays, onMessage, onRetry, onDLQ, logger } = options;
21
+ return async (batch) => {
22
+ for (const msg of batch.messages) {
23
+ const attemptNumber = msg.attempts || 0;
24
+ const logId = `[${msg.id}]`;
25
+ try {
26
+ logger?.info(`${logId} Processing message (attempt ${attemptNumber + 1})`);
27
+ await onMessage(msg.body, attemptNumber);
28
+ logger?.info(`${logId} Message processed successfully`);
29
+ } catch (error) {
30
+ const errorMsg = error instanceof Error ? error.message : String(error);
31
+ if (attemptNumber < maxRetries) {
32
+ const delaySeconds = backoffDelays[attemptNumber] ?? backoffDelays[backoffDelays.length - 1];
33
+ logger?.info(`${logId} Retrying in ${delaySeconds}s (attempt ${attemptNumber + 2}/${maxRetries + 1})`);
34
+ await onRetry?.(msg.body, attemptNumber, errorMsg, delaySeconds);
35
+ msg.retry({ delaySeconds });
36
+ } else {
37
+ logger?.error(`${logId} Max retries exceeded (${maxRetries + 1} attempts), moving to DLQ`);
38
+ await onDLQ?.(msg.body, attemptNumber, errorMsg);
39
+ }
40
+ }
41
+ }
42
+ };
43
+ }
44
+ export {
45
+ createQueueHandler
46
+ };
package/dist/router.d.ts CHANGED
@@ -6,6 +6,6 @@
6
6
  * Path parameters are extracted and passed as the 4th argument to handlers.
7
7
  */
8
8
  import type { Router } from "./types/router";
9
- export type { Handler, RouteParams } from "./types/router";
10
- export declare function createRouter<TEnv = Record<string, unknown>>(): Router<TEnv>;
9
+ export type { Handler, MiddlewareHandler, RouteParams } from "./types/router";
10
+ export declare function createRouter<TEnv = unknown>(): Router<TEnv>;
11
11
  //# sourceMappingURL=router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAIV,MAAM,EACP,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE3D,wBAAgB,YAAY,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,CAsL3E"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAKV,MAAM,EACP,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE9E,wBAAgB,YAAY,CAAC,IAAI,GAAG,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,CAsM3D"}
package/dist/router.js CHANGED
@@ -52,7 +52,7 @@ function createRouter() {
52
52
  routes.push(route);
53
53
  }
54
54
  function matchRoute(path, method) {
55
- const exact = routes.findLast ? routes.findLast((r) => r.path === path && r.method === method) : [...routes].reverse().find((r) => r.path === path && r.method === method);
55
+ const exact = routes.reduceRight((found, r) => found ?? (r.path === path && r.method === method ? r : null), null);
56
56
  if (exact)
57
57
  return { route: exact };
58
58
  for (let i = routes.length - 1;i >= 0; i--) {
@@ -85,14 +85,20 @@ function createRouter() {
85
85
  const method = request.method;
86
86
  const match = matchRoute(path, method);
87
87
  if (!match) {
88
- const pathExists = routes.some((r) => {
89
- if (r.path === path)
90
- return true;
88
+ let pathExists = false;
89
+ for (let i = routes.length - 1;i >= 0; i--) {
90
+ const r = routes[i];
91
+ if (r.path === path) {
92
+ pathExists = true;
93
+ break;
94
+ }
91
95
  if (r.params && r.params.length > 0 && r.regex) {
92
- return r.regex.test(path);
96
+ if (r.regex.test(path)) {
97
+ pathExists = true;
98
+ break;
99
+ }
93
100
  }
94
- return false;
95
- });
101
+ }
96
102
  if (pathExists) {
97
103
  return new Response(JSON.stringify({
98
104
  success: false,
@@ -114,7 +120,8 @@ function createRouter() {
114
120
  return result;
115
121
  }
116
122
  }
117
- return match.route.handler(request, env, ctx, match.params);
123
+ const handlerResult = await match.route.handler(request, env, ctx, match.params);
124
+ return handlerResult ?? new Response(null, { status: 204 });
118
125
  }
119
126
  };
120
127
  }
@@ -36,7 +36,7 @@ function deriveCalledBy(manifests) {
36
36
  var manifests = {
37
37
  hoox: {
38
38
  name: "hoox",
39
- path: "workers/hoox",
39
+ path: "workers/hoox-worker",
40
40
  vars: {
41
41
  WEBHOOK_API_KEY_BINDING: {
42
42
  type: "secret",
@@ -380,6 +380,7 @@ var manifests = {
380
380
  var CALLED_BY = deriveCalledBy(manifests);
381
381
  var WORKER_MANIFESTS = manifests;
382
382
  var WORKER_NAMES = Object.keys(manifests).sort();
383
+
383
384
  // src/schemas/validators.ts
384
385
  import { parse } from "jsonc-parser";
385
386
  function validateWranglerJsonc(workerName, manifest, jsoncContent) {
@@ -405,7 +406,8 @@ function validateWranglerJsonc(workerName, manifest, jsoncContent) {
405
406
  });
406
407
  return errors;
407
408
  }
408
- const declaredVars = parsed?.vars ?? {};
409
+ const wrangler = parsed;
410
+ const declaredVars = wrangler.vars ?? {};
409
411
  for (const [name, def] of Object.entries(manifest.vars)) {
410
412
  if (!(name in declaredVars)) {
411
413
  errors.push({
@@ -426,7 +428,7 @@ function validateWranglerJsonc(workerName, manifest, jsoncContent) {
426
428
  });
427
429
  }
428
430
  }
429
- const declaredServices = parsed?.services ?? [];
431
+ const declaredServices = wrangler.services ?? [];
430
432
  for (const expected of manifest.services) {
431
433
  const match = declaredServices.find((s) => s.binding === expected.binding && s.service === expected.service);
432
434
  if (!match) {
@@ -482,7 +484,8 @@ function validateRootSecrets(workerName, manifest, rootJsoncContent) {
482
484
  });
483
485
  return errors;
484
486
  }
485
- const rootSecrets = parsed?.workers?.[workerName]?.secrets ?? [];
487
+ const rootWrangler = parsed;
488
+ const rootSecrets = rootWrangler.workers?.[workerName]?.secrets ?? [];
486
489
  const expectedSecrets = Object.entries(manifest.vars).filter(([_, def]) => def.type === "secret").map(([name]) => name);
487
490
  for (const expected of expectedSecrets) {
488
491
  if (!rootSecrets.includes(expected)) {