stitchkit 0.2.0 → 0.4.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 (136) hide show
  1. package/README.md +11 -10
  2. package/dist/browser/client.d.ts.map +1 -1
  3. package/dist/browser/http.d.ts +5 -0
  4. package/dist/browser/http.d.ts.map +1 -1
  5. package/dist/browser/socket-io.d.ts +17 -0
  6. package/dist/browser/socket-io.d.ts.map +1 -1
  7. package/dist/cli.d.ts +23 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +21 -0
  10. package/dist/contract/define.d.ts +35 -2
  11. package/dist/contract/define.d.ts.map +1 -1
  12. package/dist/contract/index.d.ts +1 -1
  13. package/dist/contract/index.d.ts.map +1 -1
  14. package/dist/contract/index.js +2 -1
  15. package/dist/index-0ed3bx43.js +33 -0
  16. package/dist/index-0ma1eqv4.js +1007 -0
  17. package/dist/index-1cf8jkhf.js +219 -0
  18. package/dist/index-37x76zdn.js +4 -0
  19. package/dist/{index-v2z2v3mq.js → index-3qmtdfpa.js} +304 -62
  20. package/dist/index-48ffdxgk.js +6 -0
  21. package/dist/{index-5sxnvwb1.js → index-78q1qm7v.js} +6 -3
  22. package/dist/{index-kckky6zw.js → index-afzt3nmx.js} +1 -1
  23. package/dist/{index-n7bmdwmz.js → index-d4rwrjbc.js} +8 -4
  24. package/dist/index-kzfs85xp.js +9 -0
  25. package/dist/index-mwmpw6j1.js +60 -0
  26. package/dist/{index-a35v22fh.js → index-vhdvv00d.js} +13 -5
  27. package/dist/index-x3fcszf8.js +8 -0
  28. package/dist/index.js +17 -4
  29. package/dist/internal/errors.d.ts +13 -1
  30. package/dist/internal/errors.d.ts.map +1 -1
  31. package/dist/internal/http-input.d.ts +13 -0
  32. package/dist/internal/http-input.d.ts.map +1 -0
  33. package/dist/internal/safe-json.d.ts +19 -0
  34. package/dist/internal/safe-json.d.ts.map +1 -0
  35. package/dist/internal/secure-fetch.d.ts +27 -0
  36. package/dist/internal/secure-fetch.d.ts.map +1 -0
  37. package/dist/internal/within-dir.d.ts +7 -0
  38. package/dist/internal/within-dir.d.ts.map +1 -0
  39. package/dist/node.d.ts +10 -1
  40. package/dist/node.d.ts.map +1 -1
  41. package/dist/node.js +41 -7
  42. package/dist/observability/audit.d.ts.map +1 -1
  43. package/dist/observability/context.d.ts +9 -1
  44. package/dist/observability/context.d.ts.map +1 -1
  45. package/dist/observability/event.d.ts +4 -0
  46. package/dist/observability/event.d.ts.map +1 -1
  47. package/dist/observability/index.js +38 -15
  48. package/dist/observability/sanitize.d.ts.map +1 -1
  49. package/dist/react.js +2 -0
  50. package/dist/server/context.d.ts +3 -2
  51. package/dist/server/context.d.ts.map +1 -1
  52. package/dist/server/create.d.ts.map +1 -1
  53. package/dist/server/event-bus.d.ts +10 -1
  54. package/dist/server/event-bus.d.ts.map +1 -1
  55. package/dist/server/implement.d.ts.map +1 -1
  56. package/dist/server/index.d.ts +6 -3
  57. package/dist/server/index.d.ts.map +1 -1
  58. package/dist/server/index.js +203 -193
  59. package/dist/server/logger.d.ts +5 -4
  60. package/dist/server/logger.d.ts.map +1 -1
  61. package/dist/server/middleware/auth.d.ts +41 -1
  62. package/dist/server/middleware/auth.d.ts.map +1 -1
  63. package/dist/server/middleware/cookies.d.ts.map +1 -1
  64. package/dist/server/middleware/cors.d.ts +7 -0
  65. package/dist/server/middleware/cors.d.ts.map +1 -1
  66. package/dist/server/middleware/pkce.d.ts +17 -0
  67. package/dist/server/middleware/pkce.d.ts.map +1 -0
  68. package/dist/server/multipart.d.ts +2 -1
  69. package/dist/server/multipart.d.ts.map +1 -1
  70. package/dist/server/node.d.ts +9 -0
  71. package/dist/server/node.d.ts.map +1 -1
  72. package/dist/server/openapi.d.ts +52 -0
  73. package/dist/server/openapi.d.ts.map +1 -0
  74. package/dist/server/rate-limit.d.ts +7 -2
  75. package/dist/server/rate-limit.d.ts.map +1 -1
  76. package/dist/server/request.d.ts +27 -4
  77. package/dist/server/request.d.ts.map +1 -1
  78. package/dist/server/router.d.ts +4 -2
  79. package/dist/server/router.d.ts.map +1 -1
  80. package/dist/server/socket-io.d.ts +60 -15
  81. package/dist/server/socket-io.d.ts.map +1 -1
  82. package/dist/server/stream.d.ts +3 -1
  83. package/dist/server/stream.d.ts.map +1 -1
  84. package/dist/server/types.d.ts +17 -1
  85. package/dist/server/types.d.ts.map +1 -1
  86. package/dist/server/websocket.d.ts +73 -0
  87. package/dist/server/websocket.d.ts.map +1 -0
  88. package/dist/tools/cli-args.d.ts +68 -0
  89. package/dist/tools/cli-args.d.ts.map +1 -0
  90. package/dist/tools/cli-format.d.ts +39 -0
  91. package/dist/tools/cli-format.d.ts.map +1 -0
  92. package/dist/tools/cli-wait.d.ts +45 -0
  93. package/dist/tools/cli-wait.d.ts.map +1 -0
  94. package/dist/tools/cli.d.ts +77 -0
  95. package/dist/tools/cli.d.ts.map +1 -0
  96. package/dist/tools/coerce.d.ts +8 -4
  97. package/dist/tools/coerce.d.ts.map +1 -1
  98. package/dist/tools/execute.d.ts +1 -1
  99. package/dist/tools/execute.d.ts.map +1 -1
  100. package/dist/tools/json-schema.d.ts +29 -4
  101. package/dist/tools/json-schema.d.ts.map +1 -1
  102. package/dist/tools/manifest.d.ts +4 -0
  103. package/dist/tools/manifest.d.ts.map +1 -1
  104. package/dist/tools/mcp-app.d.ts +59 -0
  105. package/dist/tools/mcp-app.d.ts.map +1 -0
  106. package/dist/tools/mcp-handler.d.ts +18 -0
  107. package/dist/tools/mcp-handler.d.ts.map +1 -1
  108. package/dist/tools/mcp.d.ts +9 -0
  109. package/dist/tools/mcp.d.ts.map +1 -1
  110. package/dist/tools/mount-download.d.ts +30 -0
  111. package/dist/tools/mount-download.d.ts.map +1 -0
  112. package/dist/tools/mount-upload.d.ts +19 -0
  113. package/dist/tools/mount-upload.d.ts.map +1 -0
  114. package/dist/tools/mount-wait.d.ts +36 -0
  115. package/dist/tools/mount-wait.d.ts.map +1 -0
  116. package/dist/tools/mount.d.ts +8 -4
  117. package/dist/tools/mount.d.ts.map +1 -1
  118. package/dist/tools/native-result.d.ts +17 -0
  119. package/dist/tools/native-result.d.ts.map +1 -0
  120. package/dist/tools/oauth-metadata.d.ts +28 -0
  121. package/dist/tools/oauth-metadata.d.ts.map +1 -0
  122. package/dist/tools/oauth-provider.d.ts +85 -0
  123. package/dist/tools/oauth-provider.d.ts.map +1 -0
  124. package/dist/tools/remote.d.ts +2 -2
  125. package/dist/tools/remote.d.ts.map +1 -1
  126. package/dist/tools/toolkit.d.ts +51 -0
  127. package/dist/tools/toolkit.d.ts.map +1 -0
  128. package/dist/tools/view-file.d.ts +12 -0
  129. package/dist/tools/view-file.d.ts.map +1 -1
  130. package/dist/tools/wait-core.d.ts +33 -0
  131. package/dist/tools/wait-core.d.ts.map +1 -0
  132. package/dist/tools.d.ts +13 -2
  133. package/dist/tools.d.ts.map +1 -1
  134. package/dist/tools.js +637 -424
  135. package/package.json +22 -9
  136. package/dist/index-ke4mx4ea.js +0 -38
