@cullet/erp-core 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/KIT_CONTEXT.md +7 -1
  2. package/dist/abac/index.d.cts +2 -2
  3. package/dist/abac/index.d.ts +2 -2
  4. package/dist/aggregate-version.cjs +14 -0
  5. package/dist/aggregate-version.cjs.map +1 -0
  6. package/dist/aggregate-version.js +9 -0
  7. package/dist/aggregate-version.js.map +1 -0
  8. package/dist/app-error.cjs +21 -6
  9. package/dist/app-error.cjs.map +1 -1
  10. package/dist/app-error.js +21 -6
  11. package/dist/app-error.js.map +1 -1
  12. package/dist/application/index.cjs +8 -4
  13. package/dist/application/index.d.cts +2 -2
  14. package/dist/application/index.d.ts +2 -2
  15. package/dist/application/index.js +1 -2
  16. package/dist/authorization-error.cjs +67 -17
  17. package/dist/authorization-error.cjs.map +1 -1
  18. package/dist/authorization-error.d.cts +6 -2
  19. package/dist/authorization-error.d.ts +6 -2
  20. package/dist/authorization-error.js +50 -18
  21. package/dist/authorization-error.js.map +1 -1
  22. package/dist/authorizer.port.d.cts +18 -3
  23. package/dist/authorizer.port.d.ts +18 -3
  24. package/dist/composite-authorizer.d.cts +63 -10
  25. package/dist/composite-authorizer.d.ts +63 -10
  26. package/dist/condition-evaluator.cjs +117 -172
  27. package/dist/condition-evaluator.cjs.map +1 -1
  28. package/dist/condition-evaluator.js +118 -167
  29. package/dist/condition-evaluator.js.map +1 -1
  30. package/dist/core-config.d.cts +53 -6
  31. package/dist/core-config.d.ts +53 -6
  32. package/dist/decorate.cjs +14 -0
  33. package/dist/decorate.js +9 -0
  34. package/dist/domain/index.cjs +107 -2
  35. package/dist/domain/index.cjs.map +1 -0
  36. package/dist/domain/index.d.cts +25 -1
  37. package/dist/domain/index.d.ts +25 -1
  38. package/dist/domain/index.js +99 -3
  39. package/dist/domain/index.js.map +1 -0
  40. package/dist/domain-event-contracts.cjs +12 -8
  41. package/dist/domain-event-contracts.cjs.map +1 -1
  42. package/dist/domain-event-contracts.d.cts +29 -4
  43. package/dist/domain-event-contracts.d.ts +29 -4
  44. package/dist/domain-event-contracts.js +11 -7
  45. package/dist/domain-event-contracts.js.map +1 -1
  46. package/dist/domain-exception.cjs +2 -1
  47. package/dist/domain-exception.cjs.map +1 -1
  48. package/dist/domain-exception.js +2 -1
  49. package/dist/domain-exception.js.map +1 -1
  50. package/dist/errors/index.cjs +3 -2
  51. package/dist/errors/index.d.cts +1 -1
  52. package/dist/errors/index.d.ts +1 -1
  53. package/dist/errors/index.js +3 -2
  54. package/dist/exceptions/index.cjs +2 -2
  55. package/dist/exceptions/index.d.cts +1 -2
  56. package/dist/exceptions/index.d.ts +1 -2
  57. package/dist/exceptions/index.js +2 -2
  58. package/dist/gate-engine-registry.cjs.map +1 -1
  59. package/dist/gate-engine-registry.d.cts +1 -1
  60. package/dist/gate-engine-registry.d.ts +1 -1
  61. package/dist/gate-engine-registry.js.map +1 -1
  62. package/dist/gate-v1-payload.schema.cjs +11 -6
  63. package/dist/gate-v1-payload.schema.cjs.map +1 -1
  64. package/dist/gate-v1-payload.schema.js +11 -6
  65. package/dist/gate-v1-payload.schema.js.map +1 -1
  66. package/dist/hashing.cjs +2 -44
  67. package/dist/hashing.cjs.map +1 -1
  68. package/dist/hashing.js +3 -39
  69. package/dist/hashing.js.map +1 -1
  70. package/dist/immutable.cjs +25 -12
  71. package/dist/immutable.cjs.map +1 -1
  72. package/dist/immutable.js +24 -11
  73. package/dist/immutable.js.map +1 -1
  74. package/dist/index.cjs +15 -11
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.d.cts +9 -10
  77. package/dist/index.d.ts +9 -10
  78. package/dist/index.js +8 -9
  79. package/dist/index.js.map +1 -1
  80. package/dist/invalid-state-transition-exception.cjs +6 -6
  81. package/dist/invalid-state-transition-exception.cjs.map +1 -1
  82. package/dist/invalid-state-transition-exception.js +6 -6
  83. package/dist/invalid-state-transition-exception.js.map +1 -1
  84. package/dist/invariant-violation-exception.cjs +2 -2
  85. package/dist/invariant-violation-exception.cjs.map +1 -1
  86. package/dist/invariant-violation-exception.js +2 -2
  87. package/dist/invariant-violation-exception.js.map +1 -1
  88. package/dist/not-found-error.cjs +6 -4
  89. package/dist/not-found-error.cjs.map +1 -1
  90. package/dist/not-found-error.js +6 -4
  91. package/dist/not-found-error.js.map +1 -1
  92. package/dist/outcome.cjs +5 -5
  93. package/dist/outcome.cjs.map +1 -1
  94. package/dist/outcome.js +5 -5
  95. package/dist/outcome.js.map +1 -1
  96. package/dist/parse-gate-payload.d.cts +1 -1
  97. package/dist/parse-gate-payload.d.ts +1 -1
  98. package/dist/path.d.cts +2 -2
  99. package/dist/path.d.ts +2 -2
  100. package/dist/plugin.cjs +23 -13
  101. package/dist/plugin.cjs.map +1 -1
  102. package/dist/plugin.d.cts +22 -8
  103. package/dist/plugin.d.ts +22 -8
  104. package/dist/plugin.js +23 -13
  105. package/dist/plugin.js.map +1 -1
  106. package/dist/policies/engines/index.d.cts +1 -1
  107. package/dist/policies/engines/index.d.ts +1 -1
  108. package/dist/policies/engines/v1/gate/index.d.cts +3 -13
  109. package/dist/policies/engines/v1/gate/index.d.ts +3 -13
  110. package/dist/policies/index.d.cts +1 -1
  111. package/dist/policies/index.d.ts +1 -1
  112. package/dist/policy-bridge.cjs +30 -2
  113. package/dist/policy-bridge.cjs.map +1 -1
  114. package/dist/policy-bridge.d.cts +18 -0
  115. package/dist/policy-bridge.d.ts +18 -0
  116. package/dist/policy-bridge.js +30 -2
  117. package/dist/policy-bridge.js.map +1 -1
  118. package/dist/policy-service.cjs +41 -46
  119. package/dist/policy-service.cjs.map +1 -1
  120. package/dist/policy-service.d.cts +72 -9
  121. package/dist/policy-service.d.ts +72 -9
  122. package/dist/policy-service.js +43 -48
  123. package/dist/policy-service.js.map +1 -1
  124. package/dist/requested-by.cjs +4 -4
  125. package/dist/requested-by.cjs.map +1 -1
  126. package/dist/requested-by.js +2 -2
  127. package/dist/requested-by.js.map +1 -1
  128. package/dist/result.cjs +29 -1
  129. package/dist/result.cjs.map +1 -1
  130. package/dist/result.d.cts +12 -0
  131. package/dist/result.d.ts +12 -0
  132. package/dist/result.js +29 -1
  133. package/dist/result.js.map +1 -1
  134. package/dist/rule.cjs +94 -24
  135. package/dist/rule.cjs.map +1 -1
  136. package/dist/rule.js +94 -24
  137. package/dist/rule.js.map +1 -1
  138. package/dist/ruleset-registry.cjs +19 -0
  139. package/dist/ruleset-registry.cjs.map +1 -1
  140. package/dist/ruleset-registry.js +19 -0
  141. package/dist/ruleset-registry.js.map +1 -1
  142. package/dist/stable-stringify.cjs +87 -0
  143. package/dist/stable-stringify.cjs.map +1 -0
  144. package/dist/stable-stringify.js +76 -0
  145. package/dist/stable-stringify.js.map +1 -0
  146. package/dist/temporal-snapshot.d.cts +87 -0
  147. package/dist/temporal-snapshot.d.ts +87 -0
  148. package/dist/temporal-use-case.cjs +174 -16
  149. package/dist/temporal-use-case.cjs.map +1 -1
  150. package/dist/temporal-use-case.d.cts +82 -44
  151. package/dist/temporal-use-case.d.ts +82 -44
  152. package/dist/temporal-use-case.js +167 -15
  153. package/dist/temporal-use-case.js.map +1 -1
  154. package/dist/unexpected-error.cjs +4 -2
  155. package/dist/unexpected-error.cjs.map +1 -1
  156. package/dist/unexpected-error.js +4 -2
  157. package/dist/unexpected-error.js.map +1 -1
  158. package/dist/uuid-identifier.cjs +141 -8
  159. package/dist/uuid-identifier.cjs.map +1 -1
  160. package/dist/uuid-identifier.d.cts +26 -7
  161. package/dist/uuid-identifier.d.ts +26 -7
  162. package/dist/uuid-identifier.js +135 -8
  163. package/dist/uuid-identifier.js.map +1 -1
  164. package/dist/uuid.cjs +23 -0
  165. package/dist/uuid.cjs.map +1 -0
  166. package/dist/uuid.js +18 -0
  167. package/dist/uuid.js.map +1 -0
  168. package/dist/validation-code.cjs +9 -0
  169. package/dist/validation-code.cjs.map +1 -1
  170. package/dist/validation-code.d.cts +3 -0
  171. package/dist/validation-code.d.ts +3 -0
  172. package/dist/validation-code.js +9 -0
  173. package/dist/validation-code.js.map +1 -1
  174. package/dist/validation-error.cjs +42 -67
  175. package/dist/validation-error.cjs.map +1 -1
  176. package/dist/validation-error.d.cts +29 -8
  177. package/dist/validation-error.d.ts +29 -8
  178. package/dist/validation-error.js +41 -66
  179. package/dist/validation-error.js.map +1 -1
  180. package/dist/validation-exception.cjs +17 -6
  181. package/dist/validation-exception.cjs.map +1 -1
  182. package/dist/validation-exception.d.cts +33 -9
  183. package/dist/validation-exception.d.ts +33 -9
  184. package/dist/validation-exception.js +17 -6
  185. package/dist/validation-exception.js.map +1 -1
  186. package/dist/validation-field.cjs +3 -0
  187. package/dist/validation-field.cjs.map +1 -1
  188. package/dist/validation-field.d.cts +1 -0
  189. package/dist/validation-field.d.ts +1 -0
  190. package/dist/validation-field.js +3 -0
  191. package/dist/validation-field.js.map +1 -1
  192. package/dist/value-object-ruleset.contracts.d.cts +10 -0
  193. package/dist/value-object-ruleset.contracts.d.ts +10 -0
  194. package/dist/value-object.cjs +23 -4
  195. package/dist/value-object.cjs.map +1 -1
  196. package/dist/value-object.d.cts +25 -1
  197. package/dist/value-object.d.ts +25 -1
  198. package/dist/value-object.js +23 -4
  199. package/dist/value-object.js.map +1 -1
  200. package/dist/version.d.cts +27 -0
  201. package/dist/version.d.ts +27 -0
  202. package/dist/versioning/index.d.cts +2 -2
  203. package/dist/versioning/index.d.ts +2 -2
  204. package/meta.json +5 -2
  205. package/package.json +1 -1
  206. package/src/core/abac/authorizer.ts +60 -10
  207. package/src/core/abac/domain/policy-set.ts +52 -5
  208. package/src/core/abac/domain/rule.ts +28 -16
  209. package/src/core/abac/index.ts +7 -1
  210. package/src/core/application/commands/command.ts +14 -1
  211. package/src/core/application/commands/requested-by.ts +13 -5
  212. package/src/core/application/index.ts +2 -1
  213. package/src/core/application/policy-error-mapper.ts +6 -0
  214. package/src/core/application/ports/index.ts +7 -0
  215. package/src/core/application/ports/temporal-repository.port.ts +35 -2
  216. package/src/core/application/queries/index.ts +1 -1
  217. package/src/core/application/queries/query.ts +25 -3
  218. package/src/core/application/temporal/temporal-use-case.ts +31 -4
  219. package/src/core/application/use-case.ts +45 -8
  220. package/src/core/config/core-config.ts +46 -25
  221. package/src/core/config/index.ts +1 -0
  222. package/src/core/config/policy-reporter.ts +32 -1
  223. package/src/core/domain/entity.ts +51 -8
  224. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +0 -2
  225. package/src/core/domain/rulesets/ruleset-registry.ts +24 -0
  226. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +1 -7
  227. package/src/core/domain/temporal/half-open-interval.ts +34 -0
  228. package/src/core/domain/temporal/temporal-snapshot.ts +13 -2
  229. package/src/core/domain/temporal/transaction-time.ts +19 -15
  230. package/src/core/domain/temporal/valid-time.ts +20 -15
  231. package/src/core/domain/uuid-identifier.ts +6 -11
  232. package/src/core/domain/value-object.ts +29 -3
  233. package/src/core/errors/authentication-error.ts +5 -31
  234. package/src/core/errors/authorization-error.ts +12 -20
  235. package/src/core/errors/business-rule-violation-error.ts +4 -1
  236. package/src/core/errors/idempotency-error.ts +5 -2
  237. package/src/core/errors/index.ts +4 -0
  238. package/src/core/errors/integration-error.ts +4 -24
  239. package/src/core/errors/legacy-incompatible-error.ts +1 -0
  240. package/src/core/errors/not-found-error.ts +4 -1
  241. package/src/core/errors/temporal-error.ts +22 -20
  242. package/src/core/errors/unexpected-error.ts +5 -1
  243. package/src/core/errors/utils/factory-helpers.ts +70 -0
  244. package/src/core/errors/utils/index.ts +5 -0
  245. package/src/core/errors/utils/json-safe.ts +35 -12
  246. package/src/core/errors/validation-error.ts +4 -1
  247. package/src/core/exceptions/business-rule-violation-exception.ts +2 -1
  248. package/src/core/exceptions/domain-exception.ts +9 -1
  249. package/src/core/exceptions/entity-not-found-exception.ts +5 -1
  250. package/src/core/exceptions/invalid-state-transition-exception.ts +5 -2
  251. package/src/core/exceptions/invariant-violation-exception.ts +2 -2
  252. package/src/core/exceptions/validation-code.ts +14 -0
  253. package/src/core/exceptions/validation-exception.ts +44 -5
  254. package/src/core/exceptions/validation-field.ts +11 -1
  255. package/src/core/plugins/plugin.ts +25 -15
  256. package/src/core/plugins/types.ts +4 -2
  257. package/src/core/policies/asof/asof.ts +12 -0
  258. package/src/core/policies/catalog/policy-catalog-entry.ts +3 -1
  259. package/src/core/policies/catalog/policy-catalog.ts +5 -1
  260. package/src/core/policies/context/context-builder.ts +20 -0
  261. package/src/core/policies/context/context-resolver.ts +5 -0
  262. package/src/core/policies/context/context-seed.ts +11 -0
  263. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +0 -2
  264. package/src/core/policies/engines/parse-gate-payload.ts +9 -0
  265. package/src/core/policies/engines/v1/condition-date-operands.ts +112 -0
  266. package/src/core/policies/engines/v1/condition-evaluator.ts +120 -291
  267. package/src/core/policies/engines/v1/condition-schema.ts +23 -19
  268. package/src/core/policies/engines/v1/condition-types.ts +18 -11
  269. package/src/core/policies/index.ts +4 -6
  270. package/src/core/policies/service/policy-service.ts +46 -35
  271. package/src/core/policies/utils/hash.ts +5 -69
  272. package/src/core/policies/utils/result.ts +1 -1
  273. package/src/core/rbac/access-request.ts +12 -2
  274. package/src/core/rbac/authorizer.ts +8 -1
  275. package/src/core/rbac/domain/role.ts +20 -0
  276. package/src/core/rbac/domain/scope.ts +6 -1
  277. package/src/core/result/index.ts +5 -0
  278. package/src/core/result/outcome.ts +5 -7
  279. package/src/core/result/result.ts +34 -1
  280. package/src/core/shared/hashing.ts +6 -57
  281. package/src/core/shared/immutable.ts +22 -4
  282. package/src/core/shared/stable-stringify.ts +144 -0
  283. package/src/core/shared/uuid.ts +16 -0
  284. package/src/core/versioning/domain-event-contracts.ts +43 -15
  285. package/src/core/versioning/index.ts +1 -0
  286. package/src/core/versioning/version.ts +30 -1
  287. package/src/domain/index.ts +5 -0
  288. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +1 -1
  289. package/src/examples/rulesets/entity/order-invariants-v1.ts +2 -4
  290. package/src/examples/rulesets/entity/order-invariants-v2.ts +2 -4
  291. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +2 -4
  292. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +2 -4
  293. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +2 -4
  294. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +2 -4
  295. package/src/result/index.ts +7 -2
  296. package/src/version.ts +1 -1
  297. package/dist/domain-exception.d.cts +0 -7
  298. package/dist/domain-exception.d.ts +0 -7
  299. package/dist/entity.cjs +0 -126
  300. package/dist/entity.cjs.map +0 -1
  301. package/dist/entity.js +0 -115
  302. package/dist/entity.js.map +0 -1
  303. package/dist/use-case.cjs +0 -96
  304. package/dist/use-case.cjs.map +0 -1
  305. package/dist/use-case.js +0 -91
  306. package/dist/use-case.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ruleset-registry.js","names":[],"sources":["../src/core/domain/rulesets/ruleset-registry.ts"],"sourcesContent":["import { DomainException } from \"../../exceptions/domain-exception.js\";\nimport {\n type Ruleset,\n type RulesetRegistry as RulesetRegistryContract,\n} from \"./ruleset.contracts.js\";\n\nclass RulesetRegistryError extends DomainException {}\n\nfunction parseVersion(id: string): [number, number] {\n const atIdx = id.lastIndexOf(\"@\");\n const versionStr = id.slice(atIdx + 1);\n const [major, minor] = versionStr.split(\".\").map(Number);\n return [major, minor];\n}\n\nclass RulesetRegistry implements RulesetRegistryContract {\n private readonly _store = new Map<string, Ruleset>();\n private _sealed = false;\n\n register(ruleset: Ruleset): void {\n if (this._sealed) {\n throw new RulesetRegistryError(\n \"Registry is sealed. No new rulesets can be registered.\",\n );\n }\n if (this._store.has(ruleset.id)) {\n throw new RulesetRegistryError(\n `Ruleset with id \"${ruleset.id}\" is already registered.`,\n );\n }\n this._store.set(ruleset.id, ruleset);\n }\n\n seal(): void {\n this._sealed = true;\n }\n\n get<T extends Ruleset>(id: string): T {\n const ruleset = this._store.get(id);\n if (!ruleset) {\n const available = Array.from(this._store.keys()).join(\", \");\n throw new RulesetRegistryError(\n `Ruleset \"${id}\" not found. Available: [${available}]`,\n );\n }\n return ruleset as T;\n }\n\n getCurrent<T extends Ruleset>(prefix: string): T {\n const matchingEntries = Array.from(this._store.entries()).filter(\n ([key]) => key.startsWith(prefix + \"@\"),\n );\n\n if (matchingEntries.length === 0) {\n throw new RulesetRegistryError(\n `No rulesets found with prefix \"${prefix}\".`,\n );\n }\n\n const sorted = matchingEntries.sort(([a], [b]) => {\n const [aMajor, aMinor] = parseVersion(a);\n const [bMajor, bMinor] = parseVersion(b);\n if (aMajor !== bMajor) return aMajor - bMajor;\n return aMinor - bMinor;\n });\n\n return sorted[sorted.length - 1][1] as T;\n }\n}\n\nexport { RulesetRegistry };\n"],"mappings":";;AAMA,IAAM,uBAAN,cAAmC,gBAAgB,CAAC;AAEpD,SAAS,aAAa,IAA8B;CAChD,MAAM,QAAQ,GAAG,YAAY,GAAG;CAEhC,MAAM,CAAC,OAAO,SADK,GAAG,MAAM,QAAQ,CACJ,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;CACvD,OAAO,CAAC,OAAO,KAAK;AACxB;AAEA,IAAM,kBAAN,MAAyD;;gCAC3B,IAAI,IAAqB;iBACjC;;CAElB,SAAS,SAAwB;EAC7B,IAAI,KAAK,SACL,MAAM,IAAI,qBACN,wDACJ;EAEJ,IAAI,KAAK,OAAO,IAAI,QAAQ,EAAE,GAC1B,MAAM,IAAI,qBACN,oBAAoB,QAAQ,GAAG,yBACnC;EAEJ,KAAK,OAAO,IAAI,QAAQ,IAAI,OAAO;CACvC;CAEA,OAAa;EACT,KAAK,UAAU;CACnB;CAEA,IAAuB,IAAe;EAClC,MAAM,UAAU,KAAK,OAAO,IAAI,EAAE;EAClC,IAAI,CAAC,SAED,MAAM,IAAI,qBACN,YAAY,GAAG,2BAFD,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC,EAAE,KAAK,IAEA,EAAE,EACxD;EAEJ,OAAO;CACX;CAEA,WAA8B,QAAmB;EAC7C,MAAM,kBAAkB,MAAM,KAAK,KAAK,OAAO,QAAQ,CAAC,EAAE,QACrD,CAAC,SAAS,IAAI,WAAW,SAAS,GAAG,CAC1C;EAEA,IAAI,gBAAgB,WAAW,GAC3B,MAAM,IAAI,qBACN,kCAAkC,OAAO,GAC7C;EAGJ,MAAM,SAAS,gBAAgB,MAAM,CAAC,IAAI,CAAC,OAAO;GAC9C,MAAM,CAAC,QAAQ,UAAU,aAAa,CAAC;GACvC,MAAM,CAAC,QAAQ,UAAU,aAAa,CAAC;GACvC,IAAI,WAAW,QAAQ,OAAO,SAAS;GACvC,OAAO,SAAS;EACpB,CAAC;EAED,OAAO,OAAO,OAAO,SAAS,GAAG;CACrC;AACJ"}
