@ddd-ts-kit/events 0.0.0-stage → 0.1.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 (230) hide show
  1. package/README.md +462 -2
  2. package/dist/asyncapi/async-api-document.d.ts +15 -0
  3. package/dist/asyncapi/async-api-document.d.ts.map +1 -0
  4. package/dist/asyncapi/async-api-document.js +2 -0
  5. package/dist/asyncapi/async-api-document.js.map +1 -0
  6. package/dist/asyncapi/async-api-info.d.ts +6 -0
  7. package/dist/asyncapi/async-api-info.d.ts.map +1 -0
  8. package/dist/asyncapi/async-api-info.js +2 -0
  9. package/dist/asyncapi/async-api-info.js.map +1 -0
  10. package/dist/asyncapi/async-api-server.d.ts +7 -0
  11. package/dist/asyncapi/async-api-server.d.ts.map +1 -0
  12. package/dist/asyncapi/async-api-server.js +2 -0
  13. package/dist/asyncapi/async-api-server.js.map +1 -0
  14. package/dist/asyncapi/check-async-api-drift.d.ts +6 -0
  15. package/dist/asyncapi/check-async-api-drift.d.ts.map +1 -0
  16. package/dist/asyncapi/check-async-api-drift.js +6 -0
  17. package/dist/asyncapi/check-async-api-drift.js.map +1 -0
  18. package/dist/asyncapi/generate-async-api.d.ts +16 -0
  19. package/dist/asyncapi/generate-async-api.d.ts.map +1 -0
  20. package/dist/asyncapi/generate-async-api.js +116 -0
  21. package/dist/asyncapi/generate-async-api.js.map +1 -0
  22. package/dist/asyncapi/stringify-async-api.d.ts +4 -0
  23. package/dist/asyncapi/stringify-async-api.d.ts.map +1 -0
  24. package/dist/asyncapi/stringify-async-api.js +5 -0
  25. package/dist/asyncapi/stringify-async-api.js.map +1 -0
  26. package/dist/asyncapi.d.ts +7 -0
  27. package/dist/asyncapi.d.ts.map +1 -0
  28. package/dist/asyncapi.js +7 -0
  29. package/dist/asyncapi.js.map +1 -0
  30. package/dist/catalog/generate-event-catalog.d.ts +12 -0
  31. package/dist/catalog/generate-event-catalog.d.ts.map +1 -0
  32. package/dist/catalog/generate-event-catalog.js +63 -0
  33. package/dist/catalog/generate-event-catalog.js.map +1 -0
  34. package/dist/catalog/payload-field.d.ts +8 -0
  35. package/dist/catalog/payload-field.d.ts.map +1 -0
  36. package/dist/catalog/payload-field.js +2 -0
  37. package/dist/catalog/payload-field.js.map +1 -0
  38. package/dist/catalog/payload-fields.d.ts +7 -0
  39. package/dist/catalog/payload-fields.d.ts.map +1 -0
  40. package/dist/catalog/payload-fields.js +105 -0
  41. package/dist/catalog/payload-fields.js.map +1 -0
  42. package/dist/definition/any-integration-event-definition.d.ts +4 -0
  43. package/dist/definition/any-integration-event-definition.d.ts.map +1 -0
  44. package/dist/definition/any-integration-event-definition.js +2 -0
  45. package/dist/definition/any-integration-event-definition.js.map +1 -0
  46. package/dist/definition/define-integration-event.d.ts +15 -0
  47. package/dist/definition/define-integration-event.d.ts.map +1 -0
  48. package/dist/definition/define-integration-event.js +73 -0
  49. package/dist/definition/define-integration-event.js.map +1 -0
  50. package/dist/definition/event-meta.d.ts +7 -0
  51. package/dist/definition/event-meta.d.ts.map +1 -0
  52. package/dist/definition/event-meta.js +2 -0
  53. package/dist/definition/event-meta.js.map +1 -0
  54. package/dist/definition/event-parse-error.d.ts +14 -0
  55. package/dist/definition/event-parse-error.d.ts.map +1 -0
  56. package/dist/definition/event-parse-error.js +2 -0
  57. package/dist/definition/event-parse-error.js.map +1 -0
  58. package/dist/definition/integration-event-definition.d.ts +20 -0
  59. package/dist/definition/integration-event-definition.d.ts.map +1 -0
  60. package/dist/definition/integration-event-definition.js +2 -0
  61. package/dist/definition/integration-event-definition.js.map +1 -0
  62. package/dist/definition/invalid-event-definition-error.d.ts +4 -0
  63. package/dist/definition/invalid-event-definition-error.d.ts.map +1 -0
  64. package/dist/definition/invalid-event-definition-error.js +7 -0
  65. package/dist/definition/invalid-event-definition-error.js.map +1 -0
  66. package/dist/definition/invalid-event-payload-error.d.ts +9 -0
  67. package/dist/definition/invalid-event-payload-error.d.ts.map +1 -0
  68. package/dist/definition/invalid-event-payload-error.js +16 -0
  69. package/dist/definition/invalid-event-payload-error.js.map +1 -0
  70. package/dist/definition/payload-of.d.ts +3 -0
  71. package/dist/definition/payload-of.d.ts.map +1 -0
  72. package/dist/definition/payload-of.js +2 -0
  73. package/dist/definition/payload-of.js.map +1 -0
  74. package/dist/index.d.ts +37 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +37 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/internal/json-schema/as-schema.d.ts +3 -0
  79. package/dist/internal/json-schema/as-schema.d.ts.map +1 -0
  80. package/dist/internal/json-schema/as-schema.js +5 -0
  81. package/dist/internal/json-schema/as-schema.js.map +1 -0
  82. package/dist/internal/json-schema/compare-text.d.ts +2 -0
  83. package/dist/internal/json-schema/compare-text.d.ts.map +1 -0
  84. package/dist/internal/json-schema/compare-text.js +5 -0
  85. package/dist/internal/json-schema/compare-text.js.map +1 -0
  86. package/dist/internal/json-schema/is-record.d.ts +2 -0
  87. package/dist/internal/json-schema/is-record.d.ts.map +1 -0
  88. package/dist/internal/json-schema/is-record.js +4 -0
  89. package/dist/internal/json-schema/is-record.js.map +1 -0
  90. package/dist/internal/json-schema/local-ref-name.d.ts +3 -0
  91. package/dist/internal/json-schema/local-ref-name.d.ts.map +1 -0
  92. package/dist/internal/json-schema/local-ref-name.js +6 -0
  93. package/dist/internal/json-schema/local-ref-name.js.map +1 -0
  94. package/dist/internal/json-schema/rewrite-local-refs.d.ts +2 -0
  95. package/dist/internal/json-schema/rewrite-local-refs.d.ts.map +1 -0
  96. package/dist/internal/json-schema/rewrite-local-refs.js +19 -0
  97. package/dist/internal/json-schema/rewrite-local-refs.js.map +1 -0
  98. package/dist/internal/json-schema/sort-keys.d.ts +2 -0
  99. package/dist/internal/json-schema/sort-keys.d.ts.map +1 -0
  100. package/dist/internal/json-schema/sort-keys.js +5 -0
  101. package/dist/internal/json-schema/sort-keys.js.map +1 -0
  102. package/dist/internal/json-schema/split-definitions.d.ts +8 -0
  103. package/dist/internal/json-schema/split-definitions.d.ts.map +1 -0
  104. package/dist/internal/json-schema/split-definitions.js +13 -0
  105. package/dist/internal/json-schema/split-definitions.js.map +1 -0
  106. package/dist/outbox/duplicate-outbox-event-error.d.ts +5 -0
  107. package/dist/outbox/duplicate-outbox-event-error.d.ts.map +1 -0
  108. package/dist/outbox/duplicate-outbox-event-error.js +8 -0
  109. package/dist/outbox/duplicate-outbox-event-error.js.map +1 -0
  110. package/dist/outbox/in-memory-outbox-store.d.ts +32 -0
  111. package/dist/outbox/in-memory-outbox-store.d.ts.map +1 -0
  112. package/dist/outbox/in-memory-outbox-store.js +121 -0
  113. package/dist/outbox/in-memory-outbox-store.js.map +1 -0
  114. package/dist/outbox/outbox-publisher.d.ts +14 -0
  115. package/dist/outbox/outbox-publisher.d.ts.map +1 -0
  116. package/dist/outbox/outbox-publisher.js +18 -0
  117. package/dist/outbox/outbox-publisher.js.map +1 -0
  118. package/dist/outbox/outbox-record.d.ts +14 -0
  119. package/dist/outbox/outbox-record.d.ts.map +1 -0
  120. package/dist/outbox/outbox-record.js +2 -0
  121. package/dist/outbox/outbox-record.js.map +1 -0
  122. package/dist/outbox/outbox-stats.d.ts +9 -0
  123. package/dist/outbox/outbox-stats.d.ts.map +1 -0
  124. package/dist/outbox/outbox-stats.js +2 -0
  125. package/dist/outbox/outbox-stats.js.map +1 -0
  126. package/dist/outbox/outbox-status.d.ts +2 -0
  127. package/dist/outbox/outbox-status.d.ts.map +1 -0
  128. package/dist/outbox/outbox-status.js +2 -0
  129. package/dist/outbox/outbox-status.js.map +1 -0
  130. package/dist/outbox/outbox-store.d.ts +33 -0
  131. package/dist/outbox/outbox-store.d.ts.map +1 -0
  132. package/dist/outbox/outbox-store.js +13 -0
  133. package/dist/outbox/outbox-store.js.map +1 -0
  134. package/dist/publishing/unknown-event-error.d.ts +7 -0
  135. package/dist/publishing/unknown-event-error.d.ts.map +1 -0
  136. package/dist/publishing/unknown-event-error.js +12 -0
  137. package/dist/publishing/unknown-event-error.js.map +1 -0
  138. package/dist/publishing/validating-publisher.d.ts +12 -0
  139. package/dist/publishing/validating-publisher.d.ts.map +1 -0
  140. package/dist/publishing/validating-publisher.js +33 -0
  141. package/dist/publishing/validating-publisher.js.map +1 -0
  142. package/dist/registry/create-event-registry.d.ts +4 -0
  143. package/dist/registry/create-event-registry.d.ts.map +1 -0
  144. package/dist/registry/create-event-registry.js +5 -0
  145. package/dist/registry/create-event-registry.js.map +1 -0
  146. package/dist/registry/duplicate-event-definition-error.d.ts +4 -0
  147. package/dist/registry/duplicate-event-definition-error.d.ts.map +1 -0
  148. package/dist/registry/duplicate-event-definition-error.js +7 -0
  149. package/dist/registry/duplicate-event-definition-error.js.map +1 -0
  150. package/dist/registry/event-registry.d.ts +11 -0
  151. package/dist/registry/event-registry.d.ts.map +1 -0
  152. package/dist/registry/event-registry.js +33 -0
  153. package/dist/registry/event-registry.js.map +1 -0
  154. package/dist/relay/claim-window.d.ts +6 -0
  155. package/dist/relay/claim-window.d.ts.map +1 -0
  156. package/dist/relay/claim-window.js +2 -0
  157. package/dist/relay/claim-window.js.map +1 -0
  158. package/dist/relay/error-code.d.ts +6 -0
  159. package/dist/relay/error-code.d.ts.map +1 -0
  160. package/dist/relay/error-code.js +16 -0
  161. package/dist/relay/error-code.js.map +1 -0
  162. package/dist/relay/event-key.d.ts +3 -0
  163. package/dist/relay/event-key.d.ts.map +1 -0
  164. package/dist/relay/event-key.js +2 -0
  165. package/dist/relay/event-key.js.map +1 -0
  166. package/dist/relay/hold-until.d.ts +3 -0
  167. package/dist/relay/hold-until.d.ts.map +1 -0
  168. package/dist/relay/hold-until.js +2 -0
  169. package/dist/relay/hold-until.js.map +1 -0
  170. package/dist/relay/in-memory-relay-signal.d.ts +9 -0
  171. package/dist/relay/in-memory-relay-signal.d.ts.map +1 -0
  172. package/dist/relay/in-memory-relay-signal.js +13 -0
  173. package/dist/relay/in-memory-relay-signal.js.map +1 -0
  174. package/dist/relay/key-order.d.ts +35 -0
  175. package/dist/relay/key-order.d.ts.map +1 -0
  176. package/dist/relay/key-order.js +102 -0
  177. package/dist/relay/key-order.js.map +1 -0
  178. package/dist/relay/keyed-record.d.ts +6 -0
  179. package/dist/relay/keyed-record.d.ts.map +1 -0
  180. package/dist/relay/keyed-record.js +2 -0
  181. package/dist/relay/keyed-record.js.map +1 -0
  182. package/dist/relay/outbox-backoff.d.ts +9 -0
  183. package/dist/relay/outbox-backoff.d.ts.map +1 -0
  184. package/dist/relay/outbox-backoff.js +2 -0
  185. package/dist/relay/outbox-backoff.js.map +1 -0
  186. package/dist/relay/outbox-ordering.d.ts +7 -0
  187. package/dist/relay/outbox-ordering.d.ts.map +1 -0
  188. package/dist/relay/outbox-ordering.js +2 -0
  189. package/dist/relay/outbox-ordering.js.map +1 -0
  190. package/dist/relay/outbox-relay-failure.d.ts +12 -0
  191. package/dist/relay/outbox-relay-failure.d.ts.map +1 -0
  192. package/dist/relay/outbox-relay-failure.js +2 -0
  193. package/dist/relay/outbox-relay-failure.js.map +1 -0
  194. package/dist/relay/outbox-relay.d.ts +85 -0
  195. package/dist/relay/outbox-relay.d.ts.map +1 -0
  196. package/dist/relay/outbox-relay.js +193 -0
  197. package/dist/relay/outbox-relay.js.map +1 -0
  198. package/dist/relay/record-group.d.ts +6 -0
  199. package/dist/relay/record-group.d.ts.map +1 -0
  200. package/dist/relay/record-group.js +2 -0
  201. package/dist/relay/record-group.js.map +1 -0
  202. package/dist/relay/relay-signal.d.ts +15 -0
  203. package/dist/relay/relay-signal.d.ts.map +1 -0
  204. package/dist/relay/relay-signal.js +12 -0
  205. package/dist/relay/relay-signal.js.map +1 -0
  206. package/dist/subscription/consume.d.ts +18 -0
  207. package/dist/subscription/consume.d.ts.map +1 -0
  208. package/dist/subscription/consume.js +10 -0
  209. package/dist/subscription/consume.js.map +1 -0
  210. package/dist/subscription/event-scope-options.d.ts +13 -0
  211. package/dist/subscription/event-scope-options.d.ts.map +1 -0
  212. package/dist/subscription/event-scope-options.js +2 -0
  213. package/dist/subscription/event-scope-options.js.map +1 -0
  214. package/dist/subscription/event-subscription.d.ts +6 -0
  215. package/dist/subscription/event-subscription.d.ts.map +1 -0
  216. package/dist/subscription/event-subscription.js +2 -0
  217. package/dist/subscription/event-subscription.js.map +1 -0
  218. package/dist/subscription/on.d.ts +26 -0
  219. package/dist/subscription/on.d.ts.map +1 -0
  220. package/dist/subscription/on.js +62 -0
  221. package/dist/subscription/on.js.map +1 -0
  222. package/dist/subscription/releasable-processed-event-store.d.ts +14 -0
  223. package/dist/subscription/releasable-processed-event-store.d.ts.map +1 -0
  224. package/dist/subscription/releasable-processed-event-store.js +2 -0
  225. package/dist/subscription/releasable-processed-event-store.js.map +1 -0
  226. package/dist/subscription/subscribe-all.d.ts +5 -0
  227. package/dist/subscription/subscribe-all.d.ts.map +1 -0
  228. package/dist/subscription/subscribe-all.js +12 -0
  229. package/dist/subscription/subscribe-all.js.map +1 -0
  230. package/package.json +37 -4
