hexok 1.0.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 (201) hide show
  1. package/dist/app/api-use-case.d.ts +52 -0
  2. package/dist/app/api-use-case.d.ts.map +1 -0
  3. package/dist/app/api-use-case.js +59 -0
  4. package/dist/app/api-use-case.js.map +1 -0
  5. package/dist/app/callable-use-case.d.ts +34 -0
  6. package/dist/app/callable-use-case.d.ts.map +1 -0
  7. package/dist/app/callable-use-case.js +41 -0
  8. package/dist/app/callable-use-case.js.map +1 -0
  9. package/dist/app/contract.d.ts +46 -0
  10. package/dist/app/contract.d.ts.map +1 -0
  11. package/dist/app/contract.js +28 -0
  12. package/dist/app/contract.js.map +1 -0
  13. package/dist/app/error-factory.d.ts +9 -0
  14. package/dist/app/error-factory.d.ts.map +1 -0
  15. package/dist/app/error-factory.js +30 -0
  16. package/dist/app/error-factory.js.map +1 -0
  17. package/dist/app/event-channel.d.ts +133 -0
  18. package/dist/app/event-channel.d.ts.map +1 -0
  19. package/dist/app/event-channel.js +49 -0
  20. package/dist/app/event-channel.js.map +1 -0
  21. package/dist/app/event-use-case.d.ts +47 -0
  22. package/dist/app/event-use-case.d.ts.map +1 -0
  23. package/dist/app/event-use-case.js +54 -0
  24. package/dist/app/event-use-case.js.map +1 -0
  25. package/dist/app/execute-ctx.d.ts +92 -0
  26. package/dist/app/execute-ctx.d.ts.map +1 -0
  27. package/dist/app/execute-ctx.js +2 -0
  28. package/dist/app/execute-ctx.js.map +1 -0
  29. package/dist/app/external-use-case.d.ts +25 -0
  30. package/dist/app/external-use-case.d.ts.map +1 -0
  31. package/dist/app/external-use-case.js +25 -0
  32. package/dist/app/external-use-case.js.map +1 -0
  33. package/dist/app/index.d.ts +9 -0
  34. package/dist/app/index.d.ts.map +1 -0
  35. package/dist/app/index.js +8 -0
  36. package/dist/app/index.js.map +1 -0
  37. package/dist/app/internal-use-case.d.ts +26 -0
  38. package/dist/app/internal-use-case.d.ts.map +1 -0
  39. package/dist/app/internal-use-case.js +26 -0
  40. package/dist/app/internal-use-case.js.map +1 -0
  41. package/dist/app/nest.d.ts +9 -0
  42. package/dist/app/nest.d.ts.map +1 -0
  43. package/dist/app/nest.js +28 -0
  44. package/dist/app/nest.js.map +1 -0
  45. package/dist/app/types.d.ts +153 -0
  46. package/dist/app/types.d.ts.map +1 -0
  47. package/dist/app/types.js +17 -0
  48. package/dist/app/types.js.map +1 -0
  49. package/dist/core/coded-error.d.ts +24 -0
  50. package/dist/core/coded-error.d.ts.map +1 -0
  51. package/dist/core/coded-error.js +32 -0
  52. package/dist/core/coded-error.js.map +1 -0
  53. package/dist/core/error-map.d.ts +21 -0
  54. package/dist/core/error-map.d.ts.map +1 -0
  55. package/dist/core/error-map.js +5 -0
  56. package/dist/core/error-map.js.map +1 -0
  57. package/dist/core/index.d.ts +6 -0
  58. package/dist/core/index.d.ts.map +1 -0
  59. package/dist/core/index.js +5 -0
  60. package/dist/core/index.js.map +1 -0
  61. package/dist/core/result.d.ts +23 -0
  62. package/dist/core/result.d.ts.map +1 -0
  63. package/dist/core/result.js +11 -0
  64. package/dist/core/result.js.map +1 -0
  65. package/dist/core/schema.d.ts +19 -0
  66. package/dist/core/schema.d.ts.map +1 -0
  67. package/dist/core/schema.js +28 -0
  68. package/dist/core/schema.js.map +1 -0
  69. package/dist/core/standard-schema.d.ts +51 -0
  70. package/dist/core/standard-schema.d.ts.map +1 -0
  71. package/dist/core/standard-schema.js +2 -0
  72. package/dist/core/standard-schema.js.map +1 -0
  73. package/dist/domain/capabilities.d.ts +42 -0
  74. package/dist/domain/capabilities.d.ts.map +1 -0
  75. package/dist/domain/capabilities.js +2 -0
  76. package/dist/domain/capabilities.js.map +1 -0
  77. package/dist/domain/catalog.d.ts +46 -0
  78. package/dist/domain/catalog.d.ts.map +1 -0
  79. package/dist/domain/catalog.js +114 -0
  80. package/dist/domain/catalog.js.map +1 -0
  81. package/dist/domain/channel.d.ts +36 -0
  82. package/dist/domain/channel.d.ts.map +1 -0
  83. package/dist/domain/channel.js +2 -0
  84. package/dist/domain/channel.js.map +1 -0
  85. package/dist/domain/cow-draft.d.ts +10 -0
  86. package/dist/domain/cow-draft.d.ts.map +1 -0
  87. package/dist/domain/cow-draft.js +147 -0
  88. package/dist/domain/cow-draft.js.map +1 -0
  89. package/dist/domain/entity.d.ts +120 -0
  90. package/dist/domain/entity.d.ts.map +1 -0
  91. package/dist/domain/entity.js +263 -0
  92. package/dist/domain/entity.js.map +1 -0
  93. package/dist/domain/envelope.d.ts +59 -0
  94. package/dist/domain/envelope.d.ts.map +1 -0
  95. package/dist/domain/envelope.js +2 -0
  96. package/dist/domain/envelope.js.map +1 -0
  97. package/dist/domain/event.d.ts +44 -0
  98. package/dist/domain/event.d.ts.map +1 -0
  99. package/dist/domain/event.js +21 -0
  100. package/dist/domain/event.js.map +1 -0
  101. package/dist/domain/index.d.ts +8 -0
  102. package/dist/domain/index.d.ts.map +1 -0
  103. package/dist/domain/index.js +5 -0
  104. package/dist/domain/index.js.map +1 -0
  105. package/dist/domain/port.d.ts +45 -0
  106. package/dist/domain/port.d.ts.map +1 -0
  107. package/dist/domain/port.js +41 -0
  108. package/dist/domain/port.js.map +1 -0
  109. package/dist/infra/adapter.d.ts +22 -0
  110. package/dist/infra/adapter.d.ts.map +1 -0
  111. package/dist/infra/adapter.js +18 -0
  112. package/dist/infra/adapter.js.map +1 -0
  113. package/dist/infra/index.d.ts +3 -0
  114. package/dist/infra/index.d.ts.map +1 -0
  115. package/dist/infra/index.js +3 -0
  116. package/dist/infra/index.js.map +1 -0
  117. package/dist/infra/mapper.d.ts +48 -0
  118. package/dist/infra/mapper.d.ts.map +1 -0
  119. package/dist/infra/mapper.js +77 -0
  120. package/dist/infra/mapper.js.map +1 -0
  121. package/dist/runtime/app.d.ts +100 -0
  122. package/dist/runtime/app.d.ts.map +1 -0
  123. package/dist/runtime/app.js +292 -0
  124. package/dist/runtime/app.js.map +1 -0
  125. package/dist/runtime/channel.d.ts +34 -0
  126. package/dist/runtime/channel.d.ts.map +1 -0
  127. package/dist/runtime/channel.js +110 -0
  128. package/dist/runtime/channel.js.map +1 -0
  129. package/dist/runtime/client.d.ts +21 -0
  130. package/dist/runtime/client.d.ts.map +1 -0
  131. package/dist/runtime/client.js +2 -0
  132. package/dist/runtime/client.js.map +1 -0
  133. package/dist/runtime/completeness.d.ts +89 -0
  134. package/dist/runtime/completeness.d.ts.map +1 -0
  135. package/dist/runtime/completeness.js +2 -0
  136. package/dist/runtime/completeness.js.map +1 -0
  137. package/dist/runtime/envelope.d.ts +7 -0
  138. package/dist/runtime/envelope.d.ts.map +1 -0
  139. package/dist/runtime/envelope.js +69 -0
  140. package/dist/runtime/envelope.js.map +1 -0
  141. package/dist/runtime/events.d.ts +6 -0
  142. package/dist/runtime/events.d.ts.map +1 -0
  143. package/dist/runtime/events.js +48 -0
  144. package/dist/runtime/events.js.map +1 -0
  145. package/dist/runtime/http-status.d.ts +3 -0
  146. package/dist/runtime/http-status.d.ts.map +1 -0
  147. package/dist/runtime/http-status.js +11 -0
  148. package/dist/runtime/http-status.js.map +1 -0
  149. package/dist/runtime/http.d.ts +4 -0
  150. package/dist/runtime/http.d.ts.map +1 -0
  151. package/dist/runtime/http.js +58 -0
  152. package/dist/runtime/http.js.map +1 -0
  153. package/dist/runtime/index.d.ts +10 -0
  154. package/dist/runtime/index.d.ts.map +1 -0
  155. package/dist/runtime/index.js +6 -0
  156. package/dist/runtime/index.js.map +1 -0
  157. package/dist/runtime/interceptor.d.ts +61 -0
  158. package/dist/runtime/interceptor.d.ts.map +1 -0
  159. package/dist/runtime/interceptor.js +7 -0
  160. package/dist/runtime/interceptor.js.map +1 -0
  161. package/dist/runtime/invoke.d.ts +34 -0
  162. package/dist/runtime/invoke.d.ts.map +1 -0
  163. package/dist/runtime/invoke.js +235 -0
  164. package/dist/runtime/invoke.js.map +1 -0
  165. package/dist/runtime/middleware.d.ts +20 -0
  166. package/dist/runtime/middleware.d.ts.map +1 -0
  167. package/dist/runtime/middleware.js +2 -0
  168. package/dist/runtime/middleware.js.map +1 -0
  169. package/dist/runtime/rpc.d.ts +24 -0
  170. package/dist/runtime/rpc.d.ts.map +1 -0
  171. package/dist/runtime/rpc.js +16 -0
  172. package/dist/runtime/rpc.js.map +1 -0
  173. package/dist/testing/app-test.d.ts +77 -0
  174. package/dist/testing/app-test.d.ts.map +1 -0
  175. package/dist/testing/app-test.js +109 -0
  176. package/dist/testing/app-test.js.map +1 -0
  177. package/dist/testing/in-memory-broker.d.ts +18 -0
  178. package/dist/testing/in-memory-broker.d.ts.map +1 -0
  179. package/dist/testing/in-memory-broker.js +42 -0
  180. package/dist/testing/in-memory-broker.js.map +1 -0
  181. package/dist/testing/in-memory-bus.d.ts +19 -0
  182. package/dist/testing/in-memory-bus.d.ts.map +1 -0
  183. package/dist/testing/in-memory-bus.js +31 -0
  184. package/dist/testing/in-memory-bus.js.map +1 -0
  185. package/dist/testing/in-memory-channel.d.ts +32 -0
  186. package/dist/testing/in-memory-channel.d.ts.map +1 -0
  187. package/dist/testing/in-memory-channel.js +65 -0
  188. package/dist/testing/in-memory-channel.js.map +1 -0
  189. package/dist/testing/in-memory-queue.d.ts +24 -0
  190. package/dist/testing/in-memory-queue.d.ts.map +1 -0
  191. package/dist/testing/in-memory-queue.js +66 -0
  192. package/dist/testing/in-memory-queue.js.map +1 -0
  193. package/dist/testing/in-memory-repository.d.ts +44 -0
  194. package/dist/testing/in-memory-repository.d.ts.map +1 -0
  195. package/dist/testing/in-memory-repository.js +60 -0
  196. package/dist/testing/in-memory-repository.js.map +1 -0
  197. package/dist/testing/index.d.ts +6 -0
  198. package/dist/testing/index.d.ts.map +1 -0
  199. package/dist/testing/index.js +6 -0
  200. package/dist/testing/index.js.map +1 -0
  201. package/package.json +60 -0
