@cullet/erp-core 1.3.0 → 1.5.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 (197) hide show
  1. package/KIT_CONTEXT.md +11 -3
  2. package/README.md +160 -0
  3. package/dist/abac/index.cjs +7 -0
  4. package/dist/abac/index.d.cts +2 -0
  5. package/dist/abac/index.d.ts +2 -0
  6. package/dist/abac/index.js +2 -0
  7. package/dist/app-error.cjs +201 -0
  8. package/dist/app-error.cjs.map +1 -0
  9. package/dist/app-error.js +178 -0
  10. package/dist/app-error.js.map +1 -0
  11. package/dist/application/index.cjs +2 -1
  12. package/dist/application/index.d.cts +2 -1
  13. package/dist/application/index.d.ts +2 -1
  14. package/dist/application/index.js +2 -1
  15. package/dist/authorization-error.cjs +157 -0
  16. package/dist/authorization-error.cjs.map +1 -0
  17. package/dist/authorization-error.d.cts +113 -0
  18. package/dist/authorization-error.d.ts +113 -0
  19. package/dist/authorization-error.js +152 -0
  20. package/dist/authorization-error.js.map +1 -0
  21. package/dist/authorizer.port.d.cts +130 -0
  22. package/dist/authorizer.port.d.ts +130 -0
  23. package/dist/composite-authorizer.d.cts +216 -0
  24. package/dist/composite-authorizer.d.ts +216 -0
  25. package/dist/condition-evaluator.cjs +579 -0
  26. package/dist/condition-evaluator.cjs.map +1 -0
  27. package/dist/condition-evaluator.js +550 -0
  28. package/dist/condition-evaluator.js.map +1 -0
  29. package/dist/{gate-types.d.ts → core-config.d.cts} +78 -77
  30. package/dist/{gate-types.d.cts → core-config.d.ts} +78 -77
  31. package/dist/domain/index.cjs +2 -1
  32. package/dist/domain/index.d.cts +2 -1
  33. package/dist/domain/index.d.ts +2 -1
  34. package/dist/domain/index.js +2 -1
  35. package/dist/domain-event-contracts.cjs +3 -2
  36. package/dist/domain-event-contracts.cjs.map +1 -1
  37. package/dist/domain-event-contracts.js +2 -1
  38. package/dist/domain-event-contracts.js.map +1 -1
  39. package/dist/entity.cjs +122 -0
  40. package/dist/entity.cjs.map +1 -0
  41. package/dist/entity.js +111 -0
  42. package/dist/entity.js.map +1 -0
  43. package/dist/errors/index.cjs +10 -7
  44. package/dist/errors/index.d.cts +2 -1
  45. package/dist/errors/index.d.ts +2 -1
  46. package/dist/errors/index.js +6 -3
  47. package/dist/gate-engine-registry.cjs +5 -4
  48. package/dist/gate-engine-registry.cjs.map +1 -1
  49. package/dist/gate-engine-registry.d.cts +3 -2
  50. package/dist/gate-engine-registry.d.ts +3 -2
  51. package/dist/gate-engine-registry.js +2 -1
  52. package/dist/gate-engine-registry.js.map +1 -1
  53. package/dist/gate-v1-payload.schema.cjs +0 -562
  54. package/dist/gate-v1-payload.schema.cjs.map +1 -1
  55. package/dist/gate-v1-payload.schema.js +1 -533
  56. package/dist/gate-v1-payload.schema.js.map +1 -1
  57. package/dist/hashing.cjs +2 -44
  58. package/dist/hashing.cjs.map +1 -1
  59. package/dist/hashing.js +2 -38
  60. package/dist/hashing.js.map +1 -1
  61. package/dist/index.cjs +36 -17
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +19 -12
  64. package/dist/index.d.ts +19 -12
  65. package/dist/index.js +17 -10
  66. package/dist/index.js.map +1 -1
  67. package/dist/not-found-error.cjs +5 -5
  68. package/dist/not-found-error.cjs.map +1 -1
  69. package/dist/not-found-error.js +1 -1
  70. package/dist/outcome.d.cts +1 -83
  71. package/dist/outcome.d.ts +1 -83
  72. package/dist/parse-gate-payload.d.cts +2 -2
  73. package/dist/parse-gate-payload.d.ts +2 -2
  74. package/dist/path.d.cts +2 -2
  75. package/dist/path.d.ts +2 -2
  76. package/dist/policies/engines/index.d.cts +1 -1
  77. package/dist/policies/engines/index.d.ts +1 -1
  78. package/dist/policies/engines/v1/gate/index.cjs +5 -4
  79. package/dist/policies/engines/v1/gate/index.cjs.map +1 -1
  80. package/dist/policies/engines/v1/gate/index.d.cts +4 -2
  81. package/dist/policies/engines/v1/gate/index.d.ts +4 -2
  82. package/dist/policies/engines/v1/gate/index.js +2 -1
  83. package/dist/policies/engines/v1/gate/index.js.map +1 -1
  84. package/dist/policies/index.cjs +5 -5
  85. package/dist/policies/index.d.cts +3 -2
  86. package/dist/policies/index.d.ts +3 -2
  87. package/dist/policies/index.js +2 -2
  88. package/dist/policy-bridge.cjs +437 -0
  89. package/dist/policy-bridge.cjs.map +1 -0
  90. package/dist/policy-bridge.d.cts +185 -0
  91. package/dist/policy-bridge.d.ts +185 -0
  92. package/dist/policy-bridge.js +396 -0
  93. package/dist/policy-bridge.js.map +1 -0
  94. package/dist/policy-service.cjs +241 -240
  95. package/dist/policy-service.cjs.map +1 -1
  96. package/dist/policy-service.d.cts +2 -2
  97. package/dist/policy-service.d.ts +2 -2
  98. package/dist/policy-service.js +240 -239
  99. package/dist/policy-service.js.map +1 -1
  100. package/dist/rbac/index.cjs +9 -0
  101. package/dist/rbac/index.d.cts +3 -0
  102. package/dist/rbac/index.d.ts +3 -0
  103. package/dist/rbac/index.js +2 -0
  104. package/dist/requested-by.cjs +54 -0
  105. package/dist/requested-by.cjs.map +1 -0
  106. package/dist/requested-by.d.cts +25 -0
  107. package/dist/requested-by.d.ts +25 -0
  108. package/dist/requested-by.js +49 -0
  109. package/dist/requested-by.js.map +1 -0
  110. package/dist/result/index.d.cts +2 -1
  111. package/dist/result/index.d.ts +2 -1
  112. package/dist/result.d.cts +84 -0
  113. package/dist/result.d.ts +84 -0
  114. package/dist/rule.cjs +327 -0
  115. package/dist/rule.cjs.map +1 -0
  116. package/dist/rule.js +298 -0
  117. package/dist/rule.js.map +1 -0
  118. package/dist/stable-stringify.cjs +47 -0
  119. package/dist/stable-stringify.cjs.map +1 -0
  120. package/dist/stable-stringify.js +42 -0
  121. package/dist/stable-stringify.js.map +1 -0
  122. package/dist/temporal-use-case.cjs +6 -53
  123. package/dist/temporal-use-case.cjs.map +1 -1
  124. package/dist/temporal-use-case.d.cts +11 -28
  125. package/dist/temporal-use-case.d.ts +11 -28
  126. package/dist/temporal-use-case.js +7 -48
  127. package/dist/temporal-use-case.js.map +1 -1
  128. package/dist/unexpected-error.cjs +3 -192
  129. package/dist/unexpected-error.cjs.map +1 -1
  130. package/dist/unexpected-error.js +2 -167
  131. package/dist/unexpected-error.js.map +1 -1
  132. package/dist/use-case.cjs +2 -6
  133. package/dist/use-case.cjs.map +1 -1
  134. package/dist/use-case.js +2 -6
  135. package/dist/use-case.js.map +1 -1
  136. package/dist/uuid-identifier.cjs +2 -7
  137. package/dist/uuid-identifier.cjs.map +1 -1
  138. package/dist/uuid-identifier.d.cts +2 -85
  139. package/dist/uuid-identifier.d.ts +2 -85
  140. package/dist/uuid-identifier.js +1 -6
  141. package/dist/uuid-identifier.js.map +1 -1
  142. package/dist/uuid.cjs +18 -0
  143. package/dist/uuid.cjs.map +1 -0
  144. package/dist/uuid.js +13 -0
  145. package/dist/uuid.js.map +1 -0
  146. package/dist/validation-error.cjs +33 -166
  147. package/dist/validation-error.cjs.map +1 -1
  148. package/dist/validation-error.d.cts +12 -103
  149. package/dist/validation-error.d.ts +12 -103
  150. package/dist/validation-error.js +7 -134
  151. package/dist/validation-error.js.map +1 -1
  152. package/dist/value-object.cjs +12 -126
  153. package/dist/value-object.cjs.map +1 -1
  154. package/dist/value-object.d.cts +97 -0
  155. package/dist/value-object.d.ts +97 -0
  156. package/dist/value-object.js +13 -115
  157. package/dist/value-object.js.map +1 -1
  158. package/meta.json +20 -4
  159. package/package.json +27 -1
  160. package/src/abac/index.ts +1 -0
  161. package/src/core/abac/abac-request.ts +29 -0
  162. package/src/core/abac/attributes.ts +39 -0
  163. package/src/core/abac/authorizer.ts +108 -0
  164. package/src/core/abac/combining.ts +63 -0
  165. package/src/core/abac/composite-authorizer.ts +45 -0
  166. package/src/core/abac/domain/policy-set.ts +52 -0
  167. package/src/core/abac/domain/rule.ts +197 -0
  168. package/src/core/abac/index.ts +21 -0
  169. package/src/core/application/commands/requested-by.ts +3 -4
  170. package/src/core/application/ports/abac-authorizer.port.ts +20 -0
  171. package/src/core/application/ports/authorizer.port.ts +22 -0
  172. package/src/core/application/queries/query.ts +6 -1
  173. package/src/core/application/use-case.ts +1 -1
  174. package/src/core/domain/entity.ts +1 -1
  175. package/src/core/domain/uuid-identifier.ts +1 -8
  176. package/src/core/domain/value-object.ts +12 -3
  177. package/src/core/errors/authorization-error.ts +26 -0
  178. package/src/core/errors/error-codes.ts +1 -0
  179. package/src/core/errors/utils/json-safe.ts +20 -11
  180. package/src/core/index.ts +7 -0
  181. package/src/core/policies/engines/v1/condition-evaluator.ts +56 -1
  182. package/src/core/rbac/access-request.ts +32 -0
  183. package/src/core/rbac/authorizer.ts +91 -0
  184. package/src/core/rbac/domain/grant.ts +96 -0
  185. package/src/core/rbac/domain/permission-set.ts +67 -0
  186. package/src/core/rbac/domain/permission.ts +119 -0
  187. package/src/core/rbac/domain/role.ts +101 -0
  188. package/src/core/rbac/domain/scope.ts +84 -0
  189. package/src/core/rbac/index.ts +15 -0
  190. package/src/core/rbac/policy-bridge.ts +44 -0
  191. package/src/core/shared/hashing.ts +1 -55
  192. package/src/core/shared/stable-stringify.ts +57 -0
  193. package/src/core/shared/uuid.ts +11 -0
  194. package/src/examples/application/authorize-cancel-order-abac.example.ts +107 -0
  195. package/src/examples/application/authorize-cancel-order.example.ts +101 -0
  196. package/src/rbac/index.ts +1 -0
  197. package/src/version.ts +1 -1
