@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
package/package.json CHANGED
@@ -1,64 +1,64 @@
1
1
  {
2
- "name": "@cullet/erp-core",
3
- "version": "1.0.1",
4
- "description": "Core ERP with clean architecture, temporality, policies, and rule sets",
5
- "type": "module",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/fabiano-eduardo/cullet.git",
9
- "directory": "packages/erp-core"
10
- },
11
- "main": "./dist/index.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js"
2
+ "name": "@cullet/erp-core",
3
+ "version": "1.0.3",
4
+ "description": "Core ERP with clean architecture, temporality, policies, and rule sets",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/fabiano-eduardo/cullet.git",
9
+ "directory": "packages/erp-core"
17
10
  },
18
- "./errors": {
19
- "types": "./dist/errors/index.d.ts",
20
- "import": "./dist/errors/index.js"
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./errors": {
19
+ "types": "./dist/errors/index.d.ts",
20
+ "import": "./dist/errors/index.js"
21
+ },
22
+ "./policies": {
23
+ "types": "./dist/policies/index.d.ts",
24
+ "import": "./dist/policies/index.js"
25
+ },
26
+ "./policies/engines": {
27
+ "types": "./dist/policies/engines/index.d.ts",
28
+ "import": "./dist/policies/engines/index.js"
29
+ },
30
+ "./policies/engines/v1/gate": {
31
+ "types": "./dist/policies/engines/v1/gate/index.d.ts",
32
+ "import": "./dist/policies/engines/v1/gate/index.js"
33
+ },
34
+ "./exceptions/validation-field": {
35
+ "types": "./dist/exceptions/validation-field.d.ts",
36
+ "import": "./dist/exceptions/validation-field.js"
37
+ },
38
+ "./package.json": "./package.json"
21
39
  },
