stitchkit 0.1.0 → 0.3.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 (84) hide show
  1. package/README.md +10 -7
  2. package/dist/browser/http.d.ts +5 -0
  3. package/dist/browser/http.d.ts.map +1 -1
  4. package/dist/contract/define.d.ts.map +1 -1
  5. package/dist/contract/errors.d.ts +4 -3
  6. package/dist/contract/errors.d.ts.map +1 -1
  7. package/dist/contract/index.js +1 -1
  8. package/dist/{index-gfzn1n4n.js → index-0t460v7k.js} +13 -5
  9. package/dist/{index-n7bmdwmz.js → index-4b1j82gp.js} +8 -4
  10. package/dist/{index-5sxnvwb1.js → index-4kz3aqpx.js} +2 -2
  11. package/dist/index-dpj1jcys.js +677 -0
  12. package/dist/{index-7wfkbvss.js → index-kckky6zw.js} +6 -2
  13. package/dist/index-kzfs85xp.js +9 -0
  14. package/dist/index-mwmpw6j1.js +60 -0
  15. package/dist/index-q6ja2qwq.js +7 -0
  16. package/dist/index.js +4 -3
  17. package/dist/internal/errors.d.ts +13 -1
  18. package/dist/internal/errors.d.ts.map +1 -1
  19. package/dist/internal/safe-json.d.ts +19 -0
  20. package/dist/internal/safe-json.d.ts.map +1 -0
  21. package/dist/internal/within-dir.d.ts +7 -0
  22. package/dist/internal/within-dir.d.ts.map +1 -0
  23. package/dist/node.d.ts +4 -0
  24. package/dist/node.d.ts.map +1 -0
  25. package/dist/node.js +29 -0
  26. package/dist/observability/context.d.ts +9 -1
  27. package/dist/observability/context.d.ts.map +1 -1
  28. package/dist/observability/index.js +35 -15
  29. package/dist/observability/sanitize.d.ts.map +1 -1
  30. package/dist/server/context.d.ts +3 -2
  31. package/dist/server/context.d.ts.map +1 -1
  32. package/dist/server/create.d.ts +3 -3
  33. package/dist/server/create.d.ts.map +1 -1
  34. package/dist/server/event-bus.d.ts +10 -1
  35. package/dist/server/event-bus.d.ts.map +1 -1
  36. package/dist/server/index.d.ts +2 -2
  37. package/dist/server/index.d.ts.map +1 -1
  38. package/dist/server/index.js +94 -606
  39. package/dist/server/logger.d.ts +5 -4
  40. package/dist/server/logger.d.ts.map +1 -1
  41. package/dist/server/middleware/auth.d.ts +24 -1
  42. package/dist/server/middleware/auth.d.ts.map +1 -1
  43. package/dist/server/middleware/cookies.d.ts.map +1 -1
  44. package/dist/server/middleware/cors.d.ts +7 -0
  45. package/dist/server/middleware/cors.d.ts.map +1 -1
  46. package/dist/server/multipart.d.ts +2 -1
  47. package/dist/server/multipart.d.ts.map +1 -1
  48. package/dist/server/node.d.ts +12 -0
  49. package/dist/server/node.d.ts.map +1 -0
  50. package/dist/server/rate-limit.d.ts +7 -2
  51. package/dist/server/rate-limit.d.ts.map +1 -1
  52. package/dist/server/request.d.ts +27 -4
  53. package/dist/server/request.d.ts.map +1 -1
  54. package/dist/server/router.d.ts +4 -2
  55. package/dist/server/router.d.ts.map +1 -1
  56. package/dist/server/stream.d.ts +3 -1
  57. package/dist/server/stream.d.ts.map +1 -1
  58. package/dist/server/types.d.ts +35 -20
  59. package/dist/server/types.d.ts.map +1 -1
  60. package/dist/tools/agent.d.ts +15 -2
  61. package/dist/tools/agent.d.ts.map +1 -1
  62. package/dist/tools/coerce.d.ts +12 -0
  63. package/dist/tools/coerce.d.ts.map +1 -0
  64. package/dist/tools/execute.d.ts +26 -2
  65. package/dist/tools/execute.d.ts.map +1 -1
  66. package/dist/tools/flatten.d.ts +15 -0
  67. package/dist/tools/flatten.d.ts.map +1 -0
  68. package/dist/tools/json-schema.d.ts +18 -0
  69. package/dist/tools/json-schema.d.ts.map +1 -0
  70. package/dist/tools/manifest.d.ts +17 -0
  71. package/dist/tools/manifest.d.ts.map +1 -0
  72. package/dist/tools/mcp-handler.d.ts.map +1 -1
  73. package/dist/tools/mcp.d.ts +53 -3
  74. package/dist/tools/mcp.d.ts.map +1 -1
  75. package/dist/tools/mount.d.ts +18 -6
  76. package/dist/tools/mount.d.ts.map +1 -1
  77. package/dist/tools/schema.d.ts +19 -2
  78. package/dist/tools/schema.d.ts.map +1 -1
  79. package/dist/tools/view-file.d.ts.map +1 -1
  80. package/dist/tools.d.ts +6 -2
  81. package/dist/tools.d.ts.map +1 -1
  82. package/dist/tools.js +415 -185
  83. package/package.json +15 -4
  84. package/dist/index-ke4mx4ea.js +0 -38
