@cqrs-ddd/core 0.2.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 (212) hide show
  1. package/COMMERCIAL_LICENSE.txt +34 -0
  2. package/LICENSE +661 -0
  3. package/README.md +707 -0
  4. package/dist/application/base.command.d.ts +44 -0
  5. package/dist/application/base.command.d.ts.map +1 -0
  6. package/dist/application/base.command.js +58 -0
  7. package/dist/application/base.command.js.map +1 -0
  8. package/dist/application/base.query.d.ts +42 -0
  9. package/dist/application/base.query.d.ts.map +1 -0
  10. package/dist/application/base.query.js +52 -0
  11. package/dist/application/base.query.js.map +1 -0
  12. package/dist/application/command-base.handler.d.ts +106 -0
  13. package/dist/application/command-base.handler.d.ts.map +1 -0
  14. package/dist/application/command-base.handler.js +119 -0
  15. package/dist/application/command-base.handler.js.map +1 -0
  16. package/dist/application/index.d.ts +16 -0
  17. package/dist/application/index.d.ts.map +1 -0
  18. package/dist/application/index.js +33 -0
  19. package/dist/application/index.js.map +1 -0
  20. package/dist/application/ports/cache.port.d.ts +104 -0
  21. package/dist/application/ports/cache.port.d.ts.map +1 -0
  22. package/dist/application/ports/cache.port.js +17 -0
  23. package/dist/application/ports/cache.port.js.map +1 -0
  24. package/dist/application/ports/command-repository.port.d.ts +28 -0
  25. package/dist/application/ports/command-repository.port.d.ts.map +1 -0
  26. package/dist/application/ports/command-repository.port.js +4 -0
  27. package/dist/application/ports/command-repository.port.js.map +1 -0
  28. package/dist/application/ports/domain-event-publisher.port.d.ts +18 -0
  29. package/dist/application/ports/domain-event-publisher.port.d.ts.map +1 -0
  30. package/dist/application/ports/domain-event-publisher.port.js +4 -0
  31. package/dist/application/ports/domain-event-publisher.port.js.map +1 -0
  32. package/dist/application/ports/query-repository.port.d.ts +26 -0
  33. package/dist/application/ports/query-repository.port.d.ts.map +1 -0
  34. package/dist/application/ports/query-repository.port.js +4 -0
  35. package/dist/application/ports/query-repository.port.js.map +1 -0
  36. package/dist/application/ports/write-side-aggregate-repository.port.d.ts +33 -0
  37. package/dist/application/ports/write-side-aggregate-repository.port.d.ts.map +1 -0
  38. package/dist/application/ports/write-side-aggregate-repository.port.js +4 -0
  39. package/dist/application/ports/write-side-aggregate-repository.port.js.map +1 -0
  40. package/dist/application/query.options.d.ts +22 -0
  41. package/dist/application/query.options.d.ts.map +1 -0
  42. package/dist/application/query.options.js +4 -0
  43. package/dist/application/query.options.js.map +1 -0
  44. package/dist/application/request-fields.helper.d.ts +5 -0
  45. package/dist/application/request-fields.helper.d.ts.map +1 -0
  46. package/dist/application/request-fields.helper.js +20 -0
  47. package/dist/application/request-fields.helper.js.map +1 -0
  48. package/dist/application/tenant-resolver.d.ts +56 -0
  49. package/dist/application/tenant-resolver.d.ts.map +1 -0
  50. package/dist/application/tenant-resolver.js +60 -0
  51. package/dist/application/tenant-resolver.js.map +1 -0
  52. package/dist/domain/decorators/apply-mutation.decorator.d.ts +64 -0
  53. package/dist/domain/decorators/apply-mutation.decorator.d.ts.map +1 -0
  54. package/dist/domain/decorators/apply-mutation.decorator.js +86 -0
  55. package/dist/domain/decorators/apply-mutation.decorator.js.map +1 -0
  56. package/dist/domain/decorators/mutable.decorator.d.ts +54 -0
  57. package/dist/domain/decorators/mutable.decorator.d.ts.map +1 -0
  58. package/dist/domain/decorators/mutable.decorator.js +76 -0
  59. package/dist/domain/decorators/mutable.decorator.js.map +1 -0
  60. package/dist/domain/events/domain.event.d.ts +13 -0
  61. package/dist/domain/events/domain.event.d.ts.map +1 -0
  62. package/dist/domain/events/domain.event.js +20 -0
  63. package/dist/domain/events/domain.event.js.map +1 -0
  64. package/dist/domain/events/event.interface.d.ts +9 -0
  65. package/dist/domain/events/event.interface.d.ts.map +1 -0
  66. package/dist/domain/events/event.interface.js +4 -0
  67. package/dist/domain/events/event.interface.js.map +1 -0
  68. package/dist/domain/events/root-domain.event.d.ts +50 -0
  69. package/dist/domain/events/root-domain.event.d.ts.map +1 -0
  70. package/dist/domain/events/root-domain.event.js +156 -0
  71. package/dist/domain/events/root-domain.event.js.map +1 -0
  72. package/dist/domain/exceptions/concurrency-conflict.error.d.ts +20 -0
  73. package/dist/domain/exceptions/concurrency-conflict.error.d.ts.map +1 -0
  74. package/dist/domain/exceptions/concurrency-conflict.error.js +32 -0
  75. package/dist/domain/exceptions/concurrency-conflict.error.js.map +1 -0
  76. package/dist/domain/exceptions/domain.exception.d.ts +30 -0
  77. package/dist/domain/exceptions/domain.exception.d.ts.map +1 -0
  78. package/dist/domain/exceptions/domain.exception.js +39 -0
  79. package/dist/domain/exceptions/domain.exception.js.map +1 -0
  80. package/dist/domain/exceptions/entity-not-found.exception.d.ts +14 -0
  81. package/dist/domain/exceptions/entity-not-found.exception.d.ts.map +1 -0
  82. package/dist/domain/exceptions/entity-not-found.exception.js +23 -0
  83. package/dist/domain/exceptions/entity-not-found.exception.js.map +1 -0
  84. package/dist/domain/exceptions/invalid-value.exception.d.ts +35 -0
  85. package/dist/domain/exceptions/invalid-value.exception.d.ts.map +1 -0
  86. package/dist/domain/exceptions/invalid-value.exception.js +67 -0
  87. package/dist/domain/exceptions/invalid-value.exception.js.map +1 -0
  88. package/dist/domain/exceptions/missing-tenant-context.exception.d.ts +24 -0
  89. package/dist/domain/exceptions/missing-tenant-context.exception.d.ts.map +1 -0
  90. package/dist/domain/exceptions/missing-tenant-context.exception.js +33 -0
  91. package/dist/domain/exceptions/missing-tenant-context.exception.js.map +1 -0
  92. package/dist/domain/exceptions/transient-operation.error.d.ts +17 -0
  93. package/dist/domain/exceptions/transient-operation.error.d.ts.map +1 -0
  94. package/dist/domain/exceptions/transient-operation.error.js +27 -0
  95. package/dist/domain/exceptions/transient-operation.error.js.map +1 -0
  96. package/dist/domain/exceptions/unknown-mutable-field.error.d.ts +14 -0
  97. package/dist/domain/exceptions/unknown-mutable-field.error.d.ts.map +1 -0
  98. package/dist/domain/exceptions/unknown-mutable-field.error.js +24 -0
  99. package/dist/domain/exceptions/unknown-mutable-field.error.js.map +1 -0
  100. package/dist/domain/index.d.ts +26 -0
  101. package/dist/domain/index.d.ts.map +1 -0
  102. package/dist/domain/index.js +43 -0
  103. package/dist/domain/index.js.map +1 -0
  104. package/dist/domain/interfaces/root-entity-snapshot.interface.d.ts +7 -0
  105. package/dist/domain/interfaces/root-entity-snapshot.interface.d.ts.map +1 -0
  106. package/dist/domain/interfaces/root-entity-snapshot.interface.js +4 -0
  107. package/dist/domain/interfaces/root-entity-snapshot.interface.js.map +1 -0
  108. package/dist/domain/models/aggregate-root.d.ts +87 -0
  109. package/dist/domain/models/aggregate-root.d.ts.map +1 -0
  110. package/dist/domain/models/aggregate-root.js +122 -0
  111. package/dist/domain/models/aggregate-root.js.map +1 -0
  112. package/dist/domain/models/root.entity.d.ts +208 -0
  113. package/dist/domain/models/root.entity.d.ts.map +1 -0
  114. package/dist/domain/models/root.entity.js +350 -0
  115. package/dist/domain/models/root.entity.js.map +1 -0
  116. package/dist/domain/rules/number.rule.d.ts +81 -0
  117. package/dist/domain/rules/number.rule.d.ts.map +1 -0
  118. package/dist/domain/rules/number.rule.js +81 -0
  119. package/dist/domain/rules/number.rule.js.map +1 -0
  120. package/dist/domain/rules/rule-support.d.ts +6 -0
  121. package/dist/domain/rules/rule-support.d.ts.map +1 -0
  122. package/dist/domain/rules/rule-support.js +19 -0
  123. package/dist/domain/rules/rule-support.js.map +1 -0
  124. package/dist/domain/rules/text.rule.d.ts +98 -0
  125. package/dist/domain/rules/text.rule.d.ts.map +1 -0
  126. package/dist/domain/rules/text.rule.js +103 -0
  127. package/dist/domain/rules/text.rule.js.map +1 -0
  128. package/dist/domain/rules/value-violation.d.ts +44 -0
  129. package/dist/domain/rules/value-violation.d.ts.map +1 -0
  130. package/dist/domain/rules/value-violation.js +4 -0
  131. package/dist/domain/rules/value-violation.js.map +1 -0
  132. package/dist/http/domain-error-http-status.d.ts +43 -0
  133. package/dist/http/domain-error-http-status.d.ts.map +1 -0
  134. package/dist/http/domain-error-http-status.js +27 -0
  135. package/dist/http/domain-error-http-status.js.map +1 -0
  136. package/dist/http/index.d.ts +9 -0
  137. package/dist/http/index.d.ts.map +1 -0
  138. package/dist/http/index.js +26 -0
  139. package/dist/http/index.js.map +1 -0
  140. package/dist/index.d.ts +13 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +30 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/persistence/cache/cache-logger.d.ts +29 -0
  145. package/dist/persistence/cache/cache-logger.d.ts.map +1 -0
  146. package/dist/persistence/cache/cache-logger.js +23 -0
  147. package/dist/persistence/cache/cache-logger.js.map +1 -0
  148. package/dist/persistence/cache/memory.cache.d.ts +72 -0
  149. package/dist/persistence/cache/memory.cache.d.ts.map +1 -0
  150. package/dist/persistence/cache/memory.cache.js +183 -0
  151. package/dist/persistence/cache/memory.cache.js.map +1 -0
  152. package/dist/persistence/command-repository.abstract.d.ts +39 -0
  153. package/dist/persistence/command-repository.abstract.d.ts.map +1 -0
  154. package/dist/persistence/command-repository.abstract.js +43 -0
  155. package/dist/persistence/command-repository.abstract.js.map +1 -0
  156. package/dist/persistence/decorators/acknowledge-persisted.decorator.d.ts +82 -0
  157. package/dist/persistence/decorators/acknowledge-persisted.decorator.d.ts.map +1 -0
  158. package/dist/persistence/decorators/acknowledge-persisted.decorator.js +82 -0
  159. package/dist/persistence/decorators/acknowledge-persisted.decorator.js.map +1 -0
  160. package/dist/persistence/decorators/cache.decorator.d.ts +93 -0
  161. package/dist/persistence/decorators/cache.decorator.d.ts.map +1 -0
  162. package/dist/persistence/decorators/cache.decorator.js +200 -0
  163. package/dist/persistence/decorators/cache.decorator.js.map +1 -0
  164. package/dist/persistence/decorators/from-cache.decorator.d.ts +65 -0
  165. package/dist/persistence/decorators/from-cache.decorator.d.ts.map +1 -0
  166. package/dist/persistence/decorators/from-cache.decorator.js +165 -0
  167. package/dist/persistence/decorators/from-cache.decorator.js.map +1 -0
  168. package/dist/persistence/decorators/map-persistence-errors.decorator.d.ts +88 -0
  169. package/dist/persistence/decorators/map-persistence-errors.decorator.d.ts.map +1 -0
  170. package/dist/persistence/decorators/map-persistence-errors.decorator.js +89 -0
  171. package/dist/persistence/decorators/map-persistence-errors.decorator.js.map +1 -0
  172. package/dist/persistence/decorators/persisted-write.decorator.d.ts +61 -0
  173. package/dist/persistence/decorators/persisted-write.decorator.d.ts.map +1 -0
  174. package/dist/persistence/decorators/persisted-write.decorator.js +57 -0
  175. package/dist/persistence/decorators/persisted-write.decorator.js.map +1 -0
  176. package/dist/persistence/helpers/cache-barrier.helper.d.ts +70 -0
  177. package/dist/persistence/helpers/cache-barrier.helper.d.ts.map +1 -0
  178. package/dist/persistence/helpers/cache-barrier.helper.js +57 -0
  179. package/dist/persistence/helpers/cache-barrier.helper.js.map +1 -0
  180. package/dist/persistence/helpers/cache-key.helper.d.ts +73 -0
  181. package/dist/persistence/helpers/cache-key.helper.d.ts.map +1 -0
  182. package/dist/persistence/helpers/cache-key.helper.js +132 -0
  183. package/dist/persistence/helpers/cache-key.helper.js.map +1 -0
  184. package/dist/persistence/helpers/cache-owner.helper.d.ts +9 -0
  185. package/dist/persistence/helpers/cache-owner.helper.d.ts.map +1 -0
  186. package/dist/persistence/helpers/cache-owner.helper.js +22 -0
  187. package/dist/persistence/helpers/cache-owner.helper.js.map +1 -0
  188. package/dist/persistence/helpers/cache-snapshot.helper.d.ts +28 -0
  189. package/dist/persistence/helpers/cache-snapshot.helper.d.ts.map +1 -0
  190. package/dist/persistence/helpers/cache-snapshot.helper.js +42 -0
  191. package/dist/persistence/helpers/cache-snapshot.helper.js.map +1 -0
  192. package/dist/persistence/helpers/cache-version.helper.d.ts +29 -0
  193. package/dist/persistence/helpers/cache-version.helper.d.ts.map +1 -0
  194. package/dist/persistence/helpers/cache-version.helper.js +71 -0
  195. package/dist/persistence/helpers/cache-version.helper.js.map +1 -0
  196. package/dist/persistence/index.d.ts +23 -0
  197. package/dist/persistence/index.d.ts.map +1 -0
  198. package/dist/persistence/index.js +40 -0
  199. package/dist/persistence/index.js.map +1 -0
  200. package/dist/persistence/persistence-dialect.d.ts +35 -0
  201. package/dist/persistence/persistence-dialect.d.ts.map +1 -0
  202. package/dist/persistence/persistence-dialect.js +31 -0
  203. package/dist/persistence/persistence-dialect.js.map +1 -0
  204. package/dist/persistence/query-repository.abstract.d.ts +76 -0
  205. package/dist/persistence/query-repository.abstract.d.ts.map +1 -0
  206. package/dist/persistence/query-repository.abstract.js +67 -0
  207. package/dist/persistence/query-repository.abstract.js.map +1 -0
  208. package/dist/types/Method.type.d.ts +2 -0
  209. package/dist/types/Method.type.d.ts.map +1 -0
  210. package/dist/types/Method.type.js +4 -0
  211. package/dist/types/Method.type.js.map +1 -0
  212. package/package.json +80 -0
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.isCacheNewer = isCacheNewer;
5
+ const cache_barrier_helper_1 = require("./cache-barrier.helper");
6
+ /**
7
+ * Checks whether a cached snapshot or record is strictly newer than an incoming
8
+ * record based on explicit version numbers, generation counters, or updatedAt timestamps.
9
+ *
10
+ * Returns `true` only if `cached` is strictly newer than `incoming`.
11
+ * Returns `false` if `incoming` is newer, equal, or if no meaningful ordering can be determined.
12
+ *
13
+ * Comparison precedence:
14
+ * 1. {@link CacheMutationBarrier}: a barrier outranks any snapshot. A cached
15
+ * barrier is newer than an incoming snapshot, an incoming barrier always
16
+ * replaces a cached snapshot, and between two barriers the cached one is
17
+ * newer unless the incoming one has a later `createdAt`.
18
+ * 2. Numeric `version` (optimistic concurrency version)
19
+ * 3. Numeric `__gen` (generation sequence counter)
20
+ * 4. `updatedAt` (Date instance or ISO 8601 string / timestamp)
21
+ *
22
+ * @example Comparing versioned aggregate snapshots
23
+ * ```typescript
24
+ * isCacheNewer({ id: '1', version: 3 }, { id: '1', version: 2 }); // true
25
+ * isCacheNewer({ id: '1', version: 2 }, { id: '1', version: 3 }); // false
26
+ * isCacheNewer({ id: '1', version: 2 }, { id: '1', version: 2 }); // false
27
+ * ```
28
+ *
29
+ * @param cached - The existing data in cache.
30
+ * @param incoming - The incoming data being written or compared.
31
+ * @returns `true` if `cached` is strictly newer than `incoming`, `false` otherwise.
32
+ */
33
+ function isCacheNewer(cached, incoming) {
34
+ if (!cached ||
35
+ typeof cached !== 'object' ||
36
+ !incoming ||
37
+ typeof incoming !== 'object') {
38
+ return false;
39
+ }
40
+ // A barrier records a mutation that has already been durably applied, so it
41
+ // outranks any snapshot: a write-through that started before a concurrent
42
+ // delete must not overwrite it, or the deleted aggregate would reappear in the
43
+ // cache as an ordinary hit.
44
+ if ((0, cache_barrier_helper_1.isCacheMutationBarrier)(cached)) {
45
+ if (!(0, cache_barrier_helper_1.isCacheMutationBarrier)(incoming))
46
+ return true;
47
+ // Between two barriers the later one wins, so a fresh mutation can still
48
+ // supersede an older one.
49
+ return incoming.createdAt <= cached.createdAt;
50
+ }
51
+ // A barrier arriving over a snapshot must always be applied.
52
+ if ((0, cache_barrier_helper_1.isCacheMutationBarrier)(incoming))
53
+ return false;
54
+ const c = cached;
55
+ const inc = incoming;
56
+ if (typeof c.version === 'number' && typeof inc.version === 'number') {
57
+ return c.version > inc.version;
58
+ }
59
+ if (typeof c.__gen === 'number' && typeof inc.__gen === 'number') {
60
+ return c.__gen > inc.__gen;
61
+ }
62
+ if (c.updatedAt !== undefined && inc.updatedAt !== undefined) {
63
+ const cTime = new Date(c.updatedAt).getTime();
64
+ const incTime = new Date(inc.updatedAt).getTime();
65
+ if (!Number.isNaN(cTime) && !Number.isNaN(incTime)) {
66
+ return cTime > incTime;
67
+ }
68
+ }
69
+ return false;
70
+ }
71
+ //# sourceMappingURL=cache-version.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-version.helper.js","sourceRoot":"","sources":["../../../persistence/helpers/cache-version.helper.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AA+BtE,oCA4CC;AAzED,iEAAgE;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAgB,YAAY,CAAC,MAAe,EAAE,QAAiB;IAC7D,IACE,CAAC,MAAM;QACP,OAAO,MAAM,KAAK,QAAQ;QAC1B,CAAC,QAAQ;QACT,OAAO,QAAQ,KAAK,QAAQ,EAC5B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4EAA4E;IAC5E,0EAA0E;IAC1E,+EAA+E;IAC/E,4BAA4B;IAC5B,IAAI,IAAA,6CAAsB,EAAC,MAAM,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,IAAA,6CAAsB,EAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QACnD,yEAAyE;QACzE,0BAA0B;QAC1B,OAAO,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;IAChD,CAAC;IAED,6DAA6D;IAC7D,IAAI,IAAA,6CAAsB,EAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAEnD,MAAM,CAAC,GAAG,MAAiC,CAAC;IAC5C,MAAM,GAAG,GAAG,QAAmC,CAAC;IAEhD,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACrE,OAAO,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IACjC,CAAC;IAED,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACjE,OAAO,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAmC,CAAC,CAAC,OAAO,EAAE,CAAC;QACxE,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAmC,CAAC,CAAC,OAAO,EAAE,CAAC;QAC5E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,GAAG,OAAO,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ORM-neutral persistence building blocks: the repository base classes, the
3
+ * lifecycle decorators, the cache protocol and its in-memory adapter.
4
+ *
5
+ * Repository *ports* are exported from `@cqrs-ddd/core/application`; handlers
6
+ * should import those and leave this entry point to the adapters. ORM adapters
7
+ * live in their own packages, such as `@cqrs-ddd/mikro-orm`.
8
+ */
9
+ export * from './cache/cache-logger';
10
+ export * from './cache/memory.cache';
11
+ export * from './command-repository.abstract';
12
+ export * from './decorators/acknowledge-persisted.decorator';
13
+ export * from './decorators/cache.decorator';
14
+ export * from './decorators/from-cache.decorator';
15
+ export * from './decorators/map-persistence-errors.decorator';
16
+ export * from './decorators/persisted-write.decorator';
17
+ export * from './helpers/cache-barrier.helper';
18
+ export * from './helpers/cache-key.helper';
19
+ export * from './helpers/cache-snapshot.helper';
20
+ export * from './helpers/cache-version.helper';
21
+ export * from './persistence-dialect';
22
+ export * from './query-repository.abstract';
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../persistence/index.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wCAAwC,CAAC;AACvD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ /**
19
+ * ORM-neutral persistence building blocks: the repository base classes, the
20
+ * lifecycle decorators, the cache protocol and its in-memory adapter.
21
+ *
22
+ * Repository *ports* are exported from `@cqrs-ddd/core/application`; handlers
23
+ * should import those and leave this entry point to the adapters. ORM adapters
24
+ * live in their own packages, such as `@cqrs-ddd/mikro-orm`.
25
+ */
26
+ __exportStar(require("./cache/cache-logger"), exports);
27
+ __exportStar(require("./cache/memory.cache"), exports);
28
+ __exportStar(require("./command-repository.abstract"), exports);
29
+ __exportStar(require("./decorators/acknowledge-persisted.decorator"), exports);
30
+ __exportStar(require("./decorators/cache.decorator"), exports);
31
+ __exportStar(require("./decorators/from-cache.decorator"), exports);
32
+ __exportStar(require("./decorators/map-persistence-errors.decorator"), exports);
33
+ __exportStar(require("./decorators/persisted-write.decorator"), exports);
34
+ __exportStar(require("./helpers/cache-barrier.helper"), exports);
35
+ __exportStar(require("./helpers/cache-key.helper"), exports);
36
+ __exportStar(require("./helpers/cache-snapshot.helper"), exports);
37
+ __exportStar(require("./helpers/cache-version.helper"), exports);
38
+ __exportStar(require("./persistence-dialect"), exports);
39
+ __exportStar(require("./query-repository.abstract"), exports);
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../persistence/index.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;;;;;;;;;;;;;;AAEtE;;;;;;;GAOG;AAEH,uDAAqC;AACrC,uDAAqC;AACrC,gEAA8C;AAC9C,+EAA6D;AAC7D,+DAA6C;AAC7C,oEAAkD;AAClD,gFAA8D;AAC9D,yEAAuD;AACvD,iEAA+C;AAC/C,6DAA2C;AAC3C,kEAAgD;AAChD,iEAA+C;AAC/C,wDAAsC;AACtC,8DAA4C"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Reads which unique constraint a persistence error violated. Core declares the
3
+ * contract and knows no database; an adapter package implements it, such as
4
+ * `MikroOrmDialect` of `@cqrs-ddd/mikro-orm`.
5
+ */
6
+ export interface IPersistenceDialect {
7
+ /**
8
+ * The key of the unique constraint `error` violated while writing `entity`:
9
+ * the entity property it covers, or the declared name of a multi-column
10
+ * constraint. `undefined` when `error` is not a unique violation, or names a
11
+ * constraint the dialect does not know.
12
+ */
13
+ uniqueViolation(error: unknown, entity: object): string | undefined;
14
+ }
15
+ /**
16
+ * Registers the dialect that `@MapPersistenceErrors` and `@PersistedWrite` use
17
+ * when their options name none. Call it once at the composition root, after
18
+ * the ORM is initialized; `undefined` removes it.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * setPersistenceDialect(new MikroOrmDialect(orm));
23
+ * ```
24
+ */
25
+ export declare function setPersistenceDialect(dialect: IPersistenceDialect | undefined): void;
26
+ /**
27
+ * The registered dialect, or `undefined`.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const dialect = options.dialect ?? persistenceDialect();
32
+ * ```
33
+ */
34
+ export declare function persistenceDialect(): IPersistenceDialect | undefined;
35
+ //# sourceMappingURL=persistence-dialect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence-dialect.d.ts","sourceRoot":"","sources":["../../persistence/persistence-dialect.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACrE;AAID;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,GAAG,SAAS,GACvC,IAAI,CAEN;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,mBAAmB,GAAG,SAAS,CAEpE"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.setPersistenceDialect = setPersistenceDialect;
5
+ exports.persistenceDialect = persistenceDialect;
6
+ let registered;
7
+ /**
8
+ * Registers the dialect that `@MapPersistenceErrors` and `@PersistedWrite` use
9
+ * when their options name none. Call it once at the composition root, after
10
+ * the ORM is initialized; `undefined` removes it.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * setPersistenceDialect(new MikroOrmDialect(orm));
15
+ * ```
16
+ */
17
+ function setPersistenceDialect(dialect) {
18
+ registered = dialect;
19
+ }
20
+ /**
21
+ * The registered dialect, or `undefined`.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const dialect = options.dialect ?? persistenceDialect();
26
+ * ```
27
+ */
28
+ function persistenceDialect() {
29
+ return registered;
30
+ }
31
+ //# sourceMappingURL=persistence-dialect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence-dialect.js","sourceRoot":"","sources":["../../persistence/persistence-dialect.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AA6BtE,sDAIC;AAUD,gDAEC;AA5BD,IAAI,UAA2C,CAAC;AAEhD;;;;;;;;;GASG;AACH,SAAgB,qBAAqB,CACnC,OAAwC;IAExC,UAAU,GAAG,OAAO,CAAC;AACvB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,kBAAkB;IAChC,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { ICache } from '../application/ports/cache.port';
2
+ import { IQueryRepository } from '../application/ports/query-repository.port';
3
+ import { IQueryOptions } from '../application/query.options';
4
+ /**
5
+ * Repository-wide snapshot policy applied by {@link FromCache} to methods that
6
+ * do not declare their own `hydrateFn` / `serializeFn`.
7
+ */
8
+ export interface QueryRepositoryHydration<TResult> {
9
+ /**
10
+ * Rehydrates a cached snapshot. Every cache hit of a method relying on this
11
+ * default is rehydrated, as with `alwaysHydrate: true`.
12
+ */
13
+ hydrateFn: (cached: unknown) => TResult;
14
+ /** Converts a result into the snapshot stored on a miss. */
15
+ serializeFn?: (result: TResult) => unknown;
16
+ }
17
+ /**
18
+ * Base class for read-side (query) repositories.
19
+ *
20
+ * Resolves a query via the abstract {@link find} method and receives an
21
+ * {@link ICache} instance. Subclasses annotate `find()` with the `@FromCache` decorator
22
+ * to serve cached results, bypass cache, or rehydrate snapshots into domain entities.
23
+ *
24
+ * @typeParam TQuery - The query/options type accepted by {@link find}.
25
+ * @typeParam TResult - The result type returned by {@link find}.
26
+ *
27
+ * @example Creating a query repository with @FromCache
28
+ * ```typescript
29
+ * @Injectable()
30
+ * export class GetUserQueryRepository extends QueryRepository<GetUserQuery, User | null> {
31
+ * constructor(
32
+ * @Inject(CACHE_TOKEN) protected readonly cache: ICache<UserSnapshot>,
33
+ * @Inject(MIKRO_ORM_CLIENT) private readonly store: MikroOrmStore,
34
+ * ) {
35
+ * super(cache);
36
+ * }
37
+ *
38
+ * @FromCache<GetUserQuery, User | null>({
39
+ * keyFn: (query) => cacheKey('user', { id: query.userId }),
40
+ * hydrateFn: (cached) => User.fromJSON(cached as UserSnapshot),
41
+ * alwaysHydrate: true,
42
+ * })
43
+ * async find(query: GetUserQuery): Promise<User | null> {
44
+ * return this.store.em.findOne(User, { id: query.userId });
45
+ * }
46
+ * }
47
+ * ```
48
+ *
49
+ * @example Declaring rehydration once for the whole repository
50
+ * ```typescript
51
+ * @Injectable()
52
+ * export class GetRoleQueryRepository extends QueryRepository<GetRoleQuery, Role | null> {
53
+ * constructor(
54
+ * @Inject(CACHE_TOKEN) cache: ICache<RoleSnapshot>,
55
+ * @Inject(MIKRO_ORM_CLIENT) private readonly store: MikroOrmStore,
56
+ * ) {
57
+ * super(cache, { hydrateFn: (cached) => Role.fromJSON(cached as RoleSnapshot) });
58
+ * }
59
+ *
60
+ * @FromCache<GetRoleQuery, Role | null>({
61
+ * keyFn: (query) => cacheKey(Role.aggregateName, { id: query.roleId }),
62
+ * })
63
+ * async find(query: GetRoleQuery): Promise<Role | null> { ... }
64
+ * }
65
+ * ```
66
+ *
67
+ * A method that declares `hydrateFn` (including `null`) or `serializeFn`
68
+ * uses its own value instead of the repository default.
69
+ */
70
+ export declare abstract class QueryRepository<TQuery = IQueryOptions, TResult = unknown> implements IQueryRepository<TQuery, TResult> {
71
+ protected readonly cache: ICache<unknown>;
72
+ protected readonly hydration?: QueryRepositoryHydration<TResult> | undefined;
73
+ constructor(cache: ICache<unknown>, hydration?: QueryRepositoryHydration<TResult> | undefined);
74
+ abstract find(query: TQuery): Promise<TResult>;
75
+ }
76
+ //# sourceMappingURL=query-repository.abstract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-repository.abstract.d.ts","sourceRoot":"","sources":["../../persistence/query-repository.abstract.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,wBAAwB,CAAC,OAAO;IAC/C;;;OAGG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAExC,4DAA4D;IAC5D,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,8BAAsB,eAAe,CAAC,MAAM,GAAG,aAAa,EAAE,OAAO,GAAG,OAAO,CAC7E,YAAW,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC;IAG1C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,wBAAwB,CAAC,OAAO,CAAC;gBAD7C,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,EACtB,SAAS,CAAC,EAAE,wBAAwB,CAAC,OAAO,CAAC,YAAA;IAGlE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAC/C"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.QueryRepository = void 0;
5
+ /**
6
+ * Base class for read-side (query) repositories.
7
+ *
8
+ * Resolves a query via the abstract {@link find} method and receives an
9
+ * {@link ICache} instance. Subclasses annotate `find()` with the `@FromCache` decorator
10
+ * to serve cached results, bypass cache, or rehydrate snapshots into domain entities.
11
+ *
12
+ * @typeParam TQuery - The query/options type accepted by {@link find}.
13
+ * @typeParam TResult - The result type returned by {@link find}.
14
+ *
15
+ * @example Creating a query repository with @FromCache
16
+ * ```typescript
17
+ * @Injectable()
18
+ * export class GetUserQueryRepository extends QueryRepository<GetUserQuery, User | null> {
19
+ * constructor(
20
+ * @Inject(CACHE_TOKEN) protected readonly cache: ICache<UserSnapshot>,
21
+ * @Inject(MIKRO_ORM_CLIENT) private readonly store: MikroOrmStore,
22
+ * ) {
23
+ * super(cache);
24
+ * }
25
+ *
26
+ * @FromCache<GetUserQuery, User | null>({
27
+ * keyFn: (query) => cacheKey('user', { id: query.userId }),
28
+ * hydrateFn: (cached) => User.fromJSON(cached as UserSnapshot),
29
+ * alwaysHydrate: true,
30
+ * })
31
+ * async find(query: GetUserQuery): Promise<User | null> {
32
+ * return this.store.em.findOne(User, { id: query.userId });
33
+ * }
34
+ * }
35
+ * ```
36
+ *
37
+ * @example Declaring rehydration once for the whole repository
38
+ * ```typescript
39
+ * @Injectable()
40
+ * export class GetRoleQueryRepository extends QueryRepository<GetRoleQuery, Role | null> {
41
+ * constructor(
42
+ * @Inject(CACHE_TOKEN) cache: ICache<RoleSnapshot>,
43
+ * @Inject(MIKRO_ORM_CLIENT) private readonly store: MikroOrmStore,
44
+ * ) {
45
+ * super(cache, { hydrateFn: (cached) => Role.fromJSON(cached as RoleSnapshot) });
46
+ * }
47
+ *
48
+ * @FromCache<GetRoleQuery, Role | null>({
49
+ * keyFn: (query) => cacheKey(Role.aggregateName, { id: query.roleId }),
50
+ * })
51
+ * async find(query: GetRoleQuery): Promise<Role | null> { ... }
52
+ * }
53
+ * ```
54
+ *
55
+ * A method that declares `hydrateFn` (including `null`) or `serializeFn`
56
+ * uses its own value instead of the repository default.
57
+ */
58
+ class QueryRepository {
59
+ cache;
60
+ hydration;
61
+ constructor(cache, hydration) {
62
+ this.cache = cache;
63
+ this.hydration = hydration;
64
+ }
65
+ }
66
+ exports.QueryRepository = QueryRepository;
67
+ //# sourceMappingURL=query-repository.abstract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-repository.abstract.js","sourceRoot":"","sources":["../../persistence/query-repository.abstract.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAqBtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAsB,eAAe;IAId;IACA;IAFrB,YACqB,KAAsB,EACtB,SAA6C;QAD7C,UAAK,GAAL,KAAK,CAAiB;QACtB,cAAS,GAAT,SAAS,CAAoC;IAC/D,CAAC;CAGL;AATD,0CASC"}
@@ -0,0 +1,2 @@
1
+ export type Method = (...args: unknown[]) => unknown;
2
+ //# sourceMappingURL=Method.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Method.type.d.ts","sourceRoot":"","sources":["../../types/Method.type.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=Method.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Method.type.js","sourceRoot":"","sources":["../../types/Method.type.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@cqrs-ddd/core",
3
+ "version": "0.2.0",
4
+ "description": "Framework- and ORM-neutral DDD building blocks for TypeScript: aggregates and domain events, CQRS base classes and repository ports, and a revision-fenced repository cache, as separate entry points.",
5
+ "author": "Aristotelis",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "engines": {
8
+ "node": ">=22.0.0"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/aristoteliss/nestjs-pipeline.git",
13
+ "directory": "packages/ddd-core"
14
+ },
15
+ "homepage": "https://github.com/aristoteliss/nestjs-pipeline/tree/master/packages/ddd-core#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/aristoteliss/nestjs-pipeline/issues"
18
+ },
19
+ "keywords": [
20
+ "ddd",
21
+ "domain-driven-design",
22
+ "cqrs",
23
+ "aggregate",
24
+ "domain-events",
25
+ "repository",
26
+ "cache"
27
+ ],
28
+ "main": "dist/index.js",
29
+ "types": "dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./domain": {
36
+ "types": "./dist/domain/index.d.ts",
37
+ "default": "./dist/domain/index.js"
38
+ },
39
+ "./application": {
40
+ "types": "./dist/application/index.d.ts",
41
+ "default": "./dist/application/index.js"
42
+ },
43
+ "./persistence": {
44
+ "types": "./dist/persistence/index.d.ts",
45
+ "default": "./dist/persistence/index.js"
46
+ },
47
+ "./http": {
48
+ "types": "./dist/http/index.d.ts",
49
+ "default": "./dist/http/index.js"
50
+ }
51
+ },
52
+ "files": [
53
+ "dist",
54
+ "README.md",
55
+ "LICENSE",
56
+ "COMMERCIAL_LICENSE.txt"
57
+ ],
58
+ "publishConfig": {
59
+ "access": "public"
60
+ },
61
+ "dependencies": {
62
+ "@cqrs-ddd/safe-stringify": "^0.2.0",
63
+ "@cqrs-ddd/uuidv7": "^0.2.0"
64
+ },
65
+ "devDependencies": {
66
+ "@biomejs/biome": "^2.5.14",
67
+ "@vitest/coverage-v8": "^4.1.11",
68
+ "tsx": "^4.23.15",
69
+ "typescript": "^6.0.3",
70
+ "vitest": "^4.1.11"
71
+ },
72
+ "scripts": {
73
+ "build": "tsc -p tsconfig.build.json",
74
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
75
+ "rebuild": "pnpm run clean && pnpm run build",
76
+ "lint": "tsc --noEmit",
77
+ "test": "vitest run",
78
+ "test:watch": "vitest"
79
+ }
80
+ }