@zmdb/web 1.0.0-beta.1

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 (179) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +49 -0
  3. package/dist/app/bridge.d.ts +12 -0
  4. package/dist/app/bridge.d.ts.map +1 -0
  5. package/dist/app/bridge.js +16 -0
  6. package/dist/app/bridge.js.map +1 -0
  7. package/dist/app/index.d.ts +23 -0
  8. package/dist/app/index.d.ts.map +1 -0
  9. package/dist/app/index.js +47 -0
  10. package/dist/app/index.js.map +1 -0
  11. package/dist/bench/index.d.ts +68 -0
  12. package/dist/bench/index.d.ts.map +1 -0
  13. package/dist/bench/index.js +250 -0
  14. package/dist/bench/index.js.map +1 -0
  15. package/dist/compression/index.d.ts +13 -0
  16. package/dist/compression/index.d.ts.map +1 -0
  17. package/dist/compression/index.js +211 -0
  18. package/dist/compression/index.js.map +1 -0
  19. package/dist/context/index.d.ts +74 -0
  20. package/dist/context/index.d.ts.map +1 -0
  21. package/dist/context/index.js +118 -0
  22. package/dist/context/index.js.map +1 -0
  23. package/dist/contract/__fixtures__/http-client.generated.d.ts +70 -0
  24. package/dist/contract/__fixtures__/http-client.generated.d.ts.map +1 -0
  25. package/dist/contract/__fixtures__/http-client.generated.js +86 -0
  26. package/dist/contract/__fixtures__/http-client.generated.js.map +1 -0
  27. package/dist/contract/__fixtures__/http-convergence.d.ts +396 -0
  28. package/dist/contract/__fixtures__/http-convergence.d.ts.map +1 -0
  29. package/dist/contract/__fixtures__/http-convergence.js +425 -0
  30. package/dist/contract/__fixtures__/http-convergence.js.map +1 -0
  31. package/dist/contract/compiler/client.d.ts +12 -0
  32. package/dist/contract/compiler/client.d.ts.map +1 -0
  33. package/dist/contract/compiler/client.js +1293 -0
  34. package/dist/contract/compiler/client.js.map +1 -0
  35. package/dist/contract/compiler/index.d.ts +18 -0
  36. package/dist/contract/compiler/index.d.ts.map +1 -0
  37. package/dist/contract/compiler/index.js +1058 -0
  38. package/dist/contract/compiler/index.js.map +1 -0
  39. package/dist/contract/index.d.ts +237 -0
  40. package/dist/contract/index.d.ts.map +1 -0
  41. package/dist/contract/index.js +22 -0
  42. package/dist/contract/index.js.map +1 -0
  43. package/dist/csrf/index.d.ts +15 -0
  44. package/dist/csrf/index.d.ts.map +1 -0
  45. package/dist/csrf/index.js +218 -0
  46. package/dist/csrf/index.js.map +1 -0
  47. package/dist/data/index.d.ts +35 -0
  48. package/dist/data/index.d.ts.map +1 -0
  49. package/dist/data/index.js +58 -0
  50. package/dist/data/index.js.map +1 -0
  51. package/dist/devtools/index.d.ts +74 -0
  52. package/dist/devtools/index.d.ts.map +1 -0
  53. package/dist/devtools/index.js +552 -0
  54. package/dist/devtools/index.js.map +1 -0
  55. package/dist/dto-pipes/index.d.ts +45 -0
  56. package/dist/dto-pipes/index.d.ts.map +1 -0
  57. package/dist/dto-pipes/index.js +78 -0
  58. package/dist/dto-pipes/index.js.map +1 -0
  59. package/dist/gateways/index.d.ts +31 -0
  60. package/dist/gateways/index.d.ts.map +1 -0
  61. package/dist/gateways/index.js +138 -0
  62. package/dist/gateways/index.js.map +1 -0
  63. package/dist/health/index.d.ts +20 -0
  64. package/dist/health/index.d.ts.map +1 -0
  65. package/dist/health/index.js +148 -0
  66. package/dist/health/index.js.map +1 -0
  67. package/dist/http-token.d.ts +2 -0
  68. package/dist/http-token.d.ts.map +1 -0
  69. package/dist/http-token.js +21 -0
  70. package/dist/http-token.js.map +1 -0
  71. package/dist/index.d.ts +18 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +40 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/integrations/index.d.ts +11 -0
  76. package/dist/integrations/index.d.ts.map +1 -0
  77. package/dist/integrations/index.js +39 -0
  78. package/dist/integrations/index.js.map +1 -0
  79. package/dist/middleware/errors.d.ts +14 -0
  80. package/dist/middleware/errors.d.ts.map +1 -0
  81. package/dist/middleware/errors.js +18 -0
  82. package/dist/middleware/errors.js.map +1 -0
  83. package/dist/middleware/index.d.ts +46 -0
  84. package/dist/middleware/index.d.ts.map +1 -0
  85. package/dist/middleware/index.js +64 -0
  86. package/dist/middleware/index.js.map +1 -0
  87. package/dist/modules/__fixtures__/large-graph.d.ts +239 -0
  88. package/dist/modules/__fixtures__/large-graph.d.ts.map +1 -0
  89. package/dist/modules/__fixtures__/large-graph.js +483 -0
  90. package/dist/modules/__fixtures__/large-graph.js.map +1 -0
  91. package/dist/openapi/__fixtures__/entities.d.ts +8 -0
  92. package/dist/openapi/__fixtures__/entities.d.ts.map +1 -0
  93. package/dist/openapi/__fixtures__/entities.js +4 -0
  94. package/dist/openapi/__fixtures__/entities.js.map +1 -0
  95. package/dist/openapi/__fixtures__/openapi-tools.fixture.d.ts +38 -0
  96. package/dist/openapi/__fixtures__/openapi-tools.fixture.d.ts.map +1 -0
  97. package/dist/openapi/__fixtures__/openapi-tools.fixture.js +172 -0
  98. package/dist/openapi/__fixtures__/openapi-tools.fixture.js.map +1 -0
  99. package/dist/openapi/__fixtures__/route-schemas.d.ts +2 -0
  100. package/dist/openapi/__fixtures__/route-schemas.d.ts.map +1 -0
  101. package/dist/openapi/__fixtures__/route-schemas.js +17 -0
  102. package/dist/openapi/__fixtures__/route-schemas.js.map +1 -0
  103. package/dist/openapi/index.d.ts +61 -0
  104. package/dist/openapi/index.d.ts.map +1 -0
  105. package/dist/openapi/index.js +314 -0
  106. package/dist/openapi/index.js.map +1 -0
  107. package/dist/pipeline/guards.d.ts +9 -0
  108. package/dist/pipeline/guards.d.ts.map +1 -0
  109. package/dist/pipeline/guards.js +11 -0
  110. package/dist/pipeline/guards.js.map +1 -0
  111. package/dist/pipeline/index.d.ts +141 -0
  112. package/dist/pipeline/index.d.ts.map +1 -0
  113. package/dist/pipeline/index.js +1624 -0
  114. package/dist/pipeline/index.js.map +1 -0
  115. package/dist/routing/index.d.ts +40 -0
  116. package/dist/routing/index.d.ts.map +1 -0
  117. package/dist/routing/index.js +162 -0
  118. package/dist/routing/index.js.map +1 -0
  119. package/dist/static/index.d.ts +14 -0
  120. package/dist/static/index.d.ts.map +1 -0
  121. package/dist/static/index.js +348 -0
  122. package/dist/static/index.js.map +1 -0
  123. package/dist/testing/index.d.ts +20 -0
  124. package/dist/testing/index.d.ts.map +1 -0
  125. package/dist/testing/index.js +32 -0
  126. package/dist/testing/index.js.map +1 -0
  127. package/dist/traced-router.d.ts +5 -0
  128. package/dist/traced-router.d.ts.map +1 -0
  129. package/dist/traced-router.js +6 -0
  130. package/dist/traced-router.js.map +1 -0
  131. package/dist/upload/index.d.ts +28 -0
  132. package/dist/upload/index.d.ts.map +1 -0
  133. package/dist/upload/index.js +410 -0
  134. package/dist/upload/index.js.map +1 -0
  135. package/dist/versioning/index.d.ts +35 -0
  136. package/dist/versioning/index.d.ts.map +1 -0
  137. package/dist/versioning/index.js +66 -0
  138. package/dist/versioning/index.js.map +1 -0
  139. package/dist/versioning/runtime.d.ts +5 -0
  140. package/dist/versioning/runtime.d.ts.map +1 -0
  141. package/dist/versioning/runtime.js +34 -0
  142. package/dist/versioning/runtime.js.map +1 -0
  143. package/package.json +143 -0
  144. package/src/app/bridge.ts +39 -0
  145. package/src/app/index.ts +76 -0
  146. package/src/bench/index.ts +329 -0
  147. package/src/compression/index.ts +255 -0
  148. package/src/context/index.ts +181 -0
  149. package/src/contract/__fixtures__/http-client.generated.ts +73 -0
  150. package/src/contract/__fixtures__/http-client.generated.ts.map +1 -0
  151. package/src/contract/__fixtures__/http-convergence.ts +564 -0
  152. package/src/contract/compiler/client.ts +1518 -0
  153. package/src/contract/compiler/index.ts +1457 -0
  154. package/src/contract/index.ts +266 -0
  155. package/src/csrf/index.ts +264 -0
  156. package/src/data/index.ts +65 -0
  157. package/src/devtools/index.ts +727 -0
  158. package/src/dto-pipes/index.ts +93 -0
  159. package/src/gateways/index.ts +180 -0
  160. package/src/health/index.ts +198 -0
  161. package/src/http-token.ts +22 -0
  162. package/src/index.ts +167 -0
  163. package/src/integrations/index.ts +50 -0
  164. package/src/middleware/errors.ts +17 -0
  165. package/src/middleware/index.ts +108 -0
  166. package/src/modules/__fixtures__/large-graph.ts +540 -0
  167. package/src/openapi/__fixtures__/entities.ts +19 -0
  168. package/src/openapi/__fixtures__/openapi-tools.fixture.ts +212 -0
  169. package/src/openapi/__fixtures__/route-schemas.ts +27 -0
  170. package/src/openapi/index.ts +483 -0
  171. package/src/pipeline/guards.ts +23 -0
  172. package/src/pipeline/index.ts +2041 -0
  173. package/src/routing/index.ts +201 -0
  174. package/src/static/index.ts +443 -0
  175. package/src/testing/index.ts +58 -0
  176. package/src/traced-router.ts +8 -0
  177. package/src/upload/index.ts +489 -0
  178. package/src/versioning/index.ts +106 -0
  179. package/src/versioning/runtime.ts +38 -0