@@ -0,0 +1,60 @@
1
+ import {
2
+ isUnsafeKey
3
+ } from "./index-kzfs85xp.js";
4
+ import {
5
+ isRecord
6
+ } from "./index-809wc1tt.js";
7
+
8
+ // src/server/request.ts
9
+ function generateTraceId() {
10
+ return `${Date.now().toString(36)}-${crypto.randomUUID().slice(0, 8)}`;
11
+ }
12
+ function resolveTraceId(req) {
13
+ const header = req.headers.get("x-request-id") ?? req.headers.get("x-trace-id");
14
+ const trimmed = header?.trim();
15
+ if (trimmed && trimmed.length <= 128 && /^[\w.-]+$/.test(trimmed)) {
16
+ return trimmed;
17
+ }
18
+ return generateTraceId();
19
+ }
20
+ function resolveSocketIp(req, server) {
21
+ if (typeof server === "object" && server !== null && "requestIP" in server && typeof server.requestIP === "function") {
22
+ const addr = server.requestIP(req);
23
+ if (isRecord(addr) && typeof addr.address === "string" && addr.address) {
24
+ return addr.address;
25
+ }
26
+ }
27
+ if ("ip" in req && typeof req.ip === "string" && req.ip)
28
+ return req.ip;
29
+ return;
30
+ }
31
+ function extractIp(req, options = {}) {
32
+ if (options.trustProxy) {
33
+ const forwarded = req.headers.get("x-forwarded-for");
34
+ if (forwarded)
35
+ return (forwarded.split(",")[0] ?? "").trim().replace(/^::ffff:/, "");
36
+ const realIp = req.headers.get("x-real-ip");
37
+ if (realIp)
38
+ return realIp.trim().replace(/^::ffff:/, "");
39
+ }
40
+ return (options.socketIp ?? "").replace(/^::ffff:/, "");
41
+ }
42
+ function getClientInfo(req, options = {}) {
43
+ return {
44
+ ipAddress: extractIp(req, options) || undefined,
45
+ userAgent: req.headers.get("user-agent") ?? undefined
46
+ };
47
+ }
48
+ function parseQueryParams(url) {
49
+ const query = {};
50
+ for (const key of new Set(url.searchParams.keys())) {
51
+ if (isUnsafeKey(key))
52
+ continue;
53
+ const values = url.searchParams.getAll(key);
54
+ const [first] = values;
55
+ query[key] = values.length === 1 && first !== undefined ? first : values;
56
+ }
57
+ return query;
58
+ }
59
+
60
+ export { generateTraceId, resolveTraceId, resolveSocketIp, extractIp, getClientInfo, parseQueryParams };
@@ -0,0 +1,7 @@
1
+ // src/internal/within-dir.ts
2
+ import { sep } from "node:path";
3
+ function isWithinDir(root, target) {
4
+ return target === root || target.startsWith(root + sep);
5
+ }
6
+
7
+ export { isWithinDir };
package/dist/index.js CHANGED
@@ -3,10 +3,11 @@ import {
3
3
  createClient,
4
4
  createClients,
5
5
  createHttpClient
6
- } from "./index-5sxnvwb1.js";
6
+ } from "./index-4kz3aqpx.js";
7
7
  import {
8
8
  parseSSE
9
- } from "./index-n7bmdwmz.js";
9
+ } from "./index-4b1j82gp.js";
10
+ import"./index-0t460v7k.js";
10
11
  import {
11
12
  ALL_TRANSPORTS,
12
13
  AppError,
@@ -19,7 +20,7 @@ import {
19
20
  paginatedSchema,
20
21
  rateLimited,
21
22
  unauthorized
22
- } from "./index-7wfkbvss.js";
23
+ } from "./index-kckky6zw.js";
23
24
  import"./index-809wc1tt.js";