1
+ {"version":3,"file":"ruleset-registry.js","names":[],"sources":["../src/core/domain/rulesets/ruleset-registry.ts"],"sourcesContent":["import { DomainException } from \"../../exceptions/domain-exception.js\";\nimport {\n type Ruleset,\n type RulesetRegistry as RulesetRegistryContract,\n} from \"./ruleset.contracts.js\";\n\nclass RulesetRegistryError extends DomainException {}\n\n/**\n * Runtime guard for the `RulesetId` shape (`name@major.minor`). The template\n * type only protects TypeScript callers — a JS consumer (or a cast) could\n * register `\"foo\"` or `\"foo@1.5.2\"`, and either would silently corrupt\n * {@link RulesetRegistry.getCurrent}'s version ordering via `NaN`/ignored\n * segments. Same idea as `CONTRACT_VERSION_PATTERN` in `versioning/version.ts`.\n */\nconst RULESET_ID_PATTERN = /^.+@\\d+\\.\\d+$/;\n\nfunction parseVersion(id: string): [number, number] {\n const atIdx = id.lastIndexOf(\"@\");\n const versionStr = id.slice(atIdx + 1);\n const [major, minor] = versionStr.split(\".\").map(Number);\n return [major, minor];\n}\n\nclass RulesetRegistry implements RulesetRegistryContract {\n private readonly _store = new Map<string, Ruleset>();\n private _sealed = false;\n\n register(ruleset: Ruleset): void {\n if (this._sealed) {\n throw new RulesetRegistryError(\n \"Registry is sealed. No new rulesets can be registered.\",\n );\n }\n if (!RULESET_ID_PATTERN.test(ruleset.id)) {\n throw new RulesetRegistryError(\n `Invalid ruleset id \"${ruleset.id}\". Expected \"<name>@<major>.<minor>\", e.g. \"order-creation@1.0\".`,\n );\n }\n if (this._store.has(ruleset.id)) {\n throw new RulesetRegistryError(\n `Ruleset with id \"${ruleset.id}\" is already registered.`,\n );\n }\n this._store.set(ruleset.id, ruleset);\n }\n\n seal(): void {\n this._sealed = true;\n }\n\n /**\n * Looks up a ruleset by exact id. The `T` parameter is a caller-asserted\n * cast, not a runtime check: asking for the wrong `T` compiles and returns\n * the object mistyped — the standard registry trade-off. Keep the id and\n * the expected type paired at the call site.\n */\n get<T extends Ruleset>(id: string): T {\n const ruleset = this._store.get(id);\n if (!ruleset) {\n const available = Array.from(this._store.keys()).join(\", \");\n throw new RulesetRegistryError(\n `Ruleset \"${id}\" not found. Available: [${available}]`,\n );\n }\n return ruleset as T;\n }\n\n /**\n * Returns the highest `major.minor` version registered under `prefix`.\n * The same caller-asserted `T` cast as {@link get} applies.\n */\n getCurrent<T extends Ruleset>(prefix: string): T {\n const matchingEntries = Array.from(this._store.entries()).filter(\n ([key]) => key.startsWith(prefix + \"@\"),\n );\n\n if (matchingEntries.length === 0) {\n throw new RulesetRegistryError(\n `No rulesets found with prefix \"${prefix}\".`,\n );\n }\n\n const sorted = matchingEntries.sort(([a], [b]) => {\n const [aMajor, aMinor] = parseVersion(a);\n const [bMajor, bMinor] = parseVersion(b);\n if (aMajor !== bMajor) return aMajor - bMajor;\n return aMinor - bMinor;\n });\n\n return sorted[sorted.length - 1][1] as T;\n }\n}\n\nexport { RulesetRegistry };\n"],"mappings":";;AAMA,IAAM,uBAAN,cAAmC,gBAAgB,CAAC;;;;;;;;AASpD,MAAM,qBAAqB;AAE3B,SAAS,aAAa,IAA8B;CAChD,MAAM,QAAQ,GAAG,YAAY,GAAG;CAEhC,MAAM,CAAC,OAAO,SADK,GAAG,MAAM,QAAQ,CACJ,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;CACvD,OAAO,CAAC,OAAO,KAAK;AACxB;AAEA,IAAM,kBAAN,MAAyD;;gCAC3B,IAAI,IAAqB;iBACjC;;CAElB,SAAS,SAAwB;EAC7B,IAAI,KAAK,SACL,MAAM,IAAI,qBACN,wDACJ;EAEJ,IAAI,CAAC,mBAAmB,KAAK,QAAQ,EAAE,GACnC,MAAM,IAAI,qBACN,uBAAuB,QAAQ,GAAG,iEACtC;EAEJ,IAAI,KAAK,OAAO,IAAI,QAAQ,EAAE,GAC1B,MAAM,IAAI,qBACN,oBAAoB,QAAQ,GAAG,yBACnC;EAEJ,KAAK,OAAO,IAAI,QAAQ,IAAI,OAAO;CACvC;CAEA,OAAa;EACT,KAAK,UAAU;CACnB;;;;;;;CAQA,IAAuB,IAAe;EAClC,MAAM,UAAU,KAAK,OAAO,IAAI,EAAE;EAClC,IAAI,CAAC,SAED,MAAM,IAAI,qBACN,YAAY,GAAG,2BAFD,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC,EAAE,KAAK,IAEA,EAAE,EACxD;EAEJ,OAAO;CACX;;;;;CAMA,WAA8B,QAAmB;EAC7C,MAAM,kBAAkB,MAAM,KAAK,KAAK,OAAO,QAAQ,CAAC,EAAE,QACrD,CAAC,SAAS,IAAI,WAAW,SAAS,GAAG,CAC1C;EAEA,IAAI,gBAAgB,WAAW,GAC3B,MAAM,IAAI,qBACN,kCAAkC,OAAO,GAC7C;EAGJ,MAAM,SAAS,gBAAgB,MAAM,CAAC,IAAI,CAAC,OAAO;GAC9C,MAAM,CAAC,QAAQ,UAAU,aAAa,CAAC;GACvC,MAAM,CAAC,QAAQ,UAAU,aAAa,CAAC;GACvC,IAAI,WAAW,QAAQ,OAAO,SAAS;GACvC,OAAO,SAAS;EACpB,CAAC;EAED,OAAO,OAAO,OAAO,SAAS,GAAG;CACrC;AACJ"}
@@ -0,0 +1,87 @@
1
+ const require_temporal_guards = require("./temporal-guards.cjs");
2
+ //#region src/core/shared/stable-stringify.ts
3
+ const CIRCULAR_STRUCTURE_MESSAGE = "Cannot stably stringify a circular structure";
4
+ function sortKeysDeep(value, seen) {
5
+ if (Array.isArray(value)) {
6
+ if (seen.has(value)) throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);
7
+ seen.add(value);
8
+ const mapped = value.map((item) => sortKeysDeep(item, seen));
9
+ seen.delete(value);
10
+ return mapped;
11
+ }
12
+ if (value instanceof Date) return value;
13
+ if (value && typeof value === "object") {
14
+ if (seen.has(value)) throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);
15
+ seen.add(value);
16
+ const record = value;
17
+ const ordered = Object.create(null);
18
+ for (const key of Object.keys(record).sort()) ordered[key] = sortKeysDeep(record[key], seen);
19
+ seen.delete(value);
20
+ return ordered;
21
+ }
22
+ return value;
23
+ }
24
+ /**
25
+ * Deterministic JSON string with object keys sorted recursively, so key order
26
+ * does not affect the output.
27
+ *
28
+ * Follows `JSON.stringify` semantics for the values it serializes: `undefined`,
29
+ * functions and symbols are dropped, non-finite numbers become `null`, `bigint`
30
+ * throws, and `Map`/`Set` serialize as `{}`. Distinct payloads can therefore
31
+ * collapse to the same string — this is fine for the structural-equality use it
32
+ * serves (comparing two value objects), but **not** for hashing. For a
33
+ * collision-resistant canonical form use {@link canonicalStringify}, which
34
+ * rejects those lossy values up front.
35
+ *
36
+ * @throws {TypeError} On circular references (mirroring `JSON.stringify`).
37
+ */
38
+ function stableStringify(value) {
39
+ return JSON.stringify(sortKeysDeep(value, /* @__PURE__ */ new WeakSet()));
40
+ }
41
+ function assertHashable(value, path, seen) {
42
+ if (value === null) return;
43
+ const type = typeof value;
44
+ if (type === "undefined") throw new TypeError(`canonicalStringify does not accept undefined values (at ${path})`);
45
+ if (type === "number" && !Number.isFinite(value)) throw new TypeError(`canonicalStringify does not accept non-finite numbers (at ${path}, value: ${String(value)})`);
46
+ if (type === "bigint" || type === "function" || type === "symbol") throw new TypeError(`canonicalStringify does not accept ${type} values (at ${path})`);
47
+ if (type !== "object") return;
48
+ if (value instanceof Date) {
49
+ if (!require_temporal_guards.isValidDate(value)) throw new TypeError(`canonicalStringify does not accept Invalid Date (at ${path})`);
50
+ return;
51
+ }
52
+ if (seen.has(value)) throw new TypeError(`canonicalStringify does not accept circular references (at ${path})`);
53
+ seen.add(value);
54
+ if (Array.isArray(value)) value.forEach((item, index) => {
55
+ assertHashable(item, `${path}[${index}]`, seen);
56
+ });
57
+ else for (const [key, nested] of Object.entries(value)) assertHashable(nested, `${path}.${key}`, seen);
58
+ seen.delete(value);
59
+ }
60
+ /**
61
+ * Strict counterpart to {@link stableStringify}: same deterministic output, but
62
+ * throws on any value `JSON.stringify` would drop or coerce (`undefined`,
63
+ * non-finite numbers, `bigint`, functions, symbols, `Invalid Date`) and on
64
+ * circular references. Use this whenever the string feeds a hash or integrity
65
+ * check, so distinct payloads cannot collide.
66
+ *
67
+ * @throws {TypeError} On lossy values or circular references.
68
+ */
69
+ function canonicalStringify(value) {
70
+ assertHashable(value, "$", /* @__PURE__ */ new WeakSet());
71
+ return stableStringify(value);
72
+ }
73
+ //#endregion
74
+ Object.defineProperty(exports, "canonicalStringify", {
75
+ enumerable: true,
76
+ get: function() {
77
+ return canonicalStringify;
78
+ }
79
+ });
80
+ Object.defineProperty(exports, "stableStringify", {
81
+ enumerable: true,
82
+ get: function() {
83
+ return stableStringify;
84
+ }
85
+ });
86
+
87
+ //# sourceMappingURL=stable-stringify.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stable-stringify.cjs","names":["isValidDate"],"sources":["../src/core/shared/stable-stringify.ts"],"sourcesContent":["import { isValidDate } from \"./temporal-guards.js\";\n\nconst CIRCULAR_STRUCTURE_MESSAGE =\n \"Cannot stably stringify a circular structure\";\n\n// `seen` holds the current traversal branch so true cycles are rejected while\n// repeated (acyclic) references are still serialized — matching JSON.stringify.\nfunction sortKeysDeep(value: unknown, seen: WeakSet<object>): unknown {\n if (Array.isArray(value)) {\n if (seen.has(value)) {\n throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);\n }\n seen.add(value);\n const mapped = value.map((item) => sortKeysDeep(item, seen));\n seen.delete(value);\n return mapped;\n }\n\n if (value instanceof Date) {\n return value;\n }\n\n if (value && typeof value === \"object\") {\n if (seen.has(value)) {\n throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);\n }\n seen.add(value);\n const record = value as Record<string, unknown>;\n const ordered = Object.create(null) as Record<string, unknown>;\n\n for (const key of Object.keys(record).sort()) {\n ordered[key] = sortKeysDeep(record[key], seen);\n }\n seen.delete(value);\n\n return ordered;\n }\n\n return value;\n}\n\n/**\n * Deterministic JSON string with object keys sorted recursively, so key order\n * does not affect the output.\n *\n * Follows `JSON.stringify` semantics for the values it serializes: `undefined`,\n * functions and symbols are dropped, non-finite numbers become `null`, `bigint`\n * throws, and `Map`/`Set` serialize as `{}`. Distinct payloads can therefore\n * collapse to the same string — this is fine for the structural-equality use it\n * serves (comparing two value objects), but **not** for hashing. For a\n * collision-resistant canonical form use {@link canonicalStringify}, which\n * rejects those lossy values up front.\n *\n * @throws {TypeError} On circular references (mirroring `JSON.stringify`).\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value, new WeakSet<object>()));\n}\n\n// Rejects every value `JSON.stringify` would silently drop or coerce, so\n// semantically different payloads can never collapse to the same canonical\n// string. Owned here (rather than in policies) so `payloadHash` and\n// `PolicyHashing` share one strict definition instead of each re-implementing\n// the deep guard.\nfunction assertHashable(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): void {\n if (value === null) {\n return;\n }\n\n const type = typeof value;\n\n if (type === \"undefined\") {\n throw new TypeError(\n `canonicalStringify does not accept undefined values (at ${path})`,\n );\n }\n\n if (type === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(\n `canonicalStringify does not accept non-finite numbers (at ${path}, value: ${String(value)})`,\n );\n }\n\n if (type === \"bigint\" || type === \"function\" || type === \"symbol\") {\n throw new TypeError(\n `canonicalStringify does not accept ${type} values (at ${path})`,\n );\n }\n\n if (type !== \"object\") {\n return;\n }\n\n if (value instanceof Date) {\n if (!isValidDate(value)) {\n throw new TypeError(\n `canonicalStringify does not accept Invalid Date (at ${path})`,\n );\n }\n return;\n }\n\n if (seen.has(value as object)) {\n throw new TypeError(\n `canonicalStringify does not accept circular references (at ${path})`,\n );\n }\n seen.add(value as object);\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n assertHashable(item, `${path}[${index}]`, seen);\n });\n } else {\n for (const [key, nested] of Object.entries(\n value as Record<string, unknown>,\n )) {\n assertHashable(nested, `${path}.${key}`, seen);\n }\n }\n\n seen.delete(value as object);\n}\n\n/**\n * Strict counterpart to {@link stableStringify}: same deterministic output, but\n * throws on any value `JSON.stringify` would drop or coerce (`undefined`,\n * non-finite numbers, `bigint`, functions, symbols, `Invalid Date`) and on\n * circular references. Use this whenever the string feeds a hash or integrity\n * check, so distinct payloads cannot collide.\n *\n * @throws {TypeError} On lossy values or circular references.\n */\nfunction canonicalStringify(value: unknown): string {\n assertHashable(value, \"$\", new WeakSet<object>());\n\n return stableStringify(value);\n}\n\nexport { assertHashable, canonicalStringify, stableStringify };\n"],"mappings":";;AAEA,MAAM,6BACF;AAIJ,SAAS,aAAa,OAAgB,MAAgC;CAClE,IAAI,MAAM,QAAQ,KAAK,GAAG;EACtB,IAAI,KAAK,IAAI,KAAK,GACd,MAAM,IAAI,UAAU,0BAA0B;EAElD,KAAK,IAAI,KAAK;EACd,MAAM,SAAS,MAAM,KAAK,SAAS,aAAa,MAAM,IAAI,CAAC;EAC3D,KAAK,OAAO,KAAK;EACjB,OAAO;CACX;CAEA,IAAI,iBAAiB,MACjB,OAAO;CAGX,IAAI,SAAS,OAAO,UAAU,UAAU;EACpC,IAAI,KAAK,IAAI,KAAK,GACd,MAAM,IAAI,UAAU,0BAA0B;EAElD,KAAK,IAAI,KAAK;EACd,MAAM,SAAS;EACf,MAAM,UAAU,OAAO,OAAO,IAAI;EAElC,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,EAAE,KAAK,GACvC,QAAQ,OAAO,aAAa,OAAO,MAAM,IAAI;EAEjD,KAAK,OAAO,KAAK;EAEjB,OAAO;CACX;CAEA,OAAO;AACX;;;;;;;;;;;;;;;AAgBA,SAAS,gBAAgB,OAAwB;CAC7C,OAAO,KAAK,UAAU,aAAa,uBAAO,IAAI,QAAgB,CAAC,CAAC;AACpE;AAOA,SAAS,eACL,OACA,MACA,MACI;CACJ,IAAI,UAAU,MACV;CAGJ,MAAM,OAAO,OAAO;CAEpB,IAAI,SAAS,aACT,MAAM,IAAI,UACN,2DAA2D,KAAK,EACpE;CAGJ,IAAI,SAAS,YAAY,CAAC,OAAO,SAAS,KAAK,GAC3C,MAAM,IAAI,UACN,6DAA6D,KAAK,WAAW,OAAO,KAAK,EAAE,EAC/F;CAGJ,IAAI,SAAS,YAAY,SAAS,cAAc,SAAS,UACrD,MAAM,IAAI,UACN,sCAAsC,KAAK,cAAc,KAAK,EAClE;CAGJ,IAAI,SAAS,UACT;CAGJ,IAAI,iBAAiB,MAAM;EACvB,IAAI,CAACA,wBAAAA,YAAY,KAAK,GAClB,MAAM,IAAI,UACN,uDAAuD,KAAK,EAChE;EAEJ;CACJ;CAEA,IAAI,KAAK,IAAI,KAAe,GACxB,MAAM,IAAI,UACN,8DAA8D,KAAK,EACvE;CAEJ,KAAK,IAAI,KAAe;CAExB,IAAI,MAAM,QAAQ,KAAK,GACnB,MAAM,SAAS,MAAM,UAAU;EAC3B,eAAe,MAAM,GAAG,KAAK,GAAG,MAAM,IAAI,IAAI;CAClD,CAAC;MAED,KAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAC/B,KACJ,GACI,eAAe,QAAQ,GAAG,KAAK,GAAG,OAAO,IAAI;CAIrD,KAAK,OAAO,KAAe;AAC/B;;;;;;;;;;AAWA,SAAS,mBAAmB,OAAwB;CAChD,eAAe,OAAO,qBAAK,IAAI,QAAgB,CAAC;CAEhD,OAAO,gBAAgB,KAAK;AAChC"}
@@ -0,0 +1,76 @@
1
+ import { r as isValidDate } from "./temporal-guards.js";
2
+ //#region src/core/shared/stable-stringify.ts
3
+ const CIRCULAR_STRUCTURE_MESSAGE = "Cannot stably stringify a circular structure";
4
+ function sortKeysDeep(value, seen) {
5
+ if (Array.isArray(value)) {
6
+ if (seen.has(value)) throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);
7
+ seen.add(value);
8
+ const mapped = value.map((item) => sortKeysDeep(item, seen));
9
+ seen.delete(value);
10
+ return mapped;
11
+ }
12
+ if (value instanceof Date) return value;
13
+ if (value && typeof value === "object") {
14
+ if (seen.has(value)) throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);
15
+ seen.add(value);
16
+ const record = value;
17
+ const ordered = Object.create(null);
18
+ for (const key of Object.keys(record).sort()) ordered[key] = sortKeysDeep(record[key], seen);
19
+ seen.delete(value);
20
+ return ordered;
21
+ }
22
+ return value;
23
+ }
24
+ /**
25
+ * Deterministic JSON string with object keys sorted recursively, so key order
26
+ * does not affect the output.
27
+ *
28
+ * Follows `JSON.stringify` semantics for the values it serializes: `undefined`,
29
+ * functions and symbols are dropped, non-finite numbers become `null`, `bigint`
30
+ * throws, and `Map`/`Set` serialize as `{}`. Distinct payloads can therefore
31
+ * collapse to the same string — this is fine for the structural-equality use it
32
+ * serves (comparing two value objects), but **not** for hashing. For a
33
+ * collision-resistant canonical form use {@link canonicalStringify}, which
34
+ * rejects those lossy values up front.
35
+ *
36
+ * @throws {TypeError} On circular references (mirroring `JSON.stringify`).
37
+ */
38
+ function stableStringify(value) {
39
+ return JSON.stringify(sortKeysDeep(value, /* @__PURE__ */ new WeakSet()));
40
+ }
41
+ function assertHashable(value, path, seen) {
42
+ if (value === null) return;
43
+ const type = typeof value;
44
+ if (type === "undefined") throw new TypeError(`canonicalStringify does not accept undefined values (at ${path})`);
45
+ if (type === "number" && !Number.isFinite(value)) throw new TypeError(`canonicalStringify does not accept non-finite numbers (at ${path}, value: ${String(value)})`);
46
+ if (type === "bigint" || type === "function" || type === "symbol") throw new TypeError(`canonicalStringify does not accept ${type} values (at ${path})`);
47
+ if (type !== "object") return;
48
+ if (value instanceof Date) {
49
+ if (!isValidDate(value)) throw new TypeError(`canonicalStringify does not accept Invalid Date (at ${path})`);
50
+ return;
51
+ }
52
+ if (seen.has(value)) throw new TypeError(`canonicalStringify does not accept circular references (at ${path})`);
53
+ seen.add(value);
54
+ if (Array.isArray(value)) value.forEach((item, index) => {
55
+ assertHashable(item, `${path}[${index}]`, seen);
56
+ });
57
+ else for (const [key, nested] of Object.entries(value)) assertHashable(nested, `${path}.${key}`, seen);
58
+ seen.delete(value);
59
+ }
60
+ /**
61
+ * Strict counterpart to {@link stableStringify}: same deterministic output, but
62
+ * throws on any value `JSON.stringify` would drop or coerce (`undefined`,
63
+ * non-finite numbers, `bigint`, functions, symbols, `Invalid Date`) and on
64
+ * circular references. Use this whenever the string feeds a hash or integrity
65
+ * check, so distinct payloads cannot collide.
66
+ *
67
+ * @throws {TypeError} On lossy values or circular references.
68
+ */
69
+ function canonicalStringify(value) {
70
+ assertHashable(value, "$", /* @__PURE__ */ new WeakSet());
71
+ return stableStringify(value);
72
+ }
73
+ //#endregion
74
+ export { stableStringify as n, canonicalStringify as t };
75
+
76
+ //# sourceMappingURL=stable-stringify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stable-stringify.js","names":[],"sources":["../src/core/shared/stable-stringify.ts"],"sourcesContent":["import { isValidDate } from \"./temporal-guards.js\";\n\nconst CIRCULAR_STRUCTURE_MESSAGE =\n \"Cannot stably stringify a circular structure\";\n\n// `seen` holds the current traversal branch so true cycles are rejected while\n// repeated (acyclic) references are still serialized — matching JSON.stringify.\nfunction sortKeysDeep(value: unknown, seen: WeakSet<object>): unknown {\n if (Array.isArray(value)) {\n if (seen.has(value)) {\n throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);\n }\n seen.add(value);\n const mapped = value.map((item) => sortKeysDeep(item, seen));\n seen.delete(value);\n return mapped;\n }\n\n if (value instanceof Date) {\n return value;\n }\n\n if (value && typeof value === \"object\") {\n if (seen.has(value)) {\n throw new TypeError(CIRCULAR_STRUCTURE_MESSAGE);\n }\n seen.add(value);\n const record = value as Record<string, unknown>;\n const ordered = Object.create(null) as Record<string, unknown>;\n\n for (const key of Object.keys(record).sort()) {\n ordered[key] = sortKeysDeep(record[key], seen);\n }\n seen.delete(value);\n\n return ordered;\n }\n\n return value;\n}\n\n/**\n * Deterministic JSON string with object keys sorted recursively, so key order\n * does not affect the output.\n *\n * Follows `JSON.stringify` semantics for the values it serializes: `undefined`,\n * functions and symbols are dropped, non-finite numbers become `null`, `bigint`\n * throws, and `Map`/`Set` serialize as `{}`. Distinct payloads can therefore\n * collapse to the same string — this is fine for the structural-equality use it\n * serves (comparing two value objects), but **not** for hashing. For a\n * collision-resistant canonical form use {@link canonicalStringify}, which\n * rejects those lossy values up front.\n *\n * @throws {TypeError} On circular references (mirroring `JSON.stringify`).\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value, new WeakSet<object>()));\n}\n\n// Rejects every value `JSON.stringify` would silently drop or coerce, so\n// semantically different payloads can never collapse to the same canonical\n// string. Owned here (rather than in policies) so `payloadHash` and\n// `PolicyHashing` share one strict definition instead of each re-implementing\n// the deep guard.\nfunction assertHashable(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): void {\n if (value === null) {\n return;\n }\n\n const type = typeof value;\n\n if (type === \"undefined\") {\n throw new TypeError(\n `canonicalStringify does not accept undefined values (at ${path})`,\n );\n }\n\n if (type === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(\n `canonicalStringify does not accept non-finite numbers (at ${path}, value: ${String(value)})`,\n );\n }\n\n if (type === \"bigint\" || type === \"function\" || type === \"symbol\") {\n throw new TypeError(\n `canonicalStringify does not accept ${type} values (at ${path})`,\n );\n }\n\n if (type !== \"object\") {\n return;\n }\n\n if (value instanceof Date) {\n if (!isValidDate(value)) {\n throw new TypeError(\n `canonicalStringify does not accept Invalid Date (at ${path})`,\n );\n }\n return;\n }\n\n if (seen.has(value as object)) {\n throw new TypeError(\n `canonicalStringify does not accept circular references (at ${path})`,\n );\n }\n seen.add(value as object);\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n assertHashable(item, `${path}[${index}]`, seen);\n });\n } else {\n for (const [key, nested] of Object.entries(\n value as Record<string, unknown>,\n )) {\n assertHashable(nested, `${path}.${key}`, seen);\n }\n }\n\n seen.delete(value as object);\n}\n\n/**\n * Strict counterpart to {@link stableStringify}: same deterministic output, but\n * throws on any value `JSON.stringify` would drop or coerce (`undefined`,\n * non-finite numbers, `bigint`, functions, symbols, `Invalid Date`) and on\n * circular references. Use this whenever the string feeds a hash or integrity\n * check, so distinct payloads cannot collide.\n *\n * @throws {TypeError} On lossy values or circular references.\n */\nfunction canonicalStringify(value: unknown): string {\n assertHashable(value, \"$\", new WeakSet<object>());\n\n return stableStringify(value);\n}\n\nexport { assertHashable, canonicalStringify, stableStringify };\n"],"mappings":";;AAEA,MAAM,6BACF;AAIJ,SAAS,aAAa,OAAgB,MAAgC;CAClE,IAAI,MAAM,QAAQ,KAAK,GAAG;EACtB,IAAI,KAAK,IAAI,KAAK,GACd,MAAM,IAAI,UAAU,0BAA0B;EAElD,KAAK,IAAI,KAAK;EACd,MAAM,SAAS,MAAM,KAAK,SAAS,aAAa,MAAM,IAAI,CAAC;EAC3D,KAAK,OAAO,KAAK;EACjB,OAAO;CACX;CAEA,IAAI,iBAAiB,MACjB,OAAO;CAGX,IAAI,SAAS,OAAO,UAAU,UAAU;EACpC,IAAI,KAAK,IAAI,KAAK,GACd,MAAM,IAAI,UAAU,0BAA0B;EAElD,KAAK,IAAI,KAAK;EACd,MAAM,SAAS;EACf,MAAM,UAAU,OAAO,OAAO,IAAI;EAElC,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,EAAE,KAAK,GACvC,QAAQ,OAAO,aAAa,OAAO,MAAM,IAAI;EAEjD,KAAK,OAAO,KAAK;EAEjB,OAAO;CACX;CAEA,OAAO;AACX;;;;;;;;;;;;;;;AAgBA,SAAS,gBAAgB,OAAwB;CAC7C,OAAO,KAAK,UAAU,aAAa,uBAAO,IAAI,QAAgB,CAAC,CAAC;AACpE;AAOA,SAAS,eACL,OACA,MACA,MACI;CACJ,IAAI,UAAU,MACV;CAGJ,MAAM,OAAO,OAAO;CAEpB,IAAI,SAAS,aACT,MAAM,IAAI,UACN,2DAA2D,KAAK,EACpE;CAGJ,IAAI,SAAS,YAAY,CAAC,OAAO,SAAS,KAAK,GAC3C,MAAM,IAAI,UACN,6DAA6D,KAAK,WAAW,OAAO,KAAK,EAAE,EAC/F;CAGJ,IAAI,SAAS,YAAY,SAAS,cAAc,SAAS,UACrD,MAAM,IAAI,UACN,sCAAsC,KAAK,cAAc,KAAK,EAClE;CAGJ,IAAI,SAAS,UACT;CAGJ,IAAI,iBAAiB,MAAM;EACvB,IAAI,CAAC,YAAY,KAAK,GAClB,MAAM,IAAI,UACN,uDAAuD,KAAK,EAChE;EAEJ;CACJ;CAEA,IAAI,KAAK,IAAI,KAAe,GACxB,MAAM,IAAI,UACN,8DAA8D,KAAK,EACvE;CAEJ,KAAK,IAAI,KAAe;CAExB,IAAI,MAAM,QAAQ,KAAK,GACnB,MAAM,SAAS,MAAM,UAAU;EAC3B,eAAe,MAAM,GAAG,KAAK,GAAG,MAAM,IAAI,IAAI;CAClD,CAAC;MAED,KAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAC/B,KACJ,GACI,eAAe,QAAQ,GAAG,KAAK,GAAG,OAAO,IAAI;CAIrD,KAAK,OAAO,KAAe;AAC/B;;;;;;;;;;AAWA,SAAS,mBAAmB,OAAwB;CAChD,eAAe,OAAO,qBAAK,IAAI,QAAgB,CAAC;CAEhD,OAAO,gBAAgB,KAAK;AAChC"}
@@ -0,0 +1,87 @@
1
+ import { t as DeepReadonly } from "./immutable.cjs";
2
+
3
+ //#region src/core/domain/temporal/transaction-time.d.ts
4
+
5
+ /**
6
+ * Represents transaction time (Transaction Time).
7
+ * Defines when the system learned about or recorded a piece of information.
8
+ * Useful for auditing and reconstructing system state at a specific past moment.
9
+ *
10
+ * The window is half-open — `recordedAt` inclusive, `supersededAt` exclusive —
11
+ * and strictly non-empty: `supersededAt` must be later than `recordedAt`, so a
12
+ * record superseded in the same instant it was written is not representable.
13
+ *
14
+ * One caveat mirrors {@link ValueObject}: `createTransactionTime` clones the
15
+ * input dates (no aliasing) but the inner `Date`s are NOT frozen —
16
+ * `Object.freeze` cannot block `setTime`/`setFullYear`, so a caller can still
17
+ * mutate `recordedAt` in place and corrupt the audit record after creation.
18
+ * `readonly` only prevents reassignment. Treat the dates as read-only, or keep
19
+ * instants as ISO/epoch in your own state when that guarantee matters.
20
+ */
21
+ interface TransactionTime {
22
+ /** When the information was first recorded in the system. */
23
+ readonly recordedAt: Date;
24
+ /** When this information was superseded or invalidated by a newer version. */
25
+ readonly supersededAt?: Date;
26
+ }
27
+ type CreateTransactionTimeInput = TransactionTime;
28
+ declare function assertTransactionTime(txTime: TransactionTime, fieldName?: string): void;
29
+ declare function createTransactionTime(input: CreateTransactionTimeInput): TransactionTime;
30
+ //#endregion
31
+ //#region src/core/domain/temporal/valid-time.d.ts
32
+ /**
33
+ * Represents business time (Valid Time).
34
+ * Defines when a piece of information is considered true or in effect in the real world.
35
+ *
36
+ * The window is half-open — `from` inclusive, `to` exclusive — and strictly
37
+ * non-empty: `to` must be later than `from`, so a zero-duration range `[t, t)`
38
+ * is deliberately not representable. Model an instantaneous event as an open
39
+ * range closed by the next fact, not as an empty window.
40
+ *
41
+ * One caveat mirrors {@link ValueObject}: `createValidTime` clones the input
42
+ * dates (no aliasing) but the inner `Date`s are NOT frozen — `Object.freeze`
43
+ * cannot block `setTime`/`setFullYear`, so a caller can still mutate `from`
44
+ * in place and corrupt the range after creation. `readonly` only prevents
45
+ * reassignment. Treat the dates as read-only, or keep instants as ISO/epoch in
46
+ * your own state when that guarantee matters.
47
+ */
48
+ interface ValidTime {
49
+ /** Start of the validity window (inclusive). */
50
+ readonly from: Date;
51
+ /** End of the validity window (exclusive). When absent, the information is still in effect. */
52
+ readonly to?: Date;
53
+ }
54
+ type CreateValidTimeInput = ValidTime;
55
+ declare function assertValidTime(validTime: ValidTime, fieldName?: string): void;
56
+ declare function createValidTime(input: CreateValidTimeInput): ValidTime;
57
+ //#endregion
58
+ //#region src/core/domain/temporal/temporal-snapshot.d.ts
59
+ /**
60
+ * Pairs a domain datum with its time dimensions (Business and Transaction).
61
+ * It is the representation of an entry in the append-only (historical) table.
62
+ *
63
+ * `data` must be plain, structured-cloneable state — the primitive shape of an
64
+ * aggregate, not the aggregate itself. `createTemporalSnapshot` deep-clones it
65
+ * via `structuredClone`: functions and symbols inside `data` throw an
66
+ * `InvariantViolationException`, and class instances (a `ValueObject`, an
67
+ * `Entity`) are NOT rejected — they are silently flattened to plain objects,
68
+ * losing their prototype (and with it `equals`/`toPrimitive`). Project rich
69
+ * objects down first, e.g. with `toPrimitive()`.
70
+ */
71
+ interface TemporalSnapshot<T> {
72
+ /** The data or state captured by the snapshot. */
73
+ readonly data: DeepReadonly<T>;
74
+ /** Period during which this datum was valid in the real world. */
75
+ readonly validTime: ValidTime;
76
+ /** Period during which this record was the state known to the system. */
77
+ readonly txTime: TransactionTime;
78
+ }
79
+ interface CreateTemporalSnapshotInput<T> {
80
+ readonly data: T;
81
+ readonly validTime: CreateValidTimeInput;
82
+ readonly txTime: CreateTransactionTimeInput;
83
+ }
84
+ declare function createTemporalSnapshot<T>(input: CreateTemporalSnapshotInput<T>): TemporalSnapshot<T>;
85
+ //#endregion
86
+ export { ValidTime as a, CreateTransactionTimeInput as c, createTransactionTime as d, CreateValidTimeInput as i, TransactionTime as l, TemporalSnapshot as n, assertValidTime as o, createTemporalSnapshot as r, createValidTime as s, CreateTemporalSnapshotInput as t, assertTransactionTime as u };
87
+ //# sourceMappingURL=temporal-snapshot.d.cts.map
@@ -0,0 +1,87 @@
1
+ import { t as DeepReadonly } from "./immutable.js";
2
+
3
+ //#region src/core/domain/temporal/transaction-time.d.ts
4
+
5
+ /**
6
+ * Represents transaction time (Transaction Time).
7
+ * Defines when the system learned about or recorded a piece of information.
8
+ * Useful for auditing and reconstructing system state at a specific past moment.
9
+ *
10
+ * The window is half-open — `recordedAt` inclusive, `supersededAt` exclusive —
11
+ * and strictly non-empty: `supersededAt` must be later than `recordedAt`, so a
12
+ * record superseded in the same instant it was written is not representable.
13
+ *
14
+ * One caveat mirrors {@link ValueObject}: `createTransactionTime` clones the
15
+ * input dates (no aliasing) but the inner `Date`s are NOT frozen —
16
+ * `Object.freeze` cannot block `setTime`/`setFullYear`, so a caller can still
17
+ * mutate `recordedAt` in place and corrupt the audit record after creation.
18
+ * `readonly` only prevents reassignment. Treat the dates as read-only, or keep
19
+ * instants as ISO/epoch in your own state when that guarantee matters.
20
+ */
21
+ interface TransactionTime {
22
+ /** When the information was first recorded in the system. */
23
+ readonly recordedAt: Date;
24
+ /** When this information was superseded or invalidated by a newer version. */
25
+ readonly supersededAt?: Date;
26
+ }
27
+ type CreateTransactionTimeInput = TransactionTime;
28
+ declare function assertTransactionTime(txTime: TransactionTime, fieldName?: string): void;
29
+ declare function createTransactionTime(input: CreateTransactionTimeInput): TransactionTime;
30
+ //#endregion
31
+ //#region src/core/domain/temporal/valid-time.d.ts
32
+ /**
33
+ * Represents business time (Valid Time).
34
+ * Defines when a piece of information is considered true or in effect in the real world.
35
+ *
36
+ * The window is half-open — `from` inclusive, `to` exclusive — and strictly
37
+ * non-empty: `to` must be later than `from`, so a zero-duration range `[t, t)`
38
+ * is deliberately not representable. Model an instantaneous event as an open
39
+ * range closed by the next fact, not as an empty window.
40
+ *
41
+ * One caveat mirrors {@link ValueObject}: `createValidTime` clones the input
42
+ * dates (no aliasing) but the inner `Date`s are NOT frozen — `Object.freeze`
43
+ * cannot block `setTime`/`setFullYear`, so a caller can still mutate `from`
44
+ * in place and corrupt the range after creation. `readonly` only prevents
45
+ * reassignment. Treat the dates as read-only, or keep instants as ISO/epoch in
46
+ * your own state when that guarantee matters.
47
+ */
48
+ interface ValidTime {
49
+ /** Start of the validity window (inclusive). */
50
+ readonly from: Date;
51
+ /** End of the validity window (exclusive). When absent, the information is still in effect. */
52
+ readonly to?: Date;
53
+ }
54
+ type CreateValidTimeInput = ValidTime;
55
+ declare function assertValidTime(validTime: ValidTime, fieldName?: string): void;
56
+ declare function createValidTime(input: CreateValidTimeInput): ValidTime;
57
+ //#endregion
58
+ //#region src/core/domain/temporal/temporal-snapshot.d.ts
59
+ /**
60
+ * Pairs a domain datum with its time dimensions (Business and Transaction).
61
+ * It is the representation of an entry in the append-only (historical) table.
62
+ *
63
+ * `data` must be plain, structured-cloneable state — the primitive shape of an
64
+ * aggregate, not the aggregate itself. `createTemporalSnapshot` deep-clones it
65
+ * via `structuredClone`: functions and symbols inside `data` throw an
66
+ * `InvariantViolationException`, and class instances (a `ValueObject`, an
67
+ * `Entity`) are NOT rejected — they are silently flattened to plain objects,
68
+ * losing their prototype (and with it `equals`/`toPrimitive`). Project rich
69
+ * objects down first, e.g. with `toPrimitive()`.
70
+ */
71
+ interface TemporalSnapshot<T> {
72
+ /** The data or state captured by the snapshot. */
73
+ readonly data: DeepReadonly<T>;
74
+ /** Period during which this datum was valid in the real world. */
75
+ readonly validTime: ValidTime;
76
+ /** Period during which this record was the state known to the system. */
77
+ readonly txTime: TransactionTime;
78
+ }
79
+ interface CreateTemporalSnapshotInput<T> {
80
+ readonly data: T;
81
+ readonly validTime: CreateValidTimeInput;
82
+ readonly txTime: CreateTransactionTimeInput;
83
+ }
84
+ declare function createTemporalSnapshot<T>(input: CreateTemporalSnapshotInput<T>): TemporalSnapshot<T>;
85
+ //#endregion
86
+ export { ValidTime as a, CreateTransactionTimeInput as c, createTransactionTime as d, CreateValidTimeInput as i, TransactionTime as l, TemporalSnapshot as n, assertValidTime as o, createTemporalSnapshot as r, createValidTime as s, CreateTemporalSnapshotInput as t, assertTransactionTime as u };
87
+ //# sourceMappingURL=temporal-snapshot.d.ts.map
@@ -1,8 +1,128 @@
1
+ const require_app_error = require("./app-error.cjs");
1
2
  const require_not_found_error = require("./not-found-error.cjs");
