@cullet/erp-core 1.0.2 → 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 -67
- 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
|
@@ -9,49 +9,49 @@ import type { AppErrorOptions } from "./types";
|
|
|
9
9
|
type SerializationDirection = "serialize" | "deserialize";
|
|
10
10
|
|
|
11
11
|
type SerializationFailureCategory =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
| "invalid_json"
|
|
13
|
+
| "invalid_shape"
|
|
14
|
+
| "missing_field"
|
|
15
|
+
| "unexpected_field"
|
|
16
|
+
| "invalid_type"
|
|
17
|
+
| "schema_version_missing"
|
|
18
|
+
| "schema_version_unsupported"
|
|
19
|
+
| "mapping_not_implemented"
|
|
20
|
+
| "contract_mismatch"
|
|
21
|
+
| "parse_failed"
|
|
22
|
+
| "stringify_failed"
|
|
23
|
+
| "unknown";
|
|
24
24
|
|
|
25
25
|
type SerializationBoundary =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
| "http_in"
|
|
27
|
+
| "http_out"
|
|
28
|
+
| "graphql_in"
|
|
29
|
+
| "graphql_out"
|
|
30
|
+
| "dto_to_domain"
|
|
31
|
+
| "domain_to_dto"
|
|
32
|
+
| "persistence_to_domain"
|
|
33
|
+
| "domain_to_persistence"
|
|
34
|
+
| "event_in"
|
|
35
|
+
| "event_out"
|
|
36
|
+
| "projection"
|
|
37
|
+
| "unknown";
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Metadata shared by serialization/deserialization failures. Payload previews must be sanitized.
|
|
41
41
|
*/
|
|
42
42
|
type SerializationErrorMetadata = {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
direction: SerializationDirection;
|
|
44
|
+
category: SerializationFailureCategory;
|
|
45
|
+
boundary: SerializationBoundary;
|
|
46
|
+
contract: string;
|
|
47
|
+
schemaVersion?: number | string;
|
|
48
|
+
path?: string;
|
|
49
|
+
payloadPreview?: string;
|
|
50
|
+
correlationId?: string;
|
|
51
|
+
requestId?: string;
|
|
52
|
+
commandId?: string;
|
|
53
|
+
hint?: string;
|
|
54
|
+
details?: string;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -59,43 +59,43 @@ type SerializationErrorMetadata = {
|
|
|
59
59
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
60
60
|
|
|
61
61
|
type SerializationErrorOptions = Omit<AppErrorOptions, "metadata"> & {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
message: string;
|
|
63
|
+
code: string;
|
|
64
|
+
metadata: Omit<SerializationErrorMetadata, "direction" | "category">;
|
|
65
|
+
direction: SerializationDirection;
|
|
66
|
+
category: SerializationFailureCategory;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
abstract class SerializationError extends AppError {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
70
|
+
public readonly direction: SerializationDirection;
|
|
71
|
+
public readonly category: SerializationFailureCategory;
|
|
72
|
+
public readonly boundary: SerializationBoundary;
|
|
73
|
+
public readonly contract: string;
|
|
74
|
+
|
|
75
|
+
protected constructor(input: SerializationErrorOptions) {
|
|
76
|
+
super(input.message ?? "Serialization failure", input.code, {
|
|
77
|
+
cause: input.cause,
|
|
78
|
+
metadata: {
|
|
79
|
+
direction: input.direction,
|
|
80
|
+
category: input.category,
|
|
81
|
+
...input.metadata,
|
|
82
|
+
},
|
|
83
|
+
type: input.type,
|
|
84
|
+
severity: input.severity,
|
|
85
|
+
correlationId: input.correlationId,
|
|
86
|
+
requestId: input.requestId,
|
|
87
|
+
commandId: input.commandId,
|
|
88
|
+
createdAtIso: input.createdAtIso,
|
|
89
|
+
publicMessage: input.publicMessage,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
this.direction = input.direction;
|
|
93
|
+
this.category = input.category;
|
|
94
|
+
this.boundary = input.metadata.boundary;
|
|
95
|
+
this.contract = input.metadata.contract;
|
|
96
|
+
|
|
97
|
+
Object.freeze(this);
|
|
98
|
+
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -103,25 +103,25 @@ abstract class SerializationError extends AppError {
|
|
|
103
103
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
104
104
|
|
|
105
105
|
class SerializationInError extends SerializationError {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
106
|
+
private constructor(input: SerializationErrorOptions) {
|
|
107
|
+
super(input);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static failure(
|
|
111
|
+
category: SerializationFailureCategory,
|
|
112
|
+
metadata: Omit<SerializationErrorMetadata, "direction" | "category"> & {
|
|
113
|
+
cause?: unknown;
|
|
114
|
+
},
|
|
115
|
+
): SerializationInError {
|
|
116
|
+
return new SerializationInError({
|
|
117
|
+
message: SerializationMessages.message("deserialize", category),
|
|
118
|
+
code: SerializationCodes.code("deserialize", category),
|
|
119
|
+
category,
|
|
120
|
+
direction: "deserialize",
|
|
121
|
+
metadata,
|
|
122
|
+
cause: metadata.cause,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -129,25 +129,25 @@ class SerializationInError extends SerializationError {
|
|
|
129
129
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
130
130
|
|
|
131
131
|
class SerializationOutError extends SerializationError {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
132
|
+
private constructor(input: SerializationErrorOptions) {
|
|
133
|
+
super(input);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static failure(
|
|
137
|
+
category: SerializationFailureCategory,
|
|
138
|
+
metadata: Omit<SerializationErrorMetadata, "direction" | "category"> & {
|
|
139
|
+
cause?: unknown;
|
|
140
|
+
},
|
|
141
|
+
): SerializationOutError {
|
|
142
|
+
return new SerializationOutError({
|
|
143
|
+
message: SerializationMessages.message("serialize", category),
|
|
144
|
+
code: SerializationCodes.code("serialize", category),
|
|
145
|
+
category,
|
|
146
|
+
direction: "serialize",
|
|
147
|
+
metadata,
|
|
148
|
+
cause: metadata.cause,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -155,49 +155,49 @@ class SerializationOutError extends SerializationError {
|
|
|
155
155
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
156
156
|
|
|
157
157
|
class SerializationCodes {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
158
|
+
static code(
|
|
159
|
+
direction: SerializationDirection,
|
|
160
|
+
category: SerializationFailureCategory,
|
|
161
|
+
): string {
|
|
162
|
+
return serializationErrorCode(direction, category);
|
|
163
|
+
}
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
class SerializationMessages {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
167
|
+
static message(
|
|
168
|
+
direction: SerializationDirection,
|
|
169
|
+
category: SerializationFailureCategory,
|
|
170
|
+
): string {
|
|
171
|
+
if (direction === "deserialize") {
|
|
172
|
+
if (category === "invalid_json") {
|
|
173
|
+
return "Invalid payload: malformed JSON";
|
|
174
|
+
}
|
|
175
|
+
if (category === "schema_version_missing") {
|
|
176
|
+
return "Invalid payload: schemaVersion is missing";
|
|
177
|
+
}
|
|
178
|
+
if (category === "schema_version_unsupported") {
|
|
179
|
+
return "Invalid payload: schemaVersion is not supported";
|
|
180
|
+
}
|
|
181
|
+
if (category === "invalid_shape") {
|
|
182
|
+
return "Invalid payload: incompatible shape";
|
|
183
|
+
}
|
|
184
|
+
if (category === "mapping_not_implemented") {
|
|
185
|
+
return "Unsupported payload: mapping not implemented";
|
|
186
|
+
}
|
|
187
|
+
if (category === "contract_mismatch") {
|
|
188
|
+
return "Payload does not match the expected contract";
|
|
189
|
+
}
|
|
190
|
+
return "Failed to parse incoming payload";
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (category === "stringify_failed") {
|
|
194
|
+
return "Failed to serialize the response";
|
|
195
|
+
}
|
|
196
|
+
if (category === "contract_mismatch") {
|
|
197
|
+
return "Response does not match the expected contract";
|
|
198
|
+
}
|
|
199
|
+
return "Failed to build the response";
|
|
198
200
|
}
|
|
199
|
-
return "Failed to build the response";
|
|
200
|
-
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -205,29 +205,29 @@ class SerializationMessages {
|
|
|
205
205
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
206
206
|
|
|
207
207
|
function safePreview(value: unknown, limit = 240): string | undefined {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
208
|
+
try {
|
|
209
|
+
const serialized =
|
|
210
|
+
typeof value === "string" ? value : JSON.stringify(value);
|
|
211
|
+
return serialized.length > limit
|
|
212
|
+
? `${serialized.slice(0, limit)}…`
|
|
213
|
+
: serialized;
|
|
214
|
+
} catch {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
export {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
220
|
+
safePreview,
|
|
221
|
+
SerializationCodes,
|
|
222
|
+
SerializationError,
|
|
223
|
+
SerializationInError as DeserializationError,
|
|
224
|
+
SerializationInError,
|
|
225
|
+
SerializationMessages,
|
|
226
|
+
SerializationOutError,
|
|
227
227
|
};
|
|
228
228
|
export type {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
SerializationBoundary,
|
|
230
|
+
SerializationDirection,
|
|
231
|
+
SerializationErrorMetadata,
|
|
232
|
+
SerializationFailureCategory,
|
|
233
233
|
};
|
|
@@ -7,139 +7,141 @@ type TemporalKind = "expired" | "not_yet_valid";
|
|
|
7
7
|
type TemporalPrecision = "EXACT" | "ESTIMATED" | "UNKNOWN" | "APPROXIMATE";
|
|
8
8
|
|
|
9
9
|
type TemporalErrorMetadata = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
resourceType: string;
|
|
11
|
+
resourceId?: string;
|
|
12
|
+
operation?: string;
|
|
13
|
+
validFromIso?: string | null;
|
|
14
|
+
validUntilIso?: string | null;
|
|
15
|
+
evaluatedAtIso: string;
|
|
16
|
+
policyId?: string;
|
|
17
|
+
precision?: TemporalPrecision;
|
|
18
|
+
hint?: string;
|
|
19
|
+
details?: string;
|
|
20
|
+
correlationId?: string;
|
|
21
|
+
requestId?: string;
|
|
22
|
+
commandId?: string;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
type TemporalErrorOptions = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
message: string;
|
|
27
|
+
code: string;
|
|
28
|
+
kind: TemporalKind;
|
|
29
|
+
metadata: TemporalErrorMetadata;
|
|
30
30
|
} & AppErrorOptions;
|
|
31
31
|
|
|
32
32
|
abstract class TemporalError extends AppError {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
33
|
+
public readonly kind: TemporalKind;
|
|
34
|
+
public readonly resourceType: string;
|
|
35
|
+
public readonly evaluatedAtIso: string;
|
|
36
|
+
|
|
37
|
+
protected constructor(input: TemporalErrorOptions) {
|
|
38
|
+
super(input.message, input.code, {
|
|
39
|
+
...input,
|
|
40
|
+
metadata: {
|
|
41
|
+
kind: input.kind,
|
|
42
|
+
...input.metadata,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.kind = input.kind;
|
|
47
|
+
this.resourceType = input.metadata.resourceType;
|
|
48
|
+
this.evaluatedAtIso = input.metadata.evaluatedAtIso;
|
|
49
|
+
Object.freeze(this);
|
|
50
|
+
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
type TemporalCreationInput = TemporalErrorMetadata &
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
Partial<Omit<AppErrorOptions, "metadata">> & {
|
|
55
|
+
cause?: unknown;
|
|
56
|
+
};
|
|
57
57
|
|
|
58
58
|
class ExpiredError extends TemporalError {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
59
|
+
private constructor(input: TemporalErrorOptions) {
|
|
60
|
+
super(input);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static detected(input: TemporalCreationInput): ExpiredError {
|
|
64
|
+
return new ExpiredError({
|
|
65
|
+
message: "The validity of the resource/action has expired",
|
|
66
|
+
code: ErrorCodes.temporal.expired,
|
|
67
|
+
kind: "expired",
|
|
68
|
+
metadata: {
|
|
69
|
+
...input,
|
|
70
|
+
hint:
|
|
71
|
+
input.hint ??
|
|
72
|
+
"The window has expired. Request a new link or try again within the valid period.",
|
|
73
|
+
},
|
|
74
|
+
cause: input.cause,
|
|
75
|
+
type: input.type,
|
|
76
|
+
severity: input.severity,
|
|
77
|
+
correlationId: input.correlationId,
|
|
78
|
+
requestId: input.requestId,
|
|
79
|
+
commandId: input.commandId,
|
|
80
|
+
createdAtIso: input.createdAtIso,
|
|
81
|
+
publicMessage: input.publicMessage,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
class NotYetValidError extends TemporalError {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
87
|
+
private constructor(input: TemporalErrorOptions) {
|
|
88
|
+
super(input);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static detected(input: TemporalCreationInput): NotYetValidError {
|
|
92
|
+
return new NotYetValidError({
|
|
93
|
+
message: "The resource/action is not yet valid",
|
|
94
|
+
code: ErrorCodes.temporal.notYetValid,
|
|
95
|
+
kind: "not_yet_valid",
|
|
96
|
+
metadata: {
|
|
97
|
+
...input,
|
|
98
|
+
hint:
|
|
99
|
+
input.hint ??
|
|
100
|
+
"Not yet within the valid period. Try again later.",
|
|
101
|
+
},
|
|
102
|
+
cause: input.cause,
|
|
103
|
+
type: input.type,
|
|
104
|
+
severity: input.severity,
|
|
105
|
+
correlationId: input.correlationId,
|
|
106
|
+
requestId: input.requestId,
|
|
107
|
+
commandId: input.commandId,
|
|
108
|
+
createdAtIso: input.createdAtIso,
|
|
109
|
+
publicMessage: input.publicMessage,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
function evaluateTemporalWindow(input: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
validFromIso?: string | null;
|
|
116
|
+
validUntilIso?: string | null;
|
|
117
|
+
evaluatedAtIso: string;
|
|
116
118
|
}): { expired: boolean; notYetValid: boolean } | null {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
const evaluatedMs = Date.parse(input.evaluatedAtIso);
|
|
120
|
+
if (Number.isNaN(evaluatedMs)) return null;
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
let notYetValid = false;
|
|
121
123
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
if (input.validFromIso) {
|
|
125
|
+
const fromMs = Date.parse(input.validFromIso);
|
|
126
|
+
if (!Number.isNaN(fromMs) && evaluatedMs < fromMs) {
|
|
127
|
+
notYetValid = true;
|
|
128
|
+
}
|
|
126
129
|
}
|
|
127
|
-
}
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
if (input.validUntilIso) {
|
|
132
|
+
const untilMs = Date.parse(input.validUntilIso);
|
|
133
|
+
if (!Number.isNaN(untilMs) && evaluatedMs > untilMs) {
|
|
134
|
+
return { expired: true, notYetValid: false };
|
|
135
|
+
}
|
|
133
136
|
}
|
|
134
|
-
}
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
return { expired: false, notYetValid };
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
export {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
evaluateTemporalWindow,
|
|
143
|
+
ExpiredError,
|
|
144
|
+
NotYetValidError,
|
|
145
|
+
TemporalError,
|
|
144
146
|
};
|
|
145
147
|
export type { TemporalErrorMetadata, TemporalKind, TemporalPrecision };
|