24
25
  // src/browser/socket-io.ts
25
26
  import { io } from "socket.io-client";
@@ -1,5 +1,17 @@
1
- import { z } from 'zod';
1
+ import { type ZodType, z } from 'zod';
2
2
  import { AppError } from '../contract';
3
3
  export declare function formatZodError(error: z.ZodError): string;
4
4
  export declare function normalizeError(err: unknown): AppError;
5
+ /**
6
+ * Validate a handler's return value against the contract `output` schema. A
7
+ * mismatch is a **server** fault (the handler broke its own contract) — shared
8
+ * by the HTTP and tool transports so both report it identically.
9
+ */
10
+ export declare function validateHandlerOutput(schema: ZodType, data: unknown): {
11
+ ok: true;
12
+ data: unknown;
13
+ } | {
14
+ ok: false;
15
+ message: string;
16
+ };
5
17
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CASxD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAWrD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CASxD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAYrD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,GACZ;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAO9D"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Prototype-pollution defence for untrusted input. Assigning a `__proto__` key
3
+ * onto a plain object (`obj[key] = value`, a JSON reviver, a merge) invokes the
4
+ * `__proto__` setter and rewires the prototype chain — the single real
5
+ * pollution vector at an assignment boundary. `constructor` / `prototype` as
6
+ * plain own keys are inert (they shadow, they do not poison), so they are NOT
7
+ * stripped — dropping them would silently corrupt legitimate data fields.
8
+ *
9
+ * Every boundary that ingests client-controlled keys (JSON bodies, query
10
+ * strings, cookies, multipart fields, tool arguments) routes through here.
11
+ */
12
+ /** True for a key that must never be copied onto a plain object from untrusted input. */
13
+ export declare function isUnsafeKey(key: string): boolean;
14
+ /**
15
+ * `JSON.parse` that strips the `__proto__` key from the result. Throws on
16
+ * invalid JSON, exactly like `JSON.parse` — callers handle that as a 400.
17
+ */
18
+ export declare function safeJsonParse(text: string): unknown;
19
+ //# sourceMappingURL=safe-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-json.d.ts","sourceRoot":"","sources":["../../src/internal/safe-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * True when `target` (an already-`resolve`d absolute path) stays inside `root`.
3
+ * Blocks `..`, absolute and otherwise-escaping paths — the shared containment
4
+ * check behind `staticRoute` and `view_file`'s local-file branch.
5
+ */
6
+ export declare function isWithinDir(root: string, target: string): boolean;
7
+ //# sourceMappingURL=within-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"within-dir.d.ts","sourceRoot":"","sources":["../../src/internal/within-dir.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { createHandler } from './server/create';
2
+ export { type NodeServerConfig, type NodeServerHandle, serveNode } from './server/node';
3
+ export type { HandlerConfig } from './server/types';
4
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACxF,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/node.js ADDED
@@ -0,0 +1,29 @@
1
+ import {
2
+ createHandler
3
+ } from "./index-dpj1jcys.js";
4
+ import"./index-q6ja2qwq.js";
5
+ import"./index-0t460v7k.js";
6
+ import"./index-kckky6zw.js";
7
+ import"./index-mwmpw6j1.js";
8
+ import"./index-kzfs85xp.js";
9
+ import"./index-809wc1tt.js";
10
+ // src/server/node.ts
11
+ import { serve } from "srvx";
12
+ async function serveNode(config) {
13
+ const { port = 3000, hostname, ...handlerConfig } = config;
14
+ const handler = createHandler(handlerConfig);
15
+ const server = serve({ port, hostname, fetch: handler });
16
+ await server.ready();
17
+ const listenUrl = server.url ?? `http://${hostname ?? "localhost"}:${port}`;
18
+ const resolvedPort = Number(new URL(listenUrl).port) || port;
19
+ const resolvedHost = hostname ?? "localhost";
20
+ return {
21
+ url: `http://${resolvedHost}:${resolvedPort}`,
22
+ port: resolvedPort,
23
+ close: (closeActive) => server.close(closeActive)
24
+ };
25
+ }
26
+ export {
27
+ serveNode,
28
+ createHandler
29
+ };
@@ -46,6 +46,14 @@ export declare function setRequestError(error: {
46
46
  code?: string;
47
47
  message?: string;
48
48
  }): void;