3
+ const require_temporal_guards = require("./temporal-guards.cjs");
2
4
  const require_unexpected_error = require("./unexpected-error.cjs");
3
5
  const require_immutable = require("./immutable.cjs");
4
- const require_use_case = require("./use-case.cjs");
5
- const require_temporal_guards = require("./temporal-guards.cjs");
6
+ const require_decorate = require("./decorate.cjs");
7
+ //#region src/core/application/use-case.ts
8
+ const EXECUTION_COUNTER = "use_case.executions";
9
+ const DURATION_HISTOGRAM = "use_case.duration_ms";
10
+ let UseCase = class UseCase {
11
+ get contractVersion() {
12
+ return this.constructor.CONTRACT_VERSION;
13
+ }
14
+ /**
15
+ * Runs the use case.
16
+ *
17
+ * `run()` is the single seam every use case crosses, so it is where
18
+ * cross-cutting instrumentation lives. When {@link observability} exposes
19
+ * any adapter, the call to `execute()` is wrapped with tracing, metrics and
20
+ * failure logging; otherwise it delegates directly with no overhead.
21
+ *
22
+ * Observability is strictly side-effecting: a misbehaving adapter never
23
+ * changes the business result nor masks a thrown error — its own failures
24
+ * are swallowed.
25
+ */
26
+ async run(input) {
27
+ const observability = this.observability();
28
+ if (!observability.logger && !observability.metrics && !observability.tracer) return await this.execute(input);
29
+ return await this.runInstrumented(input, observability);
30
+ }
31
+ /**
32
+ * Adapters used to instrument {@link run}. Override to opt a use case into
33
+ * tracing/metrics/logging. Returns an empty object by default, which keeps
34
+ * the plain delegating behavior.
35
+ */
36
+ observability() {
37
+ return {};
38
+ }
39
+ /**
40
+ * Stable identity used for span names and metric labels. Defaults to the
41
+ * runtime class name; override when bundling/minification would otherwise
42
+ * erase a meaningful name.
43
+ */
44
+ get useCaseName() {
45
+ return this.constructor.name;
46
+ }
47
+ /**
48
+ * Extra attributes stamped onto the span and every metric emitted for this
49
+ * execution. Override to attach stable, **low-cardinality** dimensions
50
+ * (e.g. `Command` adds `requested_by.kind`). Keep values bounded — they
51
+ * become metric label values, so a user id or free-form string here would
52
+ * explode the metric's cardinality. Defaults to none.
53
+ */
54
+ spanAttributes(_input) {
55
+ return {};
56
+ }
57
+ async runInstrumented(input, observability) {
58
+ const { logger, metrics, tracer } = observability;
59
+ const name = this.useCaseName;
60
+ const attributes = safely(() => this.spanAttributes(input)) ?? {};
61
+ const span = safely(() => tracer?.startSpan(name, {
62
+ "use_case.name": name,
63
+ ...attributes
64
+ }));
65
+ const startedAt = performance.now();
66
+ let outcome = "exception";
67
+ try {
68
+ const output = await this.execute(input);
69
+ outcome = output.isOk() ? "ok" : "error";
70
+ if (outcome === "error") {
71
+ const code = businessErrorCode(output);
72
+ safely(() => logger?.warn(`${name} returned a business error`, {
73
+ useCase: name,
74
+ ...code ? { code } : {}
75
+ }));
76
+ }
77
+ safely(() => span?.setAttribute("use_case.outcome", outcome));
78
+ safely(() => metrics?.counter(EXECUTION_COUNTER, 1, {
79
+ useCase: name,
80
+ outcome,
81
+ ...attributes
82
+ }));
83
+ return output;
84
+ } catch (error) {
85
+ safely(() => logger?.error(`${name} threw an unexpected error`, { useCase: name }));
86
+ safely(() => span?.setAttribute("use_case.outcome", "exception"));
87
+ safely(() => span?.recordException(error));
88
+ safely(() => metrics?.counter(EXECUTION_COUNTER, 1, {
89
+ useCase: name,
90
+ outcome: "exception",
91
+ ...attributes
92
+ }));
93
+ throw error;
94
+ } finally {
95
+ safely(() => metrics?.histogram(DURATION_HISTOGRAM, performance.now() - startedAt, {
96
+ useCase: name,
97
+ outcome,
98
+ ...attributes
99
+ }));
100
+ safely(() => span?.end());
101
+ }
102
+ }
103
+ };
104
+ UseCase = require_decorate.__decorate([require_immutable.version("1.0")], UseCase);
105
+ /**
106
+ * Pulls the stable `code` off a business-error `Result` for logging. Returns
107
+ * `undefined` when the error is not an {@link AppError} — the code is safe to
108
+ * log (it's the public contract), unlike the message which may carry PII.
109
+ */
110
+ function businessErrorCode(output) {
111
+ const error = output.errorOrNull();
112
+ return error instanceof require_app_error.AppError ? error.code : void 0;
113
+ }
114
+ /**
115
+ * Invokes an observability side effect, isolating any adapter failure so it
116
+ * cannot alter the use case outcome.
117
+ */
118
+ function safely(effect) {
119
+ try {
120
+ return effect();
121
+ } catch {
122
+ return;
123
+ }
124
+ }
125
+ //#endregion
6
126
  //#region src/core/application/commands/command.ts