@@ -0,0 +1,20 @@
1
+ /** Onion around external `execute` (`local` and HTTP). Does not run for event handlers or nested `run`. */
2
+ export type ApiMiddleware<Ctx = unknown> = (args: {
3
+ /** Request context (`ctx` on the use case). */
4
+ context: Ctx;
5
+ /** Parsed API input. */
6
+ input: unknown;
7
+ /** Continue the onion. Does not accept a replacement ctx. */
8
+ next: () => Promise<unknown>;
9
+ /** Error factories from the use-case error map. */
10
+ errors: {
11
+ [code: string]: (data?: unknown) => never;
12
+ };
13
+ /** Use-case key (`incident.close`). */
14
+ path: string;
15
+ /** Present on HTTP `router.fetch` only. Read headers here; set ctx with `.ctxFrom`. */
16
+ request?: Request;
17
+ }) => Promise<unknown>;
18
+ /** @deprecated Use `ApiMiddleware`. Same type; not HTTP-only. */
19
+ export type RpcMiddleware<Ctx = unknown> = ApiMiddleware<Ctx>;
20
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/runtime/middleware.ts"],"names":[],"mappings":"AAAA,2GAA2G;AAC3G,MAAM,MAAM,aAAa,CAAC,GAAG,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE;IAChD,+CAA+C;IAC/C,OAAO,EAAE,GAAG,CAAC;IACb,wBAAwB;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,6DAA6D;IAC7D,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,mDAAmD;IACnD,MAAM,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,KAAK,CAAA;KAAE,CAAC;IACtD,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB,iEAAiE;AACjE,MAAM,MAAM,aAAa,CAAC,GAAG,GAAG,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/runtime/middleware.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import type { CatalogEntry, UseCaseBag, UseCaseContract } from '../app/index.js';
2
+ import type { PathTo, UnionToIntersection } from '../app/nest.js';
3
+ import type { ExternalKeysOf } from '../app/types.js';
4
+ /** Dotted use-case key to HTTP path (`incident.close` → `/rpc/incident/close`). */
5
+ export declare function rpcPath(key: string): string;
6
+ /** One API route with a POST path under `/rpc`. */
7
+ export type RpcRoute = CatalogEntry & {
8
+ /** Always `POST`. */
9
+ method: 'POST';
10
+ /** `/rpc/...` path derived from the use-case key. */
11
+ path: string;
12
+ };
13
+ type NestedRpc<Bag> = UnionToIntersection<ExternalKeysOf<Bag> extends infer Key ? Key extends string ? PathTo<Key, RpcRoute> : never : never>;
14
+ /** Flat `routes` plus nested keys (`rpc.incident.close.path`). */
15
+ export type RpcContract<Bag extends UseCaseBag = UseCaseBag> = {
16
+ /** Routes keyed by use-case `key`. */
17
+ routes: {
18
+ [K in Extract<ExternalKeysOf<Bag>, string>]: RpcRoute;
19
+ };
20
+ } & NestedRpc<Bag>;
21
+ /** Attach `POST /rpc/...` paths to each external catalog entry and nest by use-case key. */
22
+ export declare function deriveRpc<Bag extends UseCaseBag = UseCaseBag>(contract: UseCaseContract): RpcContract<Bag>;
23
+ export {};
24
+ //# sourceMappingURL=rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../../src/runtime/rpc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,mDAAmD;AACnD,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG;IACpC,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,SAAS,CAAC,GAAG,IAAI,mBAAmB,CACvC,cAAc,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,GACjC,GAAG,SAAS,MAAM,GAChB,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GACrB,KAAK,GACP,KAAK,CACV,CAAC;AAEF,kEAAkE;AAClE,MAAM,MAAM,WAAW,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,IAAI;IAC7D,sCAAsC;IACtC,MAAM,EAAE;SAAG,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,QAAQ;KAAE,CAAC;CACnE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;AAEnB,4FAA4F;AAC5F,wBAAgB,SAAS,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,EAC3D,QAAQ,EAAE,eAAe,GACxB,WAAW,CAAC,GAAG,CAAC,CAQlB"}
@@ -0,0 +1,16 @@
1
+ import { nestByKey } from '../app/index.js';
2
+ /** Dotted use-case key to HTTP path (`incident.close` → `/rpc/incident/close`). */
3
+ export function rpcPath(key) {
4
+ return `/rpc/${key.split('.').join('/')}`;
5
+ }
6
+ /** Attach `POST /rpc/...` paths to each external catalog entry and nest by use-case key. */
7
+ export function deriveRpc(contract) {
8
+ const routes = {};
9
+ for (const [key, entry] of Object.entries(contract.entries)) {
10
+ routes[key] = { ...entry, method: 'POST', path: rpcPath(entry.key) };
11
+ }
12
+ return Object.assign(nestByKey(Object.entries(routes)), {
13
+ routes,
14
+ });
15
+ }
16
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/runtime/rpc.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,mFAAmF;AACnF,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,QAAQ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5C,CAAC;AAwBD,4FAA4F;AAC5F,MAAM,UAAU,SAAS,CACvB,QAAyB;IAEzB,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACvE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;QACtD,MAAM;KACP,CAAqB,CAAC;AACzB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { AsUseCaseBag, ChannelSession, CheckUseCase, EventChannelCtor, UseCaseBag } from '../app/index.js';
2
+ import type { CatalogKind, ChannelAdapter, Envelope, EventCatalog, EventClass, PortToken } from '../domain/index.js';
3
+ import { type AdapterFor, type ApiMiddleware, type AppInstance, type ChannelKindError, type DuplicateCatalogError, type DuplicateChannelError, type DuplicatePortError, type Interceptor, type MissingMessages, type NestedClient } from '../runtime/index.js';
4
+ /**
5
+ * Built test app: runtime `AppInstance` plus `published` and `as(ctx)`.
6
+ * Use `App.test(...).build()`, then assert `app.published` or call `app.as(ctx)`.
7
+ */
8
+ export type TestAppInstance<Bag extends UseCaseBag, Ctx = unknown, Routed = never> = AppInstance<Bag, Ctx, Routed> & {
9
+ /** Envelopes that completed `aroundPublish`, in order. */
10
+ published: Envelope[];
11
+ /** Nested local client with `ctx` fixed on every call. */
12
+ as: (ctx: Ctx) => NestedClient<Bag, Ctx>;
13
+ };
14
+ type ChannelCatalogKind<C> = C extends {
15
+ catalog: EventCatalog<string, infer Kind, infer _E, infer _Ctx>;
16
+ } ? Kind : CatalogKind;
17
+ type ChannelCatalogKey<C> = C extends {
18
+ catalog: EventCatalog<infer K extends string, infer _Kind, infer _E, infer _Ctx>;
19
+ } ? K : string;
20
+ /**
21
+ * Test composition root with the same `provide`/`bind`/`route`/`ctx`/`build`
22
+ * as runtime, plus `published` capture. Construct with `App.test`, not `new`.
23
+ */
24
+ export declare class TestAppBuilder<Bag extends UseCaseBag, Provided = never, Bound = never, Ctx = unknown, Routed = never> {
25
+ #private;
26
+ private constructor();
27
+ /** Start a test graph from a use-case bag. The built app has `published` and `as`. */
28
+ static test<Bag extends {
29
+ [K in keyof Bag]: CheckUseCase<Bag[K]>;
30
+ }>(useCases: Bag): TestAppBuilder<AsUseCaseBag<Bag>>;
31
+ /** Bind a port token to an implementation, usually an in-memory fake. */
32
+ provide<I>(token: [PortToken<I>] extends [Provided] ? DuplicatePortError : PortToken<I>, impl: I): TestAppBuilder<Bag, Provided | PortToken<I>, Bound, Ctx, Routed>;
33
+ /** Bind a catalog to a bus or queue adapter (`InMemoryBus` / `InMemoryQueue`). */
34
+ bind<Key extends string, Kind extends CatalogKind, Events extends EventClass = never, CatCtx = undefined>(catalog: [EventCatalog<Key, Kind, Events, CatCtx>] extends [Bound] ? DuplicateCatalogError<Key> : EventCatalog<Key, Kind, Events, CatCtx>, adapter: AdapterFor<Kind>): TestAppBuilder<Bag, Provided, Bound | EventCatalog<Key, Kind, Events, CatCtx>, Ctx, Routed>;
35
+ /** Route a bus `EventChannel` to a channel adapter (`InMemoryChannel`). */
36
+ route<C extends EventChannelCtor>(channel: ChannelCatalogKind<C> extends 'bus' ? [C] extends [Routed] ? DuplicateChannelError<ChannelCatalogKey<C>> : C : ChannelKindError<ChannelCatalogKey<C>, ChannelCatalogKind<C> & string>, adapter: ChannelAdapter<ChannelSession<C>>): TestAppBuilder<Bag, Provided, Bound, Ctx, Routed | C>;
37
+ /** Set default request context for `local` and HTTP. `as(ctx)` overrides per call. */
38
+ ctx<C>(defaults?: C): TestAppBuilder<Bag, Provided, Bound, C, Routed>;
39
+ /** Set HTTP request context from the `Request`. Same as runtime `.ctxFrom`. */
40
+ ctxFrom(fn: (args: {
41
+ request: Request;
42
+ ctx: Ctx;
43
+ }) => Ctx | Promise<Ctx>): this;
44
+ /** Provide a factory from `Adapter.of` by calling `create(...deps)`. */
45
+ adapt<I, Deps extends unknown[]>(factory: {
46
+ token: [PortToken<I>] extends [Provided] ? DuplicatePortError : PortToken<I>;
47
+ create: (...deps: Deps) => I;
48
+ }, ...deps: Deps): TestAppBuilder<Bag, Provided | PortToken<I>, Bound, Ctx, Routed>;
49
+ /** Register API middleware on the inner runtime builder. */
50
+ use(middleware: ApiMiddleware): this;
51
+ /** Register an interceptor. First registered is outer; `App.test` already captured publish. */
52
+ intercept(interceptor: Interceptor): this;
53
+ /**
54
+ * Complete the graph; incomplete builders expose `build` as the missing
55
+ * port/catalog message (not callable). The instance includes `published` and `as`.
56
+ */
57
+ get build(): [MissingMessages<Bag, Provided, Bound, Routed>] extends [never] ? () => TestAppInstance<Bag, Ctx, Routed> : MissingMessages<Bag, Provided, Bound, Routed>;
58
+ }
59
+ /**
60
+ * Same completeness as `App.from`, plus `published` capture (after
61
+ * `aroundPublish`) and `as(ctx)` to rebind request context.
62
+ *
63
+ * ```ts
64
+ * const app = App.test({ close: CloseIncident })
65
+ * .provide(IncidentRepository, InMemoryRepository.of(...))
66
+ * .bind(DomainEvents, InMemoryBus.create())
67
+ * .build()
68
+ * await app.local.incident.close({ id: '1' })
69
+ * expect(app.published).toHaveLength(1)
70
+ * ```
71
+ */
72
+ export declare const App: {
73
+ /** Start a test graph. The built app has `published` and `as`. Production composition is `hexok/runtime` `App.from`. */
74
+ test: typeof TestAppBuilder.test;
75
+ };
76
+ export {};
77
+ //# sourceMappingURL=app-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-test.d.ts","sourceRoot":"","sources":["../../src/testing/app-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { App as RuntimeApp, } from '../runtime/index.js';
2
+ /**
3
+ * Test composition root with the same `provide`/`bind`/`route`/`ctx`/`build`
4
+ * as runtime, plus `published` capture. Construct with `App.test`, not `new`.
5
+ */
6
+ export class TestAppBuilder {
7
+ #inner;
8
+ #published;
9
+ constructor(inner, published) {
10
+ this.#inner = inner;
11
+ this.#published = published;
12
+ }
13
+ /** Start a test graph from a use-case bag. The built app has `published` and `as`. */
14
+ static test(useCases) {
15
+ const published = [];
16
+ const inner = RuntimeApp.from(useCases).intercept({
17
+ key: 'hexok:published',
18
+ aroundPublish: async (envelope, next) => {
19
+ await next();
20
+ published.push(envelope);
21
+ },
22
+ });
23
+ return new TestAppBuilder(inner, published);
24
+ }
25
+ /** Bind a port token to an implementation, usually an in-memory fake. */
26
+ provide(token, impl) {
27
+ const next = this.#inner.provide(token, impl);
28
+ return new TestAppBuilder(next, this.#published);
29
+ }
30
+ /** Bind a catalog to a bus or queue adapter (`InMemoryBus` / `InMemoryQueue`). */
31
+ bind(catalog, adapter) {
32
+ const next = this.#inner.bind(catalog, adapter);
33
+ return new TestAppBuilder(next, this.#published);
34
+ }
35
+ /** Route a bus `EventChannel` to a channel adapter (`InMemoryChannel`). */
36
+ route(channel, adapter) {
37
+ const next = this.#inner.route(channel, adapter);
38
+ return new TestAppBuilder(next, this.#published);
39
+ }
40
+ /** Set default request context for `local` and HTTP. `as(ctx)` overrides per call. */
41
+ ctx(defaults) {
42
+ const next = this.#inner.ctx(defaults);
43
+ return new TestAppBuilder(next, this.#published);
44
+ }
45
+ /** Set HTTP request context from the `Request`. Same as runtime `.ctxFrom`. */
46
+ ctxFrom(fn) {
47
+ this.#inner.ctxFrom(fn);
48
+ return this;
49
+ }
50
+ /** Provide a factory from `Adapter.of` by calling `create(...deps)`. */
51
+ adapt(factory, ...deps) {
52
+ return this.provide(factory.token, factory.create(...deps));
53
+ }
54
+ /** Register API middleware on the inner runtime builder. */
55
+ use(middleware) {
56
+ this.#inner.use(middleware);
57
+ return this;
58
+ }
59
+ /** Register an interceptor. First registered is outer; `App.test` already captured publish. */
60
+ intercept(interceptor) {
61
+ this.#inner.intercept(interceptor);
62
+ return this;
63
+ }
64
+ /**
65
+ * Complete the graph; incomplete builders expose `build` as the missing
66
+ * port/catalog message (not callable). The instance includes `published` and `as`.
67
+ */
68
+ get build() {
69
+ const published = this.#published;
70
+ return (() => {
71
+ const app = this.#inner.build();
72
+ return Object.assign(app, {
73
+ published,
74
+ as: (ctx) => rebindLocal(app.local, ctx),
75
+ });
76
+ });
77
+ }
78
+ }
79
+ /**
80
+ * Same completeness as `App.from`, plus `published` capture (after
81
+ * `aroundPublish`) and `as(ctx)` to rebind request context.
82
+ *
83
+ * ```ts
84
+ * const app = App.test({ close: CloseIncident })
85
+ * .provide(IncidentRepository, InMemoryRepository.of(...))
86
+ * .bind(DomainEvents, InMemoryBus.create())
87
+ * .build()
88
+ * await app.local.incident.close({ id: '1' })
89
+ * expect(app.published).toHaveLength(1)
90
+ * ```
91
+ */
92
+ export const App = {
93
+ /** Start a test graph. The built app has `published` and `as`. Production composition is `hexok/runtime` `App.from`. */
94
+ test: TestAppBuilder.test,
95
+ };
96
+ function rebindLocal(value, ctx) {
97
+ if (typeof value === 'function') {
98
+ return (input, opts) => value(input, { ...opts, ctx });
99
+ }
100
+ if (value !== null && typeof value === 'object') {
101
+ const out = Object.create(null);
102
+ for (const [key, child] of Object.entries(value)) {
103
+ out[key] = rebindLocal(child, ctx);
104
+ }
105
+ return out;
106
+ }
107
+ return value;
108
+ }
109
+ //# sourceMappingURL=app-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-test.js","sourceRoot":"","sources":["../../src/testing/app-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { BrokerAdapter, BrokerConsumeCtx, Envelope } from '../domain/index.js';
2
+ type Consumer = (envelope: Envelope, ctx: BrokerConsumeCtx) => Promise<void>;
3
+ /**
4
+ * In-process broker. `consume` dispatches with attempt; ack/nack are no-ops
5
+ * besides recording. `stop()` clears consumers.
6
+ */
7
+ export declare class InMemoryBroker implements BrokerAdapter {
8
+ #private;
9
+ readonly kind: "broker";
10
+ readonly published: Envelope[];
11
+ attempts: number;
12
+ static create(): InMemoryBroker;
13
+ publish(envelope: Envelope): Promise<void>;
14
+ consume(key: string, group: string, handler: Consumer): void;
15
+ stop(): Promise<void>;
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=in-memory-broker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-broker.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-broker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAE5B,KAAK,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7E;;;GAGG;AACH,qBAAa,cAAe,YAAW,aAAa;;IAClD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAM;IAEpC,QAAQ,SAAK;IAEb,MAAM,CAAC,MAAM,IAAI,cAAc;IAIzB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI;IAMtD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * In-process broker. `consume` dispatches with attempt; ack/nack are no-ops
3
+ * besides recording. `stop()` clears consumers.
4
+ */
5
+ export class InMemoryBroker {
6
+ kind = 'broker';
7
+ published = [];
8
+ #consumers = new Map();
9
+ attempts = 1;
10
+ static create() {
11
+ return new InMemoryBroker();
12
+ }
13
+ async publish(envelope) {
14
+ this.published.push(envelope);
15
+ const groups = this.#consumers.get(envelope.key);
16
+ if (!groups)
17
+ return;
18
+ for (const consumer of groups.values()) {
19
+ let acked = false;
20
+ const ctx = {
21
+ attempt: this.attempts,
22
+ ack: async () => {
23
+ acked = true;
24
+ },
25
+ nack: async () => {
26
+ acked = false;
27
+ },
28
+ };
29
+ await consumer(envelope, ctx);
30
+ void acked;
31
+ }
32
+ }
33
+ consume(key, group, handler) {
34
+ const groups = this.#consumers.get(key) ?? new Map();
35
+ groups.set(group, handler);
36
+ this.#consumers.set(key, groups);
37
+ }
38
+ async stop() {
39
+ this.#consumers.clear();
40
+ }
41
+ }
42
+ //# sourceMappingURL=in-memory-broker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-broker.js","sourceRoot":"","sources":["../../src/testing/in-memory-broker.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,QAAiB,CAAC;IACzB,SAAS,GAAe,EAAE,CAAC;IACpC,UAAU,GAAG,IAAI,GAAG,EAAiC,CAAC;IACtD,QAAQ,GAAG,CAAC,CAAC;IAEb,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAkB;QAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,KAAK,GAAG,KAAK,CAAC;YAClB,MAAM,GAAG,GAAqB;gBAC5B,OAAO,EAAE,IAAI,CAAC,QAAQ;gBACtB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,KAAK,GAAG,IAAI,CAAC;gBACf,CAAC;gBACD,IAAI,EAAE,KAAK,IAAI,EAAE;oBACf,KAAK,GAAG,KAAK,CAAC;gBAChB,CAAC;aACF,CAAC;YACF,MAAM,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAC9B,KAAK,KAAK,CAAC;QACb,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAW,EAAE,KAAa,EAAE,OAAiB;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAAoB,CAAC;QACvE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { BusAdapter, Envelope } from '../domain/index.js';
2
+ /**
3
+ * In-process bus. Records `published`. `stop()` clears subscribers.
4
+ */
5
+ export declare class InMemoryBus implements BusAdapter {
6
+ #private;
7
+ readonly kind: "bus";
8
+ /** Envelopes passed to `publish`, in order. */
9
+ readonly published: Envelope[];
10
+ /** Empty bus. Pass to `.bind(catalog, InMemoryBus.create())`. */
11
+ static create(): InMemoryBus;
12
+ /** Record the envelope, then await each subscriber for its key. */
13
+ publish(envelope: Envelope): Promise<void>;
14
+ /** Register a handler for `key`. Cleared by `stop()`. */
15
+ subscribe(key: string, handler: (envelope: Envelope) => Promise<void>): void;
16
+ /** Drop all subscribers. Does not clear `published`. */
17
+ stop(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=in-memory-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-bus.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-bus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;GAEG;AACH,qBAAa,WAAY,YAAW,UAAU;;IAC5C,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAM;IAMpC,iEAAiE;IACjE,MAAM,CAAC,MAAM,IAAI,WAAW;IAI5B,mEAAmE;IAC7D,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD,yDAAyD;IACzD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAM5E,wDAAwD;IAClD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * In-process bus. Records `published`. `stop()` clears subscribers.
3
+ */
4
+ export class InMemoryBus {
5
+ kind = 'bus';
6
+ /** Envelopes passed to `publish`, in order. */
7
+ published = [];
8
+ #subscribers = new Map();
9
+ /** Empty bus. Pass to `.bind(catalog, InMemoryBus.create())`. */
10
+ static create() {
11
+ return new InMemoryBus();
12
+ }
13
+ /** Record the envelope, then await each subscriber for its key. */
14
+ async publish(envelope) {
15
+ this.published.push(envelope);
16
+ for (const handler of this.#subscribers.get(envelope.key) ?? []) {
17
+ await handler(envelope);
18
+ }
19
+ }
20
+ /** Register a handler for `key`. Cleared by `stop()`. */
21
+ subscribe(key, handler) {
22
+ const list = this.#subscribers.get(key) ?? [];
23
+ list.push(handler);
24
+ this.#subscribers.set(key, list);
25
+ }
26
+ /** Drop all subscribers. Does not clear `published`. */
27
+ async stop() {
28
+ this.#subscribers.clear();
29
+ }
30
+ }
31
+ //# sourceMappingURL=in-memory-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-bus.js","sourceRoot":"","sources":["../../src/testing/in-memory-bus.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,WAAW;IACb,IAAI,GAAG,KAAc,CAAC;IAC/B,+CAA+C;IACtC,SAAS,GAAe,EAAE,CAAC;IACpC,YAAY,GAAG,IAAI,GAAG,EAGnB,CAAC;IAEJ,iEAAiE;IACjE,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,WAAW,EAAE,CAAC;IAC3B,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,OAAO,CAAC,QAAkB;QAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAChE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,SAAS,CAAC,GAAW,EAAE,OAA8C;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,wDAAwD;IACxD,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import type { ChannelAdapter, ChannelConnection } from '../domain/index.js';
2
+ /**
3
+ * In-process channel adapter. Records `sent`. `stop()` closes connections.
4
+ */
5
+ export declare class InMemoryChannel<Session = unknown> implements ChannelAdapter<Session> {
6
+ #private;
7
+ /** `{ id, payload }` records from `send`, in order. */
8
+ readonly sent: Array<{
9
+ id: string;
10
+ payload: string;
11
+ }>;
12
+ /** Empty channel. Pass to `.route(Channel, InMemoryChannel.create())`. */
13
+ static create<S>(): InMemoryChannel<S>;
14
+ /** Track a connected client. Replaces an existing row with the same `id`. */
15
+ join(id: string, session: Session, connection: ChannelConnection): void;
16
+ /** Drop the client without closing the connection. */
17
+ leave(id: string): void;
18
+ /** Close the connection; the `close` listener then `leave`s. */
19
+ eject(id: string): void;
20
+ /** Replace session claims for a connected client. No-op if unknown `id`. */
21
+ update(id: string, session: Session): void;
22
+ /** Snapshot of connected `{ id, session }` rows. */
23
+ list(): Array<{
24
+ id: string;
25
+ session: Session;
26
+ }>;
27
+ /** Record and deliver `payload` to `id`. Leaves the client if `send` throws. */
28
+ send(id: string, payload: string): void;
29
+ /** Close every connection and clear clients. Does not clear `sent`. */
30
+ stop(): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=in-memory-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-channel.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAO5E;;GAEG;AACH,qBAAa,eAAe,CAAC,OAAO,GAAG,OAAO,CAC5C,YAAW,cAAc,CAAC,OAAO,CAAC;;IAElC,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAM;IAG3D,0EAA0E;IAC1E,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,CAAC;IAItC,6EAA6E;IAC7E,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,GAAG,IAAI;IAOvE,sDAAsD;IACtD,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIvB,gEAAgE;IAChE,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAMvB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAM1C,oDAAoD;IACpD,IAAI,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAO/C,gFAAgF;IAChF,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAWvC,uEAAuE;IACjE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAM5B"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * In-process channel adapter. Records `sent`. `stop()` closes connections.
3
+ */
4
+ export class InMemoryChannel {
5
+ /** `{ id, payload }` records from `send`, in order. */
6
+ sent = [];
7
+ #clients = new Map();
8
+ /** Empty channel. Pass to `.route(Channel, InMemoryChannel.create())`. */
9
+ static create() {
10
+ return new InMemoryChannel();
11
+ }
12
+ /** Track a connected client. Replaces an existing row with the same `id`. */
13
+ join(id, session, connection) {
14
+ this.#clients.set(id, { session, connection });
15
+ connection.addEventListener('close', () => {
16
+ this.leave(id);
17
+ });
18
+ }
19
+ /** Drop the client without closing the connection. */
20
+ leave(id) {
21
+ this.#clients.delete(id);
22
+ }
23
+ /** Close the connection; the `close` listener then `leave`s. */
24
+ eject(id) {
25
+ const row = this.#clients.get(id);
26
+ if (!row)
27
+ return;
28
+ row.connection.close();
29
+ }
30
+ /** Replace session claims for a connected client. No-op if unknown `id`. */
31
+ update(id, session) {
32
+ const row = this.#clients.get(id);
33
+ if (!row)
34
+ return;
35
+ row.session = session;
36
+ }
37
+ /** Snapshot of connected `{ id, session }` rows. */
38
+ list() {
39
+ return [...this.#clients.entries()].map(([id, row]) => ({
40
+ id,
41
+ session: row.session,
42
+ }));
43
+ }
44
+ /** Record and deliver `payload` to `id`. Leaves the client if `send` throws. */
45
+ send(id, payload) {
46
+ const row = this.#clients.get(id);
47
+ if (!row)
48
+ return;
49
+ this.sent.push({ id, payload });
50
+ try {
51
+ row.connection.send(payload);
52
+ }
53
+ catch {
54
+ this.leave(id);
55
+ }
56
+ }
57
+ /** Close every connection and clear clients. Does not clear `sent`. */
58
+ async stop() {
59
+ for (const { connection } of this.#clients.values()) {
60
+ connection.close();
61
+ }
62
+ this.#clients.clear();
63
+ }
64
+ }
65
+ //# sourceMappingURL=in-memory-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-channel.js","sourceRoot":"","sources":["../../src/testing/in-memory-channel.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,OAAO,eAAe;IAG1B,uDAAuD;IAC9C,IAAI,GAA2C,EAAE,CAAC;IAC3D,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE3C,0EAA0E;IAC1E,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,eAAe,EAAK,CAAC;IAClC,CAAC;IAED,6EAA6E;IAC7E,IAAI,CAAC,EAAU,EAAE,OAAgB,EAAE,UAA6B;QAC9D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/C,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACxC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,EAAU;QACd,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,EAAU;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,EAAU,EAAE,OAAgB;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,oDAAoD;IACpD,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YACtD,EAAE;YACF,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,gFAAgF;IAChF,IAAI,CAAC,EAAU,EAAE,OAAe;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,IAAI;QACR,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACpD,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ import type { Envelope, QueueAdapter, QueueConsumeCtx } from '../domain/index.js';
2
+ type Consumer = (envelope: Envelope, ctx: QueueConsumeCtx) => Promise<void>;
3
+ /**
4
+ * In-process queue. `nack` (or a throw) redelivers with `attempt + 1` up to
5
+ * `maxAttempts` (default 3). `stop()` clears consumers.
6
+ */
7
+ export declare class InMemoryQueue implements QueueAdapter {
8
+ #private;
9
+ readonly kind: "queue";
10
+ /** Envelopes passed to `publish`, in order (one entry per publish, not per attempt). */
11
+ readonly published: Envelope[];
12
+ /** Stop redelivering after this many attempts. */
13
+ maxAttempts: number;
14
+ /** Empty queue. Pass to `.bind(catalog, InMemoryQueue.create())`. */
15
+ static create(): InMemoryQueue;
16
+ /** Record the envelope and dispatch every consumer group for its key. */
17
+ publish(envelope: Envelope): Promise<void>;
18
+ /** Register the consumer for `key`+`group`. Later calls replace that group. */
19
+ consume(key: string, group: string, handler: Consumer): void;
20
+ /** Drop all consumers. Does not clear `published`. */
21
+ stop(): Promise<void>;
22
+ }
23
+ export {};
24
+ //# sourceMappingURL=in-memory-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-queue.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,KAAK,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5E;;;GAGG;AACH,qBAAa,aAAc,YAAW,YAAY;;IAChD,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAM;IAEpC,kDAAkD;IAClD,WAAW,SAAK;IAEhB,qEAAqE;IACrE,MAAM,CAAC,MAAM,IAAI,aAAa;IAI9B,yEAAyE;IACnE,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAuChD,+EAA+E;IAC/E,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI;IAM5D,sDAAsD;IAChD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * In-process queue. `nack` (or a throw) redelivers with `attempt + 1` up to
3
+ * `maxAttempts` (default 3). `stop()` clears consumers.
4
+ */
5
+ export class InMemoryQueue {
6
+ kind = 'queue';
7
+ /** Envelopes passed to `publish`, in order (one entry per publish, not per attempt). */
8
+ published = [];
9
+ #consumers = new Map();
10
+ /** Stop redelivering after this many attempts. */
11
+ maxAttempts = 3;
12
+ /** Empty queue. Pass to `.bind(catalog, InMemoryQueue.create())`. */
13
+ static create() {
14
+ return new InMemoryQueue();
15
+ }
16
+ /** Record the envelope and dispatch every consumer group for its key. */
17
+ async publish(envelope) {
18
+ this.published.push(envelope);
19
+ const groups = this.#consumers.get(envelope.key);
20
+ if (!groups)
21
+ return;
22
+ for (const consumer of groups.values()) {
23
+ await this.#deliver(envelope, consumer, 1);
24
+ }
25
+ }
26
+ async #deliver(envelope, consumer, attempt) {
27
+ let outcome = 'none';
28
+ let thrown;
29
+ const ctx = {
30
+ attempt,
31
+ ack: async () => {
32
+ outcome = 'ack';
33
+ },
34
+ nack: async () => {
35
+ outcome = 'nack';
36
+ },
37
+ };
38
+ try {
39
+ await consumer(envelope, ctx);
40
+ }
41
+ catch (error) {
42
+ thrown = error;
43
+ if (outcome === 'none')
44
+ outcome = 'nack';
45
+ }
46
+ if (outcome !== 'nack')
47
+ return;
48
+ if (attempt < this.maxAttempts) {
49
+ await this.#deliver(envelope, consumer, attempt + 1);
50
+ return;
51
+ }
52
+ if (thrown !== undefined)
53
+ throw thrown;
54
+ }
55
+ /** Register the consumer for `key`+`group`. Later calls replace that group. */
56
+ consume(key, group, handler) {
57
+ const groups = this.#consumers.get(key) ?? new Map();
58
+ groups.set(group, handler);
59
+ this.#consumers.set(key, groups);
60
+ }
61
+ /** Drop all consumers. Does not clear `published`. */
62
+ async stop() {
63
+ this.#consumers.clear();
64
+ }
65
+ }
66
+ //# sourceMappingURL=in-memory-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-queue.js","sourceRoot":"","sources":["../../src/testing/in-memory-queue.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,OAAO,aAAa;IACf,IAAI,GAAG,OAAgB,CAAC;IACjC,wFAAwF;IAC/E,SAAS,GAAe,EAAE,CAAC;IACpC,UAAU,GAAG,IAAI,GAAG,EAAiC,CAAC;IACtD,kDAAkD;IAClD,WAAW,GAAG,CAAC,CAAC;IAEhB,qEAAqE;IACrE,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,OAAO,CAAC,QAAkB;QAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,QAAkB,EAClB,QAAkB,EAClB,OAAe;QAEf,IAAI,OAAO,GAA4B,MAAM,CAAC;QAC9C,IAAI,MAAe,CAAC;QACpB,MAAM,GAAG,GAAoB;YAC3B,OAAO;YACP,GAAG,EAAE,KAAK,IAAI,EAAE;gBACd,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;YACD,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,OAAO,GAAG,MAAM,CAAC;YACnB,CAAC;SACF,CAAC;QACF,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,KAAK,CAAC;YACf,IAAI,OAAO,KAAK,MAAM;gBAAE,OAAO,GAAG,MAAM,CAAC;QAC3C,CAAC;QACD,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO;QAC/B,IAAI,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QACD,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,MAAM,CAAC;IACzC,CAAC;IAED,+EAA+E;IAC/E,OAAO,CAAC,GAAW,EAAE,KAAa,EAAE,OAAiB;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAAoB,CAAC;QACvE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF"}