49
+ /** Options for `wrapInRequestContext`. */
50
+ export interface WrapRequestContextOptions {
51
+ /**
52
+ * Trust `x-forwarded-for` for the client IP — enable only behind a proxy
53
+ * that rewrites it. Default `false`: the real socket peer IP is used.
54
+ */
55
+ trustProxy?: boolean;
56
+ }
49
57
  /**
50
58
  * Wrap a fetch handler so it runs inside a fresh `RequestContext` — trace ids
51
59
  * (the inbound `traceparent` continued, or freshly minted), timing and client
@@ -56,5 +64,5 @@ export declare function setRequestError(error: {
56
64
  * logs share one id), pass `traceId: getTraceId` to `createServer` /
57
65
  * `createHandler`.
58
66
  */
59
- export declare function wrapInRequestContext<S>(handler: (req: Request, server: S) => Promise<Response>): (req: Request, server: S) => Promise<Response>;
67
+ export declare function wrapInRequestContext<S>(handler: (req: Request, server: S) => Promise<Response>, options?: WrapRequestContextOptions): (req: Request, server: S) => Promise<Response>;
60
68
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/observability/context.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjE,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAID,yDAAyD;AACzD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED,mEAAmE;AACnE,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAE/C;AAED,qDAAqD;AACrD,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,GACtD,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAYhD"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/observability/context.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjE,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAID,yDAAyD;AACzD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED,mEAAmE;AACnE,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAE/C;AAED,qDAAqD;AACrD,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGhF;AAED,0CAA0C;AAC1C,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,EACvD,OAAO,GAAE,yBAA8B,GACtC,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAiBhD"}
@@ -1,9 +1,13 @@
1
+ import {
2
+ getClientInfo,
3
+ resolveSocketIp
4
+ } from "../index-mwmpw6j1.js";
5
+ import {
6
+ isUnsafeKey
7
+ } from "../index-kzfs85xp.js";
1
8
  import {
2
9
  isRecord
3
10
  } from "../index-809wc1tt.js";
4
- import {
5
- getClientInfo
6
- } from "../index-ke4mx4ea.js";
7
11
 
8
12
  // src/observability/context.ts
9
13
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -27,11 +31,11 @@ function parseTraceparent(header) {
27
31
  const match = TRACEPARENT_RE.exec(header.trim());
28
32
  if (!match?.[1] || !match[2])
29
33
  return null;
30
- return {
31
- traceId: match[1].toLowerCase(),
32
- spanId: randomHex(8),
33
- parentSpanId: match[2].toLowerCase()
34
- };
34
+ const traceId = match[1].toLowerCase();
35
+ const parentSpanId = match[2].toLowerCase();
36
+ if (/^0+$/.test(traceId) || /^0+$/.test(parentSpanId))
37
+ return null;
38
+ return { traceId, spanId: randomHex(8), parentSpanId };
35
39
  }