7
127
  /**
8
128
  * Base for use cases that **mutate state** (writes), following CQS.
@@ -14,8 +134,18 @@ const require_temporal_guards = require("./temporal-guards.cjs");
14
134
  * The Command/Query distinction is semantic: the type declares the intent
15
135
  * before any implementation exists, guiding code review and API contracts.
16
136
  */
17
- let Command = class Command extends require_use_case.UseCase {};
18
- Command = require_immutable.__decorate([require_immutable.version("1.0")], Command);
137
+ let Command = class Command extends UseCase {
138
+ /**
139
+ * Surfaces the actor's *kind* (`"user"` / `"system"`) on the span and
140
+ * metrics so a write can be sliced by origin. Only the low-cardinality
141
+ * `kind` is emitted — never the raw id, which would blow up label
142
+ * cardinality and could leak a user identifier into metrics.
143
+ */
144
+ spanAttributes(input) {
145
+ return { "requested_by.kind": input.requestedBy.kind };
146
+ }
147
+ };
148
+ Command = require_decorate.__decorate([require_immutable.version("1.0")], Command);
19
149
  //#endregion
20
150
  //#region src/core/application/policy-error-mapper.ts
21
151
  function mapPolicyEvaluationError(err) {
@@ -36,11 +166,14 @@ function mapPolicyEvaluationError(err) {
36
166
  policyKind: err.policyKind,
37
167
  payloadSchemaVersion: err.payloadSchemaVersion
38
168
  }, { cause: err.cause });
