@cratis/chronicle 3.0.0 → 3.1.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 (338) hide show
  1. package/ChronicleClient.ts +4 -3
  2. package/EventStore.ts +20 -3
  3. package/IEventStore.ts +16 -0
  4. package/README.md +40 -28
  5. package/auditing/CausationType.ts +10 -0
  6. package/compliance/ComplianceContracts.ts +84 -0
  7. package/compliance/IPIIManager.ts +17 -0
  8. package/compliance/PIIManager.ts +31 -0
  9. package/compliance/index.ts +2 -0
  10. package/connection/ChronicleConnection.ts +7 -1
  11. package/connection/ChronicleServices.ts +2 -0
  12. package/connection/Guid.ts +18 -0
  13. package/connection/callResults.spec.ts +90 -0
  14. package/connection/callResults.ts +112 -0
  15. package/dist/ChronicleClient.d.ts.map +1 -1
  16. package/dist/ChronicleClient.js +4 -3
  17. package/dist/ChronicleClient.js.map +1 -1
  18. package/dist/EventStore.d.ts +8 -0
  19. package/dist/EventStore.d.ts.map +1 -1
  20. package/dist/EventStore.js +16 -3
  21. package/dist/EventStore.js.map +1 -1
  22. package/dist/IEventStore.d.ts +12 -0
  23. package/dist/IEventStore.d.ts.map +1 -1
  24. package/dist/auditing/CausationType.d.ts +8 -0
  25. package/dist/auditing/CausationType.d.ts.map +1 -1
  26. package/dist/auditing/CausationType.js +8 -0
  27. package/dist/auditing/CausationType.js.map +1 -1
  28. package/dist/compliance/ComplianceContracts.d.ts +40 -0
  29. package/dist/compliance/ComplianceContracts.d.ts.map +1 -1
  30. package/dist/compliance/ComplianceContracts.js +71 -0
  31. package/dist/compliance/ComplianceContracts.js.map +1 -1
  32. package/dist/compliance/IPIIManager.d.ts +15 -0
  33. package/dist/compliance/IPIIManager.d.ts.map +1 -0
  34. package/dist/compliance/IPIIManager.js +4 -0
  35. package/dist/compliance/IPIIManager.js.map +1 -0
  36. package/dist/compliance/PIIManager.d.ts +20 -0
  37. package/dist/compliance/PIIManager.d.ts.map +1 -0
  38. package/dist/compliance/PIIManager.js +30 -0
  39. package/dist/compliance/PIIManager.js.map +1 -0
  40. package/dist/compliance/index.d.ts +2 -0
  41. package/dist/compliance/index.d.ts.map +1 -1
  42. package/dist/compliance/index.js +1 -0
  43. package/dist/compliance/index.js.map +1 -1
  44. package/dist/connection/ChronicleConnection.d.ts +1 -0
  45. package/dist/connection/ChronicleConnection.d.ts.map +1 -1
  46. package/dist/connection/ChronicleConnection.js +6 -1
  47. package/dist/connection/ChronicleConnection.js.map +1 -1
  48. package/dist/connection/ChronicleServices.d.ts +2 -0
  49. package/dist/connection/ChronicleServices.d.ts.map +1 -1
  50. package/dist/connection/Guid.d.ts +5 -0
  51. package/dist/connection/Guid.d.ts.map +1 -1
  52. package/dist/connection/Guid.js +15 -0
  53. package/dist/connection/Guid.js.map +1 -1
  54. package/dist/connection/callResults.d.ts +69 -0
  55. package/dist/connection/callResults.d.ts.map +1 -0
  56. package/dist/connection/callResults.js +74 -0
  57. package/dist/connection/callResults.js.map +1 -0
  58. package/dist/eventSequences/AppendOperationsBroadcaster.d.ts +16 -0
  59. package/dist/eventSequences/AppendOperationsBroadcaster.d.ts.map +1 -0
  60. package/dist/eventSequences/AppendOperationsBroadcaster.js +77 -0
  61. package/dist/eventSequences/AppendOperationsBroadcaster.js.map +1 -0
  62. package/dist/eventSequences/AppendOptions.d.ts +7 -0
  63. package/dist/eventSequences/AppendOptions.d.ts.map +1 -1
  64. package/dist/eventSequences/AppendResult.d.ts +14 -0
  65. package/dist/eventSequences/AppendResult.d.ts.map +1 -1
  66. package/dist/eventSequences/AppendedEventWithResult.d.ts +13 -0
  67. package/dist/eventSequences/AppendedEventWithResult.d.ts.map +1 -0
  68. package/dist/eventSequences/AppendedEventWithResult.js +4 -0
  69. package/dist/eventSequences/AppendedEventWithResult.js.map +1 -0
  70. package/dist/eventSequences/CompleteStreamError.d.ts +17 -0
  71. package/dist/eventSequences/CompleteStreamError.d.ts.map +1 -0
  72. package/dist/eventSequences/CompleteStreamError.js +20 -0
  73. package/dist/eventSequences/CompleteStreamError.js.map +1 -0
  74. package/dist/eventSequences/CompleteStreamResult.d.ts +14 -0
  75. package/dist/eventSequences/CompleteStreamResult.d.ts.map +1 -0
  76. package/dist/eventSequences/CompleteStreamResult.js +4 -0
  77. package/dist/eventSequences/CompleteStreamResult.js.map +1 -0
  78. package/dist/eventSequences/ConcurrencyViolation.d.ts +13 -0
  79. package/dist/eventSequences/ConcurrencyViolation.d.ts.map +1 -0
  80. package/dist/eventSequences/ConcurrencyViolation.js +4 -0
  81. package/dist/eventSequences/ConcurrencyViolation.js.map +1 -0
  82. package/dist/eventSequences/EventForEventSourceId.d.ts +8 -0
  83. package/dist/eventSequences/EventForEventSourceId.d.ts.map +1 -1
  84. package/dist/eventSequences/EventSequence.d.ts +35 -1
  85. package/dist/eventSequences/EventSequence.d.ts.map +1 -1
  86. package/dist/eventSequences/EventSequence.js +350 -19
  87. package/dist/eventSequences/EventSequence.js.map +1 -1
  88. package/dist/eventSequences/IEventSequence.d.ts +85 -1
  89. package/dist/eventSequences/IEventSequence.d.ts.map +1 -1
  90. package/dist/eventSequences/WaitForCompletionResult.d.ts +11 -0
  91. package/dist/eventSequences/WaitForCompletionResult.d.ts.map +1 -0
  92. package/dist/eventSequences/WaitForCompletionResult.js +4 -0
  93. package/dist/eventSequences/WaitForCompletionResult.js.map +1 -0
  94. package/dist/eventSequences/index.d.ts +5 -0
  95. package/dist/eventSequences/index.d.ts.map +1 -1
  96. package/dist/eventSequences/index.js +1 -0
  97. package/dist/eventSequences/index.js.map +1 -1
  98. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.d.ts +3 -0
  99. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.d.ts.map +1 -1
  100. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.js +9 -0
  101. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.js.map +1 -1
  102. package/dist/eventStoreSubscriptions/IEventStoreSubscriptions.d.ts +6 -0
  103. package/dist/eventStoreSubscriptions/IEventStoreSubscriptions.d.ts.map +1 -1
  104. package/dist/eventStoreSubscriptions/contracts.d.ts +18 -0
  105. package/dist/eventStoreSubscriptions/contracts.d.ts.map +1 -1
  106. package/dist/eventStoreSubscriptions/contracts.js +106 -0
  107. package/dist/eventStoreSubscriptions/contracts.js.map +1 -1
  108. package/dist/events/constraints/Constraints.js +4 -4
  109. package/dist/events/constraints/Constraints.js.map +1 -1
  110. package/dist/externalServices/ExternalServiceBuilder.d.ts +42 -0
  111. package/dist/externalServices/ExternalServiceBuilder.d.ts.map +1 -0
  112. package/dist/externalServices/ExternalServiceBuilder.js +110 -0
  113. package/dist/externalServices/ExternalServiceBuilder.js.map +1 -0
  114. package/dist/externalServices/ExternalServices.d.ts +19 -0
  115. package/dist/externalServices/ExternalServices.d.ts.map +1 -0
  116. package/dist/externalServices/ExternalServices.js +30 -0
  117. package/dist/externalServices/ExternalServices.js.map +1 -0
  118. package/dist/externalServices/ExternalServicesContracts.d.ts +137 -0
  119. package/dist/externalServices/ExternalServicesContracts.d.ts.map +1 -0
  120. package/dist/externalServices/ExternalServicesContracts.js +654 -0
  121. package/dist/externalServices/ExternalServicesContracts.js.map +1 -0
  122. package/dist/externalServices/IExternalServiceBuilder.d.ts +67 -0
  123. package/dist/externalServices/IExternalServiceBuilder.d.ts.map +1 -0
  124. package/dist/externalServices/IExternalServiceBuilder.js +4 -0
  125. package/dist/externalServices/IExternalServiceBuilder.js.map +1 -0
  126. package/dist/externalServices/IExternalServices.d.ts +13 -0
  127. package/dist/externalServices/IExternalServices.d.ts.map +1 -0
  128. package/dist/externalServices/IExternalServices.js +4 -0
  129. package/dist/externalServices/IExternalServices.js.map +1 -0
  130. package/dist/externalServices/index.d.ts +5 -0
  131. package/dist/externalServices/index.d.ts.map +1 -0
  132. package/dist/externalServices/index.js +5 -0
  133. package/dist/externalServices/index.js.map +1 -0
  134. package/dist/identities/IIdentityManager.d.ts +17 -0
  135. package/dist/identities/IIdentityManager.d.ts.map +1 -0
  136. package/dist/identities/IIdentityManager.js +4 -0
  137. package/dist/identities/IIdentityManager.js.map +1 -0
  138. package/dist/identities/IdentityManager.d.ts +20 -0
  139. package/dist/identities/IdentityManager.d.ts.map +1 -0
  140. package/dist/identities/IdentityManager.js +31 -0
  141. package/dist/identities/IdentityManager.js.map +1 -0
  142. package/dist/identities/index.d.ts +3 -0
  143. package/dist/identities/index.d.ts.map +1 -0
  144. package/dist/identities/index.js +4 -0
  145. package/dist/identities/index.js.map +1 -0
  146. package/dist/index.d.ts +5 -1
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +5 -1
  149. package/dist/index.js.map +1 -1
  150. package/dist/jobs/IJobs.d.ts +4 -4
  151. package/dist/jobs/IJobs.d.ts.map +1 -1
  152. package/dist/jobs/Jobs.d.ts +4 -4
  153. package/dist/jobs/Jobs.d.ts.map +1 -1
  154. package/dist/jobs/Jobs.js +12 -10
  155. package/dist/jobs/Jobs.js.map +1 -1
  156. package/dist/observation/FailedPartition.d.ts +15 -0
  157. package/dist/observation/FailedPartition.d.ts.map +1 -0
  158. package/dist/observation/FailedPartition.js +4 -0
  159. package/dist/observation/FailedPartition.js.map +1 -0
  160. package/dist/observation/FailedPartitionAttempt.d.ts +15 -0
  161. package/dist/observation/FailedPartitionAttempt.d.ts.map +1 -0
  162. package/dist/observation/FailedPartitionAttempt.js +4 -0
  163. package/dist/observation/FailedPartitionAttempt.js.map +1 -0
  164. package/dist/observation/FailedPartitions.d.ts +24 -0
  165. package/dist/observation/FailedPartitions.d.ts.map +1 -0
  166. package/dist/observation/FailedPartitions.js +39 -0
  167. package/dist/observation/FailedPartitions.js.map +1 -0
  168. package/dist/observation/ICanBeNotifiedWhenPartitionReplayed.d.ts +19 -0
  169. package/dist/observation/ICanBeNotifiedWhenPartitionReplayed.d.ts.map +1 -0
  170. package/dist/observation/ICanBeNotifiedWhenPartitionReplayed.js +4 -0
  171. package/dist/observation/ICanBeNotifiedWhenPartitionReplayed.js.map +1 -0
  172. package/dist/observation/ICanBeNotifiedWhenReplay.d.ts +17 -0
  173. package/dist/observation/ICanBeNotifiedWhenReplay.d.ts.map +1 -0
  174. package/dist/observation/ICanBeNotifiedWhenReplay.js +4 -0
  175. package/dist/observation/ICanBeNotifiedWhenReplay.js.map +1 -0
  176. package/dist/observation/IFailedPartitions.d.ts +18 -0
  177. package/dist/observation/IFailedPartitions.d.ts.map +1 -0
  178. package/dist/observation/IFailedPartitions.js +4 -0
  179. package/dist/observation/IFailedPartitions.js.map +1 -0
  180. package/dist/observation/index.d.ts +6 -0
  181. package/dist/observation/index.d.ts.map +1 -1
  182. package/dist/observation/index.js +1 -0
  183. package/dist/observation/index.js.map +1 -1
  184. package/dist/observation/notifyReplayLifecycle.d.ts +13 -0
  185. package/dist/observation/notifyReplayLifecycle.d.ts.map +1 -0
  186. package/dist/observation/notifyReplayLifecycle.js +54 -0
  187. package/dist/observation/notifyReplayLifecycle.js.map +1 -0
  188. package/dist/observation/toClientFailedPartition.d.ts +9 -0
  189. package/dist/observation/toClientFailedPartition.d.ts.map +1 -0
  190. package/dist/observation/toClientFailedPartition.js +23 -0
  191. package/dist/observation/toClientFailedPartition.js.map +1 -0
  192. package/dist/projections/Projections.d.ts +0 -4
  193. package/dist/projections/Projections.d.ts.map +1 -1
  194. package/dist/projections/Projections.js +25 -103
  195. package/dist/projections/Projections.js.map +1 -1
  196. package/dist/projections/declarative/AddBuilder.d.ts +17 -0
  197. package/dist/projections/declarative/AddBuilder.d.ts.map +1 -0
  198. package/dist/projections/declarative/AddBuilder.js +28 -0
  199. package/dist/projections/declarative/AddBuilder.js.map +1 -0
  200. package/dist/projections/declarative/AddChildBuilder.d.ts +56 -0
  201. package/dist/projections/declarative/AddChildBuilder.d.ts.map +1 -0
  202. package/dist/projections/declarative/AddChildBuilder.js +72 -0
  203. package/dist/projections/declarative/AddChildBuilder.js.map +1 -0
  204. package/dist/projections/declarative/ChildrenBuilder.d.ts +28 -0
  205. package/dist/projections/declarative/ChildrenBuilder.d.ts.map +1 -0
  206. package/dist/projections/declarative/ChildrenBuilder.js +72 -0
  207. package/dist/projections/declarative/ChildrenBuilder.js.map +1 -0
  208. package/dist/projections/declarative/CompositeKeyBuilder.d.ts +16 -0
  209. package/dist/projections/declarative/CompositeKeyBuilder.d.ts.map +1 -0
  210. package/dist/projections/declarative/CompositeKeyBuilder.js +29 -0
  211. package/dist/projections/declarative/CompositeKeyBuilder.js.map +1 -0
  212. package/dist/projections/declarative/FromBuilder.d.ts +8 -6
  213. package/dist/projections/declarative/FromBuilder.d.ts.map +1 -1
  214. package/dist/projections/declarative/FromBuilder.js +44 -14
  215. package/dist/projections/declarative/FromBuilder.js.map +1 -1
  216. package/dist/projections/declarative/ICompositeKeyBuilder.d.ts +5 -0
  217. package/dist/projections/declarative/ICompositeKeyBuilder.d.ts.map +1 -1
  218. package/dist/projections/declarative/JoinBuilder.d.ts +7 -5
  219. package/dist/projections/declarative/JoinBuilder.d.ts.map +1 -1
  220. package/dist/projections/declarative/JoinBuilder.js +50 -16
  221. package/dist/projections/declarative/JoinBuilder.js.map +1 -1
  222. package/dist/projections/declarative/NestedBuilder.d.ts +24 -0
  223. package/dist/projections/declarative/NestedBuilder.d.ts.map +1 -0
  224. package/dist/projections/declarative/NestedBuilder.js +60 -0
  225. package/dist/projections/declarative/NestedBuilder.js.map +1 -0
  226. package/dist/projections/declarative/ProjectionBuilderCore.d.ts +127 -0
  227. package/dist/projections/declarative/ProjectionBuilderCore.d.ts.map +1 -0
  228. package/dist/projections/declarative/ProjectionBuilderCore.js +180 -0
  229. package/dist/projections/declarative/ProjectionBuilderCore.js.map +1 -0
  230. package/dist/projections/declarative/ProjectionBuilderFor.d.ts +6 -32
  231. package/dist/projections/declarative/ProjectionBuilderFor.d.ts.map +1 -1
  232. package/dist/projections/declarative/ProjectionBuilderFor.js +24 -118
  233. package/dist/projections/declarative/ProjectionBuilderFor.js.map +1 -1
  234. package/dist/projections/declarative/SubtractBuilder.d.ts +17 -0
  235. package/dist/projections/declarative/SubtractBuilder.d.ts.map +1 -0
  236. package/dist/projections/declarative/SubtractBuilder.js +28 -0
  237. package/dist/projections/declarative/SubtractBuilder.js.map +1 -0
  238. package/dist/projections/declarative/index.d.ts +9 -0
  239. package/dist/projections/declarative/index.d.ts.map +1 -1
  240. package/dist/projections/declarative/index.js +8 -0
  241. package/dist/projections/declarative/index.js.map +1 -1
  242. package/dist/projections/modelBound/childrenAndNestedBuilder.d.ts +90 -0
  243. package/dist/projections/modelBound/childrenAndNestedBuilder.d.ts.map +1 -0
  244. package/dist/projections/modelBound/childrenAndNestedBuilder.js +290 -0
  245. package/dist/projections/modelBound/childrenAndNestedBuilder.js.map +1 -0
  246. package/dist/reactors/ReactorSideEffects.d.ts +29 -0
  247. package/dist/reactors/ReactorSideEffects.d.ts.map +1 -0
  248. package/dist/reactors/ReactorSideEffects.js +70 -0
  249. package/dist/reactors/ReactorSideEffects.js.map +1 -0
  250. package/dist/reactors/Reactors.d.ts +4 -1
  251. package/dist/reactors/Reactors.d.ts.map +1 -1
  252. package/dist/reactors/Reactors.js +23 -4
  253. package/dist/reactors/Reactors.js.map +1 -1
  254. package/dist/reducers/Reducers.d.ts.map +1 -1
  255. package/dist/reducers/Reducers.js +15 -3
  256. package/dist/reducers/Reducers.js.map +1 -1
  257. package/dist/reducers/reducer.d.ts +9 -1
  258. package/dist/reducers/reducer.d.ts.map +1 -1
  259. package/dist/reducers/reducer.js +4 -2
  260. package/dist/reducers/reducer.js.map +1 -1
  261. package/dist/transactions/IUnitOfWork.d.ts +18 -0
  262. package/dist/transactions/IUnitOfWork.d.ts.map +1 -1
  263. package/dist/transactions/UnitOfWork.d.ts +9 -0
  264. package/dist/transactions/UnitOfWork.d.ts.map +1 -1
  265. package/dist/transactions/UnitOfWork.js +14 -0
  266. package/dist/transactions/UnitOfWork.js.map +1 -1
  267. package/dist/tsconfig.tsbuildinfo +1 -1
  268. package/eventSequences/AppendOperationsBroadcaster.ts +83 -0
  269. package/eventSequences/AppendOptions.ts +8 -0
  270. package/eventSequences/AppendResult.ts +16 -0
  271. package/eventSequences/AppendedEventWithResult.ts +17 -0
  272. package/eventSequences/CompleteStreamError.ts +20 -0
  273. package/eventSequences/CompleteStreamResult.ts +13 -0
  274. package/eventSequences/ConcurrencyViolation.ts +18 -0
  275. package/eventSequences/EventForEventSourceId.ts +12 -0
  276. package/eventSequences/EventSequence.spec.ts +588 -0
  277. package/eventSequences/EventSequence.ts +406 -20
  278. package/eventSequences/IEventSequence.ts +109 -1
  279. package/eventSequences/WaitForCompletionResult.ts +15 -0
  280. package/eventSequences/index.ts +5 -0
  281. package/eventStoreSubscriptions/EventStoreSubscriptions.spec.ts +52 -0
  282. package/eventStoreSubscriptions/EventStoreSubscriptions.ts +19 -1
  283. package/eventStoreSubscriptions/IEventStoreSubscriptions.ts +7 -0
  284. package/eventStoreSubscriptions/contracts.ts +126 -0
  285. package/events/constraints/Constraints.ts +4 -4
  286. package/externalServices/ExternalServiceBuilder.ts +128 -0
  287. package/externalServices/ExternalServices.ts +34 -0
  288. package/externalServices/ExternalServicesContracts.ts +709 -0
  289. package/externalServices/IExternalServiceBuilder.ts +76 -0
  290. package/externalServices/IExternalServices.ts +16 -0
  291. package/externalServices/index.ts +7 -0
  292. package/identities/IIdentityManager.ts +19 -0
  293. package/identities/IdentityManager.ts +32 -0
  294. package/identities/index.ts +5 -0
  295. package/index.ts +6 -0
  296. package/jobs/IJobs.ts +4 -4
  297. package/jobs/Jobs.ts +16 -14
  298. package/observation/FailedPartition.ts +21 -0
  299. package/observation/FailedPartitionAttempt.ts +21 -0
  300. package/observation/FailedPartitions.spec.ts +75 -0
  301. package/observation/FailedPartitions.ts +44 -0
  302. package/observation/ICanBeNotifiedWhenPartitionReplayed.ts +22 -0
  303. package/observation/ICanBeNotifiedWhenReplay.ts +20 -0
  304. package/observation/IFailedPartitions.ts +22 -0
  305. package/observation/index.ts +6 -0
  306. package/observation/notifyReplayLifecycle.spec.ts +98 -0
  307. package/observation/notifyReplayLifecycle.ts +61 -0
  308. package/observation/toClientFailedPartition.ts +26 -0
  309. package/package.json +28 -3
  310. package/projections/Projections.childrenAndNested.spec.ts +188 -0
  311. package/projections/Projections.spec.ts +131 -0
  312. package/projections/Projections.ts +37 -119
  313. package/projections/declarative/AddBuilder.ts +28 -0
  314. package/projections/declarative/AddChildBuilder.ts +97 -0
  315. package/projections/declarative/ChildrenBuilder.spec.ts +157 -0
  316. package/projections/declarative/ChildrenBuilder.ts +90 -0
  317. package/projections/declarative/CompositeKeyBuilder.spec.ts +117 -0
  318. package/projections/declarative/CompositeKeyBuilder.ts +38 -0
  319. package/projections/declarative/FromBuilder.ts +60 -15
  320. package/projections/declarative/ICompositeKeyBuilder.ts +6 -0
  321. package/projections/declarative/JoinBuilder.ts +66 -17
  322. package/projections/declarative/NestedBuilder.ts +76 -0
  323. package/projections/declarative/ProjectionBuilderCore.ts +257 -0
  324. package/projections/declarative/ProjectionBuilderFor.spec.ts +115 -0
  325. package/projections/declarative/ProjectionBuilderFor.ts +29 -168
  326. package/projections/declarative/SubtractBuilder.ts +28 -0
  327. package/projections/declarative/index.ts +9 -0
  328. package/projections/modelBound/childrenAndNestedBuilder.ts +354 -0
  329. package/reactors/ReactorSideEffects.spec.ts +182 -0
  330. package/reactors/ReactorSideEffects.ts +97 -0
  331. package/reactors/Reactors.ts +29 -4
  332. package/reducers/Reducers.spec.ts +87 -0
  333. package/reducers/Reducers.ts +15 -3
  334. package/reducers/reducer.spec.ts +40 -0
  335. package/reducers/reducer.ts +11 -2
  336. package/transactions/IUnitOfWork.ts +21 -0
  337. package/transactions/UnitOfWork.spec.ts +82 -0
  338. package/transactions/UnitOfWork.ts +20 -0
