@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,81 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.numberRule = numberRule;
5
+ const rule_support_1 = require("./rule-support");
6
+ function assertBound(name, value) {
7
+ if (value !== undefined && !Number.isFinite(value)) {
8
+ throw new TypeError(`numberRule: ${name} must be a finite number.`);
9
+ }
10
+ }
11
+ /**
12
+ * Defines the rule for one number field of an aggregate: declared once, used
13
+ * by the aggregate to parse the value, and read by other layers (such as a
14
+ * request schema) for its limits.
15
+ *
16
+ * `parse(value)` checks, in this order:
17
+ * 1. `null` or `undefined`: `null`, or a `required` violation;
18
+ * 2. not a number: a `type` violation (a numeric string is not converted);
19
+ * 3. `NaN` or an infinity: a `finite` violation;
20
+ * 4. with `integer`, not a safe integer: an `integer` violation;
21
+ * 5. `min`, then `max`.
22
+ *
23
+ * @param options - The field name, its constraints and its error.
24
+ * @returns The frozen rule.
25
+ * @throws TypeError when an option is invalid: an empty `field`, a bound that
26
+ * is not a finite number, or `min` above `max`.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * export class Order extends RootEntity<OrderSnapshot> {
31
+ * static readonly rules = {
32
+ * quantity: numberRule({
33
+ * field: 'quantity',
34
+ * integer: true,
35
+ * min: 1,
36
+ * max: 100,
37
+ * error: (violation) => new InvalidQuantityException(violation),
38
+ * }),
39
+ * } as const;
40
+ *
41
+ * @Mutable<number>({ normalize: (value) => Order.rules.quantity.parse(value) })
42
+ * private _quantity: number;
43
+ * }
44
+ *
45
+ * Order.rules.quantity.parse(0);
46
+ * // throws InvalidQuantityException: "quantity must be at least 1."
47
+ * ```
48
+ */
49
+ function numberRule(options) {
50
+ (0, rule_support_1.assertField)(options.field, 'numberRule');
51
+ assertBound('min', options.min);
52
+ assertBound('max', options.max);
53
+ const { field, required = true, integer = false, min, max } = options;
54
+ if (min !== undefined && max !== undefined && min > max) {
55
+ throw new TypeError('numberRule: min must not exceed max.');
56
+ }
57
+ const fail = (0, rule_support_1.violationThrower)(options.error);
58
+ const parse = (value) => {
59
+ if (value === null || value === undefined) {
60
+ return required ? fail({ field, rule: 'required' }) : null;
61
+ }
62
+ if (typeof value !== 'number') {
63
+ return fail({ field, rule: 'type', expected: 'number' });
64
+ }
65
+ if (!Number.isFinite(value)) {
66
+ return fail({ field, rule: 'finite' });
67
+ }
68
+ if (integer && !Number.isSafeInteger(value)) {
69
+ return fail({ field, rule: 'integer' });
70
+ }
71
+ if (min !== undefined && value < min) {
72
+ return fail({ field, rule: 'min', limit: min });
73
+ }
74
+ if (max !== undefined && value > max) {
75
+ return fail({ field, rule: 'max', limit: max });
76
+ }
77
+ return value;
78
+ };
79
+ return Object.freeze({ ...options, parse });
80
+ }
81
+ //# sourceMappingURL=number.rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.rule.js","sourceRoot":"","sources":["../../../domain/rules/number.rule.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AA8FtE,gCAoCC;AAhID,iDAA+D;AAgD/D,SAAS,WAAW,CAAC,IAAY,EAAE,KAAyB;IAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,SAAS,CAAC,eAAe,IAAI,2BAA2B,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,SAAgB,UAAU,CACxB,OAAiB;IAEjB,IAAA,0BAAW,EAAC,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACzC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACtE,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACxD,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,+BAAgB,EAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE7C,MAAM,KAAK,GAAG,CAAC,KAAc,EAAiB,EAAE;QAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAyB,CAAC;AACtE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ValueViolation, ValueViolationError } from './value-violation';
2
+ /** Throws a `TypeError` naming the rule when `field` is not a non-empty string. */
3
+ export declare function assertField(field: unknown, rule: string): void;
4
+ /** Returns a function that throws the rule's error for a violation, frozen. */
5
+ export declare function violationThrower(error?: ValueViolationError): (violation: ValueViolation) => never;
6
+ //# sourceMappingURL=rule-support.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-support.d.ts","sourceRoot":"","sources":["../../../domain/rules/rule-support.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7E,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAC9B,KAAK,GAAE,mBAC+B,GACrC,CAAC,SAAS,EAAE,cAAc,KAAK,KAAK,CAItC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.assertField = assertField;
5
+ exports.violationThrower = violationThrower;
6
+ const invalid_value_exception_1 = require("../exceptions/invalid-value.exception");
7
+ /** Throws a `TypeError` naming the rule when `field` is not a non-empty string. */
8
+ function assertField(field, rule) {
9
+ if (typeof field !== 'string' || field.trim().length === 0) {
10
+ throw new TypeError(`${rule}: field must be a non-empty string.`);
11
+ }
12
+ }
13
+ /** Returns a function that throws the rule's error for a violation, frozen. */
14
+ function violationThrower(error = (violation) => new invalid_value_exception_1.InvalidValueException(violation)) {
15
+ return (violation) => {
16
+ throw error(Object.freeze(violation));
17
+ };
18
+ }
19
+ //# sourceMappingURL=rule-support.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-support.js","sourceRoot":"","sources":["../../../domain/rules/rule-support.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAMtE,kCAIC;AAGD,4CAOC;AAlBD,mFAA8E;AAG9E,mFAAmF;AACnF,SAAgB,WAAW,CAAC,KAAc,EAAE,IAAY;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,qCAAqC,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAgB,gBAAgB,CAC9B,QAA6B,CAAC,SAAS,EAAE,EAAE,CACzC,IAAI,+CAAqB,CAAC,SAAS,CAAC;IAEtC,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,98 @@
1
+ import type { ValueViolationError } from './value-violation';
2
+ /** Options of {@link textRule}. */
3
+ export interface TextRuleOptions {
4
+ /** Field name reported in the violation and in the default message. */
5
+ readonly field: string;
6
+ /**
7
+ * `false` accepts `null`, `undefined` and blank text, and normalizes them
8
+ * to `null`. Defaults to `true`: they are a `required` violation.
9
+ */
10
+ readonly required?: boolean;
11
+ /**
12
+ * Fewest characters after normalization, counted in UTF-16 code units like
13
+ * `String.length` and Zod's `.min()`.
14
+ */
15
+ readonly minLength?: number;
16
+ /**
17
+ * Most characters after normalization, counted like {@link minLength}. A
18
+ * column limit counted in code points, such as `varchar(n)`, is never
19
+ * exceeded by a value within it.
20
+ */
21
+ readonly maxLength?: number;
22
+ /**
23
+ * Pattern the normalized text must match. A `g` or `y` flag is rejected,
24
+ * because `test()` would then depend on the previous call.
25
+ */
26
+ readonly pattern?: RegExp;
27
+ /**
28
+ * `true` accepts tab, line feed and carriage return inside the text.
29
+ * Defaults to `false`: they are a `characters` violation.
30
+ */
31
+ readonly multiline?: boolean;
32
+ /**
33
+ * Builds the error thrown for a violation. Defaults to
34
+ * `InvalidValueException`.
35
+ */
36
+ readonly error?: ValueViolationError;
37
+ }
38
+ /** What {@link TextRule.parse} returns: `string | null` when not required. */
39
+ export type TextRuleValue<TOptions extends TextRuleOptions> = TOptions extends {
40
+ readonly required: true;
41
+ } ? string : TOptions extends {
42
+ readonly required: boolean;
43
+ } ? string | null : string;
44
+ /** A text rule: its options, frozen, and the parser that enforces them. */
45
+ export type TextRule<TOptions extends TextRuleOptions = TextRuleOptions> = Readonly<TOptions> & {
46
+ /**
47
+ * Returns the value in Unicode NFC form and trimmed, or `null` for blank
48
+ * text the rule does not require. A standalone function: pass it without
49
+ * binding.
50
+ *
51
+ * @throws The `error` option's result, by default `InvalidValueException`.
52
+ */
53
+ readonly parse: (value: unknown) => TextRuleValue<TOptions>;
54
+ };
55
+ /**
56
+ * Defines the rule for one text field of an aggregate: declared once, used by
57
+ * the aggregate to parse the value, and read by other layers (such as a
58
+ * request schema) for its limits.
59
+ *
60
+ * `parse(value)` checks, in this order:
61
+ * 1. `null` or `undefined`: `null`, or a `required` violation;
62
+ * 2. not a string: a `type` violation;
63
+ * 3. an unpaired surrogate: a `characters` violation, since it cannot be
64
+ * stored as UTF-8;
65
+ * 4. Unicode NFC normalization, then trimming; blank text is `null`, or a
66
+ * `required` violation;
67
+ * 5. a control character (tab and line breaks too, unless `multiline`): a
68
+ * `characters` violation;
69
+ * 6. `minLength`, `maxLength`, then `pattern`.
70
+ *
71
+ * @param options - The field name, its constraints and its error.
72
+ * @returns The frozen rule.
73
+ * @throws TypeError when an option is invalid: an empty `field`, a length
74
+ * that is not a non-negative integer, `minLength` above `maxLength`, or a
75
+ * `pattern` with a `g` or `y` flag.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * export class User extends RootEntity<UserSnapshot> {
80
+ * static readonly rules = {
81
+ * username: textRule({
82
+ * field: 'username',
83
+ * minLength: 3,
84
+ * maxLength: 255,
85
+ * error: (violation) => new InvalidUsernameException(violation),
86
+ * }),
87
+ * } as const;
88
+ *
89
+ * @Mutable<string>({ normalize: (value) => User.rules.username.parse(value) })
90
+ * private _username: string;
91
+ * }
92
+ *
93
+ * User.rules.username.parse(' Ana María '); // 'Ana María'
94
+ * z.string().trim().min(User.rules.username.minLength); // a request schema
95
+ * ```
96
+ */
97
+ export declare function textRule<const TOptions extends TextRuleOptions>(options: TOptions): TextRule<TOptions>;
98
+ //# sourceMappingURL=text.rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.rule.d.ts","sourceRoot":"","sources":["../../../domain/rules/text.rule.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,mCAAmC;AACnC,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC;CACtC;AAED,8EAA8E;AAC9E,MAAM,MAAM,aAAa,CAAC,QAAQ,SAAS,eAAe,IAAI,QAAQ,SAAS;IAC7E,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;CACzB,GACG,MAAM,GACN,QAAQ,SAAS;IAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAC7C,MAAM,GAAG,IAAI,GACb,MAAM,CAAC;AAEb,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,CAAC,QAAQ,SAAS,eAAe,GAAG,eAAe,IACrE,QAAQ,CAAC,QAAQ,CAAC,GAAG;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,aAAa,CAAC,QAAQ,CAAC,CAAC;CAC7D,CAAC;AAaJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,QAAQ,CAAC,KAAK,CAAC,QAAQ,SAAS,eAAe,EAC7D,OAAO,EAAE,QAAQ,GAChB,QAAQ,CAAC,QAAQ,CAAC,CA0DpB"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.textRule = textRule;
5
+ const rule_support_1 = require("./rule-support");
6
+ const CONTROL_CHARACTER = /\p{Cc}/u;
7
+ const CONTROL_CHARACTER_EXCEPT_LINE_BREAK = /(?![\t\n\r])\p{Cc}/u;
8
+ const UNPAIRED_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
9
+ function assertLength(name, value) {
10
+ if (value !== undefined && !(Number.isSafeInteger(value) && value >= 0)) {
11
+ throw new TypeError(`textRule: ${name} must be a non-negative integer.`);
12
+ }
13
+ }
14
+ /**
15
+ * Defines the rule for one text field of an aggregate: declared once, used by
16
+ * the aggregate to parse the value, and read by other layers (such as a
17
+ * request schema) for its limits.
18
+ *
19
+ * `parse(value)` checks, in this order:
20
+ * 1. `null` or `undefined`: `null`, or a `required` violation;
21
+ * 2. not a string: a `type` violation;
22
+ * 3. an unpaired surrogate: a `characters` violation, since it cannot be
23
+ * stored as UTF-8;
24
+ * 4. Unicode NFC normalization, then trimming; blank text is `null`, or a
25
+ * `required` violation;
26
+ * 5. a control character (tab and line breaks too, unless `multiline`): a
27
+ * `characters` violation;
28
+ * 6. `minLength`, `maxLength`, then `pattern`.
29
+ *
30
+ * @param options - The field name, its constraints and its error.
31
+ * @returns The frozen rule.
32
+ * @throws TypeError when an option is invalid: an empty `field`, a length
33
+ * that is not a non-negative integer, `minLength` above `maxLength`, or a
34
+ * `pattern` with a `g` or `y` flag.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * export class User extends RootEntity<UserSnapshot> {
39
+ * static readonly rules = {
40
+ * username: textRule({
41
+ * field: 'username',
42
+ * minLength: 3,
43
+ * maxLength: 255,
44
+ * error: (violation) => new InvalidUsernameException(violation),
45
+ * }),
46
+ * } as const;
47
+ *
48
+ * @Mutable<string>({ normalize: (value) => User.rules.username.parse(value) })
49
+ * private _username: string;
50
+ * }
51
+ *
52
+ * User.rules.username.parse(' Ana María '); // 'Ana María'
53
+ * z.string().trim().min(User.rules.username.minLength); // a request schema
54
+ * ```
55
+ */
56
+ function textRule(options) {
57
+ (0, rule_support_1.assertField)(options.field, 'textRule');
58
+ assertLength('minLength', options.minLength);
59
+ assertLength('maxLength', options.maxLength);
60
+ const { field, required = true, minLength, maxLength, pattern, multiline = false, } = options;
61
+ if (minLength !== undefined &&
62
+ maxLength !== undefined &&
63
+ minLength > maxLength) {
64
+ throw new TypeError('textRule: minLength must not exceed maxLength.');
65
+ }
66
+ if (pattern !== undefined && (pattern.global || pattern.sticky)) {
67
+ throw new TypeError('textRule: pattern must not use the g or y flag.');
68
+ }
69
+ const fail = (0, rule_support_1.violationThrower)(options.error);
70
+ const controlCharacter = multiline
71
+ ? CONTROL_CHARACTER_EXCEPT_LINE_BREAK
72
+ : CONTROL_CHARACTER;
73
+ const parse = (value) => {
74
+ if (value === null || value === undefined) {
75
+ return required ? fail({ field, rule: 'required' }) : null;
76
+ }
77
+ if (typeof value !== 'string') {
78
+ return fail({ field, rule: 'type', expected: 'string' });
79
+ }
80
+ if (UNPAIRED_SURROGATE.test(value)) {
81
+ return fail({ field, rule: 'characters' });
82
+ }
83
+ const text = value.normalize('NFC').trim();
84
+ if (text.length === 0) {
85
+ return required ? fail({ field, rule: 'required' }) : null;
86
+ }
87
+ if (controlCharacter.test(text)) {
88
+ return fail({ field, rule: 'characters' });
89
+ }
90
+ if (minLength !== undefined && text.length < minLength) {
91
+ return fail({ field, rule: 'minLength', limit: minLength });
92
+ }
93
+ if (maxLength !== undefined && text.length > maxLength) {
94
+ return fail({ field, rule: 'maxLength', limit: maxLength });
95
+ }
96
+ if (pattern !== undefined && !pattern.test(text)) {
97
+ return fail({ field, rule: 'pattern' });
98
+ }
99
+ return text;
100
+ };
101
+ return Object.freeze({ ...options, parse });
102
+ }
103
+ //# sourceMappingURL=text.rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.rule.js","sourceRoot":"","sources":["../../../domain/rules/text.rule.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAqHtE,4BA4DC;AA/KD,iDAA+D;AA8D/D,MAAM,iBAAiB,GAAG,SAAS,CAAC;AACpC,MAAM,mCAAmC,GAAG,qBAAqB,CAAC;AAClE,MAAM,kBAAkB,GACtB,wEAAwE,CAAC;AAE3E,SAAS,YAAY,CAAC,IAAY,EAAE,KAAyB;IAC3D,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,SAAS,CAAC,aAAa,IAAI,kCAAkC,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,SAAgB,QAAQ,CACtB,OAAiB;IAEjB,IAAA,0BAAW,EAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACvC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,EACJ,KAAK,EACL,QAAQ,GAAG,IAAI,EACf,SAAS,EACT,SAAS,EACT,OAAO,EACP,SAAS,GAAG,KAAK,GAClB,GAAG,OAAO,CAAC;IACZ,IACE,SAAS,KAAK,SAAS;QACvB,SAAS,KAAK,SAAS;QACvB,SAAS,GAAG,SAAS,EACrB,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,+BAAgB,EAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,gBAAgB,GAAG,SAAS;QAChC,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,iBAAiB,CAAC;IAEtB,MAAM,KAAK,GAAG,CAAC,KAAc,EAAiB,EAAE;QAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D,CAAC;QACD,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAuB,CAAC;AACpE,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The rule a value broke, as reported by {@link textRule} and
3
+ * {@link numberRule}. `field` is the rule's field name; `limit` is the
4
+ * configured bound of a length or range rule.
5
+ *
6
+ * | `rule` | Broken when the value |
7
+ * |---|---|
8
+ * | `required` | is `null`, `undefined` or blank, and the rule requires it |
9
+ * | `type` | is not a string (`textRule`) or not a number (`numberRule`) |
10
+ * | `characters` | contains a control character or an unpaired surrogate |
11
+ * | `minLength`, `maxLength` | is shorter or longer than `limit` |
12
+ * | `pattern` | does not match the rule's pattern |
13
+ * | `finite` | is `NaN` or infinite |
14
+ * | `integer` | is not a safe integer |
15
+ * | `min`, `max` | is below or above `limit` |
16
+ */
17
+ export type ValueViolation = {
18
+ readonly field: string;
19
+ readonly rule: 'required';
20
+ } | {
21
+ readonly field: string;
22
+ readonly rule: 'type';
23
+ readonly expected: 'string' | 'number';
24
+ } | {
25
+ readonly field: string;
26
+ readonly rule: 'characters';
27
+ } | {
28
+ readonly field: string;
29
+ readonly rule: 'minLength' | 'maxLength';
30
+ readonly limit: number;
31
+ } | {
32
+ readonly field: string;
33
+ readonly rule: 'pattern';
34
+ } | {
35
+ readonly field: string;
36
+ readonly rule: 'finite' | 'integer';
37
+ } | {
38
+ readonly field: string;
39
+ readonly rule: 'min' | 'max';
40
+ readonly limit: number;
41
+ };
42
+ /** Builds the error a rule throws for a violation. */
43
+ export type ValueViolationError = (violation: ValueViolation) => Error;
44
+ //# sourceMappingURL=value-violation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-violation.d.ts","sourceRoot":"","sources":["../../../domain/rules/value-violation.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GACrD;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC;CACxC,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GACvD;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,GAC/D;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,sDAAsD;AACtD,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,cAAc,KAAK,KAAK,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=value-violation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-violation.js","sourceRoot":"","sources":["../../../domain/rules/value-violation.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
@@ -0,0 +1,43 @@
1
+ import { DomainException } from '../domain/exceptions/domain.exception';
2
+ /** HTTP answer for a {@link DomainException}, as plain values. */
3
+ export interface DomainErrorHttpStatus {
4
+ /** HTTP status code. */
5
+ readonly statusCode: number;
6
+ /** Reason phrase of `statusCode`, such as `'Conflict'`. */
7
+ readonly error: string;
8
+ /**
9
+ * Message safe to return to the caller: the exception's own message, or a
10
+ * generic one when the exception message is meant for developers.
11
+ */
12
+ readonly message: string;
13
+ }
14
+ /**
15
+ * Maps this package's errors to an HTTP status, for any HTTP framework.
16
+ *
17
+ * | Exception | Status | Message |
18
+ * |---|---|---|
19
+ * | {@link ConcurrencyConflictError} | 409 Conflict | the exception's |
20
+ * | {@link EntityNotFoundException} | 404 Not Found | the exception's |
21
+ * | {@link MissingTenantContextError} | 500 Internal Server Error | `'Internal server error'` |
22
+ * | any other {@link DomainException} | 400 Bad Request | the exception's |
23
+ *
24
+ * A missing tenant is a server misconfiguration, not a caller mistake, so it
25
+ * answers 500 and keeps its message, which names the failed operation, out of
26
+ * the response.
27
+ *
28
+ * An application maps its own `DomainException` subclasses first and passes the
29
+ * rest here. Anything that is not a `DomainException` returns `undefined`, so
30
+ * the framework's default handling still applies.
31
+ *
32
+ * @example An Express error handler
33
+ * ```ts
34
+ * app.use((err, req, res, next) => {
35
+ * const mapped = domainErrorHttpStatus(err);
36
+ * if (!mapped) return next(err);
37
+ * res.status(mapped.statusCode).json(mapped);
38
+ * });
39
+ * ```
40
+ */
41
+ export declare function domainErrorHttpStatus(error: DomainException): DomainErrorHttpStatus;
42
+ export declare function domainErrorHttpStatus(error: unknown): DomainErrorHttpStatus | undefined;
43
+ //# sourceMappingURL=domain-error-http-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-error-http-status.d.ts","sourceRoot":"","sources":["../../http/domain-error-http-status.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAIxE,kEAAkE;AAClE,MAAM,WAAW,qBAAqB;IACpC,wBAAwB;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,eAAe,GACrB,qBAAqB,CAAC;AACzB,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,GACb,qBAAqB,GAAG,SAAS,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.domainErrorHttpStatus = domainErrorHttpStatus;
5
+ const concurrency_conflict_error_1 = require("../domain/exceptions/concurrency-conflict.error");
6
+ const domain_exception_1 = require("../domain/exceptions/domain.exception");
7
+ const entity_not_found_exception_1 = require("../domain/exceptions/entity-not-found.exception");
8
+ const missing_tenant_context_exception_1 = require("../domain/exceptions/missing-tenant-context.exception");
9
+ function domainErrorHttpStatus(error) {
10
+ if (!(error instanceof domain_exception_1.DomainException))
11
+ return undefined;
12
+ if (error instanceof missing_tenant_context_exception_1.MissingTenantContextError) {
13
+ return {
14
+ statusCode: 500,
15
+ error: 'Internal Server Error',
16
+ message: 'Internal server error',
17
+ };
18
+ }
19
+ if (error instanceof concurrency_conflict_error_1.ConcurrencyConflictError) {
20
+ return { statusCode: 409, error: 'Conflict', message: error.message };
21
+ }
22
+ if (error instanceof entity_not_found_exception_1.EntityNotFoundException) {
23
+ return { statusCode: 404, error: 'Not Found', message: error.message };
24
+ }
25
+ return { statusCode: 400, error: 'Bad Request', message: error.message };
26
+ }
27
+ //# sourceMappingURL=domain-error-http-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-error-http-status.js","sourceRoot":"","sources":["../../http/domain-error-http-status.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAqDtE,sDAmBC;AAtED,gGAA2F;AAC3F,4EAAwE;AACxE,gGAA0F;AAC1F,4GAAkG;AAgDlG,SAAgB,qBAAqB,CACnC,KAAc;IAEd,IAAI,CAAC,CAAC,KAAK,YAAY,kCAAe,CAAC;QAAE,OAAO,SAAS,CAAC;IAE1D,IAAI,KAAK,YAAY,4DAAyB,EAAE,CAAC;QAC/C,OAAO;YACL,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,uBAAuB;SACjC,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,YAAY,qDAAwB,EAAE,CAAC;QAC9C,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,YAAY,oDAAuB,EAAE,CAAC;QAC7C,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * HTTP status mapping for this package's errors.
3
+ *
4
+ * It returns plain numbers and strings and loads no HTTP framework, so an
5
+ * application's own error handler or exception filter decides how to send it.
6
+ * HTTP stays out of `/domain` and `/application`.
7
+ */
8
+ export * from './domain-error-http-status';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../http/index.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,cAAc,4BAA4B,CAAC"}
@@ -0,0 +1,26 @@
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
+ * HTTP status mapping for this package's errors.
20
+ *
21
+ * It returns plain numbers and strings and loads no HTTP framework, so an
22
+ * application's own error handler or exception filter decides how to send it.
23
+ * HTTP stays out of `/domain` and `/application`.
24
+ */
25
+ __exportStar(require("./domain-error-http-status"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../http/index.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;;;;;;;;;;;;;;AAEtE;;;;;;GAMG;AAEH,6DAA2C"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Convenience barrel re-exporting every layer.
3
+ *
4
+ * Prefer the layered entry points — `@cqrs-ddd/core/domain` and
5
+ * `.../application` — in domain and CQRS code so the layering is expressed by
6
+ * the import itself rather than only by convention.
7
+ */
8
+ export * from './application/index';
9
+ export * from './domain/index';
10
+ export * from './http/index';
11
+ export * from './persistence/index';
12
+ export * from './types/Method.type';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
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
+ * Convenience barrel re-exporting every layer.
20
+ *
21
+ * Prefer the layered entry points — `@cqrs-ddd/core/domain` and
22
+ * `.../application` — in domain and CQRS code so the layering is expressed by
23
+ * the import itself rather than only by convention.
24
+ */
25
+ __exportStar(require("./application/index"), exports);
26
+ __exportStar(require("./domain/index"), exports);
27
+ __exportStar(require("./http/index"), exports);
28
+ __exportStar(require("./persistence/index"), exports);
29
+ __exportStar(require("./types/Method.type"), exports);
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;;;;;;;;;;;;;;AAEtE;;;;;;GAMG;AAEH,sDAAoC;AACpC,iDAA+B;AAC/B,+CAA6B;AAC7B,sDAAoC;AACpC,sDAAoC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Receives the operational warnings of the cache decorators and adapters, such as
3
+ * a failed cache write or a miswired repository.
4
+ *
5
+ * Pass one through the `logger` option to route these warnings into an
6
+ * application's logging. `console` and a NestJS `Logger` both fit. Without it,
7
+ * warnings go to `console.warn` with a `[CacheDecorator]`-style prefix. A logger
8
+ * that throws never changes a repository result.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * @Cache<User, UserSnapshot>({
13
+ * setKey: (user) => cacheKey(User.aggregateName, { id: user.id }),
14
+ * logger: new Logger('UserCache'), // NestJS
15
+ * })
16
+ * ```
17
+ */
18
+ export interface ICacheLogger {
19
+ warn(message: string): unknown;
20
+ }
21
+ /** The default {@link ICacheLogger}: `console.warn` with a `[context]` prefix. */
22
+ export declare function consoleCacheLogger(context: string): ICacheLogger;
23
+ /**
24
+ * Writes a warning without letting the logger change the caller's outcome:
25
+ * cache maintenance runs after a durable write, and a throwing logger must not
26
+ * turn that success into an error.
27
+ */
28
+ export declare function safeWarn(logger: ICacheLogger, message: string): void;
29
+ //# sourceMappingURL=cache-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-logger.d.ts","sourceRoot":"","sources":["../../../persistence/cache/cache-logger.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAMpE"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.consoleCacheLogger = consoleCacheLogger;
5
+ exports.safeWarn = safeWarn;
6
+ /** The default {@link ICacheLogger}: `console.warn` with a `[context]` prefix. */
7
+ function consoleCacheLogger(context) {
8
+ return { warn: (message) => console.warn(`[${context}] ${message}`) };
9
+ }
10
+ /**
11
+ * Writes a warning without letting the logger change the caller's outcome:
12
+ * cache maintenance runs after a durable write, and a throwing logger must not
13
+ * turn that success into an error.
14
+ */
15
+ function safeWarn(logger, message) {
16
+ try {
17
+ logger.warn(message);
18
+ }
19
+ catch {
20
+ // The logger itself failed; the warning is dropped, the result is not.
21
+ }
22
+ }
23
+ //# sourceMappingURL=cache-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-logger.js","sourceRoot":"","sources":["../../../persistence/cache/cache-logger.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAwBtE,gDAEC;AAOD,4BAMC;AAhBD,kFAAkF;AAClF,SAAgB,kBAAkB,CAAC,OAAe;IAChD,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC,EAAE,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,SAAgB,QAAQ,CAAC,MAAoB,EAAE,OAAe;IAC5D,IAAI,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;AACH,CAAC"}