@ddd-ts-kit/kernel 0.9.0 → 0.10.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 (260) hide show
  1. package/README.md +138 -2
  2. package/dist/application/criteria/index.d.ts +33 -0
  3. package/dist/application/criteria/index.d.ts.map +1 -0
  4. package/dist/application/criteria/index.js +33 -0
  5. package/dist/application/criteria/index.js.map +1 -0
  6. package/dist/application/event-sourcing/appended.d.ts +8 -0
  7. package/dist/application/event-sourcing/appended.d.ts.map +1 -0
  8. package/dist/application/event-sourcing/appended.js +2 -0
  9. package/dist/application/event-sourcing/appended.js.map +1 -0
  10. package/dist/application/event-sourcing/define-stored-event.d.ts +10 -0
  11. package/dist/application/event-sourcing/define-stored-event.d.ts.map +1 -0
  12. package/dist/application/event-sourcing/define-stored-event.js +22 -0
  13. package/dist/application/event-sourcing/define-stored-event.js.map +1 -0
  14. package/dist/application/event-sourcing/erased-personal-data.d.ts +3 -0
  15. package/dist/application/event-sourcing/erased-personal-data.d.ts.map +1 -0
  16. package/dist/application/event-sourcing/erased-personal-data.js +3 -0
  17. package/dist/application/event-sourcing/erased-personal-data.js.map +1 -0
  18. package/dist/application/event-sourcing/event-envelope.d.ts +9 -0
  19. package/dist/application/event-sourcing/event-envelope.d.ts.map +1 -0
  20. package/dist/application/event-sourcing/event-envelope.js +2 -0
  21. package/dist/application/event-sourcing/event-envelope.js.map +1 -0
  22. package/dist/application/event-sourcing/event-to-append.d.ts +15 -0
  23. package/dist/application/event-sourcing/event-to-append.d.ts.map +1 -0
  24. package/dist/application/event-sourcing/event-to-append.js +2 -0
  25. package/dist/application/event-sourcing/event-to-append.js.map +1 -0
  26. package/dist/application/event-sourcing/index.d.ts +21 -0
  27. package/dist/application/event-sourcing/index.d.ts.map +1 -0
  28. package/dist/application/event-sourcing/index.js +21 -0
  29. package/dist/application/event-sourcing/index.js.map +1 -0
  30. package/dist/application/event-sourcing/is-stored-data.d.ts +5 -0
  31. package/dist/application/event-sourcing/is-stored-data.d.ts.map +1 -0
  32. package/dist/application/event-sourcing/is-stored-data.js +5 -0
  33. package/dist/application/event-sourcing/is-stored-data.js.map +1 -0
  34. package/dist/application/event-sourcing/is-stored-list.d.ts +4 -0
  35. package/dist/application/event-sourcing/is-stored-list.d.ts.map +1 -0
  36. package/dist/application/event-sourcing/is-stored-list.js +5 -0
  37. package/dist/application/event-sourcing/is-stored-list.js.map +1 -0
  38. package/dist/application/event-sourcing/personal-data.d.ts +14 -0
  39. package/dist/application/event-sourcing/personal-data.d.ts.map +1 -0
  40. package/dist/application/event-sourcing/personal-data.js +9 -0
  41. package/dist/application/event-sourcing/personal-data.js.map +1 -0
  42. package/dist/application/event-sourcing/stored-data-of.d.ts +9 -0
  43. package/dist/application/event-sourcing/stored-data-of.d.ts.map +1 -0
  44. package/dist/application/event-sourcing/stored-data-of.js +40 -0
  45. package/dist/application/event-sourcing/stored-data-of.js.map +1 -0
  46. package/dist/application/event-sourcing/stored-data.d.ts +6 -0
  47. package/dist/application/event-sourcing/stored-data.d.ts.map +1 -0
  48. package/dist/application/event-sourcing/stored-data.js +2 -0
  49. package/dist/application/event-sourcing/stored-data.js.map +1 -0
  50. package/dist/application/event-sourcing/stored-event-data.d.ts +25 -0
  51. package/dist/application/event-sourcing/stored-event-data.d.ts.map +1 -0
  52. package/dist/application/event-sourcing/stored-event-data.js +82 -0
  53. package/dist/application/event-sourcing/stored-event-data.js.map +1 -0
  54. package/dist/application/event-sourcing/stored-event-spec.d.ts +20 -0
  55. package/dist/application/event-sourcing/stored-event-spec.d.ts.map +1 -0
  56. package/dist/application/event-sourcing/stored-event-spec.js +2 -0
  57. package/dist/application/event-sourcing/stored-event-spec.js.map +1 -0
  58. package/dist/application/event-sourcing/stored-event-type.d.ts +14 -0
  59. package/dist/application/event-sourcing/stored-event-type.d.ts.map +1 -0
  60. package/dist/application/event-sourcing/stored-event-type.js +2 -0
  61. package/dist/application/event-sourcing/stored-event-type.js.map +1 -0
  62. package/dist/application/event-sourcing/stored-event-types.d.ts +9 -0
  63. package/dist/application/event-sourcing/stored-event-types.d.ts.map +1 -0
  64. package/dist/application/event-sourcing/stored-event-types.js +2 -0
  65. package/dist/application/event-sourcing/stored-event-types.js.map +1 -0
  66. package/dist/application/event-sourcing/stored-event.d.ts +12 -0
  67. package/dist/application/event-sourcing/stored-event.d.ts.map +1 -0
  68. package/dist/application/event-sourcing/stored-event.js +2 -0
  69. package/dist/application/event-sourcing/stored-event.js.map +1 -0
  70. package/dist/application/event-sourcing/stored-json.d.ts +5 -0
  71. package/dist/application/event-sourcing/stored-json.d.ts.map +1 -0
  72. package/dist/application/event-sourcing/stored-json.js +2 -0
  73. package/dist/application/event-sourcing/stored-json.js.map +1 -0
  74. package/dist/application/event-sourcing/stored-snapshot.d.ts +11 -0
  75. package/dist/application/event-sourcing/stored-snapshot.d.ts.map +1 -0
  76. package/dist/application/event-sourcing/stored-snapshot.js +2 -0
  77. package/dist/application/event-sourcing/stored-snapshot.js.map +1 -0
  78. package/dist/application/event-sourcing/subject-key.d.ts +10 -0
  79. package/dist/application/event-sourcing/subject-key.d.ts.map +1 -0
  80. package/dist/application/event-sourcing/subject-key.js +2 -0
  81. package/dist/application/event-sourcing/subject-key.js.map +1 -0
  82. package/dist/application/event-sourcing/unreadable-event-error.d.ts +5 -0
  83. package/dist/application/event-sourcing/unreadable-event-error.d.ts.map +1 -0
  84. package/dist/application/event-sourcing/unreadable-event-error.js +8 -0
  85. package/dist/application/event-sourcing/unreadable-event-error.js.map +1 -0
  86. package/dist/application/event-sourcing/upcaster.d.ts +4 -0
  87. package/dist/application/event-sourcing/upcaster.d.ts.map +1 -0
  88. package/dist/application/event-sourcing/upcaster.js +2 -0
  89. package/dist/application/event-sourcing/upcaster.js.map +1 -0
  90. package/dist/application/persistence/append-changes.d.ts +18 -0
  91. package/dist/application/persistence/append-changes.d.ts.map +1 -0
  92. package/dist/application/persistence/append-changes.js +17 -0
  93. package/dist/application/persistence/append-changes.js.map +1 -0
  94. package/dist/application/ports/checkpoint-store.d.ts +14 -0
  95. package/dist/application/ports/checkpoint-store.d.ts.map +1 -0
  96. package/dist/application/ports/checkpoint-store.js +10 -0
  97. package/dist/application/ports/checkpoint-store.js.map +1 -0
  98. package/dist/application/ports/event-store.d.ts +24 -0
  99. package/dist/application/ports/event-store.d.ts.map +1 -0
  100. package/dist/application/ports/event-store.js +12 -0
  101. package/dist/application/ports/event-store.js.map +1 -0
  102. package/dist/application/ports/snapshot-store.d.ts +8 -0
  103. package/dist/application/ports/snapshot-store.d.ts.map +1 -0
  104. package/dist/application/ports/snapshot-store.js +7 -0
  105. package/dist/application/ports/snapshot-store.js.map +1 -0
  106. package/dist/application/ports/subject-key-store.d.ts +17 -0
  107. package/dist/application/ports/subject-key-store.d.ts.map +1 -0
  108. package/dist/application/ports/subject-key-store.js +13 -0
  109. package/dist/application/ports/subject-key-store.js.map +1 -0
  110. package/dist/declarations/decorators/projection-options.d.ts +5 -0
  111. package/dist/declarations/decorators/projection-options.d.ts.map +1 -0
  112. package/dist/declarations/decorators/projection-options.js +2 -0
  113. package/dist/declarations/decorators/projection-options.js.map +1 -0
  114. package/dist/declarations/decorators/projection.d.ts +4 -0
  115. package/dist/declarations/decorators/projection.d.ts.map +1 -1
  116. package/dist/declarations/decorators/projection.js +16 -8
  117. package/dist/declarations/decorators/projection.js.map +1 -1
  118. package/dist/declarations/model/projection-declaration.d.ts +3 -0
  119. package/dist/declarations/model/projection-declaration.d.ts.map +1 -1
  120. package/dist/declarations/model/projection-feed.d.ts +8 -0
  121. package/dist/declarations/model/projection-feed.d.ts.map +1 -0
  122. package/dist/declarations/model/projection-feed.js +2 -0
  123. package/dist/declarations/model/projection-feed.js.map +1 -0
  124. package/dist/declarations/projection/applying-projection.d.ts +14 -0
  125. package/dist/declarations/projection/applying-projection.d.ts.map +1 -0
  126. package/dist/declarations/projection/applying-projection.js +32 -0
  127. package/dist/declarations/projection/applying-projection.js.map +1 -0
  128. package/dist/declarations.d.ts +3 -0
  129. package/dist/declarations.d.ts.map +1 -1
  130. package/dist/declarations.js +1 -0
  131. package/dist/declarations.js.map +1 -1
  132. package/dist/domain/event-sourcing/aggregate-history.d.ts +10 -0
  133. package/dist/domain/event-sourcing/aggregate-history.d.ts.map +1 -0
  134. package/dist/domain/event-sourcing/aggregate-history.js +2 -0
  135. package/dist/domain/event-sourcing/aggregate-history.js.map +1 -0
  136. package/dist/domain/event-sourcing/aggregate-snapshot.d.ts +6 -0
  137. package/dist/domain/event-sourcing/aggregate-snapshot.d.ts.map +1 -0
  138. package/dist/domain/event-sourcing/aggregate-snapshot.js +2 -0
  139. package/dist/domain/event-sourcing/aggregate-snapshot.js.map +1 -0
  140. package/dist/domain/event-sourcing/appliers.d.ts +12 -0
  141. package/dist/domain/event-sourcing/appliers.d.ts.map +1 -0
  142. package/dist/domain/event-sourcing/appliers.js +2 -0
  143. package/dist/domain/event-sourcing/appliers.js.map +1 -0
  144. package/dist/domain/event-sourcing/event-sourced-aggregate.d.ts +28 -0
  145. package/dist/domain/event-sourcing/event-sourced-aggregate.d.ts.map +1 -0
  146. package/dist/domain/event-sourcing/event-sourced-aggregate.js +51 -0
  147. package/dist/domain/event-sourcing/event-sourced-aggregate.js.map +1 -0
  148. package/dist/domain/event-sourcing/unstored-events.d.ts +8 -0
  149. package/dist/domain/event-sourcing/unstored-events.d.ts.map +1 -0
  150. package/dist/domain/event-sourcing/unstored-events.js +7 -0
  151. package/dist/domain/event-sourcing/unstored-events.js.map +1 -0
  152. package/dist/index.d.ts +32 -32
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.js +32 -32
  155. package/dist/index.js.map +1 -1
  156. package/dist/infrastructure/event-sourcing/catch-up-subscription.d.ts +33 -0
  157. package/dist/infrastructure/event-sourcing/catch-up-subscription.d.ts.map +1 -0
  158. package/dist/infrastructure/event-sourcing/catch-up-subscription.js +39 -0
  159. package/dist/infrastructure/event-sourcing/catch-up-subscription.js.map +1 -0
  160. package/dist/infrastructure/event-sourcing/event-serializer.d.ts +35 -0
  161. package/dist/infrastructure/event-sourcing/event-serializer.d.ts.map +1 -0
  162. package/dist/infrastructure/event-sourcing/event-serializer.js +104 -0
  163. package/dist/infrastructure/event-sourcing/event-serializer.js.map +1 -0
  164. package/dist/infrastructure/event-sourcing/event-sourced-repository.d.ts +32 -0
  165. package/dist/infrastructure/event-sourcing/event-sourced-repository.d.ts.map +1 -0
  166. package/dist/infrastructure/event-sourcing/event-sourced-repository.js +68 -0
  167. package/dist/infrastructure/event-sourcing/event-sourced-repository.js.map +1 -0
  168. package/dist/infrastructure/event-sourcing/event-sourcing-stores.d.ts +12 -0
  169. package/dist/infrastructure/event-sourcing/event-sourcing-stores.d.ts.map +1 -0
  170. package/dist/infrastructure/event-sourcing/event-sourcing-stores.js +2 -0
  171. package/dist/infrastructure/event-sourcing/event-sourcing-stores.js.map +1 -0
  172. package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.d.ts +34 -0
  173. package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.d.ts.map +1 -0
  174. package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.js +48 -0
  175. package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.js.map +1 -0
  176. package/dist/infrastructure/event-sourcing/personal-data-cipher.d.ts +19 -0
  177. package/dist/infrastructure/event-sourcing/personal-data-cipher.d.ts.map +1 -0
  178. package/dist/infrastructure/event-sourcing/personal-data-cipher.js +84 -0
  179. package/dist/infrastructure/event-sourcing/personal-data-cipher.js.map +1 -0
  180. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.d.ts +6 -0
  181. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.d.ts.map +1 -0
  182. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.js +2 -0
  183. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.js.map +1 -0
  184. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.d.ts +9 -0
  185. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.d.ts.map +1 -0
  186. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.js +32 -0
  187. package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.js.map +1 -0
  188. package/dist/infrastructure/event-sourcing/postgres/event-store-tables.d.ts +9 -0
  189. package/dist/infrastructure/event-sourcing/postgres/event-store-tables.d.ts.map +1 -0
  190. package/dist/infrastructure/event-sourcing/postgres/event-store-tables.js +9 -0
  191. package/dist/infrastructure/event-sourcing/postgres/event-store-tables.js.map +1 -0
  192. package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.d.ts +3 -0
  193. package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.d.ts.map +1 -0
  194. package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.js +22 -0
  195. package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.js.map +1 -0
  196. package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.d.ts +12 -0
  197. package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.d.ts.map +1 -0
  198. package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.js +26 -0
  199. package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.js.map +1 -0
  200. package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.d.ts +6 -0
  201. package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.d.ts.map +1 -0
  202. package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.js +14 -0
  203. package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.js.map +1 -0
  204. package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.d.ts +31 -0
  205. package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.d.ts.map +1 -0
  206. package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.js +120 -0
  207. package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.js.map +1 -0
  208. package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.d.ts +13 -0
  209. package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.d.ts.map +1 -0
  210. package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.js +28 -0
  211. package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.js.map +1 -0
  212. package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.d.ts +21 -0
  213. package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.d.ts.map +1 -0
  214. package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.js +48 -0
  215. package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.js.map +1 -0
  216. package/dist/infrastructure/event-sourcing/postgres/qualified-table.d.ts +4 -0
  217. package/dist/infrastructure/event-sourcing/postgres/qualified-table.d.ts.map +1 -0
  218. package/dist/infrastructure/event-sourcing/postgres/qualified-table.js +10 -0
  219. package/dist/infrastructure/event-sourcing/postgres/qualified-table.js.map +1 -0
  220. package/dist/infrastructure/event-sourcing/postgres/stored-data-from.d.ts +4 -0
  221. package/dist/infrastructure/event-sourcing/postgres/stored-data-from.d.ts.map +1 -0
  222. package/dist/infrastructure/event-sourcing/postgres/stored-data-from.js +23 -0
  223. package/dist/infrastructure/event-sourcing/postgres/stored-data-from.js.map +1 -0
  224. package/dist/infrastructure/event-sourcing/rewrite-objects.d.ts +8 -0
  225. package/dist/infrastructure/event-sourcing/rewrite-objects.d.ts.map +1 -0
  226. package/dist/infrastructure/event-sourcing/rewrite-objects.js +16 -0
  227. package/dist/infrastructure/event-sourcing/rewrite-objects.js.map +1 -0
  228. package/dist/infrastructure/event-sourcing/snapshot-policy.d.ts +14 -0
  229. package/dist/infrastructure/event-sourcing/snapshot-policy.d.ts.map +1 -0
  230. package/dist/infrastructure/event-sourcing/snapshot-policy.js +2 -0
  231. package/dist/infrastructure/event-sourcing/snapshot-policy.js.map +1 -0
  232. package/dist/infrastructure/event-sourcing/stored-origins.d.ts +5 -0
  233. package/dist/infrastructure/event-sourcing/stored-origins.d.ts.map +1 -0
  234. package/dist/infrastructure/event-sourcing/stored-origins.js +3 -0
  235. package/dist/infrastructure/event-sourcing/stored-origins.js.map +1 -0
  236. package/dist/infrastructure/event-sourcing/stored-stamp-of.d.ts +10 -0
  237. package/dist/infrastructure/event-sourcing/stored-stamp-of.d.ts.map +1 -0
  238. package/dist/infrastructure/event-sourcing/stored-stamp-of.js +14 -0
  239. package/dist/infrastructure/event-sourcing/stored-stamp-of.js.map +1 -0
  240. package/dist/infrastructure/in-memory/in-memory-checkpoint-store.d.ts +8 -0
  241. package/dist/infrastructure/in-memory/in-memory-checkpoint-store.d.ts.map +1 -0
  242. package/dist/infrastructure/in-memory/in-memory-checkpoint-store.js +15 -0
  243. package/dist/infrastructure/in-memory/in-memory-checkpoint-store.js.map +1 -0
  244. package/dist/infrastructure/in-memory/in-memory-event-store.d.ts +14 -0
  245. package/dist/infrastructure/in-memory/in-memory-event-store.d.ts.map +1 -0
  246. package/dist/infrastructure/in-memory/in-memory-event-store.js +37 -0
  247. package/dist/infrastructure/in-memory/in-memory-event-store.js.map +1 -0
  248. package/dist/infrastructure/in-memory/in-memory-snapshot-store.d.ts +9 -0
  249. package/dist/infrastructure/in-memory/in-memory-snapshot-store.d.ts.map +1 -0
  250. package/dist/infrastructure/in-memory/in-memory-snapshot-store.js +15 -0
  251. package/dist/infrastructure/in-memory/in-memory-snapshot-store.js.map +1 -0
  252. package/dist/infrastructure/in-memory/in-memory-subject-key-store.d.ts +10 -0
  253. package/dist/infrastructure/in-memory/in-memory-subject-key-store.d.ts.map +1 -0
  254. package/dist/infrastructure/in-memory/in-memory-subject-key-store.js +21 -0
  255. package/dist/infrastructure/in-memory/in-memory-subject-key-store.js.map +1 -0
  256. package/dist/infrastructure/read-model/shadow-read-model-store.d.ts +20 -0
  257. package/dist/infrastructure/read-model/shadow-read-model-store.d.ts.map +1 -0
  258. package/dist/infrastructure/read-model/shadow-read-model-store.js +25 -0
  259. package/dist/infrastructure/read-model/shadow-read-model-store.js.map +1 -0
  260. package/package.json +1 -1
