@cullet/erp-core 1.0.2 → 1.0.3

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 (144) hide show
  1. package/README.md +24 -24
  2. package/dist/gate-engine-registry.js.map +1 -1
  3. package/dist/gate-v1-payload.schema.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/outcome.js.map +1 -1
  8. package/dist/policies/engines/v1/gate/index.js.map +1 -1
  9. package/dist/policy-service.js.map +1 -1
  10. package/dist/validation-code.js.map +1 -1
  11. package/dist/validation-error.js.map +1 -1
  12. package/dist/validation-field.js.map +1 -1
  13. package/meta.json +67 -67
  14. package/package.json +56 -56
  15. package/src/core/application/commands/command.ts +3 -3
  16. package/src/core/application/commands/requested-by.ts +60 -60
  17. package/src/core/application/index.ts +21 -21
  18. package/src/core/application/policy-error-mapper.ts +54 -54
  19. package/src/core/application/ports/index.ts +6 -6
  20. package/src/core/application/ports/logger.port.ts +4 -4
  21. package/src/core/application/ports/metrics.port.ts +3 -3
  22. package/src/core/application/ports/policy-port.ts +7 -7
  23. package/src/core/application/ports/repository.port.ts +3 -3
  24. package/src/core/application/ports/temporal-repository.port.ts +4 -4
  25. package/src/core/application/ports/tracer.port.ts +7 -7
  26. package/src/core/application/queries/query.ts +13 -13
  27. package/src/core/application/temporal/index.ts +7 -7
  28. package/src/core/application/temporal/temporal-context.ts +20 -20
  29. package/src/core/application/temporal/temporal-use-case.ts +22 -22
  30. package/src/core/application/use-case.ts +10 -10
  31. package/src/core/config/core-config.instance.ts +1 -1
  32. package/src/core/config/core-config.ts +59 -59
  33. package/src/core/config/index.ts +6 -6
  34. package/src/core/config/policy-reporter.ts +31 -31
  35. package/src/core/config/silent-policy-reporter.ts +1 -1
  36. package/src/core/domain/entity.ts +44 -44
  37. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +6 -6
  38. package/src/core/domain/rulesets/ruleset-registry.ts +49 -49
  39. package/src/core/domain/rulesets/ruleset.contracts.ts +6 -6
  40. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +5 -5
  41. package/src/core/domain/temporal/index.ts +11 -11
  42. package/src/core/domain/temporal/temporal-range.ts +16 -16
  43. package/src/core/domain/temporal/temporal-snapshot.ts +24 -24
  44. package/src/core/domain/temporal/transaction-time.ts +30 -30
  45. package/src/core/domain/temporal/valid-time.ts +29 -29
  46. package/src/core/domain/value-object.ts +16 -16
  47. package/src/core/errors/app-error.ts +64 -64
  48. package/src/core/errors/authentication-error.ts +134 -134
  49. package/src/core/errors/authorization-error.ts +154 -154
  50. package/src/core/errors/business-rule-violation-error.ts +15 -15
  51. package/src/core/errors/conflict-error.ts +202 -201
  52. package/src/core/errors/error-codes.ts +48 -48
  53. package/src/core/errors/idempotency-error.ts +324 -320
  54. package/src/core/errors/index.ts +50 -50
  55. package/src/core/errors/integration-error.ts +120 -120
  56. package/src/core/errors/legacy-incompatible-error.ts +13 -13
  57. package/src/core/errors/not-found-error.ts +14 -14
  58. package/src/core/errors/serialization-error.ts +167 -167
  59. package/src/core/errors/temporal-error.ts +109 -107
  60. package/src/core/errors/types.ts +35 -35
  61. package/src/core/errors/unexpected-error.ts +10 -10
  62. package/src/core/errors/utils/index.ts +2 -2
  63. package/src/core/errors/utils/json-safe.ts +53 -53
  64. package/src/core/errors/validation-error.ts +18 -18
  65. package/src/core/exceptions/business-rule-violation-exception.ts +6 -6
  66. package/src/core/exceptions/domain-exception.ts +5 -5
  67. package/src/core/exceptions/entity-not-found-exception.ts +6 -6
  68. package/src/core/exceptions/invalid-state-transition-exception.ts +8 -8
  69. package/src/core/exceptions/invariant-violation-exception.ts +3 -3
  70. package/src/core/exceptions/validation-code.ts +35 -29
  71. package/src/core/exceptions/validation-exception.ts +19 -19
  72. package/src/core/exceptions/validation-field.ts +20 -19
  73. package/src/core/index.ts +7 -7
  74. package/src/core/policies/asof/asof.ts +47 -47
  75. package/src/core/policies/catalog/catalog.instance.ts +8 -6
  76. package/src/core/policies/catalog/index.ts +4 -4
  77. package/src/core/policies/catalog/policy-catalog-entry.ts +199 -197
  78. package/src/core/policies/catalog/policy-catalog.ts +101 -101
  79. package/src/core/policies/catalog/policy-key.ts +51 -51
  80. package/src/core/policies/context/context-builder.ts +335 -313
  81. package/src/core/policies/context/context-registry.instance.ts +9 -9
  82. package/src/core/policies/context/context-registry.ts +61 -61
  83. package/src/core/policies/context/context-resolver.ts +12 -12
  84. package/src/core/policies/context/context-seed.ts +19 -15
  85. package/src/core/policies/context/index.ts +9 -9
  86. package/src/core/policies/context/path.ts +135 -128
  87. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +56 -55
  88. package/src/core/policies/defs/index.ts +10 -10
  89. package/src/core/policies/defs/policy-definition-repository.ts +3 -3
  90. package/src/core/policies/defs/policy-definition.ts +143 -142
  91. package/src/core/policies/defs/policy-scope.ts +21 -19
  92. package/src/core/policies/defs/policy-semver.ts +51 -51
  93. package/src/core/policies/engines/compute-engine-registry.ts +43 -43
  94. package/src/core/policies/engines/compute-evaluator-registry.ts +20 -20
  95. package/src/core/policies/engines/compute-registry.ts +45 -45
  96. package/src/core/policies/engines/compute-types.ts +15 -15
  97. package/src/core/policies/engines/condition-evaluator-reporter.ts +17 -17
  98. package/src/core/policies/engines/gate-engine-registry.ts +27 -25
  99. package/src/core/policies/engines/gate-types.ts +28 -28
  100. package/src/core/policies/engines/index.ts +28 -28
  101. package/src/core/policies/engines/parse-compute-payload.ts +51 -45
  102. package/src/core/policies/engines/parse-gate-payload.ts +42 -42
  103. package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +39 -37
  104. package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +43 -41
  105. package/src/core/policies/engines/v1/compute/index.ts +6 -6
  106. package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +41 -39
  107. package/src/core/policies/engines/v1/condition-evaluator.ts +547 -505
  108. package/src/core/policies/engines/v1/condition-schema.ts +35 -35
  109. package/src/core/policies/engines/v1/condition-types.ts +21 -21
  110. package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +134 -130
  111. package/src/core/policies/engines/v1/gate/gate-types-v1.ts +5 -5
  112. package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +32 -30
  113. package/src/core/policies/engines/v1/gate/index.ts +4 -4
  114. package/src/core/policies/engines/v1/index.ts +8 -8
  115. package/src/core/policies/index.ts +72 -72
  116. package/src/core/policies/package/policy-package.ts +3 -3
  117. package/src/core/policies/policy-ids.ts +25 -25
  118. package/src/core/policies/resolver/policy-resolver.ts +34 -34
  119. package/src/core/policies/service/index.ts +6 -6
  120. package/src/core/policies/service/policy-evaluation-error.ts +141 -133
  121. package/src/core/policies/service/policy-service.ts +432 -419
  122. package/src/core/policies/utils/date.ts +3 -3
  123. package/src/core/policies/utils/hash.ts +61 -61
  124. package/src/core/result/outcome.ts +131 -126
  125. package/src/core/result/result.ts +130 -127
  126. package/src/core/shared/aggregate-version.ts +5 -5
  127. package/src/core/shared/hashing.ts +18 -18
  128. package/src/core/shared/immutable.ts +29 -29
  129. package/src/core/shared/temporal-guards.ts +9 -9
  130. package/src/core/versioning/domain-event-contracts.ts +40 -40
  131. package/src/core/versioning/version.ts +19 -19
  132. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +18 -18
  133. package/src/examples/rulesets/entity/order-invariants-v1.ts +31 -29
  134. package/src/examples/rulesets/entity/order-invariants-v2.ts +12 -12
  135. package/src/examples/rulesets/entity/order.ts +127 -127
  136. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +41 -39
  137. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +14 -12
  138. package/src/examples/rulesets/value-object/cpf.ts +24 -24
  139. package/src/examples/rulesets/value-object/customer.ts +42 -39
  140. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +27 -27
  141. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +13 -13
  142. package/src/examples/rulesets/value-object/person-name.ts +29 -26
  143. package/src/index.ts +2 -2
  144. package/src/version.ts +1 -1
