@hoox-sh/hoox-shared 1.3.0 → 1.5.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 (97) hide show
  1. package/README.md +6 -0
  2. package/dist/agent-config-fields.js +23 -29
  3. package/dist/analytics.d.ts +3 -4
  4. package/dist/analytics.d.ts.map +1 -1
  5. package/dist/analytics.js +56 -16
  6. package/dist/api-client.js +12 -21
  7. package/dist/colors.js +5 -21
  8. package/dist/config.js +11 -27
  9. package/dist/cron-handler.js +0 -16
  10. package/dist/d1/index.js +12 -27
  11. package/dist/d1/repository.js +7 -21
  12. package/dist/d1/schemas.js +4 -20
  13. package/dist/dashboard-manifest.d.ts +2 -1
  14. package/dist/dashboard-manifest.d.ts.map +1 -1
  15. package/dist/dashboard-manifest.js +37 -33
  16. package/dist/entitlements.d.ts +46 -0
  17. package/dist/entitlements.d.ts.map +1 -0
  18. package/dist/entitlements.js +15 -0
  19. package/dist/errors.d.ts.map +1 -1
  20. package/dist/errors.js +11 -25
  21. package/dist/exchange-client.js +2 -18
  22. package/dist/exchanges/base-exchange-client.js +0 -16
  23. package/dist/exchanges/index.js +0 -16
  24. package/dist/format-time.js +2 -18
  25. package/dist/formatters.js +12 -28
  26. package/dist/health.js +7 -21
  27. package/dist/index.d.ts +8 -4
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +3895 -3653
  30. package/dist/kill-switch.js +14 -20
  31. package/dist/kvKeys.d.ts +11 -0
  32. package/dist/kvKeys.d.ts.map +1 -1
  33. package/dist/kvKeys.js +44 -45
  34. package/dist/kvUtils.d.ts +34 -1
  35. package/dist/kvUtils.d.ts.map +1 -1
  36. package/dist/kvUtils.js +60 -23
  37. package/dist/legal.js +5 -21
  38. package/dist/middleware/auth.d.ts +6 -3
  39. package/dist/middleware/auth.d.ts.map +1 -1
  40. package/dist/middleware/auth.js +27 -29
  41. package/dist/middleware/cors.js +4 -20
  42. package/dist/middleware/index.d.ts +3 -2
  43. package/dist/middleware/index.d.ts.map +1 -1
  44. package/dist/middleware/index.js +222 -164
  45. package/dist/middleware/logger.js +13 -27
  46. package/dist/middleware/rate-limit.js +2 -18
  47. package/dist/middleware/security-headers.js +2 -18
  48. package/dist/middleware/validate.d.ts +16 -0
  49. package/dist/middleware/validate.d.ts.map +1 -1
  50. package/dist/middleware/validate.js +39 -19
  51. package/dist/middleware/wait-until.d.ts +32 -0
  52. package/dist/middleware/wait-until.d.ts.map +1 -0
  53. package/dist/middleware/wait-until.js +30 -0
  54. package/dist/operator-transport.js +13 -17
  55. package/dist/path-utils.js +15 -31
  56. package/dist/queue-handler.d.ts +6 -0
  57. package/dist/queue-handler.d.ts.map +1 -1
  58. package/dist/queue-handler.js +51 -36
  59. package/dist/router.d.ts.map +1 -1
  60. package/dist/router.js +12 -18
  61. package/dist/schemas/index.d.ts +2 -1
  62. package/dist/schemas/index.d.ts.map +1 -1
  63. package/dist/schemas/index.js +91 -38
  64. package/dist/schemas/registry.d.ts +13 -0
  65. package/dist/schemas/registry.d.ts.map +1 -1
  66. package/dist/schemas/registry.js +82 -30
  67. package/dist/schemas/types.d.ts +5 -0
  68. package/dist/schemas/types.d.ts.map +1 -1
  69. package/dist/schemas/validators.d.ts.map +1 -1
  70. package/dist/schemas/validators.js +8 -22
  71. package/dist/service-bindings.js +31 -34
  72. package/dist/session.js +2 -18
  73. package/dist/sse.js +10 -18
  74. package/dist/stores/config-store.js +8 -22
  75. package/dist/stores/service-store.js +17 -30
  76. package/dist/stores/ui-store.js +0 -16
  77. package/dist/tenant.d.ts +61 -0
  78. package/dist/tenant.d.ts.map +1 -0
  79. package/dist/tenant.js +56 -0
  80. package/dist/test-utils.js +11 -27
  81. package/dist/types.d.ts +26 -6
  82. package/dist/types.d.ts.map +1 -1
  83. package/dist/types.js +16 -26
  84. package/dist/wizard/engine.d.ts.map +1 -1
  85. package/dist/wizard/engine.js +39 -56
  86. package/dist/wizard/index.d.ts +1 -0
  87. package/dist/wizard/index.d.ts.map +1 -1
  88. package/dist/wizard/index.js +54 -68
  89. package/dist/wizard/persistence.d.ts +4 -0
  90. package/dist/wizard/persistence.d.ts.map +1 -1
  91. package/dist/wizard/persistence.js +7 -19
  92. package/dist/wizard/presets.d.ts.map +1 -1
  93. package/dist/wizard/presets.js +16 -54
  94. package/dist/wizard/types.d.ts +6 -0
  95. package/dist/wizard/types.d.ts.map +1 -1
  96. package/dist/wizard/types.js +5 -0
  97. package/package.json +7 -2