39
- case "ENGINE_FAILURE": return new require_unexpected_error.UnexpectedError(err.message, err.cause, { metadata: {
40
- policyKey: err.policyKey,
41
- engine: err.engine,
42
- engineVersion: err.engineVersion
43
- } });
169
+ case "ENGINE_FAILURE": return new require_unexpected_error.UnexpectedError(err.message, err.cause, {
170
+ publicMessage: "Policy evaluation failed unexpectedly.",
171
+ metadata: {
172
+ policyKey: err.policyKey,
173
+ engine: err.engine,
174
+ engineVersion: err.engineVersion
175
+ }
176
+ });
44
177
  }
45
178
  }
46
179
  //#endregion
@@ -58,12 +191,17 @@ function mapPolicyEvaluationError(err) {
58
191
  * A Query must never mutate persisted data — its execution must be idempotent
59
192
  * and safe to call multiple times with the same input.
60
193
  */
61
- let Query = class Query extends require_use_case.UseCase {
194
+ let Query = class Query extends UseCase {
195
+ /**
196
+ * Declares how infrastructure should cache this query's result. Public so
197
+ * a caching adapter can actually read it off the instance; overrides must
198
+ * stay public.
199
+ */
62
200
  cacheStrategy() {
63
201
  return { kind: "NO_CACHE" };
64
202
  }
65
203
  };
66
- Query = require_immutable.__decorate([require_immutable.version("1.0")], Query);
204
+ Query = require_decorate.__decorate([require_immutable.version("1.0")], Query);
67
205
  //#endregion
68
206
  //#region src/core/application/temporal/temporal-context.ts
69
207
  function assertTemporalContext(temporalContext, fieldName = "temporalContext") {
@@ -84,20 +222,34 @@ function createTemporalContext(input = {}) {
84
222
  }
85
223
  //#endregion
86
224
  //#region src/core/application/temporal/temporal-use-case.ts
87
- var TemporalUseCase = class extends require_use_case.UseCase {
225
+ let TemporalUseCase = class TemporalUseCase extends UseCase {
88
226
  resolveTemporalContext(input) {
89
227
  return createTemporalContext(input.temporalContext);
90
228
  }
229
+ /**
230
+ * Enriches a policy `ContextSeed` with `fields.now`, taken from the
231
+ * context's `requestedAt` (wall-clock time of the request).
232
+ *
233
+ * NOTE: this injects **only** `now` (from `requestedAt`) — it does *not*
234
+ * propagate `temporalContext.asOf`. Policy evaluation derives its own
235
+ * `asOf` from whichever seed field the policy's `asOfSource` points at
236
+ * (via `fields.now` by default). So a retroactive use case (an `asOf` in
237
+ * the past) will still evaluate policies at the *current* time unless the
238
+ * author maps `temporalContext.asOf` onto that seed field explicitly. Do
239
+ * that mapping in the use case when back-dated evaluation is intended.
240
+ */
91
241
  buildPolicySeed(seed, temporalContext) {
242
+ const fields = Object.freeze({
243
+ ...seed.fields,
244
+ now: new Date(temporalContext.requestedAt.getTime())
245
+ });
92
246
  return Object.freeze({
93
247
  ...seed,
94
- fields: {
95
- ...seed.fields,
96
- now: new Date(temporalContext.requestedAt.getTime())
97
- }
248
+ fields
98
249
  });
99
250
  }
100
251
  };
252
+ TemporalUseCase = require_decorate.__decorate([require_immutable.version("1.0")], TemporalUseCase);
101
253
  //#endregion
102
254
  Object.defineProperty(exports, "Command", {
103
255
  enumerable: true,
@@ -117,6 +269,12 @@ Object.defineProperty(exports, "TemporalUseCase", {
117
269
  return TemporalUseCase;
118
270
  }
119
271
  });
272
+ Object.defineProperty(exports, "UseCase", {
273
+ enumerable: true,
274
+ get: function() {
275
+ return UseCase;
276
+ }
277
+ });
120
278
  Object.defineProperty(exports, "assertTemporalContext", {
121
279
  enumerable: true,
122
280
  get: function() {