@cullet/erp-core 1.0.1 → 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 -62
  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
@@ -1,71 +1,71 @@
1
1
  import { DomainException } from "../../exceptions/domain-exception";
2
2
  import {
3
- type Ruleset,
4
- type RulesetRegistry as RulesetRegistryContract,
3
+ type Ruleset,
4
+ type RulesetRegistry as RulesetRegistryContract,
5
5
  } from "./ruleset.contracts";
6
6
 
7
7
  class RulesetRegistryError extends DomainException {}
8
8
 
9
9
  function parseVersion(id: string): [number, number] {
10
- const atIdx = id.lastIndexOf("@");
11
- const versionStr = id.slice(atIdx + 1);
12
- const [major, minor] = versionStr.split(".").map(Number);
13
- return [major, minor];
10
+ const atIdx = id.lastIndexOf("@");
11
+ const versionStr = id.slice(atIdx + 1);
12
+ const [major, minor] = versionStr.split(".").map(Number);
13
+ return [major, minor];
14
14
  }
15
15
 
16
16
  class RulesetRegistry implements RulesetRegistryContract {
17
- private readonly _store = new Map<string, Ruleset>();
18
- private _sealed = false;
17
+ private readonly _store = new Map<string, Ruleset>();
18
+ private _sealed = false;
19
19
 
20
- register(ruleset: Ruleset): void {
21
- if (this._sealed) {
22
- throw new RulesetRegistryError(
23
- "Registry is sealed. No new rulesets can be registered.",
24
- );
20
+ register(ruleset: Ruleset): void {
21
+ if (this._sealed) {
22
+ throw new RulesetRegistryError(
23
+ "Registry is sealed. No new rulesets can be registered.",
24
+ );
25
+ }
26
+ if (this._store.has(ruleset.id)) {
27
+ throw new RulesetRegistryError(
28
+ `Ruleset with id "${ruleset.id}" is already registered.`,
29
+ );
30
+ }
31
+ this._store.set(ruleset.id, ruleset);
25
32
  }
26
- if (this._store.has(ruleset.id)) {
27
- throw new RulesetRegistryError(
28
- `Ruleset with id "${ruleset.id}" is already registered.`,
29
- );
30
- }
31
- this._store.set(ruleset.id, ruleset);
32
- }
33
33
 
34
- seal(): void {
35
- this._sealed = true;
36
- }
34
+ seal(): void {
35
+ this._sealed = true;
36
+ }
37
37
 
38
- get<T extends Ruleset>(id: string): T {
39
- const ruleset = this._store.get(id);
40
- if (!ruleset) {
41
- const available = Array.from(this._store.keys()).join(", ");
42
- throw new RulesetRegistryError(
43
- `Ruleset "${id}" not found. Available: [${available}]`,
44
- );
38
+ get<T extends Ruleset>(id: string): T {
39
+ const ruleset = this._store.get(id);
40
+ if (!ruleset) {
41
+ const available = Array.from(this._store.keys()).join(", ");
42
+ throw new RulesetRegistryError(
43
+ `Ruleset "${id}" not found. Available: [${available}]`,
44
+ );
45
+ }
46
+ return ruleset as T;
45
47
  }
46
- return ruleset as T;
47
- }
48
48
 
49
- getCurrent<T extends Ruleset>(prefix: string): T {
50
- const matchingEntries = Array.from(this._store.entries()).filter(([key]) =>
51
- key.startsWith(prefix + "@"),
52
- );
49
+ getCurrent<T extends Ruleset>(prefix: string): T {
50
+ const matchingEntries = Array.from(this._store.entries()).filter(
51
+ ([key]) => key.startsWith(prefix + "@"),
52
+ );
53
53
 
54
- if (matchingEntries.length === 0) {
55
- throw new RulesetRegistryError(
56
- `No rulesets found with prefix "${prefix}".`,
57
- );
58
- }
54
+ if (matchingEntries.length === 0) {
55
+ throw new RulesetRegistryError(
56
+ `No rulesets found with prefix "${prefix}".`,
57
+ );
58
+ }
59
59
 
60
- const sorted = matchingEntries.sort(([a], [b]) => {
61
- const [aMajor, aMinor] = parseVersion(a);
62
- const [bMajor, bMinor] = parseVersion(b);
63
- if (aMajor !== bMajor) return aMajor - bMajor;
64
- return aMinor - bMinor;
65
- });
60
+ const sorted = matchingEntries.sort(([a], [b]) => {
61
+ const [aMajor, aMinor] = parseVersion(a);
62
+ const [bMajor, bMinor] = parseVersion(b);
63
+ if (aMajor !== bMajor) return aMajor - bMajor;
64
+ return aMinor - bMinor;
65
+ });
66
66
 
67
- return sorted[sorted.length - 1][1] as T;
68
- }
67
+ return sorted[sorted.length - 1][1] as T;
68
+ }
69
69
  }
70
70
 
71
71
  export { RulesetRegistry };
@@ -1,15 +1,15 @@
1
1
  type RulesetId = `${string}@${number}.${number}`;
2
2
 
3
3
  interface Ruleset {
4
- readonly id: RulesetId;
5
- readonly description: string;
4
+ readonly id: RulesetId;
5
+ readonly description: string;
6
6
  }
7
7
 
8
8
  interface RulesetRegistry {
9
- register(ruleset: Ruleset): void;
10
- seal(): void;
11
- get<T extends Ruleset>(id: string): T;
12
- getCurrent<T extends Ruleset>(prefix: string): T;
9
+ register(ruleset: Ruleset): void;
10
+ seal(): void;
11
+ get<T extends Ruleset>(id: string): T;
12
+ getCurrent<T extends Ruleset>(prefix: string): T;
13
13
  }
14
14
 
15
15
  export { type Ruleset, type RulesetId, type RulesetRegistry };
@@ -2,12 +2,12 @@ import { DomainException } from "../../exceptions/domain-exception";
2
2
  import { type Ruleset, type RulesetId } from "./ruleset.contracts";
3
3
 
4
4
  interface ValueObjectRuleset<T> extends Ruleset {
5
- validate(value: T): void;
5
+ validate(value: T): void;
6
6
  }
7
7
 
8
8
  export {
9
- DomainException,
10
- type Ruleset,
11
- type RulesetId,
12
- type ValueObjectRuleset,
9
+ DomainException,
10
+ type Ruleset,
11
+ type RulesetId,
12
+ type ValueObjectRuleset,
13
13
  };
@@ -1,18 +1,18 @@
1
1
  export {
2
- assertTransactionTime,
3
- createTransactionTime,
4
- type CreateTransactionTimeInput,
5
- type TransactionTime,
2
+ assertTransactionTime,
3
+ createTransactionTime,
4
+ type CreateTransactionTimeInput,
5
+ type TransactionTime,
6
6
  } from "./transaction-time";
7
7
  export { contains, isClosed, isOpen, overlaps } from "./temporal-range";
8
8
  export {
9
- createTemporalSnapshot,
10
- type CreateTemporalSnapshotInput,
11
- type TemporalSnapshot,
9
+ createTemporalSnapshot,
10
+ type CreateTemporalSnapshotInput,
11
+ type TemporalSnapshot,
12
12
  } from "./temporal-snapshot";
13
13
  export {
14
- assertValidTime,
15
- createValidTime,
16
- type CreateValidTimeInput,
17
- type ValidTime,
14
+ assertValidTime,
15
+ createValidTime,
16
+ type CreateValidTimeInput,
17
+ type ValidTime,
18
18
  } from "./valid-time";
@@ -7,16 +7,16 @@ import { assertValidTime, type ValidTime } from "./valid-time";
7
7
  * Useful for identifying information that is still in effect / active.
8
8
  */
9
9
  function isOpen(range: ValidTime): boolean {
10
- assertValidTime(range, "range");
10
+ assertValidTime(range, "range");
11
11
 
12
- return range.to === undefined;
12
+ return range.to === undefined;
13
13
  }
14
14
 
15
15
  /**
16
16
  * Checks whether a temporal range is "closed" (has a defined end date).
17
17
  */
18
18
  function isClosed(range: ValidTime): boolean {
19
- return !isOpen(range);
19
+ return !isOpen(range);
20
20
  }
21
21
 
22
22
  /**
@@ -24,14 +24,14 @@ function isClosed(range: ValidTime): boolean {
24
24
  * The lower bound (`from`) is inclusive, while the upper bound (`to`) is exclusive.
25
25
  */
26
26
  function contains(range: ValidTime, date: Date): boolean {
27
- assertValidTime(range, "range");
28
- assertValidDate("date", date);
27
+ assertValidTime(range, "range");
28
+ assertValidDate("date", date);
29
29
 
30
- const fromTime = range.from.getTime();
31
- const toTime = range.to?.getTime() ?? Number.POSITIVE_INFINITY;
32
- const targetTime = date.getTime();
30
+ const fromTime = range.from.getTime();
31
+ const toTime = range.to?.getTime() ?? Number.POSITIVE_INFINITY;
32
+ const targetTime = date.getTime();
33
33
 
34
- return targetTime >= fromTime && targetTime < toTime;
34
+ return targetTime >= fromTime && targetTime < toTime;
35
35
  }
36
36
 
37
37
  /**
@@ -39,15 +39,15 @@ function contains(range: ValidTime, date: Date): boolean {
39
39
  * Useful for validating whether a new rule conflicts with an existing one.
40
40
  */
41
41
  function overlaps(left: ValidTime, right: ValidTime): boolean {
42
- assertValidTime(left, "left");
43
- assertValidTime(right, "right");
42
+ assertValidTime(left, "left");
43
+ assertValidTime(right, "right");
44
44
 
45
- const leftFrom = left.from.getTime();
46
- const leftTo = left.to?.getTime() ?? Number.POSITIVE_INFINITY;
47
- const rightFrom = right.from.getTime();
48
- const rightTo = right.to?.getTime() ?? Number.POSITIVE_INFINITY;
45
+ const leftFrom = left.from.getTime();
46
+ const leftTo = left.to?.getTime() ?? Number.POSITIVE_INFINITY;
47
+ const rightFrom = right.from.getTime();
48
+ const rightTo = right.to?.getTime() ?? Number.POSITIVE_INFINITY;
49
49
 
50
- return leftFrom < rightTo && rightFrom < leftTo;
50
+ return leftFrom < rightTo && rightFrom < leftTo;
51
51
  }
52
52
 
53
53
  export { contains, isClosed, isOpen, overlaps };
@@ -1,14 +1,14 @@
1
1
  import { type DeepReadonly, makeImmutable } from "../../shared/immutable";
2
2
 
3
3
  import {
4
- createTransactionTime,
5
- type CreateTransactionTimeInput,
6
- type TransactionTime,
4
+ createTransactionTime,
5
+ type CreateTransactionTimeInput,
6
+ type TransactionTime,
7
7
  } from "./transaction-time";
8
8
  import {
9
- createValidTime,
10
- type CreateValidTimeInput,
11
- type ValidTime,
9
+ createValidTime,
10
+ type CreateValidTimeInput,
11
+ type ValidTime,
12
12
  } from "./valid-time";
13
13
 
14
14
  /**
@@ -16,32 +16,32 @@ import {
16
16
  * It is the representation of an entry in the append-only (historical) table.
17
17
  */
18
18
  interface TemporalSnapshot<T> {
19
- /** The data or state captured by the snapshot. */
20
- readonly data: DeepReadonly<T>;
21
- /** Period during which this datum was valid in the real world. */
22
- readonly validTime: ValidTime;
23
- /** Period during which this record was the state known to the system. */
24
- readonly txTime: TransactionTime;
19
+ /** The data or state captured by the snapshot. */
20
+ readonly data: DeepReadonly<T>;
21
+ /** Period during which this datum was valid in the real world. */
22
+ readonly validTime: ValidTime;
23
+ /** Period during which this record was the state known to the system. */
24
+ readonly txTime: TransactionTime;
25
25
  }
26
26
 
27
27
  interface CreateTemporalSnapshotInput<T> {
28
- readonly data: T;
29
- readonly validTime: CreateValidTimeInput;
30
- readonly txTime: CreateTransactionTimeInput;
28
+ readonly data: T;
29
+ readonly validTime: CreateValidTimeInput;
30
+ readonly txTime: CreateTransactionTimeInput;
31
31
  }
32
32
 
33
33
  function createTemporalSnapshot<T>(
34
- input: CreateTemporalSnapshotInput<T>,
34
+ input: CreateTemporalSnapshotInput<T>,
35
35
  ): TemporalSnapshot<T> {
36
- return makeImmutable({
37
- data: input.data,
38
- validTime: createValidTime(input.validTime),
39
- txTime: createTransactionTime(input.txTime),
40
- });
36
+ return makeImmutable({
37
+ data: input.data,
38
+ validTime: createValidTime(input.validTime),
39
+ txTime: createTransactionTime(input.txTime),
40
+ });
41
41
  }
42
42
 
43
43
  export {
44
- createTemporalSnapshot,
45
- type CreateTemporalSnapshotInput,
46
- type TemporalSnapshot,
44
+ createTemporalSnapshot,
45
+ type CreateTemporalSnapshotInput,
46
+ type TemporalSnapshot,
47
47
  };
@@ -8,53 +8,53 @@ import { assertValidDate } from "../../shared/temporal-guards";
8
8
  * Useful for auditing and reconstructing system state at a specific past moment.
9
9
  */
10
10
  interface TransactionTime {
11
- /** When the information was first recorded in the system. */
12
- readonly recordedAt: Date;
13
- /** When this information was superseded or invalidated by a newer version. */
14
- readonly supersededAt?: Date;
11
+ /** When the information was first recorded in the system. */
12
+ readonly recordedAt: Date;
13
+ /** When this information was superseded or invalidated by a newer version. */
14
+ readonly supersededAt?: Date;
15
15
  }
16
16
 
17
17
  type CreateTransactionTimeInput = TransactionTime;
18
18
 
19
19
  function assertTransactionTime(
20
- txTime: TransactionTime,
21
- fieldName: string = "txTime",
20
+ txTime: TransactionTime,
21
+ fieldName: string = "txTime",
22
22
  ): void {
23
- assertValidDate(`${fieldName}.recordedAt`, txTime.recordedAt);
23
+ assertValidDate(`${fieldName}.recordedAt`, txTime.recordedAt);
24
24
 
25
- if (txTime.supersededAt === undefined) {
26
- return;
27
- }
25
+ if (txTime.supersededAt === undefined) {
26
+ return;
27
+ }
28
28
 
29
- assertValidDate(`${fieldName}.supersededAt`, txTime.supersededAt);
29
+ assertValidDate(`${fieldName}.supersededAt`, txTime.supersededAt);
30
30
 
31
- if (txTime.supersededAt.getTime() <= txTime.recordedAt.getTime()) {
32
- throw new InvariantViolationException(
33
- `${fieldName}.supersededAt must be later than ${fieldName}.recordedAt`,
34
- );
35
- }
31
+ if (txTime.supersededAt.getTime() <= txTime.recordedAt.getTime()) {
32
+ throw new InvariantViolationException(
33
+ `${fieldName}.supersededAt must be later than ${fieldName}.recordedAt`,
34
+ );
35
+ }
36
36
  }
37
37
 
38
38
  function createTransactionTime(
39
- input: CreateTransactionTimeInput,
39
+ input: CreateTransactionTimeInput,
40
40
  ): TransactionTime {
41
- assertTransactionTime(input, "txTime");
41
+ assertTransactionTime(input, "txTime");
42
+
43
+ if (input.supersededAt === undefined) {
44
+ return makeImmutable({
45
+ recordedAt: input.recordedAt,
46
+ });
47
+ }
42
48
 
43
- if (input.supersededAt === undefined) {
44
49
  return makeImmutable({
45
- recordedAt: input.recordedAt,
50
+ recordedAt: input.recordedAt,
51
+ supersededAt: input.supersededAt,
46
52
  });
47
- }
48
-
49
- return makeImmutable({
50
- recordedAt: input.recordedAt,
51
- supersededAt: input.supersededAt,
52
- });
53
53
  }
54
54
 
55
55
  export {
56
- assertTransactionTime,
57
- createTransactionTime,
58
- type CreateTransactionTimeInput,
59
- type TransactionTime,
56
+ assertTransactionTime,
57
+ createTransactionTime,
58
+ type CreateTransactionTimeInput,
59
+ type TransactionTime,
60
60
  };
@@ -7,51 +7,51 @@ import { assertValidDate } from "../../shared/temporal-guards";
7
7
  * Defines when a piece of information is considered true or in effect in the real world.
8
8
  */
9
9
  interface ValidTime {
10
- /** Start of the validity window (inclusive). */
11
- readonly from: Date;
12
- /** End of the validity window (exclusive). When absent, the information is still in effect. */
13
- readonly to?: Date;
10
+ /** Start of the validity window (inclusive). */
11
+ readonly from: Date;
12
+ /** End of the validity window (exclusive). When absent, the information is still in effect. */
13
+ readonly to?: Date;
14
14
  }
15
15
 
16
16
  type CreateValidTimeInput = ValidTime;
17
17
 
18
18
  function assertValidTime(
19
- validTime: ValidTime,
20
- fieldName: string = "validTime",
19
+ validTime: ValidTime,
20
+ fieldName: string = "validTime",
21
21
  ): void {
22
- assertValidDate(`${fieldName}.from`, validTime.from);
22
+ assertValidDate(`${fieldName}.from`, validTime.from);
23
23
 
24
- if (validTime.to === undefined) {
25
- return;
26
- }
24
+ if (validTime.to === undefined) {
25
+ return;
26
+ }
27
27
 
28
- assertValidDate(`${fieldName}.to`, validTime.to);
28
+ assertValidDate(`${fieldName}.to`, validTime.to);
29
29
 
30
- if (validTime.to.getTime() <= validTime.from.getTime()) {
31
- throw new InvariantViolationException(
32
- `${fieldName}.to must be later than ${fieldName}.from`,
33
- );
34
- }
30
+ if (validTime.to.getTime() <= validTime.from.getTime()) {
31
+ throw new InvariantViolationException(
32
+ `${fieldName}.to must be later than ${fieldName}.from`,
33
+ );
34
+ }
35
35
  }
36
36
 
37
37
  function createValidTime(input: CreateValidTimeInput): ValidTime {
38
- assertValidTime(input, "validTime");
38
+ assertValidTime(input, "validTime");
39
+
40
+ if (input.to === undefined) {
41
+ return makeImmutable({
42
+ from: input.from,
43
+ });
44
+ }
39
45
 
40
- if (input.to === undefined) {
41
46
  return makeImmutable({
42
- from: input.from,
47
+ from: input.from,
48
+ to: input.to,
43
49
  });
44
- }
45
-
46
- return makeImmutable({
47
- from: input.from,
48
- to: input.to,
49
- });
50
50
  }
51
51
 
52
52
  export {
53
- assertValidTime,
54
- createValidTime,
55
- type CreateValidTimeInput,
56
- type ValidTime,
53
+ assertValidTime,
54
+ createValidTime,
55
+ type CreateValidTimeInput,
56
+ type ValidTime,
57
57
  };
@@ -3,28 +3,28 @@ import { type ContractVersion, version } from "../versioning/version";
3
3
 
4
4
  @version("1.0")
5
5
  abstract class ValueObject<T, P> {
6
- public static readonly CONTRACT_VERSION: ContractVersion;
7
- public readonly value: DeepReadonly<T>;
6
+ public static readonly CONTRACT_VERSION: ContractVersion;
7
+ public readonly value: DeepReadonly<T>;
8
8
 
9
- protected constructor(value: T) {
10
- this.value = makeImmutable(value);
11
- }
9
+ protected constructor(value: T) {
10
+ this.value = makeImmutable(value);
11
+ }
12
12
 
13
- public get contractVersion(): ContractVersion {
14
- return ValueObject.CONTRACT_VERSION;
15
- }
13
+ public get contractVersion(): ContractVersion {
14
+ return ValueObject.CONTRACT_VERSION;
15
+ }
16
16
 
17
- protected finalize(): void {
18
- Object.freeze(this);
19
- }
17
+ protected finalize(): void {
18
+ Object.freeze(this);
19
+ }
20
20
 
21
- public toJSON(): P {
22
- return this.toPrimitive();
23
- }
21
+ public toJSON(): P {
22
+ return this.toPrimitive();
23
+ }
24
24
 
25
- public abstract equals(other: this): boolean;
25
+ public abstract equals(other: this): boolean;
26
26
 
27
- public abstract toPrimitive(): P;
27
+ public abstract toPrimitive(): P;
28
28
  }
29
29
 
30
30
  export { type DeepReadonly, ValueObject };