@cullet/erp-core 1.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.
Files changed (182) hide show
  1. package/KIT_CONTEXT.md +39 -0
  2. package/README.md +110 -0
  3. package/dist/errors/index.d.ts +2 -0
  4. package/dist/errors/index.js +3 -0
  5. package/dist/exceptions/validation-field.d.ts +2 -0
  6. package/dist/exceptions/validation-field.js +2 -0
  7. package/dist/gate-engine-registry.js +260 -0
  8. package/dist/gate-engine-registry.js.map +1 -0
  9. package/dist/gate-types.d.ts +307 -0
  10. package/dist/gate-v1-payload.schema.js +677 -0
  11. package/dist/gate-v1-payload.schema.js.map +1 -0
  12. package/dist/index.d.ts +88 -0
  13. package/dist/index.js +153 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/outcome.js +92 -0
  16. package/dist/outcome.js.map +1 -0
  17. package/dist/parse-gate-payload.d.ts +136 -0
  18. package/dist/policies/engines/index.d.ts +3 -0
  19. package/dist/policies/engines/index.js +2 -0
  20. package/dist/policies/engines/v1/gate/index.d.ts +115 -0
  21. package/dist/policies/engines/v1/gate/index.js +84 -0
  22. package/dist/policies/engines/v1/gate/index.js.map +1 -0
  23. package/dist/policies/index.d.ts +4 -0
  24. package/dist/policies/index.js +5 -0
  25. package/dist/policy-service.d.ts +541 -0
  26. package/dist/policy-service.js +992 -0
  27. package/dist/policy-service.js.map +1 -0
  28. package/dist/validation-code.js +210 -0
  29. package/dist/validation-code.js.map +1 -0
  30. package/dist/validation-error.d.ts +686 -0
  31. package/dist/validation-error.js +757 -0
  32. package/dist/validation-error.js.map +1 -0
  33. package/dist/validation-field.d.ts +12 -0
  34. package/dist/validation-field.js +23 -0
  35. package/dist/validation-field.js.map +1 -0
  36. package/meta.json +66 -0
  37. package/package.json +59 -0
  38. package/src/core/application/commands/command.ts +28 -0
  39. package/src/core/application/commands/index.ts +2 -0
  40. package/src/core/application/commands/requested-by.ts +97 -0
  41. package/src/core/application/index.ts +31 -0
  42. package/src/core/application/policy-error-mapper.ts +60 -0
  43. package/src/core/application/ports/index.ts +14 -0
  44. package/src/core/application/ports/logger.port.ts +10 -0
  45. package/src/core/application/ports/metrics.port.ts +9 -0
  46. package/src/core/application/ports/policy-port.ts +20 -0
  47. package/src/core/application/ports/repository.port.ts +7 -0
  48. package/src/core/application/ports/temporal-repository.port.ts +14 -0
  49. package/src/core/application/ports/tracer.port.ts +16 -0
  50. package/src/core/application/queries/index.ts +2 -0
  51. package/src/core/application/queries/query.ts +53 -0
  52. package/src/core/application/temporal/index.ts +11 -0
  53. package/src/core/application/temporal/temporal-context.ts +41 -0
  54. package/src/core/application/temporal/temporal-use-case.ts +41 -0
  55. package/src/core/application/use-case.ts +24 -0
  56. package/src/core/config/core-config.instance.ts +14 -0
  57. package/src/core/config/core-config.ts +87 -0
  58. package/src/core/config/index.ts +12 -0
  59. package/src/core/config/policy-reporter.ts +60 -0
  60. package/src/core/config/silent-policy-reporter.ts +5 -0
  61. package/src/core/domain/entity.ts +69 -0
  62. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +16 -0
  63. package/src/core/domain/rulesets/ruleset-registry.ts +71 -0
  64. package/src/core/domain/rulesets/ruleset.contracts.ts +15 -0
  65. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +13 -0
  66. package/src/core/domain/temporal/index.ts +18 -0
  67. package/src/core/domain/temporal/temporal-range.ts +53 -0
  68. package/src/core/domain/temporal/temporal-snapshot.ts +47 -0
  69. package/src/core/domain/temporal/transaction-time.ts +60 -0
  70. package/src/core/domain/temporal/valid-time.ts +57 -0
  71. package/src/core/domain/value-object.ts +30 -0
  72. package/src/core/errors/app-error.ts +85 -0
  73. package/src/core/errors/authentication-error.ts +171 -0
  74. package/src/core/errors/authorization-error.ts +204 -0
  75. package/src/core/errors/business-rule-violation-error.ts +28 -0
  76. package/src/core/errors/conflict-error.ts +246 -0
  77. package/src/core/errors/error-codes.ts +60 -0
  78. package/src/core/errors/idempotency-error.ts +372 -0
  79. package/src/core/errors/index.ts +99 -0
  80. package/src/core/errors/integration-error.ts +157 -0
  81. package/src/core/errors/legacy-incompatible-error.ts +26 -0
  82. package/src/core/errors/not-found-error.ts +27 -0
  83. package/src/core/errors/serialization-error.ts +233 -0
  84. package/src/core/errors/temporal-error.ts +145 -0
  85. package/src/core/errors/types.ts +74 -0
  86. package/src/core/errors/unexpected-error.ts +22 -0
  87. package/src/core/errors/utils/index.ts +4 -0
  88. package/src/core/errors/utils/json-safe.ts +93 -0
  89. package/src/core/errors/validation-error.ts +34 -0
  90. package/src/core/exceptions/business-rule-violation-exception.ts +12 -0
  91. package/src/core/exceptions/domain-exception.ts +9 -0
  92. package/src/core/exceptions/entity-not-found-exception.ts +12 -0
  93. package/src/core/exceptions/invalid-state-transition-exception.ts +15 -0
  94. package/src/core/exceptions/invariant-violation-exception.ts +9 -0
  95. package/src/core/exceptions/validation-code.ts +39 -0
  96. package/src/core/exceptions/validation-exception.ts +39 -0
  97. package/src/core/exceptions/validation-field.ts +32 -0
  98. package/src/core/index.ts +15 -0
  99. package/src/core/policies/asof/asof.ts +68 -0
  100. package/src/core/policies/asof/index.ts +2 -0
  101. package/src/core/policies/catalog/catalog-types.ts +12 -0
  102. package/src/core/policies/catalog/catalog.instance.ts +21 -0
  103. package/src/core/policies/catalog/index.ts +11 -0
  104. package/src/core/policies/catalog/policy-catalog-entry.ts +220 -0
  105. package/src/core/policies/catalog/policy-catalog.ts +124 -0
  106. package/src/core/policies/catalog/policy-key.ts +78 -0
  107. package/src/core/policies/context/context-builder.ts +391 -0
  108. package/src/core/policies/context/context-registry.instance.ts +26 -0
  109. package/src/core/policies/context/context-registry.ts +95 -0
  110. package/src/core/policies/context/context-resolver.ts +31 -0
  111. package/src/core/policies/context/context-seed.ts +32 -0
  112. package/src/core/policies/context/index.ts +21 -0
  113. package/src/core/policies/context/path.ts +152 -0
  114. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +73 -0
  115. package/src/core/policies/defs/index.ts +20 -0
  116. package/src/core/policies/defs/policy-definition-repository.ts +8 -0
  117. package/src/core/policies/defs/policy-definition.ts +192 -0
  118. package/src/core/policies/defs/policy-payload.contracts.ts +13 -0
  119. package/src/core/policies/defs/policy-scope.ts +53 -0
  120. package/src/core/policies/defs/policy-semver.ts +83 -0
  121. package/src/core/policies/engines/compute-engine-registry.ts +57 -0
  122. package/src/core/policies/engines/compute-evaluator-registry.ts +28 -0
  123. package/src/core/policies/engines/compute-payload.ts +5 -0
  124. package/src/core/policies/engines/compute-registry.ts +67 -0
  125. package/src/core/policies/engines/compute-types.ts +51 -0
  126. package/src/core/policies/engines/condition-evaluator-reporter.ts +34 -0
  127. package/src/core/policies/engines/gate-engine-registry.ts +38 -0
  128. package/src/core/policies/engines/gate-payload.ts +5 -0
  129. package/src/core/policies/engines/gate-types.ts +63 -0
  130. package/src/core/policies/engines/index.ts +48 -0
  131. package/src/core/policies/engines/parse-compute-payload.ts +71 -0
  132. package/src/core/policies/engines/parse-gate-payload.ts +68 -0
  133. package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +55 -0
  134. package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +75 -0
  135. package/src/core/policies/engines/v1/compute/index.ts +12 -0
  136. package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +54 -0
  137. package/src/core/policies/engines/v1/condition-evaluator.ts +592 -0
  138. package/src/core/policies/engines/v1/condition-schema.ts +50 -0
  139. package/src/core/policies/engines/v1/condition-types.ts +41 -0
  140. package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +157 -0
  141. package/src/core/policies/engines/v1/gate/gate-types-v1.ts +12 -0
  142. package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +46 -0
  143. package/src/core/policies/engines/v1/gate/index.ts +9 -0
  144. package/src/core/policies/engines/v1/index.ts +13 -0
  145. package/src/core/policies/index.ts +132 -0
  146. package/src/core/policies/package/policy-package.ts +17 -0
  147. package/src/core/policies/policy-ids.ts +60 -0
  148. package/src/core/policies/resolver/index.ts +1 -0
  149. package/src/core/policies/resolver/policy-resolver.ts +57 -0
  150. package/src/core/policies/service/index.ts +10 -0
  151. package/src/core/policies/service/policy-evaluation-error.ts +148 -0
  152. package/src/core/policies/service/policy-service.ts +493 -0
  153. package/src/core/policies/utils/date.ts +7 -0
  154. package/src/core/policies/utils/hash.ts +90 -0
  155. package/src/core/policies/utils/index.ts +3 -0
  156. package/src/core/policies/utils/result.ts +4 -0
  157. package/src/core/result/outcome.ts +158 -0
  158. package/src/core/result/result.ts +153 -0
  159. package/src/core/shared/aggregate-version.ts +11 -0
  160. package/src/core/shared/hashing.ts +38 -0
  161. package/src/core/shared/immutable.ts +46 -0
  162. package/src/core/shared/temporal-guards.ts +22 -0
  163. package/src/core/versioning/domain-event-contracts.ts +73 -0
  164. package/src/core/versioning/version.ts +34 -0
  165. package/src/errors/index.ts +1 -0
  166. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +31 -0
  167. package/src/examples/rulesets/entity/order-invariants-v1.ts +48 -0
  168. package/src/examples/rulesets/entity/order-invariants-v2.ts +28 -0
  169. package/src/examples/rulesets/entity/order.ts +162 -0
  170. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +52 -0
  171. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +27 -0
  172. package/src/examples/rulesets/value-object/cpf.ts +37 -0
  173. package/src/examples/rulesets/value-object/customer.ts +67 -0
  174. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +37 -0
  175. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +27 -0
  176. package/src/examples/rulesets/value-object/person-name.ts +39 -0
  177. package/src/exceptions/validation-field.ts +1 -0
  178. package/src/index.ts +11 -0
  179. package/src/policies/engines/index.ts +1 -0
  180. package/src/policies/engines/v1/gate/index.ts +1 -0
  181. package/src/policies/index.ts +1 -0
  182. package/src/version.ts +7 -0
