@cullet/erp-core 1.0.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 (182) hide show
  1. package/KIT_CONTEXT.md +39 -0
  2. package/README.md +110 -0
  3. package/dist/errors/index.d.ts +2 -0
  4. package/dist/errors/index.js +3 -0
  5. package/dist/exceptions/validation-field.d.ts +2 -0
  6. package/dist/exceptions/validation-field.js +2 -0
  7. package/dist/gate-engine-registry.js +260 -0
  8. package/dist/gate-engine-registry.js.map +1 -0
  9. package/dist/gate-types.d.ts +307 -0
  10. package/dist/gate-v1-payload.schema.js +677 -0
  11. package/dist/gate-v1-payload.schema.js.map +1 -0
  12. package/dist/index.d.ts +88 -0
  13. package/dist/index.js +153 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/outcome.js +92 -0
  16. package/dist/outcome.js.map +1 -0
  17. package/dist/parse-gate-payload.d.ts +136 -0
  18. package/dist/policies/engines/index.d.ts +3 -0
  19. package/dist/policies/engines/index.js +2 -0
  20. package/dist/policies/engines/v1/gate/index.d.ts +115 -0
  21. package/dist/policies/engines/v1/gate/index.js +84 -0
  22. package/dist/policies/engines/v1/gate/index.js.map +1 -0
  23. package/dist/policies/index.d.ts +4 -0
  24. package/dist/policies/index.js +5 -0
  25. package/dist/policy-service.d.ts +541 -0
  26. package/dist/policy-service.js +992 -0
  27. package/dist/policy-service.js.map +1 -0
  28. package/dist/validation-code.js +210 -0
  29. package/dist/validation-code.js.map +1 -0
  30. package/dist/validation-error.d.ts +686 -0
  31. package/dist/validation-error.js +757 -0
  32. package/dist/validation-error.js.map +1 -0
  33. package/dist/validation-field.d.ts +12 -0
  34. package/dist/validation-field.js +23 -0
  35. package/dist/validation-field.js.map +1 -0
  36. package/meta.json +66 -0
  37. package/package.json +59 -0
  38. package/src/core/application/commands/command.ts +28 -0
  39. package/src/core/application/commands/index.ts +2 -0
  40. package/src/core/application/commands/requested-by.ts +97 -0
  41. package/src/core/application/index.ts +31 -0
  42. package/src/core/application/policy-error-mapper.ts +60 -0
  43. package/src/core/application/ports/index.ts +14 -0
  44. package/src/core/application/ports/logger.port.ts +10 -0
  45. package/src/core/application/ports/metrics.port.ts +9 -0
  46. package/src/core/application/ports/policy-port.ts +20 -0
  47. package/src/core/application/ports/repository.port.ts +7 -0
  48. package/src/core/application/ports/temporal-repository.port.ts +14 -0
  49. package/src/core/application/ports/tracer.port.ts +16 -0
  50. package/src/core/application/queries/index.ts +2 -0
  51. package/src/core/application/queries/query.ts +53 -0
  52. package/src/core/application/temporal/index.ts +11 -0
  53. package/src/core/application/temporal/temporal-context.ts +41 -0
  54. package/src/core/application/temporal/temporal-use-case.ts +41 -0
  55. package/src/core/application/use-case.ts +24 -0
  56. package/src/core/config/core-config.instance.ts +14 -0
  57. package/src/core/config/core-config.ts +87 -0
  58. package/src/core/config/index.ts +12 -0
  59. package/src/core/config/policy-reporter.ts +60 -0
  60. package/src/core/config/silent-policy-reporter.ts +5 -0
  61. package/src/core/domain/entity.ts +69 -0
  62. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +16 -0
  63. package/src/core/domain/rulesets/ruleset-registry.ts +71 -0
  64. package/src/core/domain/rulesets/ruleset.contracts.ts +15 -0
  65. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +13 -0
  66. package/src/core/domain/temporal/index.ts +18 -0
  67. package/src/core/domain/temporal/temporal-range.ts +53 -0
  68. package/src/core/domain/temporal/temporal-snapshot.ts +47 -0
  69. package/src/core/domain/temporal/transaction-time.ts +60 -0
  70. package/src/core/domain/temporal/valid-time.ts +57 -0
  71. package/src/core/domain/value-object.ts +30 -0
  72. package/src/core/errors/app-error.ts +85 -0
  73. package/src/core/errors/authentication-error.ts +171 -0
  74. package/src/core/errors/authorization-error.ts +204 -0
  75. package/src/core/errors/business-rule-violation-error.ts +28 -0
  76. package/src/core/errors/conflict-error.ts +246 -0
  77. package/src/core/errors/error-codes.ts +60 -0
  78. package/src/core/errors/idempotency-error.ts +372 -0
  79. package/src/core/errors/index.ts +99 -0
  80. package/src/core/errors/integration-error.ts +157 -0
  81. package/src/core/errors/legacy-incompatible-error.ts +26 -0
  82. package/src/core/errors/not-found-error.ts +27 -0
  83. package/src/core/errors/serialization-error.ts +233 -0
  84. package/src/core/errors/temporal-error.ts +145 -0
  85. package/src/core/errors/types.ts +74 -0
  86. package/src/core/errors/unexpected-error.ts +22 -0
  87. package/src/core/errors/utils/index.ts +4 -0
  88. package/src/core/errors/utils/json-safe.ts +93 -0
  89. package/src/core/errors/validation-error.ts +34 -0
  90. package/src/core/exceptions/business-rule-violation-exception.ts +12 -0
  91. package/src/core/exceptions/domain-exception.ts +9 -0
  92. package/src/core/exceptions/entity-not-found-exception.ts +12 -0
  93. package/src/core/exceptions/invalid-state-transition-exception.ts +15 -0
  94. package/src/core/exceptions/invariant-violation-exception.ts +9 -0
  95. package/src/core/exceptions/validation-code.ts +39 -0
  96. package/src/core/exceptions/validation-exception.ts +39 -0
  97. package/src/core/exceptions/validation-field.ts +32 -0
  98. package/src/core/index.ts +15 -0
  99. package/src/core/policies/asof/asof.ts +68 -0
  100. package/src/core/policies/asof/index.ts +2 -0
  101. package/src/core/policies/catalog/catalog-types.ts +12 -0
  102. package/src/core/policies/catalog/catalog.instance.ts +21 -0
  103. package/src/core/policies/catalog/index.ts +11 -0
  104. package/src/core/policies/catalog/policy-catalog-entry.ts +220 -0
  105. package/src/core/policies/catalog/policy-catalog.ts +124 -0
  106. package/src/core/policies/catalog/policy-key.ts +78 -0
  107. package/src/core/policies/context/context-builder.ts +391 -0
  108. package/src/core/policies/context/context-registry.instance.ts +26 -0
  109. package/src/core/policies/context/context-registry.ts +95 -0
  110. package/src/core/policies/context/context-resolver.ts +31 -0
  111. package/src/core/policies/context/context-seed.ts +32 -0
  112. package/src/core/policies/context/index.ts +21 -0
  113. package/src/core/policies/context/path.ts +152 -0
  114. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +73 -0
  115. package/src/core/policies/defs/index.ts +20 -0
  116. package/src/core/policies/defs/policy-definition-repository.ts +8 -0
  117. package/src/core/policies/defs/policy-definition.ts +192 -0
  118. package/src/core/policies/defs/policy-payload.contracts.ts +13 -0
  119. package/src/core/policies/defs/policy-scope.ts +53 -0
  120. package/src/core/policies/defs/policy-semver.ts +83 -0
  121. package/src/core/policies/engines/compute-engine-registry.ts +57 -0
  122. package/src/core/policies/engines/compute-evaluator-registry.ts +28 -0
  123. package/src/core/policies/engines/compute-payload.ts +5 -0
  124. package/src/core/policies/engines/compute-registry.ts +67 -0
  125. package/src/core/policies/engines/compute-types.ts +51 -0
  126. package/src/core/policies/engines/condition-evaluator-reporter.ts +34 -0
  127. package/src/core/policies/engines/gate-engine-registry.ts +38 -0
  128. package/src/core/policies/engines/gate-payload.ts +5 -0
  129. package/src/core/policies/engines/gate-types.ts +63 -0
  130. package/src/core/policies/engines/index.ts +48 -0
  131. package/src/core/policies/engines/parse-compute-payload.ts +71 -0
  132. package/src/core/policies/engines/parse-gate-payload.ts +68 -0
  133. package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +55 -0
  134. package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +75 -0
  135. package/src/core/policies/engines/v1/compute/index.ts +12 -0
  136. package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +54 -0
  137. package/src/core/policies/engines/v1/condition-evaluator.ts +592 -0
  138. package/src/core/policies/engines/v1/condition-schema.ts +50 -0
  139. package/src/core/policies/engines/v1/condition-types.ts +41 -0
  140. package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +157 -0
  141. package/src/core/policies/engines/v1/gate/gate-types-v1.ts +12 -0
  142. package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +46 -0
  143. package/src/core/policies/engines/v1/gate/index.ts +9 -0
  144. package/src/core/policies/engines/v1/index.ts +13 -0
  145. package/src/core/policies/index.ts +132 -0
  146. package/src/core/policies/package/policy-package.ts +17 -0
  147. package/src/core/policies/policy-ids.ts +60 -0
  148. package/src/core/policies/resolver/index.ts +1 -0
  149. package/src/core/policies/resolver/policy-resolver.ts +57 -0
  150. package/src/core/policies/service/index.ts +10 -0
  151. package/src/core/policies/service/policy-evaluation-error.ts +148 -0
  152. package/src/core/policies/service/policy-service.ts +493 -0
  153. package/src/core/policies/utils/date.ts +7 -0
  154. package/src/core/policies/utils/hash.ts +90 -0
  155. package/src/core/policies/utils/index.ts +3 -0
  156. package/src/core/policies/utils/result.ts +4 -0
  157. package/src/core/result/outcome.ts +158 -0
  158. package/src/core/result/result.ts +153 -0
  159. package/src/core/shared/aggregate-version.ts +11 -0
  160. package/src/core/shared/hashing.ts +38 -0
  161. package/src/core/shared/immutable.ts +46 -0
  162. package/src/core/shared/temporal-guards.ts +22 -0
  163. package/src/core/versioning/domain-event-contracts.ts +73 -0
  164. package/src/core/versioning/version.ts +34 -0
  165. package/src/errors/index.ts +1 -0
  166. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +31 -0
  167. package/src/examples/rulesets/entity/order-invariants-v1.ts +48 -0
  168. package/src/examples/rulesets/entity/order-invariants-v2.ts +28 -0
  169. package/src/examples/rulesets/entity/order.ts +162 -0
  170. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +52 -0
  171. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +27 -0
  172. package/src/examples/rulesets/value-object/cpf.ts +37 -0
  173. package/src/examples/rulesets/value-object/customer.ts +67 -0
  174. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +37 -0
  175. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +27 -0
  176. package/src/examples/rulesets/value-object/person-name.ts +39 -0
  177. package/src/exceptions/validation-field.ts +1 -0
  178. package/src/index.ts +11 -0
  179. package/src/policies/engines/index.ts +1 -0
  180. package/src/policies/engines/v1/gate/index.ts +1 -0
  181. package/src/policies/index.ts +1 -0
  182. package/src/version.ts +7 -0