@@ -4,28 +4,28 @@ import { type OrderCreationData, type OrderCreationRuleset } from "./order";
4
4
  class OrderCreationValidationError extends DomainException {}
5
5
 
6
6
  class OrderCreationRulesV1 implements OrderCreationRuleset {
7
- readonly id = "order-creation@1.0" as const;
8
- readonly description = "Order creation rules — version 1.0";
7
+ readonly id = "order-creation@1.0" as const;
8
+ readonly description = "Order creation rules — version 1.0";
9
9
 
10
- validate(data: OrderCreationData): void {
11
- if (!data.customerId) {
12
- throw new OrderCreationValidationError("customerId is required.");
13
- }
10
+ validate(data: OrderCreationData): void {
11
+ if (!data.customerId) {
12
+ throw new OrderCreationValidationError("customerId is required.");
13
+ }
14
14
 
15
- if (!data.items || data.items.length === 0) {
16
- throw new OrderCreationValidationError(
17
- "The order must contain at least one item.",
18
- );
19
- }
15
+ if (!data.items || data.items.length === 0) {
16
+ throw new OrderCreationValidationError(
17
+ "The order must contain at least one item.",
18
+ );
19
+ }
20
20
 
21
- for (const item of data.items) {
22
- if (item.quantity <= 0) {
23
- throw new OrderCreationValidationError(
24
- `Item "${item.sku}" quantity must be greater than zero. Received: ${item.quantity}.`,
25
- );
26
- }
21
+ for (const item of data.items) {
22
+ if (item.quantity <= 0) {
23
+ throw new OrderCreationValidationError(
24
+ `Item "${item.sku}" quantity must be greater than zero. Received: ${item.quantity}.`,
25
+ );
26
+ }
27
+ }
27
28
  }
28
- }
29
29
  }
30
30
 
31
31
  export { OrderCreationRulesV1 };
@@ -1,48 +1,50 @@
1
1
  import {
2
- DomainException,
3
- type RulesetId,
2
+ DomainException,
3
+ type RulesetId,
4
4
  } from "../../../core/domain/rulesets/entity-ruleset.contracts";
5
5
  import {
6
- type Order,
7
- type OrderInvariantRuleset,
8
- type OrderItem,
6
+ type Order,
7
+ type OrderInvariantRuleset,
8
+ type OrderItem,
9
9
  } from "./order";
10
10
 
11
11
  class OrderInvariantError extends DomainException {}
12
12
 
13
13
  class OrderInvariantsV1 implements OrderInvariantRuleset {
14
- readonly id: RulesetId = "order-invariants@1.0";
15
- readonly description: string = "Order invariants — version 1.0";
14
+ readonly id: RulesetId = "order-invariants@1.0";
15
+ readonly description: string = "Order invariants — version 1.0";
16
16
 
17
- assertCanAddItem(order: Order, _item: OrderItem): void {
18
- if (order.status !== "open") {
19
- throw new OrderInvariantError(
20
- `Cannot add an item to an order with status "${order.status}". The order must be open.`,
21
- );
17
+ assertCanAddItem(order: Order, _item: OrderItem): void {
18
+ if (order.status !== "open") {
19
+ throw new OrderInvariantError(
20
+ `Cannot add an item to an order with status "${order.status}". The order must be open.`,
21
+ );
22
+ }
22
23
  }
23
- }
24
24
 
25
- assertCanCancel(order: Order): void {
26
- if (order.status === "delivered") {
27
- throw new OrderInvariantError(
28
- "Cannot cancel an order that has already been delivered.",
29
- );
25
+ assertCanCancel(order: Order): void {
26
+ if (order.status === "delivered") {
27
+ throw new OrderInvariantError(
28
+ "Cannot cancel an order that has already been delivered.",
29
+ );
30
+ }
30
31
  }
31
- }
32
32
 
33
- assertCanCheckout(order: Order): void {
34
- if (order.items.length === 0) {
35
- throw new OrderInvariantError("Cannot check out an order with no items.");
33
+ assertCanCheckout(order: Order): void {
34
+ if (order.items.length === 0) {
35
+ throw new OrderInvariantError(
36
+ "Cannot check out an order with no items.",
37
+ );
38
+ }
36
39
  }
37
- }
38
40
 
39
- assertCanMarkAsDelivered(order: Order): void {
40
- if (order.status !== "shipped") {
41
- throw new OrderInvariantError(
42
- `Cannot mark as delivered an order with status "${order.status}". The order must be shipped.`,
43
- );
41
+ assertCanMarkAsDelivered(order: Order): void {
42
+ if (order.status !== "shipped") {
43
+ throw new OrderInvariantError(
44
+ `Cannot mark as delivered an order with status "${order.status}". The order must be shipped.`,
45
+ );
46
+ }
44
47
  }
45
- }
46
48
  }
47
49
 
48
50
  export { OrderInvariantsV1 };
@@ -1,6 +1,6 @@
1
1
  import {
2
- DomainException,
3
- type RulesetId,
2
+ DomainException,
3
+ type RulesetId,
4
4
  } from "../../../core/domain/rulesets/entity-ruleset.contracts";
5
5
  import { type Order } from "./order";
6
6
  import { OrderInvariantsV1 } from "./order-invariants-v1";
@@ -10,19 +10,19 @@ class OrderCancellationWindowError extends DomainException {}
10
10
  const FORTY_EIGHT_HOURS_MS = 48 * 60 * 60 * 1000;
11
11
 
12
12
  class OrderInvariantsV2 extends OrderInvariantsV1 {
13
- override readonly id: RulesetId = "order-invariants@2.0";
14
- override readonly description = "Order invariants — version 2.0";
13
+ override readonly id: RulesetId = "order-invariants@2.0";
14
+ override readonly description = "Order invariants — version 2.0";
15
15
 
16
- override assertCanCancel(order: Order): void {
17
- super.assertCanCancel(order);
16
+ override assertCanCancel(order: Order): void {
17
+ super.assertCanCancel(order);
18
18
 
19
- const ageMs = Date.now() - order.createdAt.getTime();
20
- if (ageMs > FORTY_EIGHT_HOURS_MS) {
21
- throw new OrderCancellationWindowError(
22
- "Cannot cancel an order created more than 48 hours ago.",
23
- );
19
+ const ageMs = Date.now() - order.createdAt.getTime();
20
+ if (ageMs > FORTY_EIGHT_HOURS_MS) {
21
+ throw new OrderCancellationWindowError(
22
+ "Cannot cancel an order created more than 48 hours ago.",
23
+ );
24
+ }
24
25
  }
25
- }
26
26
  }
27
27
 
28
28
  export { OrderInvariantsV2 };
@@ -1,32 +1,32 @@
1
1
  import {
2
- type CreationRuleset,
3
- type InvariantRuleset,
4
- type RulesetId,
2
+ type CreationRuleset,
3
+ type InvariantRuleset,
4
+ type RulesetId,
5
5
  } from "../../../core/domain/rulesets/entity-ruleset.contracts";
6
6
 
7
7
  type OrderStatus = "open" | "cancelled" | "shipped" | "delivered";
8
8
 
9
9
  interface OrderItem {
10
- readonly sku: string;
11
- readonly quantity: number;
10
+ readonly sku: string;
11
+ readonly quantity: number;
12
12
  }
13
13
 
14
14
  interface OrderCreationData {
15
- readonly id: string;
16
- readonly customerId: string;
17
- readonly items: readonly OrderItem[];
18
- readonly createdAt: Date;
15
+ readonly id: string;
16
+ readonly customerId: string;
17
+ readonly items: readonly OrderItem[];
18
+ readonly createdAt: Date;
19
19
  }
20
20
 
21
21
  interface OrderSnapshot extends OrderCreationData {
22
- readonly status: OrderStatus;
23
- readonly creationRulesetId: RulesetId;
24
- readonly aggregateVersion: number;
22
+ readonly status: OrderStatus;
23
+ readonly creationRulesetId: RulesetId;
24
+ readonly aggregateVersion: number;
25
25
  }
26
26
 
27
27
  interface OrderCancelledEvent {
28
- readonly type: "OrderCancelled";
29
- readonly invariantRulesetId: RulesetId;
28
+ readonly type: "OrderCancelled";
29
+ readonly invariantRulesetId: RulesetId;
30
30
  }
31
31
 
32
32
  type OrderDomainEvent = OrderCancelledEvent;
@@ -34,129 +34,129 @@ type OrderDomainEvent = OrderCancelledEvent;
34
34
  type OrderCreationRuleset = CreationRuleset<OrderCreationData>;
35
35
 
36
36
  interface OrderInvariantRuleset extends InvariantRuleset {
37
- assertCanAddItem(order: Order, item: OrderItem): void;
38
- assertCanCancel(order: Order): void;
39
- assertCanCheckout(order: Order): void;
40
- assertCanMarkAsDelivered(order: Order): void;
37
+ assertCanAddItem(order: Order, item: OrderItem): void;
38
+ assertCanCancel(order: Order): void;
39
+ assertCanCheckout(order: Order): void;
40
+ assertCanMarkAsDelivered(order: Order): void;
41
41
  }
42
42
 
43
43
  interface OrderStatic {
44
- create(data: OrderCreationData, ruleset: OrderCreationRuleset): Order;
45
- reconstitute(snapshot: OrderSnapshot): Order;
44
+ create(data: OrderCreationData, ruleset: OrderCreationRuleset): Order;
45
+ reconstitute(snapshot: OrderSnapshot): Order;
46
46
  }
47
47
 
48
48
  class Order {
49
- private readonly _id: string;
50
- private readonly _customerId: string;
51
- private _status: OrderStatus;
52
- private readonly _items: OrderItem[];
53
- private readonly _createdAt: Date;
54
- private readonly _creationRulesetId: RulesetId;
55
- private _aggregateVersion: number;
56
- private readonly _domainEvents: OrderDomainEvent[] = [];
57
-
58
- private constructor(snapshot: OrderSnapshot) {
59
- this._id = snapshot.id;
60
- this._customerId = snapshot.customerId;
61
- this._status = snapshot.status;
62
- this._items = [...snapshot.items];
63
- this._createdAt = new Date(snapshot.createdAt.getTime());
64
- this._creationRulesetId = snapshot.creationRulesetId;
65
- this._aggregateVersion = snapshot.aggregateVersion;
66
- }
67
-
68
- get id(): string {
69
- return this._id;
70
- }
71
-
72
- get customerId(): string {
73
- return this._customerId;
74
- }
75
-
76
- get status(): OrderStatus {
77
- return this._status;
78
- }
79
-
80
- get items(): readonly OrderItem[] {
81
- return this._items;
82
- }
83
-
84
- get createdAt(): Date {
85
- return new Date(this._createdAt.getTime());
86
- }
87
-
88
- get creationRulesetId(): RulesetId {
89
- return this._creationRulesetId;
90
- }
91
-
92
- get aggregateVersion(): number {
93
- return this._aggregateVersion;
94
- }
95
-
96
- addItem(item: OrderItem, ruleset: OrderInvariantRuleset): void {
97
- ruleset.assertCanAddItem(this, item);
98
- this._items.push(item);
99
- this._aggregateVersion += 1;
100
- }
101
-
102
- cancel(ruleset: OrderInvariantRuleset): void {
103
- ruleset.assertCanCancel(this);
104
- this._status = "cancelled";
105
- this._aggregateVersion += 1;
106
- this._domainEvents.push({
107
- type: "OrderCancelled",
108
- invariantRulesetId: ruleset.id,
109
- });
110
- }
111
-
112
- checkout(ruleset: OrderInvariantRuleset): void {
113
- ruleset.assertCanCheckout(this);
114
- this._status = "shipped";
115
- this._aggregateVersion += 1;
116
- }
117
-
118
- markAsDelivered(ruleset: OrderInvariantRuleset): void {
119
- ruleset.assertCanMarkAsDelivered(this);
120
- this._status = "delivered";
121
- this._aggregateVersion += 1;
122
- }
123
-
124
- pullDomainEvents(): readonly OrderDomainEvent[] {
125
- const events = [...this._domainEvents];
126
- this._domainEvents.length = 0;
127
- return events;
128
- }
129
-
130
- static create(
131
- data: OrderCreationData,
132
- ruleset: CreationRuleset<OrderCreationData>,
133
- ): Order {
134
- ruleset.validate(data);
135
- return new Order({
136
- ...data,
137
- status: "open",
138
- creationRulesetId: ruleset.id,
139
- aggregateVersion: 0,
140
- });
141
- }
142
-
143
- static reconstitute(snapshot: OrderSnapshot): Order {
144
- return new Order(snapshot);
145
- }
49
+ private readonly _id: string;
50
+ private readonly _customerId: string;
51
+ private _status: OrderStatus;
52
+ private readonly _items: OrderItem[];
53
+ private readonly _createdAt: Date;
54
+ private readonly _creationRulesetId: RulesetId;
55
+ private _aggregateVersion: number;
56
+ private readonly _domainEvents: OrderDomainEvent[] = [];
57
+
58
+ private constructor(snapshot: OrderSnapshot) {
59
+ this._id = snapshot.id;
60
+ this._customerId = snapshot.customerId;
61
+ this._status = snapshot.status;
62
+ this._items = [...snapshot.items];
63
+ this._createdAt = new Date(snapshot.createdAt.getTime());
64
+ this._creationRulesetId = snapshot.creationRulesetId;
65
+ this._aggregateVersion = snapshot.aggregateVersion;
66
+ }
67
+
68
+ get id(): string {
69
+ return this._id;
70
+ }
71
+
72
+ get customerId(): string {
73
+ return this._customerId;
74
+ }
75
+
76
+ get status(): OrderStatus {
77
+ return this._status;
78
+ }
79
+
80
+ get items(): readonly OrderItem[] {
81
+ return this._items;
82
+ }
83
+
84
+ get createdAt(): Date {
85
+ return new Date(this._createdAt.getTime());
86
+ }
87
+
88
+ get creationRulesetId(): RulesetId {
89
+ return this._creationRulesetId;
90
+ }
91
+
92
+ get aggregateVersion(): number {
93
+ return this._aggregateVersion;
94
+ }
95
+
96
+ addItem(item: OrderItem, ruleset: OrderInvariantRuleset): void {
97
+ ruleset.assertCanAddItem(this, item);
98
+ this._items.push(item);
99
+ this._aggregateVersion += 1;
100
+ }
101
+
102
+ cancel(ruleset: OrderInvariantRuleset): void {
103
+ ruleset.assertCanCancel(this);
104
+ this._status = "cancelled";
105
+ this._aggregateVersion += 1;
106
+ this._domainEvents.push({
107
+ type: "OrderCancelled",
108
+ invariantRulesetId: ruleset.id,
109
+ });
110
+ }
111
+
112
+ checkout(ruleset: OrderInvariantRuleset): void {
113
+ ruleset.assertCanCheckout(this);
114
+ this._status = "shipped";
115
+ this._aggregateVersion += 1;
116
+ }
117
+
118
+ markAsDelivered(ruleset: OrderInvariantRuleset): void {
119
+ ruleset.assertCanMarkAsDelivered(this);
120
+ this._status = "delivered";
121
+ this._aggregateVersion += 1;
122
+ }
123
+
124
+ pullDomainEvents(): readonly OrderDomainEvent[] {
125
+ const events = [...this._domainEvents];
126
+ this._domainEvents.length = 0;
127
+ return events;
128
+ }
129
+
130
+ static create(
131
+ data: OrderCreationData,
132
+ ruleset: CreationRuleset<OrderCreationData>,
133
+ ): Order {
134
+ ruleset.validate(data);
135
+ return new Order({
136
+ ...data,
137
+ status: "open",
138
+ creationRulesetId: ruleset.id,
139
+ aggregateVersion: 0,
140
+ });
141
+ }
142
+
143
+ static reconstitute(snapshot: OrderSnapshot): Order {
144
+ return new Order(snapshot);
145
+ }
146
146
  }
147
147
 
148
148
  const _typeCheck: OrderStatic = Order;
149
149
  void _typeCheck;
150
150
 
151
151
  export {
152
- Order,
153
- type OrderCancelledEvent,
154
- type OrderCreationData,
155
- type OrderCreationRuleset,
156
- type OrderDomainEvent,
157
- type OrderInvariantRuleset,
158
- type OrderItem,
159
- type OrderSnapshot,
160
- type OrderStatic,
161
- type OrderStatus,
152
+ Order,
153
+ type OrderCancelledEvent,
154
+ type OrderCreationData,
155
+ type OrderCreationRuleset,
156
+ type OrderDomainEvent,
157
+ type OrderInvariantRuleset,
158
+ type OrderItem,
159
+ type OrderSnapshot,
160
+ type OrderStatic,
161
+ type OrderStatus,
162
162
  };
@@ -1,52 +1,54 @@
1
1
  import {
2
- DomainException,
3
- type ValueObjectRuleset,
2
+ DomainException,
3
+ type ValueObjectRuleset,
4
4
  } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
5
 
6
6
  class CPFValidationError extends DomainException {}
7
7
 
8
8
  function validateCheckDigits(digits: number[]): boolean {
9
- // First check digit: multiply first 9 digits by weights 10..2
10
- let sum = 0;
11
- for (let i = 0; i < 9; i++) {
12
- sum += digits[i]! * (10 - i);
13
- }
14
- const rem1 = sum % 11;
15
- const expected1 = rem1 < 2 ? 0 : 11 - rem1;
16
- if (digits[9] !== expected1) return false;
17
-
18
- // Second check digit: multiply first 10 digits by weights 11..2
19
- sum = 0;
20
- for (let i = 0; i < 10; i++) {
21
- sum += digits[i]! * (11 - i);
22
- }
23
- const rem2 = sum % 11;
24
- const expected2 = rem2 < 2 ? 0 : 11 - rem2;
25
- return digits[10] === expected2;
26
- }
27
-
28
- class CPFRulesV1 implements ValueObjectRuleset<string> {
29
- readonly id = "cpf-rules@1.0" as const;
30
- readonly description = "CPF validation using the check-digit algorithm";
31
-
32
- validate(value: string): void {
33
- if (!/^\d{11}$/.test(value)) {
34
- throw new CPFValidationError(
35
- `CPF must contain exactly 11 numeric digits. Received: "${value}".`,
36
- );
9
+ // First check digit: multiply first 9 digits by weights 10..2
10
+ let sum = 0;
11
+ for (let i = 0; i < 9; i++) {
12
+ sum += digits[i]! * (10 - i);
37
13
  }
38
-
39
- if (/^(\d)\1{10}$/.test(value)) {
40
- throw new CPFValidationError(
41
- `A CPF with all repeating digits is invalid: "${value}".`,
42
- );
14
+ const rem1 = sum % 11;
15
+ const expected1 = rem1 < 2 ? 0 : 11 - rem1;
16
+ if (digits[9] !== expected1) return false;
17
+
18
+ // Second check digit: multiply first 10 digits by weights 11..2
19
+ sum = 0;
20
+ for (let i = 0; i < 10; i++) {
21
+ sum += digits[i]! * (11 - i);
43
22
  }
23
+ const rem2 = sum % 11;
24
+ const expected2 = rem2 < 2 ? 0 : 11 - rem2;
25
+ return digits[10] === expected2;
26
+ }
44
27
 
45
- const digits = value.split("").map(Number);
46
- if (!validateCheckDigits(digits)) {
47
- throw new CPFValidationError(`Invalid check digits for CPF "${value}".`);
28
+ class CPFRulesV1 implements ValueObjectRuleset<string> {
29
+ readonly id = "cpf-rules@1.0" as const;
30
+ readonly description = "CPF validation using the check-digit algorithm";
31
+
32
+ validate(value: string): void {
33
+ if (!/^\d{11}$/.test(value)) {
34
+ throw new CPFValidationError(
35
+ `CPF must contain exactly 11 numeric digits. Received: "${value}".`,
36
+ );
37
+ }
38
+
39
+ if (/^(\d)\1{10}$/.test(value)) {
40
+ throw new CPFValidationError(
41
+ `A CPF with all repeating digits is invalid: "${value}".`,
42
+ );
43
+ }
44
+
45
+ const digits = value.split("").map(Number);
46
+ if (!validateCheckDigits(digits)) {
47
+ throw new CPFValidationError(
48
+ `Invalid check digits for CPF "${value}".`,
49
+ );
50
+ }
48
51
  }
49
- }
50
52
  }
51
53
 
52
54
  export { CPFRulesV1 };
@@ -1,27 +1,29 @@
1
1
  import {
2
- DomainException,
3
- type ValueObjectRuleset,
2
+ DomainException,
3
+ type ValueObjectRuleset,
4
4
  } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
5
  import { CPFRulesV1 } from "./cpf-rules-v1";
6
6
 
7
7
  class CPFBlocklistError extends DomainException {}
8
8
 
9
9
  class CPFRulesV2 implements ValueObjectRuleset<string> {
10
- readonly id = "cpf-rules@2.0" as const;
11
- readonly description =
12
- "CPF validation with check-digit algorithm and blocklist";
10
+ readonly id = "cpf-rules@2.0" as const;
11
+ readonly description =
12
+ "CPF validation with check-digit algorithm and blocklist";
13
13
 
14
- private readonly v1 = new CPFRulesV1();
14
+ private readonly v1 = new CPFRulesV1();
15
15
 
16
- constructor(private readonly blocklist: readonly string[]) {}
16
+ constructor(private readonly blocklist: readonly string[]) {}
17
17
 
18
- validate(value: string): void {
19
- this.v1.validate(value);
18
+ validate(value: string): void {
19
+ this.v1.validate(value);
20
20
 
21
- if (this.blocklist.includes(value)) {
22
- throw new CPFBlocklistError(`CPF "${value}" appears on the blocklist.`);
21
+ if (this.blocklist.includes(value)) {
22
+ throw new CPFBlocklistError(
23
+ `CPF "${value}" appears on the blocklist.`,
24
+ );
25
+ }
23
26
  }
24
- }
25
27
  }
26
28
 
27
29
  export { CPFRulesV2 };
@@ -1,34 +1,34 @@
1
1
  import {
2
- type RulesetId,
3
- type ValueObjectRuleset,
2
+ type RulesetId,
3
+ type ValueObjectRuleset,
4
4
  } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
5
 
6
6
  interface CPFStatic {
7
- create(raw: string, ruleset: ValueObjectRuleset<string>): CPF;
8
- reconstitute(value: string, rulesetId: RulesetId): CPF;
7
+ create(raw: string, ruleset: ValueObjectRuleset<string>): CPF;
8
+ reconstitute(value: string, rulesetId: RulesetId): CPF;
9
9
  }
10
10
 
11
11
  class CPF {
12
- readonly value: string;
13
- readonly appliedRulesetId: RulesetId;
14
-
15
- private constructor(value: string, appliedRulesetId: RulesetId) {
16
- this.value = value;
17
- this.appliedRulesetId = appliedRulesetId;
18
- }
19
-
20
- equals(other: CPF): boolean {
21
- return this.value === other.value;
22
- }
23
-
24
- static create(raw: string, ruleset: ValueObjectRuleset<string>): CPF {
25
- ruleset.validate(raw);
26
- return new CPF(raw, ruleset.id);
27
- }
28
-
29
- static reconstitute(value: string, rulesetId: RulesetId): CPF {
30
- return new CPF(value, rulesetId);
31
- }
12
+ readonly value: string;
13
+ readonly appliedRulesetId: RulesetId;
14
+
15
+ private constructor(value: string, appliedRulesetId: RulesetId) {
16
+ this.value = value;
17
+ this.appliedRulesetId = appliedRulesetId;
18
+ }
19
+
20
+ equals(other: CPF): boolean {
21
+ return this.value === other.value;
22
+ }
23
+
24
+ static create(raw: string, ruleset: ValueObjectRuleset<string>): CPF {
25
+ ruleset.validate(raw);
26
+ return new CPF(raw, ruleset.id);
27
+ }
28
+
29
+ static reconstitute(value: string, rulesetId: RulesetId): CPF {
30
+ return new CPF(value, rulesetId);
31
+ }
32
32
  }
33
33
 
34
34
  const _typeCheck: CPFStatic = CPF;