@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
@@ -0,0 +1,257 @@
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 { AutoMap } from '@cratis/chronicle.contracts';
5
+ import { getEventTypeFor } from '../../events/eventTypeDecorator';
6
+ import { FromBuilder } from './FromBuilder';
7
+ import { IFromBuilder } from './IFromBuilder';
8
+ import { IFromEveryBuilder } from './IFromEveryBuilder';
9
+ import { IJoinBuilder } from './IJoinBuilder';
10
+ import { IRemovedWithBuilder } from './IRemovedWithBuilder';
11
+ import { IRemovedWithJoinBuilder } from './IRemovedWithJoinBuilder';
12
+ import { JoinBuilder } from './JoinBuilder';
13
+ import { FromEveryBuilder } from './FromEveryBuilder';
14
+ import { RemovedWithBuilder } from './RemovedWithBuilder';
15
+ import { RemovedWithJoinBuilder } from './RemovedWithJoinBuilder';
16
+ import { ChildAdditionEntry } from './AddChildBuilder';
17
+
18
+ /** The contract-level event type identifier shape used across projection definitions. */
19
+ export type ContractEventType = { Id: string; Generation: number; Tombstone: boolean };
20
+
21
+ /** Accumulated property mapping for a from clause. */
22
+ export interface FromRecord {
23
+ Key: ContractEventType;
24
+ Value: { Properties: Record<string, string>; Key: string; ParentKey: string };
25
+ }
26
+
27
+ /** Accumulated property mapping for a join clause. */
28
+ export interface JoinRecord {
29
+ Key: ContractEventType;
30
+ Value: { On: string; Properties: Record<string, string>; Key: string };
31
+ }
32
+
33
+ /** Accumulated removal mapping for a removedWith clause. */
34
+ export interface RemovedWithRecord {
35
+ Key: ContractEventType;
36
+ Value: { Key: string; ParentKey: string };
37
+ }
38
+
39
+ /** Accumulated removal mapping for a removedWithJoin clause. */
40
+ export interface RemovedWithJoinRecord {
41
+ Key: ContractEventType;
42
+ Value: { Key: string };
43
+ }
44
+
45
+ /**
46
+ * Plain object shape matching the wire-level `ChildrenDefinition` used for both children
47
+ * collections and nested single-object projections.
48
+ */
49
+ export interface ChildrenDefinitionLike {
50
+ IdentifiedBy: string;
51
+ From: FromRecord[];
52
+ Join: JoinRecord[];
53
+ Children: Record<string, ChildrenDefinitionLike>;
54
+ All: { Properties: Record<string, string>; IncludeChildren: boolean; AutoMap: AutoMap };
55
+ FromEventProperty?: { Event: ContractEventType | undefined; PropertyExpression: string };
56
+ RemovedWith: RemovedWithRecord[];
57
+ RemovedWithJoin: RemovedWithJoinRecord[];
58
+ AutoMap: AutoMap;
59
+ Nested: Record<string, ChildrenDefinitionLike>;
60
+ }
61
+
62
+ /**
63
+ * Base accumulator shared by every projection-shaped builder (the top-level
64
+ * {@link ProjectionBuilderFor}, and the child/nested builders reached through
65
+ * `.children()`/`.nested()`). Holds the from/join/fromEvery/removedWith/removedWithJoin/
66
+ * children/nested state and the mapping operations common to all of them, mirroring the
67
+ * shared `ProjectionBuilder<TReadModel, TBuilder>` base class on the C# client.
68
+ * @template TReadModel - The read model type this builder produces.
69
+ * @template TBuilder - The concrete builder type returned for fluent chaining.
70
+ */
71
+ export abstract class ProjectionBuilderCore<TReadModel, TBuilder> {
72
+ protected _autoMap: AutoMap = AutoMap.Inherit;
73
+ protected _initialState: string = '{}';
74
+ protected readonly _from: FromRecord[] = [];
75
+ protected readonly _join: JoinRecord[] = [];
76
+ protected readonly _removedWith: RemovedWithRecord[] = [];
77
+ protected readonly _removedWithJoin: RemovedWithJoinRecord[] = [];
78
+ protected readonly _children: Record<string, ChildrenDefinitionLike> = {};
79
+ protected readonly _nested: Record<string, ChildrenDefinitionLike> = {};
80
+ protected _all: { Properties: Record<string, string>; IncludeChildren: boolean; AutoMap: AutoMap } = {
81
+ Properties: {},
82
+ IncludeChildren: false,
83
+ AutoMap: AutoMap.Inherit
84
+ };
85
+
86
+ /** @inheritdoc */
87
+ autoMap(): TBuilder {
88
+ this._autoMap = AutoMap.Enabled;
89
+ return this as unknown as TBuilder;
90
+ }
91
+
92
+ /** @inheritdoc */
93
+ noAutoMap(): TBuilder {
94
+ this._autoMap = AutoMap.Disabled;
95
+ return this as unknown as TBuilder;
96
+ }
97
+
98
+ /** @inheritdoc */
99
+ withInitialValues(initialValueProvider: () => TReadModel): TBuilder {
100
+ this._initialState = JSON.stringify(initialValueProvider());
101
+ return this as unknown as TBuilder;
102
+ }
103
+
104
+ /** @inheritdoc */
105
+ from<TEvent>(
106
+ eventType: new (...args: any[]) => TEvent,
107
+ builderCallback?: (builder: IFromBuilder<TReadModel, TEvent>) => void
108
+ ): TBuilder {
109
+ const contractType = this.toContractEventType(eventType);
110
+ const fromBuilder = new FromBuilder<TReadModel, TEvent>();
111
+ builderCallback?.(fromBuilder);
112
+ this._from.push({
113
+ Key: contractType,
114
+ Value: {
115
+ Properties: fromBuilder.entry.properties,
116
+ Key: fromBuilder.entry.key,
117
+ ParentKey: fromBuilder.entry.parentKey
118
+ }
119
+ });
120
+ this.mergeChildAdditions(contractType, fromBuilder.entry.children);
121
+ return this as unknown as TBuilder;
122
+ }
123
+
124
+ /** @inheritdoc */
125
+ join<TEvent>(
126
+ eventType: new (...args: any[]) => TEvent,
127
+ builderCallback?: (builder: IJoinBuilder<TReadModel, TEvent>) => void
128
+ ): TBuilder {
129
+ const contractType = this.toContractEventType(eventType);
130
+ const joinBuilder = new JoinBuilder<TReadModel, TEvent>();
131
+ builderCallback?.(joinBuilder);
132
+ this._join.push({
133
+ Key: contractType,
134
+ Value: {
135
+ On: joinBuilder.entry.on,
136
+ Properties: joinBuilder.entry.properties,
137
+ Key: joinBuilder.entry.key
138
+ }
139
+ });
140
+ this.mergeChildAdditions(contractType, joinBuilder.entry.children);
141
+ return this as unknown as TBuilder;
142
+ }
143
+
144
+ /** @inheritdoc */
145
+ fromEvery(builderCallback: (builder: IFromEveryBuilder<TReadModel>) => void): TBuilder {
146
+ const builder = new FromEveryBuilder<TReadModel>();
147
+ builderCallback(builder);
148
+ this._all = {
149
+ Properties: {
150
+ ...this._all.Properties,
151
+ ...builder.entry.properties
152
+ },
153
+ IncludeChildren: builder.entry.includeChildren,
154
+ AutoMap: AutoMap.Inherit
155
+ };
156
+ return this as unknown as TBuilder;
157
+ }
158
+
159
+ /** @inheritdoc */
160
+ removedWith<TEvent>(
161
+ eventType: new (...args: any[]) => TEvent,
162
+ builderCallback?: (builder: IRemovedWithBuilder<TReadModel, TEvent>) => void
163
+ ): TBuilder {
164
+ const contractType = this.toContractEventType(eventType);
165
+ const removedWithBuilder = new RemovedWithBuilder<TReadModel, TEvent>();
166
+ builderCallback?.(removedWithBuilder);
167
+ this._removedWith.push({
168
+ Key: contractType,
169
+ Value: {
170
+ Key: removedWithBuilder.entry.key,
171
+ ParentKey: removedWithBuilder.entry.parentKey
172
+ }
173
+ });
174
+ return this as unknown as TBuilder;
175
+ }
176
+
177
+ /** @inheritdoc */
178
+ removedWithJoin<TEvent>(
179
+ eventType: new (...args: any[]) => TEvent,
180
+ builderCallback?: (builder: IRemovedWithJoinBuilder<TReadModel, TEvent>) => void
181
+ ): TBuilder {
182
+ const contractType = this.toContractEventType(eventType);
183
+ const removedWithJoinBuilder = new RemovedWithJoinBuilder<TReadModel, TEvent>();
184
+ builderCallback?.(removedWithJoinBuilder);
185
+ this._removedWithJoin.push({
186
+ Key: contractType,
187
+ Value: {
188
+ Key: removedWithJoinBuilder.entry.key
189
+ }
190
+ });
191
+ return this as unknown as TBuilder;
192
+ }
193
+
194
+ /**
195
+ * Creates an empty {@link ChildrenDefinitionLike} accumulator for a children/nested entry.
196
+ * @returns A fresh, empty children definition.
197
+ */
198
+ protected createEmptyChildrenDefinition(): ChildrenDefinitionLike {
199
+ return {
200
+ IdentifiedBy: '$eventSourceId',
201
+ From: [],
202
+ Join: [],
203
+ Children: {},
204
+ All: { Properties: {}, IncludeChildren: false, AutoMap: AutoMap.Inherit },
205
+ RemovedWith: [],
206
+ RemovedWithJoin: [],
207
+ AutoMap: AutoMap.Inherit,
208
+ Nested: {}
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Merges `.addChild()` accumulations captured on a from/join builder into this builder's
214
+ * children definitions, creating the target child entry on first use.
215
+ * @param eventType - The contract event type the child additions were captured for.
216
+ * @param children - The accumulated child additions.
217
+ */
218
+ private mergeChildAdditions(eventType: ContractEventType, children: ChildAdditionEntry[]): void {
219
+ for (const child of children) {
220
+ const childDefinition = this._children[child.targetProperty] ??= this.createEmptyChildrenDefinition();
221
+
222
+ if (child.identifiedBy) {
223
+ childDefinition.IdentifiedBy = child.identifiedBy;
224
+ }
225
+
226
+ if (child.fromEventProperty) {
227
+ childDefinition.FromEventProperty = { Event: eventType, PropertyExpression: child.fromEventProperty };
228
+ }
229
+
230
+ childDefinition.From.push({
231
+ Key: eventType,
232
+ Value: {
233
+ Key: child.usingKey ?? '$eventSourceId',
234
+ ParentKey: '$eventSourceId',
235
+ Properties: {}
236
+ }
237
+ });
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Resolves the contract event type for a decorated event constructor.
243
+ * @param eventTypeConstructor - The event class constructor.
244
+ * @returns The contract-level event type identifier.
245
+ */
246
+ protected toContractEventType(eventTypeConstructor: Function): ContractEventType {
247
+ const eventType = getEventTypeFor(eventTypeConstructor);
248
+ if (eventType.id.value === '') {
249
+ throw new Error(`Event type '${eventTypeConstructor.name}' is not decorated with @eventType().`);
250
+ }
251
+ return {
252
+ Id: eventType.id.value,
253
+ Generation: eventType.generation.value,
254
+ Tombstone: false
255
+ };
256
+ }
257
+ }
@@ -0,0 +1,115 @@
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 'reflect-metadata';
5
+ import { describe, expect, it } from 'vitest';
6
+ import { eventType } from '../../events/eventTypeDecorator';
7
+ import { ProjectionBuilderFor } from './ProjectionBuilderFor';
8
+
9
+ // Decorators are applied as plain function calls (rather than `@decorator` syntax) so these
10
+ // fixtures don't depend on the test runner's decorator-syntax support.
11
+
12
+ class ItemAdded {
13
+ quantity!: number;
14
+ }
15
+ eventType()(ItemAdded);
16
+
17
+ class ItemRemoved {
18
+ quantity!: number;
19
+ }
20
+ eventType()(ItemRemoved);
21
+
22
+ class ThingHappened {}
23
+ eventType()(ThingHappened);
24
+
25
+ class Inventory {
26
+ id!: string;
27
+ total!: number;
28
+ removedTotal!: number;
29
+ thingsHappenedCount!: number;
30
+ }
31
+
32
+ interface FromRecord {
33
+ Key: { Id: string };
34
+ Value: { Properties: Record<string, string>; Key: string };
35
+ }
36
+
37
+ interface JoinRecord {
38
+ Key: { Id: string };
39
+ Value: { Properties: Record<string, string> };
40
+ }
41
+
42
+ describe('ProjectionBuilderFor', () => {
43
+ describe('when using add on a from builder', () => {
44
+ it('should produce a $add expression targeting the event property', () => {
45
+ const builder = new ProjectionBuilderFor<Inventory>();
46
+ builder.from(ItemAdded, from => from.add(model => model.total).with(event => event.quantity));
47
+
48
+ const definition = builder.build('inventory', 'Inventory') as unknown as { From: FromRecord[] };
49
+ const entry = definition.From.find(candidate => candidate.Key.Id === 'ItemAdded')!;
50
+
51
+ expect(entry.Value.Properties.total).toBe('$add(quantity)');
52
+ });
53
+ });
54
+
55
+ describe('when using subtract on a from builder', () => {
56
+ it('should produce a $subtract expression targeting the event property', () => {
57
+ const builder = new ProjectionBuilderFor<Inventory>();
58
+ builder.from(ItemRemoved, from => from.subtract(model => model.removedTotal).with(event => event.quantity));
59
+
60
+ const definition = builder.build('inventory', 'Inventory') as unknown as { From: FromRecord[] };
61
+ const entry = definition.From.find(candidate => candidate.Key.Id === 'ItemRemoved')!;
62
+
63
+ expect(entry.Value.Properties.removedTotal).toBe('$subtract(quantity)');
64
+ });
65
+ });
66
+
67
+ describe('when using count on a from builder', () => {
68
+ it('should produce a $count expression and return the builder for chaining', () => {
69
+ const builder = new ProjectionBuilderFor<Inventory>();
70
+ builder.from(ThingHappened, from => from.count(model => model.thingsHappenedCount).usingConstantKey('singleton'));
71
+
72
+ const definition = builder.build('inventory', 'Inventory') as unknown as { From: FromRecord[] };
73
+ const entry = definition.From.find(candidate => candidate.Key.Id === 'ThingHappened')!;
74
+
75
+ expect(entry.Value.Properties.thingsHappenedCount).toBe('$count');
76
+ expect(entry.Value.Key).toBe('singleton');
77
+ });
78
+ });
79
+
80
+ describe('when using add on a join builder', () => {
81
+ it('should produce a $add expression targeting the event property', () => {
82
+ const builder = new ProjectionBuilderFor<Inventory>();
83
+ builder.join(ItemAdded, join => join.add(model => model.total).with(event => event.quantity));
84
+
85
+ const definition = builder.build('inventory', 'Inventory') as unknown as { Join: JoinRecord[] };
86
+ const entry = definition.Join.find(candidate => candidate.Key.Id === 'ItemAdded')!;
87
+
88
+ expect(entry.Value.Properties.total).toBe('$add(quantity)');
89
+ });
90
+ });
91
+
92
+ describe('when using subtract on a join builder', () => {
93
+ it('should produce a $subtract expression targeting the event property', () => {
94
+ const builder = new ProjectionBuilderFor<Inventory>();
95
+ builder.join(ItemRemoved, join => join.subtract(model => model.removedTotal).with(event => event.quantity));
96
+
97
+ const definition = builder.build('inventory', 'Inventory') as unknown as { Join: JoinRecord[] };
98
+ const entry = definition.Join.find(candidate => candidate.Key.Id === 'ItemRemoved')!;
99
+
100
+ expect(entry.Value.Properties.removedTotal).toBe('$subtract(quantity)');
101
+ });
102
+ });
103
+
104
+ describe('when using count on a join builder', () => {
105
+ it('should produce a $count expression', () => {
106
+ const builder = new ProjectionBuilderFor<Inventory>();
107
+ builder.join(ThingHappened, join => join.count(model => model.thingsHappenedCount));
108
+
109
+ const definition = builder.build('inventory', 'Inventory') as unknown as { Join: JoinRecord[] };
110
+ const entry = definition.Join.find(candidate => candidate.Key.Id === 'ThingHappened')!;
111
+
112
+ expect(entry.Value.Properties.thingsHappenedCount).toBe('$count');
113
+ });
114
+ });
115
+ });
@@ -2,65 +2,30 @@
2
2
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
 
4
4
  import { AutoMap } from '@cratis/chronicle.contracts';
5
- import { getEventTypeFor } from '../../events/eventTypeDecorator';
5
+ import { PropertyAccessor, PropertyPathResolverProxyHandler } from '@cratis/fundamentals';
6
6
  import { EventSequenceId } from '../../eventSequences/EventSequenceId';
7
+ import { ChildrenBuilder } from './ChildrenBuilder';
7
8
  import { IChildrenBuilder } from './IChildrenBuilder';
8
- import { IFromBuilder } from './IFromBuilder';
9
- import { IFromEveryBuilder } from './IFromEveryBuilder';
10
- import { IJoinBuilder } from './IJoinBuilder';
11
9
  import { INestedBuilder } from './INestedBuilder';
12
10
  import { IProjectionBuilderFor } from './IProjectionBuilderFor';
13
- import { IRemovedWithBuilder } from './IRemovedWithBuilder';
14
- import { IRemovedWithJoinBuilder } from './IRemovedWithJoinBuilder';
15
- import { JoinBuilder } from './JoinBuilder';
16
- import { FromEveryBuilder } from './FromEveryBuilder';
17
- import { FromBuilder } from './FromBuilder';
18
- import { RemovedWithBuilder } from './RemovedWithBuilder';
19
- import { RemovedWithJoinBuilder } from './RemovedWithJoinBuilder';
20
-
21
- type ContractEventType = { Id: string; Generation: number; Tombstone: boolean };
22
-
23
- interface FromRecord {
24
- Key: ContractEventType;
25
- Value: { Properties: Record<string, string>; Key: string; ParentKey: string };
26
- }
27
-
28
- interface RemovedWithRecord {
29
- Key: ContractEventType;
30
- Value: { Key: string; ParentKey: string };
31
- }
32
-
33
- interface JoinRecord {
34
- Key: ContractEventType;
35
- Value: { On: string; Properties: Record<string, string>; Key: string };
36
- }
37
-
38
- interface RemovedWithJoinRecord {
39
- Key: ContractEventType;
40
- Value: { Key: string };
41
- }
11
+ import { NestedBuilder } from './NestedBuilder';
12
+ import { ProjectionBuilderCore } from './ProjectionBuilderCore';
42
13
 
43
14
  /**
44
15
  * Concrete implementation of {@link IProjectionBuilderFor} that accumulates projection
45
16
  * configuration and produces a Chronicle-compatible projection definition payload.
46
17
  * @template TReadModel - The read model type this projection produces.
47
18
  */
48
- export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<TReadModel> {
19
+ export class ProjectionBuilderFor<TReadModel> extends ProjectionBuilderCore<TReadModel, ProjectionBuilderFor<TReadModel>> implements IProjectionBuilderFor<TReadModel> {
49
20
  private _eventSequenceId: string = EventSequenceId.eventLog.value;
50
21
  private _containerName: string | undefined;
51
22
  private _rewindable: boolean = true;
52
23
  private _active: boolean = true;
53
- private _autoMap: AutoMap = AutoMap.Enabled;
54
- private _initialState: string = '{}';
55
- private readonly _from: FromRecord[] = [];
56
- private readonly _join: JoinRecord[] = [];
57
- private readonly _removedWith: RemovedWithRecord[] = [];
58
- private readonly _removedWithJoin: RemovedWithJoinRecord[] = [];
59
- private _all: { Properties: Record<string, string>; IncludeChildren: boolean; AutoMap: AutoMap } = {
60
- Properties: {},
61
- IncludeChildren: false,
62
- AutoMap: AutoMap.Inherit
63
- };
24
+
25
+ constructor() {
26
+ super();
27
+ this._autoMap = AutoMap.Enabled;
28
+ }
64
29
 
65
30
  /** @inheritdoc */
66
31
  fromEventSequence(eventSequenceId: string): this {
@@ -87,127 +52,35 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
87
52
  }
88
53
 
89
54
  /** @inheritdoc */
90
- autoMap(): this {
91
- this._autoMap = AutoMap.Enabled;
92
- return this;
93
- }
94
-
95
- /** @inheritdoc */
96
- noAutoMap(): this {
97
- this._autoMap = AutoMap.Disabled;
98
- return this;
99
- }
100
-
101
- /** @inheritdoc */
102
- withInitialValues(initialValueProvider: () => TReadModel): this {
103
- this._initialState = JSON.stringify(initialValueProvider());
104
- return this;
105
- }
106
-
107
- /** @inheritdoc */
108
- from<TEvent>(
109
- eventType: new (...args: any[]) => TEvent,
110
- builderCallback?: (builder: IFromBuilder<TReadModel, TEvent>) => void
111
- ): this {
112
- const contractType = this.toContractEventType(eventType);
113
- const fromBuilder = new FromBuilder<TReadModel, TEvent>();
114
- builderCallback?.(fromBuilder);
115
- this._from.push({
116
- Key: contractType,
117
- Value: {
118
- Properties: fromBuilder.entry.properties,
119
- Key: fromBuilder.entry.key,
120
- ParentKey: fromBuilder.entry.parentKey
121
- }
122
- });
123
- return this;
124
- }
125
-
126
- /** @inheritdoc */
127
- join<TEvent>(
128
- eventType: new (...args: any[]) => TEvent,
129
- builderCallback?: (builder: IJoinBuilder<TReadModel, TEvent>) => void
55
+ children<TChildModel>(
56
+ targetPropertyAccessor: PropertyAccessor<TReadModel>,
57
+ builderCallback: (builder: IChildrenBuilder<TReadModel, TChildModel>) => void
130
58
  ): this {
131
- const contractType = this.toContractEventType(eventType);
132
- const joinBuilder = new JoinBuilder<TReadModel, TEvent>();
133
- builderCallback?.(joinBuilder);
134
- this._join.push({
135
- Key: contractType,
136
- Value: {
137
- On: joinBuilder.entry.on,
138
- Properties: joinBuilder.entry.properties,
139
- Key: joinBuilder.entry.key
140
- }
141
- });
142
- return this;
143
- }
59
+ const handler = new PropertyPathResolverProxyHandler();
60
+ const proxy = new Proxy({}, handler);
61
+ targetPropertyAccessor(proxy as TReadModel);
144
62
 
145
- /** @inheritdoc */
146
- fromEvery(builderCallback: (builder: IFromEveryBuilder<TReadModel>) => void): this {
147
- const builder = new FromEveryBuilder<TReadModel>();
63
+ const builder = new ChildrenBuilder<TReadModel, TChildModel>();
148
64
  builderCallback(builder);
149
- this._all = {
150
- Properties: {
151
- ...this._all.Properties,
152
- ...builder.entry.properties
153
- },
154
- IncludeChildren: builder.entry.includeChildren,
155
- AutoMap: AutoMap.Inherit
156
- };
65
+ this._children[handler.property] = builder.buildDefinition();
157
66
  return this;
158
67
  }
159
68
 
160
69
  /** @inheritdoc */
161
- removedWith<TEvent>(
162
- eventType: new (...args: any[]) => TEvent,
163
- builderCallback?: (builder: IRemovedWithBuilder<TReadModel, TEvent>) => void
70
+ nested<TNestedModel>(
71
+ targetPropertyAccessor: PropertyAccessor<TReadModel>,
72
+ builderCallback: (builder: INestedBuilder<TReadModel, TNestedModel>) => void
164
73
  ): this {
165
- const contractType = this.toContractEventType(eventType);
166
- const removedWithBuilder = new RemovedWithBuilder<TReadModel, TEvent>();
167
- builderCallback?.(removedWithBuilder);
168
- this._removedWith.push({
169
- Key: contractType,
170
- Value: {
171
- Key: removedWithBuilder.entry.key,
172
- ParentKey: removedWithBuilder.entry.parentKey
173
- }
174
- });
175
- return this;
176
- }
74
+ const handler = new PropertyPathResolverProxyHandler();
75
+ const proxy = new Proxy({}, handler);
76
+ targetPropertyAccessor(proxy as TReadModel);
177
77
 
178
- /** @inheritdoc */
179
- removedWithJoin<TEvent>(
180
- eventType: new (...args: any[]) => TEvent,
181
- builderCallback?: (builder: IRemovedWithJoinBuilder<TReadModel, TEvent>) => void
182
- ): this {
183
- const contractType = this.toContractEventType(eventType);
184
- const removedWithJoinBuilder = new RemovedWithJoinBuilder<TReadModel, TEvent>();
185
- builderCallback?.(removedWithJoinBuilder);
186
- this._removedWithJoin.push({
187
- Key: contractType,
188
- Value: {
189
- Key: removedWithJoinBuilder.entry.key
190
- }
191
- });
78
+ const builder = new NestedBuilder<TReadModel, TNestedModel>();
79
+ builderCallback(builder);
80
+ this._nested[handler.property] = builder.buildDefinition();
192
81
  return this;
193
82
  }
194
83
 
195
- /** @inheritdoc */
196
- children<TChildModel>(
197
- _targetPropertyAccessor: any,
198
- _builderCallback: (builder: IChildrenBuilder<TReadModel, TChildModel>) => void
199
- ): this {
200
- throw new Error('children is not implemented yet.');
201
- }
202
-
203
- /** @inheritdoc */
204
- nested<TNestedModel>(
205
- _targetPropertyAccessor: any,
206
- _builderCallback: (builder: INestedBuilder<TReadModel, TNestedModel>) => void
207
- ): this {
208
- throw new Error('nested is not implemented yet.');
209
- }
210
-
211
84
  /**
212
85
  * Builds the contract-compatible projection definition payload.
213
86
  * @param identifier - The projection identifier.
@@ -224,7 +97,7 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
224
97
  InitialModelState: this._initialState,
225
98
  From: this._from,
226
99
  Join: this._join,
227
- Children: {},
100
+ Children: this._children,
228
101
  FromEvery: [],
229
102
  All: this._all,
230
103
  FromEventProperty: undefined,
@@ -233,7 +106,7 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
233
106
  LastUpdated: { Value: '' },
234
107
  Tags: [],
235
108
  AutoMap: this._autoMap,
236
- Nested: {}
109
+ Nested: this._nested
237
110
  };
238
111
  definition.LastUpdated = { Value: this.computeStableLastUpdated(definition) };
239
112
  return definition;
@@ -265,18 +138,6 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
265
138
  return Array.from(mappedProperties.values());
266
139
  }
267
140
 
268
- private toContractEventType(eventTypeConstructor: Function): ContractEventType {
269
- const eventType = getEventTypeFor(eventTypeConstructor);
270
- if (eventType.id.value === '') {
271
- throw new Error(`Event type '${eventTypeConstructor.name}' is not decorated with @eventType().`);
272
- }
273
- return {
274
- Id: eventType.id.value,
275
- Generation: eventType.generation.value,
276
- Tombstone: false
277
- };
278
- }
279
-
280
141
  /**
281
142
  * Computes a stable, deterministic ISO timestamp from the projection definition content,
282
143
  * excluding the LastUpdated field itself. This ensures the server does not interpret
@@ -0,0 +1,28 @@
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 { PropertyAccessor, PropertyPathResolverProxyHandler } from '@cratis/fundamentals';
5
+ import { ISubtractBuilder } from './ISubtractBuilder';
6
+
7
+ /**
8
+ * Concrete implementation of {@link ISubtractBuilder} that records a subtract expression
9
+ * into the owning from/join builder.
10
+ * @template TEvent - The event type.
11
+ * @template TParentBuilder - The parent builder type.
12
+ */
13
+ export class SubtractBuilder<TEvent, TParentBuilder> implements ISubtractBuilder<TEvent, TParentBuilder> {
14
+ constructor(
15
+ private readonly _readModelProperty: string,
16
+ private readonly _setProperty: (readModelProp: string, expression: string) => void,
17
+ private readonly _parent: TParentBuilder
18
+ ) {}
19
+
20
+ /** @inheritdoc */
21
+ with(eventPropertyAccessor: PropertyAccessor<TEvent>): TParentBuilder {
22
+ const handler = new PropertyPathResolverProxyHandler();
23
+ const proxy = new Proxy({}, handler);
24
+ eventPropertyAccessor(proxy as TEvent);
25
+ this._setProperty(this._readModelProperty, `$subtract(${handler.property})`);
26
+ return this._parent;
27
+ }
28
+ }
@@ -4,8 +4,17 @@
4
4
  export { projection, getProjectionMetadata, isProjection } from './projection';
5
5
  export type { ProjectionMetadata } from './projection';
6
6
  export { ProjectionBuilderFor } from './ProjectionBuilderFor';
7
+ export { ProjectionBuilderCore } from './ProjectionBuilderCore';
8
+ export { ChildrenBuilder } from './ChildrenBuilder';
9
+ export { NestedBuilder } from './NestedBuilder';
10
+ export { AddChildBuilder } from './AddChildBuilder';
11
+ export type { ChildAdditionEntry } from './AddChildBuilder';
12
+ export { CompositeKeyBuilder } from './CompositeKeyBuilder';
7
13
  export { FromBuilder } from './FromBuilder';
14
+ export { JoinBuilder } from './JoinBuilder';
8
15
  export { SetBuilder } from './SetBuilder';
16
+ export { AddBuilder } from './AddBuilder';
17
+ export { SubtractBuilder } from './SubtractBuilder';
9
18
  export { RemovedWithBuilder } from './RemovedWithBuilder';
10
19
  export type { IProjectionFor } from './IProjectionFor';
11
20
  export type { IProjectionBuilderFor } from './IProjectionBuilderFor';