@@ -1,28 +1,14 @@
1
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
2
  // src/errors.ts
19
3
  function toError(err, fallback = "Unknown error") {
20
4
  if (err instanceof Error)
21
5
  return err.message;
22
6
  if (typeof err === "string")
23
7
  return err;
24
- if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
25
- return err.message;
8
+ if (err && typeof err === "object" && "message" in err) {
9
+ const message = err.message;
10
+ if (typeof message === "string")
11
+ return message;
26
12
  }
27
13
  if (err === null || err === undefined)
28
14
  return fallback;
@@ -70,14 +56,14 @@ function sanitizeOutput(data) {
70
56
  const obj = data;
71
57
  const keys = Object.keys(obj);
72
58
  if (keys.length < 10) {
73
- const sanitized2 = {};
59
+ const sanitized = {};
74
60
  for (const k of keys) {
75
61
  if (k === "stack" || k === "cause")
76
62
  continue;
77
63
  const v = obj[k];
78
- sanitized2[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
64
+ sanitized[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
79
65
  }
80
- return sanitized2;
66
+ return sanitized;
81
67
  }
82
68
  if (!hasSensitiveFields(obj) && !hasErrorValues(obj)) {
83
69
  return obj;
@@ -141,6 +127,61 @@ var Errors = {
141
127
  }
142
128
  };
143
129
 
130
+ // src/middleware/logger.ts
131
+ function createLogger(ctx) {
132
+ const base = { service: ctx.service, module: ctx.module };
133
+ function emit(level, message, context) {
134
+ const entry = {
135
+ level,
136
+ timestamp: new Date().toISOString(),
137
+ ...base,
138
+ message,
139
+ ...context && { context }
140
+ };
141
+ const line = JSON.stringify(entry);
142
+ if (level === "error")
143
+ console.error(line);
144
+ else if (level === "warn")
145
+ console.warn(line);
146
+ else if (level === "debug")
147
+ console.debug(line);
148
+ else
149
+ console.info(line);
150
+ }
151
+ return {
152
+ debug: (msg, ctx) => emit("debug", msg, ctx),
153
+ info: (msg, ctx) => emit("info", msg, ctx),
154
+ warn: (msg, ctx) => emit("warn", msg, ctx),
155
+ error: (msg, ctx) => emit("error", msg, ctx)
156
+ };
157
+ }
158
+ function withRequestLog(handler, logCtx) {
159
+ return async (request, env, ctx) => {
160
+ const start = Date.now();
161
+ const logger = createLogger(logCtx);
162
+ try {
163
+ const response = await handler(request, env, ctx);
164
+ const duration = Date.now() - start;
165
+ const url = new URL(request.url);
166
+ logger.info(`${request.method} ${url.pathname}`, {
167
+ method: request.method,
168
+ path: url.pathname,
169
+ status: response.status,
170
+ durationMs: duration
171
+ });
172
+ return response;
173
+ } catch (error) {
174
+ const duration = Date.now() - start;
175
+ logger.error("Request failed", {
176
+ method: request.method,
177
+ path: new URL(request.url).pathname,
178
+ durationMs: duration,
179
+ error: toError(error)
180
+ });
181
+ throw error;
182
+ }
183
+ };
184
+ }
144
185
  // src/middleware/auth.ts
145
186
  function timingSafeEqual(a, b) {
146
187
  const encoder = new TextEncoder;
@@ -149,12 +190,24 @@ function timingSafeEqual(a, b) {
149
190
  const len = Math.max(aBuf.length, bBuf.length);
150
191
  let result = aBuf.length === bBuf.length ? 0 : 1;
151
192
  for (let i = 0;i < len; i++) {
152
- const av = i < aBuf.length ? aBuf[i] : 0;
153
- const bv = i < bBuf.length ? bBuf[i] : 0;
193
+ const av = aBuf[i] ?? 0;
194
+ const bv = bBuf[i] ?? 0;
154
195
  result |= av ^ bv;
155
196
  }
156
197
  return result === 0;
157
198
  }
199
+ async function timingSafeEqualAsync(a, b) {
200
+ const subtle = globalThis.crypto?.subtle;
201
+ if (!subtle || typeof subtle.digest !== "function" || typeof subtle.timingSafeEqual !== "function") {
202
+ return timingSafeEqual(a, b);
203
+ }
204
+ const encoder = new TextEncoder;
205
+ const [providedHash, expectedHash] = await Promise.all([
206
+ subtle.digest("SHA-256", encoder.encode(a)),
207
+ subtle.digest("SHA-256", encoder.encode(b))
208
+ ]);
209
+ return subtle.timingSafeEqual(providedHash, expectedHash);
210
+ }
158
211
  function resolveOperatorApiKey(env) {
159
212
  const preferred = env.OPERATOR_API_KEY;
160
213
  if (typeof preferred === "string" && preferred.length > 0) {
@@ -179,7 +232,7 @@ async function requireOperatorAuth(request, env) {
179
232
  }
180
233
  const authHeader = request.headers.get("Authorization");
181
234
  const expectedHeader = `Bearer ${apiKey}`;
182
- if (!authHeader || !timingSafeEqual(authHeader, expectedHeader)) {
235
+ if (!authHeader || !await timingSafeEqualAsync(authHeader, expectedHeader)) {
183
236
  return new Response(JSON.stringify({ error: "Unauthorized" }), {
184
237
  status: 401,
185
238
  headers: { "Content-Type": "application/json" }
@@ -212,12 +265,13 @@ function collectInternalAuthKeys(env, keyNames) {
212
265
  return keys;
213
266
  }
214
267
  function matchesAnyInternalAuthKey(providedKey, expectedKeys) {
268
+ let matched = false;
215
269
  for (const expected of expectedKeys) {
216
270
  if (timingSafeEqual(providedKey, expected)) {
217
- return true;
271
+ matched = true;
218
272
  }
219
273
  }
220
- return false;
274
+ return matched;
221
275
  }
222
276
  function internalAuthNotConfiguredResponse(keyNames) {
223
277
  const label = normalizeKeyNames(keyNames).join(" | ");
@@ -264,117 +318,6 @@ function checkInternalAuth(request, env, keyName = "INTERNAL_KEY_BINDING") {
264
318
  }
265
319
  return { authorized: true };
266
320
  }
267
-
268
- // src/middleware/cors.ts
269
- var DEFAULT_OPTIONS = {
270
- allowOrigin: "",
271
- allowMethods: "GET, POST, OPTIONS, PUT, DELETE",
272
- allowHeaders: "Content-Type, Authorization, X-Request-ID",
273
- allowCredentials: false,
274
- maxAge: 86400
275
- };
276
- function corsHeaders(options) {
277
- const opts = { ...DEFAULT_OPTIONS, ...options };
278
- const headers = {
279
- "Access-Control-Allow-Methods": opts.allowMethods,
280
- "Access-Control-Allow-Headers": opts.allowHeaders,
281
- "Access-Control-Max-Age": String(opts.maxAge)
282
- };
283
- if (opts.allowOrigin) {
284
- headers["Access-Control-Allow-Origin"] = opts.allowOrigin;
285
- }
286
- if (opts.allowCredentials) {
287
- headers["Access-Control-Allow-Credentials"] = "true";
288
- }
289
- return headers;
290
- }
291
- function publicCorsHeaders(origin = "*", options) {
292
- return corsHeaders({ ...options, allowOrigin: origin });
293
- }
294
- function internalCorsHeaders() {
295
- return {};
296
- }
297
- function resolveCorsOptions(request, env) {
298
- const raw = env && typeof env === "object" && "CORS_ALLOW_ORIGIN" in env && typeof env.CORS_ALLOW_ORIGIN === "string" ? env.CORS_ALLOW_ORIGIN : undefined;
299
- const configured = raw?.trim();
300
- if (!configured) {
301
- return {};
302
- }
303
- const allowed = configured.split(",").map((entry) => entry.trim()).filter(Boolean);
304
- const origin = request.headers.get("Origin");
305
- if (origin && allowed.includes(origin)) {
306
- return { allowOrigin: origin, allowCredentials: true };
307
- }
308
- if (!origin && allowed.length === 1) {
309
- return { allowOrigin: allowed[0] };
310
- }
311
- return {};
312
- }
313
- function handleCorsPreflightRequest(request, options) {
314
- if (request.method !== "OPTIONS")
315
- return null;
316
- return new Response(null, {
317
- status: 204,
318
- headers: corsHeaders(options)
319
- });
320
- }
321
-
322
- // src/middleware/logger.ts
323
- function createLogger(ctx) {
324
- const base = { service: ctx.service, module: ctx.module };
325
- function emit(level, message, context) {
326
- const entry = {
327
- level,
328
- timestamp: new Date().toISOString(),
329
- ...base,
330
- message,
331
- ...context && { context }
332
- };
333
- const line = JSON.stringify(entry);
334
- if (level === "error")
335
- console.error(line);
336
- else if (level === "warn")
337
- console.warn(line);
338
- else if (level === "debug")
339
- console.debug(line);
340
- else
341
- console.info(line);
342
- }
343
- return {
344
- debug: (msg, ctx2) => emit("debug", msg, ctx2),
345
- info: (msg, ctx2) => emit("info", msg, ctx2),
346
- warn: (msg, ctx2) => emit("warn", msg, ctx2),
347
- error: (msg, ctx2) => emit("error", msg, ctx2)
348
- };
349
- }
350
- function withRequestLog(handler, logCtx) {
351
- return async (request, env, ctx) => {
352
- const start = Date.now();
353
- const logger = createLogger(logCtx);
354
- try {
355
- const response = await handler(request, env, ctx);
356
- const duration = Date.now() - start;
357
- const url = new URL(request.url);
358
- logger.info(`${request.method} ${url.pathname}`, {
359
- method: request.method,
360
- path: url.pathname,
361
- status: response.status,
362
- durationMs: duration
363
- });
364
- return response;
365
- } catch (error) {
366
- const duration = Date.now() - start;
367
- logger.error("Request failed", {
368
- method: request.method,
369
- path: new URL(request.url).pathname,
370
- durationMs: duration,
371
- error: toError(error)
372
- });
373
- throw error;
374
- }
375
- };
376
- }
377
-
378
321
  // src/middleware/rate-limit.ts
379
322
  function createStorage(kv) {
380
323
  if (!kv) {
@@ -429,8 +372,8 @@ function createStorage(kv) {
429
372
  attempts++;
430
373
  if (attempts >= maxAttempts) {
431
374
  const current = await this.get(key);
432
- const count2 = current ? parseInt(current, 10) : 0;
433
- newValue = count2 + 1;
375
+ const count = current ? parseInt(current, 10) : 0;
376
+ newValue = count + 1;
434
377
  const ttl = opts?.expirationTtl ?? 0;
435
378
  const expiresAt = ttl > 0 ? Date.now() + ttl * 1000 : Infinity;
436
379
  memory.set(key, { value: String(newValue), expiresAt });
@@ -536,8 +479,8 @@ function createRateLimiter(kv, config) {
536
479
  }
537
480
  return { check, enforce, checkKey, enforceKey };
538
481
  }
539
-
540
482
  // src/middleware/validate.ts
483
+ var DEFAULT_MAX_JSON_BODY_BYTES = 1048576;
541
484
  function validateJson(schema, data) {
542
485
  const result = schema.safeParse(data);
543
486
  if (!result.success) {
@@ -548,6 +491,39 @@ function validateJson(schema, data) {
548
491
  }
549
492
  return { ok: true, value: result.data };
550
493
  }
494
+ async function parseJsonBody(request, schema, options = {}) {
495
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_JSON_BODY_BYTES;
496
+ const contentLength = request.headers.get("content-length");
497
+ if (contentLength !== null) {
498
+ const declared = Number(contentLength);
499
+ if (Number.isFinite(declared) && declared > maxBytes) {
500
+ return {
501
+ ok: false,
502
+ error: `Request body too large (max ${maxBytes} bytes)`
503
+ };
504
+ }
505
+ }
506
+ let text;
507
+ try {
508
+ text = await request.text();
509
+ } catch {
510
+ return { ok: false, error: "Failed to read request body" };
511
+ }
512
+ const byteLength = new TextEncoder().encode(text).byteLength;
513
+ if (byteLength > maxBytes) {
514
+ return {
515
+ ok: false,
516
+ error: `Request body too large (max ${maxBytes} bytes)`
517
+ };
518
+ }
519
+ let data;
520
+ try {
521
+ data = text.length === 0 ? null : JSON.parse(text);
522
+ } catch {
523
+ return { ok: false, error: "Invalid JSON in request body" };
524
+ }
525
+ return validateJson(schema, data);
526
+ }
551
527
  async function validateJsonLegacy(request) {
552
528
  try {
553
529
  const body = await request.json();
@@ -570,7 +546,84 @@ function optionalField(body, field, defaultValue) {
570
546
  return defaultValue;
571
547
  return body[field];
572
548
  }
573
-
549
+ // src/middleware/wait-until.ts
550
+ function safeWaitUntil(ctx, promise, onError) {
551
+ ctx.waitUntil(promise.catch((err) => {
552
+ onError?.(err);
553
+ console.error(JSON.stringify({
554
+ message: "waitUntil background task failed",
555
+ error: err instanceof Error ? err.message : String(err)
556
+ }));
557
+ }));
558
+ }
559
+ function waitUntilAll(ctx, promises, onError) {
560
+ if (promises.length === 0)
561
+ return;
562
+ safeWaitUntil(ctx, Promise.allSettled(promises).then((results) => {
563
+ for (const result of results) {
564
+ if (result.status === "rejected") {
565
+ onError?.(result.reason);
566
+ console.error(JSON.stringify({
567
+ message: "waitUntilAll background task failed",
568
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason)
569
+ }));
570
+ }
571
+ }
572
+ }), onError);
573
+ }
574
+ // src/middleware/cors.ts
575
+ var DEFAULT_OPTIONS = {
576
+ allowOrigin: "",
577
+ allowMethods: "GET, POST, OPTIONS, PUT, DELETE",
578
+ allowHeaders: "Content-Type, Authorization, X-Request-ID",
579
+ allowCredentials: false,
580
+ maxAge: 86400
581
+ };
582
+ function corsHeaders(options) {
583
+ const opts = { ...DEFAULT_OPTIONS, ...options };
584
+ const headers = {
585
+ "Access-Control-Allow-Methods": opts.allowMethods,
586
+ "Access-Control-Allow-Headers": opts.allowHeaders,
587
+ "Access-Control-Max-Age": String(opts.maxAge)
588
+ };
589
+ if (opts.allowOrigin) {
590
+ headers["Access-Control-Allow-Origin"] = opts.allowOrigin;
591
+ }
592
+ if (opts.allowCredentials) {
593
+ headers["Access-Control-Allow-Credentials"] = "true";
594
+ }
595
+ return headers;
596
+ }
597
+ function publicCorsHeaders(origin = "*", options) {
598
+ return corsHeaders({ ...options, allowOrigin: origin });
599
+ }
600
+ function internalCorsHeaders() {
601
+ return {};
602
+ }
603
+ function resolveCorsOptions(request, env) {
604
+ const raw = env && typeof env === "object" && "CORS_ALLOW_ORIGIN" in env && typeof env.CORS_ALLOW_ORIGIN === "string" ? env.CORS_ALLOW_ORIGIN : undefined;
605
+ const configured = raw?.trim();
606
+ if (!configured) {
607
+ return {};
608
+ }
609
+ const allowed = configured.split(",").map((entry) => entry.trim()).filter(Boolean);
610
+ const origin = request.headers.get("Origin");
611
+ if (origin && allowed.includes(origin)) {
612
+ return { allowOrigin: origin, allowCredentials: true };
613
+ }
614
+ if (!origin && allowed.length === 1) {
615
+ return { allowOrigin: allowed[0] };
616
+ }
617
+ return {};
618
+ }
619
+ function handleCorsPreflightRequest(request, options) {
620
+ if (request.method !== "OPTIONS")
621
+ return null;
622
+ return new Response(null, {
623
+ status: 204,
624
+ headers: corsHeaders(options)
625
+ });
626
+ }
574
627
  // src/middleware/security-headers.ts
575
628
  var SECURITY_HEADERS_DEFAULTS = {
576
629
  xContentTypeOptions: "nosniff",
@@ -608,28 +661,33 @@ function wrapWithSecurityHeaders(response, options) {
608
661
  });
609
662
  }
610
663
  export {
611
- wrapWithSecurityHeaders,
612
- withRequestLog,
613
- validateJsonLegacy,
614
- validateJson,
615
- timingSafeEqual,
616
- secureHeaders,
617
- resolveOperatorApiKey,
618
- resolveCorsOptions,
619
- requireOperatorAuth,
620
- requireInternalAuth,
621
- requireField,
622
- requireAuth,
623
- publicCorsHeaders,
624
- optionalField,
625
- internalCorsHeaders,
626
- handleCorsPreflightRequest,
627
- createRateLimiter,
628
- createOperatorAuthMiddleware,
629
- createLogger,
630
- createInternalAuthMiddleware,
631
- corsHeaders,
632
- collectInternalAuthKeys,
664
+ DEFAULT_MAX_JSON_BODY_BYTES,
665
+ SECURITY_HEADERS_DEFAULTS,
633
666
  checkInternalAuth,
634
- SECURITY_HEADERS_DEFAULTS
667
+ collectInternalAuthKeys,
668
+ corsHeaders,
669
+ createInternalAuthMiddleware,
670
+ createLogger,
671
+ createOperatorAuthMiddleware,
672
+ createRateLimiter,
673
+ handleCorsPreflightRequest,
674
+ internalCorsHeaders,
675
+ optionalField,
676
+ parseJsonBody,
677
+ publicCorsHeaders,
678
+ requireAuth,
679
+ requireField,
680
+ requireInternalAuth,
681
+ requireOperatorAuth,
682
+ resolveCorsOptions,
683
+ resolveOperatorApiKey,
684
+ safeWaitUntil,
685
+ secureHeaders,
686
+ timingSafeEqual,
687
+ timingSafeEqualAsync,
688
+ validateJson,
689
+ validateJsonLegacy,
690
+ waitUntilAll,
691
+ withRequestLog,
692
+ wrapWithSecurityHeaders
635
693
  };
@@ -1,28 +1,14 @@
1
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
2
  // src/errors.ts
19
3
  function toError(err, fallback = "Unknown error") {
20
4
  if (err instanceof Error)
21
5
  return err.message;
22
6
  if (typeof err === "string")
23
7
  return err;
24
- if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
25
- return err.message;
8
+ if (err && typeof err === "object" && "message" in err) {
9
+ const message = err.message;
10
+ if (typeof message === "string")
11
+ return message;
26
12
  }
27
13
  if (err === null || err === undefined)
28
14
  return fallback;
@@ -70,14 +56,14 @@ function sanitizeOutput(data) {
70
56
  const obj = data;
71
57
  const keys = Object.keys(obj);
72
58
  if (keys.length < 10) {
73
- const sanitized2 = {};
59
+ const sanitized = {};
74
60
  for (const k of keys) {
75
61
  if (k === "stack" || k === "cause")
76
62
  continue;
77
63
  const v = obj[k];
78
- sanitized2[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
64
+ sanitized[k] = v instanceof Error ? { name: v.name, message: v.message } : sanitizeOutput(v);
79
65
  }
80
- return sanitized2;
66
+ return sanitized;
81
67
  }
82
68
  if (!hasSensitiveFields(obj) && !hasErrorValues(obj)) {
83
69
  return obj;
@@ -163,10 +149,10 @@ function createLogger(ctx) {
163
149
  console.info(line);
164
150
  }
165
151
  return {
166
- debug: (msg, ctx2) => emit("debug", msg, ctx2),
167
- info: (msg, ctx2) => emit("info", msg, ctx2),
168
- warn: (msg, ctx2) => emit("warn", msg, ctx2),
169
- error: (msg, ctx2) => emit("error", msg, ctx2)
152
+ debug: (msg, ctx) => emit("debug", msg, ctx),
153
+ info: (msg, ctx) => emit("info", msg, ctx),
154
+ warn: (msg, ctx) => emit("warn", msg, ctx),
155
+ error: (msg, ctx) => emit("error", msg, ctx)
170
156
  };
171
157
  }
172
158
  function withRequestLog(handler, logCtx) {
@@ -197,6 +183,6 @@ function withRequestLog(handler, logCtx) {
197
183
  };
198
184
  }
199
185
  export {
200
- withRequestLog,
201
- createLogger
186
+ createLogger,
187
+ withRequestLog
202
188
  };
@@ -1,20 +1,4 @@
1
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
2
  // src/middleware/rate-limit.ts
19
3
  function createStorage(kv) {
20
4
  if (!kv) {
@@ -69,8 +53,8 @@ function createStorage(kv) {
69
53
  attempts++;
70
54
  if (attempts >= maxAttempts) {
71
55
  const current = await this.get(key);
72
- const count2 = current ? parseInt(current, 10) : 0;
73
- newValue = count2 + 1;
56
+ const count = current ? parseInt(current, 10) : 0;
57
+ newValue = count + 1;
74
58
  const ttl = opts?.expirationTtl ?? 0;
75
59
  const expiresAt = ttl > 0 ? Date.now() + ttl * 1000 : Infinity;
76
60
  memory.set(key, { value: String(newValue), expiresAt });
@@ -1,20 +1,4 @@
1
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
2
  // src/middleware/security-headers.ts
19
3
  var SECURITY_HEADERS_DEFAULTS = {
20
4
  xContentTypeOptions: "nosniff",
@@ -52,7 +36,7 @@ function wrapWithSecurityHeaders(response, options) {
52
36
  });
53
37
  }
54
38
  export {
55
- wrapWithSecurityHeaders,
39
+ SECURITY_HEADERS_DEFAULTS,
56
40
  secureHeaders,
57
- SECURITY_HEADERS_DEFAULTS
41
+ wrapWithSecurityHeaders
58
42
  };
@@ -10,11 +10,27 @@
10
10
  */
11
11
  import { z } from "zod";
12
12
  import type { Result } from "../types";
13
+ /** Default body size cap for JSON request parsing (1 MiB). */
14
+ export declare const DEFAULT_MAX_JSON_BODY_BYTES = 1048576;
15
+ export interface ParseJsonBodyOptions {
16
+ /** Reject bodies larger than this many bytes (Content-Length or measured). */
17
+ maxBytes?: number;
18
+ }
13
19
  /**
14
20
  * Validate unknown data against a Zod schema, returning a Result type.
15
21
  * Provides structured error messages from Zod issue paths.
16
22
  */
17
23
  export declare function validateJson<T extends z.ZodTypeAny>(schema: T, data: unknown): Result<z.infer<T>>;
24
+ /**
25
+ * Parse a Request body as JSON and validate against a Zod schema.
26
+ * Enforces an optional max body size to stay within Workers memory limits.
27
+ *
28
+ * @example
29
+ * const parsed = await parseJsonBody(request, WebhookPayloadSchema);
30
+ * if (!parsed.ok) return Errors.badRequest(parsed.error);
31
+ * const payload = parsed.value;
32
+ */
33
+ export declare function parseJsonBody<T extends z.ZodTypeAny>(request: Request, schema: T, options?: ParseJsonBodyOptions): Promise<Result<z.infer<T>>>;
18
34
  /**
19
35
  * Legacy signature: parse request body as JSON object.
20
36
  * Kept for backward compatibility with existing workers.
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/middleware/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EACjD,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAWpB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAU1C;AAED,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,CAAC,CAAC,CAKX;AAED,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,CAAC,GACd,CAAC,CAGH"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/middleware/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,8DAA8D;AAC9D,eAAO,MAAM,2BAA2B,UAAY,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EACjD,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAWpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EACxD,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAsC7B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAU1C;AAED,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,CAAC,CAAC,CAKX;AAED,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,CAAC,GACd,CAAC,CAGH"}