22
- "./policies": {
23
- "types": "./dist/policies/index.d.ts",
24
- "import": "./dist/policies/index.js"
40
+ "scripts": {
41
+ "build": "tsdown --config tsdown.config.ts",
42
+ "dev": "tsdown --config tsdown.config.ts --watch"
25
43
  },
26
- "./policies/engines": {
27
- "types": "./dist/policies/engines/index.d.ts",
28
- "import": "./dist/policies/engines/index.js"
44
+ "files": [
45
+ "dist",
46
+ "src",
47
+ "!src/**/*.spec.ts",
48
+ "!src/**/*.test.ts",
49
+ "meta.json",
50
+ "KIT_CONTEXT.md",
51
+ "README.md"
52
+ ],
53
+ "sideEffects": false,
54
+ "engines": {
55
+ "node": ">=18.17"
29
56
  },
30
- "./policies/engines/v1/gate": {
31
- "types": "./dist/policies/engines/v1/gate/index.d.ts",
32
- "import": "./dist/policies/engines/v1/gate/index.js"
57
+ "peerDependencies": {
58
+ "zod": ">=3.22.0 <5"
33
59
  },
34
- "./exceptions/validation-field": {
35
- "types": "./dist/exceptions/validation-field.d.ts",
36
- "import": "./dist/exceptions/validation-field.js"
60
+ "publishConfig": {
61
+ "access": "public"
37
62
  },
38
- "./package.json": "./package.json"
39
- },
40
- "scripts": {
41
- "build": "tsdown --config tsdown.config.ts",
42
- "dev": "tsdown --config tsdown.config.ts --watch"
43
- },
44
- "files": [
45
- "dist",
46
- "src",
47
- "!src/**/*.spec.ts",
48
- "!src/**/*.test.ts",
49
- "meta.json",
50
- "KIT_CONTEXT.md",
51
- "README.md"
52
- ],
53
- "sideEffects": false,
54
- "engines": {
55
- "node": ">=18.17"
56
- },
57
- "peerDependencies": {
58
- "zod": ">=3.22.0 <5"
59
- },
60
- "publishConfig": {
61
- "access": "public"
62
- },
63
- "license": "MIT"
63
+ "license": "MIT"
64
64
  }
@@ -5,7 +5,7 @@ import type { Result } from "../../result/result";
5
5
  import { RequestedBy } from "./requested-by";
6
6
 
7
7
  interface CommandInput {
8
- readonly requestedBy: RequestedBy;
8
+ readonly requestedBy: RequestedBy;
9
9
  }
10
10
 
11
11
  /**
@@ -20,8 +20,8 @@ interface CommandInput {
20
20
  */
21
21
  @version("1.0")
22
22
  abstract class Command<
23
- Input extends CommandInput,
24
- Output extends Result<unknown, unknown> = Result<void, never>,
23
+ Input extends CommandInput,
24
+ Output extends Result<unknown, unknown> = Result<void, never>,
25
25
  > extends UseCase<Input, Output> {}
26
26
 
27
27
  export type { CommandInput };
@@ -16,81 +16,81 @@ type RequestedByKind = "user" | "system";
16
16
  const REQUESTED_BY_FIELD = ValidationField.of("requestedBy");
17
17
 
18
18
  const UUID_PATTERN =
19
- /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
20
20
 
21
21
  // system:<job> where <job> starts with a lowercase letter and may have hyphens between segments
22
22
  const SYSTEM_IDENTITY_PATTERN = /^system:[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
23
23
 
24
24
  class RequestedBy {
25
- readonly kind: RequestedByKind;
26
- readonly raw: string;
27
-
28
- private constructor(kind: RequestedByKind, raw: string) {
29
- this.kind = kind;
30
- this.raw = raw;
31
- Object.freeze(this);
32
- }
33
-
34
- /** Builds from a human user ID (must be a UUID). */
35
- static fromUser(userId: string): RequestedBy {
36
- if (!UUID_PATTERN.test(userId)) {
37
- throw new InvalidValueException(
38
- REQUESTED_BY_FIELD,
39
- ValidationCode.INVALID_FORMAT,
40
- `requestedBy: user identity must be a UUID, got "${userId}"`,
41
- );
42
- }
25
+ readonly kind: RequestedByKind;
26
+ readonly raw: string;
43
27
 
44
- return new RequestedBy("user", userId);
45
- }
46
-
47
- /**
48
- * Builds from a system identity.
49
- * Only accepts the format "system:<job>", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.
50
- */
51
- static fromSystem(systemIdentity: string): RequestedBy {
52
- if (!SYSTEM_IDENTITY_PATTERN.test(systemIdentity)) {
53
- throw new InvalidValueException(
54
- REQUESTED_BY_FIELD,
55
- ValidationCode.INVALID_FORMAT,
56
- `requestedBy: system identity must match "system:<job>" (e.g. "system:late-fee-job"), got "${systemIdentity}"`,
57
- );
28
+ private constructor(kind: RequestedByKind, raw: string) {
29
+ this.kind = kind;
30
+ this.raw = raw;
31
+ Object.freeze(this);
58
32
  }
59
33
 
60
- return new RequestedBy("system", systemIdentity);
61
- }
62
-
63
- /**
64
- * Infers the kind from the raw value.
65
- * Use when the origin (user vs system) is not known at the call-site.
66
- */
67
- static parse(raw: string): RequestedBy {
68
- if (UUID_PATTERN.test(raw)) {
69
- return new RequestedBy("user", raw);
34
+ /** Builds from a human user ID (must be a UUID). */
35
+ static fromUser(userId: string): RequestedBy {
36
+ if (!UUID_PATTERN.test(userId)) {
37
+ throw new InvalidValueException(
38
+ REQUESTED_BY_FIELD,
39
+ ValidationCode.INVALID_FORMAT,
40
+ `requestedBy: user identity must be a UUID, got "${userId}"`,
41
+ );
42
+ }
43
+
44
+ return new RequestedBy("user", userId);
70
45
  }
71
46
 
72
- if (SYSTEM_IDENTITY_PATTERN.test(raw)) {
73
- return new RequestedBy("system", raw);
47
+ /**
48
+ * Builds from a system identity.
49
+ * Only accepts the format "system:<job>", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.
50
+ */
51
+ static fromSystem(systemIdentity: string): RequestedBy {
52
+ if (!SYSTEM_IDENTITY_PATTERN.test(systemIdentity)) {
53
+ throw new InvalidValueException(
54
+ REQUESTED_BY_FIELD,
55
+ ValidationCode.INVALID_FORMAT,
56
+ `requestedBy: system identity must match "system:<job>" (e.g. "system:late-fee-job"), got "${systemIdentity}"`,
57
+ );
58
+ }
59
+
60
+ return new RequestedBy("system", systemIdentity);
74
61
  }
75
62
 
76
- throw new InvalidValueException(
77
- REQUESTED_BY_FIELD,
78
- ValidationCode.INVALID_FORMAT,
79
- `requestedBy must be a UUID (user) or "system:<job>" (system), got "${raw}"`,
80
- );
81
- }
63
+ /**
64
+ * Infers the kind from the raw value.
65
+ * Use when the origin (user vs system) is not known at the call-site.
66
+ */
67
+ static parse(raw: string): RequestedBy {
68
+ if (UUID_PATTERN.test(raw)) {
69
+ return new RequestedBy("user", raw);
70
+ }
71
+
72
+ if (SYSTEM_IDENTITY_PATTERN.test(raw)) {
73
+ return new RequestedBy("system", raw);
74
+ }
75
+
76
+ throw new InvalidValueException(
77
+ REQUESTED_BY_FIELD,
78
+ ValidationCode.INVALID_FORMAT,
79
+ `requestedBy must be a UUID (user) or "system:<job>" (system), got "${raw}"`,
80
+ );
81
+ }
82
82
 
83
- get isUser(): boolean {
84
- return this.kind === "user";
85
- }
83
+ get isUser(): boolean {
84
+ return this.kind === "user";
85
+ }
86
86
 
87
- get isSystem(): boolean {
88
- return this.kind === "system";
89
- }
87
+ get isSystem(): boolean {
88
+ return this.kind === "system";
89
+ }
90
90
 
91
- toString(): string {
92
- return this.raw;
93
- }
91
+ toString(): string {
92
+ return this.raw;
93
+ }
94
94
  }
95
95
 
96
96
  export type { RequestedByKind };
@@ -1,31 +1,31 @@
1
1
  export type { CommandInput } from "./commands";
2
2
  export { Command } from "./commands";
3
3
  export type {
4
- LogPayload,
5
- LoggerPort,
6
- MetricLabels,
7
- MetricsPort,
8
- PolicyEvaluationError,
9
- PolicyEvaluationInput,
10
- PolicyEvaluationOutput,
11
- PolicyPort,
12
- Repository,
13
- TraceAttributeValue,
14
- TraceSpan,
15
- TracerPort,
16
- TemporalHistory,
17
- TemporalRepository,
4
+ LogPayload,
5
+ LoggerPort,
6
+ MetricLabels,
7
+ MetricsPort,
8
+ PolicyEvaluationError,
9
+ PolicyEvaluationInput,
10
+ PolicyEvaluationOutput,
11
+ PolicyPort,
12
+ Repository,
13
+ TraceAttributeValue,
14
+ TraceSpan,
15
+ TracerPort,
16
+ TemporalHistory,
17
+ TemporalRepository,
18
18
  } from "./ports";
19
19
  export { mapPolicyEvaluationError } from "./policy-error-mapper";
20
20
  export type { CacheStrategy, Page } from "./queries";
21
21
  export { Query } from "./queries";
22
22
  export {
23
- assertTemporalContext,
24
- createTemporalContext,
25
- type CreateTemporalContextInput,
26
- type TemporalContext,
27
- type TemporalizedContextSeed,
28
- TemporalUseCase,
29
- type TemporalUseCaseInput,
23
+ assertTemporalContext,
24
+ createTemporalContext,
25
+ type CreateTemporalContextInput,
26
+ type TemporalContext,
27
+ type TemporalizedContextSeed,
28
+ TemporalUseCase,
29
+ type TemporalUseCaseInput,
30
30
  } from "./temporal";
31
31
  export { type MaybePromise, UseCase } from "./use-case";
@@ -1,60 +1,60 @@
1
1
  import {
2
- type AppError,
3
- BusinessRuleViolationError,
4
- NotFoundError,
5
- UnexpectedError,
2
+ type AppError,
3
+ BusinessRuleViolationError,
4
+ NotFoundError,
5
+ UnexpectedError,
6
6
  } from "../errors";
7
7
  import type { PolicyEvaluationError } from "../policies";
8
8
 
9
9
  export function mapPolicyEvaluationError(err: PolicyEvaluationError): AppError {
10
- switch (err.kind) {
11
- case "INVALID_CONTEXT":
12
- return new BusinessRuleViolationError(
13
- `policy.${err.stage.toLowerCase()}`,
14
- err.message,
15
- { policyKey: err.policyKey, stage: err.stage },
16
- { cause: err.cause },
17
- );
18
- case "INVALID_POLICY_KEY":
19
- return new BusinessRuleViolationError(
20
- "policy.invalid_key",
21
- err.message,
22
- { rawPolicyKey: err.rawPolicyKey },
23
- { cause: err.cause },
24
- );
25
- case "POLICY_NOT_FOUND":
26
- return new NotFoundError(
27
- "Policy",
28
- { policyKey: err.policyKey },
29
- { cause: err.cause },
30
- );
31
- case "POLICY_DEFINITION_NOT_FOUND":
32
- return new NotFoundError(
33
- "PolicyDefinition",
34
- {
35
- policyKey: err.policyKey,
36
- contextVersion: err.contextVersion,
37
- asOf: err.asOf.toISOString(),
38
- },
39
- { cause: err.cause },
40
- );
41
- case "POLICY_VARIANT_NOT_FOUND":
42
- return new NotFoundError(
43
- "PolicyVariant",
44
- {
45
- policyKey: err.policyKey,
46
- policyKind: err.policyKind,
47
- payloadSchemaVersion: err.payloadSchemaVersion,
48
- },
49
- { cause: err.cause },
50
- );
51
- case "ENGINE_FAILURE":
52
- return new UnexpectedError(err.message, err.cause, {
53
- metadata: {
54
- policyKey: err.policyKey,
55
- engine: err.engine,
56
- engineVersion: err.engineVersion,
57
- },
58
- });
59
- }
10
+ switch (err.kind) {
11
+ case "INVALID_CONTEXT":
12
+ return new BusinessRuleViolationError(
13
+ `policy.${err.stage.toLowerCase()}`,
14
+ err.message,
15
+ { policyKey: err.policyKey, stage: err.stage },
16
+ { cause: err.cause },
17
+ );
18
+ case "INVALID_POLICY_KEY":
19
+ return new BusinessRuleViolationError(
20
+ "policy.invalid_key",
21
+ err.message,
22
+ { rawPolicyKey: err.rawPolicyKey },
23
+ { cause: err.cause },
24
+ );
25
+ case "POLICY_NOT_FOUND":
26
+ return new NotFoundError(
27
+ "Policy",
28
+ { policyKey: err.policyKey },
29
+ { cause: err.cause },
30
+ );
31
+ case "POLICY_DEFINITION_NOT_FOUND":
32
+ return new NotFoundError(
33
+ "PolicyDefinition",
34
+ {
35
+ policyKey: err.policyKey,
36
+ contextVersion: err.contextVersion,
37
+ asOf: err.asOf.toISOString(),
38
+ },
39
+ { cause: err.cause },
40
+ );
41
+ case "POLICY_VARIANT_NOT_FOUND":
42
+ return new NotFoundError(
43
+ "PolicyVariant",
44
+ {
45
+ policyKey: err.policyKey,
46
+ policyKind: err.policyKind,
47
+ payloadSchemaVersion: err.payloadSchemaVersion,
48
+ },
49
+ { cause: err.cause },
50
+ );
51
+ case "ENGINE_FAILURE":
52
+ return new UnexpectedError(err.message, err.cause, {
53
+ metadata: {
54
+ policyKey: err.policyKey,
55
+ engine: err.engine,
56
+ engineVersion: err.engineVersion,
57
+ },
58
+ });
59
+ }
60
60
  }
@@ -1,14 +1,14 @@
1
1
  export type { LogPayload, LoggerPort } from "./logger.port";
2
2
  export type { MetricLabels, MetricsPort } from "./metrics.port";
3
3
  export type {
4
- PolicyEvaluationError,
5
- PolicyEvaluationInput,
6
- PolicyEvaluationOutput,
7
- PolicyPort,
4
+ PolicyEvaluationError,
5
+ PolicyEvaluationInput,
6
+ PolicyEvaluationOutput,
7
+ PolicyPort,
8
8
  } from "./policy-port";
9
9
  export type { Repository } from "./repository.port";
10
10
  export type {
11
- TemporalHistory,
12
- TemporalRepository,
11
+ TemporalHistory,
12
+ TemporalRepository,
13
13
  } from "./temporal-repository.port";
14
14
  export type { TraceAttributeValue, TraceSpan, TracerPort } from "./tracer.port";
@@ -1,10 +1,10 @@
1
1
  type LogPayload = Record<string, unknown>;
2
2
 
3
3
  interface LoggerPort {
4
- debug(message: string, payload?: LogPayload): void;
5
- info(message: string, payload?: LogPayload): void;
6
- warn(message: string, payload?: LogPayload): void;
7
- error(message: string, payload?: LogPayload): void;
4
+ debug(message: string, payload?: LogPayload): void;
5
+ info(message: string, payload?: LogPayload): void;
6
+ warn(message: string, payload?: LogPayload): void;
7
+ error(message: string, payload?: LogPayload): void;
8
8
  }
9
9
 
10
10
  export type { LogPayload, LoggerPort };
@@ -1,9 +1,9 @@
1
1
  type MetricLabels = Readonly<Record<string, string | number | boolean>>;
2
2
 
3
3
  interface MetricsPort {
4
- counter(name: string, value: number, labels?: MetricLabels): void;
5
- gauge(name: string, value: number, labels?: MetricLabels): void;
6
- histogram(name: string, value: number, labels?: MetricLabels): void;
4
+ counter(name: string, value: number, labels?: MetricLabels): void;
5
+ gauge(name: string, value: number, labels?: MetricLabels): void;
6
+ histogram(name: string, value: number, labels?: MetricLabels): void;
7
7
  }
8
8
 
9
9
  export type { MetricLabels, MetricsPort };
@@ -7,14 +7,14 @@ type PolicyEvaluationOutput = PolicyEvaluationResult;
7
7
  type PolicyEvaluationError = AppError;
8
8
 
9
9
  interface PolicyPort {
10
- evaluate(
11
- input: PolicyEvaluationInput,
12
- ): Promise<Result<PolicyEvaluationOutput, PolicyEvaluationError>>;
10
+ evaluate(
11
+ input: PolicyEvaluationInput,
12
+ ): Promise<Result<PolicyEvaluationOutput, PolicyEvaluationError>>;
13
13
  }
14
14
 
15
15
  export type {
16
- PolicyEvaluationError,
17
- PolicyEvaluationInput,
18
- PolicyEvaluationOutput,
19
- PolicyPort,
16
+ PolicyEvaluationError,
17
+ PolicyEvaluationInput,
18
+ PolicyEvaluationOutput,
19
+ PolicyPort,
20
20
  };
@@ -1,7 +1,7 @@
1
1
  interface Repository<TEntity, TId> {
2
- findById(id: TId): Promise<TEntity | null>;
3
- save(entity: TEntity): Promise<void>;
4
- delete(id: TId): Promise<void>;
2
+ findById(id: TId): Promise<TEntity | null>;
3
+ save(entity: TEntity): Promise<void>;
4
+ delete(id: TId): Promise<void>;
5
5
  }
6
6
 
7
7
  export type { Repository };
@@ -5,10 +5,10 @@ import type { Repository } from "./repository.port";
5
5
  type TemporalHistory<TEntity> = readonly TemporalSnapshot<TEntity>[];
6
6
 
7
7
  interface TemporalRepository<TEntity, TId> extends Repository<TEntity, TId> {
8
- findAsOf(id: TId, asOf: Date): Promise<TEntity | null>;
9
- findAtTransaction(id: TId, txTime: Date): Promise<TEntity | null>;
10
- findHistory(id: TId): Promise<TemporalHistory<TEntity>>;
11
- save(entity: TEntity, validFrom?: Date): Promise<void>;
8
+ findAsOf(id: TId, asOf: Date): Promise<TEntity | null>;
9
+ findAtTransaction(id: TId, txTime: Date): Promise<TEntity | null>;
10
+ findHistory(id: TId): Promise<TemporalHistory<TEntity>>;
11
+ save(entity: TEntity, validFrom?: Date): Promise<void>;
12
12
  }
13
13
 
14
14
  export type { TemporalHistory, TemporalRepository };
@@ -1,16 +1,16 @@
1
1
  type TraceAttributeValue = string | number | boolean;
2
2
 
3
3
  interface TraceSpan {
4
- setAttribute(key: string, value: TraceAttributeValue): void;
5
- recordException(error: unknown): void;
6
- end(): void;
4
+ setAttribute(key: string, value: TraceAttributeValue): void;
5
+ recordException(error: unknown): void;
6
+ end(): void;
7
7
  }
8
8
 
9
9
  interface TracerPort {
10
- startSpan(
11
- name: string,
12
- attributes?: Record<string, TraceAttributeValue>,
13
- ): TraceSpan;
10
+ startSpan(
11
+ name: string,
12
+ attributes?: Record<string, TraceAttributeValue>,
13
+ ): TraceSpan;
14
14
  }
15
15
 
16
16
  export type { TraceAttributeValue, TraceSpan, TracerPort };
@@ -8,10 +8,10 @@ import type { Result } from "../../result/result";
8
8
  * Use as `Output` when the query returns a collection with pagination metadata.
9
9
  */
10
10
  interface Page<T> {
11
- readonly items: readonly T[];
12
- readonly total: number;
13
- readonly page: number;
14
- readonly pageSize: number;
11
+ readonly items: readonly T[];
12
+ readonly total: number;
13
+ readonly page: number;
14
+ readonly pageSize: number;
15
15
  }
16
16
 
17
17
  /**
@@ -19,9 +19,9 @@ interface Page<T> {
19
19
  * Infrastructure reads this value to decide whether and how to cache the result.
20
20
  */
21
21
  type CacheStrategy =
22
- | { readonly kind: "NO_CACHE" }
23
- | { readonly kind: "TIME_TO_LIVE"; readonly ttlMs: number }
24
- | { readonly kind: "STALE_WHILE_REVALIDATE"; readonly ttlMs: number };
22
+ | { readonly kind: "NO_CACHE" }
23
+ | { readonly kind: "TIME_TO_LIVE"; readonly ttlMs: number }
24
+ | { readonly kind: "STALE_WHILE_REVALIDATE"; readonly ttlMs: number };
25
25
 
26
26
  type QueryOutput = object | string | number | boolean | bigint | symbol | null;
27
27
 
@@ -40,13 +40,13 @@ type QueryOutput = object | string | number | boolean | bigint | symbol | null;
40
40
  */
41
41
  @version("1.0")
42
42
  abstract class Query<
43
- Input = void,
44
- Data extends QueryOutput = never,
45
- Failure = AppError,
43
+ Input = void,
44
+ Data extends QueryOutput = never,
45
+ Failure = AppError,
46
46
  > extends UseCase<Input, Result<Data, Failure>> {
47
- protected cacheStrategy(): CacheStrategy {
48
- return { kind: "NO_CACHE" };
49
- }
47
+ protected cacheStrategy(): CacheStrategy {
48
+ return { kind: "NO_CACHE" };
49
+ }
50
50
  }
51
51
 
52
52
  export type { CacheStrategy, Page, QueryOutput };
@@ -1,11 +1,11 @@
1
1
  export {
2
- assertTemporalContext,
3
- createTemporalContext,
4
- type CreateTemporalContextInput,
5
- type TemporalContext,
2
+ assertTemporalContext,
3
+ createTemporalContext,
4
+ type CreateTemporalContextInput,
5
+ type TemporalContext,
6
6
  } from "./temporal-context";
7
7
  export {
8
- type TemporalUseCaseInput,
9
- type TemporalizedContextSeed,
10
- TemporalUseCase,
8
+ type TemporalUseCaseInput,
9
+ type TemporalizedContextSeed,
10
+ TemporalUseCase,
11
11
  } from "./temporal-use-case";