@@ -13,7 +13,10 @@ import { EventContext } from '../events/EventContext';
13
13
  import { EventTypeId } from '../events/EventTypeId';
14
14
  import { EventTypeGeneration } from '../events/EventTypeGeneration';
15
15
  import { EventSequenceId } from '../eventSequences/EventSequenceId';
16
+ import type { IEventLog } from '../eventSequences/IEventLog';
17
+ import { notifyReplayLifecycle } from '../observation/notifyReplayLifecycle';
16
18
  import { IReactors } from './IReactors';
19
+ import { appendReactorSideEffects } from './ReactorSideEffects';
17
20
  import { getReactorMetadata } from './reactor';
18
21
 
19
22
  /** Expression used to partition reactor observations by event source ID. */
@@ -107,13 +110,15 @@ export class Reactors implements IReactors {
107
110
  * @param _eventStoreName - The name of the event store.
108
111
  * @param _namespace - The namespace within the event store.
109
112
  * @param lifecycle - The connection lifecycle used to react to disconnect events.
113
+ * @param _eventLog - The event log used to append side-effect events a reactor handler returns.
110
114
  */
111
115
  constructor(
112
116
  private readonly _clientArtifacts: IClientArtifactsProvider,
113
117
  private readonly _connection: ChronicleConnection,
114
118
  private readonly _eventStoreName: string,
115
119
  private readonly _namespace: string,
116
- lifecycle: ConnectionLifecycle
120
+ lifecycle: ConnectionLifecycle,
121
+ private readonly _eventLog: IEventLog
117
122
  ) {
118
123
  this._lifecycle = lifecycle;
119
124
  lifecycle.onDisconnected(async () => {
@@ -258,10 +263,20 @@ export class Reactors implements IReactors {
258
263
  this._logger.debug('Received events to observe', {
259
264
  reactorId: id,
260
265
  partition: eventsToObserve.Partition,
261
- count: eventsToObserve.Events.length
266
+ count: eventsToObserve.Events.length,
267
+ replayState: eventsToObserve.ReplayState
262
268
  });
263
269
 
264
- for (const event of eventsToObserve.Events) {
270
+ try {
271
+ await notifyReplayLifecycle(reactorInstance, eventsToObserve.ReplayState, eventsToObserve.Partition);
272
+ } catch (err) {
273
+ this._logger.error('Error notifying reactor of replay lifecycle transition', { reactorId: id, error: String(err) });
274
+ exceptionMessages.push(String(err));
275
+ exceptionStackTrace = err instanceof Error ? (err.stack ?? '') : '';
276
+ state = ObservationState.Failed;
277
+ }
278
+
279
+ for (const event of state === ObservationState.Failed ? [] : eventsToObserve.Events) {
265
280
  try {
266
281
  const eventTypeId = event.Context?.EventType?.Id;
267
282
  if (!eventTypeId) {
@@ -298,7 +313,17 @@ export class Reactors implements IReactors {
298
313
  eventTypeId
299
314
  });
300
315
 
301
- await reactorInstance[entry.methodName](content, context);
316
+ const handlerResult = await reactorInstance[entry.methodName](content, context);
317
+ const sideEffectResult = await appendReactorSideEffects(
318
+ this._eventLog,
319
+ handlerResult,
320
+ event.Context!.EventSourceId,
321
+ event.Context!.EventStreamType,
322
+ event.Context!.EventStreamId);
323
+ if (!sideEffectResult.isSuccess) {
324
+ throw new Error(`Reactor side effect failed to append: ${sideEffectResult.errors.join('; ')}`);
325
+ }
326
+
302
327
  lastSuccessfullyObservedEvent = event.Context!.SequenceNumber;
303
328
  } catch (err) {
304
329
  this._logger.error('Error handling event in reactor', { reactorId: id, error: String(err) });
@@ -0,0 +1,87 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ import type { Constructor } from '@cratis/fundamentals';
6
+ import type { IClientArtifactsProvider } from '../artifacts';
7
+ import type { ChronicleConnection } from '../connection';
8
+ import { ConnectionLifecycle } from '../connection/ConnectionLifecycle';
9
+ import { reducer } from './reducer';
10
+ import { Reducers } from './Reducers';
11
+
12
+ const flush = () => new Promise(resolve => setTimeout(resolve, 0));
13
+
14
+ /**
15
+ * A minimal client artifacts provider exposing only the reducer types under test —
16
+ * Reducers.ts only reads .reducers and .eventTypes off this during discovery.
17
+ */
18
+ function createArtifacts(reducers: Constructor[]): IClientArtifactsProvider {
19
+ return {
20
+ eventTypes: [],
21
+ readModels: [],
22
+ reactors: [],
23
+ reducers,
24
+ seeders: [],
25
+ constraints: [],
26
+ projections: [],
27
+ webhooks: [],
28
+ eventTypeMigrations: []
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Captures the first message a reducer observation pushes onto its queue (the registration
34
+ * message), by having the mocked `observe` call itself consume the queue's async iterator.
35
+ */
36
+ function createConnection() {
37
+ const registrationMessages: unknown[] = [];
38
+ const observe = vi.fn().mockImplementation(async function* (queue: AsyncIterable<unknown>) {
39
+ for await (const message of queue) {
40
+ registrationMessages.push(message);
41
+ break;
42
+ }
43
+ });
44
+ const registerMany = vi.fn().mockResolvedValue({});
45
+ const connection = {
46
+ reducers: { observe },
47
+ readModels: { registerMany }
48
+ } as unknown as ChronicleConnection;
49
+
50
+ return { connection, registrationMessages };
51
+ }
52
+
53
+ describe('Reducers', () => {
54
+ describe('when registering an active reducer (the default)', () => {
55
+ class SomeReducer {}
56
+ reducer('some-active-reducer')(SomeReducer);
57
+
58
+ it('should send a registration message with IsActive true', async () => {
59
+ const { connection, registrationMessages } = createConnection();
60
+ const reducers = new Reducers(createArtifacts([SomeReducer]), connection, 'my-event-store', 'my-namespace', new ConnectionLifecycle(), 'default-sink');
61
+
62
+ await reducers.register();
63
+ await flush();
64
+
65
+ expect(registrationMessages).toHaveLength(1);
66
+ const message = registrationMessages[0] as { Content: { Value0: { Reducer: { IsActive: boolean } } } };
67
+ expect(message.Content.Value0.Reducer.IsActive).toBe(true);
68
+ });
69
+ });
70
+
71
+ describe('when registering a passive (isActive: false) reducer', () => {
72
+ class SomePassiveReducer {}
73
+ reducer('some-passive-reducer', undefined, undefined, false)(SomePassiveReducer);
74
+
75
+ it('should send a registration message with IsActive false', async () => {
76
+ const { connection, registrationMessages } = createConnection();
77
+ const reducers = new Reducers(createArtifacts([SomePassiveReducer]), connection, 'my-event-store', 'my-namespace', new ConnectionLifecycle(), 'default-sink');
78
+
79
+ await reducers.register();
80
+ await flush();
81
+
82
+ expect(registrationMessages).toHaveLength(1);
83
+ const message = registrationMessages[0] as { Content: { Value0: { Reducer: { IsActive: boolean } } } };
84
+ expect(message.Content.Value0.Reducer.IsActive).toBe(false);
85
+ });
86
+ });
87
+ });
@@ -11,6 +11,7 @@ import { toContractsGuid } from '../connection/Guid';
11
11
  import { ConnectionLifecycle } from '../connection/ConnectionLifecycle';
12
12
  import { getEventTypeMetadata } from '../events/eventTypeDecorator';
13
13
  import { EventSequenceId } from '../eventSequences/EventSequenceId';
14
+ import { notifyReplayLifecycle } from '../observation/notifyReplayLifecycle';
14
15
  import { IReducers } from './IReducers';
15
16
  import { getReducerMetadata } from './reducer';
16
17
  import { getReadModelMetadata } from '../readModels';
@@ -292,6 +293,7 @@ export class Reducers implements IReducers {
292
293
  ): Promise<void> {
293
294
  const queue = new AsyncQueue<ReducerMessage>();
294
295
  this._queues.set(id, queue);
296
+ const isActive = getReducerMetadata(reducerType)?.isActive ?? true;
295
297
 
296
298
  queue.send({
297
299
  Content: {
@@ -307,7 +309,7 @@ export class Reducers implements IReducers {
307
309
  Key: EVENT_SOURCE_ID_KEY
308
310
  })),
309
311
  ReadModel: readModelName,
310
- IsActive: true,
312
+ IsActive: isActive,
311
313
  Tags: [],
312
314
  Filters: {
313
315
  FilterTags: [],
@@ -334,14 +336,24 @@ export class Reducers implements IReducers {
334
336
  reducerId: id,
335
337
  partition: operation.Partition,
336
338
  count: operation.Events.length,
337
- hasInitialState: operation.InitialState !== ''
339
+ hasInitialState: operation.InitialState !== '',
340
+ replayState: operation.ReplayState
338
341
  });
339
342
 
343
+ try {
344
+ await notifyReplayLifecycle(reducerInstance, operation.ReplayState, operation.Partition);
345
+ } catch (err) {
346
+ this._logger.error('Error notifying reducer of replay lifecycle transition', { reducerId: id, error: String(err) });
347
+ exceptionMessages.push(String(err));
348
+ exceptionStackTrace = err instanceof Error ? (err.stack ?? '') : '';
349
+ state = ObservationState.Failed;
350
+ }
351
+
340
352
  let currentState: unknown = operation.InitialState
341
353
  ? JSON.parse(operation.InitialState) as unknown
342
354
  : undefined;
343
355
 
344
- for (const event of operation.Events) {
356
+ for (const event of state === ObservationState.Failed ? [] : operation.Events) {
345
357
  try {
346
358
  const eventTypeId = event.Context?.EventType?.Id;
347
359
  if (!eventTypeId) {
@@ -0,0 +1,40 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { describe, expect, it } from 'vitest';
5
+ import { getReducerMetadata, reducer } from './reducer';
6
+
7
+ describe('reducer', () => {
8
+ describe('when decorating a class without specifying isActive', () => {
9
+ class SomeReducer {}
10
+ reducer('some-reducer')(SomeReducer);
11
+
12
+ it('should default isActive to true', () => {
13
+ const metadata = getReducerMetadata(SomeReducer);
14
+
15
+ expect(metadata?.isActive).toBe(true);
16
+ });
17
+ });
18
+
19
+ describe('when decorating a class with isActive explicitly true', () => {
20
+ class SomeActiveReducer {}
21
+ reducer('some-active-reducer', undefined, undefined, true)(SomeActiveReducer);
22
+
23
+ it('should set isActive to true', () => {
24
+ const metadata = getReducerMetadata(SomeActiveReducer);
25
+
26
+ expect(metadata?.isActive).toBe(true);
27
+ });
28
+ });
29
+
30
+ describe('when decorating a class with isActive false', () => {
31
+ class SomePassiveReducer {}
32
+ reducer('some-passive-reducer', undefined, undefined, false)(SomePassiveReducer);
33
+
34
+ it('should set isActive to false', () => {
35
+ const metadata = getReducerMetadata(SomePassiveReducer);
36
+
37
+ expect(metadata?.isActive).toBe(false);
38
+ });
39
+ });
40
+ });
@@ -21,6 +21,13 @@ export interface ReducerMetadata {
21
21
 
22
22
  /** The optional read model type produced by the reducer. */
23
23
  readonly readModel: Constructor | undefined;
24
+
25
+ /**
26
+ * Whether the reducer is active. An inactive (passive) reducer is registered with the
27
+ * Chronicle Kernel but does not automatically observe events — it can still be invoked
28
+ * on demand. Defaults to true.
29
+ */
30
+ readonly isActive: boolean;
24
31
  }
25
32
 
26
33
  /**
@@ -34,6 +41,8 @@ export interface ReducerMetadata {
34
41
  * @param id - The unique identifier for the reducer. Defaults to the class name if omitted.
35
42
  * @param eventSequenceId - Optional explicit event sequence identifier.
36
43
  * @param readModel - Optional read model type produced by the reducer.
44
+ * @param isActive - Whether the reducer is active (automatically observes events). Defaults to true.
45
+ * A passive reducer is registered but must be invoked on demand rather than observing automatically.
37
46
  * @returns A class decorator.
38
47
  *
39
48
  * @example
@@ -46,11 +55,11 @@ export interface ReducerMetadata {
46
55
  * }
47
56
  * ```
48
57
  */
49
- export function reducer(id: string = '', eventSequenceId?: string, readModel?: Constructor): ClassDecorator {
58
+ export function reducer(id: string = '', eventSequenceId?: string, readModel?: Constructor, isActive: boolean = true): ClassDecorator {
50
59
  return (target: object) => {
51
60
  const constructor = target as Function;
52
61
  const reducerId = new ReducerId(id || constructor.name);
53
- const metadata: ReducerMetadata = { id: reducerId, eventSequenceId, readModel };
62
+ const metadata: ReducerMetadata = { id: reducerId, eventSequenceId, readModel, isActive };
54
63
  Reflect.defineMetadata(REDUCER_METADATA_KEY, metadata, target);
55
64
  TypeDiscoverer.default.register(
56
65
  DecoratorType.Reducer,
@@ -2,6 +2,9 @@
2
2
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
 
4
4
  import { Guid } from '@cratis/fundamentals';
5
+ import { AppendError } from '../eventSequences/AppendError';
6
+ import { ConcurrencyViolation } from '../eventSequences/ConcurrencyViolation';
7
+ import { ConstraintViolation } from '../eventSequences/ConstraintViolation';
5
8
  import { EventSequenceId } from '../eventSequences/EventSequenceId';
6
9
  import { AppendResult } from '../eventSequences/AppendResult';
7
10
 
@@ -38,6 +41,24 @@ export interface IUnitOfWork {
38
41
  */
39
42
  getAppendResults(): ReadonlyArray<AppendResult>;
40
43
 
44
+ /**
45
+ * Gets any constraint violations that occurred across the append results from the latest commit.
46
+ * @returns A thin filter over {@link getAppendResults}.
47
+ */
48
+ getConstraintViolations(): ReadonlyArray<ConstraintViolation>;
49
+
50
+ /**
51
+ * Gets any concurrency violations that occurred across the append results from the latest commit.
52
+ * @returns A thin filter over {@link getAppendResults}.
53
+ */
54
+ getConcurrencyViolations(): ReadonlyArray<ConcurrencyViolation>;
55
+
56
+ /**
57
+ * Gets any errors that occurred while attempting to commit.
58
+ * @returns A thin filter over {@link getAppendResults}.
59
+ */
60
+ getAppendErrors(): ReadonlyArray<AppendError>;
61
+
41
62
  /**
42
63
  * Commits all buffered events.
43
64
  */
@@ -0,0 +1,82 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ import { Guid } from '@cratis/fundamentals';
6
+ import type { AppendResult } from '../eventSequences/AppendResult';
7
+ import { EventSequenceId } from '../eventSequences/EventSequenceId';
8
+ import { EventSequenceNumber } from '../eventSequences/EventSequenceNumber';
9
+ import type { IEventSequence } from '../eventSequences/IEventSequence';
10
+ import type { IEventStore } from '../IEventStore';
11
+ import { UnitOfWork } from './UnitOfWork';
12
+
13
+ function createAppendResult(overrides: Partial<AppendResult> = {}): AppendResult {
14
+ return {
15
+ sequenceNumber: EventSequenceNumber.first,
16
+ constraintViolations: [],
17
+ errors: [],
18
+ isSuccess: true,
19
+ waitForCompletion: vi.fn(),
20
+ ...overrides
21
+ };
22
+ }
23
+
24
+ function createUnitOfWork(appendManyResult: AppendResult[]) {
25
+ const appendMany = vi.fn().mockResolvedValue(appendManyResult);
26
+ const eventSequence = { appendMany } as unknown as IEventSequence;
27
+ const eventStore = { getEventSequence: vi.fn().mockReturnValue(eventSequence) } as unknown as IEventStore;
28
+ const unitOfWork = new UnitOfWork(Guid.create(), vi.fn(), eventStore);
29
+ return { unitOfWork, eventStore };
30
+ }
31
+
32
+ class SomethingHappened {
33
+ constructor(readonly value: string = '') {}
34
+ }
35
+
36
+ describe('UnitOfWork', () => {
37
+ describe('when filtering violations after a commit', () => {
38
+ const constraintViolation = { constraintId: 'unique', message: 'Value must be unique', details: {} };
39
+ const concurrencyViolation = {
40
+ eventSourceId: 'some-event-source',
41
+ expectedSequenceNumber: new EventSequenceNumber(1n),
42
+ actualSequenceNumber: new EventSequenceNumber(2n)
43
+ };
44
+ const appendError = { message: 'Something went wrong' };
45
+
46
+ const { unitOfWork } = createUnitOfWork([
47
+ createAppendResult({ constraintViolations: [constraintViolation], isSuccess: false }),
48
+ createAppendResult({ concurrencyViolation, isSuccess: false }),
49
+ createAppendResult({ errors: [appendError], isSuccess: false }),
50
+ createAppendResult()
51
+ ]);
52
+
53
+ it('should expose the constraint violations, concurrency violations, and errors as separate thin filters over getAppendResults', async () => {
54
+ unitOfWork.addEvent(EventSequenceId.eventLog, 'some-event-source', new SomethingHappened('a'));
55
+ unitOfWork.addEvent(EventSequenceId.eventLog, 'some-event-source', new SomethingHappened('b'));
56
+ unitOfWork.addEvent(EventSequenceId.eventLog, 'some-event-source', new SomethingHappened('c'));
57
+ unitOfWork.addEvent(EventSequenceId.eventLog, 'some-event-source', new SomethingHappened('d'));
58
+
59
+ await unitOfWork.commit();
60
+
61
+ expect(unitOfWork.getAppendResults()).toHaveLength(4);
62
+ expect(unitOfWork.getConstraintViolations()).toEqual([constraintViolation]);
63
+ expect(unitOfWork.getConcurrencyViolations()).toEqual([concurrencyViolation]);
64
+ expect(unitOfWork.getAppendErrors()).toEqual([appendError]);
65
+ });
66
+ });
67
+
68
+ describe('when nothing failed', () => {
69
+ const { unitOfWork } = createUnitOfWork([createAppendResult(), createAppendResult()]);
70
+
71
+ it('should return empty arrays for all three violation filters', async () => {
72
+ unitOfWork.addEvent(EventSequenceId.eventLog, 'some-event-source', new SomethingHappened('a'));
73
+ unitOfWork.addEvent(EventSequenceId.eventLog, 'some-event-source', new SomethingHappened('b'));
74
+
75
+ await unitOfWork.commit();
76
+
77
+ expect(unitOfWork.getConstraintViolations()).toEqual([]);
78
+ expect(unitOfWork.getConcurrencyViolations()).toEqual([]);
79
+ expect(unitOfWork.getAppendErrors()).toEqual([]);
80
+ });
81
+ });
82
+ });
@@ -2,7 +2,10 @@
2
2
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
 
4
4
  import { Guid } from '@cratis/fundamentals';
5
+ import { AppendError } from '../eventSequences/AppendError';
5
6
  import { AppendResult } from '../eventSequences/AppendResult';
7
+ import { ConcurrencyViolation } from '../eventSequences/ConcurrencyViolation';
8
+ import { ConstraintViolation } from '../eventSequences/ConstraintViolation';
6
9
  import { EventForEventSourceId } from '../eventSequences/EventForEventSourceId';
7
10
  import { EventSequenceId } from '../eventSequences/EventSequenceId';
8
11
  import { IEventStore } from '../IEventStore';
@@ -65,6 +68,23 @@ export class UnitOfWork implements IUnitOfWork {
65
68
  return this._appendResults;
66
69
  }
67
70
 
71
+ /** @inheritdoc */
72
+ getConstraintViolations(): ReadonlyArray<ConstraintViolation> {
73
+ return this._appendResults.flatMap(appendResult => appendResult.constraintViolations);
74
+ }
75
+
76
+ /** @inheritdoc */
77
+ getConcurrencyViolations(): ReadonlyArray<ConcurrencyViolation> {
78
+ return this._appendResults
79
+ .map(appendResult => appendResult.concurrencyViolation)
80
+ .filter((violation): violation is ConcurrencyViolation => violation !== undefined);
81
+ }
82
+
83
+ /** @inheritdoc */
84
+ getAppendErrors(): ReadonlyArray<AppendError> {
85
+ return this._appendResults.flatMap(appendResult => appendResult.errors);
86
+ }
87
+
68
88
  /** @inheritdoc */
69
89
  async commit(): Promise<void> {
70
90
  this.throwIfCompleted();