@@ -0,0 +1,54 @@
1
+ const require_validation_code = require("./validation-code.cjs");
2
+ const require_validation_field = require("./validation-field.cjs");
3
+ const require_validation_exception = require("./validation-exception.cjs");
4
+ const require_uuid = require("./uuid.cjs");
5
+ //#region src/core/application/commands/requested-by.ts
6
+ const REQUESTED_BY_FIELD = require_validation_field.ValidationField.of("requestedBy");
7
+ const SYSTEM_IDENTITY_PATTERN = /^system:[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
8
+ var RequestedBy = class RequestedBy {
9
+ constructor(kind, raw) {
10
+ this.kind = kind;
11
+ this.raw = raw;
12
+ Object.freeze(this);
13
+ }
14
+ /** Builds from a human user ID (must be a UUID). */
15
+ static fromUser(userId) {
16
+ if (!require_uuid.UUID_PATTERN.test(userId)) throw new require_validation_exception.InvalidValueException(REQUESTED_BY_FIELD, require_validation_code.ValidationCode.INVALID_FORMAT, `requestedBy: user identity must be a UUID, got "${userId}"`);
17
+ return new RequestedBy("user", userId);
18
+ }
19
+ /**
20
+ * Builds from a system identity.
21
+ * Only accepts the format "system:<job>", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.
22
+ */
23
+ static fromSystem(systemIdentity) {
24
+ if (!SYSTEM_IDENTITY_PATTERN.test(systemIdentity)) throw new require_validation_exception.InvalidValueException(REQUESTED_BY_FIELD, require_validation_code.ValidationCode.INVALID_FORMAT, `requestedBy: system identity must match "system:<job>" (e.g. "system:late-fee-job"), got "${systemIdentity}"`);
25
+ return new RequestedBy("system", systemIdentity);
26
+ }
27
+ /**
28
+ * Infers the kind from the raw value.
29
+ * Use when the origin (user vs system) is not known at the call-site.
30
+ */
31
+ static parse(raw) {
32
+ if (require_uuid.UUID_PATTERN.test(raw)) return new RequestedBy("user", raw);
33
+ if (SYSTEM_IDENTITY_PATTERN.test(raw)) return new RequestedBy("system", raw);
34
+ throw new require_validation_exception.InvalidValueException(REQUESTED_BY_FIELD, require_validation_code.ValidationCode.INVALID_FORMAT, `requestedBy must be a UUID (user) or "system:<job>" (system), got "${raw}"`);
35
+ }
36
+ get isUser() {
37
+ return this.kind === "user";
38
+ }
39
+ get isSystem() {
40
+ return this.kind === "system";
41
+ }
42
+ toString() {
43
+ return this.raw;
44
+ }
45
+ };
46
+ //#endregion
47
+ Object.defineProperty(exports, "RequestedBy", {
48
+ enumerable: true,
49
+ get: function() {
50
+ return RequestedBy;
51
+ }
52
+ });
53
+
54
+ //# sourceMappingURL=requested-by.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requested-by.cjs","names":["ValidationField","UUID_PATTERN","InvalidValueException","ValidationCode"],"sources":["../src/core/application/commands/requested-by.ts"],"sourcesContent":["import { ValidationCode } from \"../../exceptions/validation-code.js\";\nimport { InvalidValueException } from \"../../exceptions/validation-exception.js\";\nimport { ValidationField } from \"../../exceptions/validation-field.js\";\nimport { UUID_PATTERN } from \"../../shared/uuid.js\";\n\n// Identifies who triggered a Command.\n// Two valid formats:\n// - Human user: canonical RFC-4122 UUID, versions 1–5 — the same pattern\n// `UuidIdentifier` enforces (e.g.: \"550e8400-e29b-41d4-a716-446655440000\")\n// - System identity: \"system:<job>\" where <job> is [a-z][a-z0-9]*(-[a-z0-9]+)*\n// (e.g.: \"system:late-fee-job\", \"system:email-sender\")\n//\n// The split between `fromUser` / `fromSystem` / `parse` exists to make intent\n// explicit at the call-site: whoever builds the value knows where it came from.\n\ntype RequestedByKind = \"user\" | \"system\";\n\nconst REQUESTED_BY_FIELD = ValidationField.of(\"requestedBy\");\n\n// system:<job> where <job> starts with a lowercase letter and may have hyphens between segments\nconst SYSTEM_IDENTITY_PATTERN = /^system:[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;\n\nclass RequestedBy {\n readonly kind: RequestedByKind;\n readonly raw: string;\n\n private constructor(kind: RequestedByKind, raw: string) {\n this.kind = kind;\n this.raw = raw;\n Object.freeze(this);\n }\n\n /** Builds from a human user ID (must be a UUID). */\n static fromUser(userId: string): RequestedBy {\n if (!UUID_PATTERN.test(userId)) {\n throw new InvalidValueException(\n REQUESTED_BY_FIELD,\n ValidationCode.INVALID_FORMAT,\n `requestedBy: user identity must be a UUID, got \"${userId}\"`,\n );\n }\n\n return new RequestedBy(\"user\", userId);\n }\n\n /**\n * Builds from a system identity.\n * Only accepts the format \"system:<job>\", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.\n */\n static fromSystem(systemIdentity: string): RequestedBy {\n if (!SYSTEM_IDENTITY_PATTERN.test(systemIdentity)) {\n throw new InvalidValueException(\n REQUESTED_BY_FIELD,\n ValidationCode.INVALID_FORMAT,\n `requestedBy: system identity must match \"system:<job>\" (e.g. \"system:late-fee-job\"), got \"${systemIdentity}\"`,\n );\n }\n\n return new RequestedBy(\"system\", systemIdentity);\n }\n\n /**\n * Infers the kind from the raw value.\n * Use when the origin (user vs system) is not known at the call-site.\n */\n static parse(raw: string): RequestedBy {\n if (UUID_PATTERN.test(raw)) {\n return new RequestedBy(\"user\", raw);\n }\n\n if (SYSTEM_IDENTITY_PATTERN.test(raw)) {\n return new RequestedBy(\"system\", raw);\n }\n\n throw new InvalidValueException(\n REQUESTED_BY_FIELD,\n ValidationCode.INVALID_FORMAT,\n `requestedBy must be a UUID (user) or \"system:<job>\" (system), got \"${raw}\"`,\n );\n }\n\n get isUser(): boolean {\n return this.kind === \"user\";\n }\n\n get isSystem(): boolean {\n return this.kind === \"system\";\n }\n\n toString(): string {\n return this.raw;\n }\n}\n\nexport type { RequestedByKind };\nexport { RequestedBy };\n"],"mappings":";;;;;AAiBA,MAAM,qBAAqBA,yBAAAA,gBAAgB,GAAG,aAAa;AAG3D,MAAM,0BAA0B;AAEhC,IAAM,cAAN,MAAM,YAAY;CAId,YAAoB,MAAuB,KAAa;EACpD,KAAK,OAAO;EACZ,KAAK,MAAM;EACX,OAAO,OAAO,IAAI;CACtB;;CAGA,OAAO,SAAS,QAA6B;EACzC,IAAI,CAACC,aAAAA,aAAa,KAAK,MAAM,GACzB,MAAM,IAAIC,6BAAAA,sBACN,oBACAC,wBAAAA,eAAe,gBACf,mDAAmD,OAAO,EAC9D;EAGJ,OAAO,IAAI,YAAY,QAAQ,MAAM;CACzC;;;;;CAMA,OAAO,WAAW,gBAAqC;EACnD,IAAI,CAAC,wBAAwB,KAAK,cAAc,GAC5C,MAAM,IAAID,6BAAAA,sBACN,oBACAC,wBAAAA,eAAe,gBACf,6FAA6F,eAAe,EAChH;EAGJ,OAAO,IAAI,YAAY,UAAU,cAAc;CACnD;;;;;CAMA,OAAO,MAAM,KAA0B;EACnC,IAAIF,aAAAA,aAAa,KAAK,GAAG,GACrB,OAAO,IAAI,YAAY,QAAQ,GAAG;EAGtC,IAAI,wBAAwB,KAAK,GAAG,GAChC,OAAO,IAAI,YAAY,UAAU,GAAG;EAGxC,MAAM,IAAIC,6BAAAA,sBACN,oBACAC,wBAAAA,eAAe,gBACf,sEAAsE,IAAI,EAC9E;CACJ;CAEA,IAAI,SAAkB;EAClB,OAAO,KAAK,SAAS;CACzB;CAEA,IAAI,WAAoB;EACpB,OAAO,KAAK,SAAS;CACzB;CAEA,WAAmB;EACf,OAAO,KAAK;CAChB;AACJ"}
@@ -0,0 +1,25 @@
1
+ //#region src/core/application/commands/requested-by.d.ts
2
+ type RequestedByKind = "user" | "system";
3
+ declare class RequestedBy {
4
+ readonly kind: RequestedByKind;
5
+ readonly raw: string;
6
+ private constructor();
7
+ /** Builds from a human user ID (must be a UUID). */
8
+ static fromUser(userId: string): RequestedBy;
9
+ /**
10
+ * Builds from a system identity.
11
+ * Only accepts the format "system:<job>", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.
12
+ */
13
+ static fromSystem(systemIdentity: string): RequestedBy;
14
+ /**
15
+ * Infers the kind from the raw value.
16
+ * Use when the origin (user vs system) is not known at the call-site.
17
+ */
18
+ static parse(raw: string): RequestedBy;
19
+ get isUser(): boolean;
20
+ get isSystem(): boolean;
21
+ toString(): string;
22
+ }
23
+ //#endregion
24
+ export { RequestedByKind as n, RequestedBy as t };
25
+ //# sourceMappingURL=requested-by.d.cts.map
@@ -0,0 +1,25 @@
1
+ //#region src/core/application/commands/requested-by.d.ts
2
+ type RequestedByKind = "user" | "system";
3
+ declare class RequestedBy {
4
+ readonly kind: RequestedByKind;
5
+ readonly raw: string;
6
+ private constructor();
7
+ /** Builds from a human user ID (must be a UUID). */
8
+ static fromUser(userId: string): RequestedBy;
9
+ /**
10
+ * Builds from a system identity.
11
+ * Only accepts the format "system:<job>", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.
12
+ */
13
+ static fromSystem(systemIdentity: string): RequestedBy;
14
+ /**
15
+ * Infers the kind from the raw value.
16
+ * Use when the origin (user vs system) is not known at the call-site.
17
+ */
18
+ static parse(raw: string): RequestedBy;
19
+ get isUser(): boolean;
20
+ get isSystem(): boolean;
21
+ toString(): string;
22
+ }
23
+ //#endregion
24
+ export { RequestedByKind as n, RequestedBy as t };
25
+ //# sourceMappingURL=requested-by.d.ts.map
@@ -0,0 +1,49 @@
1
+ import { t as ValidationCode } from "./validation-code.js";
2
+ import { t as ValidationField } from "./validation-field.js";
3
+ import { t as InvalidValueException } from "./validation-exception.js";
4
+ import { t as UUID_PATTERN } from "./uuid.js";
5
+ //#region src/core/application/commands/requested-by.ts
6
+ const REQUESTED_BY_FIELD = ValidationField.of("requestedBy");
7
+ const SYSTEM_IDENTITY_PATTERN = /^system:[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
8
+ var RequestedBy = class RequestedBy {
9
+ constructor(kind, raw) {
10
+ this.kind = kind;
11
+ this.raw = raw;
12
+ Object.freeze(this);
13
+ }
14
+ /** Builds from a human user ID (must be a UUID). */
15
+ static fromUser(userId) {
16
+ if (!UUID_PATTERN.test(userId)) throw new InvalidValueException(REQUESTED_BY_FIELD, ValidationCode.INVALID_FORMAT, `requestedBy: user identity must be a UUID, got "${userId}"`);
17
+ return new RequestedBy("user", userId);
18
+ }
19
+ /**
20
+ * Builds from a system identity.
21
+ * Only accepts the format "system:<job>", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.
22
+ */
23
+ static fromSystem(systemIdentity) {
24
+ if (!SYSTEM_IDENTITY_PATTERN.test(systemIdentity)) throw new InvalidValueException(REQUESTED_BY_FIELD, ValidationCode.INVALID_FORMAT, `requestedBy: system identity must match "system:<job>" (e.g. "system:late-fee-job"), got "${systemIdentity}"`);
25
+ return new RequestedBy("system", systemIdentity);
26
+ }
27
+ /**
28
+ * Infers the kind from the raw value.
29
+ * Use when the origin (user vs system) is not known at the call-site.
30
+ */
31
+ static parse(raw) {
32
+ if (UUID_PATTERN.test(raw)) return new RequestedBy("user", raw);
33
+ if (SYSTEM_IDENTITY_PATTERN.test(raw)) return new RequestedBy("system", raw);
34
+ throw new InvalidValueException(REQUESTED_BY_FIELD, ValidationCode.INVALID_FORMAT, `requestedBy must be a UUID (user) or "system:<job>" (system), got "${raw}"`);
35
+ }
36
+ get isUser() {
37
+ return this.kind === "user";
38
+ }
39
+ get isSystem() {
40
+ return this.kind === "system";
41
+ }
42
+ toString() {
43
+ return this.raw;
44
+ }
45
+ };
46
+ //#endregion
47
+ export { RequestedBy as t };
48
+
49
+ //# sourceMappingURL=requested-by.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requested-by.js","names":[],"sources":["../src/core/application/commands/requested-by.ts"],"sourcesContent":["import { ValidationCode } from \"../../exceptions/validation-code.js\";\nimport { InvalidValueException } from \"../../exceptions/validation-exception.js\";\nimport { ValidationField } from \"../../exceptions/validation-field.js\";\nimport { UUID_PATTERN } from \"../../shared/uuid.js\";\n\n// Identifies who triggered a Command.\n// Two valid formats:\n// - Human user: canonical RFC-4122 UUID, versions 1–5 — the same pattern\n// `UuidIdentifier` enforces (e.g.: \"550e8400-e29b-41d4-a716-446655440000\")\n// - System identity: \"system:<job>\" where <job> is [a-z][a-z0-9]*(-[a-z0-9]+)*\n// (e.g.: \"system:late-fee-job\", \"system:email-sender\")\n//\n// The split between `fromUser` / `fromSystem` / `parse` exists to make intent\n// explicit at the call-site: whoever builds the value knows where it came from.\n\ntype RequestedByKind = \"user\" | \"system\";\n\nconst REQUESTED_BY_FIELD = ValidationField.of(\"requestedBy\");\n\n// system:<job> where <job> starts with a lowercase letter and may have hyphens between segments\nconst SYSTEM_IDENTITY_PATTERN = /^system:[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;\n\nclass RequestedBy {\n readonly kind: RequestedByKind;\n readonly raw: string;\n\n private constructor(kind: RequestedByKind, raw: string) {\n this.kind = kind;\n this.raw = raw;\n Object.freeze(this);\n }\n\n /** Builds from a human user ID (must be a UUID). */\n static fromUser(userId: string): RequestedBy {\n if (!UUID_PATTERN.test(userId)) {\n throw new InvalidValueException(\n REQUESTED_BY_FIELD,\n ValidationCode.INVALID_FORMAT,\n `requestedBy: user identity must be a UUID, got \"${userId}\"`,\n );\n }\n\n return new RequestedBy(\"user\", userId);\n }\n\n /**\n * Builds from a system identity.\n * Only accepts the format \"system:<job>\", where <job> matches [a-z][a-z0-9]*(-[a-z0-9]+)*.\n */\n static fromSystem(systemIdentity: string): RequestedBy {\n if (!SYSTEM_IDENTITY_PATTERN.test(systemIdentity)) {\n throw new InvalidValueException(\n REQUESTED_BY_FIELD,\n ValidationCode.INVALID_FORMAT,\n `requestedBy: system identity must match \"system:<job>\" (e.g. \"system:late-fee-job\"), got \"${systemIdentity}\"`,\n );\n }\n\n return new RequestedBy(\"system\", systemIdentity);\n }\n\n /**\n * Infers the kind from the raw value.\n * Use when the origin (user vs system) is not known at the call-site.\n */\n static parse(raw: string): RequestedBy {\n if (UUID_PATTERN.test(raw)) {\n return new RequestedBy(\"user\", raw);\n }\n\n if (SYSTEM_IDENTITY_PATTERN.test(raw)) {\n return new RequestedBy(\"system\", raw);\n }\n\n throw new InvalidValueException(\n REQUESTED_BY_FIELD,\n ValidationCode.INVALID_FORMAT,\n `requestedBy must be a UUID (user) or \"system:<job>\" (system), got \"${raw}\"`,\n );\n }\n\n get isUser(): boolean {\n return this.kind === \"user\";\n }\n\n get isSystem(): boolean {\n return this.kind === \"system\";\n }\n\n toString(): string {\n return this.raw;\n }\n}\n\nexport type { RequestedByKind };\nexport { RequestedBy };\n"],"mappings":";;;;;AAiBA,MAAM,qBAAqB,gBAAgB,GAAG,aAAa;AAG3D,MAAM,0BAA0B;AAEhC,IAAM,cAAN,MAAM,YAAY;CAId,YAAoB,MAAuB,KAAa;EACpD,KAAK,OAAO;EACZ,KAAK,MAAM;EACX,OAAO,OAAO,IAAI;CACtB;;CAGA,OAAO,SAAS,QAA6B;EACzC,IAAI,CAAC,aAAa,KAAK,MAAM,GACzB,MAAM,IAAI,sBACN,oBACA,eAAe,gBACf,mDAAmD,OAAO,EAC9D;EAGJ,OAAO,IAAI,YAAY,QAAQ,MAAM;CACzC;;;;;CAMA,OAAO,WAAW,gBAAqC;EACnD,IAAI,CAAC,wBAAwB,KAAK,cAAc,GAC5C,MAAM,IAAI,sBACN,oBACA,eAAe,gBACf,6FAA6F,eAAe,EAChH;EAGJ,OAAO,IAAI,YAAY,UAAU,cAAc;CACnD;;;;;CAMA,OAAO,MAAM,KAA0B;EACnC,IAAI,aAAa,KAAK,GAAG,GACrB,OAAO,IAAI,YAAY,QAAQ,GAAG;EAGtC,IAAI,wBAAwB,KAAK,GAAG,GAChC,OAAO,IAAI,YAAY,UAAU,GAAG;EAGxC,MAAM,IAAI,sBACN,oBACA,eAAe,gBACf,sEAAsE,IAAI,EAC9E;CACJ;CAEA,IAAI,SAAkB;EAClB,OAAO,KAAK,SAAS;CACzB;CAEA,IAAI,WAAoB;EACpB,OAAO,KAAK,SAAS;CACzB;CAEA,WAAmB;EACf,OAAO,KAAK;CAChB;AACJ"}
@@ -1,2 +1,3 @@
1
- import { a as Result, i as Ok, n as Outcome, r as Err, t as CommonOutcomeStatus } from "../outcome.cjs";
1
+ import { n as Ok, r as Result, t as Err } from "../result.cjs";
2
+ import { n as Outcome, t as CommonOutcomeStatus } from "../outcome.cjs";
2
3
  export { type CommonOutcomeStatus, Err, Ok, Outcome, Result };
@@ -1,2 +1,3 @@
1
- import { a as Result, i as Ok, n as Outcome, r as Err, t as CommonOutcomeStatus } from "../outcome.js";
1
+ import { n as Ok, r as Result, t as Err } from "../result.js";
2
+ import { n as Outcome, t as CommonOutcomeStatus } from "../outcome.js";
2
3
  export { type CommonOutcomeStatus, Err, Ok, Outcome, Result };
@@ -0,0 +1,84 @@
1
+ //#region src/core/result/result.d.ts
2
+ /**
3
+ * Represents the outcome of an operation that may succeed or fail.
4
+ * Useful for avoiding excessive exceptions and making error flows explicit.
5
+ */
6
+ declare abstract class Result<T, E> {
7
+ protected constructor();
8
+ /**
9
+ * Creates a success result containing a value.
10
+ */
11
+ static ok<T>(value: T): Result<T, never>;
12
+ /**
13
+ * Creates an error result containing an error object.
14
+ */
15
+ static err<E>(error: E): Result<never, E>;
16
+ /**
17
+ * Returns true when this is a success result.
18
+ */
19
+ abstract isOk(): this is Ok<T>;
20
+ /**
21
+ * Returns true when this is an error result.
22
+ */
23
+ abstract isErr(): this is Err<E>;
24
+ /**
25
+ * Runs a handler based on the result state (similar to pattern matching).
26
+ */
27
+ abstract match<R>(handlers: {
28
+ ok: (value: T) => R;
29
+ err: (error: E) => R;
30
+ }): R;
31
+ /**
32
+ * Returns the value when this is success, or null when this is an error.
33
+ */
34
+ getOrNull(): T | null;
35
+ /**
36
+ * Returns the error when this is a failure, or null when this is a success.
37
+ */
38
+ errorOrNull(): E | null;
39
+ /**
40
+ * Returns the value when this is a success, or throws the error when this is a failure.
41
+ */
42
+ getOrThrow(): T;
43
+ /**
44
+ * Transforms the success value using the provided function. Keeps the error when this is a failure.
45
+ */
46
+ map<R>(transform: (value: T) => R): Result<R, E>;
47
+ /**
48
+ * Transforms the error using the provided function. Keeps the value when this is a success.
49
+ */
50
+ mapError<F>(transform: (error: E) => F): Result<T, F>;
51
+ /**
52
+ * Chains another operation that returns a Result when this result is a success.
53
+ */
54
+ flatMap<R>(transform: (value: T) => Result<R, E>): Result<R, E>;
55
+ }
56
+ /**
57
+ * Success variant of Result.
58
+ */
59
+ declare class Ok<T> extends Result<T, never> {
60
+ readonly value: T;
61
+ constructor(value: T);
62
+ isOk(): this is Ok<T>;
63
+ isErr(): this is Err<never>;
64
+ match<R>(handlers: {
65
+ ok: (value: T) => R;
66
+ err: (error: never) => R;
67
+ }): R;
68
+ }
69
+ /**
70
+ * Error variant of Result.
71
+ */
72
+ declare class Err<E> extends Result<never, E> {
73
+ readonly error: E;
74
+ constructor(error: E);
75
+ isOk(): this is Ok<never>;
76
+ isErr(): this is Err<E>;
77
+ match<R>(handlers: {
78
+ ok: (value: never) => R;
79
+ err: (error: E) => R;
80
+ }): R;
81
+ }
82
+ //#endregion
83
+ export { Ok as n, Result as r, Err as t };
84
+ //# sourceMappingURL=result.d.cts.map
@@ -0,0 +1,84 @@
1
+ //#region src/core/result/result.d.ts
2
+ /**
3
+ * Represents the outcome of an operation that may succeed or fail.
4
+ * Useful for avoiding excessive exceptions and making error flows explicit.
5
+ */
6
+ declare abstract class Result<T, E> {
7
+ protected constructor();
8
+ /**
9
+ * Creates a success result containing a value.
10
+ */
11
+ static ok<T>(value: T): Result<T, never>;
12
+ /**
13
+ * Creates an error result containing an error object.
14
+ */
15
+ static err<E>(error: E): Result<never, E>;
16
+ /**
17
+ * Returns true when this is a success result.
18
+ */
19
+ abstract isOk(): this is Ok<T>;
20
+ /**
21
+ * Returns true when this is an error result.
22
+ */
23
+ abstract isErr(): this is Err<E>;
24
+ /**
25
+ * Runs a handler based on the result state (similar to pattern matching).
26
+ */
27
+ abstract match<R>(handlers: {
28
+ ok: (value: T) => R;
29
+ err: (error: E) => R;
30
+ }): R;
31
+ /**
32
+ * Returns the value when this is success, or null when this is an error.
33
+ */
34
+ getOrNull(): T | null;
35
+ /**
36
+ * Returns the error when this is a failure, or null when this is a success.
37
+ */
38
+ errorOrNull(): E | null;
39
+ /**
40
+ * Returns the value when this is a success, or throws the error when this is a failure.
41
+ */
42
+ getOrThrow(): T;
43
+ /**
44
+ * Transforms the success value using the provided function. Keeps the error when this is a failure.
45
+ */
46
+ map<R>(transform: (value: T) => R): Result<R, E>;
47
+ /**
48
+ * Transforms the error using the provided function. Keeps the value when this is a success.
49
+ */
50
+ mapError<F>(transform: (error: E) => F): Result<T, F>;
51
+ /**
52
+ * Chains another operation that returns a Result when this result is a success.
53
+ */
54
+ flatMap<R>(transform: (value: T) => Result<R, E>): Result<R, E>;
55
+ }
56
+ /**
57
+ * Success variant of Result.
58
+ */
59
+ declare class Ok<T> extends Result<T, never> {
60
+ readonly value: T;
61
+ constructor(value: T);
62
+ isOk(): this is Ok<T>;
63
+ isErr(): this is Err<never>;
64
+ match<R>(handlers: {
65
+ ok: (value: T) => R;
66
+ err: (error: never) => R;
67
+ }): R;
68
+ }
69
+ /**
70
+ * Error variant of Result.
71
+ */
72
+ declare class Err<E> extends Result<never, E> {
73
+ readonly error: E;
74
+ constructor(error: E);
75
+ isOk(): this is Ok<never>;
76
+ isErr(): this is Err<E>;
77
+ match<R>(handlers: {
78
+ ok: (value: never) => R;
79
+ err: (error: E) => R;
80
+ }): R;
81
+ }
82
+ //#endregion
83
+ export { Ok as n, Result as r, Err as t };
84
+ //# sourceMappingURL=result.d.ts.map