@@ -0,0 +1,162 @@
1
+ import {
2
+ type CreationRuleset,
3
+ type InvariantRuleset,
4
+ type RulesetId,
5
+ } from "../../../core/domain/rulesets/entity-ruleset.contracts";
6
+
7
+ type OrderStatus = "open" | "cancelled" | "shipped" | "delivered";
8
+
9
+ interface OrderItem {
10
+ readonly sku: string;
11
+ readonly quantity: number;
12
+ }
13
+
14
+ interface OrderCreationData {
15
+ readonly id: string;
16
+ readonly customerId: string;
17
+ readonly items: readonly OrderItem[];
18
+ readonly createdAt: Date;
19
+ }
20
+
21
+ interface OrderSnapshot extends OrderCreationData {
22
+ readonly status: OrderStatus;
23
+ readonly creationRulesetId: RulesetId;
24
+ readonly aggregateVersion: number;
25
+ }
26
+
27
+ interface OrderCancelledEvent {
28
+ readonly type: "OrderCancelled";
29
+ readonly invariantRulesetId: RulesetId;
30
+ }
31
+
32
+ type OrderDomainEvent = OrderCancelledEvent;
33
+
34
+ type OrderCreationRuleset = CreationRuleset<OrderCreationData>;
35
+
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;
41
+ }
42
+
43
+ interface OrderStatic {
44
+ create(data: OrderCreationData, ruleset: OrderCreationRuleset): Order;
45
+ reconstitute(snapshot: OrderSnapshot): Order;
46
+ }
47
+
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
+ }
146
+ }
147
+
148
+ const _typeCheck: OrderStatic = Order;
149
+ void _typeCheck;
150
+
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,
162
+ };
@@ -0,0 +1,52 @@
1
+ import {
2
+ DomainException,
3
+ type ValueObjectRuleset,
4
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
+
6
+ class CPFValidationError extends DomainException {}
7
+
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
+ );
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(`Invalid check digits for CPF "${value}".`);
48
+ }
49
+ }
50
+ }
51
+
52
+ export { CPFRulesV1 };
@@ -0,0 +1,27 @@
1
+ import {
2
+ DomainException,
3
+ type ValueObjectRuleset,
4
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
+ import { CPFRulesV1 } from "./cpf-rules-v1";
6
+
7
+ class CPFBlocklistError extends DomainException {}
8
+
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";
13
+
14
+ private readonly v1 = new CPFRulesV1();
15
+
16
+ constructor(private readonly blocklist: readonly string[]) {}
17
+
18
+ validate(value: string): void {
19
+ this.v1.validate(value);
20
+
21
+ if (this.blocklist.includes(value)) {
22
+ throw new CPFBlocklistError(`CPF "${value}" appears on the blocklist.`);
23
+ }
24
+ }
25
+ }
26
+
27
+ export { CPFRulesV2 };
@@ -0,0 +1,37 @@
1
+ import {
2
+ type RulesetId,
3
+ type ValueObjectRuleset,
4
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
+
6
+ interface CPFStatic {
7
+ create(raw: string, ruleset: ValueObjectRuleset<string>): CPF;
8
+ reconstitute(value: string, rulesetId: RulesetId): CPF;
9
+ }
10
+
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
+ }
32
+ }
33
+
34
+ const _typeCheck: CPFStatic = CPF;
35
+ void _typeCheck;
36
+
37
+ export { CPF, type CPFStatic };
@@ -0,0 +1,67 @@
1
+ import { CPF } from "./cpf";
2
+ import { PersonName } from "./person-name";
3
+ import {
4
+ type RulesetId,
5
+ type ValueObjectRuleset,
6
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
7
+
8
+ interface CustomerCreateData {
9
+ readonly cpf: string;
10
+ readonly name: string;
11
+ }
12
+
13
+ interface CustomerCreateRulesets {
14
+ readonly cpf: ValueObjectRuleset<string>;
15
+ readonly name: ValueObjectRuleset<string>;
16
+ }
17
+
18
+ interface CustomerSnapshot {
19
+ readonly cpf_value: string;
20
+ readonly cpf_ruleset: RulesetId;
21
+ readonly name_value: string;
22
+ readonly name_ruleset: RulesetId;
23
+ }
24
+
25
+ interface CustomerStatic {
26
+ create(data: CustomerCreateData, rulesets: CustomerCreateRulesets): Customer;
27
+ reconstitute(snapshot: CustomerSnapshot): Customer;
28
+ }
29
+
30
+ class Customer {
31
+ readonly cpf: CPF;
32
+ readonly name: PersonName;
33
+
34
+ private constructor(cpf: CPF, name: PersonName) {
35
+ this.cpf = cpf;
36
+ this.name = name;
37
+ }
38
+
39
+ static create(
40
+ data: CustomerCreateData,
41
+ rulesets: CustomerCreateRulesets,
42
+ ): Customer {
43
+ const cpf = CPF.create(data.cpf, rulesets.cpf);
44
+ const name = PersonName.create(data.name, rulesets.name);
45
+ return new Customer(cpf, name);
46
+ }
47
+
48
+ static reconstitute(snapshot: CustomerSnapshot): Customer {
49
+ const cpf = CPF.reconstitute(snapshot.cpf_value, snapshot.cpf_ruleset);
50
+ const name = PersonName.reconstitute(
51
+ snapshot.name_value,
52
+ snapshot.name_ruleset,
53
+ );
54
+ return new Customer(cpf, name);
55
+ }
56
+ }
57
+
58
+ const _typeCheck: CustomerStatic = Customer;
59
+ void _typeCheck;
60
+
61
+ export {
62
+ Customer,
63
+ type CustomerCreateData,
64
+ type CustomerCreateRulesets,
65
+ type CustomerSnapshot,
66
+ type CustomerStatic,
67
+ };
@@ -0,0 +1,37 @@
1
+ import {
2
+ DomainException,
3
+ type ValueObjectRuleset,
4
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
+
6
+ class PersonNameValidationError extends DomainException {}
7
+
8
+ class PersonNameRulesV1 implements ValueObjectRuleset<string> {
9
+ readonly id = "person-name-rules@1.0" as const;
10
+ readonly description = "Name validation requiring at least two words";
11
+
12
+ validate(value: string): void {
13
+ const trimmed = value.trim();
14
+
15
+ if (trimmed.length === 0) {
16
+ throw new PersonNameValidationError("Name cannot be empty.");
17
+ }
18
+
19
+ const words = trimmed.split(/\s+/);
20
+
21
+ if (words.length < 2) {
22
+ throw new PersonNameValidationError(
23
+ `Name must have at least two words. Received: "${value}".`,
24
+ );
25
+ }
26
+
27
+ for (const word of words) {
28
+ if (word.length < 2) {
29
+ throw new PersonNameValidationError(
30
+ `Each word of the name must be at least two characters long. Invalid word: "${word}".`,
31
+ );
32
+ }
33
+ }
34
+ }
35
+ }
36
+
37
+ export { PersonNameRulesV1 };
@@ -0,0 +1,27 @@
1
+ import {
2
+ DomainException,
3
+ type ValueObjectRuleset,
4
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
+ import { PersonNameRulesV1 } from "./person-name-rules-v1";
6
+
7
+ class PersonNameCharacterError extends DomainException {}
8
+
9
+ class PersonNameRulesV2 implements ValueObjectRuleset<string> {
10
+ readonly id = "person-name-rules@2.0" as const;
11
+ readonly description =
12
+ "Name validation with restriction on special characters";
13
+
14
+ private readonly v1 = new PersonNameRulesV1();
15
+
16
+ validate(value: string): void {
17
+ this.v1.validate(value);
18
+
19
+ if (/[^a-zA-ZÀ-ÿ\s'-]/.test(value)) {
20
+ throw new PersonNameCharacterError(
21
+ `Name contains invalid characters: "${value}". Only letters, hyphens, and apostrophes are allowed.`,
22
+ );
23
+ }
24
+ }
25
+ }
26
+
27
+ export { PersonNameRulesV2 };
@@ -0,0 +1,39 @@
1
+ import {
2
+ type RulesetId,
3
+ type ValueObjectRuleset,
4
+ } from "../../../core/domain/rulesets/value-object-ruleset.contracts";
5
+
6
+ interface PersonNameStatic {
7
+ create(raw: string, ruleset: ValueObjectRuleset<string>): PersonName;
8
+ reconstitute(value: string, rulesetId: RulesetId): PersonName;
9
+ }
10
+
11
+ class PersonName {
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: PersonName): boolean {
21
+ const normalize = (v: string) =>
22
+ v.trim().replace(/\s+/g, " ").toLowerCase();
23
+ return normalize(this.value) === normalize(other.value);
24
+ }
25
+
26
+ static create(raw: string, ruleset: ValueObjectRuleset<string>): PersonName {
27
+ ruleset.validate(raw);
28
+ return new PersonName(raw, ruleset.id);
29
+ }
30
+
31
+ static reconstitute(value: string, rulesetId: RulesetId): PersonName {
32
+ return new PersonName(value, rulesetId);
33
+ }
34
+ }
35
+
36
+ const _typeCheck: PersonNameStatic = PersonName;
37
+ void _typeCheck;
38
+
39
+ export { PersonName, type PersonNameStatic };
@@ -0,0 +1 @@
1
+ export * from "../core/exceptions/validation-field.js";
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { version } from "./version.js";
2
+
3
+ export * from "./core/index.js";
4
+
5
+ export const ERP_CORE_NAME = "erp-core";
6
+ export const ERP_CORE_VERSION = version;
7
+
8
+ export const erpCoreRelease = {
9
+ name: ERP_CORE_NAME,
10
+ version: ERP_CORE_VERSION,
11
+ } as const;
@@ -0,0 +1 @@
1
+ export * from "../../core/policies/engines/index.js";
@@ -0,0 +1 @@
1
+ export * from "../../../../core/policies/engines/v1/gate/index.js";
@@ -0,0 +1 @@
1
+ export * from "../core/policies/index.js";
package/src/version.ts ADDED
@@ -0,0 +1,7 @@
1
+ // Versao do kit, sincronizada com package.json por scripts/sync-kit-version.mjs.
2
+ // Nao edite a mao: rode `npm run sync-kit-version` (ou e regenerado no release).
3
+ //
4
+ // Mantemos a versao aqui, dentro de src/, para que a copia full-control seja
5
+ // auto-contida: ao copiar so o conteudo de src/, o entry nao depende de um
6
+ // `../package.json` que deixaria de existir no projeto consumidor.
7
+ export const version = "1.0.0";