@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.
- package/README.md +24 -24
- package/dist/gate-engine-registry.js.map +1 -1
- package/dist/gate-v1-payload.schema.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/outcome.js.map +1 -1
- package/dist/policies/engines/v1/gate/index.js.map +1 -1
- package/dist/policy-service.js.map +1 -1
- package/dist/validation-code.js.map +1 -1
- package/dist/validation-error.js.map +1 -1
- package/dist/validation-field.js.map +1 -1
- package/meta.json +67 -62
- package/package.json +56 -56
- package/src/core/application/commands/command.ts +3 -3
- package/src/core/application/commands/requested-by.ts +60 -60
- package/src/core/application/index.ts +21 -21
- package/src/core/application/policy-error-mapper.ts +54 -54
- package/src/core/application/ports/index.ts +6 -6
- package/src/core/application/ports/logger.port.ts +4 -4
- package/src/core/application/ports/metrics.port.ts +3 -3
- package/src/core/application/ports/policy-port.ts +7 -7
- package/src/core/application/ports/repository.port.ts +3 -3
- package/src/core/application/ports/temporal-repository.port.ts +4 -4
- package/src/core/application/ports/tracer.port.ts +7 -7
- package/src/core/application/queries/query.ts +13 -13
- package/src/core/application/temporal/index.ts +7 -7
- package/src/core/application/temporal/temporal-context.ts +20 -20
- package/src/core/application/temporal/temporal-use-case.ts +22 -22
- package/src/core/application/use-case.ts +10 -10
- package/src/core/config/core-config.instance.ts +1 -1
- package/src/core/config/core-config.ts +59 -59
- package/src/core/config/index.ts +6 -6
- package/src/core/config/policy-reporter.ts +31 -31
- package/src/core/config/silent-policy-reporter.ts +1 -1
- package/src/core/domain/entity.ts +44 -44
- package/src/core/domain/rulesets/entity-ruleset.contracts.ts +6 -6
- package/src/core/domain/rulesets/ruleset-registry.ts +49 -49
- package/src/core/domain/rulesets/ruleset.contracts.ts +6 -6
- package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +5 -5
- package/src/core/domain/temporal/index.ts +11 -11
- package/src/core/domain/temporal/temporal-range.ts +16 -16
- package/src/core/domain/temporal/temporal-snapshot.ts +24 -24
- package/src/core/domain/temporal/transaction-time.ts +30 -30
- package/src/core/domain/temporal/valid-time.ts +29 -29
- package/src/core/domain/value-object.ts +16 -16
- package/src/core/errors/app-error.ts +64 -64
- package/src/core/errors/authentication-error.ts +134 -134
- package/src/core/errors/authorization-error.ts +154 -154
- package/src/core/errors/business-rule-violation-error.ts +15 -15
- package/src/core/errors/conflict-error.ts +202 -201
- package/src/core/errors/error-codes.ts +48 -48
- package/src/core/errors/idempotency-error.ts +324 -320
- package/src/core/errors/index.ts +50 -50
- package/src/core/errors/integration-error.ts +120 -120
- package/src/core/errors/legacy-incompatible-error.ts +13 -13
- package/src/core/errors/not-found-error.ts +14 -14
- package/src/core/errors/serialization-error.ts +167 -167
- package/src/core/errors/temporal-error.ts +109 -107
- package/src/core/errors/types.ts +35 -35
- package/src/core/errors/unexpected-error.ts +10 -10
- package/src/core/errors/utils/index.ts +2 -2
- package/src/core/errors/utils/json-safe.ts +53 -53
- package/src/core/errors/validation-error.ts +18 -18
- package/src/core/exceptions/business-rule-violation-exception.ts +6 -6
- package/src/core/exceptions/domain-exception.ts +5 -5
- package/src/core/exceptions/entity-not-found-exception.ts +6 -6
- package/src/core/exceptions/invalid-state-transition-exception.ts +8 -8
- package/src/core/exceptions/invariant-violation-exception.ts +3 -3
- package/src/core/exceptions/validation-code.ts +35 -29
- package/src/core/exceptions/validation-exception.ts +19 -19
- package/src/core/exceptions/validation-field.ts +20 -19
- package/src/core/index.ts +7 -7
- package/src/core/policies/asof/asof.ts +47 -47
- package/src/core/policies/catalog/catalog.instance.ts +8 -6
- package/src/core/policies/catalog/index.ts +4 -4
- package/src/core/policies/catalog/policy-catalog-entry.ts +199 -197
- package/src/core/policies/catalog/policy-catalog.ts +101 -101
- package/src/core/policies/catalog/policy-key.ts +51 -51
- package/src/core/policies/context/context-builder.ts +335 -313
- package/src/core/policies/context/context-registry.instance.ts +9 -9
- package/src/core/policies/context/context-registry.ts +61 -61
- package/src/core/policies/context/context-resolver.ts +12 -12
- package/src/core/policies/context/context-seed.ts +19 -15
- package/src/core/policies/context/index.ts +9 -9
- package/src/core/policies/context/path.ts +135 -128
- package/src/core/policies/defs/in-memory-policy-definition-repo.ts +56 -55
- package/src/core/policies/defs/index.ts +10 -10
- package/src/core/policies/defs/policy-definition-repository.ts +3 -3
- package/src/core/policies/defs/policy-definition.ts +143 -142
- package/src/core/policies/defs/policy-scope.ts +21 -19
- package/src/core/policies/defs/policy-semver.ts +51 -51
- package/src/core/policies/engines/compute-engine-registry.ts +43 -43
- package/src/core/policies/engines/compute-evaluator-registry.ts +20 -20
- package/src/core/policies/engines/compute-registry.ts +45 -45
- package/src/core/policies/engines/compute-types.ts +15 -15
- package/src/core/policies/engines/condition-evaluator-reporter.ts +17 -17
- package/src/core/policies/engines/gate-engine-registry.ts +27 -25
- package/src/core/policies/engines/gate-types.ts +28 -28
- package/src/core/policies/engines/index.ts +28 -28
- package/src/core/policies/engines/parse-compute-payload.ts +51 -45
- package/src/core/policies/engines/parse-gate-payload.ts +42 -42
- package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +39 -37
- package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +43 -41
- package/src/core/policies/engines/v1/compute/index.ts +6 -6
- package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +41 -39
- package/src/core/policies/engines/v1/condition-evaluator.ts +547 -505
- package/src/core/policies/engines/v1/condition-schema.ts +35 -35
- package/src/core/policies/engines/v1/condition-types.ts +21 -21
- package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +134 -130
- package/src/core/policies/engines/v1/gate/gate-types-v1.ts +5 -5
- package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +32 -30
- package/src/core/policies/engines/v1/gate/index.ts +4 -4
- package/src/core/policies/engines/v1/index.ts +8 -8
- package/src/core/policies/index.ts +72 -72
- package/src/core/policies/package/policy-package.ts +3 -3
- package/src/core/policies/policy-ids.ts +25 -25
- package/src/core/policies/resolver/policy-resolver.ts +34 -34
- package/src/core/policies/service/index.ts +6 -6
- package/src/core/policies/service/policy-evaluation-error.ts +141 -133
- package/src/core/policies/service/policy-service.ts +432 -419
- package/src/core/policies/utils/date.ts +3 -3
- package/src/core/policies/utils/hash.ts +61 -61
- package/src/core/result/outcome.ts +131 -126
- package/src/core/result/result.ts +130 -127
- package/src/core/shared/aggregate-version.ts +5 -5
- package/src/core/shared/hashing.ts +18 -18
- package/src/core/shared/immutable.ts +29 -29
- package/src/core/shared/temporal-guards.ts +9 -9
- package/src/core/versioning/domain-event-contracts.ts +40 -40
- package/src/core/versioning/version.ts +19 -19
- package/src/examples/rulesets/entity/order-creation-rules-v1.ts +18 -18
- package/src/examples/rulesets/entity/order-invariants-v1.ts +31 -29
- package/src/examples/rulesets/entity/order-invariants-v2.ts +12 -12
- package/src/examples/rulesets/entity/order.ts +127 -127
- package/src/examples/rulesets/value-object/cpf-rules-v1.ts +41 -39
- package/src/examples/rulesets/value-object/cpf-rules-v2.ts +14 -12
- package/src/examples/rulesets/value-object/cpf.ts +24 -24
- package/src/examples/rulesets/value-object/customer.ts +42 -39
- package/src/examples/rulesets/value-object/person-name-rules-v1.ts +27 -27
- package/src/examples/rulesets/value-object/person-name-rules-v2.ts +13 -13
- package/src/examples/rulesets/value-object/person-name.ts +29 -26
- package/src/index.ts +2 -2
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsdown --config tsdown.config.ts",
|
|
42
|
+
"dev": "tsdown --config tsdown.config.ts --watch"
|
|
25
43
|
},
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
"
|
|
31
|
-
|
|
32
|
-
"import": "./dist/policies/engines/v1/gate/index.js"
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"zod": ">=3.22.0 <5"
|
|
33
59
|
},
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"import": "./dist/exceptions/validation-field.js"
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
37
62
|
},
|
|
38
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
73
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
get isUser(): boolean {
|
|
84
|
+
return this.kind === "user";
|
|
85
|
+
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
get isSystem(): boolean {
|
|
88
|
+
return this.kind === "system";
|
|
89
|
+
}
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
12
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
evaluate(
|
|
11
|
+
input: PolicyEvaluationInput,
|
|
12
|
+
): Promise<Result<PolicyEvaluationOutput, PolicyEvaluationError>>;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export type {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
PolicyEvaluationError,
|
|
17
|
+
PolicyEvaluationInput,
|
|
18
|
+
PolicyEvaluationOutput,
|
|
19
|
+
PolicyPort,
|
|
20
20
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
interface Repository<TEntity, TId> {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
setAttribute(key: string, value: TraceAttributeValue): void;
|
|
5
|
+
recordException(error: unknown): void;
|
|
6
|
+
end(): void;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
interface TracerPort {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
Input = void,
|
|
44
|
+
Data extends QueryOutput = never,
|
|
45
|
+
Failure = AppError,
|
|
46
46
|
> extends UseCase<Input, Result<Data, Failure>> {
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
assertTemporalContext,
|
|
3
|
+
createTemporalContext,
|
|
4
|
+
type CreateTemporalContextInput,
|
|
5
|
+
type TemporalContext,
|
|
6
6
|
} from "./temporal-context";
|
|
7
7
|
export {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
type TemporalUseCaseInput,
|
|
9
|
+
type TemporalizedContextSeed,
|
|
10
|
+
TemporalUseCase,
|
|
11
11
|
} from "./temporal-use-case";
|