@@ -0,0 +1,757 @@
1
+ import { c as ErrorCodes, l as serializationErrorCode, o as AppError } from "./validation-code.js";
2
+ //#region src/core/errors/authentication-error.ts
3
+ var AuthenticationError = class AuthenticationError extends AppError {
4
+ constructor(params) {
5
+ super(params.message, params.code, {
6
+ cause: params.cause,
7
+ metadata: {
8
+ reason: params.reason,
9
+ ...params.metadata ?? {}
10
+ },
11
+ type: params.type,
12
+ severity: params.severity,
13
+ correlationId: params.correlationId,
14
+ requestId: params.requestId,
15
+ commandId: params.commandId,
16
+ createdAtIso: params.createdAtIso,
17
+ publicMessage: params.publicMessage
18
+ });
19
+ this.reason = params.reason;
20
+ Object.freeze(this);
21
+ }
22
+ static missingToken(options) {
23
+ return new AuthenticationError({
24
+ message: "Missing credentials",
25
+ code: ErrorCodes.authentication.missingToken,
26
+ reason: "missing_token",
27
+ metadata: compactMetadata$1(options),
28
+ ...extractAppErrorOptions$1(options)
29
+ });
30
+ }
31
+ static invalidToken(options) {
32
+ return new AuthenticationError({
33
+ message: "Invalid credentials",
34
+ code: ErrorCodes.authentication.invalidToken,
35
+ reason: "invalid_token",
36
+ metadata: compactMetadata$1({
37
+ authScheme: options?.authScheme,
38
+ tokenLocation: options?.tokenLocation,
39
+ details: options?.details,
40
+ correlationId: options?.correlationId,
41
+ requestId: options?.requestId
42
+ }),
43
+ ...extractAppErrorOptions$1(options)
44
+ });
45
+ }
46
+ static expiredToken(options) {
47
+ return new AuthenticationError({
48
+ message: "Expired credentials",
49
+ code: ErrorCodes.authentication.expiredToken,
50
+ reason: "expired_token",
51
+ metadata: compactMetadata$1(options),
52
+ ...extractAppErrorOptions$1(options)
53
+ });
54
+ }
55
+ static invalidCredentials(options) {
56
+ return new AuthenticationError({
57
+ message: "Invalid username or password",
58
+ code: ErrorCodes.authentication.invalidCredentials,
59
+ reason: "invalid_credentials",
60
+ metadata: compactMetadata$1(options),
61
+ ...extractAppErrorOptions$1(options)
62
+ });
63
+ }
64
+ };
65
+ function extractAppErrorOptions$1(options) {
66
+ return {
67
+ cause: options?.cause,
68
+ type: options?.type,
69
+ severity: options?.severity,
70
+ correlationId: options?.correlationId,
71
+ requestId: options?.requestId,
72
+ commandId: options?.commandId,
73
+ createdAtIso: options?.createdAtIso,
74
+ publicMessage: options?.publicMessage
75
+ };
76
+ }
77
+ function compactMetadata$1(input) {
78
+ if (!input) return void 0;
79
+ return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
80
+ }
81
+ //#endregion
82
+ //#region src/core/errors/authorization-error.ts
83
+ var AuthorizationError = class AuthorizationError extends AppError {
84
+ constructor(params) {
85
+ super(params.message, params.code, {
86
+ cause: params.cause,
87
+ metadata: params.metadata,
88
+ type: params.type,
89
+ severity: params.severity,
90
+ correlationId: params.correlationId,
91
+ requestId: params.requestId,
92
+ commandId: params.commandId,
93
+ createdAtIso: params.createdAtIso,
94
+ publicMessage: params.publicMessage
95
+ });
96
+ this.reason = params.reason;
97
+ Object.freeze(this);
98
+ }
99
+ static forbidden(input) {
100
+ return new AuthorizationError({
101
+ message: "Action not allowed",
102
+ code: ErrorCodes.authorization.forbidden,
103
+ reason: "forbidden",
104
+ metadata: {
105
+ reason: "forbidden",
106
+ ...extractMetadataOnly(input)
107
+ },
108
+ ...extractAppErrorOptions(input)
109
+ });
110
+ }
111
+ static policyDenied(input) {
112
+ return new AuthorizationError({
113
+ message: "Action denied by policy",
114
+ code: ErrorCodes.authorization.policyDenied,
115
+ reason: "policy_denied",
116
+ metadata: {
117
+ reason: "policy_denied",
118
+ ...extractMetadataOnly(input),
119
+ decision: "deny"
120
+ },
121
+ ...extractAppErrorOptions(input)
122
+ });
123
+ }
124
+ static missingCapability(input) {
125
+ return new AuthorizationError({
126
+ message: "Insufficient capability to perform the action",
127
+ code: ErrorCodes.authorization.missingCapability,
128
+ reason: "missing_capability",
129
+ metadata: {
130
+ reason: "missing_capability",
131
+ ...extractMetadataOnly(input)
132
+ },
133
+ ...extractAppErrorOptions(input)
134
+ });
135
+ }
136
+ static outOfScope(input) {
137
+ return new AuthorizationError({
138
+ message: "Action outside the allowed scope",
139
+ code: ErrorCodes.authorization.outOfScope,
140
+ reason: "out_of_scope",
141
+ metadata: {
142
+ reason: "out_of_scope",
143
+ ...extractMetadataOnly(input)
144
+ },
145
+ ...extractAppErrorOptions(input)
146
+ });
147
+ }
148
+ };
149
+ function extractAppErrorOptions(options) {
150
+ return {
151
+ cause: options?.cause,
152
+ type: options?.type,
153
+ severity: options?.severity,
154
+ correlationId: options?.correlationId,
155
+ requestId: options?.requestId,
156
+ commandId: options?.commandId,
157
+ createdAtIso: options?.createdAtIso,
158
+ publicMessage: options?.publicMessage
159
+ };
160
+ }
161
+ function extractMetadataOnly(input) {
162
+ const { cause, type, severity, correlationId, requestId, commandId, createdAtIso, publicMessage, ...metadata } = input;
163
+ return metadata;
164
+ }
165
+ //#endregion
166
+ //#region src/core/errors/business-rule-violation-error.ts
167
+ var BusinessRuleViolationError = class extends AppError {
168
+ constructor(rule, message, detail, options) {
169
+ const baseMetadata = detail ? {
170
+ rule,
171
+ detail
172
+ } : { rule };
173
+ const mergedMetadata = options?.metadata ? {
174
+ ...baseMetadata,
175
+ ...options.metadata
176
+ } : baseMetadata;
177
+ super(message, ErrorCodes.businessRuleViolation, {
178
+ ...options,
179
+ metadata: mergedMetadata
180
+ });
181
+ }
182
+ };
183
+ //#endregion
184
+ //#region src/core/errors/conflict-error.ts
185
+ var ConflictError = class extends AppError {
186
+ constructor(params) {
187
+ super(params.message, params.code, {
188
+ ...params,
189
+ metadata: {
190
+ kind: params.kind,
191
+ ...params.metadata
192
+ }
193
+ });
194
+ this.kind = params.kind;
195
+ Object.freeze(this);
196
+ }
197
+ };
198
+ var AlreadyExistsError = class AlreadyExistsError extends ConflictError {
199
+ constructor(input) {
200
+ super({
201
+ message: "A matching record already exists for the requested operation",
202
+ code: ErrorCodes.conflict.alreadyExists,
203
+ kind: "already_exists",
204
+ ...input
205
+ });
206
+ }
207
+ static detected(input) {
208
+ return new AlreadyExistsError({
209
+ metadata: {
210
+ entity: input.entity,
211
+ operation: input.operation ?? "create",
212
+ field: input.field,
213
+ existingId: input.existingId,
214
+ valueHash: input.valueHash,
215
+ valuePreview: input.valuePreview,
216
+ detectedAtIso: input.detectedAtIso,
217
+ correlationId: input.correlationId,
218
+ requestId: input.requestId,
219
+ commandId: input.commandId,
220
+ hint: input.hint ?? "Verify existing records before retrying."
221
+ },
222
+ cause: input.cause
223
+ });
224
+ }
225
+ };
226
+ var DuplicateError = class DuplicateError extends ConflictError {
227
+ constructor(input) {
228
+ super({
229
+ message: "Conflict: an existing record violates uniqueness",
230
+ code: ErrorCodes.conflict.duplicate,
231
+ kind: "duplicate",
232
+ ...input
233
+ });
234
+ }
235
+ static detected(input) {
236
+ return new DuplicateError({
237
+ metadata: {
238
+ entity: input.entity,
239
+ operation: input.operation,
240
+ field: input.field,
241
+ constraintName: input.constraintName,
242
+ existingId: input.existingId,
243
+ valueHash: input.valueHash,
244
+ valuePreview: input.valuePreview,
245
+ detectedAtIso: input.detectedAtIso,
246
+ correlationId: input.correlationId,
247
+ requestId: input.requestId,
248
+ commandId: input.commandId,
249
+ hint: input.hint ?? "Adjust the data so it does not duplicate existing records."
250
+ },
251
+ cause: input.cause
252
+ });
253
+ }
254
+ };
255
+ var UniqueConstraintViolationError = class UniqueConstraintViolationError extends ConflictError {
256
+ constructor(input) {
257
+ super({
258
+ message: "Uniqueness violation in storage",
259
+ code: ErrorCodes.conflict.uniqueViolation,
260
+ kind: "unique_violation",
261
+ ...input
262
+ });
263
+ }
264
+ static detected(input) {
265
+ return new UniqueConstraintViolationError({
266
+ metadata: {
267
+ entity: input.entity,
268
+ operation: input.operation,
269
+ constraintName: input.constraintName,
270
+ detectedAtIso: input.detectedAtIso,
271
+ correlationId: input.correlationId,
272
+ requestId: input.requestId,
273
+ commandId: input.commandId,
274
+ violation: {
275
+ kind: "unique_violation",
276
+ constraintName: input.constraintName,
277
+ table: input.table,
278
+ columns: input.columns
279
+ },
280
+ hint: "Uniqueness conflict detected in the database."
281
+ },
282
+ cause: input.cause
283
+ });
284
+ }
285
+ };
286
+ function translateUniqueViolationToDuplicate(input) {
287
+ return DuplicateError.detected({
288
+ entity: input.entity,
289
+ operation: input.operation,
290
+ field: input.field,
291
+ constraintName: input.violation.constraintName,
292
+ detectedAtIso: input.ctx?.nowIso,
293
+ correlationId: input.ctx?.correlationId,
294
+ requestId: input.ctx?.requestId,
295
+ commandId: input.ctx?.commandId,
296
+ cause: input.cause
297
+ });
298
+ }
299
+ //#endregion
300
+ //#region src/core/errors/idempotency-error.ts
301
+ var IdempotencyError = class extends AppError {
302
+ constructor(input) {
303
+ super(input.message, input.code, {
304
+ cause: input.cause,
305
+ metadata: {
306
+ kind: input.kind,
307
+ ...input.metadata
308
+ }
309
+ });
310
+ this.kind = input.kind;
311
+ Object.freeze(this);
312
+ }
313
+ static keyMissing(input) {
314
+ return IdempotencyKeyMissingError.detected(input);
315
+ }
316
+ static inProgress(input) {
317
+ return IdempotencyInProgressError.detected(input);
318
+ }
319
+ static payloadMismatch(input) {
320
+ return IdempotencyPayloadMismatchError.detected(input);
321
+ }
322
+ static replayNotSupported(input) {
323
+ return IdempotencyReplayNotSupportedError.detected(input);
324
+ }
325
+ };
326
+ var IdempotencyKeyMissingError = class IdempotencyKeyMissingError extends IdempotencyError {
327
+ constructor(input) {
328
+ super({
329
+ message: "Idempotency key/commandId missing for the requested operation",
330
+ code: ErrorCodes.idempotency.keyMissing,
331
+ kind: "key_missing",
332
+ metadata: input.metadata,
333
+ cause: input.cause
334
+ });
335
+ }
336
+ static detected(input) {
337
+ return new IdempotencyKeyMissingError({
338
+ cause: input.cause,
339
+ metadata: {
340
+ operation: input.operation,
341
+ scope: input.scope,
342
+ entity: input.entity,
343
+ correlationId: input.correlationId,
344
+ requestId: input.requestId,
345
+ commandId: input.commandId,
346
+ detectedAtIso: input.detectedAtIso,
347
+ hint: input.hint ?? "Send a commandId/idempotency key to prevent duplicate processing.",
348
+ details: input.details
349
+ }
350
+ });
351
+ }
352
+ };
353
+ var IdempotencyInProgressError = class IdempotencyInProgressError extends IdempotencyError {
354
+ constructor(input) {
355
+ super({
356
+ message: "The same business intent is already being processed",
357
+ code: ErrorCodes.idempotency.inProgress,
358
+ kind: "in_progress",
359
+ metadata: input.metadata,
360
+ cause: input.cause
361
+ });
362
+ }
363
+ static detected(input) {
364
+ const resolved = resolveKeyIdentity(input.key, input.keyHash, input.keyPreview);
365
+ return new IdempotencyInProgressError({
366
+ cause: input.cause,
367
+ metadata: {
368
+ operation: input.operation,
369
+ scope: input.scope,
370
+ entity: input.entity,
371
+ keyHash: resolved.keyHash,
372
+ keyPreview: resolved.keyPreview,
373
+ idempotencyRecordId: input.idempotencyRecordId,
374
+ correlationId: input.correlationId,
375
+ requestId: input.requestId,
376
+ commandId: input.commandId,
377
+ detectedAtIso: input.detectedAtIso,
378
+ hint: input.hint ?? "Wait for completion and retry using the same key.",
379
+ details: input.details
380
+ }
381
+ });
382
+ }
383
+ };
384
+ var IdempotencyPayloadMismatchError = class IdempotencyPayloadMismatchError extends IdempotencyError {
385
+ constructor(input) {
386
+ super({
387
+ message: "The idempotency key was reused with a different payload",
388
+ code: ErrorCodes.idempotency.payloadMismatch,
389
+ kind: "payload_mismatch",
390
+ metadata: input.metadata,
391
+ cause: input.cause
392
+ });
393
+ }
394
+ static detected(input) {
395
+ const resolved = resolveKeyIdentity(input.key, input.keyHash, input.keyPreview);
396
+ return new IdempotencyPayloadMismatchError({
397
+ cause: input.cause,
398
+ metadata: {
399
+ operation: input.operation,
400
+ scope: input.scope,
401
+ entity: input.entity,
402
+ keyHash: resolved.keyHash,
403
+ keyPreview: resolved.keyPreview,
404
+ incomingPayloadHash: input.incomingPayloadHash,
405
+ existingPayloadHash: input.existingPayloadHash,
406
+ idempotencyRecordId: input.idempotencyRecordId,
407
+ correlationId: input.correlationId,
408
+ requestId: input.requestId,
409
+ commandId: input.commandId,
410
+ detectedAtIso: input.detectedAtIso,
411
+ hint: input.hint ?? "Use a new idempotency key for a new intent. The same key should only be reused for retries of the same payload.",
412
+ details: input.details
413
+ }
414
+ });
415
+ }
416
+ };
417
+ var IdempotencyReplayNotSupportedError = class IdempotencyReplayNotSupportedError extends IdempotencyError {
418
+ constructor(input) {
419
+ super({
420
+ message: "Re-execution detected, but replay of the previous result is not implemented",
421
+ code: ErrorCodes.idempotency.replayNotSupported,
422
+ kind: "replay_not_supported",
423
+ metadata: input.metadata,
424
+ cause: input.cause
425
+ });
426
+ }
427
+ static detected(input) {
428
+ const resolved = resolveKeyIdentity(input.key, input.keyHash, input.keyPreview);
429
+ return new IdempotencyReplayNotSupportedError({
430
+ cause: input.cause,
431
+ metadata: {
432
+ operation: input.operation,
433
+ scope: input.scope,
434
+ entity: input.entity,
435
+ keyHash: resolved.keyHash,
436
+ keyPreview: resolved.keyPreview,
437
+ idempotencyRecordId: input.idempotencyRecordId,
438
+ correlationId: input.correlationId,
439
+ requestId: input.requestId,
440
+ commandId: input.commandId,
441
+ detectedAtIso: input.detectedAtIso,
442
+ hint: input.hint ?? "Try again later, or enable result replay for full idempotency.",
443
+ details: input.details
444
+ }
445
+ });
446
+ }
447
+ };
448
+ function resolveKeyIdentity(key, keyHash, keyPreview) {
449
+ return {
450
+ keyHash,
451
+ keyPreview: keyPreview ?? (key ? key.length <= 8 ? key : key.slice(0, 8) : void 0)
452
+ };
453
+ }
454
+ //#endregion
455
+ //#region src/core/errors/integration-error.ts
456
+ var IntegrationError = class IntegrationError extends AppError {
457
+ constructor(params) {
458
+ const { message, code, metadata, ...rest } = params;
459
+ super(message, code, {
460
+ ...rest,
461
+ metadata
462
+ });
463
+ this.reason = params.reason;
464
+ Object.freeze(this);
465
+ }
466
+ static timeout(options) {
467
+ return new IntegrationError({
468
+ message: "Timeout while integrating with external provider",
469
+ code: ErrorCodes.integration.timeout,
470
+ reason: "timeout",
471
+ metadata: buildMetadata({
472
+ reason: "timeout",
473
+ ...options
474
+ }),
475
+ ...pickAppErrorFields(options)
476
+ });
477
+ }
478
+ static unreachable(options) {
479
+ return new IntegrationError({
480
+ message: "Provider unavailable",
481
+ code: ErrorCodes.integration.unreachable,
482
+ reason: "unreachable",
483
+ metadata: buildMetadata({
484
+ reason: "unreachable",
485
+ ...options
486
+ }),
487
+ ...pickAppErrorFields(options)
488
+ });
489
+ }
490
+ static badResponse(options) {
491
+ return new IntegrationError({
492
+ message: "Unexpected response from provider",
493
+ code: ErrorCodes.integration.badResponse,
494
+ reason: "bad_response",
495
+ metadata: buildMetadata({
496
+ reason: "bad_response",
497
+ ...options
498
+ }),
499
+ ...pickAppErrorFields(options)
500
+ });
501
+ }
502
+ };
503
+ function buildMetadata(input) {
504
+ return compactMetadata({
505
+ reason: input.reason,
506
+ provider: input.provider,
507
+ operation: input.operation,
508
+ startedAtIso: input.startedAtIso,
509
+ durationMs: input.durationMs,
510
+ detectedAtIso: input.detectedAtIso,
511
+ correlationId: input.correlationId,
512
+ requestId: input.requestId,
513
+ commandId: input.commandId,
514
+ details: input.details,
515
+ statusCode: input.statusCode,
516
+ responseCode: input.responseCode
517
+ });
518
+ }
519
+ function pickAppErrorFields(options) {
520
+ return {
521
+ cause: options.cause,
522
+ type: options.type,
523
+ severity: options.severity,
524
+ correlationId: options.correlationId,
525
+ requestId: options.requestId,
526
+ commandId: options.commandId,
527
+ createdAtIso: options.createdAtIso,
528
+ publicMessage: options.publicMessage
529
+ };
530
+ }
531
+ function compactMetadata(input) {
532
+ return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
533
+ }
534
+ //#endregion
535
+ //#region src/core/errors/legacy-incompatible-error.ts
536
+ var LegacyIncompatibleError = class extends AppError {
537
+ constructor(message, context, options) {
538
+ const mergedMetadata = options?.metadata ? {
539
+ ...context ?? {},
540
+ ...options.metadata
541
+ } : context;
542
+ super(message, ErrorCodes.legacyIncompatible, {
543
+ ...options,
544
+ metadata: mergedMetadata
545
+ });
546
+ }
547
+ };
548
+ //#endregion
549
+ //#region src/core/errors/not-found-error.ts
550
+ var NotFoundError = class extends AppError {
551
+ constructor(resource, criteria, options) {
552
+ const baseMetadata = criteria ? {
553
+ resource,
554
+ criteria
555
+ } : { resource };
556
+ const mergedMetadata = options?.metadata ? {
557
+ ...baseMetadata,
558
+ ...options.metadata
559
+ } : baseMetadata;
560
+ super(`${resource} not found`, ErrorCodes.notFound, {
561
+ ...options,
562
+ metadata: mergedMetadata
563
+ });
564
+ }
565
+ };
566
+ //#endregion
567
+ //#region src/core/errors/serialization-error.ts
568
+ var SerializationError = class extends AppError {
569
+ constructor(input) {
570
+ super(input.message ?? "Serialization failure", input.code, {
571
+ cause: input.cause,
572
+ metadata: {
573
+ direction: input.direction,
574
+ category: input.category,
575
+ ...input.metadata
576
+ },
577
+ type: input.type,
578
+ severity: input.severity,
579
+ correlationId: input.correlationId,
580
+ requestId: input.requestId,
581
+ commandId: input.commandId,
582
+ createdAtIso: input.createdAtIso,
583
+ publicMessage: input.publicMessage
584
+ });
585
+ this.direction = input.direction;
586
+ this.category = input.category;
587
+ this.boundary = input.metadata.boundary;
588
+ this.contract = input.metadata.contract;
589
+ Object.freeze(this);
590
+ }
591
+ };
592
+ var SerializationInError = class SerializationInError extends SerializationError {
593
+ constructor(input) {
594
+ super(input);
595
+ }
596
+ static failure(category, metadata) {
597
+ return new SerializationInError({
598
+ message: SerializationMessages.message("deserialize", category),
599
+ code: SerializationCodes.code("deserialize", category),
600
+ category,
601
+ direction: "deserialize",
602
+ metadata,
603
+ cause: metadata.cause
604
+ });
605
+ }
606
+ };
607
+ var SerializationOutError = class SerializationOutError extends SerializationError {
608
+ constructor(input) {
609
+ super(input);
610
+ }
611
+ static failure(category, metadata) {
612
+ return new SerializationOutError({
613
+ message: SerializationMessages.message("serialize", category),
614
+ code: SerializationCodes.code("serialize", category),
615
+ category,
616
+ direction: "serialize",
617
+ metadata,
618
+ cause: metadata.cause
619
+ });
620
+ }
621
+ };
622
+ var SerializationCodes = class {
623
+ static code(direction, category) {
624
+ return serializationErrorCode(direction, category);
625
+ }
626
+ };
627
+ var SerializationMessages = class {
628
+ static message(direction, category) {
629
+ if (direction === "deserialize") {
630
+ if (category === "invalid_json") return "Invalid payload: malformed JSON";
631
+ if (category === "schema_version_missing") return "Invalid payload: schemaVersion is missing";
632
+ if (category === "schema_version_unsupported") return "Invalid payload: schemaVersion is not supported";
633
+ if (category === "invalid_shape") return "Invalid payload: incompatible shape";
634
+ if (category === "mapping_not_implemented") return "Unsupported payload: mapping not implemented";
635
+ if (category === "contract_mismatch") return "Payload does not match the expected contract";
636
+ return "Failed to parse incoming payload";
637
+ }
638
+ if (category === "stringify_failed") return "Failed to serialize the response";
639
+ if (category === "contract_mismatch") return "Response does not match the expected contract";
640
+ return "Failed to build the response";
641
+ }
642
+ };
643
+ function safePreview(value, limit = 240) {
644
+ try {
645
+ const serialized = typeof value === "string" ? value : JSON.stringify(value);
646
+ return serialized.length > limit ? `${serialized.slice(0, limit)}…` : serialized;
647
+ } catch {
648
+ return;
649
+ }
650
+ }
651
+ //#endregion
652
+ //#region src/core/errors/temporal-error.ts
653
+ var TemporalError = class extends AppError {
654
+ constructor(input) {
655
+ super(input.message, input.code, {
656
+ ...input,
657
+ metadata: {
658
+ kind: input.kind,
659
+ ...input.metadata
660
+ }
661
+ });
662
+ this.kind = input.kind;
663
+ this.resourceType = input.metadata.resourceType;
664
+ this.evaluatedAtIso = input.metadata.evaluatedAtIso;
665
+ Object.freeze(this);
666
+ }
667
+ };
668
+ var ExpiredError = class ExpiredError extends TemporalError {
669
+ constructor(input) {
670
+ super(input);
671
+ }
672
+ static detected(input) {
673
+ return new ExpiredError({
674
+ message: "The validity of the resource/action has expired",
675
+ code: ErrorCodes.temporal.expired,
676
+ kind: "expired",
677
+ metadata: {
678
+ ...input,
679
+ hint: input.hint ?? "The window has expired. Request a new link or try again within the valid period."
680
+ },
681
+ cause: input.cause,
682
+ type: input.type,
683
+ severity: input.severity,
684
+ correlationId: input.correlationId,
685
+ requestId: input.requestId,
686
+ commandId: input.commandId,
687
+ createdAtIso: input.createdAtIso,
688
+ publicMessage: input.publicMessage
689
+ });
690
+ }
691
+ };
692
+ var NotYetValidError = class NotYetValidError extends TemporalError {
693
+ constructor(input) {
694
+ super(input);
695
+ }
696
+ static detected(input) {
697
+ return new NotYetValidError({
698
+ message: "The resource/action is not yet valid",
699
+ code: ErrorCodes.temporal.notYetValid,
700
+ kind: "not_yet_valid",
701
+ metadata: {
702
+ ...input,
703
+ hint: input.hint ?? "Not yet within the valid period. Try again later."
704
+ },
705
+ cause: input.cause,
706
+ type: input.type,
707
+ severity: input.severity,
708
+ correlationId: input.correlationId,
709
+ requestId: input.requestId,
710
+ commandId: input.commandId,
711
+ createdAtIso: input.createdAtIso,
712
+ publicMessage: input.publicMessage
713
+ });
714
+ }
715
+ };
716
+ function evaluateTemporalWindow(input) {
717
+ const evaluatedMs = Date.parse(input.evaluatedAtIso);
718
+ if (Number.isNaN(evaluatedMs)) return null;
719
+ let notYetValid = false;
720
+ if (input.validFromIso) {
721
+ const fromMs = Date.parse(input.validFromIso);
722
+ if (!Number.isNaN(fromMs) && evaluatedMs < fromMs) notYetValid = true;
723
+ }
724
+ if (input.validUntilIso) {
725
+ const untilMs = Date.parse(input.validUntilIso);
726
+ if (!Number.isNaN(untilMs) && evaluatedMs > untilMs) return {
727
+ expired: true,
728
+ notYetValid: false
729
+ };
730
+ }
731
+ return {
732
+ expired: false,
733
+ notYetValid
734
+ };
735
+ }
736
+ //#endregion
737
+ //#region src/core/errors/validation-error.ts
738
+ var ValidationError = class extends AppError {
739
+ constructor(field, code, message, options) {
740
+ const baseMetadata = {
741
+ field: field.value,
742
+ validationCode: code.value
743
+ };
744
+ const mergedMetadata = options?.metadata ? {
745
+ ...baseMetadata,
746
+ ...options.metadata
747
+ } : baseMetadata;
748
+ super(message, ErrorCodes.validation, {
749
+ ...options,
750
+ metadata: mergedMetadata
751
+ });
752
+ }
753
+ };
754
+ //#endregion
755
+ export { UniqueConstraintViolationError as C, AuthenticationError as D, AuthorizationError as E, DuplicateError as S, BusinessRuleViolationError as T, IdempotencyKeyMissingError as _, evaluateTemporalWindow as a, AlreadyExistsError as b, SerializationInError as c, safePreview as d, NotFoundError as f, IdempotencyInProgressError as g, IdempotencyError as h, TemporalError as i, SerializationMessages as l, IntegrationError as m, ExpiredError as n, SerializationCodes as o, LegacyIncompatibleError as p, NotYetValidError as r, SerializationError as s, ValidationError as t, SerializationOutError as u, IdempotencyPayloadMismatchError as v, translateUniqueViolationToDuplicate as w, ConflictError as x, IdempotencyReplayNotSupportedError as y };
756
+
757
+ //# sourceMappingURL=validation-error.js.map