36
40
  function formatTraceparent(ctx) {
37
41
  return `00-${ctx.traceId}-${ctx.spanId}-01`;
@@ -71,15 +75,18 @@ function setRequestError(error) {
71
75
  if (ctx)
72
76
  ctx.error = error;
73
77
  }
74
- function wrapInRequestContext(handler) {
78
+ function wrapInRequestContext(handler, options = {}) {
75
79
  return (req, server) => {
76
80
  const ctx = {
77
81
  trace: resolveTraceContext(req),
78
82
  source: "http",
79
83
  method: req.method,
80
- path: new URL(req.url).pathname,
84
+ path: new URL(req.url, "http://localhost").pathname,
81
85
  startedAt: process.hrtime.bigint(),
82
- ...getClientInfo(req)
86
+ ...getClientInfo(req, {
87
+ trustProxy: options.trustProxy,
88
+ socketIp: resolveSocketIp(req, server)
89
+ })
83
90
  };
84
91
  return runWithRequestContext(ctx, () => handler(req, server));
85
92
  };
@@ -93,6 +100,7 @@ var MASK = "[redacted]";
93
100
  function redact(value, options = {}) {
94
101
  const sensitive = options.sensitiveKeys ?? DEFAULT_SENSITIVE_KEYS;
95
102
  const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
103
+ const ancestors = new Set;
96
104
  const walk = (input, depth) => {
97
105
  if (depth > maxDepth)
98
106
  return "[max depth]";
@@ -111,13 +119,24 @@ function redact(value, options = {}) {
111
119
  return { _type: "formdata", keys: [...input.keys()] };
112
120
  }
113
121
  if (Array.isArray(input)) {
114
- return input.map((item) => walk(item, depth + 1));
122
+ if (ancestors.has(input))
123
+ return "[circular]";
124
+ ancestors.add(input);
125
+ const result = input.map((item) => walk(item, depth + 1));
126
+ ancestors.delete(input);
127
+ return result;
115
128
  }
116
129
  if (isRecord(input)) {
130
+ if (ancestors.has(input))
131
+ return "[circular]";
132
+ ancestors.add(input);
117
133
  const out = {};
118
134
  for (const [key, val] of Object.entries(input)) {
135
+ if (isUnsafeKey(key))
136
+ continue;
119
137
  out[key] = sensitive.test(key) ? MASK : walk(val, depth + 1);
120
138
  }
139
+ ancestors.delete(input);
121
140
  return out;
122
141
  }
123
142
  return String(input);
@@ -126,11 +145,12 @@ function redact(value, options = {}) {
126
145
  }
127
146
  function truncatePreview(value, maxBytes = DEFAULT_MAX_BYTES) {
128
147
  const json = JSON.stringify(value);
129
- if (json.length <= maxBytes)
148
+ const bytes = Buffer.byteLength(json, "utf8");
149
+ if (bytes <= maxBytes)
130
150
  return value;
131
151
  return {
132
152
  _truncated: true,
133
- _originalBytes: json.length,
153
+ _originalBytes: bytes,
134
154
  preview: `${json.slice(0, maxBytes)}…`
135
155
  };
136
156
  }
@@ -147,7 +167,7 @@ function measureSize(value) {
147
167
  if (Array.isArray(value)) {
148
168
  return { resultSize: value.length, responseBytes };
149
169
  }
150
- if (typeof value === "object" && "items" in value && Array.isArray(value.items)) {
170
+ if (isRecord(value) && Array.isArray(value.items) && "nextCursor" in value) {
151
171
  return { resultSize: value.items.length, responseBytes };
152
172
  }
153
173
  return { resultSize: null, responseBytes };
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/observability/sanitize.ts"],"names":[],"mappings":"AAMA,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;CACvB;AASD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,SAAS,CAsC/E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,SAAoB,GAAG,SAAS,CAQzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,eAAoB,GAC5B,SAAS,GAAG,IAAI,CAGlB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAYvD"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/observability/sanitize.ts"],"names":[],"mappings":"AAOA,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;CACvB;AASD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,SAAS,CAoD/E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,SAAoB,GAAG,SAAS,CASzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,eAAoB,GAC5B,SAAS,GAAG,IAAI,CAGlB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAcvD"}
@@ -3,7 +3,8 @@
3
3
  * endpoint schemas and gathers request metadata (trace id, client info).
4
4
  */
5
5
  import { type RuntimeContext } from '../contract';
6
+ import { type ClientIpOptions } from './request';
6
7
  import type { MethodDef } from './types';
7
- export declare function buildContext(req: Request, url: URL, method: MethodDef, pathParams: Record<string, string>, traceId: string): Promise<RuntimeContext>;
8
- export declare function buildErrorContext(req: Request, url: URL, traceId: string): RuntimeContext;
8
+ export declare function buildContext(req: Request, url: URL, method: MethodDef, pathParams: Record<string, string>, traceId: string, clientIp: ClientIpOptions): Promise<RuntimeContext>;
9
+ export declare function buildErrorContext(req: Request, url: URL, traceId: string, clientIp: ClientIpOptions): RuntimeContext;
9
10
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AA2BzC,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,CAyCzB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAWzF"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,KAAK,eAAe,EAAmC,MAAM,WAAW,CAAC;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAmCzC,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,cAAc,CAAC,CA2CzB;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,eAAe,GACxB,cAAc,CAWhB"}
@@ -1,4 +1,4 @@
1
- import type { ServerConfig } from './types';
2
- export declare function createHandler(config: ServerConfig): (req: Request) => Promise<Response>;
3
- export declare function createServer(config: ServerConfig): Bun.Server<unknown>;
1
+ import type { BunServerConfig, HandlerConfig } from './types';
2
+ export declare function createHandler(config: HandlerConfig): (req: Request) => Promise<Response>;
3
+ export declare function createServer(config: BunServerConfig): Bun.Server<unknown>;
4
4
  //# sourceMappingURL=create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAwB,YAAY,EAAgB,MAAM,SAAS,CAAC;AAEhF,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA+KvF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,uBAsBhD"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EAGd,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAwMxF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,uBAsBnD"}
@@ -19,6 +19,15 @@ export interface EventBus<M extends Record<string, unknown> = DefaultEventMap> {
19
19
  off<K extends keyof M & string>(event: K, handler: EventHandler<M[K]>): void;
20
20
  clear(): void;
21
21
  }
22
- export declare function createEventBus<M extends Record<string, unknown> = DefaultEventMap>(): EventBus<M>;
22
+ /** Options for `createEventBus`. */
23
+ export interface EventBusOptions {
24
+ /**
25
+ * Called when a listener throws or rejects. A bus listener's failure must
26
+ * never break the bus, so it is caught — but without this hook it is also
27
+ * invisible. Wire it to a logger to surface listener bugs.
28
+ */
29
+ onListenerError?: (error: unknown, event: string) => void;
30
+ }
31
+ export declare function createEventBus<M extends Record<string, unknown> = DefaultEventMap>(options?: EventBusOptions): EventBus<M>;
23
32
  export {};
24
33
  //# sourceMappingURL=event-bus.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/server/event-bus.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnE,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe;IAC3E,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAClF,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IACpF,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7E,KAAK,IAAI,IAAI,CAAC;CACf;AAYD,wBAAgB,cAAc,CAC5B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,KAChD,QAAQ,CAAC,CAAC,CAAC,CAuDf"}
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/server/event-bus.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnE,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe;IAC3E,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAClF,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IACpF,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7E,KAAK,IAAI,IAAI,CAAC;CACf;AAYD,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EAChF,OAAO,GAAE,eAAoB,GAC5B,QAAQ,CAAC,CAAC,CAAC,CA0Db"}
@@ -8,10 +8,10 @@ export { type CookieDef, type CookieOptions, defineCookie, parseCookies, seriali
8
8
  export { type CorsConfig, corsHeaders, corsPreflightResponse, } from './middleware/cors';
9
9
  export { parseMultipart } from './multipart';
10
10
  export { createRateLimiter, type RateLimitConfig } from './rate-limit';
11
- export { extractIp, generateTraceId, getClientInfo, resolveTraceId, } from './request';
11
+ export { type ClientIpOptions, extractIp, generateTraceId, getClientInfo, resolveSocketIp, resolveTraceId, } from './request';
12
12
  export { staticRoute } from './router';
13
13
  export type { SocketIOServerConfig, SocketIOServerHandle } from './socket-io';
14
14
  export { createSocketIOServer } from './socket-io';
15
15
  export { type ParseSSEOptions, parseSSE, streamSSE } from './stream';
16
- export type { BunServer, Handlers, LifecycleHooks, MethodDef, RawRoute, RawRouteContext, RouteGroup, ServerConfig, ServerPassthrough, ServiceDef, StitchLogger, } from './types';
16
+ export type { BunServer, BunServerConfig, HandlerConfig, Handlers, LifecycleHooks, MethodDef, RawRoute, RawRouteContext, RouteGroup, ServerPassthrough, ServiceDef, StitchLogger, } from './types';
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EACL,SAAS,EACT,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EACV,SAAS,EACT,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,EACf,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EACL,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,SAAS,CAAC"}