@cullet/erp-core 1.5.0 → 2.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.
- package/KIT_CONTEXT.md +2 -2
- package/dist/abac/index.d.cts +2 -2
- package/dist/abac/index.d.ts +2 -2
- package/dist/aggregate-version.cjs +14 -0
- package/dist/aggregate-version.cjs.map +1 -0
- package/dist/aggregate-version.js +9 -0
- package/dist/aggregate-version.js.map +1 -0
- package/dist/app-error.cjs +8 -1
- package/dist/app-error.cjs.map +1 -1
- package/dist/app-error.js +8 -1
- package/dist/app-error.js.map +1 -1
- package/dist/application/index.cjs +8 -4
- package/dist/application/index.d.cts +2 -2
- package/dist/application/index.d.ts +2 -2
- package/dist/application/index.js +1 -2
- package/dist/authorization-error.cjs +67 -17
- package/dist/authorization-error.cjs.map +1 -1
- package/dist/authorization-error.d.cts +6 -2
- package/dist/authorization-error.d.ts +6 -2
- package/dist/authorization-error.js +50 -18
- package/dist/authorization-error.js.map +1 -1
- package/dist/authorizer.port.d.cts +18 -3
- package/dist/authorizer.port.d.ts +18 -3
- package/dist/composite-authorizer.d.cts +63 -10
- package/dist/composite-authorizer.d.ts +63 -10
- package/dist/condition-evaluator.cjs +115 -184
- package/dist/condition-evaluator.cjs.map +1 -1
- package/dist/condition-evaluator.js +116 -179
- package/dist/condition-evaluator.js.map +1 -1
- package/dist/core-config.d.cts +53 -6
- package/dist/core-config.d.ts +53 -6
- package/dist/decorate.cjs +14 -0
- package/dist/decorate.js +9 -0
- package/dist/domain/index.cjs +107 -2
- package/dist/domain/index.cjs.map +1 -0
- package/dist/domain/index.d.cts +25 -1
- package/dist/domain/index.d.ts +25 -1
- package/dist/domain/index.js +99 -3
- package/dist/domain/index.js.map +1 -0
- package/dist/domain-event-contracts.cjs +12 -8
- package/dist/domain-event-contracts.cjs.map +1 -1
- package/dist/domain-event-contracts.d.cts +29 -4
- package/dist/domain-event-contracts.d.ts +29 -4
- package/dist/domain-event-contracts.js +11 -7
- package/dist/domain-event-contracts.js.map +1 -1
- package/dist/domain-exception.cjs +2 -1
- package/dist/domain-exception.cjs.map +1 -1
- package/dist/domain-exception.js +2 -1
- package/dist/domain-exception.js.map +1 -1
- package/dist/errors/index.cjs +1 -1
- package/dist/errors/index.d.cts +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +2 -2
- package/dist/exceptions/index.cjs +2 -2
- package/dist/exceptions/index.d.cts +1 -2
- package/dist/exceptions/index.d.ts +1 -2
- package/dist/exceptions/index.js +2 -2
- package/dist/gate-engine-registry.cjs.map +1 -1
- package/dist/gate-engine-registry.d.cts +1 -1
- package/dist/gate-engine-registry.d.ts +1 -1
- package/dist/gate-engine-registry.js.map +1 -1
- package/dist/gate-v1-payload.schema.cjs +11 -6
- package/dist/gate-v1-payload.schema.cjs.map +1 -1
- package/dist/gate-v1-payload.schema.js +11 -6
- package/dist/gate-v1-payload.schema.js.map +1 -1
- package/dist/hashing.cjs +1 -1
- package/dist/hashing.cjs.map +1 -1
- package/dist/hashing.js +2 -2
- package/dist/hashing.js.map +1 -1
- package/dist/immutable.cjs +25 -12
- package/dist/immutable.cjs.map +1 -1
- package/dist/immutable.js +24 -11
- package/dist/immutable.js.map +1 -1
- package/dist/index.cjs +13 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -10
- package/dist/index.d.ts +9 -10
- package/dist/index.js +7 -9
- package/dist/index.js.map +1 -1
- package/dist/invalid-state-transition-exception.cjs +6 -6
- package/dist/invalid-state-transition-exception.cjs.map +1 -1
- package/dist/invalid-state-transition-exception.js +6 -6
- package/dist/invalid-state-transition-exception.js.map +1 -1
- package/dist/invariant-violation-exception.cjs +2 -2
- package/dist/invariant-violation-exception.cjs.map +1 -1
- package/dist/invariant-violation-exception.js +2 -2
- package/dist/invariant-violation-exception.js.map +1 -1
- package/dist/not-found-error.cjs +6 -4
- package/dist/not-found-error.cjs.map +1 -1
- package/dist/not-found-error.js +6 -4
- package/dist/not-found-error.js.map +1 -1
- package/dist/outcome.cjs +5 -5
- package/dist/outcome.cjs.map +1 -1
- package/dist/outcome.js +5 -5
- package/dist/outcome.js.map +1 -1
- package/dist/parse-gate-payload.d.cts +1 -1
- package/dist/parse-gate-payload.d.ts +1 -1
- package/dist/path.d.cts +2 -2
- package/dist/path.d.ts +2 -2
- package/dist/plugin.cjs +23 -13
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +22 -8
- package/dist/plugin.d.ts +22 -8
- package/dist/plugin.js +23 -13
- package/dist/plugin.js.map +1 -1
- package/dist/policies/engines/index.d.cts +1 -1
- package/dist/policies/engines/index.d.ts +1 -1
- package/dist/policies/engines/v1/gate/index.d.cts +3 -15
- package/dist/policies/engines/v1/gate/index.d.ts +3 -15
- package/dist/policies/index.d.cts +1 -1
- package/dist/policies/index.d.ts +1 -1
- package/dist/policy-bridge.cjs +30 -2
- package/dist/policy-bridge.cjs.map +1 -1
- package/dist/policy-bridge.d.cts +18 -0
- package/dist/policy-bridge.d.ts +18 -0
- package/dist/policy-bridge.js +30 -2
- package/dist/policy-bridge.js.map +1 -1
- package/dist/policy-service.cjs +40 -46
- package/dist/policy-service.cjs.map +1 -1
- package/dist/policy-service.d.cts +72 -9
- package/dist/policy-service.d.ts +72 -9
- package/dist/policy-service.js +42 -48
- package/dist/policy-service.js.map +1 -1
- package/dist/requested-by.cjs +1 -1
- package/dist/requested-by.cjs.map +1 -1
- package/dist/requested-by.js +1 -1
- package/dist/requested-by.js.map +1 -1
- package/dist/result.cjs +29 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +12 -0
- package/dist/result.d.ts +12 -0
- package/dist/result.js +29 -1
- package/dist/result.js.map +1 -1
- package/dist/rule.cjs +94 -24
- package/dist/rule.cjs.map +1 -1
- package/dist/rule.js +94 -24
- package/dist/rule.js.map +1 -1
- package/dist/ruleset-registry.cjs +19 -0
- package/dist/ruleset-registry.cjs.map +1 -1
- package/dist/ruleset-registry.js +19 -0
- package/dist/ruleset-registry.js.map +1 -1
- package/dist/stable-stringify.cjs +43 -3
- package/dist/stable-stringify.cjs.map +1 -1
- package/dist/stable-stringify.js +38 -4
- package/dist/stable-stringify.js.map +1 -1
- package/dist/temporal-snapshot.d.cts +87 -0
- package/dist/temporal-snapshot.d.ts +87 -0
- package/dist/temporal-use-case.cjs +169 -16
- package/dist/temporal-use-case.cjs.map +1 -1
- package/dist/temporal-use-case.d.cts +76 -43
- package/dist/temporal-use-case.d.ts +76 -43
- package/dist/temporal-use-case.js +162 -15
- package/dist/temporal-use-case.js.map +1 -1
- package/dist/unexpected-error.cjs +4 -2
- package/dist/unexpected-error.cjs.map +1 -1
- package/dist/unexpected-error.js +4 -2
- package/dist/unexpected-error.js.map +1 -1
- package/dist/uuid-identifier.cjs +140 -2
- package/dist/uuid-identifier.cjs.map +1 -1
- package/dist/uuid-identifier.d.cts +26 -7
- package/dist/uuid-identifier.d.ts +26 -7
- package/dist/uuid-identifier.js +135 -3
- package/dist/uuid-identifier.js.map +1 -1
- package/dist/uuid.cjs +11 -6
- package/dist/uuid.cjs.map +1 -1
- package/dist/uuid.js +11 -6
- package/dist/uuid.js.map +1 -1
- package/dist/validation-code.cjs +9 -0
- package/dist/validation-code.cjs.map +1 -1
- package/dist/validation-code.d.cts +3 -0
- package/dist/validation-code.d.ts +3 -0
- package/dist/validation-code.js +9 -0
- package/dist/validation-code.js.map +1 -1
- package/dist/validation-error.cjs +42 -67
- package/dist/validation-error.cjs.map +1 -1
- package/dist/validation-error.d.cts +24 -8
- package/dist/validation-error.d.ts +24 -8
- package/dist/validation-error.js +41 -66
- package/dist/validation-error.js.map +1 -1
- package/dist/validation-exception.cjs +17 -6
- package/dist/validation-exception.cjs.map +1 -1
- package/dist/validation-exception.d.cts +33 -9
- package/dist/validation-exception.d.ts +33 -9
- package/dist/validation-exception.js +17 -6
- package/dist/validation-exception.js.map +1 -1
- package/dist/validation-field.cjs +3 -0
- package/dist/validation-field.cjs.map +1 -1
- package/dist/validation-field.d.cts +1 -0
- package/dist/validation-field.d.ts +1 -0
- package/dist/validation-field.js +3 -0
- package/dist/validation-field.js.map +1 -1
- package/dist/value-object-ruleset.contracts.d.cts +10 -0
- package/dist/value-object-ruleset.contracts.d.ts +10 -0
- package/dist/value-object.cjs +12 -2
- package/dist/value-object.cjs.map +1 -1
- package/dist/value-object.d.cts +16 -0
- package/dist/value-object.d.ts +16 -0
- package/dist/value-object.js +13 -3
- package/dist/value-object.js.map +1 -1
- package/dist/version.d.cts +27 -0
- package/dist/version.d.ts +27 -0
- package/dist/versioning/index.d.cts +2 -2
- package/dist/versioning/index.d.ts +2 -2
- package/meta.json +3 -2
- package/package.json +1 -1
- package/src/core/abac/authorizer.ts +60 -10
- package/src/core/abac/domain/policy-set.ts +52 -5
- package/src/core/abac/domain/rule.ts +28 -16
- package/src/core/abac/index.ts +7 -1
- package/src/core/application/commands/command.ts +14 -1
- package/src/core/application/commands/requested-by.ts +12 -3
- package/src/core/application/index.ts +2 -1
- package/src/core/application/policy-error-mapper.ts +6 -0
- package/src/core/application/ports/index.ts +7 -0
- package/src/core/application/ports/temporal-repository.port.ts +35 -2
- package/src/core/application/queries/index.ts +1 -1
- package/src/core/application/queries/query.ts +19 -2
- package/src/core/application/temporal/temporal-use-case.ts +31 -4
- package/src/core/application/use-case.ts +44 -7
- package/src/core/config/core-config.ts +46 -25
- package/src/core/config/index.ts +1 -0
- package/src/core/config/policy-reporter.ts +32 -1
- package/src/core/domain/entity.ts +50 -7
- package/src/core/domain/rulesets/entity-ruleset.contracts.ts +0 -2
- package/src/core/domain/rulesets/ruleset-registry.ts +24 -0
- package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +1 -7
- package/src/core/domain/temporal/half-open-interval.ts +34 -0
- package/src/core/domain/temporal/temporal-snapshot.ts +13 -2
- package/src/core/domain/temporal/transaction-time.ts +19 -15
- package/src/core/domain/temporal/valid-time.ts +20 -15
- package/src/core/domain/uuid-identifier.ts +5 -3
- package/src/core/domain/value-object.ts +17 -0
- package/src/core/errors/authentication-error.ts +5 -31
- package/src/core/errors/authorization-error.ts +12 -20
- package/src/core/errors/business-rule-violation-error.ts +4 -1
- package/src/core/errors/idempotency-error.ts +5 -2
- package/src/core/errors/index.ts +4 -0
- package/src/core/errors/integration-error.ts +4 -24
- package/src/core/errors/legacy-incompatible-error.ts +1 -0
- package/src/core/errors/not-found-error.ts +4 -1
- package/src/core/errors/temporal-error.ts +22 -20
- package/src/core/errors/unexpected-error.ts +5 -1
- package/src/core/errors/utils/factory-helpers.ts +70 -0
- package/src/core/errors/utils/index.ts +5 -0
- package/src/core/errors/utils/json-safe.ts +15 -1
- package/src/core/errors/validation-error.ts +4 -1
- package/src/core/exceptions/business-rule-violation-exception.ts +2 -1
- package/src/core/exceptions/domain-exception.ts +9 -1
- package/src/core/exceptions/entity-not-found-exception.ts +5 -1
- package/src/core/exceptions/invalid-state-transition-exception.ts +5 -2
- package/src/core/exceptions/invariant-violation-exception.ts +2 -2
- package/src/core/exceptions/validation-code.ts +14 -0
- package/src/core/exceptions/validation-exception.ts +44 -5
- package/src/core/exceptions/validation-field.ts +11 -1
- package/src/core/plugins/plugin.ts +25 -15
- package/src/core/plugins/types.ts +4 -2
- package/src/core/policies/asof/asof.ts +12 -0
- package/src/core/policies/catalog/policy-catalog-entry.ts +3 -1
- package/src/core/policies/catalog/policy-catalog.ts +5 -1
- package/src/core/policies/context/context-builder.ts +20 -0
- package/src/core/policies/context/context-resolver.ts +5 -0
- package/src/core/policies/context/context-seed.ts +11 -0
- package/src/core/policies/defs/in-memory-policy-definition-repo.ts +0 -2
- package/src/core/policies/engines/parse-gate-payload.ts +9 -0
- package/src/core/policies/engines/v1/condition-date-operands.ts +112 -0
- package/src/core/policies/engines/v1/condition-evaluator.ts +99 -325
- package/src/core/policies/engines/v1/condition-schema.ts +23 -19
- package/src/core/policies/engines/v1/condition-types.ts +18 -11
- package/src/core/policies/index.ts +4 -6
- package/src/core/policies/service/policy-service.ts +46 -35
- package/src/core/policies/utils/hash.ts +5 -69
- package/src/core/policies/utils/result.ts +1 -1
- package/src/core/rbac/access-request.ts +12 -2
- package/src/core/rbac/authorizer.ts +8 -1
- package/src/core/rbac/domain/role.ts +20 -0
- package/src/core/rbac/domain/scope.ts +6 -1
- package/src/core/result/index.ts +5 -0
- package/src/core/result/outcome.ts +5 -7
- package/src/core/result/result.ts +34 -1
- package/src/core/shared/hashing.ts +6 -3
- package/src/core/shared/immutable.ts +22 -4
- package/src/core/shared/stable-stringify.ts +91 -4
- package/src/core/shared/uuid.ts +11 -6
- package/src/core/versioning/domain-event-contracts.ts +43 -15
- package/src/core/versioning/index.ts +1 -0
- package/src/core/versioning/version.ts +30 -1
- package/src/domain/index.ts +5 -0
- package/src/examples/rulesets/entity/order-creation-rules-v1.ts +1 -1
- package/src/examples/rulesets/entity/order-invariants-v1.ts +2 -4
- package/src/examples/rulesets/entity/order-invariants-v2.ts +2 -4
- package/src/examples/rulesets/value-object/cpf-rules-v1.ts +2 -4
- package/src/examples/rulesets/value-object/cpf-rules-v2.ts +2 -4
- package/src/examples/rulesets/value-object/person-name-rules-v1.ts +2 -4
- package/src/examples/rulesets/value-object/person-name-rules-v2.ts +2 -4
- package/src/result/index.ts +7 -2
- package/src/version.ts +1 -1
- package/dist/domain-exception.d.cts +0 -7
- package/dist/domain-exception.d.ts +0 -7
- package/dist/entity.cjs +0 -122
- package/dist/entity.cjs.map +0 -1
- package/dist/entity.js +0 -111
- package/dist/entity.js.map +0 -1
- package/dist/use-case.cjs +0 -92
- package/dist/use-case.cjs.map +0 -1
- package/dist/use-case.js +0 -87
- package/dist/use-case.js.map +0 -1
|
@@ -6,14 +6,23 @@ var SilentPolicyReporter = class {
|
|
|
6
6
|
};
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/core/config/core-config.ts
|
|
9
|
-
|
|
9
|
+
/** Reports an event without letting a throwing reporter abort the caller. */
|
|
10
|
+
function safeReport(policyReporter, event) {
|
|
10
11
|
try {
|
|
11
12
|
policyReporter.report(event);
|
|
12
13
|
} catch {}
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* The core's config namespace. Today it holds a single section —
|
|
17
|
+
* `observability` — whose whole job is to decide *where policy telemetry goes*
|
|
18
|
+
* while guaranteeing telemetry is best-effort (a throwing reporter can never
|
|
19
|
+
* abort a domain flow). App config (env, settings, feature flags) is
|
|
20
|
+
* deliberately absent for now: when the core needs it, it joins here as a
|
|
21
|
+
* sibling section rather than a new module — which is why this is `config`,
|
|
22
|
+
* not `observability`. It holds the active {@link PolicyReporter} (silent by
|
|
23
|
+
* default, so the core carries no logging dependency), bridges it to the
|
|
24
|
+
* engines' {@link ConditionEvaluatorReporter}, and offers `reportSafely` as
|
|
25
|
+
* the single guarded emit path shared with {@link PolicyService}.
|
|
17
26
|
*/
|
|
18
27
|
var CoreConfig = class {
|
|
19
28
|
#initialReporter;
|
|
@@ -23,17 +32,23 @@ var CoreConfig = class {
|
|
|
23
32
|
this.#initialReporter = reporter;
|
|
24
33
|
this.#currentReporter = reporter;
|
|
25
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Swaps the active reporter. Pass `observability.reporter` to enable
|
|
37
|
+
* telemetry, or set it explicitly to `undefined` to go silent again.
|
|
38
|
+
* Omitting `observability` (or its `reporter` key) is a no-op.
|
|
39
|
+
*/
|
|
26
40
|
configure(options) {
|
|
27
|
-
const
|
|
28
|
-
if (reporter) this.#currentReporter = reporter;
|
|
41
|
+
const observability = options.observability;
|
|
42
|
+
if (observability && "reporter" in observability) this.#currentReporter = observability.reporter ?? new SilentPolicyReporter();
|
|
29
43
|
return this;
|
|
30
44
|
}
|
|
31
45
|
reset() {
|
|
32
46
|
this.#currentReporter = this.#initialReporter;
|
|
33
47
|
return this;
|
|
34
48
|
}
|
|
35
|
-
|
|
36
|
-
|
|
49
|
+
/** Emits a policy event through the active reporter, best-effort. */
|
|
50
|
+
reportSafely(event) {
|
|
51
|
+
safeReport(this.#currentReporter, event);
|
|
37
52
|
}
|
|
38
53
|
getConditionEvaluationOptions(engineVersion) {
|
|
39
54
|
return {
|
|
@@ -42,19 +57,16 @@ var CoreConfig = class {
|
|
|
42
57
|
};
|
|
43
58
|
}
|
|
44
59
|
#bridgeToConditionReporter(policyReporter) {
|
|
60
|
+
const emit = (level, report) => {
|
|
61
|
+
safeReport(policyReporter, {
|
|
62
|
+
kind: "condition-eval",
|
|
63
|
+
...report,
|
|
64
|
+
level
|
|
65
|
+
});
|
|
66
|
+
};
|
|
45
67
|
return {
|
|
46
|
-
warn(report)
|
|
47
|
-
|
|
48
|
-
kind: "condition-eval",
|
|
49
|
-
...report
|
|
50
|
-
});
|
|
51
|
-
},
|
|
52
|
-
error(report) {
|
|
53
|
-
reportSafely(policyReporter, {
|
|
54
|
-
kind: "condition-eval",
|
|
55
|
-
...report
|
|
56
|
-
});
|
|
57
|
-
}
|
|
68
|
+
warn: (report) => emit("warn", report),
|
|
69
|
+
error: (report) => emit("error", report)
|
|
58
70
|
};
|
|
59
71
|
}
|
|
60
72
|
};
|
|
@@ -159,6 +171,54 @@ var PolicyDateUtils = class {
|
|
|
159
171
|
}
|
|
160
172
|
};
|
|
161
173
|
//#endregion
|
|
174
|
+
//#region src/core/policies/engines/v1/condition-date-operands.ts
|
|
175
|
+
/**
|
|
176
|
+
* The one instant format condition date operands may use. Strict on purpose
|
|
177
|
+
* (UTC, milliseconds) so comparisons are unambiguous across time zones — and
|
|
178
|
+
* so a malformed operand fails loudly instead of comparing wrong.
|
|
179
|
+
*/
|
|
180
|
+
const CANONICAL_UTC_DATE_FORMAT = "YYYY-MM-DDTHH:mm:ss.SSSZ";
|
|
181
|
+
const ISO_8601_UTC_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
182
|
+
const ISO_8601_DATE_LIKE_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}/;
|
|
183
|
+
/**
|
|
184
|
+
* Parses a value used as a date operand:
|
|
185
|
+
* - `Result.ok(Date)` for a valid Date or a canonical ISO-8601 UTC string;
|
|
186
|
+
* - `Result.err` when it is date-shaped but malformed (invalid Date, or a
|
|
187
|
+
* date-like string that isn't canonical UTC) — a configuration error worth
|
|
188
|
+
* surfacing rather than silently treating as "not a date";
|
|
189
|
+
* - `null` when the value isn't date-shaped at all, so the caller can fall
|
|
190
|
+
* through to a numeric comparison.
|
|
191
|
+
*/
|
|
192
|
+
function parseComparableDate(value) {
|
|
193
|
+
if (value instanceof Date) return PolicyDateUtils.isValid(value) ? Result.ok(value) : Result.err("Invalid Date instance");
|
|
194
|
+
if (typeof value !== "string") return null;
|
|
195
|
+
if (ISO_8601_UTC_DATE_PATTERN.test(value)) {
|
|
196
|
+
const parsed = new Date(value);
|
|
197
|
+
if (!PolicyDateUtils.isValid(parsed) || parsed.toISOString() !== value) return Result.err("Invalid ISO 8601 UTC date string");
|
|
198
|
+
return Result.ok(parsed);
|
|
199
|
+
}
|
|
200
|
+
if (ISO_8601_DATE_LIKE_PATTERN.test(value)) return Result.err(`date operand must be canonical ISO 8601 UTC (${CANONICAL_UTC_DATE_FORMAT})`);
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
function evaluateRelationalNumbers(actual, op, expected) {
|
|
204
|
+
switch (op) {
|
|
205
|
+
case "gt": return actual > expected;
|
|
206
|
+
case "gte": return actual >= expected;
|
|
207
|
+
case "lt": return actual < expected;
|
|
208
|
+
case "lte": return actual <= expected;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function containsInvalidDate(value) {
|
|
212
|
+
if (value instanceof Date) return !PolicyDateUtils.isValid(value);
|
|
213
|
+
if (Array.isArray(value)) return value.some((item) => containsInvalidDate(item));
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
function normalizeDateOperand(value) {
|
|
217
|
+
if (value instanceof Date) return value.toISOString();
|
|
218
|
+
if (Array.isArray(value)) return value.map((item) => normalizeDateOperand(item));
|
|
219
|
+
return value;
|
|
220
|
+
}
|
|
221
|
+
//#endregion
|
|
162
222
|
//#region src/core/policies/engines/v1/condition-evaluator.ts
|
|
163
223
|
const CONDITION_EVAL_THROWN_TAG = "CONDITION_EVAL_THREW";
|
|
164
224
|
const NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG = "NULLISH_NUMERIC_OPERAND_NOT_ALLOWED";
|
|
@@ -168,7 +228,6 @@ const INVALID_NUMERIC_OPERAND_TAG = "INVALID_NUMERIC_OPERAND";
|
|
|
168
228
|
const INVALID_SET_OPERAND_TAG = "INVALID_SET_OPERAND";
|
|
169
229
|
const EMPTY_OR_CONDITION_TAG = "EMPTY_OR_CONDITION";
|
|
170
230
|
const EMPTY_AND_CONDITION_TAG = "EMPTY_AND_CONDITION";
|
|
171
|
-
const ISO_8601_UTC_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
172
231
|
var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
173
232
|
constructor(context, options) {
|
|
174
233
|
this.context = context;
|
|
@@ -199,46 +258,8 @@ var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
|
199
258
|
message: String(error)
|
|
200
259
|
};
|
|
201
260
|
}
|
|
202
|
-
static
|
|
203
|
-
|
|
204
|
-
return `${NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG}: "${node.field}" resolved to ${resolvedValue} for numeric operator "${node.op}"`;
|
|
205
|
-
}
|
|
206
|
-
static buildNullishDateOperandMessage(node, actual) {
|
|
207
|
-
const resolvedValue = actual === null ? "null" : "undefined";
|
|
208
|
-
return `${NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG}: "${node.field}" resolved to ${resolvedValue} for date comparison operator "${node.op}"`;
|
|
209
|
-
}
|
|
210
|
-
static buildInvalidDateOperandMessage(node) {
|
|
211
|
-
return `${INVALID_DATE_OPERAND_TAG}: "${node.field}" with operator "${node.op}" requires Date or ISO 8601 UTC string operands`;
|
|
212
|
-
}
|
|
213
|
-
static buildInvalidNumericOperandMessage(node) {
|
|
214
|
-
return `${INVALID_NUMERIC_OPERAND_TAG}: "${node.field}" with operator "${node.op}" requires numeric operands`;
|
|
215
|
-
}
|
|
216
|
-
static buildInvalidSetOperandMessage(node) {
|
|
217
|
-
return `${INVALID_SET_OPERAND_TAG}: "${node.field}" with operator "${node.op}" requires an array operand`;
|
|
218
|
-
}
|
|
219
|
-
static buildEmptyOrConditionMessage() {
|
|
220
|
-
return `${EMPTY_OR_CONDITION_TAG}: OR nodes must contain at least one child condition`;
|
|
221
|
-
}
|
|
222
|
-
static buildEmptyAndConditionMessage() {
|
|
223
|
-
return `${EMPTY_AND_CONDITION_TAG}: AND nodes must contain at least one child condition`;
|
|
224
|
-
}
|
|
225
|
-
static parseComparableDate(value) {
|
|
226
|
-
if (value instanceof Date) {
|
|
227
|
-
if (!PolicyDateUtils.isValid(value)) return Result.err("Invalid Date instance");
|
|
228
|
-
return Result.ok(value);
|
|
229
|
-
}
|
|
230
|
-
if (typeof value !== "string" || !ISO_8601_UTC_DATE_PATTERN.test(value)) return null;
|
|
231
|
-
const parsed = new Date(value);
|
|
232
|
-
if (!PolicyDateUtils.isValid(parsed) || parsed.toISOString() !== value) return Result.err("Invalid ISO 8601 UTC date string");
|
|
233
|
-
return Result.ok(parsed);
|
|
234
|
-
}
|
|
235
|
-
static evaluateRelationalNumbers(actual, op, expected) {
|
|
236
|
-
switch (op) {
|
|
237
|
-
case "gt": return actual > expected;
|
|
238
|
-
case "gte": return actual >= expected;
|
|
239
|
-
case "lt": return actual < expected;
|
|
240
|
-
case "lte": return actual <= expected;
|
|
241
|
-
}
|
|
261
|
+
static invalidDateOperandMessage(node) {
|
|
262
|
+
return `${INVALID_DATE_OPERAND_TAG}: "${node.field}" with operator "${node.op}" requires Date or ISO 8601 UTC (${CANONICAL_UTC_DATE_FORMAT}) string operands`;
|
|
242
263
|
}
|
|
243
264
|
buildReport(params) {
|
|
244
265
|
return {
|
|
@@ -250,172 +271,88 @@ var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
|
250
271
|
details: params.details
|
|
251
272
|
};
|
|
252
273
|
}
|
|
253
|
-
|
|
254
|
-
const cause = ConditionEvaluatorV1.describeError(error);
|
|
255
|
-
const message = `${CONDITION_EVAL_THROWN_TAG}: ${cause.name}: ${cause.message}`;
|
|
274
|
+
reportLeafError(tag, message, node, actual, extra) {
|
|
256
275
|
this.options.reporter.error(this.buildReport({
|
|
257
276
|
level: "error",
|
|
258
|
-
tag
|
|
259
|
-
message,
|
|
260
|
-
details: {
|
|
261
|
-
node,
|
|
262
|
-
cause
|
|
263
|
-
}
|
|
264
|
-
}));
|
|
265
|
-
return Result.err(message);
|
|
266
|
-
}
|
|
267
|
-
static containsInvalidDate(value) {
|
|
268
|
-
if (value instanceof Date) return !PolicyDateUtils.isValid(value);
|
|
269
|
-
if (Array.isArray(value)) return value.some((item) => ConditionEvaluatorV1.containsInvalidDate(item));
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
static normalizeDateOperand(value) {
|
|
273
|
-
if (value instanceof Date) return value.toISOString();
|
|
274
|
-
if (Array.isArray(value)) return value.map((item) => ConditionEvaluatorV1.normalizeDateOperand(item));
|
|
275
|
-
return value;
|
|
276
|
-
}
|
|
277
|
-
reportDateOperandError(node, actual) {
|
|
278
|
-
const message = ConditionEvaluatorV1.buildInvalidDateOperandMessage(node);
|
|
279
|
-
this.options.reporter.error(this.buildReport({
|
|
280
|
-
level: "error",
|
|
281
|
-
tag: INVALID_DATE_OPERAND_TAG,
|
|
277
|
+
tag,
|
|
282
278
|
message,
|
|
283
279
|
details: {
|
|
284
280
|
field: node.field,
|
|
285
281
|
op: node.op,
|
|
286
282
|
actual,
|
|
287
283
|
expected: node.value,
|
|
284
|
+
...extra,
|
|
288
285
|
node
|
|
289
286
|
}
|
|
290
287
|
}));
|
|
291
288
|
return Result.err(message);
|
|
292
289
|
}
|
|
293
|
-
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
level: "error",
|
|
297
|
-
tag: INVALID_NUMERIC_OPERAND_TAG,
|
|
298
|
-
message,
|
|
299
|
-
details: {
|
|
300
|
-
field: node.field,
|
|
301
|
-
op: node.op,
|
|
302
|
-
actual,
|
|
303
|
-
expected: node.value,
|
|
304
|
-
node
|
|
305
|
-
}
|
|
306
|
-
}));
|
|
307
|
-
return Result.err(message);
|
|
308
|
-
}
|
|
309
|
-
reportInvalidSetOperand(node, actual) {
|
|
310
|
-
const message = ConditionEvaluatorV1.buildInvalidSetOperandMessage(node);
|
|
290
|
+
conditionEvalErr(node, error) {
|
|
291
|
+
const cause = ConditionEvaluatorV1.describeError(error);
|
|
292
|
+
const message = `${CONDITION_EVAL_THROWN_TAG}: ${cause.name}: ${cause.message}`;
|
|
311
293
|
this.options.reporter.error(this.buildReport({
|
|
312
294
|
level: "error",
|
|
313
|
-
tag:
|
|
295
|
+
tag: CONDITION_EVAL_THROWN_TAG,
|
|
314
296
|
message,
|
|
315
297
|
details: {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
actual,
|
|
319
|
-
expected: node.value,
|
|
320
|
-
node
|
|
298
|
+
node,
|
|
299
|
+
cause
|
|
321
300
|
}
|
|
322
301
|
}));
|
|
323
302
|
return Result.err(message);
|
|
324
303
|
}
|
|
325
304
|
evaluateDateRelationalNode(node, actual) {
|
|
326
305
|
if (!ConditionEvaluatorV1.isRelationalOperator(node.op)) return null;
|
|
327
|
-
const
|
|
328
|
-
const
|
|
329
|
-
if (
|
|
306
|
+
const actualDate = parseComparableDate(actual);
|
|
307
|
+
const expectedDate = parseComparableDate(node.value);
|
|
308
|
+
if (actualDate === null && expectedDate === null) return null;
|
|
330
309
|
const allowsNull = node.allowNull === true;
|
|
331
|
-
if (actual === null)
|
|
332
|
-
|
|
333
|
-
const
|
|
334
|
-
this.
|
|
335
|
-
level: "error",
|
|
336
|
-
tag: NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG,
|
|
337
|
-
message,
|
|
338
|
-
details: {
|
|
339
|
-
field: node.field,
|
|
340
|
-
op: node.op,
|
|
341
|
-
actual,
|
|
342
|
-
expected: node.value,
|
|
343
|
-
allowNull: allowsNull,
|
|
344
|
-
node
|
|
345
|
-
}
|
|
346
|
-
}));
|
|
347
|
-
return Result.err(message);
|
|
348
|
-
}
|
|
349
|
-
if (actual === void 0) {
|
|
350
|
-
const message = ConditionEvaluatorV1.buildNullishDateOperandMessage(node, actual);
|
|
351
|
-
this.options.reporter.error(this.buildReport({
|
|
352
|
-
level: "error",
|
|
353
|
-
tag: NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG,
|
|
354
|
-
message,
|
|
355
|
-
details: {
|
|
356
|
-
field: node.field,
|
|
357
|
-
op: node.op,
|
|
358
|
-
actual,
|
|
359
|
-
expected: node.value,
|
|
360
|
-
allowNull: allowsNull,
|
|
361
|
-
node
|
|
362
|
-
}
|
|
363
|
-
}));
|
|
364
|
-
return Result.err(message);
|
|
310
|
+
if (actual === null && allowsNull) return Result.ok(false);
|
|
311
|
+
if (actual === null || actual === void 0) {
|
|
312
|
+
const resolved = actual === null ? "null" : "undefined";
|
|
313
|
+
return this.reportLeafError(NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG, `${NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG}: "${node.field}" resolved to ${resolved} for date comparison operator "${node.op}"`, node, actual, { allowNull: allowsNull });
|
|
365
314
|
}
|
|
366
|
-
if (
|
|
367
|
-
return Result.ok(
|
|
315
|
+
if (actualDate === null || actualDate.isErr() || expectedDate === null || expectedDate.isErr()) return this.reportLeafError(INVALID_DATE_OPERAND_TAG, ConditionEvaluatorV1.invalidDateOperandMessage(node), node, actual);
|
|
316
|
+
return Result.ok(evaluateRelationalNumbers(actualDate.getOrNull().getTime(), node.op, expectedDate.getOrNull().getTime()));
|
|
368
317
|
}
|
|
369
318
|
evaluateOperator(actual, op, expected) {
|
|
370
319
|
switch (op) {
|
|
371
320
|
case "eq": return actual === expected;
|
|
372
321
|
case "neq": return actual !== expected;
|
|
373
|
-
case "gt":
|
|
374
|
-
case "gte":
|
|
375
|
-
case "lt":
|
|
376
|
-
case "lte": return typeof actual === "number" && typeof expected === "number" &&
|
|
322
|
+
case "gt":
|
|
323
|
+
case "gte":
|
|
324
|
+
case "lt":
|
|
325
|
+
case "lte": return typeof actual === "number" && typeof expected === "number" && evaluateRelationalNumbers(actual, op, expected);
|
|
377
326
|
case "in": return Array.isArray(expected) && expected.includes(actual);
|
|
378
327
|
case "notIn": return Array.isArray(expected) && !expected.includes(actual);
|
|
379
|
-
case "isNull": return actual === null;
|
|
328
|
+
case "isNull": return actual === null || actual === void 0;
|
|
380
329
|
case "isNotNull": return actual !== null && actual !== void 0;
|
|
381
330
|
}
|
|
382
331
|
}
|
|
383
332
|
evaluateNumericRelationalNode(node, actual) {
|
|
384
333
|
const allowsNull = node.allowNull === true;
|
|
385
334
|
if (actual === void 0 || actual === null && !allowsNull) {
|
|
386
|
-
const
|
|
387
|
-
this.
|
|
388
|
-
level: "error",
|
|
389
|
-
tag: NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG,
|
|
390
|
-
message,
|
|
391
|
-
details: {
|
|
392
|
-
field: node.field,
|
|
393
|
-
op: node.op,
|
|
394
|
-
actual,
|
|
395
|
-
expected: node.value,
|
|
396
|
-
allowNull: allowsNull,
|
|
397
|
-
node
|
|
398
|
-
}
|
|
399
|
-
}));
|
|
400
|
-
return Result.err(message);
|
|
335
|
+
const resolved = actual === null ? "null" : "undefined";
|
|
336
|
+
return this.reportLeafError(NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG, `${NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG}: "${node.field}" resolved to ${resolved} for numeric operator "${node.op}"`, node, actual, { allowNull: allowsNull });
|
|
401
337
|
}
|
|
402
338
|
if (actual === null) return Result.ok(false);
|
|
403
|
-
if (typeof actual !== "number" || typeof node.value !== "number") return this.
|
|
339
|
+
if (typeof actual !== "number" || Number.isNaN(actual) || typeof node.value !== "number" || Number.isNaN(node.value)) return this.reportLeafError(INVALID_NUMERIC_OPERAND_TAG, `${INVALID_NUMERIC_OPERAND_TAG}: "${node.field}" with operator "${node.op}" requires numeric operands`, node, actual);
|
|
404
340
|
return Result.ok(this.evaluateOperator(actual, node.op, node.value));
|
|
405
341
|
}
|
|
406
342
|
evaluateLeafNode(node) {
|
|
407
343
|
const actualResult = PolicyContextPath.getOrAbsent(this.context, node.field);
|
|
408
344
|
if (actualResult.isErr()) {
|
|
345
|
+
const message = `MISSING_CONTEXT_FIELD: "${node.field}" not found in context`;
|
|
409
346
|
this.options.reporter.warn(this.buildReport({
|
|
410
347
|
level: "warn",
|
|
411
348
|
tag: "MISSING_CONTEXT_FIELD",
|
|
412
|
-
message
|
|
349
|
+
message,
|
|
413
350
|
details: {
|
|
414
351
|
field: node.field,
|
|
415
352
|
node
|
|
416
353
|
}
|
|
417
354
|
}));
|
|
418
|
-
return Result.err(
|
|
355
|
+
return Result.err(message);
|
|
419
356
|
}
|
|
420
357
|
try {
|
|
421
358
|
const actual = actualResult.getOrThrow();
|
|
@@ -424,10 +361,10 @@ var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
|
424
361
|
if (dateResult !== null) return dateResult;
|
|
425
362
|
return this.evaluateNumericRelationalNode(node, actual);
|
|
426
363
|
}
|
|
427
|
-
if ((node.op === "in" || node.op === "notIn") && !Array.isArray(node.value)) return this.
|
|
364
|
+
if ((node.op === "in" || node.op === "notIn") && !Array.isArray(node.value)) return this.reportLeafError(INVALID_SET_OPERAND_TAG, `${INVALID_SET_OPERAND_TAG}: "${node.field}" with operator "${node.op}" requires an array operand`, node, actual);
|
|
428
365
|
if (node.op === "eq" || node.op === "neq" || node.op === "in" || node.op === "notIn") {
|
|
429
|
-
if (
|
|
430
|
-
return Result.ok(this.evaluateOperator(
|
|
366
|
+
if (containsInvalidDate(actual) || containsInvalidDate(node.value)) return this.reportLeafError(INVALID_DATE_OPERAND_TAG, ConditionEvaluatorV1.invalidDateOperandMessage(node), node, actual);
|
|
367
|
+
return Result.ok(this.evaluateOperator(normalizeDateOperand(actual), node.op, normalizeDateOperand(node.value)));
|
|
431
368
|
}
|
|
432
369
|
return Result.ok(this.evaluateOperator(actual, node.op, node.value));
|
|
433
370
|
} catch (error) {
|
|
@@ -460,7 +397,7 @@ var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
|
460
397
|
});
|
|
461
398
|
}
|
|
462
399
|
if (ConditionEvaluatorV1.isAndNode(node)) {
|
|
463
|
-
if (node.and.length === 0) return Result.err(
|
|
400
|
+
if (node.and.length === 0) return Result.err(`${EMPTY_AND_CONDITION_TAG}: AND nodes must contain at least one child condition`);
|
|
464
401
|
let lastTracedChild = null;
|
|
465
402
|
for (const [index, child] of node.and.entries()) {
|
|
466
403
|
const childPath = `${path}.and[${index}]`;
|
|
@@ -496,7 +433,7 @@ var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
|
496
433
|
trace: tracedChild.trace
|
|
497
434
|
});
|
|
498
435
|
}
|
|
499
|
-
if (lastTrace === null) return Result.err(
|
|
436
|
+
if (lastTrace === null) return Result.err(`${EMPTY_OR_CONDITION_TAG}: OR nodes must contain at least one child condition`);
|
|
500
437
|
return Result.ok({
|
|
501
438
|
matched: false,
|
|
502
439
|
trace: lastTrace
|
|
@@ -545,6 +482,6 @@ var ConditionEvaluatorV1 = class ConditionEvaluatorV1 {
|
|
|
545
482
|
}
|
|
546
483
|
};
|
|
547
484
|
//#endregion
|
|
548
|
-
export {
|
|
485
|
+
export { CoreConfig as i, PolicyContextPath as n, coreConfig as r, ConditionEvaluatorV1 as t };
|
|
549
486
|
|
|
550
487
|
//# sourceMappingURL=condition-evaluator.js.map
|