@@ -2,7 +2,8 @@ import type { ZodType } from 'zod';
2
2
  /** A parsed multipart request — the uploaded `file` and the validated `fields`. */
3
3
  export interface MultipartResult {
4
4
  file: File;
5
- fields: Record<string, unknown>;
5
+ /** Validated when a `fieldsSchema` was given, else the raw decoded fields. */
6
+ fields: unknown;
6
7
  }
7
8
  /**
8
9
  * Parse a `multipart/form-data` request — extract the file at `fileField` and
@@ -1 +1 @@
1
- {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAGnC,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAKD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAC/B,QAAQ,SAA2B,GAClC,OAAO,CAAC,eAAe,CAAC,CAkC1B"}
1
+ {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;CACjB;AA0CD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAC/B,QAAQ,SAA2B,GAClC,OAAO,CAAC,eAAe,CAAC,CA6B1B"}
@@ -1,7 +1,16 @@
1
+ import type { Server as HttpServer } from 'node:http';
1
2
  import type { HandlerConfig } from './types';
2
3
  export interface NodeServerConfig extends HandlerConfig {
3
4
  port?: number;
4
5
  hostname?: string;
6
+ /**
7
+ * A Socket.IO handle from `createSocketIOServer` — attached to the underlying
8
+ * `node:http.Server` (srvx `server.node.server`) once it is listening, so
9
+ * Socket.IO owns the HTTP `upgrade` event on the same port.
10
+ */
11
+ socket?: {
12
+ attach(server: HttpServer): void;
13
+ };
5
14
  }