package/README.md CHANGED
@@ -1203,8 +1203,10 @@ the fakes, `KnexReadModelStore`, `DrizzleReadModelStore`, `PrismaReadModelStore`
1203
1203
 
1204
1204
  ### Rebuild
1205
1205
 
1206
- The kit has no event store: a read model is rebuilt from the source of truth, the read
1207
- contract the owning context publishes, behind a gateway port that answers stamped rows.
1206
+ A read model fed by events that no event store keeps is rebuilt from the source of truth, the
1207
+ read contract the owning context publishes, behind a gateway port that answers stamped rows. A
1208
+ read model of event-sourced aggregates is rebuilt from the store instead:
1209
+ [Fed by the event store](#fed-by-the-event-store).
1208
1210
 
1209
1211
  ```ts
1210
1212
  await new ProjectionRebuild({ table: appointments.table, source, unitOfWork }).run();
@@ -1239,6 +1241,40 @@ privileges granted on the table by name, row security policies and triggers are
1239
1241
  and are restored by the migration that follows, and the indexes of the copy keep the names
1240
1242
  PostgreSQL derived for them.
1241
1243
 
1244
+ ### Fed by the event store
1245
+
1246
+ A projection of event-sourced aggregates can be fed by the store rather than where the domain
1247
+ events are dispatched: `@Projection('scheduling.attendance-history', { feed: 'event-store' })`.
1248
+ The dispatcher then never calls it (`@ddd-ts-kit/di` registers no handler for it); a catch-up
1249
+ subscription does, under the name of the projection, and the same projection rebuilds its read
1250
+ model from position zero.
1251
+
1252
+ ```ts
1253
+ const apply = applyingProjection(projection, serializer); // the @On methods, by event name
1254
+
1255
+ const subscription = new CatchUpSubscription({ name: 'scheduling.attendance-history', store, checkpoints, unitOfWork, apply });
1256
+
1257
+ await subscription.catchUp(); // or poll() from a job: one batch, one unit of work
1258
+
1259
+ await new EventStoreProjectionRebuild({
1260
+ table: history.table,
1261
+ store,
1262
+ unitOfWork,
1263
+ applierOn: (copy) => applyingProjection(new AttendanceHistoryProjection(copy), serializer),
1264
+ }).run();
1265
+ ```
1266
+
1267
+ | Piece | What it does |
1268
+ |---|---|
1269
+ | `CatchUpSubscription` | Reads the store after the checkpoint of its subscriber (`CheckpointStore`), applies a batch and moves the checkpoint in one unit of work. A failure applies none of the batch; two runs of one subscriber never both move it (`ConcurrencyError`). A new projection starts at zero, so it catches up on the whole history |
1270
+ | `applyingProjection(projection, serializer)` | (`@ddd-ts-kit/kernel/declarations`) hands each stored event an `@On` method applies, read back by the serializer of its aggregate, to that method; passes over the rest of the store |
1271
+ | `storedStampOf(event)` | The stamp of an event read from the store: its id, instant and version in its stream, so the rows of one stream are ordered by the stream, not by clocks. `undefined` for an event that did not come from a store |
1272
+ | `EventStoreProjectionRebuild` | Fills an empty copy of the table by replaying the store from position zero through the projection built over the copy (`ShadowReadModelStore`); then, in one transaction, holds the writers, replays what was appended meanwhile and puts the copy in place of the table. The subscription goes on from its checkpoint; what it applies again is stale against the copy. A failed rebuild leaves the table as it was |
1273
+
1274
+ A projection fed by the store applies the domain events of its context only: an integration
1275
+ event reaches a projection where it is consumed, and `@On(definition)` on such a projection
1276
+ throws when the file loads.
1277
+
1242
1278
  ### Seen from outside
1243
1279
 
1244
1280
  Through the ports that exist. `@ddd-ts-kit/di` counts `projection_events_total` by `context`,
@@ -1248,6 +1284,106 @@ A projection is subscribed as a consumer under its name, so each delivery is one
1248
1284
  <projection>` span, with the calls to its read model below it, and an event buried after its
1249
1285
  retries reaches the error reporter as for any consumer.
1250
1286
 
1287
+ ## Event sourcing
1288
+
1289
+ Chosen per aggregate, never per project: the other aggregates of the context keep their state
1290
+ in tables. When to choose it and what it costs:
1291
+ [docs/concepts/event-sourcing.md](../../docs/concepts/event-sourcing.md).
1292
+
1293
+ ```ts
1294
+ // domain/aggregates/attendance-record.aggregate.ts
1295
+ type AttendanceEvent = AttendanceRecordOpened | NoShowNoted;
1296
+
1297
+ export class AttendanceRecord extends EventSourcedAggregate<AttendanceEvent, AttendanceState> {
1298
+ private state: AttendanceState = { noShows: 0 };
1299
+
1300
+ private constructor(id: string) {
1301
+ super(id);
1302
+ }
1303
+
1304
+ static open(id: string, now: Date): AttendanceRecord {
1305
+ const record = new AttendanceRecord(id);
1306
+
1307
+ record.record(new AttendanceRecordOpened(id, now));
1308
+
1309
+ return record;
1310
+ }
1311
+
1312
+ static rehydrate(id: string, history: AggregateHistory<AttendanceEvent, AttendanceState>): AttendanceRecord {
1313
+ const record = new AttendanceRecord(id);
1314
+
1315
+ return record.replay(history, (state) => record.restore(state));
1316
+ }
1317
+
1318
+ noteNoShow(appointmentId: string, now: Date): void {
1319
+ if (this.state.noShows >= 3) {
1320
+ throw AttendanceRecordError.alreadyBarred(this.id);
1321
+ }
1322
+
1323
+ this.record(new NoShowNoted(this.id, now, appointmentId));
1324
+ }
1325
+
1326
+ protected appliers(): Appliers<AttendanceEvent> {
1327
+ return {
1328
+ [AttendanceRecordOpened.eventName]: () => undefined,
1329
+ [NoShowNoted.eventName]: (event) => this.applyNoShowNoted(event),
1330
+ };
1331
+ }
1332
+
1333
+ private restore(state: AttendanceState): void {
1334
+ this.state = state;
1335
+ }
1336
+
1337
+ private applyNoShowNoted(event: NoShowNoted): void {
1338
+ this.state = { noShows: this.state.noShows + 1 };
1339
+ }
1340
+ }
1341
+ ```
1342
+
1343
+ | Piece | What it does |
1344
+ |---|---|
1345
+ | `EventSourcedAggregate<E, S>` | A command checks its invariants on the state, then `record(event)`: the event is applied through the method `appliers()` names for it, and kept for the save. Only apply methods (and `restore`, for a snapshot) change the state (`event-sourcing/state-in-apply`). `appliers()` must name every event of the union, or it does not compile |
1346
+ | `replay(history, restore?)` | Rebuilds from `{ snapshot?, events }`, through the same apply methods, recording nothing. `version` is the number of events of the stream the aggregate reflects |
1347
+ | `appendChanges(aggregate, append)` | What a repository adapter calls: the events recorded since the load and the version the stream must still have; on success the aggregate is at the new version |
1348
+ | `EventStore` | The port: `append(stream, expectedVersion, events)` (a `ConcurrencyError` when somebody appended first, nothing kept of it), `readStream(stream, after?)`, `readAll(after, limit)` in the order the appends committed, `head()`. `InMemoryEventStore` here; PostgreSQL through every ORM adapter. Held to `eventStoreContract` |
1349
+ | `defineStoredEvent(Event, spec)` | How one event is stored: `version` of its shape, `encode(event): NamedData` (plain data, dates kept as ISO text), `decode(data, envelope)` reading each field by type (`data.text('x')`, `data.instant('at')`, `data.record('amount')`), and `upcasters` from each older version |
1350
+ | `EventSerializer<E>` | Every stored event of one aggregate (`StoredEventTypes<E>`: one entry per event, or it does not compile). A stored event is never rewritten: it is upcast when read. An event of a later shape than the release knows, or a version without upcaster, is an `UnreadableEventError` |
1351
+ | `EventSourcedRepository` | What the repository adapter delegates to: `findById` replays the stream `<category>-<id>` (from the last snapshot), `save` appends in the transaction of the unit of work; the events then leave with the save like any other |
1352
+ | `SnapshotPolicy` | Per aggregate: `every` so many events, a `version` of the shape (another one is ignored, the stream replayed), `encode` and `decode`. `expectSnapshotEquivalence` of `@ddd-ts-kit/testing` proves a snapshot rebuilds the state a full replay does |
1353
+ | `personalData(subject, value)` | Marks a personal value in `encode`. `PersonalDataCipher` over a `SubjectKeyStore` seals it with the key of its data subject (AES-256-GCM); `SubjectKeyStore.erase(subject)` destroys the key, and a replay then reads `ERASED_PERSONAL_DATA` |
1354
+
1355
+ ```ts
1356
+ // infrastructure/persistence/event-store-attendance-record.repository.ts
1357
+ @Repository(AttendanceRecordRepository)
1358
+ export class EventStoreAttendanceRecordRepository implements AttendanceRecordRepository {
1359
+ private readonly streams: EventSourcedRepository<AttendanceRecord, AttendanceEvent, AttendanceState>;
1360
+
1361
+ constructor(store: EventStore, snapshots: SnapshotStore, cipher: PersonalDataCipher) {
1362
+ this.streams = new EventSourcedRepository({
1363
+ store,
1364
+ category: 'scheduling.attendance-record',
1365
+ serializer: new EventSerializer<AttendanceEvent>(attendanceRecordEvents, { cipher }),
1366
+ rehydrate: (id, history) => AttendanceRecord.rehydrate(id, history),
1367
+ snapshots: { store: snapshots, every: 50, version: 1, encode: (record) => record.toState(), decode: stateOf },
1368
+ });
1369
+ }
1370
+
1371
+ findById(id: string): Promise<AttendanceRecord | undefined> {
1372
+ return this.streams.findById(id);
1373
+ }
1374
+
1375
+ save(record: AttendanceRecord): Promise<void> {
1376
+ return this.streams.save(record);
1377
+ }
1378
+ }
1379
+ ```
1380
+
1381
+ **No double write.** The store joins the transaction of the unit of work, and the publisher of
1382
+ the integration events is a handler of the domain events that runs before the commit and
1383
+ writes the outbox: the stream and the outbox records commit together or not at all.
1384
+ `eventStoreUnitOfWorkContract` of `@ddd-ts-kit/testing` proves it for each transactional store:
1385
+ nothing is published for an append rolled back or refused by a concurrency conflict.
1386
+
1251
1387
  ## How to extend
1252
1388
 
1253
1389
  `Session`, `ExecutionContext`, `Actor`, `AuditEntry` and `ErrorReport` each have an empty interface that a project fills by
@@ -0,0 +1,33 @@
1
+ export * from './filter-operator.js';
2
+ export * from './field-value.js';
3
+ export * from './field-of.js';
4
+ export * from './operator-of.js';
5
+ export * from './operand-of.js';
6
+ export * from './filter-node.js';
7
+ export * from './filters.js';
8
+ export * from './criteria.js';
9
+ export * from './field-type.js';
10
+ export * from './field-type-of.js';
11
+ export * from './field-rule.js';
12
+ export * from './field-declaration.js';
13
+ export * from './criteria-limits.js';
14
+ export * from './criteria-declaration.js';
15
+ export * from './criteria-definition.js';
16
+ export * from './criteria-definition-error.js';
17
+ export * from './define-criteria.js';
18
+ export * from './criteria-violation.js';
19
+ export * from './validate-criteria.js';
20
+ export * from './invalid-criteria-error.js';
21
+ export * from './read-scope.js';
22
+ export * from './read-scope-mapping.js';
23
+ export * from './unmapped-read-scope-error.js';
24
+ export * from './scoped-criteria.js';
25
+ export * from './scoped.js';
26
+ export * from './predicate.js';
27
+ export * from './criteria-plan.js';
28
+ export * from './plan-criteria.js';
29
+ export * from './page-of-plan.js';
30
+ export * from './select-rows.js';
31
+ export * from './evaluate-plan.js';
32
+ export * from './evaluate-criteria.js';
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/application/criteria/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,33 @@
1
+ export * from './filter-operator.js';
2
+ export * from './field-value.js';
3
+ export * from './field-of.js';
4
+ export * from './operator-of.js';
5
+ export * from './operand-of.js';
6
+ export * from './filter-node.js';
7
+ export * from './filters.js';
8
+ export * from './criteria.js';
9
+ export * from './field-type.js';
10
+ export * from './field-type-of.js';
11
+ export * from './field-rule.js';
12
+ export * from './field-declaration.js';
13
+ export * from './criteria-limits.js';
14
+ export * from './criteria-declaration.js';
15
+ export * from './criteria-definition.js';
16
+ export * from './criteria-definition-error.js';
17
+ export * from './define-criteria.js';
18
+ export * from './criteria-violation.js';
19
+ export * from './validate-criteria.js';
20
+ export * from './invalid-criteria-error.js';
21
+ export * from './read-scope.js';
22
+ export * from './read-scope-mapping.js';
23
+ export * from './unmapped-read-scope-error.js';
24
+ export * from './scoped-criteria.js';
25
+ export * from './scoped.js';
26
+ export * from './predicate.js';
27
+ export * from './criteria-plan.js';
28
+ export * from './plan-criteria.js';
29
+ export * from './page-of-plan.js';
30
+ export * from './select-rows.js';
31
+ export * from './evaluate-plan.js';
32
+ export * from './evaluate-criteria.js';
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/application/criteria/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /** Where an append left its stream and the store. */
2
+ export interface Appended {
3
+ /** The version of the stream after the append. */
4
+ readonly version: number;
5
+ /** The position of the last event appended; the position of the store when nothing was. */
6
+ readonly position: number;
7
+ }
8
+ //# sourceMappingURL=appended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appended.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/appended.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=appended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appended.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/appended.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { DomainEvent } from '../../domain/domain-event.js';
2
+ import type { DomainEventType } from '../../declarations/model/domain-event-type.js';
3
+ import type { StoredEventSpec } from './stored-event-spec.js';
4
+ import type { StoredEventType } from './stored-event-type.js';
5
+ /**
6
+ * Declares how an event of `type` is stored, in the event codec of its aggregate (infrastructure):
7
+ * `defineStoredEvent(NoShowNoted, { version: 1, encode: (event): NoShowNotedData => ({ ... }), decode: ... })`.
8
+ */
9
+ export declare function defineStoredEvent<E extends DomainEvent, Data extends object>(type: DomainEventType<E>, spec: StoredEventSpec<E, Data>): StoredEventType<E>;
10
+ //# sourceMappingURL=define-stored-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-stored-event.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/define-stored-event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AAErF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,SAAS,MAAM,EAC1E,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,GAC7B,eAAe,CAAC,CAAC,CAAC,CAiBpB"}
@@ -0,0 +1,22 @@
1
+ import { storedDataOf } from './stored-data-of.js';
2
+ /**
3
+ * Declares how an event of `type` is stored, in the event codec of its aggregate (infrastructure):
4
+ * `defineStoredEvent(NoShowNoted, { version: 1, encode: (event): NoShowNotedData => ({ ... }), decode: ... })`.
5
+ */
6
+ export function defineStoredEvent(type, spec) {
7
+ if (!Number.isInteger(spec.version) || spec.version < 1) {
8
+ throw new TypeError(`The stored version of ${type.name} is a whole number from 1, not ${spec.version}`);
9
+ }
10
+ return {
11
+ version: spec.version,
12
+ upcasters: spec.upcasters ?? {},
13
+ encode: (event) => {
14
+ if (!(event instanceof type)) {
15
+ throw new TypeError(`"${event.name}" is declared as a ${type.name} and was recorded as another class`);
16
+ }
17
+ return storedDataOf(spec.encode(event));
18
+ },
19
+ decode: (data, envelope) => spec.decode(data, envelope),
20
+ };
21
+ }
22
+ //# sourceMappingURL=define-stored-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-stored-event.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/define-stored-event.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAwB,EACxB,IAA8B;IAE9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,SAAS,CAAC,yBAAyB,IAAI,CAAC,IAAI,kCAAkC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1G,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;QAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAChB,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,sBAAsB,IAAI,CAAC,IAAI,oCAAoC,CAAC,CAAC;YACzG,CAAC;YAED,OAAO,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;KACxD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** What a replay reads in place of a personal value whose data subject was erased: the key that sealed it is gone. */
2
+ export declare const ERASED_PERSONAL_DATA = "[erased]";
3
+ //# sourceMappingURL=erased-personal-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"erased-personal-data.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/erased-personal-data.ts"],"names":[],"mappings":"AAAA,sHAAsH;AACtH,eAAO,MAAM,oBAAoB,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** What a replay reads in place of a personal value whose data subject was erased: the key that sealed it is gone. */
2
+ export const ERASED_PERSONAL_DATA = '[erased]';
3
+ //# sourceMappingURL=erased-personal-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"erased-personal-data.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/erased-personal-data.ts"],"names":[],"mappings":"AAAA,sHAAsH;AACtH,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** What a stored event says besides its data, handed to `decode` to build the domain event back. */
2
+ export interface EventEnvelope {
3
+ readonly id: string;
4
+ readonly aggregateId: string;
5
+ readonly occurredAt: Date;
6
+ /** Its rank in its stream. */
7
+ readonly version: number;
8
+ }
9
+ //# sourceMappingURL=event-envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-envelope.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/event-envelope.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event-envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-envelope.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/event-envelope.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import type { StoredData } from './stored-data.js';
2
+ /** An event as the store is handed it: serialized, not yet placed in its stream. */
3
+ export interface EventToAppend {
4
+ /** Unique in the store. */
5
+ readonly id: string;
6
+ /** The name the domain event carries, `<context>.<aggregate>.<fact>`. */
7
+ readonly type: string;
8
+ /** The version of the shape of `data`; a stored event is never rewritten, it is upcast when read. */
9
+ readonly schemaVersion: number;
10
+ readonly data: StoredData;
11
+ /** What is not the fact itself: correlation, causation, actor. */
12
+ readonly metadata?: StoredData;
13
+ readonly occurredAt: Date;
14
+ }
15
+ //# sourceMappingURL=event-to-append.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-to-append.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/event-to-append.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qGAAqG;IACrG,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event-to-append.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-to-append.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/event-to-append.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ export * from './appended.js';
2
+ export * from './define-stored-event.js';
3
+ export * from './erased-personal-data.js';
4
+ export * from './event-envelope.js';
5
+ export * from './event-to-append.js';
6
+ export * from './is-stored-data.js';
7
+ export * from './is-stored-list.js';
8
+ export * from './personal-data.js';
9
+ export * from './stored-data-of.js';
10
+ export * from './stored-data.js';
11
+ export * from './stored-event-data.js';
12
+ export * from './stored-event-spec.js';
13
+ export * from './stored-event-type.js';
14
+ export * from './stored-event-types.js';
15
+ export * from './stored-event.js';
16
+ export * from './stored-json.js';
17
+ export * from './stored-snapshot.js';
18
+ export * from './subject-key.js';
19
+ export * from './unreadable-event-error.js';
20
+ export * from './upcaster.js';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC"}
@@ -0,0 +1,21 @@
1
+ export * from './appended.js';
2
+ export * from './define-stored-event.js';
3
+ export * from './erased-personal-data.js';
4
+ export * from './event-envelope.js';
5
+ export * from './event-to-append.js';
6
+ export * from './is-stored-data.js';
7
+ export * from './is-stored-list.js';
8
+ export * from './personal-data.js';
9
+ export * from './stored-data-of.js';
10
+ export * from './stored-data.js';
11
+ export * from './stored-event-data.js';
12
+ export * from './stored-event-spec.js';
13
+ export * from './stored-event-type.js';
14
+ export * from './stored-event-types.js';
15
+ export * from './stored-event.js';
16
+ export * from './stored-json.js';
17
+ export * from './stored-snapshot.js';
18
+ export * from './subject-key.js';
19
+ export * from './unreadable-event-error.js';
20
+ export * from './upcaster.js';
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { StoredData } from './stored-data.js';
2
+ import type { StoredJson } from './stored-json.js';
3
+ /** Whether a stored value is an object, not a list nor a scalar. */
4
+ export declare function isStoredData(value: StoredJson | undefined): value is StoredData;
5
+ //# sourceMappingURL=is-stored-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-stored-data.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/is-stored-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,KAAK,IAAI,UAAU,CAE/E"}
@@ -0,0 +1,5 @@
1
+ /** Whether a stored value is an object, not a list nor a scalar. */
2
+ export function isStoredData(value) {
3
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
4
+ }
5
+ //# sourceMappingURL=is-stored-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-stored-data.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/is-stored-data.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,KAA6B;IACxD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { StoredJson } from './stored-json.js';
2
+ /** Whether a stored value is a list. */
3
+ export declare function isStoredList(value: StoredJson | undefined): value is readonly StoredJson[];
4
+ //# sourceMappingURL=is-stored-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-stored-list.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/is-stored-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,KAAK,IAAI,SAAS,UAAU,EAAE,CAE1F"}
@@ -0,0 +1,5 @@
1
+ /** Whether a stored value is a list. */
2
+ export function isStoredList(value) {
3
+ return Array.isArray(value);
4
+ }
5
+ //# sourceMappingURL=is-stored-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-stored-list.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/is-stored-list.ts"],"names":[],"mappings":"AAEA,wCAAwC;AACxC,MAAM,UAAU,YAAY,CAAC,KAA6B;IACxD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,14 @@
1
+ /** A personal value in the data `encode` answers, until the serializer seals it. */
2
+ export interface PersonalValue {
3
+ readonly $personal: {
4
+ readonly subject: string;
5
+ readonly value: string;
6
+ };
7
+ }
8
+ /**
9
+ * Marks a personal value of the data of a stored event, in `encode`: `note: personalData(patientId, note)`.
10
+ * The serializer seals it with the key of its data subject before it reaches the store, and opens
11
+ * it when the event is read; once the subject is erased, the read gives `ERASED_PERSONAL_DATA`.
12
+ */
13
+ export declare function personalData(subject: string, value: string): PersonalValue;
14
+ //# sourceMappingURL=personal-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personal-data.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/personal-data.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAE1E"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Marks a personal value of the data of a stored event, in `encode`: `note: personalData(patientId, note)`.
3
+ * The serializer seals it with the key of its data subject before it reaches the store, and opens
4
+ * it when the event is read; once the subject is erased, the read gives `ERASED_PERSONAL_DATA`.
5
+ */
6
+ export function personalData(subject, value) {
7
+ return { $personal: { subject, value } };
8
+ }
9
+ //# sourceMappingURL=personal-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personal-data.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/personal-data.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,KAAa;IACzD,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { StoredData } from './stored-data.js';
2
+ /**
3
+ * The JSON an event store keeps for what `encode` answered: a date becomes its ISO text, a field
4
+ * holding `undefined` is left out. Anything else that is not plain data (a class instance, a
5
+ * function, a number that is not finite) is refused with a TypeError: encode maps value objects
6
+ * to their fields, the store never guesses.
7
+ */
8
+ export declare function storedDataOf(value: object): StoredData;
9
+ //# sourceMappingURL=stored-data-of.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-data-of.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/stored-data-of.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAQtD"}
@@ -0,0 +1,40 @@
1
+ import { isStoredData } from './is-stored-data.js';
2
+ /**
3
+ * The JSON an event store keeps for what `encode` answered: a date becomes its ISO text, a field
4
+ * holding `undefined` is left out. Anything else that is not plain data (a class instance, a
5
+ * function, a number that is not finite) is refused with a TypeError: encode maps value objects
6
+ * to their fields, the store never guesses.
7
+ */
8
+ export function storedDataOf(value) {
9
+ const json = jsonOf(value, 'data');
10
+ if (!isStoredData(json)) {
11
+ throw new TypeError('The data of a stored event is an object');
12
+ }
13
+ return json;
14
+ }
15
+ function jsonOf(value, path) {
16
+ if (value === null || typeof value === 'string' || typeof value === 'boolean') {
17
+ return value;
18
+ }
19
+ if (typeof value === 'number' && Number.isFinite(value)) {
20
+ return value;
21
+ }
22
+ if (value instanceof Date) {
23
+ return value.toISOString();
24
+ }
25
+ if (Array.isArray(value)) {
26
+ return value.map((item, index) => jsonOf(item, `${path}[${index}]`));
27
+ }
28
+ if (isPlainObject(value)) {
29
+ return Object.fromEntries(Object.entries(value).flatMap(([key, field]) => field === undefined ? [] : [[key, jsonOf(field, `${path}.${key}`)]]));
30
+ }
31
+ throw new TypeError(`${path} is not plain data: map it to strings, numbers, booleans, dates, arrays and plain objects`);
32
+ }
33
+ function isPlainObject(value) {
34
+ if (typeof value !== 'object' || value === null) {
35
+ return false;
36
+ }
37
+ const prototype = Object.getPrototypeOf(value);
38
+ return prototype === Object.prototype || prototype === null;
39
+ }
40
+ //# sourceMappingURL=stored-data-of.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-data-of.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/stored-data-of.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEnC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,MAAM,CAAC,KAAc,EAAE,IAAY;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAa,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAoB,EAAE,EAAE,CAChE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CACpE,CACF,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,SAAS,CACjB,GAAG,IAAI,2FAA2F,CACnG,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAY,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAExD,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { StoredJson } from './stored-json.js';
2
+ /** The data of a stored event or snapshot: a JSON object. */
3
+ export type StoredData = {
4
+ readonly [key: string]: StoredJson;
5
+ };
6
+ //# sourceMappingURL=stored-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-data.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/stored-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stored-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-data.js","sourceRoot":"","sources":["../../../src/application/event-sourcing/stored-data.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import type { StoredData } from './stored-data.js';
2
+ /**
3
+ * The data of a stored event as `decode` reads it. Each read names the field and the type it
4
+ * expects, and refuses a field that is absent or of another type with an UnreadableEventError:
5
+ * a corrupt row or a forgotten upcaster stops the load instead of building a wrong aggregate.
6
+ */
7
+ export declare class StoredEventData {
8
+ readonly data: StoredData;
9
+ private readonly where;
10
+ constructor(data: StoredData, where: string);
11
+ text(field: string): string;
12
+ optionalText(field: string): string | undefined;
13
+ number(field: string): number;
14
+ flag(field: string): boolean;
15
+ /** A date, kept as its ISO text. */
16
+ instant(field: string): Date;
17
+ optionalInstant(field: string): Date | undefined;
18
+ texts(field: string): string[];
19
+ record(field: string): StoredEventData;
20
+ records(field: string): StoredEventData[];
21
+ private list;
22
+ private nested;
23
+ private unreadable;
24
+ }
25
+ //# sourceMappingURL=stored-event-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-event-data.d.ts","sourceRoot":"","sources":["../../../src/application/event-sourcing/stored-event-data.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD;;;;GAIG;AACH,qBAAa,eAAe;IAExB,QAAQ,CAAC,IAAI,EAAE,UAAU;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFxB,YACW,IAAI,EAAE,UAAU,EACR,KAAK,EAAE,MAAM,EAC5B;IAEJ,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ1B;IAED,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9C;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ5B;IAED,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQ3B;IAED,oCAAoC;IACpC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ3B;IAED,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE/C;IAED,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ7B;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAErC;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAExC;IAED,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,UAAU;CAGnB"}