@@ -0,0 +1,2 @@
1
+ export type OutboxStatus = 'pending' | 'published' | 'dead';
2
+ //# sourceMappingURL=outbox-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-status.d.ts","sourceRoot":"","sources":["../../src/outbox/outbox-status.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=outbox-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-status.js","sourceRoot":"","sources":["../../src/outbox/outbox-status.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ import type { IntegrationEvent } from '@ddd-ts-kit/kernel';
2
+ import type { OutboxRecord } from './outbox-record.js';
3
+ import type { OutboxStats } from './outbox-stats.js';
4
+ /**
5
+ * Where events wait between the commit of the command and their publication.
6
+ *
7
+ * A claim is a lease, not a lock held by the caller: `claimBatch` hands out due records and
8
+ * pushes their `nextAttemptAt` forward by the lease of the store, so a relay that dies
9
+ * mid-flight simply lets the lease expire and the records are claimed again. This keeps the
10
+ * port implementable by SQL (`FOR UPDATE SKIP LOCKED` inside the claim), by a document store
11
+ * with a conditional update, or by a queue with a visibility timeout.
12
+ */
13
+ export declare abstract class OutboxStore {
14
+ static readonly tokenKey = "events.OutboxStore";
15
+ /** Must join the transaction of the command when the store is transactional. */
16
+ abstract append(events: readonly IntegrationEvent[]): Promise<void>;
17
+ /**
18
+ * Claims up to `limit` pending records due at `now`, oldest first, and counts the attempt.
19
+ * Two concurrent calls never return the same record.
20
+ */
21
+ abstract claimBatch(limit: number, now: Date): Promise<OutboxRecord[]>;
22
+ abstract markPublished(ids: readonly string[], at: Date): Promise<void>;
23
+ /** Schedules the retry at `nextAttemptAt`, or declares the record dead when it is `null`. */
24
+ abstract markFailed(id: string, error: {
25
+ readonly code: string;
26
+ }, nextAttemptAt: Date | null): Promise<void>;
27
+ /** Puts dead records back in the queue with a fresh attempt budget. Returns how many. */
28
+ abstract retryDead(ids: readonly string[], now: Date): Promise<number>;
29
+ /** Housekeeping: drops the records published before `before`. Returns how many. */
30
+ abstract purgePublished(before: Date): Promise<number>;
31
+ abstract stats(): Promise<OutboxStats>;
32
+ }
33
+ //# sourceMappingURL=outbox-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-store.d.ts","sourceRoot":"","sources":["../../src/outbox/outbox-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;GAQG;AACH,8BAAsB,WAAW;IAC/B,MAAM,CAAC,QAAQ,CAAC,QAAQ,wBAAwB;IAEhD,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEvE,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE,6FAA6F;IAC7F,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,aAAa,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7G,yFAAyF;IACzF,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvE,mFAAmF;IACnF,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvD,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACxC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Where events wait between the commit of the command and their publication.
3
+ *
4
+ * A claim is a lease, not a lock held by the caller: `claimBatch` hands out due records and
5
+ * pushes their `nextAttemptAt` forward by the lease of the store, so a relay that dies
6
+ * mid-flight simply lets the lease expire and the records are claimed again. This keeps the
7
+ * port implementable by SQL (`FOR UPDATE SKIP LOCKED` inside the claim), by a document store
8
+ * with a conditional update, or by a queue with a visibility timeout.
9
+ */
10
+ export class OutboxStore {
11
+ static tokenKey = 'events.OutboxStore';
12
+ }
13
+ //# sourceMappingURL=outbox-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-store.js","sourceRoot":"","sources":["../../src/outbox/outbox-store.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,MAAM,OAAgB,WAAW;IAC/B,MAAM,CAAU,QAAQ,GAAG,oBAAoB,CAAC;CAuBjD"}
@@ -0,0 +1,7 @@
1
+ export declare class UnknownEventError extends Error {
2
+ readonly eventType: string;
3
+ readonly eventVersion: number;
4
+ readonly code = "UNKNOWN_EVENT";
5
+ constructor(eventType: string, eventVersion: number);
6
+ }
7
+ //# sourceMappingURL=unknown-event-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknown-event-error.d.ts","sourceRoot":"","sources":["../../src/publishing/unknown-event-error.ts"],"names":[],"mappings":"AAAA,qBAAa,iBAAkB,SAAQ,KAAK;IAIxC,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM;IAJ/B,QAAQ,CAAC,IAAI,mBAAmB;IAEhC,YACW,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EAI9B;CACF"}
@@ -0,0 +1,12 @@
1
+ export class UnknownEventError extends Error {
2
+ eventType;
3
+ eventVersion;
4
+ code = 'UNKNOWN_EVENT';
5
+ constructor(eventType, eventVersion) {
6
+ super(`Integration event ${eventType} v${eventVersion} is not declared in the registry`);
7
+ this.eventType = eventType;
8
+ this.eventVersion = eventVersion;
9
+ this.name = 'UnknownEventError';
10
+ }
11
+ }
12
+ //# sourceMappingURL=unknown-event-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknown-event-error.js","sourceRoot":"","sources":["../../src/publishing/unknown-event-error.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAI/B,SAAS;IACT,YAAY;IAJd,IAAI,GAAG,eAAe,CAAC;IAEhC,YACW,SAAiB,EACjB,YAAoB;QAE7B,KAAK,CAAC,qBAAqB,SAAS,KAAK,YAAY,kCAAkC,CAAC,CAAC;yBAHhF,SAAS;4BACT,YAAY;QAGrB,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import { type IntegrationEventPublisher } from '@ddd-ts-kit/kernel';
2
+ import type { EventRegistry } from '../registry/event-registry.js';
3
+ export interface ValidatingPublisherOptions {
4
+ /** What to do with an event whose type and version are not in the registry. */
5
+ readonly unknown: 'reject' | 'allow';
6
+ }
7
+ /**
8
+ * Refuses what the registry does not describe. The whole batch is checked before anything
9
+ * is published, so a refused batch leaves no partial publication behind.
10
+ */
11
+ export declare function validatingPublisher(publisher: IntegrationEventPublisher, registry: EventRegistry, options?: ValidatingPublisherOptions): IntegrationEventPublisher;
12
+ //# sourceMappingURL=validating-publisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validating-publisher.d.ts","sourceRoot":"","sources":["../../src/publishing/validating-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE9G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE,MAAM,WAAW,0BAA0B;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,yBAAyB,EACpC,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,0BAAkD,GAC1D,yBAAyB,CAa3B"}
@@ -0,0 +1,33 @@
1
+ import { messagingSystemOf } from '@ddd-ts-kit/kernel';
2
+ import { InvalidEventPayloadError } from '../definition/invalid-event-payload-error.js';
3
+ import { UnknownEventError } from './unknown-event-error.js';
4
+ /**
5
+ * Refuses what the registry does not describe. The whole batch is checked before anything
6
+ * is published, so a refused batch leaves no partial publication behind.
7
+ */
8
+ export function validatingPublisher(publisher, registry, options = { unknown: 'reject' }) {
9
+ const messagingSystem = messagingSystemOf(publisher);
10
+ return {
11
+ async publish(events) {
12
+ for (const event of events) {
13
+ assertDeclared(event, registry, options);
14
+ }
15
+ await publisher.publish(events);
16
+ },
17
+ ...(messagingSystem === undefined ? {} : { messagingSystem }),
18
+ };
19
+ }
20
+ function assertDeclared(event, registry, options) {
21
+ const definition = registry.get(event.type, event.version);
22
+ if (definition === undefined) {
23
+ if (options.unknown === 'reject') {
24
+ throw new UnknownEventError(event.type, event.version);
25
+ }
26
+ return;
27
+ }
28
+ const parsed = definition.payload.parse(event.payload);
29
+ if (!parsed.ok) {
30
+ throw new InvalidEventPayloadError(event.type, event.version, parsed.error);
31
+ }
32
+ }
33
+ //# sourceMappingURL=validating-publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validating-publisher.js","sourceRoot":"","sources":["../../src/publishing/validating-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAyD,MAAM,oBAAoB,CAAC;AAC9G,OAAO,EAAE,wBAAwB,EAAE,MAAM,8CAA8C,CAAC;AAExF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAO7D;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAoC,EACpC,QAAuB,EACvB,OAAO,GAA+B,EAAE,OAAO,EAAE,QAAQ,EAAE;IAE3D,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAErD,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,MAAM;YAClB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC3C,CAAC;YAED,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QACD,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAuB,EAAE,QAAuB,EAAE,OAAmC;IAC3G,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAE3D,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACzD,CAAC;QAED,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,wBAAwB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { AnyIntegrationEventDefinition } from '../definition/any-integration-event-definition.js';
2
+ import { EventRegistry } from './event-registry.js';
3
+ export declare function createEventRegistry(definitions?: readonly AnyIntegrationEventDefinition[]): EventRegistry;
4
+ //# sourceMappingURL=create-event-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-event-registry.d.ts","sourceRoot":"","sources":["../../src/registry/create-event-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAC;AACvG,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,WAAW,GAAE,SAAS,6BAA6B,EAAO,GAAG,aAAa,CAE7G"}
@@ -0,0 +1,5 @@
1
+ import { EventRegistry } from './event-registry.js';
2
+ export function createEventRegistry(definitions = []) {
3
+ return new EventRegistry().register(...definitions);
4
+ }
5
+ //# sourceMappingURL=create-event-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-event-registry.js","sourceRoot":"","sources":["../../src/registry/create-event-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,UAAU,mBAAmB,CAAC,WAAW,GAA6C,EAAE;IAC5F,OAAO,IAAI,aAAa,EAAE,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare class DuplicateEventDefinitionError extends Error {
2
+ constructor(type: string, version: number);
3
+ }
4
+ //# sourceMappingURL=duplicate-event-definition-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-event-definition-error.d.ts","sourceRoot":"","sources":["../../src/registry/duplicate-event-definition-error.ts"],"names":[],"mappings":"AAAA,qBAAa,6BAA8B,SAAQ,KAAK;IACtD,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGxC;CACF"}
@@ -0,0 +1,7 @@
1
+ export class DuplicateEventDefinitionError extends Error {
2
+ constructor(type, version) {
3
+ super(`Integration event ${type} v${version} is already registered`);
4
+ this.name = 'DuplicateEventDefinitionError';
5
+ }
6
+ }
7
+ //# sourceMappingURL=duplicate-event-definition-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-event-definition-error.js","sourceRoot":"","sources":["../../src/registry/duplicate-event-definition-error.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,6BAA8B,SAAQ,KAAK;IACtD,YAAY,IAAY,EAAE,OAAe;QACvC,KAAK,CAAC,qBAAqB,IAAI,KAAK,OAAO,wBAAwB,CAAC,CAAC;QACrE,IAAI,CAAC,IAAI,GAAG,+BAA+B,CAAC;IAC9C,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { AnyIntegrationEventDefinition } from '../definition/any-integration-event-definition.js';
2
+ /** Every event a system publishes. Feeds validation, the AsyncAPI document and the catalog. */
3
+ export declare class EventRegistry {
4
+ private readonly definitions;
5
+ register(...definitions: readonly AnyIntegrationEventDefinition[]): this;
6
+ get(type: string, version: number): AnyIntegrationEventDefinition | undefined;
7
+ /** Sorted by type then version, whatever the registration order. */
8
+ all(): AnyIntegrationEventDefinition[];
9
+ versionsOf(type: string): number[];
10
+ }
11
+ //# sourceMappingURL=event-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-registry.d.ts","sourceRoot":"","sources":["../../src/registry/event-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAC;AAIvG,+FAA+F;AAC/F,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoD;IAEhF,QAAQ,CAAC,GAAG,WAAW,EAAE,SAAS,6BAA6B,EAAE,GAAG,IAAI,CAYvE;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,6BAA6B,GAAG,SAAS,CAE5E;IAED,oEAAoE;IACpE,GAAG,IAAI,6BAA6B,EAAE,CAErC;IAED,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAIjC;CACF"}
@@ -0,0 +1,33 @@
1
+ import { compareText } from '../internal/json-schema/compare-text.js';
2
+ import { DuplicateEventDefinitionError } from './duplicate-event-definition-error.js';
3
+ /** Every event a system publishes. Feeds validation, the AsyncAPI document and the catalog. */
4
+ export class EventRegistry {
5
+ definitions = new Map();
6
+ register(...definitions) {
7
+ for (const definition of definitions) {
8
+ const key = keyOf(definition.type, definition.version);
9
+ if (this.definitions.has(key)) {
10
+ throw new DuplicateEventDefinitionError(definition.type, definition.version);
11
+ }
12
+ this.definitions.set(key, definition);
13
+ }
14
+ return this;
15
+ }
16
+ get(type, version) {
17
+ return this.definitions.get(keyOf(type, version));
18
+ }
19
+ /** Sorted by type then version, whatever the registration order. */
20
+ all() {
21
+ return [...this.definitions.values()].sort((a, b) => compareText(a.type, b.type) || a.version - b.version);
22
+ }
23
+ versionsOf(type) {
24
+ return this.all()
25
+ .filter((definition) => definition.type === type)
26
+ .map((definition) => definition.version);
27
+ }
28
+ }
29
+ // A type never contains "@", so the key cannot collide.
30
+ function keyOf(type, version) {
31
+ return `${type}@${version}`;
32
+ }
33
+ //# sourceMappingURL=event-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-registry.js","sourceRoot":"","sources":["../../src/registry/event-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAEtF,+FAA+F;AAC/F,MAAM,OAAO,aAAa;IACP,WAAW,GAAG,IAAI,GAAG,EAAyC,CAAC;IAEhF,QAAQ,CAAC,GAAG,WAAqD;QAC/D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;YAEvD,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,6BAA6B,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;YAC/E,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,OAAe;QAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,oEAAoE;IACpE,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IAC7G,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,GAAG,EAAE;aACd,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;aAChD,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;CACF;AAED,wDAAwD;AACxD,SAAS,KAAK,CAAC,IAAY,EAAE,OAAe;IAC1C,OAAO,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface ClaimWindow {
2
+ readonly now: Date;
3
+ /** True when the claim returned fewer records than asked: nothing else was due. */
4
+ readonly complete: boolean;
5
+ }
6
+ //# sourceMappingURL=claim-window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-window.d.ts","sourceRoot":"","sources":["../../src/relay/claim-window.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=claim-window.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-window.js","sourceRoot":"","sources":["../../src/relay/claim-window.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * What may be stored and logged about a caught error: its `code` when it carries one, else
3
+ * its class name. Never its message, which may quote payload data.
4
+ */
5
+ export declare function errorCode(error: unknown): string;
6
+ //# sourceMappingURL=error-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-code.d.ts","sourceRoot":"","sources":["../../src/relay/error-code.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAYhD"}
@@ -0,0 +1,16 @@
1
+ const IDENTIFIER = /^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;
2
+ /**
3
+ * What may be stored and logged about a caught error: its `code` when it carries one, else
4
+ * its class name. Never its message, which may quote payload data.
5
+ */
6
+ export function errorCode(error) {
7
+ if (typeof error !== 'object' || error === null) {
8
+ return 'UNKNOWN_ERROR';
9
+ }
10
+ if ('code' in error && typeof error.code === 'string' && IDENTIFIER.test(error.code)) {
11
+ return error.code;
12
+ }
13
+ const name = error instanceof Error ? error.constructor.name : '';
14
+ return IDENTIFIER.test(name) ? name : 'UNKNOWN_ERROR';
15
+ }
16
+ //# sourceMappingURL=error-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-code.js","sourceRoot":"","sources":["../../src/relay/error-code.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,iCAAiC,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrF,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAElE,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC;AACxD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { IntegrationEvent } from '@ddd-ts-kit/kernel';
2
+ export type EventKey = (event: IntegrationEvent) => string | undefined;
3
+ //# sourceMappingURL=event-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-key.d.ts","sourceRoot":"","sources":["../../src/relay/event-key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,MAAM,GAAG,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-key.js","sourceRoot":"","sources":["../../src/relay/event-key.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ /** A retry instant, or the end of a lease the relay cannot know. */
2
+ export type HoldUntil = Date | 'lease-expiry';
3
+ //# sourceMappingURL=hold-until.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hold-until.d.ts","sourceRoot":"","sources":["../../src/relay/hold-until.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hold-until.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hold-until.js","sourceRoot":"","sources":["../../src/relay/hold-until.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { RelaySignal } from './relay-signal.js';
2
+ export declare class InMemoryRelaySignal implements RelaySignal {
3
+ private readonly listeners;
4
+ subscribe(listener: () => void): {
5
+ unsubscribe(): void;
6
+ };
7
+ notify(): void;
8
+ }
9
+ //# sourceMappingURL=in-memory-relay-signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-relay-signal.d.ts","sourceRoot":"","sources":["../../src/relay/in-memory-relay-signal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG;QAAE,WAAW,IAAI,IAAI,CAAA;KAAE,CAIvD;IAED,MAAM,IAAI,IAAI,CAIb;CACF"}
@@ -0,0 +1,13 @@
1
+ export class InMemoryRelaySignal {
2
+ listeners = new Set();
3
+ subscribe(listener) {
4
+ this.listeners.add(listener);
5
+ return { unsubscribe: () => void this.listeners.delete(listener) };
6
+ }
7
+ notify() {
8
+ for (const listener of [...this.listeners]) {
9
+ listener();
10
+ }
11
+ }
12
+ }
13
+ //# sourceMappingURL=in-memory-relay-signal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-relay-signal.js","sourceRoot":"","sources":["../../src/relay/in-memory-relay-signal.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,mBAAmB;IACb,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAEnD,SAAS,CAAC,QAAoB;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE7B,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IACrE,CAAC;IAED,MAAM;QACJ,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ import type { ClaimWindow } from './claim-window.js';
2
+ import type { EventKey } from './event-key.js';
3
+ import type { HoldUntil } from './hold-until.js';
4
+ import type { KeyedRecord } from './keyed-record.js';
5
+ import type { RecordGroup } from './record-group.js';
6
+ /**
7
+ * What a relay remembers to keep the records of one key in order: which record is at the
8
+ * head of each key, in which order it first saw the others, and how many of their claims
9
+ * were spent waiting. Kept in memory: it holds for one relay as long as it lives.
10
+ */
11
+ export declare class KeyOrder<R extends KeyedRecord> {
12
+ private readonly keyOf;
13
+ private readonly heads;
14
+ private readonly tracked;
15
+ private arrivals;
16
+ constructor(keyOf: EventKey);
17
+ /** One group per key, earliest seen first inside it; a record without key stands alone. */
18
+ groups(records: readonly R[]): RecordGroup<R>[];
19
+ /** Until when the group waits because an earlier record of its key is still to publish. */
20
+ holdOf(group: RecordGroup<R>, window: ClaimWindow): HoldUntil | undefined;
21
+ block(key: string | undefined, eventId: string, until: Date): void;
22
+ /** The record was published or declared dead: it no longer stands in the way. */
23
+ settle(key: string | undefined, eventId: string): void;
24
+ countHold(eventId: string): void;
25
+ /** Delivery attempts really made: claims spent waiting for the head are not counted. */
26
+ attemptsOf(record: R): number;
27
+ /**
28
+ * After an aborted tick, the records it claimed and did not settle are leased by the store
29
+ * for a time the relay does not know: each key waits for its first such record to come back.
30
+ */
31
+ suspend(groups: readonly RecordGroup<R>[], settled: ReadonlySet<string>): void;
32
+ private sortByArrival;
33
+ private arrivalOf;
34
+ }
35
+ //# sourceMappingURL=key-order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-order.d.ts","sourceRoot":"","sources":["../../src/relay/key-order.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAYrD;;;;GAIG;AACH,qBAAa,QAAQ,CAAC,CAAC,SAAS,WAAW;IAO7B,OAAO,CAAC,QAAQ,CAAC,KAAK;IANlC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IAEjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IAEtD,OAAO,CAAC,QAAQ,CAAK;IAErB,YAA6B,KAAK,EAAE,QAAQ,EAAI;IAEhD,2FAA2F;IAC3F,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CA2B9C;IAED,2FAA2F;IAC3F,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAmBxE;IAED,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,CAIjE;IAED,iFAAiF;IACjF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAMrD;IAED,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM/B;IAED,wFAAwF;IACxF,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAE5B;IAED;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAa7E;IAED,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,SAAS;CAGlB"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * What a relay remembers to keep the records of one key in order: which record is at the
3
+ * head of each key, in which order it first saw the others, and how many of their claims
4
+ * were spent waiting. Kept in memory: it holds for one relay as long as it lives.
5
+ */
6
+ export class KeyOrder {
7
+ keyOf;
8
+ heads = new Map();
9
+ tracked = new Map();
10
+ arrivals = 0;
11
+ constructor(keyOf) {
12
+ this.keyOf = keyOf;
13
+ }
14
+ /** One group per key, earliest seen first inside it; a record without key stands alone. */
15
+ groups(records) {
16
+ const byKey = new Map();
17
+ const groups = [];
18
+ for (const record of records) {
19
+ const key = this.keyOf(record.event);
20
+ const siblings = key === undefined ? undefined : byKey.get(key);
21
+ if (siblings !== undefined) {
22
+ siblings.push(record);
23
+ continue;
24
+ }
25
+ const members = [record];
26
+ groups.push({ key, records: members });
27
+ if (key !== undefined) {
28
+ byKey.set(key, members);
29
+ }
30
+ }
31
+ for (const members of byKey.values()) {
32
+ this.sortByArrival(members);
33
+ }
34
+ return groups;
35
+ }
36
+ /** Until when the group waits because an earlier record of its key is still to publish. */
37
+ holdOf(group, window) {
38
+ const head = group.key === undefined ? undefined : this.heads.get(group.key);
39
+ if (group.key === undefined || head === undefined) {
40
+ return undefined;
41
+ }
42
+ if (group.records.some((record) => record.event.id === head.eventId)) {
43
+ return undefined;
44
+ }
45
+ // Due, yet absent from a claim that took everything due: it left the queue another way.
46
+ if (head.until !== 'lease-expiry' && window.complete && head.until <= window.now) {
47
+ this.heads.delete(group.key);
48
+ return undefined;
49
+ }
50
+ return head.until;
51
+ }
52
+ block(key, eventId, until) {
53
+ if (key !== undefined) {
54
+ this.heads.set(key, { eventId, until });
55
+ }
56
+ }
57
+ /** The record was published or declared dead: it no longer stands in the way. */
58
+ settle(key, eventId) {
59
+ this.tracked.delete(eventId);
60
+ if (key !== undefined && this.heads.get(key)?.eventId === eventId) {
61
+ this.heads.delete(key);
62
+ }
63
+ }
64
+ countHold(eventId) {
65
+ const tracked = this.tracked.get(eventId);
66
+ if (tracked !== undefined) {
67
+ tracked.holds += 1;
68
+ }
69
+ }
70
+ /** Delivery attempts really made: claims spent waiting for the head are not counted. */
71
+ attemptsOf(record) {
72
+ return record.attempts - (this.tracked.get(record.event.id)?.holds ?? 0);
73
+ }
74
+ /**
75
+ * After an aborted tick, the records it claimed and did not settle are leased by the store
76
+ * for a time the relay does not know: each key waits for its first such record to come back.
77
+ */
78
+ suspend(groups, settled) {
79
+ for (const { key, records } of groups) {
80
+ const unsettled = records.filter((record) => !settled.has(record.event.id));
81
+ const head = key === undefined ? undefined : this.heads.get(key);
82
+ const blocker = unsettled.find((record) => record.event.id === head?.eventId) ??
83
+ (head === undefined ? unsettled[0] : undefined);
84
+ if (key !== undefined && blocker !== undefined) {
85
+ this.heads.set(key, { eventId: blocker.event.id, until: 'lease-expiry' });
86
+ }
87
+ }
88
+ }
89
+ sortByArrival(members) {
90
+ for (const { event } of members) {
91
+ if (!this.tracked.has(event.id)) {
92
+ this.arrivals += 1;
93
+ this.tracked.set(event.id, { arrival: this.arrivals, holds: 0 });
94
+ }
95
+ }
96
+ members.sort((a, b) => this.arrivalOf(a) - this.arrivalOf(b));
97
+ }
98
+ arrivalOf(record) {
99
+ return this.tracked.get(record.event.id)?.arrival ?? 0;
100
+ }
101
+ }
102
+ //# sourceMappingURL=key-order.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-order.js","sourceRoot":"","sources":["../../src/relay/key-order.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { IntegrationEvent } from '@ddd-ts-kit/kernel';
2
+ export interface KeyedRecord {
3
+ readonly event: IntegrationEvent;
4
+ readonly attempts: number;
5
+ }
6
+ //# sourceMappingURL=keyed-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyed-record.d.ts","sourceRoot":"","sources":["../../src/relay/keyed-record.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=keyed-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyed-record.js","sourceRoot":"","sources":["../../src/relay/keyed-record.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ export interface OutboxBackoff {
2
+ /** Delay before the second attempt. Default 1000. */
3
+ readonly baseMs?: number;
4
+ /** Multiplier applied at each further attempt. Default 2. */
5
+ readonly factor?: number;
6
+ /** Upper bound of the delay. Default 300000 (five minutes). */
7
+ readonly maxMs?: number;
8
+ }
9
+ //# sourceMappingURL=outbox-backoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-backoff.d.ts","sourceRoot":"","sources":["../../src/relay/outbox-backoff.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=outbox-backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-backoff.js","sourceRoot":"","sources":["../../src/relay/outbox-backoff.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `none`: records go out in store order and a failed one is overtaken by its successors.
3
+ * `per-key`: a record is never published while an earlier record with the same key is still
4
+ * pending or failed, at the price of head-of-line blocking on that key.
5
+ */
6
+ export type OutboxOrdering = 'none' | 'per-key';
7
+ //# sourceMappingURL=outbox-ordering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-ordering.d.ts","sourceRoot":"","sources":["../../src/relay/outbox-ordering.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=outbox-ordering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-ordering.js","sourceRoot":"","sources":["../../src/relay/outbox-ordering.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ export type OutboxRelayFailure = {
2
+ readonly kind: 'publish';
3
+ readonly eventId: string;
4
+ readonly eventType: string;
5
+ readonly code: string;
6
+ readonly attempts: number;
7
+ readonly dead: boolean;
8
+ } | {
9
+ readonly kind: 'tick';
10
+ readonly code: string;
11
+ };
12
+ //# sourceMappingURL=outbox-relay-failure.d.ts.map