6
15
  export interface NodeServerHandle {
7
16
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/server/node.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgBnF"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/server/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA6BnF"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * OpenAPI 3.1 generation from contracts. A `defineContract` already carries the
3
+ * full type information — Zod `params` / `input` / `output`, `desc`, `method`,
4
+ * `path`, `scope` — so the spec is generated, not hand-maintained: the contract
5
+ * IS the spec. No decorators, no duplicated annotations. → ADR 0018.
6
+ *
7
+ * Schemas are converted through the same single `toJsonSchema` point the tool
8
+ * layer uses (and `jsonSchemaFields`, shared with the CLI `--help` walker), so
9
+ * the JSON Schema in the spec is the JSON Schema the rest of the framework
10
+ * emits — not a divergent code path. Schemas are inlined (valid OpenAPI);
11
+ * `$ref` de-duplication can come later if a spec grows unwieldy.
12
+ */
13
+ import type { RawRoute, ServiceDef } from './types';
14
+ export interface OpenApiInfo {
15
+ title: string;
16
+ version: string;
17
+ description?: string;
18
+ }
19
+ export interface OpenApiServer {
20
+ url: string;
21
+ description?: string;
22
+ }
23
+ export interface OpenApiConfig {
24
+ info: OpenApiInfo;
25
+ /** Flat services, mounted at their own prefix. */
26
+ services?: ServiceDef[];
27
+ /** Grouped services, each mounted under a path prefix (mirrors `RouteGroup`). */
28
+ groups?: Array<{
29
+ pathPrefix?: string;
30
+ services: ServiceDef[];
31
+ }>;
32
+ /** `servers` block for the spec. */
33
+ servers?: OpenApiServer[];
34
+ }
35
+ export interface OpenApiDocument {
36
+ openapi: '3.1.0';
37
+ info: OpenApiInfo;
38
+ servers?: OpenApiServer[];
39
+ paths: Record<string, Record<string, unknown>>;
40
+ }
41
+ /**
42
+ * Generate an OpenAPI 3.1 document from contract services. Only methods exposed
43
+ * on HTTP are included — a method whose `expose` omits `'HTTP'` (an MCP/agent
44
+ * only tool) is skipped, matching the router's own route-building rule.
45
+ */
46
+ export declare function generateOpenApiDocument(config: OpenApiConfig): OpenApiDocument;
47
+ /**
48
+ * A `RawRoute` that serves a generated OpenAPI document as JSON — mount it
49
+ * alongside contract routes to expose `/openapi.json`.
50
+ */
51
+ export declare function openApiRoute(path: string, document: OpenApiDocument): RawRoute;
52
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/server/openapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,iFAAiF;IACjF,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAC;IAChE,oCAAoC;IACpC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChD;AAsED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,aAAa,GAAG,eAAe,CAgH9E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,QAAQ,CAM9E"}
@@ -6,8 +6,13 @@ export interface RateLimitConfig {
6
6
  /**
7
7
  * In-memory token-bucket rate limiter. `check(key, config)` consumes a token
8
8
  * and returns whether the request is allowed; `remaining(key, config)` reports
9
- * the count without consuming. Idle keys are swept on a 60-second timer;
10
- * `destroy()` stops it.
9
+ * the count without consuming. Idle keys are swept on a 60-second timer and the
10
+ * map is capped at `MAX_BUCKETS` (least-recently-used eviction); `destroy()`
11
+ * stops the timer.
12
+ *
13
+ * `config` is per-call — reusing one `key` with two different configs lets
14
+ * whichever call created the bucket fix its `max` / `window`. Key a bucket to
15
+ * one config (one limiter per limit) if that matters.
11
16
  */
12
17
  export declare function createRateLimiter(): {
13
18
  destroy: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/server/rate-limit.ts"],"names":[],"mappings":"AAOA,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AASD;;;;;GAKG;AACH,wBAAgB,iBAAiB;;eAQlB,MAAM,UAAU,eAAe,GAAG,OAAO;mBAiBrC,MAAM,UAAU,eAAe,GAAG,MAAM;EAO1D"}
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/server/rate-limit.ts"],"names":[],"mappings":"AAOA,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAeD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB;;eAQlB,MAAM,UAAU,eAAe,GAAG,OAAO;mBA6BrC,MAAM,UAAU,eAAe,GAAG,MAAM;EAO1D"}
@@ -2,7 +2,7 @@
2
2
  * HTTP request helpers — header parsing, client identification, trace ids.
3
3
  * Pure `Request → value` functions; no framework state.
4
4
  */
5
- /** Compact, time-sortable id — base36 timestamp + base36 random, ~14 chars. */
5
+ /** Compact, time-sortable id — base36 timestamp + a cryptographic suffix. */
6
6
  export declare function generateTraceId(): string;
7
7
  /**
8
8
  * Trace id for a request: a trusted inbound `x-request-id` / `x-trace-id`
@@ -10,10 +10,33 @@ export declare function generateTraceId(): string;
10
10
  * Shared by the router, the logger and any consumer that wants the same id.
11
11
  */
12
12
  export declare function resolveTraceId(req: Request): string;
13
- /** Client IP from `x-forwarded-for` / `x-real-ip` (IPv4-mapped prefix stripped). */
14
- export declare function extractIp(req: Request): string;
13
+ /**
14
+ * Resolve the real socket peer IP from the runtime — unspoofable, unlike a
15
+ * header. On Bun the server resolves it (`server.requestIP`); on Node / Deno
16
+ * the `srvx` adapter attaches `.ip` to the request. `undefined` when neither
17
+ * is available (the bare `createHandler` fetch with no server).
18
+ */
19
+ export declare function resolveSocketIp(req: Request, server: unknown): string | undefined;
20
+ /** Options for `extractIp` / `getClientInfo`. */
21
+ export interface ClientIpOptions {
22
+ /**
23
+ * Trust `x-forwarded-for` / `x-real-ip` for the client IP. Enable only behind
24
+ * a proxy that overwrites them — they are client-controllable. Default
25
+ * `false`: the real socket IP (`socketIp`) is used instead.
26
+ */
27
+ trustProxy?: boolean;
28
+ /** The real socket peer IP — see `resolveSocketIp`. */
29
+ socketIp?: string;
30
+ }
31
+ /**
32
+ * The client IP for a request. With `trustProxy`, the `x-forwarded-for` /
33
+ * `x-real-ip` client wins (the server sits behind a proxy that rewrites them);
34
+ * otherwise the real, unspoofable socket peer (`socketIp`) is used. Returns
35
+ * `''` when nothing is known.
36
+ */
37
+ export declare function extractIp(req: Request, options?: ClientIpOptions): string;
15
38
  /** Client identity — IP + user-agent. The one place projects derive both. */
16
- export declare function getClientInfo(req: Request): {
39
+ export declare function getClientInfo(req: Request, options?: ClientIpOptions): {
17
40
  ipAddress?: string;
18
41
  userAgent?: string;
19
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/server/request.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+EAA+E;AAC/E,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CASnD;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAM9C;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAKA;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAQ5E"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/server/request.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,6EAA6E;AAC7E,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CASnD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAejF;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CAQ7E;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,eAAoB,GAC5B;IACD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAKA;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAU5E"}
@@ -34,8 +34,10 @@ export declare function matchRawRoute(rawRoutes: RawRoute[], httpMethod: string,
34
34
  params: Record<string, string>;
35
35
  } | null;
36
36
  /**
37
- * Build a `RawRoute` that serves files from `dir` under `prefix`.
38
- * Rejects path traversal (`..`); 404 for a missing file.
37
+ * Build a `RawRoute` that serves files from `dir` under `prefix`. Basic by
38
+ * design — no Range, no conditional requests; put a CDN in front for those.
39
+ * Rejects path traversal (including the percent-encoded form); 404 for a
40
+ * missing file. Uses `node:fs`, so it runs on both Bun and Node.
39
41
  */
40
42
  export declare function staticRoute(prefix: string, dir: string): RawRoute;
41
43
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAqCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,QAAQ,CAmCjE;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,UAAU,GAAG,IAAI,CAmBnB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAc7E;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAiBvD;AAID,wBAAgB,aAAa,CAC3B,SAAS,EAAE,QAAQ,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAyB5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAuBjE"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAqCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,QAAQ,CAmCjE;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,UAAU,GAAG,IAAI,CAmBnB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAc7E;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAiBvD;AAID,wBAAgB,aAAa,CAC3B,SAAS,EAAE,QAAQ,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAyB5D;AAoBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAmCjE"}
@@ -1,20 +1,26 @@
1
1
  /**
2
- * Socket.IO server setup — the family WebSocket server boilerplate.
2
+ * Socket.IO server setup — the family WebSocket server boilerplate, runtime-aware.
3
3
  *
4
- * Every project repeats the same wiring: `new SocketIOServer(...)`, a
5
- * `@socket.io/bun-engine` instance, `io.bind(engine)`, `engine.handler()` for
6
- * the `Bun.serve` `websocket` field, and an `/socket.io/*` route delegating to
7
- * `engine.handleRequest`. `createSocketIOServer` is exactly that wiring.
4
+ * The engine differs per runtime, so the socket packages are loaded **lazily**
5
+ * (dynamic `import` inside the function) — a `type`-only import at the top would
6
+ * still be erased, but a top-level *value* import of `@socket.io/bun-engine`
7
+ * (Bun-only) would crash the whole `stitchkit/server` barrel on Node before any
8
+ * socket code runs. Lazy loading keeps the barrel Node-importable for apps that
9
+ * never use sockets.
8
10
  *
9
- * Connection handlers, rooms and handshake auth stay in the project — they are
10
- * domain logic. This helper owns only the transport plumbing: it returns the
11
- * typed `io` to attach handlers to, the `websocket` handler for `Bun.serve`,
12
- * and a ready-made `route` to drop into `createServer({ rawRoutes })`.
11
+ * - **Bun** — `@socket.io/bun-engine` + `io.bind(engine)`; returns the
12
+ * `websocket` handler for `Bun.serve` and a `/socket.io/*` route.
13
+ * - **Node** — `io.attach(server)` onto the `node:http.Server` exposed by
14
+ * `serveNode` (srvx `server.node.server`); Socket.IO owns the `upgrade` event.
15
+ *
16
+ * Connection handlers, rooms and handshake auth stay in the project.
13
17
  */
14
- import { Server as BunEngine } from '@socket.io/bun-engine';
15
- import { Server as SocketIOServer } from 'socket.io';
18
+ import type { Server as HttpServer } from 'node:http';
19
+ import type { Server as BunEngine } from '@socket.io/bun-engine';
20
+ import type { Server as SocketIOServer } from 'socket.io';
16
21
  import type { SocketEventMap } from '../browser/socket-io';
17
22
  import type { RawRoute } from './types';
23
+ import { type ComposedLane } from './websocket';
18
24
  export interface SocketIOServerConfig {
19
25
  /** CORS — the browser origin(s) allowed to open a socket. */
20
26
  cors: {
@@ -23,7 +29,13 @@ export interface SocketIOServerConfig {
23
29
  };
24
30
  /** Socket.IO endpoint path. Default `/socket.io/`. */
25
31
  path?: string;
26
- /** Transports offered to clients. Default `['websocket', 'polling']`. */
32
+ /**
33
+ * Transports offered to clients. Default `['websocket', 'polling']` on Bun;
34
+ * on Node the default is `['websocket']` — Socket.IO shares the HTTP server
35
+ * with srvx there, so its polling request-handler would collide with srvx's;
36
+ * WebSocket uses the separate `upgrade` event and does not. Configure the
37
+ * client with `transports: ['websocket']` to match.
38
+ */
27
39
  transports?: Array<'websocket' | 'polling'>;
28
40
  /** Heartbeat: ms without a pong before the connection is dropped. Default `20000`. */
29
41
  pingTimeout?: number;
@@ -33,10 +45,43 @@ export interface SocketIOServerConfig {
33
45
  export interface SocketIOServerHandle<TServerEvents extends SocketEventMap, TClientEvents extends SocketEventMap> {
34
46
  /** The typed Socket.IO server — attach `io.on('connection', ...)` handlers. */
35
47
  io: SocketIOServer<TClientEvents, TServerEvents>;
36
- /** WebSocket handler for `Bun.serve({ websocket })`. */
48
+ /**
49
+ * WebSocket handler for `Bun.serve({ websocket })`. Real on Bun; on Node it is
50
+ * an inert no-op — sockets there are driven by the `node:http.Server`
51
+ * `upgrade` event via `serveNode({ socket })`, never by this field — so a Bun
52
+ * consumer can pass it unconditionally without a runtime guard.
53
+ */
37
54
  websocket: ReturnType<BunEngine['handler']>['websocket'];
38
- /** Ready `/socket.io/*` route — drop into `createServer({ rawRoutes })`. */
55
+ /**
56
+ * `/socket.io/*` route for `createServer({ rawRoutes })`. Real on Bun; on Node
57
+ * it is unused (sockets attach to the http.Server via `serveNode({ socket })`)
58
+ * and throws if it is ever mounted — so it is safe to spread into `rawRoutes`
59
+ * unconditionally on either runtime.
60
+ */
39
61
  route: RawRoute;
62
+ /**
63
+ * Node only — attach the Socket.IO server to the `node:http.Server` from
64
+ * `serveNode`. A no-op on Bun (the engine + route handle transport there).
65
+ * `serveNode({ socket })` calls this for you.
66
+ */
67
+ attach(server: HttpServer): void;
40
68
  }
41
- export declare function createSocketIOServer<TServerEvents extends SocketEventMap, TClientEvents extends SocketEventMap>(config: SocketIOServerConfig): SocketIOServerHandle<TServerEvents, TClientEvents>;
69
+ export declare function createSocketIOServer<TServerEvents extends SocketEventMap, TClientEvents extends SocketEventMap>(config: SocketIOServerConfig): Promise<SocketIOServerHandle<TServerEvents, TClientEvents>>;
70
+ /**
71
+ * Wrap a Socket.IO handle's `websocket` as a catch-all {@link ComposedLane} for
72
+ * {@link composeWebSocketHandlers} — when a second, raw WebSocket lane shares
73
+ * the one `Bun.serve` websocket handler. It claims every socket no earlier
74
+ * (raw-marker) lane matched, so the engine owns whatever the raw lanes did not
75
+ * — and it never inspects the engine's opaque `ws.data`. Place it **last**.
76
+ *
77
+ * ```ts
78
+ * const ws = composeWebSocketHandlers([
79
+ * webSocketLane({ match: isPcmSocket, handlers: pcmHandlers }),
80
+ * socketIoLane(socket.websocket),
81
+ * ])
82
+ * ```
83
+ *
84
+ * Bun-only (so is the raw-lane composition it serves).
85
+ */
86
+ export declare function socketIoLane(websocket: SocketIOServerHandle<SocketEventMap, SocketEventMap>['websocket']): ComposedLane;
42
87
  //# sourceMappingURL=socket-io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/server/socket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,UAAU,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC5C,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CACnC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc;IAEpC,+EAA+E;IAC/E,EAAE,EAAE,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACjD,wDAAwD;IACxD,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACzD,4EAA4E;IAC5E,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc,EACpC,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CAAC,aAAa,EAAE,aAAa,CAAC,CAqClF"}
1
+ {"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/server/socket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,KAAK,YAAY,EAAiB,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC5C,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CACnC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc;IAEpC,+EAA+E;IAC/E,EAAE,EAAE,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACjD;;;;;OAKG;IACH,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACzD;;;;;OAKG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAClC;AAOD,wBAAsB,oBAAoB,CACxC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc,EACpC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CA8D3F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,oBAAoB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,WAAW,CAAC,GAC3E,YAAY,CAMd"}
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Turn an async generator into a Server-Sent Events `Response` — each yielded
3
3
  * value is one JSON `data:` event, the stream ends with a `[DONE]` sentinel,
4
- * and a thrown error is emitted as a final `{ error }` event.
4
+ * and a thrown error is emitted as a final error event. The error is
5
+ * normalised (`normalizeError`) so an internal failure never leaks its raw
6
+ * message into the stream.
5
7
  */
6
8
  export declare function streamSSE(generator: AsyncGenerator<unknown>): Response;
7
9
  /** Options for `parseSSE`. */
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/server/stream.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,QAAQ,CA2BtE;AAED,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpD;AAED;;;;GAIG;AACH,wBAAuB,QAAQ,CAAC,CAAC,EAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAAC,CAAC,CAAC,CAkCnB"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/server/stream.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,QAAQ,CA2BtE;AAED,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpD;AAED;;;;GAIG;AACH,wBAAuB,QAAQ,CAAC,CAAC,EAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAAC,CAAC,CAAC,CAmCnB"}
@@ -1,5 +1,5 @@
1
1
  import type { ZodType } from 'zod';
2
- import type { EndpointDef, HandlerContext, HttpMethod, RuntimeContext, Transport } from '../contract';
2
+ import type { EndpointDef, EndpointToolAnnotations, EndpointUiMeta, HandlerContext, HttpMethod, RuntimeContext, Transport } from '../contract';
3
3
  import type { CorsConfig } from './middleware/cors';
4
4
  type Prop<T, K extends string> = K extends keyof T ? T[K] : undefined;
5
5
  type InferParams<E> = Prop<E, 'params'> extends ZodType<infer P> ? P : undefined;
@@ -22,6 +22,10 @@ export interface MethodDef<TParams = unknown, TInput = unknown, TOutput = unknow
22
22
  inputSchema?: ZodType<TInput>;
23
23
  outputSchema?: ZodType<TOutput>;
24
24
  multipart?: string;
25
+ /** MCP Apps widget metadata — carried onto the MCP tool's `_meta.ui`. */
26
+ ui?: EndpointUiMeta;
27
+ /** MCP behavioural hints — carried onto the MCP tool's `annotations`. */
28
+ annotations?: EndpointToolAnnotations;
25
29
  handler: (ctx: RuntimeContext) => Promise<TOutput> | TOutput;
26
30
  }
27
31
  export interface ServiceDef {
@@ -61,6 +65,11 @@ export interface RawRouteContext {
61
65
  * Absent when the handler runs via the bare `createHandler` fetch.
62
66
  */
63
67
  server?: BunServer;
68
+ /**
69
+ * Client IP — the real socket peer, or the `x-forwarded-for` client when
70
+ * `trustProxy` is set. Resolved by the framework; never spoofable by default.
71
+ */
72
+ ipAddress?: string;
64
73
  }
65
74
  export interface RawRoute {
66
75
  method: HttpMethod | 'ALL';
@@ -91,6 +100,13 @@ export interface HandlerConfig {
91
100
  hooks?: LifecycleHooks;
92
101
  logging?: boolean | StitchLogger;
93
102
  traceId?: (req: Request) => string;
103
+ /**
104
+ * Trust the `x-forwarded-for` / `x-real-ip` headers for the client IP.
105
+ * These are client-controllable — enable only when the server runs behind a
106
+ * proxy that overwrites them. Default `false`: the IP a spoofable header
107
+ * carries never reaches `ctx.ipAddress`, a rate-limit key or an audit row.
108
+ */
109
+ trustProxy?: boolean;
94
110
  }
95
111
  type BunServeOptions = Parameters<typeof Bun.serve>[0];
96
112
  type BunWebSocketHandlers = BunServeOptions extends {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Compose one Bun `websocket` handler from several independent lanes.
3
+ *
4
+ * `Bun.serve` accepts a **single** `websocket` handler. `@socket.io/bun-engine`
5
+ * claims it (via `createSocketIOServer().websocket`). A project that also wants a
6
+ * second, truly-raw binary WebSocket lane on the same server — a high-frequency
7
+ * stream (PCM, video, large transfers) with no Socket.IO framing — has to
8
+ * hand-compose that one handler: route each socket to the engine or to its own
9
+ * raw handlers.
10
+ *
11
+ * The fragile part is the discriminator. Routing *to* Socket.IO means asking
12
+ * "is this an engine socket?", which forces inspecting the engine's opaque
13
+ * `ws.data` — a brittle guard, hard to keep cast-free. The fix here is to invert
14
+ * it: a raw lane stamps **its own** marker onto `ws.data` at upgrade time and is
15
+ * matched positively; Socket.IO is simply the **fallback** lane (matched last,
16
+ * `() => true`). The engine's data is therefore never inspected.
17
+ *
18
+ * Cast-free: each lane carries a type-predicate `match` that narrows
19
+ * `ServerWebSocket<unknown>` to its own data type, so the typed handlers are
20
+ * invoked without a single `as`.
21
+ *
22
+ * Bun-only. On Node, Socket.IO drives sockets through the `node:http.Server`
23
+ * `upgrade` event (`serveNode({ socket })`) — a different model, and a raw lane
24
+ * there would be a separate upgrade handler, not this composition.
25
+ */
26
+ import type { ServerWebSocket, WebSocketHandler } from 'bun';
27
+ /** One lane of a composed handler — a typed slice of the single Bun websocket. */
28
+ export interface WebSocketLane<TData> {
29
+ /**
30
+ * Type-predicate selecting the sockets this lane owns — usually a check on
31
+ * `ws.data` set at upgrade. As a predicate it narrows `ws` to the lane's data
32
+ * type, which is what keeps the handler call cast-free.
33
+ */
34
+ match: (ws: ServerWebSocket<unknown>) => ws is ServerWebSocket<TData>;
35
+ /** Handlers for this lane's sockets — `ws.data` is fully typed as `TData`. */
36
+ handlers: WebSocketHandler<TData>;
37
+ }
38
+ /** A lane already bridged to the loose (`unknown`) data type, ready to compose. */
39
+ export interface ComposedLane {
40
+ match: (ws: ServerWebSocket<unknown>) => boolean;
41
+ handlers: WebSocketHandler<unknown>;
42
+ }
43
+ /**
44
+ * Server-wide WebSocket tuning for the composed handler. Bun applies these to
45
+ * every socket on the server (they cannot be per-lane), so set them to the most
46
+ * permissive value across lanes — a raw binary lane typically needs a larger
47
+ * `maxPayloadLength` than Socket.IO's default (its `maxHttpBufferSize`, 1 MB).
48
+ */
49
+ export type WebSocketComposeConfig = Omit<WebSocketHandler<unknown>, 'open' | 'message' | 'close' | 'drain' | 'ping' | 'pong'>;
50
+ /**
51
+ * Build a `ComposedLane` from typed handlers. Each callback is wrapped so it
52
+ * fires only for sockets the lane's `match` predicate claims — narrowing `ws`
53
+ * to `ServerWebSocket<TData>` for the typed handler. This is the one bridge from
54
+ * Bun's single untyped `websocket` to a typed, per-lane handler, and it holds
55
+ * no casts.
56
+ */
57
+ export declare function webSocketLane<TData>(lane: WebSocketLane<TData>): ComposedLane;
58
+ /**
59
+ * Compose lanes into the single `websocket` handler for `createServer`. On each
60
+ * callback the first lane whose `match` claims the socket handles it — so put
61
+ * specific lanes (raw markers) first and the catch-all (Socket.IO,
62
+ * `socketIoLane`) last. `config` carries the server-wide tuning.
63
+ *
64
+ * ```ts
65
+ * const ws = composeWebSocketHandlers(
66
+ * [webSocketLane({ match: isPcmSocket, handlers: pcmHandlers }), socketIoLane(socket.websocket)],
67
+ * { maxPayloadLength: 16 * 1024 * 1024 },
68
+ * )
69
+ * createServer({ websocket: ws, rawRoutes: [socket.route, pcmUpgradeRoute] })
70
+ * ```
71
+ */
72
+ export declare function composeWebSocketHandlers(lanes: ComposedLane[], config?: WebSocketComposeConfig): WebSocketHandler<unknown>;
73
+ //# sourceMappingURL=websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/server/websocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAE7D,kFAAkF;AAClF,MAAM,WAAW,aAAa,CAAC,KAAK;IAClC;;;;OAIG;IACH,KAAK,EAAE,CAAC,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;IACtE,8EAA8E;IAC9E,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;CACnC;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,CAAC,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC;IACjD,QAAQ,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,gBAAgB,CAAC,OAAO,CAAC,EACzB,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CACzD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,YAAY,CAyB7E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,YAAY,EAAE,EACrB,MAAM,CAAC,EAAE,sBAAsB,GAC9B,gBAAgB,CAAC,OAAO,CAAC,CAyB3B"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Turn a CLI `argv` slice into the flat argument object `executeToolMethod`
3
+ * parses — the CLI transport's front half, the counterpart of how the HTTP
4
+ * transport slices a `Request`.
5
+ *
6
+ * Two jobs the other transports never face:
7
+ * 1. **Reserved options.** `--json`, `--wait`, `--output-dir`, … are CLI
8
+ * behaviour, not tool arguments — they are stripped before the rest is read
9
+ * as tool args.
10
+ * 2. **String → typed coercion.** Every argv token is a string; the tool's Zod
11
+ * schema says what each field should be. We coerce primitives here
12
+ * (`--count 5` → `5`, `--flag` → `true`) and leave array / object values as
13
+ * strings for `executeToolMethod`'s `coerceJson` pass (the same path the MCP
14
+ * transport uses for an LLM's double-serialized JSON).
15
+ *
16
+ * The advertised schema is never mutated — coercion operates on the arguments,
17
+ * so a CLI call validates against the exact same contract schema an HTTP or MCP
18
+ * call does (ADR 0014 parity).
19
+ */
20
+ import { z } from 'zod';
21
+ /** CLI-behaviour flags, parsed out of argv before the tool arguments. */
22
+ export interface CliRunOptions {
23
+ /** `--json` — emit raw JSON on stdout for piping. */
24
+ json: boolean;
25
+ /** `--wait` — block-poll an async result to a terminal state. */
26
+ wait: boolean;
27
+ /** `--wait-timeout <seconds>` — override the poll timeout. */
28
+ waitTimeout?: number;
29
+ /** `--output-dir <dir>` — download result media into this directory. */
30
+ outputDir?: string;
31
+ /** `--quiet` — suppress non-essential stderr chatter. */
32
+ quiet: boolean;
33
+ /** `--dry-run` — print the resolved call instead of executing it. */
34
+ dryRun: boolean;
35
+ /** `--help` / `-h` — print usage for the command. */
36
+ help: boolean;
37
+ }
38
+ export interface ParsedCliArgs {
39
+ /** The flat tool-argument object handed to `executeToolMethod`. */
40
+ toolArgs: Record<string, unknown>;
41
+ /** The CLI-behaviour flags. */
42
+ options: CliRunOptions;
43
+ }
44
+ type FieldKind = 'boolean' | 'number' | 'bigint' | 'date' | 'string' | 'enum' | 'array' | 'object' | 'other';
45
+ interface FieldInfo {
46
+ kind: FieldKind;
47
+ /** Element kind for an `array` field — drives per-element coercion. */
48
+ elementKind?: FieldKind;
49
+ }
50
+ /**
51
+ * Map a merged tool schema to per-field kind info — what each `--flag` should
52
+ * coerce to. A non-object schema (a union) yields an empty map: every value is
53
+ * left as a string and the schema validates it.
54
+ */
55
+ export declare function describeSchemaFields(schema: z.ZodType | undefined): Map<string, FieldInfo>;
56
+ /**
57
+ * Parse a command's argv slice (everything after the command name) against its
58
+ * merged tool schema.
59
+ *
60
+ * Supported forms:
61
+ * - `--key value` / `--key=value` / `-` repeated for arrays
62
+ * - `--flag` boolean presence, `--no-flag` to negate
63
+ * - `--a.b=c` dotted path → nested object (loose-coerced leaf)
64
+ * - positional args fill non-boolean fields in schema-declaration order
65
+ */
66
+ export declare function parseCliArgs(argv: string[], schema: z.ZodType | undefined): ParsedCliArgs;
67
+ export {};
68
+ //# sourceMappingURL=cli-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../../src/tools/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,IAAI,EAAE,OAAO,CAAC;IACd,iEAAiE;IACjE,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,+BAA+B;IAC/B,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,KAAK,SAAS,GACV,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,MAAM,GACN,OAAO,GACP,QAAQ,GACR,OAAO,CAAC;AAEZ,UAAU,SAAS;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,uEAAuE;IACvE,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AA6BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAa1F;AAmFD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,GAAG,aAAa,CAkIzF"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Render a `ToolResult` for the CLI surface and map it to a process exit code.
3
+ *
4
+ * Output is JSON — the CLI's audience is agents (Skills via Bash), scripts and
5
+ * `| jq`, for which structured JSON is the right shape, not a hand-formatted
6
+ * table. The default is pretty-printed (indented, the same shape an MCP tool
7
+ * returns); `--json` switches to a compact single line for piping.
8
+ *
9
+ * stdout is reserved for that result; an error goes to stderr as the same
10
+ * model-facing `{ error, details, _hint }` object the MCP / agent transports
11
+ * return (`formatToolError`), so a script can keep `2>/dev/null` clean while
12
+ * still parsing a success.
13
+ */
14
+ import type { ToolResult } from './execute';
15
+ /** Map a `ToolResult.code` to a process exit code. */
16
+ export type ExitCodeMap = Record<string, number>;
17
+ /**
18
+ * Conventional exit codes — `0` success, distinct non-zero per error class so a
19
+ * script can branch on `$?`. Merged under any `CliConfig.exitCodes` override.
20
+ */
21
+ export declare const DEFAULT_EXIT_CODES: ExitCodeMap;
22
+ export interface CliWriters {
23
+ stdout: (text: string) => void;
24
+ stderr: (text: string) => void;
25
+ }
26
+ export interface EmitOptions {
27
+ /** Compact single-line JSON (for `| jq` / scripts); otherwise pretty-printed. */
28
+ json: boolean;
29
+ toolName: string;
30
+ errorHint?: (toolName: string, errorCode: string) => string | null;
31
+ exitCodes?: ExitCodeMap;
32
+ }
33
+ /**
34
+ * Write a result to the right stream and return the exit code. Success → JSON
35
+ * on stdout (pretty by default, compact with `--json`), exit `0`. Failure → the
36
+ * error JSON on stderr, exit per the code map (unknown code → `1`).
37
+ */
38
+ export declare function emitResult(result: ToolResult, writers: CliWriters, opts: EmitOptions): number;
39
+ //# sourceMappingURL=cli-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-format.d.ts","sourceRoot":"","sources":["../../src/tools/cli-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,sDAAsD;AACtD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAUhC,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,WAAW,GAChB,MAAM,CAeR"}