@@ -0,0 +1,78 @@
1
+ // @zmdb/web — DTO validation & serialization pipes (epic #297, spec ./SPEC.md).
2
+ // Bind routes to schema-derived DTO validation (a Pipe) and entity serialization
3
+ // (an Interceptor), built on the middleware chain. Zero runtime parser (consumer
4
+ // supplies the AOT assert); no `as` on the consumer surface.
5
+ import { parseMultipart } from '../upload/index.js';
6
+ /**
7
+ * A validation pipe: runs `validator` (e.g. `assert<CreateDTO<S>>`) on the body,
8
+ * yielding the typed value. A throw becomes the chain's 400. The framework
9
+ * embeds no parser — validation is the consumer's AOT `assert`.
10
+ */
11
+ export function validationPipe(validator) {
12
+ return {
13
+ transform(value) {
14
+ return validator(value);
15
+ },
16
+ };
17
+ }
18
+ /**
19
+ * A pipe that only converts: the wire→app decode at the boundary (plan D3).
20
+ *
21
+ * Separate from `validationPipe` because the two do different jobs and the order matters.
22
+ * `wireDecoder(Schema)` turns the ISO string JSON carries into the `Date` a `CreateDTO`
23
+ * asks for; the validator then checks the app type. Decoding after validation would mean
24
+ * validating the wrong layer, and doing both in one function is how a validator ends up
25
+ * accepting `Date | string` and checking neither.
26
+ */
27
+ export function decodePipe(decode) {
28
+ return {
29
+ transform(value) {
30
+ return decode(value);
31
+ },
32
+ };
33
+ }
34
+ /**
35
+ * Parse the exact request bytes as multipart at the ordinary pipe boundary.
36
+ *
37
+ * The returned `Multipart` remains available to later validation pipes, so form
38
+ * fields use the same validation path as JSON bodies.
39
+ */
40
+ export function multipartPipe(limits = {}) {
41
+ const configured = { ...limits };
42
+ return {
43
+ transform(value, ctx) {
44
+ return parseMultipart(value, ctx.headers['content-type'] ?? '', configured);
45
+ },
46
+ };
47
+ }
48
+ /**
49
+ * A serialization interceptor: transforms the handler's result via `serialize`
50
+ * (default: identity — the pipeline JSON-encodes downstream). Pass an entity
51
+ * serializer to shape the response from `Entity<S>`.
52
+ */
53
+ export function serializationInterceptor(serialize = r => r) {
54
+ return {
55
+ async intercept(_ctx, next) {
56
+ const result = await next();
57
+ return serialize(result);
58
+ },
59
+ };
60
+ }
61
+ /**
62
+ * Compose a Chain with the validation pipe (+ optional decode pipe and
63
+ * serialization interceptor), so a route adopts DTO validation/serialization in
64
+ * one call.
65
+ */
66
+ export function dtoChain(options) {
67
+ return {
68
+ guards: [],
69
+ // Decode first, then validate: the validator checks the app type, which is only what
70
+ // the body holds once the two types JSON cannot carry have been converted.
71
+ pipes: options.decode === undefined
72
+ ? [validationPipe(options.validate)]
73
+ : [decodePipe(options.decode), validationPipe(options.validate)],
74
+ interceptors: options.serialize === undefined ? [] : [serializationInterceptor(options.serialize)],
75
+ filters: [],
76
+ };
77
+ }
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dto-pipes/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,iFAAiF;AACjF,6DAA6D;AAG7D,OAAO,EAAE,cAAc,EAAqC,MAAM,oBAAoB,CAAC;AAEvF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAI,SAA8B;IAC9D,OAAO;QACL,SAAS,CAAC,KAAc;YACtB,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAA8B,MAA0B;IAChF,OAAO;QACL,SAAS,CAAC,KAAS;YACjB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAM,GAA0B,EAAE;IAC9D,MAAM,UAAU,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IACjC,OAAO;QACL,SAAS,CAAC,KAAK,EAAE,GAAG;YAClB,OAAO,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9E,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAAS,GAAiC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvF,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI;YACxB,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;YAC5B,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAUD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAI,OAA2B;IACrD,OAAO;QACL,MAAM,EAAE,EAAE;QACV,qFAAqF;QACrF,2EAA2E;QAC3E,KAAK,EACH,OAAO,CAAC,MAAM,KAAK,SAAS;YAC1B,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACpC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpE,YAAY,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClG,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import '@zmdb/app';
2
+ /** The context a subscribed handler receives. */
3
+ export interface MessageCtx<T = unknown> {
4
+ readonly event: string;
5
+ readonly data: T;
6
+ }
7
+ /** A recorded event subscription. */
8
+ export interface Subscription {
9
+ readonly event: string;
10
+ readonly handlerName: string;
11
+ }
12
+ /** Stage-3 class decorator: mark a gateway with an optional namespace. */
13
+ export declare function Gateway(namespace?: string): <T extends abstract new (...args: never[]) => unknown>(_target: T, context: ClassDecoratorContext<T>) => void;
14
+ /** Stage-3 method decorator: subscribe the method to an event. */
15
+ export declare function Subscribe(event: string): (_target: (...args: never[]) => unknown, context: ClassMethodDecoratorContext) => void;
16
+ /** Read a gateway class's subscriptions (declaration order). No reflection. */
17
+ export declare function getSubscriptions(gateway: abstract new (...args: never[]) => unknown): readonly Subscription[];
18
+ /** A dispatcher routing an event+message to the gateway's matching handler. */
19
+ export interface GatewayDispatcher {
20
+ dispatch(event: string, data: unknown): Promise<unknown>;
21
+ }
22
+ /** Build a dispatcher for a gateway instance. */
23
+ export declare function createGatewayDispatcher(gateway: object): GatewayDispatcher;
24
+ /** A Server-Sent-Events frame. */
25
+ export interface SseFrame<T = unknown> {
26
+ readonly event?: string;
27
+ readonly data: T;
28
+ }
29
+ /** Turn an async iterable of frames into an SSE-framed byte stream. */
30
+ export declare function sseStream(source: AsyncIterable<SseFrame>): ReadableStream<Uint8Array>;
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,CAAC;AAEnB,iDAAiD;AACjD,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CAClB;AAED,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAgBD,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,SAAS,SAAK,IACnB,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,WAC1D,CAAC,WACD,qBAAqB,CAAC,CAAC,CAAC,KAChC,IAAI,CAGR;AAED,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,aACX,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,WAAW,2BAA2B,KAAG,IAAI,CAUrG;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAAG,SAAS,YAAY,EAAE,CAM7G;AAID,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AAED,iDAAiD;AACjD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAoB1E;AAqBD,kCAAkC;AAClC,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CAClB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,CAyDrF"}
@@ -0,0 +1,138 @@
1
+ // @zmdb/web — WebSocket & SSE gateways (epic #307, spec ./SPEC.md). @Gateway/
2
+ // @Subscribe store handlers in context.metadata; a dispatcher routes events with
3
+ // a typed message ctx; sseStream frames an async iterable as SSE. No ws
4
+ // dependency, no reflection, no `as` on the consumer surface.
5
+ import '@zmdb/app';
6
+ const NAMESPACE = Symbol('zmdb.web.gateway.namespace');
7
+ const SUBSCRIPTIONS = Symbol('zmdb.web.gateway.subscriptions');
8
+ // boundary: our @Gateway/@Subscribe decorators are the only writers of these
9
+ // slots, so viewing the record through GatewayMetadata is sound (§2.1).
10
+ function gatewayView(metadata) {
11
+ return metadata;
12
+ }
13
+ /** Stage-3 class decorator: mark a gateway with an optional namespace. */
14
+ export function Gateway(namespace = '') {
15
+ return function (_target, context) {
16
+ gatewayView(context.metadata)[NAMESPACE] = namespace;
17
+ };
18
+ }
19
+ /** Stage-3 method decorator: subscribe the method to an event. */
20
+ export function Subscribe(event) {
21
+ return function (_target, context) {
22
+ const handlerName = typeof context.name === 'string' ? context.name : context.name.toString();
23
+ const view = gatewayView(context.metadata);
24
+ const existing = view[SUBSCRIPTIONS];
25
+ if (existing === undefined) {
26
+ view[SUBSCRIPTIONS] = [{ event, handlerName }];
27
+ }
28
+ else {
29
+ existing.push({ event, handlerName });
30
+ }
31
+ };
32
+ }
33
+ /** Read a gateway class's subscriptions (declaration order). No reflection. */
34
+ export function getSubscriptions(gateway) {
35
+ const metadata = gateway[Symbol.metadata];
36
+ if (metadata === undefined || metadata === null) {
37
+ return [];
38
+ }
39
+ return gatewayView(metadata)[SUBSCRIPTIONS] ?? [];
40
+ }
41
+ /** Build a dispatcher for a gateway instance. */
42
+ export function createGatewayDispatcher(gateway) {
43
+ const ctor = gateway.constructor;
44
+ const subs = typeof ctor === 'function' ? getSubscriptions(gatewayClass(ctor)) : [];
45
+ const byEvent = new Map();
46
+ for (const sub of subs) {
47
+ byEvent.set(sub.event, sub.handlerName);
48
+ }
49
+ return {
50
+ async dispatch(event, data) {
51
+ const handlerName = byEvent.get(event);
52
+ if (handlerName === undefined) {
53
+ return undefined;
54
+ }
55
+ const handler = readMessageHandler(gateway, handlerName);
56
+ if (handler === undefined) {
57
+ return undefined;
58
+ }
59
+ return handler({ event, data });
60
+ },
61
+ };
62
+ }
63
+ // boundary: an instance's `.constructor` carries the gateway metadata; narrowing
64
+ // it for getSubscriptions is sound (§2.1).
65
+ function gatewayClass(ctor) {
66
+ return ctor;
67
+ }
68
+ // boundary: @Subscribe only records names of the gateway's own methods; reading
69
+ // one by name and calling it as a MessageHandler is sound (§2.1).
70
+ function readMessageHandler(gateway, name) {
71
+ const value = Reflect.get(gateway, name);
72
+ if (typeof value !== 'function') {
73
+ return undefined;
74
+ }
75
+ const bound = value.bind(gateway);
76
+ return bound;
77
+ }
78
+ /** Turn an async iterable of frames into an SSE-framed byte stream. */
79
+ export function sseStream(source) {
80
+ const encoder = new TextEncoder();
81
+ const iterator = source[Symbol.asyncIterator]();
82
+ let state = 'open';
83
+ let cancellation;
84
+ const cancel = (reason) => {
85
+ if (state === 'closed') {
86
+ return Promise.resolve();
87
+ }
88
+ if (cancellation !== undefined) {
89
+ return cancellation;
90
+ }
91
+ state = 'cancelling';
92
+ cancellation = (async () => {
93
+ try {
94
+ await iterator.return?.(reason);
95
+ }
96
+ catch {
97
+ // A client disconnect is normal teardown. This helper has no error
98
+ // reporter, so a cleanup rejection must not become a server failure;
99
+ // sources that need reporting own it inside return/finally.
100
+ }
101
+ finally {
102
+ state = 'closed';
103
+ }
104
+ })();
105
+ return cancellation;
106
+ };
107
+ return new ReadableStream({
108
+ async pull(controller) {
109
+ if (state !== 'open') {
110
+ return;
111
+ }
112
+ let next;
113
+ try {
114
+ next = await iterator.next();
115
+ }
116
+ catch (error) {
117
+ if (state !== 'open') {
118
+ return;
119
+ }
120
+ state = 'closed';
121
+ throw error;
122
+ }
123
+ if (state !== 'open') {
124
+ return;
125
+ }
126
+ const { value, done } = next;
127
+ if (done) {
128
+ state = 'closed';
129
+ controller.close();
130
+ return;
131
+ }
132
+ const prefix = value.event === undefined ? '' : `event: ${value.event}\n`;
133
+ controller.enqueue(encoder.encode(`${prefix}data: ${JSON.stringify(value.data)}\n\n`));
134
+ },
135
+ cancel,
136
+ });
137
+ }
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { DetailedCheck, HealthChecks } from '@zmdb/app/health';
2
+ import { type WebResponse } from '../pipeline/index.js';
3
+ export interface HealthProbes {
4
+ readonly live: () => WebResponse;
5
+ readonly ready: () => Promise<WebResponse>;
6
+ }
7
+ export interface DetailedBody {
8
+ readonly status: 'ok' | 'error';
9
+ readonly checks: readonly DetailedCheck[];
10
+ }
11
+ /** Build the public liveness and readiness handlers from this application's explicit checks. */
12
+ export declare function healthRoutes(checks: HealthChecks): HealthProbes;
13
+ /**
14
+ * Build the opt-in detailed readiness handler.
15
+ *
16
+ * Mount this separate handler through the application's normal RouteOptions.guards composition.
17
+ * The public handlers returned by healthRoutes never expose names, details, or timings.
18
+ */
19
+ export declare function detailedReadyRoute(checks: HealthChecks): () => Promise<WebResponse>;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/health/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,aAAa,EAAE,YAAY,EAAiC,MAAM,kBAAkB,CAAC;AAEhH,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAK9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,WAAW,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;CAC3C;AAwJD,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAU/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAOnF"}
@@ -0,0 +1,148 @@
1
+ // @zmdb/web — HTTP liveness and readiness routes (#581, epic #578).
2
+ // Liveness is synchronous by type. Readiness is concurrent, bounded, success-cached,
3
+ // and coalesced while a probe invocation is still waiting.
4
+ import { json } from '../pipeline/index.js';
5
+ const DEFAULT_CACHE_MS = 1000;
6
+ const DEADLINE_GRACE_MS = 50;
7
+ function createCheckState() {
8
+ return {};
9
+ }
10
+ function publicResponse(ok) {
11
+ return json({ status: ok ? 'ok' : 'error' }, ok ? {} : { status: 503 });
12
+ }
13
+ function runLiveness(checks) {
14
+ for (const check of checks) {
15
+ try {
16
+ if (!check.run()) {
17
+ return false;
18
+ }
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ return true;
25
+ }
26
+ function createReadinessRunner(checks) {
27
+ const entries = checks.map(check => ({ check, state: createCheckState() }));
28
+ return {
29
+ run: () => {
30
+ if (entries.length === 0) {
31
+ return Promise.resolve([]);
32
+ }
33
+ const completed = entries.map(() => undefined);
34
+ const running = entries.map(({ check, state }, index) => runReadinessCheck(check, state).then(result => {
35
+ completed[index] = result;
36
+ return result;
37
+ }));
38
+ const aggregateDeadline = Math.max(...entries.map(({ check }) => check.timeoutMs)) + DEADLINE_GRACE_MS;
39
+ const startedAt = Date.now();
40
+ return new Promise(resolve => {
41
+ let settled = false;
42
+ const finish = (results) => {
43
+ if (settled) {
44
+ return;
45
+ }
46
+ settled = true;
47
+ clearTimeout(timer);
48
+ resolve(results);
49
+ };
50
+ const timer = setTimeout(() => {
51
+ finish(entries.map(({ check }, index) => completed[index] ?? {
52
+ name: check.name,
53
+ ok: false,
54
+ detail: 'timeout',
55
+ durationMs: Math.max(0, Date.now() - startedAt),
56
+ }));
57
+ }, aggregateDeadline);
58
+ void Promise.all(running).then(finish);
59
+ });
60
+ },
61
+ };
62
+ }
63
+ function runReadinessCheck(check, state) {
64
+ const now = Date.now();
65
+ if (state.cached !== undefined) {
66
+ if (now < state.cached.expiresAt) {
67
+ return Promise.resolve(state.cached.result);
68
+ }
69
+ delete state.cached;
70
+ }
71
+ if (state.inFlight !== undefined) {
72
+ return state.inFlight;
73
+ }
74
+ const startedAt = now;
75
+ const controller = new AbortController();
76
+ const pending = new Promise(resolve => {
77
+ let settled = false;
78
+ let timedOut = false;
79
+ const finish = (result) => {
80
+ if (settled) {
81
+ return;
82
+ }
83
+ settled = true;
84
+ clearTimeout(abortTimer);
85
+ clearTimeout(deadlineTimer);
86
+ const detailed = {
87
+ name: check.name,
88
+ ok: result.ok,
89
+ ...(result.detail === undefined ? {} : { detail: result.detail }),
90
+ durationMs: Math.max(0, Date.now() - startedAt),
91
+ };
92
+ if (result.ok) {
93
+ state.cached = {
94
+ expiresAt: Date.now() + (check.cacheMs ?? DEFAULT_CACHE_MS),
95
+ result: detailed,
96
+ };
97
+ }
98
+ resolve(detailed);
99
+ };
100
+ const abortTimer = setTimeout(() => {
101
+ timedOut = true;
102
+ controller.abort();
103
+ }, check.timeoutMs);
104
+ const deadlineTimer = setTimeout(() => {
105
+ finish({ ok: false, detail: 'timeout' });
106
+ }, check.timeoutMs + DEADLINE_GRACE_MS);
107
+ try {
108
+ void check.run(controller.signal).then(result => finish(timedOut ? { ok: false, detail: 'timeout' } : result), () => finish(timedOut ? { ok: false, detail: 'timeout' } : { ok: false }));
109
+ }
110
+ catch {
111
+ finish({ ok: false });
112
+ }
113
+ });
114
+ state.inFlight = pending;
115
+ void pending.finally(() => {
116
+ if (state.inFlight === pending) {
117
+ delete state.inFlight;
118
+ }
119
+ });
120
+ return pending;
121
+ }
122
+ /** Build the public liveness and readiness handlers from this application's explicit checks. */
123
+ export function healthRoutes(checks) {
124
+ const liveness = checks.liveness ?? [];
125
+ const readiness = createReadinessRunner(checks.readiness ?? []);
126
+ return {
127
+ live: () => publicResponse(runLiveness(liveness)),
128
+ ready: async () => {
129
+ const results = await readiness.run();
130
+ return publicResponse(results.every(result => result.ok));
131
+ },
132
+ };
133
+ }
134
+ /**
135
+ * Build the opt-in detailed readiness handler.
136
+ *
137
+ * Mount this separate handler through the application's normal RouteOptions.guards composition.
138
+ * The public handlers returned by healthRoutes never expose names, details, or timings.
139
+ */
140
+ export function detailedReadyRoute(checks) {
141
+ const readiness = createReadinessRunner(checks.readiness ?? []);
142
+ return async () => {
143
+ const results = await readiness.run();
144
+ const ok = results.every(result => result.ok);
145
+ return json({ status: ok ? 'ok' : 'error', checks: results }, ok ? {} : { status: 503 });
146
+ };
147
+ }
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/health/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function isHttpTokenCode(code: number): boolean;
2
+ //# sourceMappingURL=http-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-token.d.ts","sourceRoot":"","sources":["../src/http-token.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAqBrD"}
@@ -0,0 +1,21 @@
1
+ export function isHttpTokenCode(code) {
2
+ return ((code >= 48 && code <= 57) ||
3
+ (code >= 65 && code <= 90) ||
4
+ (code >= 97 && code <= 122) ||
5
+ code === 33 ||
6
+ code === 35 ||
7
+ code === 36 ||
8
+ code === 37 ||
9
+ code === 38 ||
10
+ code === 39 ||
11
+ code === 42 ||
12
+ code === 43 ||
13
+ code === 45 ||
14
+ code === 46 ||
15
+ code === 94 ||
16
+ code === 95 ||
17
+ code === 96 ||
18
+ code === 124 ||
19
+ code === 126);
20
+ }
21
+ //# sourceMappingURL=http-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-token.js","sourceRoot":"","sources":["../src/http-token.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,CACL,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;QAC1B,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;QAC1B,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC;QAC3B,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,EAAE;QACX,IAAI,KAAK,GAAG;QACZ,IAAI,KAAK,GAAG,CACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import '@zmdb/app';
2
+ export { Controller, Get, Post, Put, Patch, Delete, Public, getRoutes, isPublic, type RouteDefinition, type ResolvedRoute, } from './routing/index.js';
3
+ export { defineHttpContract, httpOperation, type AuthorizationCodeFlow, type ClientCredentialsFlow, type CompiledHttpContract, type CompiledHttpOperation, type HttpBodyDeclaration, type HttpBodyIR, type HttpBodyKind, type HttpContractDeclaration, type HttpContractIR, type HttpController, type HttpMethod, type HttpOperationDeclaration, type HttpOperationIR, type HttpOperationTypes, type HttpParameterDeclaration, type HttpParameterIR, type HttpRequestBodyDeclaration, type HttpRequestBodyIR, type HttpResponseDeclaration, type HttpResponseHeaderDeclaration, type HttpResponseHeaderIR, type HttpResponseIR, type HttpTypeIR, type HttpVersionDeclaration, type HttpVersionIR, type ImplicitFlow, type JsonValue, type OAuthFlow, type OAuthFlows, type PasswordFlow, type SecurityRequirement, type SecurityScheme, } from './contract/index.js';
4
+ export { Version, VersionNeutral, versionsOf, type VersionStrategy } from './versioning/index.js';
5
+ export { extractParams, compilePattern, countSegments, matchCompiled, type CompiledPattern, type PathParams, type QueryValues, type Ctx, type HandlerFor, } from './context/index.js';
6
+ export { createRouter, toNodeHandler, toFetchHandler, json, text, respond, bytes, stream, file, bodyText, type Router, type WebRequest, type WebResponse, type ResponseBody, type RouteOptions, type GuardRegistry, type RouterOptions, type ResponseOptions, type StreamOptions, type FileResponseOptions, type AdapterOptions, } from './pipeline/index.js';
7
+ export { createStaticHandler, type StaticHandler, type StaticOptions } from './static/index.js';
8
+ export { compress, compressionInterceptor, type CompressionOptions, type ContentCoding } from './compression/index.js';
9
+ export { createTracedRouter } from './traced-router.js';
10
+ export { validateWith } from './data/index.js';
11
+ export { runChain, ChainError, type AnyCtx, type Guard, type SecurityAwareGuard, type Pipe, type Interceptor, type ExceptionFilter, type Chain, type ChainHandler, } from './middleware/index.js';
12
+ export { createApp, type WebApplication, type WebApplicationOptions } from './app/index.js';
13
+ export { validationPipe, multipartPipe, serializationInterceptor, dtoChain, type DtoChainOptions, } from './dto-pipes/index.js';
14
+ export { parseMultipart, UPLOAD_DEFAULTS, type Multipart, type UploadLimits, type UploadPart } from './upload/index.js';
15
+ export { createCsrf, type Csrf, type CsrfOptions } from './csrf/index.js';
16
+ export { toOpenApi, serveOpenApi, type JsonSchema, type OpenApiDocument, type OpenApiRenderOptions, } from './openapi/index.js';
17
+ export { Gateway, Subscribe, getSubscriptions, createGatewayDispatcher, sseStream, type MessageCtx, type Subscription, type GatewayDispatcher, type SseFrame, } from './gateways/index.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,40 @@
1
+ // @zmdb/web — the HTTP adapter for the zmdb application kernel.
2
+ //
3
+ // Stage-3 metadata, DI, modules and lifecycle are installed and owned by
4
+ // @zmdb/app. Importing the web root activates that one metadata baseline before
5
+ // any HTTP decorator is evaluated.
6
+ import '@zmdb/app';
7
+ // Controllers & routing (Stage-3 decorators → context.metadata). See ./routing.
8
+ export { Controller, Get, Post, Put, Patch, Delete, Public, getRoutes, isPublic, } from './routing/index.js';
9
+ // Inert HTTP declarations and serialisable operation IR. The compiler-backed
10
+ // collector is intentionally available only from `@zmdb/web/contract/compiler`.
11
+ export { defineHttpContract, httpOperation, } from './contract/index.js';
12
+ // API version declarations and strategy types. See ./versioning.
13
+ export { Version, VersionNeutral, versionsOf } from './versioning/index.js';
14
+ // Typed request context + compile-time path-param derivation. See ./context.
15
+ export { extractParams, compilePattern, countSegments, matchCompiled, } from './context/index.js';
16
+ // Request pipeline & runtime adapters. See ./pipeline.
17
+ export { createRouter, toNodeHandler, toFetchHandler, json, text, respond, bytes, stream, file, bodyText, } from './pipeline/index.js';
18
+ // Confined static files with validators and single-range streaming. See ./static.
19
+ export { createStaticHandler } from './static/index.js';
20
+ // Incremental, cross-runtime gzip/deflate middleware. See ./compression.
21
+ export { compress, compressionInterceptor } from './compression/index.js';
22
+ // HTTP router construction over app-owned observability ports.
23
+ export { createTracedRouter } from './traced-router.js';
24
+ // HTTP validation and wire conversion. Repository DI tokens are app-owned.
25
+ export { validateWith } from './data/index.js';
26
+ // Guards, pipes, interceptors & exception filters. See ./middleware.
27
+ export { runChain, ChainError, } from './middleware/index.js';
28
+ // HTTP application bootstrap over one app-owned graph. See ./app.
29
+ export { createApp } from './app/index.js';
30
+ // DTO validation & serialization pipes. See ./dto-pipes.
31
+ export { validationPipe, multipartPipe, serializationInterceptor, dtoChain, } from './dto-pipes/index.js';
32
+ // Bounded multipart/form-data parsing. See ./upload.
33
+ export { parseMultipart, UPLOAD_DEFAULTS } from './upload/index.js';
34
+ // Stateless, session-bound CSRF protection. See ./csrf.
35
+ export { createCsrf } from './csrf/index.js';
36
+ // OpenAPI 3.1 projection from the shared HTTP contract IR. See ./openapi.
37
+ export { toOpenApi, serveOpenApi, } from './openapi/index.js';
38
+ // WebSocket & SSE gateways. See ./gateways.
39
+ export { Gateway, Subscribe, getSubscriptions, createGatewayDispatcher, sseStream, } from './gateways/index.js';
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,EAAE;AACF,yEAAyE;AACzE,gFAAgF;AAChF,mCAAmC;AACnC,OAAO,WAAW,CAAC;AAEnB,gFAAgF;AAChF,OAAO,EACL,UAAU,EACV,GAAG,EACH,IAAI,EACJ,GAAG,EACH,KAAK,EACL,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,GAGT,MAAM,oBAAoB,CAAC;AAE5B,6EAA6E;AAC7E,gFAAgF;AAChF,OAAO,EACL,kBAAkB,EAClB,aAAa,GAiCd,MAAM,qBAAqB,CAAC;AAE7B,iEAAiE;AACjE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAwB,MAAM,uBAAuB,CAAC;AAElG,6EAA6E;AAC7E,OAAO,EACL,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,GAMd,MAAM,oBAAoB,CAAC;AAE5B,uDAAuD;AACvD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,cAAc,EACd,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,KAAK,EACL,MAAM,EACN,IAAI,EACJ,QAAQ,GAYT,MAAM,qBAAqB,CAAC;AAE7B,kFAAkF;AAClF,OAAO,EAAE,mBAAmB,EAA0C,MAAM,mBAAmB,CAAC;AAEhG,yEAAyE;AACzE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAA+C,MAAM,wBAAwB,CAAC;AAEvH,+DAA+D;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,2EAA2E;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,qEAAqE;AACrE,OAAO,EACL,QAAQ,EACR,UAAU,GASX,MAAM,uBAAuB,CAAC;AAE/B,kEAAkE;AAClE,OAAO,EAAE,SAAS,EAAmD,MAAM,gBAAgB,CAAC;AAE5F,yDAAyD;AACzD,OAAO,EACL,cAAc,EACd,aAAa,EACb,wBAAwB,EACxB,QAAQ,GAET,MAAM,sBAAsB,CAAC;AAE9B,qDAAqD;AACrD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAsD,MAAM,mBAAmB,CAAC;AAExH,wDAAwD;AACxD,OAAO,EAAE,UAAU,EAA+B,MAAM,iBAAiB,CAAC;AAE1E,0EAA0E;AAC1E,OAAO,EACL,SAAS,EACT,YAAY,GAIb,MAAM,oBAAoB,CAAC;AAE5B,4CAA4C;AAC5C,OAAO,EACL,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,uBAAuB,EACvB,SAAS,GAKV,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface Handler<In, Out> {
2
+ validate: (raw: unknown) => In;
3
+ handle: (input: In) => Promise<Out>;
4
+ serialize?: (out: Out) => string;
5
+ }
6
+ export interface EndpointResult {
7
+ status: number;
8
+ body: string;
9
+ }
10
+ export declare function makeEndpoint<In, Out>(h: Handler<In, Out>): (raw: unknown) => Promise<EndpointResult>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,OAAO,CAAC,EAAE,EAAE,GAAG;IAC9B,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,EAAE,CAAC;IAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,cAAc,CAAC,CA2BpG"}
@@ -0,0 +1,39 @@
1
+ // Framework-agnostic endpoint adapter — see ./SPEC.md.
2
+ import { claimsValidationIssues, ValidationError, validationIssuesOf } from '@zmdb/validator';
3
+ export function makeEndpoint(h) {
4
+ const serialize = h.serialize ?? ((o) => JSON.stringify(o));
5
+ return async (raw) => {
6
+ let input;
7
+ try {
8
+ input = h.validate(raw);
9
+ }
10
+ catch (err) {
11
+ const error = err instanceof Error ? err.message : 'invalid input';
12
+ const issues = validationIssuesOf(err);
13
+ return { status: 400, body: JSON.stringify(issues ? { error, issues } : { error }) };
14
+ }
15
+ try {
16
+ const out = await h.handle(input);
17
+ return { status: 200, body: serialize(out) };
18
+ }
19
+ catch (err) {
20
+ // A validation error from the *handler* is still the caller's fault — a write that
21
+ // failed its own schema check on the way to the driver — so it is a 400 and not a 500.
22
+ // Anything else is rethrown untouched: this adapter has no business deciding what an
23
+ // unexpected exception means.
24
+ if (err instanceof ValidationError || claimsValidationIssues(err)) {
25
+ const error = err instanceof Error ? err.message : 'invalid input';
26
+ const issues = validationIssuesOf(err);
27
+ return { status: 400, body: JSON.stringify(issues ? { error, issues } : { error }) };
28
+ }
29
+ throw err;
30
+ }
31
+ };
32
+ }
33
+ // --- Thin per-framework adapters (optional; no hard deps) ---
34
+ // Hono: app.post('/x', async (c) => { const r = await ep(await c.req.json()); return c.body(r.body, r.status); })
35
+ // Express: app.post('/x', async (req,res) => { const r = await ep(req.body); res.status(r.status).send(r.body); })
36
+ // tRPC: procedure.input(z.unknown()).mutation(({input}) => ep(input))
37
+ // NestJS: @Post() async create(@Body() b){ return ep(b); }
38
+ // Each is a 1–2 line wrapper over makeEndpoint — see docs/framework-integrations.
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAa9F,MAAM,UAAU,YAAY,CAAU,CAAmB;IACvD,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,OAAO,KAAK,EAAE,GAAY,EAAE,EAAE;QAC5B,IAAI,KAAS,CAAC;QACd,IAAI,CAAC;YACH,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACnE,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACvC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACvF,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAClC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mFAAmF;YACnF,uFAAuF;YACvF,qFAAqF;YACrF,8BAA8B;YAC9B,IAAI,GAAG,YAAY,eAAe,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClE,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBACnE,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBACvC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YACvF,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,qHAAqH;AACrH,mHAAmH;AACnH,yEAAyE;AACzE,4DAA4D;AAC5D,kFAAkF"}
@@ -0,0 +1,14 @@
1
+ /** An error carrying an HTTP status, thrown when a middleware chain short-circuits. */
2
+ export declare class ChainError extends Error {
3
+ readonly status: number;
4
+ constructor(status: number, message: string);
5
+ }
6
+ /**
7
+ * Internal boundary error whose status is already the framework's decision.
8
+ *
9
+ * Ordinary user-thrown pipe errors still become ChainError(400). Built-in
10
+ * boundary parsers use this subclass when 400 and 413 have distinct meanings.
11
+ */
12
+ export declare class BoundaryStatusError extends ChainError {
13
+ }
14
+ //# sourceMappingURL=errors.d.ts.map