@bett3r-dev/pv3 1.0.0 → 1.1.7

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 (648) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/build/adapters/cache/memory/index.d.ts.map +1 -1
  3. package/build/adapters/cache/memory/index.js +93 -20
  4. package/build/adapters/cache/memory/index.js.map +1 -1
  5. package/build/adapters/cache/memory/index.test.d.ts +2 -0
  6. package/build/adapters/cache/memory/index.test.d.ts.map +1 -0
  7. package/build/adapters/cache/memory/index.test.js +98 -0
  8. package/build/adapters/cache/memory/index.test.js.map +1 -0
  9. package/build/adapters/configuration/dotEnv.d.ts.map +1 -1
  10. package/build/adapters/configuration/dotEnv.js.map +1 -1
  11. package/build/adapters/database/memory/index.d.ts +5 -1
  12. package/build/adapters/database/memory/index.d.ts.map +1 -1
  13. package/build/adapters/database/memory/index.js +336 -44
  14. package/build/adapters/database/memory/index.js.map +1 -1
  15. package/build/adapters/database/memory/index.test.d.ts +2 -0
  16. package/build/adapters/database/memory/index.test.d.ts.map +1 -0
  17. package/build/adapters/database/memory/index.test.js +167 -0
  18. package/build/adapters/database/memory/index.test.js.map +1 -0
  19. package/build/adapters/database/memory/pagingCursorZero.test.d.ts +2 -0
  20. package/build/adapters/database/memory/pagingCursorZero.test.d.ts.map +1 -0
  21. package/build/adapters/database/memory/pagingCursorZero.test.js +60 -0
  22. package/build/adapters/database/memory/pagingCursorZero.test.js.map +1 -0
  23. package/build/adapters/database/memory/pagingVanishedCursor.test.d.ts +2 -0
  24. package/build/adapters/database/memory/pagingVanishedCursor.test.d.ts.map +1 -0
  25. package/build/adapters/database/memory/pagingVanishedCursor.test.js +72 -0
  26. package/build/adapters/database/memory/pagingVanishedCursor.test.js.map +1 -0
  27. package/build/adapters/endpoints/addAuthUser/index.d.ts +6 -4
  28. package/build/adapters/endpoints/addAuthUser/index.d.ts.map +1 -1
  29. package/build/adapters/endpoints/addAuthUser/index.js +12 -31
  30. package/build/adapters/endpoints/addAuthUser/index.js.map +1 -1
  31. package/build/adapters/endpoints/addDevAuthUser/index.d.ts +32 -0
  32. package/build/adapters/endpoints/addDevAuthUser/index.d.ts.map +1 -0
  33. package/build/adapters/endpoints/addDevAuthUser/index.js +39 -0
  34. package/build/adapters/endpoints/addDevAuthUser/index.js.map +1 -0
  35. package/build/adapters/endpoints/asyncLocalStorage/__tests__/asyncLocalStorage.test.d.ts +2 -0
  36. package/build/adapters/endpoints/asyncLocalStorage/__tests__/asyncLocalStorage.test.d.ts.map +1 -0
  37. package/build/adapters/endpoints/asyncLocalStorage/__tests__/asyncLocalStorage.test.js +97 -0
  38. package/build/adapters/endpoints/asyncLocalStorage/__tests__/asyncLocalStorage.test.js.map +1 -0
  39. package/build/adapters/endpoints/asyncLocalStorage/index.d.ts +22 -0
  40. package/build/adapters/endpoints/asyncLocalStorage/index.d.ts.map +1 -0
  41. package/build/adapters/endpoints/asyncLocalStorage/index.js +62 -0
  42. package/build/adapters/endpoints/asyncLocalStorage/index.js.map +1 -0
  43. package/build/adapters/endpoints/endpointValidation/__tests__/endpointValidation.test.d.ts +2 -0
  44. package/build/adapters/endpoints/endpointValidation/__tests__/endpointValidation.test.d.ts.map +1 -0
  45. package/build/adapters/endpoints/endpointValidation/__tests__/endpointValidation.test.js +98 -0
  46. package/build/adapters/endpoints/endpointValidation/__tests__/endpointValidation.test.js.map +1 -0
  47. package/build/adapters/endpoints/endpointValidation/index.d.ts +2 -2
  48. package/build/adapters/endpoints/endpointValidation/index.d.ts.map +1 -1
  49. package/build/adapters/endpoints/endpointValidation/index.js +19 -9
  50. package/build/adapters/endpoints/endpointValidation/index.js.map +1 -1
  51. package/build/adapters/endpoints/genericMiddleware/index.d.ts +23 -0
  52. package/build/adapters/endpoints/genericMiddleware/index.d.ts.map +1 -0
  53. package/build/adapters/endpoints/genericMiddleware/index.js +30 -0
  54. package/build/adapters/endpoints/genericMiddleware/index.js.map +1 -0
  55. package/build/adapters/endpoints/httpMethodOverride/index.d.ts +8 -0
  56. package/build/adapters/endpoints/httpMethodOverride/index.d.ts.map +1 -0
  57. package/build/adapters/endpoints/httpMethodOverride/index.js +44 -0
  58. package/build/adapters/endpoints/httpMethodOverride/index.js.map +1 -0
  59. package/build/adapters/endpoints/index.d.ts +5 -0
  60. package/build/adapters/endpoints/index.d.ts.map +1 -1
  61. package/build/adapters/endpoints/index.js +5 -1
  62. package/build/adapters/endpoints/index.js.map +1 -1
  63. package/build/adapters/endpoints/localAuthorization/index.d.ts +1 -0
  64. package/build/adapters/endpoints/localAuthorization/index.js +2 -0
  65. package/build/adapters/endpoints/localAuthorization/index.js.map +1 -1
  66. package/build/adapters/endpoints/mapQueryFromHeaders/index.d.ts +8 -0
  67. package/build/adapters/endpoints/mapQueryFromHeaders/index.d.ts.map +1 -0
  68. package/build/adapters/endpoints/mapQueryFromHeaders/index.js +36 -0
  69. package/build/adapters/endpoints/mapQueryFromHeaders/index.js.map +1 -0
  70. package/build/adapters/endpoints/tcpConsumer/index.d.ts.map +1 -1
  71. package/build/adapters/endpoints/tcpConsumer/index.js +8 -7
  72. package/build/adapters/endpoints/tcpConsumer/index.js.map +1 -1
  73. package/build/adapters/endpoints/userSession/__tests__/userSession.test.d.ts +2 -0
  74. package/build/adapters/endpoints/userSession/__tests__/userSession.test.d.ts.map +1 -0
  75. package/build/adapters/endpoints/userSession/__tests__/userSession.test.js +175 -0
  76. package/build/adapters/endpoints/userSession/__tests__/userSession.test.js.map +1 -0
  77. package/build/adapters/endpoints/userSession/index.d.ts +2 -2
  78. package/build/adapters/endpoints/userSession/index.d.ts.map +1 -1
  79. package/build/adapters/endpoints/userSession/index.js +36 -2
  80. package/build/adapters/endpoints/userSession/index.js.map +1 -1
  81. package/build/adapters/eventstore/database.d.ts.map +1 -1
  82. package/build/adapters/eventstore/database.js +261 -58
  83. package/build/adapters/eventstore/database.js.map +1 -1
  84. package/build/adapters/eventstore/database.test.d.ts +2 -0
  85. package/build/adapters/eventstore/database.test.d.ts.map +1 -0
  86. package/build/adapters/eventstore/database.test.js +123 -0
  87. package/build/adapters/eventstore/database.test.js.map +1 -0
  88. package/build/adapters/infrastructure/local/index.d.ts +2 -2
  89. package/build/adapters/infrastructure/local/index.d.ts.map +1 -1
  90. package/build/adapters/infrastructure/local/index.js +3 -3
  91. package/build/adapters/infrastructure/local/index.js.map +1 -1
  92. package/build/adapters/logger/__tests__/json.test.d.ts +2 -0
  93. package/build/adapters/logger/__tests__/json.test.d.ts.map +1 -0
  94. package/build/adapters/logger/__tests__/json.test.js +125 -0
  95. package/build/adapters/logger/__tests__/json.test.js.map +1 -0
  96. package/build/adapters/logger/console.d.ts.map +1 -1
  97. package/build/adapters/logger/console.js +4 -2
  98. package/build/adapters/logger/console.js.map +1 -1
  99. package/build/adapters/logger/http.d.ts +3 -0
  100. package/build/adapters/logger/http.d.ts.map +1 -0
  101. package/build/adapters/logger/http.js +49 -0
  102. package/build/adapters/logger/http.js.map +1 -0
  103. package/build/adapters/logger/index.d.ts +3 -0
  104. package/build/adapters/logger/index.d.ts.map +1 -1
  105. package/build/adapters/logger/index.js +3 -0
  106. package/build/adapters/logger/index.js.map +1 -1
  107. package/build/adapters/logger/json.d.ts +3 -0
  108. package/build/adapters/logger/json.d.ts.map +1 -0
  109. package/build/adapters/logger/json.js +41 -0
  110. package/build/adapters/logger/json.js.map +1 -0
  111. package/build/adapters/logger/stdout.d.ts +3 -0
  112. package/build/adapters/logger/stdout.d.ts.map +1 -0
  113. package/build/adapters/logger/stdout.js +52 -0
  114. package/build/adapters/logger/stdout.js.map +1 -0
  115. package/build/index.d.ts +3 -1
  116. package/build/index.d.ts.map +1 -1
  117. package/build/index.js +3 -1
  118. package/build/index.js.map +1 -1
  119. package/build/libraries/deployment-units/computeMDUs.d.ts +11 -0
  120. package/build/libraries/deployment-units/computeMDUs.d.ts.map +1 -0
  121. package/build/libraries/deployment-units/computeMDUs.js +695 -0
  122. package/build/libraries/deployment-units/computeMDUs.js.map +1 -0
  123. package/build/libraries/deployment-units/computeMDUs.test.d.ts +2 -0
  124. package/build/libraries/deployment-units/computeMDUs.test.d.ts.map +1 -0
  125. package/build/libraries/deployment-units/computeMDUs.test.js +996 -0
  126. package/build/libraries/deployment-units/computeMDUs.test.js.map +1 -0
  127. package/build/libraries/deployment-units/index.d.ts +6 -0
  128. package/build/libraries/deployment-units/index.d.ts.map +1 -0
  129. package/build/libraries/deployment-units/index.js +8 -0
  130. package/build/libraries/deployment-units/index.js.map +1 -0
  131. package/build/libraries/deployment-units/manifestWriter.d.ts +11 -0
  132. package/build/libraries/deployment-units/manifestWriter.d.ts.map +1 -0
  133. package/build/libraries/deployment-units/manifestWriter.js +28 -0
  134. package/build/libraries/deployment-units/manifestWriter.js.map +1 -0
  135. package/build/libraries/deployment-units/types.d.ts +43 -0
  136. package/build/libraries/deployment-units/types.d.ts.map +1 -0
  137. package/build/libraries/deployment-units/types.js +3 -0
  138. package/build/libraries/deployment-units/types.js.map +1 -0
  139. package/build/libraries/eventsourcing/__tests__/fixtures/defaultVisibilityThings.readmodel.d.ts +2 -0
  140. package/build/libraries/eventsourcing/__tests__/fixtures/defaultVisibilityThings.readmodel.d.ts.map +1 -0
  141. package/build/libraries/eventsourcing/__tests__/fixtures/defaultVisibilityThings.readmodel.js +17 -0
  142. package/build/libraries/eventsourcing/__tests__/fixtures/defaultVisibilityThings.readmodel.js.map +1 -0
  143. package/build/libraries/eventsourcing/__tests__/fixtures/dupA/things.readmodel.d.ts +2 -0
  144. package/build/libraries/eventsourcing/__tests__/fixtures/dupA/things.readmodel.d.ts.map +1 -0
  145. package/build/libraries/eventsourcing/__tests__/fixtures/dupA/things.readmodel.js +13 -0
  146. package/build/libraries/eventsourcing/__tests__/fixtures/dupA/things.readmodel.js.map +1 -0
  147. package/build/libraries/eventsourcing/__tests__/fixtures/dupB/things.readmodel.d.ts +2 -0
  148. package/build/libraries/eventsourcing/__tests__/fixtures/dupB/things.readmodel.d.ts.map +1 -0
  149. package/build/libraries/eventsourcing/__tests__/fixtures/dupB/things.readmodel.js +12 -0
  150. package/build/libraries/eventsourcing/__tests__/fixtures/dupB/things.readmodel.js.map +1 -0
  151. package/build/libraries/eventsourcing/__tests__/fixtures/publicThings.readmodel.d.ts +2 -0
  152. package/build/libraries/eventsourcing/__tests__/fixtures/publicThings.readmodel.d.ts.map +1 -0
  153. package/build/libraries/eventsourcing/__tests__/fixtures/publicThings.readmodel.js +21 -0
  154. package/build/libraries/eventsourcing/__tests__/fixtures/publicThings.readmodel.js.map +1 -0
  155. package/build/libraries/eventsourcing/__tests__/fixtures/queryOnlyThings.readmodel.d.ts +2 -0
  156. package/build/libraries/eventsourcing/__tests__/fixtures/queryOnlyThings.readmodel.d.ts.map +1 -0
  157. package/build/libraries/eventsourcing/__tests__/fixtures/queryOnlyThings.readmodel.js +16 -0
  158. package/build/libraries/eventsourcing/__tests__/fixtures/queryOnlyThings.readmodel.js.map +1 -0
  159. package/build/libraries/eventsourcing/__tests__/fixtures/subscribingThings.readmodel.d.ts +2 -0
  160. package/build/libraries/eventsourcing/__tests__/fixtures/subscribingThings.readmodel.d.ts.map +1 -0
  161. package/build/libraries/eventsourcing/__tests__/fixtures/subscribingThings.readmodel.js +14 -0
  162. package/build/libraries/eventsourcing/__tests__/fixtures/subscribingThings.readmodel.js.map +1 -0
  163. package/build/libraries/eventsourcing/__tests__/queryOnlyReadmodel.test.d.ts +2 -0
  164. package/build/libraries/eventsourcing/__tests__/queryOnlyReadmodel.test.d.ts.map +1 -0
  165. package/build/libraries/eventsourcing/__tests__/queryOnlyReadmodel.test.js +88 -0
  166. package/build/libraries/eventsourcing/__tests__/queryOnlyReadmodel.test.js.map +1 -0
  167. package/build/libraries/eventsourcing/__tests__/queryVisibility.test.d.ts +2 -0
  168. package/build/libraries/eventsourcing/__tests__/queryVisibility.test.d.ts.map +1 -0
  169. package/build/libraries/eventsourcing/__tests__/queryVisibility.test.js +82 -0
  170. package/build/libraries/eventsourcing/__tests__/queryVisibility.test.js.map +1 -0
  171. package/build/libraries/eventsourcing/commandHandlers/index.d.ts +40 -0
  172. package/build/libraries/eventsourcing/commandHandlers/index.d.ts.map +1 -0
  173. package/build/libraries/eventsourcing/commandHandlers/index.js +1065 -0
  174. package/build/libraries/eventsourcing/commandHandlers/index.js.map +1 -0
  175. package/build/libraries/eventsourcing/commandTemplates/index.d.ts.map +1 -0
  176. package/build/libraries/eventsourcing/commandTemplates/index.js.map +1 -0
  177. package/build/libraries/eventsourcing/commandTemplates/multiStream.d.ts +7 -0
  178. package/build/libraries/eventsourcing/commandTemplates/multiStream.d.ts.map +1 -0
  179. package/build/libraries/eventsourcing/commandTemplates/multiStream.js +116 -0
  180. package/build/libraries/eventsourcing/commandTemplates/multiStream.js.map +1 -0
  181. package/build/libraries/eventsourcing/commandTemplates/snapshot.d.ts +108 -0
  182. package/build/libraries/eventsourcing/commandTemplates/snapshot.d.ts.map +1 -0
  183. package/build/libraries/eventsourcing/commandTemplates/snapshot.js +127 -0
  184. package/build/libraries/eventsourcing/commandTemplates/snapshot.js.map +1 -0
  185. package/build/libraries/eventsourcing/eventHandlers/__tests__/queryResponseFormatterCaller.test.d.ts +2 -0
  186. package/build/libraries/eventsourcing/eventHandlers/__tests__/queryResponseFormatterCaller.test.d.ts.map +1 -0
  187. package/build/libraries/eventsourcing/eventHandlers/__tests__/queryResponseFormatterCaller.test.js +77 -0
  188. package/build/libraries/eventsourcing/eventHandlers/__tests__/queryResponseFormatterCaller.test.js.map +1 -0
  189. package/build/libraries/eventsourcing/eventHandlers/index.d.ts +52 -0
  190. package/build/libraries/eventsourcing/eventHandlers/index.d.ts.map +1 -0
  191. package/build/libraries/eventsourcing/eventHandlers/index.js +474 -0
  192. package/build/libraries/eventsourcing/eventHandlers/index.js.map +1 -0
  193. package/build/libraries/eventsourcing/executionContext.d.ts +50 -0
  194. package/build/libraries/eventsourcing/executionContext.d.ts.map +1 -0
  195. package/build/libraries/eventsourcing/executionContext.js +10 -0
  196. package/build/libraries/eventsourcing/executionContext.js.map +1 -0
  197. package/build/libraries/eventsourcing/idempotencyChecks/index.d.ts +5 -0
  198. package/build/libraries/eventsourcing/idempotencyChecks/index.d.ts.map +1 -0
  199. package/build/libraries/eventsourcing/idempotencyChecks/index.js +26 -0
  200. package/build/libraries/eventsourcing/idempotencyChecks/index.js.map +1 -0
  201. package/build/libraries/eventsourcing/index.d.ts +14 -0
  202. package/build/libraries/eventsourcing/index.d.ts.map +1 -0
  203. package/build/{ports → libraries}/eventsourcing/index.js +50 -15
  204. package/build/{ports → libraries}/eventsourcing/index.js.map +1 -1
  205. package/build/libraries/eventsourcing/invariants/combinators.d.ts +4 -0
  206. package/build/libraries/eventsourcing/invariants/combinators.d.ts.map +1 -0
  207. package/build/{ports → libraries}/eventsourcing/invariants/combinators.js +3 -3
  208. package/build/libraries/eventsourcing/invariants/combinators.js.map +1 -0
  209. package/build/libraries/eventsourcing/invariants/common.d.ts +15 -0
  210. package/build/libraries/eventsourcing/invariants/common.d.ts.map +1 -0
  211. package/build/libraries/eventsourcing/invariants/common.js +27 -0
  212. package/build/libraries/eventsourcing/invariants/common.js.map +1 -0
  213. package/build/libraries/eventsourcing/invariants/comparisons.d.ts +16 -0
  214. package/build/libraries/eventsourcing/invariants/comparisons.d.ts.map +1 -0
  215. package/build/libraries/eventsourcing/invariants/comparisons.js +35 -0
  216. package/build/libraries/eventsourcing/invariants/comparisons.js.map +1 -0
  217. package/build/libraries/eventsourcing/invariants/comparisons.test.d.ts +2 -0
  218. package/build/libraries/eventsourcing/invariants/comparisons.test.d.ts.map +1 -0
  219. package/build/libraries/eventsourcing/invariants/comparisons.test.js +25 -0
  220. package/build/libraries/eventsourcing/invariants/comparisons.test.js.map +1 -0
  221. package/build/libraries/eventsourcing/invariants/index.d.ts +17 -0
  222. package/build/libraries/eventsourcing/invariants/index.d.ts.map +1 -0
  223. package/build/libraries/eventsourcing/invariants/index.js +47 -0
  224. package/build/libraries/eventsourcing/invariants/index.js.map +1 -0
  225. package/build/libraries/eventsourcing/invariants/stateExistance.d.ts +4 -0
  226. package/build/libraries/eventsourcing/invariants/stateExistance.d.ts.map +1 -0
  227. package/build/libraries/eventsourcing/invariants/stateExistance.js +22 -0
  228. package/build/libraries/eventsourcing/invariants/stateExistance.js.map +1 -0
  229. package/build/libraries/eventsourcing/subscriptions/__tests__/sseSubscriptions.test.d.ts +2 -0
  230. package/build/libraries/eventsourcing/subscriptions/__tests__/sseSubscriptions.test.d.ts.map +1 -0
  231. package/build/libraries/eventsourcing/subscriptions/__tests__/sseSubscriptions.test.js +563 -0
  232. package/build/libraries/eventsourcing/subscriptions/__tests__/sseSubscriptions.test.js.map +1 -0
  233. package/build/libraries/eventsourcing/subscriptions/index.d.ts.map +1 -0
  234. package/build/libraries/eventsourcing/subscriptions/index.js.map +1 -0
  235. package/build/libraries/eventsourcing/subscriptions/sseSubscriptions.d.ts +5 -0
  236. package/build/libraries/eventsourcing/subscriptions/sseSubscriptions.d.ts.map +1 -0
  237. package/build/libraries/eventsourcing/subscriptions/sseSubscriptions.js +198 -0
  238. package/build/libraries/eventsourcing/subscriptions/sseSubscriptions.js.map +1 -0
  239. package/build/libraries/eventsourcing/utils/aggregateBuilder.d.ts +5 -0
  240. package/build/libraries/eventsourcing/utils/aggregateBuilder.d.ts.map +1 -0
  241. package/build/{ports → libraries}/eventsourcing/utils/aggregateBuilder.js +17 -3
  242. package/build/libraries/eventsourcing/utils/aggregateBuilder.js.map +1 -0
  243. package/build/libraries/eventsourcing/utils/commandBuilder.d.ts +3 -0
  244. package/build/libraries/eventsourcing/utils/commandBuilder.d.ts.map +1 -0
  245. package/build/{ports → libraries}/eventsourcing/utils/commandBuilder.js +44 -1
  246. package/build/libraries/eventsourcing/utils/commandBuilder.js.map +1 -0
  247. package/build/{ports → libraries}/eventsourcing/utils/eventHandlerBuilder.d.ts +2 -2
  248. package/build/libraries/eventsourcing/utils/eventHandlerBuilder.d.ts.map +1 -0
  249. package/build/libraries/eventsourcing/utils/eventHandlerBuilder.js.map +1 -0
  250. package/build/libraries/eventsourcing/utils/externalSystemBuilder.d.ts +5 -0
  251. package/build/libraries/eventsourcing/utils/externalSystemBuilder.d.ts.map +1 -0
  252. package/build/libraries/eventsourcing/utils/externalSystemBuilder.js +43 -0
  253. package/build/libraries/eventsourcing/utils/externalSystemBuilder.js.map +1 -0
  254. package/build/libraries/eventsourcing/utils/index.d.ts +22 -0
  255. package/build/libraries/eventsourcing/utils/index.d.ts.map +1 -0
  256. package/build/libraries/eventsourcing/utils/index.js +88 -0
  257. package/build/libraries/eventsourcing/utils/index.js.map +1 -0
  258. package/build/libraries/eventsourcing/utils/policyBuilder.d.ts +4 -0
  259. package/build/libraries/eventsourcing/utils/policyBuilder.d.ts.map +1 -0
  260. package/build/libraries/eventsourcing/utils/policyBuilder.js +53 -0
  261. package/build/libraries/eventsourcing/utils/policyBuilder.js.map +1 -0
  262. package/build/libraries/eventsourcing/utils/readmodelBuilder.d.ts +6 -0
  263. package/build/libraries/eventsourcing/utils/readmodelBuilder.d.ts.map +1 -0
  264. package/build/libraries/eventsourcing/utils/readmodelBuilder.js +68 -0
  265. package/build/libraries/eventsourcing/utils/readmodelBuilder.js.map +1 -0
  266. package/build/libraries/localOutbox/index.d.ts +6 -0
  267. package/build/libraries/localOutbox/index.d.ts.map +1 -0
  268. package/build/libraries/localOutbox/index.js +72 -0
  269. package/build/libraries/localOutbox/index.js.map +1 -0
  270. package/build/libraries/modulePath.d.ts +14 -0
  271. package/build/libraries/modulePath.d.ts.map +1 -0
  272. package/build/libraries/modulePath.js +21 -0
  273. package/build/libraries/modulePath.js.map +1 -0
  274. package/build/libraries/modules/fs.d.ts +2 -4
  275. package/build/libraries/modules/fs.d.ts.map +1 -1
  276. package/build/libraries/modules/fs.js +21 -84
  277. package/build/libraries/modules/fs.js.map +1 -1
  278. package/build/libraries/modules/index.d.ts +2 -0
  279. package/build/libraries/modules/index.d.ts.map +1 -1
  280. package/build/libraries/modules/index.js +2 -0
  281. package/build/libraries/modules/index.js.map +1 -1
  282. package/build/libraries/modules/scopedPortsView.d.ts +42 -0
  283. package/build/libraries/modules/scopedPortsView.d.ts.map +1 -0
  284. package/build/libraries/modules/scopedPortsView.js +55 -0
  285. package/build/libraries/modules/scopedPortsView.js.map +1 -0
  286. package/build/libraries/modules/scopedPortsView.test.d.ts +10 -0
  287. package/build/libraries/modules/scopedPortsView.test.d.ts.map +1 -0
  288. package/build/libraries/modules/scopedPortsView.test.js +103 -0
  289. package/build/libraries/modules/scopedPortsView.test.js.map +1 -0
  290. package/build/libraries/modules/selectiveLoader.d.ts +21 -0
  291. package/build/libraries/modules/selectiveLoader.d.ts.map +1 -0
  292. package/build/libraries/modules/selectiveLoader.js +164 -0
  293. package/build/libraries/modules/selectiveLoader.js.map +1 -0
  294. package/build/libraries/modules/selectiveLoader.test.d.ts +2 -0
  295. package/build/libraries/modules/selectiveLoader.test.d.ts.map +1 -0
  296. package/build/libraries/modules/selectiveLoader.test.js +471 -0
  297. package/build/libraries/modules/selectiveLoader.test.js.map +1 -0
  298. package/build/libraries/openApi/pruneUnusedRef.d.ts.map +1 -1
  299. package/build/libraries/openApi/pruneUnusedRef.js.map +1 -1
  300. package/build/libraries/tcp/index.d.ts +0 -1
  301. package/build/libraries/tcp/index.d.ts.map +1 -1
  302. package/build/libraries/tcp/index.js +32 -9
  303. package/build/libraries/tcp/index.js.map +1 -1
  304. package/build/libraries/tcp/types.d.ts +0 -1
  305. package/build/libraries/tcp/types.d.ts.map +1 -1
  306. package/build/libraries/validation/__tests__/readmodelQuerySchema.test.d.ts +2 -0
  307. package/build/libraries/validation/__tests__/readmodelQuerySchema.test.d.ts.map +1 -0
  308. package/build/libraries/validation/__tests__/readmodelQuerySchema.test.js +100 -0
  309. package/build/libraries/validation/__tests__/readmodelQuerySchema.test.js.map +1 -0
  310. package/build/libraries/validation/__tests__/validation.test.js +17 -7
  311. package/build/libraries/validation/__tests__/validation.test.js.map +1 -1
  312. package/build/libraries/validation/index.d.ts +3 -3
  313. package/build/libraries/validation/index.d.ts.map +1 -1
  314. package/build/libraries/validation/index.js +49 -15
  315. package/build/libraries/validation/index.js.map +1 -1
  316. package/build/ports/authentication/index.js.map +1 -1
  317. package/build/ports/authentication/index.test.d.ts +2 -0
  318. package/build/ports/authentication/index.test.d.ts.map +1 -0
  319. package/build/ports/authentication/index.test.js +38 -0
  320. package/build/ports/authentication/index.test.js.map +1 -0
  321. package/build/ports/base.d.ts.map +1 -1
  322. package/build/ports/base.js +39 -5
  323. package/build/ports/base.js.map +1 -1
  324. package/build/ports/base.test.d.ts +2 -0
  325. package/build/ports/base.test.d.ts.map +1 -0
  326. package/build/ports/base.test.js +92 -0
  327. package/build/ports/base.test.js.map +1 -0
  328. package/build/ports/cache/index.js.map +1 -1
  329. package/build/ports/cache/index.test.d.ts +2 -0
  330. package/build/ports/cache/index.test.d.ts.map +1 -0
  331. package/build/ports/cache/index.test.js +43 -0
  332. package/build/ports/cache/index.test.js.map +1 -0
  333. package/build/ports/configuration/__tests__/cliArgs.test.d.ts +2 -0
  334. package/build/ports/configuration/__tests__/cliArgs.test.d.ts.map +1 -0
  335. package/build/ports/configuration/__tests__/cliArgs.test.js +158 -0
  336. package/build/ports/configuration/__tests__/cliArgs.test.js.map +1 -0
  337. package/build/ports/configuration/__tests__/configurationPortEmitter.test.d.ts +2 -0
  338. package/build/ports/configuration/__tests__/configurationPortEmitter.test.d.ts.map +1 -0
  339. package/build/ports/configuration/__tests__/configurationPortEmitter.test.js +63 -0
  340. package/build/ports/configuration/__tests__/configurationPortEmitter.test.js.map +1 -0
  341. package/build/ports/configuration/__tests__/getArgsSync.test.d.ts +2 -0
  342. package/build/ports/configuration/__tests__/getArgsSync.test.d.ts.map +1 -0
  343. package/build/ports/configuration/__tests__/getArgsSync.test.js +85 -0
  344. package/build/ports/configuration/__tests__/getArgsSync.test.js.map +1 -0
  345. package/build/ports/configuration/args.d.ts +50 -43
  346. package/build/ports/configuration/args.d.ts.map +1 -1
  347. package/build/ports/configuration/args.js +76 -13
  348. package/build/ports/configuration/args.js.map +1 -1
  349. package/build/ports/configuration/common.js +1 -2
  350. package/build/ports/configuration/common.js.map +1 -1
  351. package/build/ports/configuration/index.d.ts +1 -1
  352. package/build/ports/configuration/index.d.ts.map +1 -1
  353. package/build/ports/configuration/index.js +85 -17
  354. package/build/ports/configuration/index.js.map +1 -1
  355. package/build/ports/configuration/localConfig.d.ts.map +1 -1
  356. package/build/ports/configuration/localConfig.js +46 -27
  357. package/build/ports/configuration/localConfig.js.map +1 -1
  358. package/build/ports/database/index.d.ts +1 -2
  359. package/build/ports/database/index.d.ts.map +1 -1
  360. package/build/ports/database/index.js +23 -17
  361. package/build/ports/database/index.js.map +1 -1
  362. package/build/ports/database/index.test.d.ts +2 -0
  363. package/build/ports/database/index.test.d.ts.map +1 -0
  364. package/build/ports/database/index.test.js +43 -0
  365. package/build/ports/database/index.test.js.map +1 -0
  366. package/build/ports/endpoints/__tests__/declarationSite.test.d.ts +2 -0
  367. package/build/ports/endpoints/__tests__/declarationSite.test.d.ts.map +1 -0
  368. package/build/ports/endpoints/__tests__/declarationSite.test.js +165 -0
  369. package/build/ports/endpoints/__tests__/declarationSite.test.js.map +1 -0
  370. package/build/ports/endpoints/__tests__/fixtures/modules/sales/appLoginUrl.d.ts +9 -0
  371. package/build/ports/endpoints/__tests__/fixtures/modules/sales/appLoginUrl.d.ts.map +1 -0
  372. package/build/ports/endpoints/__tests__/fixtures/modules/sales/appLoginUrl.js +20 -0
  373. package/build/ports/endpoints/__tests__/fixtures/modules/sales/appLoginUrl.js.map +1 -0
  374. package/build/ports/endpoints/__tests__/fixtures/modules/sales/index.d.ts +10 -0
  375. package/build/ports/endpoints/__tests__/fixtures/modules/sales/index.d.ts.map +1 -0
  376. package/build/ports/endpoints/__tests__/fixtures/modules/sales/index.js +21 -0
  377. package/build/ports/endpoints/__tests__/fixtures/modules/sales/index.js.map +1 -0
  378. package/build/ports/endpoints/__tests__/fixtures/modules/sales/orders.endpoints.d.ts +15 -0
  379. package/build/ports/endpoints/__tests__/fixtures/modules/sales/orders.endpoints.d.ts.map +1 -0
  380. package/build/ports/endpoints/__tests__/fixtures/modules/sales/orders.endpoints.js +46 -0
  381. package/build/ports/endpoints/__tests__/fixtures/modules/sales/orders.endpoints.js.map +1 -0
  382. package/build/ports/endpoints/__tests__/manifestEndpoints.test.d.ts +2 -0
  383. package/build/ports/endpoints/__tests__/manifestEndpoints.test.d.ts.map +1 -0
  384. package/build/ports/endpoints/__tests__/manifestEndpoints.test.js +117 -0
  385. package/build/ports/endpoints/__tests__/manifestEndpoints.test.js.map +1 -0
  386. package/build/ports/endpoints/declarationSite.d.ts +63 -0
  387. package/build/ports/endpoints/declarationSite.d.ts.map +1 -0
  388. package/build/ports/endpoints/declarationSite.js +126 -0
  389. package/build/ports/endpoints/declarationSite.js.map +1 -0
  390. package/build/ports/endpoints/health.d.ts +26 -0
  391. package/build/ports/endpoints/health.d.ts.map +1 -0
  392. package/build/ports/endpoints/health.js +96 -0
  393. package/build/ports/endpoints/health.js.map +1 -0
  394. package/build/ports/endpoints/index.d.ts +43 -7
  395. package/build/ports/endpoints/index.d.ts.map +1 -1
  396. package/build/ports/endpoints/index.js +317 -67
  397. package/build/ports/endpoints/index.js.map +1 -1
  398. package/build/ports/endpoints/openApi.d.ts +3 -2
  399. package/build/ports/endpoints/openApi.d.ts.map +1 -1
  400. package/build/ports/endpoints/openApi.js +184 -55
  401. package/build/ports/endpoints/openApi.js.map +1 -1
  402. package/build/ports/endpoints/utils.d.ts.map +1 -1
  403. package/build/ports/endpoints/utils.js.map +1 -1
  404. package/build/ports/eventstore/index.d.ts.map +1 -1
  405. package/build/ports/eventstore/index.js +37 -5
  406. package/build/ports/eventstore/index.js.map +1 -1
  407. package/build/ports/eventstore/index.test.d.ts +2 -0
  408. package/build/ports/eventstore/index.test.d.ts.map +1 -0
  409. package/build/ports/eventstore/index.test.js +68 -0
  410. package/build/ports/eventstore/index.test.js.map +1 -0
  411. package/build/ports/infrastructure/index.d.ts +61 -23
  412. package/build/ports/infrastructure/index.d.ts.map +1 -1
  413. package/build/ports/infrastructure/index.js +187 -37
  414. package/build/ports/infrastructure/index.js.map +1 -1
  415. package/build/ports/infrastructure/index.test.d.ts +2 -0
  416. package/build/ports/infrastructure/index.test.d.ts.map +1 -0
  417. package/build/ports/infrastructure/index.test.js +228 -0
  418. package/build/ports/infrastructure/index.test.js.map +1 -0
  419. package/build/ports/infrastructure/utils.d.ts +2 -1
  420. package/build/ports/infrastructure/utils.d.ts.map +1 -1
  421. package/build/ports/infrastructure/utils.js +48 -22
  422. package/build/ports/infrastructure/utils.js.map +1 -1
  423. package/build/ports/logger/__tests__/logger.test.d.ts +2 -0
  424. package/build/ports/logger/__tests__/logger.test.d.ts.map +1 -0
  425. package/build/ports/logger/__tests__/logger.test.js +69 -0
  426. package/build/ports/logger/__tests__/logger.test.js.map +1 -0
  427. package/build/ports/logger/index.d.ts.map +1 -1
  428. package/build/ports/logger/index.js +3 -2
  429. package/build/ports/logger/index.js.map +1 -1
  430. package/build/utils/__tests__/applyCollectionFilterInMemory.test.d.ts +2 -0
  431. package/build/utils/__tests__/applyCollectionFilterInMemory.test.d.ts.map +1 -0
  432. package/build/utils/__tests__/applyCollectionFilterInMemory.test.js +33 -0
  433. package/build/utils/__tests__/applyCollectionFilterInMemory.test.js.map +1 -0
  434. package/build/utils/__tests__/decodeObjectQueryParams.test.d.ts +2 -0
  435. package/build/utils/__tests__/decodeObjectQueryParams.test.d.ts.map +1 -0
  436. package/build/utils/__tests__/decodeObjectQueryParams.test.js +118 -0
  437. package/build/utils/__tests__/decodeObjectQueryParams.test.js.map +1 -0
  438. package/build/utils/index.d.ts +26 -34
  439. package/build/utils/index.d.ts.map +1 -1
  440. package/build/utils/index.js +159 -170
  441. package/build/utils/index.js.map +1 -1
  442. package/package.json +31 -11
  443. package/build/adapters/cache/memory/__tests__/memoryCache.test.d.ts +0 -1
  444. package/build/adapters/cache/memory/__tests__/memoryCache.test.d.ts.map +0 -1
  445. package/build/adapters/cache/memory/__tests__/memoryCache.test.js +0 -6
  446. package/build/adapters/cache/memory/__tests__/memoryCache.test.js.map +0 -1
  447. package/build/adapters/database/memory/__tests__/memoryDb.test.d.ts +0 -1
  448. package/build/adapters/database/memory/__tests__/memoryDb.test.d.ts.map +0 -1
  449. package/build/adapters/database/memory/__tests__/memoryDb.test.js +0 -36
  450. package/build/adapters/database/memory/__tests__/memoryDb.test.js.map +0 -1
  451. package/build/ports/endpoints/__tests__/endpointsCall.test.d.ts +0 -2
  452. package/build/ports/endpoints/__tests__/endpointsCall.test.d.ts.map +0 -1
  453. package/build/ports/endpoints/__tests__/endpointsCall.test.js +0 -21
  454. package/build/ports/endpoints/__tests__/endpointsCall.test.js.map +0 -1
  455. package/build/ports/endpoints/__tests__/test-client-library/base.d.ts +0 -77
  456. package/build/ports/endpoints/__tests__/test-client-library/base.d.ts.map +0 -1
  457. package/build/ports/endpoints/__tests__/test-client-library/base.js +0 -91
  458. package/build/ports/endpoints/__tests__/test-client-library/base.js.map +0 -1
  459. package/build/ports/endpoints/__tests__/test-client-library/index.d.ts +0 -29
  460. package/build/ports/endpoints/__tests__/test-client-library/index.d.ts.map +0 -1
  461. package/build/ports/endpoints/__tests__/test-client-library/index.js +0 -43
  462. package/build/ports/endpoints/__tests__/test-client-library/index.js.map +0 -1
  463. package/build/ports/endpoints/__tests__/test-client-library/services/service.d.ts +0 -106
  464. package/build/ports/endpoints/__tests__/test-client-library/services/service.d.ts.map +0 -1
  465. package/build/ports/endpoints/__tests__/test-client-library/services/service.js +0 -62
  466. package/build/ports/endpoints/__tests__/test-client-library/services/service.js.map +0 -1
  467. package/build/ports/endpoints/__tests__/utils.test.d.ts +0 -1
  468. package/build/ports/endpoints/__tests__/utils.test.d.ts.map +0 -1
  469. package/build/ports/endpoints/__tests__/utils.test.js +0 -53
  470. package/build/ports/endpoints/__tests__/utils.test.js.map +0 -1
  471. package/build/ports/eventsourcing/__tests__/eventhandlers.test.d.ts +0 -2
  472. package/build/ports/eventsourcing/__tests__/eventhandlers.test.d.ts.map +0 -1
  473. package/build/ports/eventsourcing/__tests__/eventhandlers.test.js +0 -35
  474. package/build/ports/eventsourcing/__tests__/eventhandlers.test.js.map +0 -1
  475. package/build/ports/eventsourcing/__tests__/invariants.test.d.ts +0 -2
  476. package/build/ports/eventsourcing/__tests__/invariants.test.d.ts.map +0 -1
  477. package/build/ports/eventsourcing/__tests__/invariants.test.js +0 -210
  478. package/build/ports/eventsourcing/__tests__/invariants.test.js.map +0 -1
  479. package/build/ports/eventsourcing/commandHandlers/index.d.ts +0 -25
  480. package/build/ports/eventsourcing/commandHandlers/index.d.ts.map +0 -1
  481. package/build/ports/eventsourcing/commandHandlers/index.js +0 -392
  482. package/build/ports/eventsourcing/commandHandlers/index.js.map +0 -1
  483. package/build/ports/eventsourcing/commandTemplates/index.d.ts.map +0 -1
  484. package/build/ports/eventsourcing/commandTemplates/index.js.map +0 -1
  485. package/build/ports/eventsourcing/commandTemplates/multiStream.d.ts +0 -4
  486. package/build/ports/eventsourcing/commandTemplates/multiStream.d.ts.map +0 -1
  487. package/build/ports/eventsourcing/commandTemplates/multiStream.js +0 -73
  488. package/build/ports/eventsourcing/commandTemplates/multiStream.js.map +0 -1
  489. package/build/ports/eventsourcing/commandTemplates/snapshot.d.ts +0 -9
  490. package/build/ports/eventsourcing/commandTemplates/snapshot.d.ts.map +0 -1
  491. package/build/ports/eventsourcing/commandTemplates/snapshot.js +0 -39
  492. package/build/ports/eventsourcing/commandTemplates/snapshot.js.map +0 -1
  493. package/build/ports/eventsourcing/eventHandlers/index.d.ts +0 -33
  494. package/build/ports/eventsourcing/eventHandlers/index.d.ts.map +0 -1
  495. package/build/ports/eventsourcing/eventHandlers/index.js +0 -276
  496. package/build/ports/eventsourcing/eventHandlers/index.js.map +0 -1
  497. package/build/ports/eventsourcing/index.d.ts +0 -9
  498. package/build/ports/eventsourcing/index.d.ts.map +0 -1
  499. package/build/ports/eventsourcing/invariants/combinators.d.ts +0 -4
  500. package/build/ports/eventsourcing/invariants/combinators.d.ts.map +0 -1
  501. package/build/ports/eventsourcing/invariants/combinators.js.map +0 -1
  502. package/build/ports/eventsourcing/invariants/common.d.ts +0 -10
  503. package/build/ports/eventsourcing/invariants/common.d.ts.map +0 -1
  504. package/build/ports/eventsourcing/invariants/common.js +0 -37
  505. package/build/ports/eventsourcing/invariants/common.js.map +0 -1
  506. package/build/ports/eventsourcing/invariants/comparisons.d.ts +0 -19
  507. package/build/ports/eventsourcing/invariants/comparisons.d.ts.map +0 -1
  508. package/build/ports/eventsourcing/invariants/comparisons.js +0 -83
  509. package/build/ports/eventsourcing/invariants/comparisons.js.map +0 -1
  510. package/build/ports/eventsourcing/invariants/index.d.ts +0 -5
  511. package/build/ports/eventsourcing/invariants/index.d.ts.map +0 -1
  512. package/build/ports/eventsourcing/invariants/index.js +0 -21
  513. package/build/ports/eventsourcing/invariants/index.js.map +0 -1
  514. package/build/ports/eventsourcing/invariants/stateExistance.d.ts +0 -4
  515. package/build/ports/eventsourcing/invariants/stateExistance.d.ts.map +0 -1
  516. package/build/ports/eventsourcing/invariants/stateExistance.js +0 -33
  517. package/build/ports/eventsourcing/invariants/stateExistance.js.map +0 -1
  518. package/build/ports/eventsourcing/subscriptions/index.d.ts.map +0 -1
  519. package/build/ports/eventsourcing/subscriptions/index.js.map +0 -1
  520. package/build/ports/eventsourcing/subscriptions/sseSubscriptions.d.ts +0 -3
  521. package/build/ports/eventsourcing/subscriptions/sseSubscriptions.d.ts.map +0 -1
  522. package/build/ports/eventsourcing/subscriptions/sseSubscriptions.js +0 -81
  523. package/build/ports/eventsourcing/subscriptions/sseSubscriptions.js.map +0 -1
  524. package/build/ports/eventsourcing/utils/aggregateBuilder.d.ts +0 -4
  525. package/build/ports/eventsourcing/utils/aggregateBuilder.d.ts.map +0 -1
  526. package/build/ports/eventsourcing/utils/aggregateBuilder.js.map +0 -1
  527. package/build/ports/eventsourcing/utils/commandBuilder.d.ts +0 -3
  528. package/build/ports/eventsourcing/utils/commandBuilder.d.ts.map +0 -1
  529. package/build/ports/eventsourcing/utils/commandBuilder.js.map +0 -1
  530. package/build/ports/eventsourcing/utils/eventHandlerBuilder.d.ts.map +0 -1
  531. package/build/ports/eventsourcing/utils/eventHandlerBuilder.js.map +0 -1
  532. package/build/ports/eventsourcing/utils/externalSystemBuilder.d.ts +0 -4
  533. package/build/ports/eventsourcing/utils/externalSystemBuilder.d.ts.map +0 -1
  534. package/build/ports/eventsourcing/utils/externalSystemBuilder.js +0 -34
  535. package/build/ports/eventsourcing/utils/externalSystemBuilder.js.map +0 -1
  536. package/build/ports/eventsourcing/utils/index.d.ts +0 -13
  537. package/build/ports/eventsourcing/utils/index.d.ts.map +0 -1
  538. package/build/ports/eventsourcing/utils/index.js +0 -45
  539. package/build/ports/eventsourcing/utils/index.js.map +0 -1
  540. package/build/ports/eventsourcing/utils/policyBuilder.d.ts +0 -3
  541. package/build/ports/eventsourcing/utils/policyBuilder.d.ts.map +0 -1
  542. package/build/ports/eventsourcing/utils/policyBuilder.js +0 -29
  543. package/build/ports/eventsourcing/utils/policyBuilder.js.map +0 -1
  544. package/build/ports/eventsourcing/utils/readmodelBuilder.d.ts +0 -5
  545. package/build/ports/eventsourcing/utils/readmodelBuilder.d.ts.map +0 -1
  546. package/build/ports/eventsourcing/utils/readmodelBuilder.js +0 -45
  547. package/build/ports/eventsourcing/utils/readmodelBuilder.js.map +0 -1
  548. package/build/ports/infrastructure/__tests__/fixture/index.d.ts +0 -3
  549. package/build/ports/infrastructure/__tests__/fixture/index.d.ts.map +0 -1
  550. package/build/ports/infrastructure/__tests__/fixture/index.js +0 -19
  551. package/build/ports/infrastructure/__tests__/fixture/index.js.map +0 -1
  552. package/build/ports/infrastructure/__tests__/fixture/infrastructureServices.d.ts +0 -19
  553. package/build/ports/infrastructure/__tests__/fixture/infrastructureServices.d.ts.map +0 -1
  554. package/build/ports/infrastructure/__tests__/fixture/infrastructureServices.js +0 -76
  555. package/build/ports/infrastructure/__tests__/fixture/infrastructureServices.js.map +0 -1
  556. package/build/ports/infrastructure/__tests__/fixture/structureState.d.ts +0 -177
  557. package/build/ports/infrastructure/__tests__/fixture/structureState.d.ts.map +0 -1
  558. package/build/ports/infrastructure/__tests__/fixture/structureState.js +0 -258
  559. package/build/ports/infrastructure/__tests__/fixture/structureState.js.map +0 -1
  560. package/build/ports/infrastructure/__tests__/infrastructure.test.d.ts +0 -2
  561. package/build/ports/infrastructure/__tests__/infrastructure.test.d.ts.map +0 -1
  562. package/build/ports/infrastructure/__tests__/infrastructure.test.js +0 -11
  563. package/build/ports/infrastructure/__tests__/infrastructure.test.js.map +0 -1
  564. package/src/adapters/cache/index.ts +0 -1
  565. package/src/adapters/cache/memory/__tests__/memoryCache.test.ts +0 -6
  566. package/src/adapters/cache/memory/index.ts +0 -142
  567. package/src/adapters/configuration/__tests__/.env +0 -4
  568. package/src/adapters/configuration/__tests__/dotEnv.test.ts +0 -38
  569. package/src/adapters/configuration/dotEnv.ts +0 -33
  570. package/src/adapters/configuration/index.ts +0 -1
  571. package/src/adapters/database/index.ts +0 -1
  572. package/src/adapters/database/memory/__tests__/memoryDb.test.ts +0 -37
  573. package/src/adapters/database/memory/index.ts +0 -279
  574. package/src/adapters/endpoints/addAuthUser/index.ts +0 -55
  575. package/src/adapters/endpoints/endpointValidation/index.ts +0 -26
  576. package/src/adapters/endpoints/index.ts +0 -4
  577. package/src/adapters/endpoints/localAuthorization/index.ts +0 -75
  578. package/src/adapters/endpoints/tcpConsumer/index.ts +0 -69
  579. package/src/adapters/endpoints/userSession/index.ts +0 -40
  580. package/src/adapters/eventstore/database.ts +0 -178
  581. package/src/adapters/eventstore/index.ts +0 -1
  582. package/src/adapters/infrastructure/index.ts +0 -1
  583. package/src/adapters/infrastructure/local/index.ts +0 -40
  584. package/src/adapters/logger/console.ts +0 -42
  585. package/src/adapters/logger/index.ts +0 -1
  586. package/src/index.ts +0 -25
  587. package/src/libraries/modules/fs.ts +0 -88
  588. package/src/libraries/modules/index.ts +0 -1
  589. package/src/libraries/openApi/index.ts +0 -1
  590. package/src/libraries/openApi/pruneUnusedRef.ts +0 -35
  591. package/src/libraries/tcp/index.ts +0 -98
  592. package/src/libraries/tcp/types.ts +0 -43
  593. package/src/libraries/validation/__tests__/validation.test.ts +0 -25
  594. package/src/libraries/validation/index.ts +0 -48
  595. package/src/ports/authentication/index.ts +0 -25
  596. package/src/ports/base.ts +0 -20
  597. package/src/ports/cache/index.ts +0 -17
  598. package/src/ports/configuration/__tests__/configurationPort.test.ts +0 -47
  599. package/src/ports/configuration/args.ts +0 -39
  600. package/src/ports/configuration/common.ts +0 -12
  601. package/src/ports/configuration/index.ts +0 -110
  602. package/src/ports/configuration/localConfig.ts +0 -117
  603. package/src/ports/database/index.ts +0 -25
  604. package/src/ports/endpoints/__tests__/endpointsCall.test.ts +0 -20
  605. package/src/ports/endpoints/__tests__/test-client-library/base.ts +0 -167
  606. package/src/ports/endpoints/__tests__/test-client-library/index.ts +0 -23
  607. package/src/ports/endpoints/__tests__/test-client-library/services/service.ts +0 -181
  608. package/src/ports/endpoints/__tests__/utils.test.ts +0 -54
  609. package/src/ports/endpoints/index.ts +0 -272
  610. package/src/ports/endpoints/openApi.ts +0 -191
  611. package/src/ports/endpoints/utils.ts +0 -31
  612. package/src/ports/eventsourcing/__tests__/eventhandlers.test.ts +0 -30
  613. package/src/ports/eventsourcing/__tests__/invariants.test.ts +0 -213
  614. package/src/ports/eventsourcing/commandHandlers/index.ts +0 -625
  615. package/src/ports/eventsourcing/commandTemplates/index.ts +0 -2
  616. package/src/ports/eventsourcing/commandTemplates/multiStream.ts +0 -70
  617. package/src/ports/eventsourcing/commandTemplates/snapshot.ts +0 -43
  618. package/src/ports/eventsourcing/eventHandlers/index.ts +0 -429
  619. package/src/ports/eventsourcing/index.ts +0 -98
  620. package/src/ports/eventsourcing/invariants/combinators.ts +0 -25
  621. package/src/ports/eventsourcing/invariants/common.ts +0 -42
  622. package/src/ports/eventsourcing/invariants/comparisons.ts +0 -90
  623. package/src/ports/eventsourcing/invariants/index.ts +0 -4
  624. package/src/ports/eventsourcing/invariants/stateExistance.ts +0 -34
  625. package/src/ports/eventsourcing/subscriptions/index.ts +0 -1
  626. package/src/ports/eventsourcing/subscriptions/sseSubscriptions.ts +0 -103
  627. package/src/ports/eventsourcing/utils/aggregateBuilder.ts +0 -49
  628. package/src/ports/eventsourcing/utils/commandBuilder.ts +0 -113
  629. package/src/ports/eventsourcing/utils/eventHandlerBuilder.ts +0 -22
  630. package/src/ports/eventsourcing/utils/externalSystemBuilder.ts +0 -42
  631. package/src/ports/eventsourcing/utils/index.ts +0 -25
  632. package/src/ports/eventsourcing/utils/policyBuilder.ts +0 -31
  633. package/src/ports/eventsourcing/utils/readmodelBuilder.ts +0 -52
  634. package/src/ports/eventstore/index.ts +0 -11
  635. package/src/ports/infrastructure/__tests__/fixture/index.ts +0 -2
  636. package/src/ports/infrastructure/__tests__/fixture/infrastructureServices.ts +0 -72
  637. package/src/ports/infrastructure/__tests__/fixture/structureState.ts +0 -254
  638. package/src/ports/infrastructure/__tests__/infrastructure.test.ts +0 -11
  639. package/src/ports/infrastructure/index.ts +0 -162
  640. package/src/ports/infrastructure/utils.ts +0 -130
  641. package/src/ports/logger/index.ts +0 -34
  642. package/src/utils/index.ts +0 -186
  643. package/tsconfig.json +0 -19
  644. /package/build/{ports → libraries}/eventsourcing/commandTemplates/index.d.ts +0 -0
  645. /package/build/{ports → libraries}/eventsourcing/commandTemplates/index.js +0 -0
  646. /package/build/{ports → libraries}/eventsourcing/subscriptions/index.d.ts +0 -0
  647. /package/build/{ports → libraries}/eventsourcing/subscriptions/index.js +0 -0
  648. /package/build/{ports → libraries}/eventsourcing/utils/eventHandlerBuilder.js +0 -0
@@ -0,0 +1,1065 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createCommandHandlers = exports.handleCommand = exports.defaultEventsourcingLoad = exports.validateInvariants = exports.formatEventSourcedCommandResponse = exports.formatDomainModelCommandResponse = exports.reduceEventsIntoState = exports.defaultCommit = exports.defaultHandler = exports.domainModelCommit = exports.domainModelLoad = exports.loadAggregateState = exports.getNonNoopEventNames = exports.loadStream = exports.getStreamReducer = exports.commitEvents = exports.appendEventsToOwnStreams = exports.prepareEventsToCommit = exports.addMetadata = exports.appendEventsToStream = exports.getEventReducers = exports.formatAggregateGetQueryParams = void 0;
7
+ const bett3r_utils_1 = require("@bett3r-dev/bett3r-utils");
8
+ const jsonschema_definer_1 = __importDefault(require("@bett3r-dev/jsonschema-definer"));
9
+ const pv3_types_1 = require("@bett3r-dev/pv3-types");
10
+ const change_case_1 = require("change-case");
11
+ const ramda_1 = require("ramda");
12
+ const uuidv7_1 = require("uuidv7");
13
+ const reducersByAggregateMap = new Map();
14
+ let getActiveTraceId = () => undefined;
15
+ // Capture the metrics FACADE (not a meter/counter) at module load — that is safe. Resolving a
16
+ // concrete counter here (`metrics.getMeter(...).createCounter(...)`) would bind to the no-op
17
+ // MeterProvider before the host registers its real one and stay a permanent no-op (the OTel
18
+ // dual-api module-load hazard); the counter is instead resolved lazily on first skip below.
19
+ let otelMetrics;
20
+ try {
21
+ const { trace, metrics } = require('@opentelemetry/api');
22
+ getActiveTraceId = () => {
23
+ const span = trace.getActiveSpan();
24
+ const traceId = span?.spanContext().traceId;
25
+ return traceId && traceId !== '00000000000000000000000000000000' ? traceId : undefined;
26
+ };
27
+ otelMetrics = metrics;
28
+ }
29
+ catch {
30
+ // @opentelemetry/api not available
31
+ }
32
+ // Lazily-resolved, memoized counter for declarative-idempotency dedup skips. Every time a
33
+ // `withIdempotencyCheck(...)` short-circuits the command pipeline (the skip branch below), this
34
+ // increments so the otherwise-invisible dedup activity is countable. Resolved on FIRST use —
35
+ // after the host has registered its MeterProvider — never at module load (see note above).
36
+ let idempotencySkipCounter;
37
+ const getIdempotencySkipCounter = () => {
38
+ if (idempotencySkipCounter || !otelMetrics)
39
+ return idempotencySkipCounter;
40
+ idempotencySkipCounter = otelMetrics.getMeter('pv3').createCounter('pv3.command.idempotency_skip', {
41
+ description: 'Declarative withIdempotencyCheck dedup short-circuits: a duplicate command matched an idempotency check and skipped the handler + commit before any application code ran. Labelled by { command, aggregate }.'
42
+ });
43
+ return idempotencySkipCounter;
44
+ };
45
+ /* ─── Optimistic-concurrency retry observability + backoff ──────────────────────────────
46
+ *
47
+ * `executeCommand` has always retried a `ConcurrencyError` up to ten times, IMMEDIATELY and
48
+ * SILENTLY: nothing counted the retries, nothing named the stream that lost, and giving up
49
+ * produced one `logger.error` indistinguishable from any other failed command. That is the
50
+ * wrong shape for a multi-stream command whose fan-out width is a property of the CATALOG —
51
+ * a Composite Item ("Kit") whose component sits in fifty kits re-runs a fifty-one-stream
52
+ * command on every conflict, so contention is the thing that decides whether the design
53
+ * holds, and it was invisible.
54
+ *
55
+ * Three instruments, all `{ command, aggregate }`-labelled and therefore BOUNDED. The
56
+ * contended STREAM is deliberately NOT a label: a stream name is per-entity, so labelling by
57
+ * it makes the series cardinality equal to the catalog. It goes in the log line instead,
58
+ * which is where the "WHICH hot item" question is actually answered.
59
+ *
60
+ * pv3.command.occ_retry one per re-execution — the leading contention indicator.
61
+ * pv3.command.occ_retry_backoff ms actually waited, so backoff can be told apart from
62
+ * latency spent doing work.
63
+ * pv3.command.occ_retry_exhausted PAGE ON THIS. The command failed after the whole budget;
64
+ * for a stock decrement that means an order's stock was
65
+ * never decremented.
66
+ */
67
+ let occInstruments;
68
+ const getOccInstruments = () => {
69
+ if (occInstruments || !otelMetrics)
70
+ return occInstruments;
71
+ const meter = otelMetrics.getMeter('pv3');
72
+ occInstruments = {
73
+ retry: meter.createCounter('pv3.command.occ_retry', {
74
+ description: 'A command re-executed from the top because its commit lost an optimistic-concurrency check. The leading indicator of write contention on a stream. Labelled by { command, aggregate } — the contended stream is in the accompanying debug log, never a label (per-entity cardinality).'
75
+ }),
76
+ backoff: meter.createHistogram('pv3.command.occ_retry_backoff', {
77
+ description: 'Milliseconds waited before an optimistic-concurrency re-execution (full-jitter, capped). Separates time spent BACKING OFF from time spent working, so a contention problem is not read as a slow command. Labelled by { command, aggregate }.',
78
+ unit: 'ms'
79
+ }),
80
+ exhausted: meter.createCounter('pv3.command.occ_retry_exhausted', {
81
+ description: 'A command that exhausted its optimistic-concurrency retry budget and FAILED — nothing was committed. PAGE ON THIS: for a stock decrement it means an order never decremented its stock. Labelled by { command, aggregate }.'
82
+ })
83
+ };
84
+ return occInstruments;
85
+ };
86
+ /** The retry budget. Deliberately NOT raised to absorb contention: under sustained
87
+ * contention more attempts mostly add load — the lever is the WAIT below, not the count. */
88
+ const OCC_RETRY_CEILING = 10;
89
+ const OCC_BACKOFF_BASE_MS = 5;
90
+ const OCC_BACKOFF_CAP_MS = 250;
91
+ /**
92
+ * FULL JITTER over an exponentially-growing window, plus a small floor.
93
+ *
94
+ * Immediate retry is what turns one hot stream into a thundering herd: every loser re-reads,
95
+ * re-computes and re-appends in lockstep, so they collide again on the same tick and the
96
+ * conflict rate is preserved rather than drained. Spreading the attempts over a random
97
+ * interval de-synchronizes them, which is what actually lets one of them win. The floor
98
+ * guarantees a non-zero wait even on the first retry (a zero-length "backoff" is not one),
99
+ * and the cap keeps a pathological stream from turning a retry budget into a stall.
100
+ *
101
+ * Budget across all 10 retries (attempts 0..9): floor 10×5ms plus a jitter window of
102
+ * 5+10+20+40+80+160+250+250+250+250 = 1315ms ⇒ **1365ms worst case, ~707ms mean**. Applies
103
+ * to the pooled path only (see the call site).
104
+ */
105
+ const occBackoffMs = (attempt) => OCC_BACKOFF_BASE_MS + Math.floor(Math.random() * Math.min(2 ** attempt * OCC_BACKOFF_BASE_MS, OCC_BACKOFF_CAP_MS));
106
+ const canSavepoint = (transaction) => typeof transaction.savepoint === 'function'
107
+ && typeof transaction.rollbackToSavepoint === 'function'
108
+ && typeof transaction.releaseSavepoint === 'function';
109
+ /**
110
+ * The concurrency mode a command actually runs under — resolved here and never read raw, so the
111
+ * default and the one illegal combination are decided in ONE place.
112
+ *
113
+ * `optimistic` is the default (see `CommandConcurrencyMode` for what each mode costs).
114
+ *
115
+ * A NON-AGGREGATE External System is `unversioned` BY CONSTRUCTION, whatever it declares: its
116
+ * load hands the commit `expectedVersion: null` (below), so every event it writes is stored
117
+ * version-free. Saying so here rather than letting it default to `optimistic` keeps the mode a
118
+ * true description of what reaches the append — which is what the savepoint gate keys on.
119
+ * ONE EXCEPTION, and it is not resolvable here: an aggregate command with a CUSTOM `load`
120
+ * (`multiStream`, `snapshot`'s delegating load aside) bypasses the derivation entirely and keeps
121
+ * whatever expectation its own load built, so its resolved mode describes the savepoint decision
122
+ * rather than the append. See the gate in `executeCommand` for what that costs.
123
+ *
124
+ * And that is exactly why an AGGREGATE may not declare `unversioned`: it would be asking to
125
+ * behave like a non-aggregate. An aggregate reduces its stream to state, and a stream whose
126
+ * events carry no version has no deterministic order to reduce in, so the same events could fold
127
+ * to a different state on every load. Refused LOUDLY — a silent fallback would produce precisely
128
+ * the unorderable stream, and it would be found much later, in the reduced state, by someone with
129
+ * no reason to suspect the declaration.
130
+ */
131
+ const resolveConcurrencyMode = (commandHandler, command) => {
132
+ if (command?.concurrency === 'unversioned' && commandHandler?.isAggregate)
133
+ throw new pv3_types_1.InternalServerError(`Command '${command.name}' on aggregate '${commandHandler.name}' declares concurrency: 'unversioned', which writes every event with version NULL. An aggregate REDUCES its stream to state, and a version-free stream has no deterministic order to reduce in, so the same events could fold to a different state on every load. Version-free streams belong to non-aggregate External Systems, which reduce nothing. Use 'optimistic' (the default), or 'rebase' if — and only if — this aggregate's events are provably commutative.`, 'UNVERSIONED_CONCURRENCY_ON_AGGREGATE', { aggregate: commandHandler.name, command: command.name });
134
+ return commandHandler?.isAggregate ? (command?.concurrency || 'optimistic') : 'unversioned';
135
+ };
136
+ const validation_1 = require("../../../libraries/validation");
137
+ const utils_1 = require("../../../utils");
138
+ const utils_2 = require("../utils");
139
+ const executionContext_1 = require("../executionContext");
140
+ const formatAggregateGetQueryParams = (params) => ({
141
+ stream: params.stream,
142
+ events: params.names,
143
+ direction: params.backward ? 'backwards' : 'forwards',
144
+ from: params.from,
145
+ limit: params.limit,
146
+ after: params.after,
147
+ before: params.before
148
+ });
149
+ exports.formatAggregateGetQueryParams = formatAggregateGetQueryParams;
150
+ const getEventReducers = (aggregate) => (reducedState /* = { state: aggregate.initialValue() } */, event) => {
151
+ const reducer = aggregate.eventReducers[event.name];
152
+ if (!reducer || reducer === pv3_types_1.ReducerNOOP)
153
+ return reducedState;
154
+ return {
155
+ ...reducedState,
156
+ state: reducer(reducedState.state, event.data, event.metadata)
157
+ };
158
+ };
159
+ exports.getEventReducers = getEventReducers;
160
+ const appendEventsToStream = (logger, eventstore, expectedVersion, transaction, retryAttempts = 0) => (events) => {
161
+ const stream = events[0].stream;
162
+ return events.length
163
+ ? eventstore.appendToStream(stream, events, expectedVersion, transaction)
164
+ .catch((err) => {
165
+ if (err.type === 'ConcurrencyError' && expectedVersion === null) {
166
+ if (retryAttempts >= 10) {
167
+ logger.error('Event', events[0].name, 'failed after 10 retries', err);
168
+ throw err;
169
+ }
170
+ logger.debug('Retrying event', events[0].name, 'due to ConcurrencyError', transaction ? 'with transaction' : 'without transaction');
171
+ return (0, exports.appendEventsToStream)(logger, eventstore, null, transaction, retryAttempts + 1)(events);
172
+ }
173
+ throw err;
174
+ })
175
+ : Promise.resolve([]);
176
+ };
177
+ exports.appendEventsToStream = appendEventsToStream;
178
+ const addMetadata = ({ metadata, context, stream }) => (event) => {
179
+ (0, ramda_1.mergeRight)(metadata || {}, event.metadata || {}); //?
180
+ return {
181
+ stream,
182
+ ...event,
183
+ metadata: {
184
+ ...(context?.user ? { userId: context.user.id } : {}),
185
+ ...(0, ramda_1.mergeRight)(metadata || {}, event.metadata || {})
186
+ }
187
+ };
188
+ };
189
+ exports.addMetadata = addMetadata;
190
+ const prepareEventsToCommit = (handlerState) => {
191
+ return Promise.resolve(handlerState.events)
192
+ .then(bett3r_utils_1.ensureArray)
193
+ .then((0, bett3r_utils_1.map)((eventFactory) => {
194
+ return { ...eventFactory() };
195
+ }))
196
+ .then((0, bett3r_utils_1.map)((0, exports.addMetadata)(handlerState)));
197
+ };
198
+ exports.prepareEventsToCommit = prepareEventsToCommit;
199
+ /**
200
+ * `expectedVersion` narrowed to the shape the SINGLE-stream append takes.
201
+ *
202
+ * It carries two shapes (see `CommandHandlerState.expectedVersion`): the scalar this
203
+ * path wants, and the per-stream MAP that `multiStream.commit` consumes. A map reaching
204
+ * here means a command paired a multi-stream `load` with the single-stream `commit` —
205
+ * mis-wired, and the one thing we must NOT do about it is coerce it to `undefined`:
206
+ * that would append with no version expectation at all, silently discarding the
207
+ * optimistic-concurrency control the load went to the trouble of computing. Fail loudly.
208
+ *
209
+ * Still exactly this guard now that the default commit can fan out to several streams
210
+ * (`appendEventsToOwnStreams` below): what it produces there is a SCALAR expectation routed to
211
+ * the one stream the load read, never a caller-built per-stream map. A map arriving here is the
212
+ * same mis-wiring it always was.
213
+ */
214
+ const singleStreamExpectedVersion = (expectedVersion, commandName) => {
215
+ if (expectedVersion !== null && typeof expectedVersion === 'object') {
216
+ throw new pv3_types_1.InternalServerError('A per-stream expectedVersion map reached the single-stream commit. The command\'s load produced a multi-stream expectation but its commit is not the multiStream template.', 'EXPECTED_VERSION_SHAPE_MISMATCH', { command: commandName, streams: Object.keys(expectedVersion) });
217
+ }
218
+ return expectedVersion;
219
+ };
220
+ /**
221
+ * The prepared events keyed by the stream each one actually TARGETS, in first-appearance order.
222
+ *
223
+ * A handler may emit onto a stream other than its aggregate's — `createEvent( name, data,
224
+ * { stream } )` puts a stream on the event and `addMetadata` spreads `stream` BEFORE `...event`,
225
+ * so the event's own stream wins. `Object.keys` preserves insertion order for non-numeric keys,
226
+ * so the aggregate's own stream keeps whatever position the handler gave it.
227
+ */
228
+ const groupEventsByStream = (events) => events.reduce((groups, event) => {
229
+ (groups[event.stream] ||= []).push(event);
230
+ return groups;
231
+ }, {});
232
+ /**
233
+ * The committed events back in the order the HANDLER emitted them.
234
+ *
235
+ * A multi-stream append returns its rows GROUPED BY STREAM, but the response is not a set:
236
+ * `formatEventSourcedCommandResponse` reduces `committedEvents` in array order into the state it
237
+ * returns, and hosts assert on `events[0].name`. So an interleaved emit (`companion, own,
238
+ * companion` — teselly's composite-release shape) must not come back regrouped.
239
+ *
240
+ * Each stream's rows keep their own relative order through the adapters (both build and insert a
241
+ * stream's events in the order given, and `RETURNING` follows the VALUES list), so re-threading
242
+ * the groups against the prepared events restores the emit order exactly. If the two ever fail to
243
+ * line up — which the adapters make impossible, since both prove nothing was dropped before
244
+ * returning — the adapter's own array is handed back untouched rather than silently short.
245
+ */
246
+ const inEmitOrder = (prepared, committed) => {
247
+ const queues = committed.reduce((grouped, event) => {
248
+ (grouped[event.stream] ||= []).push(event);
249
+ return grouped;
250
+ }, {});
251
+ const ordered = prepared.map((event) => queues[event.stream]?.shift());
252
+ return ordered.length === committed.length && ordered.every(Boolean)
253
+ ? ordered
254
+ : committed;
255
+ };
256
+ /**
257
+ * Append each prepared event to THE STREAM IT NAMES, asserting the expectation on THE STREAM THE
258
+ * LOAD READ and on no other.
259
+ *
260
+ * `defaultEventsourcingLoad` takes the head of `handlerState.stream` and records it as the
261
+ * command's expectation. A single `appendToStream` then targeted `events[0].stream` while
262
+ * carrying that number, so a handler emitting onto any other stream had its aggregate's head
263
+ * asserted against a stream nothing had ever compared it to — two streams, one number. It also
264
+ * numbered EVERY event off `events[0].stream`'s head + index, so a cross-stream command wrote
265
+ * per-stream version GAPS (which the outbox's per-stream watermark reads as missing events).
266
+ * Both close here.
267
+ */
268
+ const appendEventsToOwnStreams = (logger, eventstore, loadedStream, expectedVersion, transaction) => async (events) => {
269
+ if (!events.length)
270
+ return [];
271
+ /* `null` IS NOT AN ASSERTION ABOUT A HEAD — it declares the whole command version-FREE, so
272
+ * every event it writes is stored with `version = NULL` whatever stream it lands on. There is
273
+ * nothing per-stream to get right: no numbering happens, so no gaps can open, and nothing is
274
+ * compared, so no stream can be asserted wrongly. The single append is already exactly
275
+ * correct for it.
276
+ *
277
+ * Keeping it here is also what keeps `appendEventsToStream`'s `expectedVersion === null`
278
+ * RETRY LOOP on the only path that can ever reach it — the loop is not dropped, it is proven
279
+ * unreachable from the multi-stream route below, which never sees a null expectation.
280
+ *
281
+ * And routing it through `appendToMultipleStreams` would not be equivalent:
282
+ * `DatabaseEventstore`'s takes every stream's head unconditionally and would VERSION events
283
+ * that are version-free today, silently changing the class the outbox dedups them by. */
284
+ if (expectedVersion === null)
285
+ return (0, exports.appendEventsToStream)(logger, eventstore, null, transaction)(events);
286
+ const eventsByStream = groupEventsByStream(events);
287
+ const streams = Object.keys(eventsByStream);
288
+ // The expectation was computed from ONE stream's head — the stream the load reduced. Every
289
+ // other stream gets `undefined`: the append reads that stream's own head and numbers from it,
290
+ // asserting nothing. Never assert a head this command never read; on a stream whose head
291
+ // moves independently the two can never converge, so the "conflict" is unbreakable and burns
292
+ // the whole retry budget on a stream the command has no opinion about.
293
+ const expectationFor = (stream) => stream === loadedStream ? expectedVersion : undefined;
294
+ if (streams.length === 1)
295
+ return (0, exports.appendEventsToStream)(logger, eventstore, expectationFor(streams[0]), transaction)(events);
296
+ if (!eventstore.appendToMultipleStreams)
297
+ throw new pv3_types_1.InternalServerError('A command emitted events onto several streams but the Eventstore in use does not support multiple streams. Appending them as one stream would number every event off the first stream\'s head, leaving per-stream version gaps.', 'MULTI_STREAM_COMMANDS_NOT_SUPPORTED', { stream: loadedStream, streams });
298
+ const committed = await eventstore.appendToMultipleStreams(streams.reduce((perStream, stream) => {
299
+ perStream[stream] = { events: eventsByStream[stream], expectedVersion: expectationFor(stream) };
300
+ return perStream;
301
+ }, {}), transaction);
302
+ return inEmitOrder(events, committed);
303
+ };
304
+ exports.appendEventsToOwnStreams = appendEventsToOwnStreams;
305
+ const commitEvents = (logger, eventstore) => (handlerState, transaction) => {
306
+ if (!handlerState.events.length)
307
+ return Promise.resolve(handlerState);
308
+ const expectedVersion = singleStreamExpectedVersion(handlerState.expectedVersion, handlerState.command?.name);
309
+ return (0, exports.prepareEventsToCommit)(handlerState)
310
+ .then((0, exports.appendEventsToOwnStreams)(logger, eventstore, handlerState.stream, expectedVersion, transaction))
311
+ .then((0, ramda_1.objOf)('committedEvents'))
312
+ .then((0, ramda_1.mergeRight)(handlerState));
313
+ };
314
+ exports.commitEvents = commitEvents;
315
+ const getStreamReducer = (state, event) => {
316
+ state[event.stream] ||= { events: [], state: null };
317
+ state[event.stream].events?.push(event);
318
+ return state;
319
+ };
320
+ exports.getStreamReducer = getStreamReducer;
321
+ const loadStream = (eventstore) => (stream, options) => {
322
+ return eventstore.reduceStream({ ...options, stream }, exports.getStreamReducer, {})
323
+ .then((state) => !Object.keys(state).length
324
+ ? undefined
325
+ : state[stream].events);
326
+ };
327
+ exports.loadStream = loadStream;
328
+ const getNonNoopEventNames = (aggregate) => {
329
+ if (reducersByAggregateMap.has(aggregate.name)) {
330
+ return reducersByAggregateMap.get(aggregate.name) || [];
331
+ }
332
+ const nonNoopEvents = Object.entries(aggregate.eventReducers)
333
+ .filter(([, reducer]) => reducer !== pv3_types_1.ReducerNOOP)
334
+ .map(([name]) => name);
335
+ reducersByAggregateMap.set(aggregate.name, nonNoopEvents);
336
+ return nonNoopEvents;
337
+ };
338
+ exports.getNonNoopEventNames = getNonNoopEventNames;
339
+ const loadAggregateState = (eventstore) => (aggregate, stream, options, state = aggregate.initialValue()) => {
340
+ const nonNoopEvents = (0, exports.getNonNoopEventNames)(aggregate);
341
+ const eventFilter = options?.events
342
+ ? options.events.filter((name) => nonNoopEvents.includes(name))
343
+ : nonNoopEvents;
344
+ return !stream || !aggregate.isAggregate
345
+ ? Promise.resolve(null)
346
+ : eventstore.reduceStream({ ...options, stream, events: eventFilter }, (0, exports.getEventReducers)(aggregate), { state })
347
+ .then((_state) => {
348
+ return _state || { state };
349
+ });
350
+ };
351
+ exports.loadAggregateState = loadAggregateState;
352
+ const domainModelLoad = (database, collection, transaction) => (handlerState) => {
353
+ const innerTransactionOperation = (innerTransaction) => {
354
+ return innerTransaction
355
+ .getCollection(collection)
356
+ .readById(handlerState.params.id)
357
+ .then((state) => {
358
+ return (0, ramda_1.assoc)('state', state
359
+ ? (0, ramda_1.omit)(['id'], state)
360
+ : handlerState.commandHandler.initialValue(), handlerState);
361
+ });
362
+ };
363
+ return (transaction || handlerState.transaction) ? innerTransactionOperation(transaction || handlerState.transaction) : database.initTransaction(innerTransactionOperation);
364
+ };
365
+ exports.domainModelLoad = domainModelLoad;
366
+ exports.domainModelCommit = (0, ramda_1.curry)((logger, eventstore, database, collection, transaction) => async (handlerState) => {
367
+ const innerTransactionOperation = async (innerTransaction) => {
368
+ const { params, expectedVersion } = handlerState;
369
+ const initialValue = handlerState.commandHandler.initialValue();
370
+ const eventsToCommit = await (0, exports.prepareEventsToCommit)(handlerState);
371
+ if (eventsToCommit.length === 0) {
372
+ return handlerState;
373
+ }
374
+ // Snapshot-consistency fix: reduce the committed events onto the CURRENT persisted snapshot,
375
+ // re-read FOR UPDATE inside THIS transaction — NOT handlerState.state (the state loaded, unlocked,
376
+ // at the START of the command). The row lock is held until this transaction commits, so concurrent
377
+ // committers on the same aggregate serialize here; a late delta event (e.g. StructureAcked, whose
378
+ // reducer carries the whole prior state forward) then reduces onto the LATEST committed state and
379
+ // can never resurrect a nested key (a removed broker) that a concurrent commit dropped. This keeps
380
+ // the notEventsourced snapshot a faithful, serialized projection of the event log == a full replay.
381
+ const currentRow = await innerTransaction.getCollection(collection).readById(params.id, { forUpdate: true });
382
+ const currentState = currentRow ? (0, ramda_1.omit)(['id', 'version'], currentRow) : initialValue;
383
+ const { state, events } = (0, exports.reduceEventsIntoState)(currentState, handlerState.commandHandler, eventsToCommit);
384
+ let lastCommittedVersion = 0;
385
+ if (eventstore._adapter()._adapter().connectionId === database._adapter().connectionId) {
386
+ const state = await (0, exports.commitEvents)(logger, eventstore)(handlerState, innerTransaction);
387
+ lastCommittedVersion = state.committedEvents?.at(-1)?.version || 1;
388
+ }
389
+ else {
390
+ /* THE OUTBOX BRANCH HAS ITS OWN AUDIT LOG, AND ITS OWN WAY TO NUMBER IT.
391
+ *
392
+ * Nothing is appended to the eventstore here — the events land in `<collection>_outbox`
393
+ * — so there are no `committedEvents` to read a version off. The version is DERIVED
394
+ * instead, and it is derived from the one place that keeps it truthful: `currentRow`,
395
+ * the snapshot re-read FOR UPDATE a few lines above. That read is what the
396
+ * snapshot-consistency fix documented above rests on, and this reuses it rather than
397
+ * taking a second, unlocked one. The row lock is held until this transaction commits,
398
+ * so concurrent committers on the same aggregate serialize HERE, each one reading the
399
+ * version the previous one wrote and numbering from it. No gaps, no reuse.
400
+ *
401
+ * Why `+ events.length` is the same numbering the eventstore would have produced: the
402
+ * eventstore numbers an append from the stream head, head N -> N+1 … N+k, and the
403
+ * snapshot is by construction a faithful, serialized projection of that log — version N
404
+ * means N events precede this commit. Writing k more therefore puts the head at N + k,
405
+ * which is a POSITION in the audit log and not a counter that merely increases.
406
+ */
407
+ const currentVersion = Number(currentRow?.version ?? 0);
408
+ lastCommittedVersion = currentVersion + events.length;
409
+ await innerTransaction
410
+ .getCollection(`${collection}_outbox`)
411
+ .createMany(events.map((e) => (0, ramda_1.assoc)('id', (0, uuidv7_1.uuidv7)(), e)));
412
+ }
413
+ // REPLACE (not merge) the snapshot with the fully-reduced state: it is the COMPLETE aggregate
414
+ // state, so a merge could only accumulate stale nested keys a reducer dropped (e.g. a removed
415
+ // broker never leaving `brokers`) — the eventstore_cluster ↔ cluster_infrastructure divergence.
416
+ if (expectedVersion) {
417
+ const updated = await innerTransaction.getCollection(collection).updateMany([
418
+ { field: 'id', op: 'eq', value: params.id },
419
+ { field: 'version', op: 'eq', value: expectedVersion }
420
+ ], { ...state, version: lastCommittedVersion }, { replace: true });
421
+ /* A COMPARE-AND-SET THAT MATCHED NOTHING IS A LOST COMMAND, NOT A SUCCESS.
422
+ *
423
+ * `updateMany` reports the rows it wrote, and this write is a CAS —
424
+ * `WHERE id = … AND version = expectedVersion`. Discarding that result made a failed
425
+ * assertion indistinguishable from a satisfied one: the caller was told it won, the
426
+ * audit row had already been written, and the snapshot never moved. Raising here is
427
+ * what makes the assertion mean something, and it rolls the audit row back with it.
428
+ *
429
+ * `ConcurrencyError` specifically, because that is the type the command pipeline knows:
430
+ * a command that asserted its OWN expectation (`?expectedVersion=`) gets the 409, while
431
+ * one whose expectation the library derived is re-run against fresh state.
432
+ */
433
+ if (!updated.length)
434
+ throw new pv3_types_1.ConcurrencyError(`Concurrency Error: the ${collection} snapshot for '${params.id}' is no longer at the expected version ${expectedVersion}`, 'SNAPSHOT_EXPECTED_VERSION_MISMATCH');
435
+ }
436
+ else {
437
+ if (state !== null) {
438
+ await innerTransaction
439
+ .getCollection(collection)
440
+ .upsert(handlerState.params.id, {
441
+ ...state,
442
+ version: lastCommittedVersion
443
+ }, { replace: true });
444
+ }
445
+ else {
446
+ await innerTransaction
447
+ .getCollection(collection)
448
+ .destroyById(handlerState.params.id);
449
+ }
450
+ }
451
+ return {
452
+ ...handlerState,
453
+ state
454
+ };
455
+ };
456
+ return (transaction || handlerState.transaction) ? innerTransactionOperation(transaction || handlerState.transaction) : database.initTransaction(innerTransactionOperation);
457
+ });
458
+ const defaultHandler = (eventsProducedByCommand) => (_1, _2, data) => {
459
+ return Promise.all((eventsProducedByCommand || []).map((e) => () => ({
460
+ name: e,
461
+ data
462
+ })));
463
+ };
464
+ exports.defaultHandler = defaultHandler;
465
+ const defaultCommit = (logger, eventstore) => (state) => {
466
+ if (!state.transaction || (state.transaction && eventstore.getConnectionId() === state.transaction?.connectionId)) {
467
+ return (0, exports.commitEvents)(logger, eventstore)(state, state.transaction);
468
+ }
469
+ else {
470
+ logger.error('Attempting to Transactionally commit events with a transaction belonging to a different database. Dying now');
471
+ logger.info(state);
472
+ process.exit(1);
473
+ }
474
+ };
475
+ exports.defaultCommit = defaultCommit;
476
+ const reduceEventsIntoState = (initialState, commandHandler, events) => {
477
+ const _state = events.reduce((0, exports.getEventReducers)(commandHandler), { state: initialState });
478
+ return { events, state: _state.state };
479
+ };
480
+ exports.reduceEventsIntoState = reduceEventsIntoState;
481
+ const formatDomainModelCommandResponse = (handlerState) => {
482
+ return Promise.resolve({
483
+ state: handlerState.state
484
+ });
485
+ };
486
+ exports.formatDomainModelCommandResponse = formatDomainModelCommandResponse;
487
+ const formatEventSourcedCommandResponse = async (handlerState) => {
488
+ const { commandHandler, state } = handlerState;
489
+ // Default to [] (not undefined) so an empty-event command still returns an
490
+ // `events: []` response. Mirrors the snapshot command-template's `format`
491
+ // (`committedEvents || []`); without this the response shape diverges between
492
+ // snapshotted and non-snapshotted aggregates (a no-event command returns
493
+ // `{ state }` with no `events` key here, but `{ events: [], state }` there).
494
+ const committedEvents = handlerState.committedEvents || [];
495
+ if (!commandHandler.isAggregate) {
496
+ return Promise.resolve({ events: committedEvents });
497
+ }
498
+ return (0, exports.reduceEventsIntoState)(state, commandHandler, committedEvents);
499
+ };
500
+ exports.formatEventSourcedCommandResponse = formatEventSourcedCommandResponse;
501
+ const validateInvariants = (invariants) => (state) => {
502
+ return invariants.reduce((success, invariant) => {
503
+ return success
504
+ .then((state) => invariant.check(state))
505
+ .then((resultState) => resultState || state);
506
+ }, Promise.resolve(state));
507
+ };
508
+ exports.validateInvariants = validateInvariants;
509
+ const checkIdempotency = (idempotencyChecks) => (state) => {
510
+ return idempotencyChecks.reduce((success, idempotencyCheck) => {
511
+ return success
512
+ .then((state) => idempotencyCheck.check(state))
513
+ .then((resultState) => resultState || state);
514
+ }, Promise.resolve(state));
515
+ };
516
+ const defaultEventsourcingLoad = (eventstore) => async (handlerState, options, state) => {
517
+ /* ⚠ THE HEAD READ IS STRICTLY BEFORE THE REDUCE. Do not swap these two statements.
518
+ *
519
+ * The command runs inside `initTransaction` (see `executeCommand` below) at READ COMMITTED,
520
+ * so EVERY STATEMENT GETS ITS OWN SNAPSHOT and a concurrent commit can land between two of
521
+ * them. Which of the two runs first is therefore the whole correctness of this change:
522
+ *
523
+ * head -> reduce (this order) — head <= what we reduced. An interleaving writer means we
524
+ * reduced MORE than the version we assert, the commit's assertion FAILS CLOSED, and the
525
+ * command retries against the winner's state. Costs at worst a spurious retry.
526
+ * (`head <= reduced` holds while both reads are POOL-EQUIVALENT. The head read below is
527
+ * never pool-SCOPED — it passes the transaction on purpose, see the last paragraph — but
528
+ * on the default path that transaction is the one `executeCommand` opened for this command
529
+ * and it has not written this stream yet, so it answers exactly what a pool read would.
530
+ * It does NOT hold inside a caller-owned transaction that has ALREADY appended to THIS
531
+ * stream: there the head sees those uncommitted rows and `loadAggregateState`, which
532
+ * reduces through the pool, does not. That exposure predates this read — the reduce was
533
+ * already pool-scoped and there was no assertion at all — and it cannot produce a conflict,
534
+ * since both the head here and the head the append numbers from come from the same
535
+ * per-transaction cache. Fixing it means giving the reduce the transaction, its own change.)
536
+ * reduce -> head (reversed) — head >= what we reduced. We would assert version 7 having
537
+ * only reduced 1-5, the assertion PASSES, and a decision computed on stale state gets
538
+ * committed. That is precisely the lost update this change exists to remove.
539
+ *
540
+ * Reversing them produces NO type error and NO other test failure — the tripwire is the
541
+ * ordering case in `occLoadTimeExpectation.deps.test.ts`.
542
+ *
543
+ * The expectation comes from the HEAD, never from the reduce: the reduce is filtered by
544
+ * event name at the SQL level (`getNonNoopEventNames`) and yields only `{ state }`, so the
545
+ * greatest version among the events it saw sits permanently behind the head on any stream
546
+ * carrying a `ReducerNOOP` event or another writer's event. Sourcing it there would make
547
+ * every command on such a stream conflict, burn its whole retry budget and fail forever.
548
+ *
549
+ * And the transaction is passed on purpose: inside a caller-owned transaction that has
550
+ * already appended to this stream, a pool read would miss those uncommitted appends, assert
551
+ * a head the commit can never agree with, and retry to exhaustion.
552
+ */
553
+ /* The command's declared mode, spelled out as the three things the append can be told. This is
554
+ * the whole of the dispatch — the adapters already branch on exactly these values:
555
+ *
556
+ * optimistic — the head read below: assert it, and conflict when it moved.
557
+ * rebase — `undefined`: the append reads the head itself and numbers from it, asserting
558
+ * NOTHING. Per-stream order survives; conflict DETECTION does not. The head read
559
+ * is skipped rather than taken and discarded, so a mode that asserts nothing
560
+ * also costs nothing.
561
+ * unversioned — `null`: every event is written version-free. Unreachable for an aggregate
562
+ * (`resolveConcurrencyMode` refuses it) and reachable here only for a
563
+ * non-aggregate that borrowed this load through a custom template, which is
564
+ * already what the non-aggregate load gives it.
565
+ */
566
+ const concurrency = resolveConcurrencyMode(handlerState.commandHandler, handlerState.command);
567
+ const expectedVersion = handlerState.expectedVersion !== undefined
568
+ // An expectation SUPPLIED by the caller is never overwritten — the test is "was one
569
+ // supplied at all", not "was it exactly null". `null` means "version-free stream", and a
570
+ // custom load may have built a per-stream map; a null-only carve-out would clobber both.
571
+ ? handlerState.expectedVersion
572
+ : concurrency === 'rebase'
573
+ ? undefined
574
+ : concurrency === 'unversioned'
575
+ ? null
576
+ : await eventstore.getStreamVersion(handlerState.stream, handlerState.transaction);
577
+ const reducedState = await (0, exports.loadAggregateState)(eventstore)(handlerState.commandHandler, handlerState.stream, options, state ||
578
+ handlerState.state ||
579
+ handlerState.commandHandler.initialValue());
580
+ return {
581
+ ...handlerState,
582
+ expectedVersion,
583
+ state: reducedState?.state
584
+ };
585
+ };
586
+ exports.defaultEventsourcingLoad = defaultEventsourcingLoad;
587
+ const handleCommand = (handler) => async (handlerState) => {
588
+ const { state, data } = handlerState;
589
+ handlerState.events = await Promise.resolve()
590
+ .then(() => handler((0, utils_1.createEvent)(handlerState.commandHandler), state ? (0, ramda_1.clone)(state) : null, (0, ramda_1.clone)(data), handlerState))
591
+ .then((events) => {
592
+ return [...handlerState.events, ...events];
593
+ });
594
+ return handlerState;
595
+ };
596
+ exports.handleCommand = handleCommand;
597
+ const createCommandHandlers = (logger, endpoint, eventstore, metadataSchema, formatMetadataFromContext = () => ({}), instrumentCommandExecution) => {
598
+ const internalExecuteCommand = (commandHandler, commandName, transaction) => async (actionParams) => {
599
+ const command = commandHandler.commands[commandName]
600
+ .build
601
+ ? commandHandler.commands[commandName].build()
602
+ : commandHandler.commands[commandName];
603
+ command.name = commandName;
604
+ const start = Date.now();
605
+ logger.log('Processing Command', commandName, 'in', commandHandler.isAggregate ? 'Aggregate' : 'External System', commandHandler.name);
606
+ const alsContext = (0, executionContext_1.getExecutionContext)();
607
+ const { body, params, query, context: explicitContext } = actionParams;
608
+ // Merge: explicit params > ALS > defaults
609
+ const context = (explicitContext?.user
610
+ ? explicitContext
611
+ : alsContext
612
+ ? { ...explicitContext, user: { id: alsContext.userId, accountId: alsContext.accountId, impersonatedBy: alsContext.impersonatedBy } }
613
+ : explicitContext);
614
+ const id = command.dataPropertyId
615
+ ? (0, utils_2.existsPath)(command.dataPropertyId.split('.'), body)
616
+ : params?.id;
617
+ if ((commandHandler.isStreamable || commandHandler.isAggregate) && !id) {
618
+ throw Error(`Command requires an id to be executed for commandHandler ${commandHandler.name} and command ${command.name}`);
619
+ }
620
+ // Non-streamable, non-aggregate systems with no supplied id emit null-version,
621
+ // order-free events. Fan them out by varying the stream id with a random bounded
622
+ // token (affects ONLY `stream`; `id` stays untouched for downstream use).
623
+ const streamId = (!id && !command.dataPropertyId && !commandHandler.isAggregate && !commandHandler.isStreamable)
624
+ ? (0, utils_2.randomStreamSuffix)()
625
+ : id;
626
+ const stream = (0, utils_2.formatStream)(commandHandler.name, streamId);
627
+ const mergedQuery = query || {};
628
+ const correlationId = mergedQuery.correlationId || alsContext?.correlationId;
629
+ const causationId = mergedQuery.causationId || alsContext?.causationId;
630
+ const handlerState = {
631
+ command,
632
+ data: body,
633
+ query,
634
+ params,
635
+ context,
636
+ stream,
637
+ events: [],
638
+ commandHandler,
639
+ expectedVersion: query?.expectedVersion,
640
+ state: undefined,
641
+ metadata: {
642
+ // Ambient execution TAGS ride NESTED under `metadata.tags`, never spread, so a
643
+ // tag can never collide with (or forge) a reserved metadata key. Written FIRST
644
+ // so the reserved keys below always win even if a host's
645
+ // `formatMetadataFromContext` were to emit its own `tags`.
646
+ ...(alsContext?.tags ? { tags: alsContext.tags } : {}),
647
+ correlationId: correlationId || getActiveTraceId() || (0, uuidv7_1.uuidv7)(),
648
+ causationId,
649
+ ...formatMetadataFromContext(context || {})
650
+ },
651
+ transaction
652
+ };
653
+ const loadFunction = command.load ||
654
+ (!commandHandler.isAggregate
655
+ ? (state) => ({ ...state, expectedVersion: null })
656
+ : commandHandler.isEventsourced
657
+ ? (0, exports.defaultEventsourcingLoad)(eventstore)
658
+ : (0, exports.domainModelLoad)(commandHandler.outboxDatabase, commandHandler.outboxCollection));
659
+ const commitFunction = command.commit ||
660
+ (commandHandler.isEventsourced
661
+ ? (0, exports.defaultCommit)(logger, eventstore)
662
+ : (0, exports.domainModelCommit)(logger, eventstore, commandHandler.outboxDatabase, commandHandler.outboxCollection, undefined));
663
+ const formatFunction = command.format ||
664
+ (commandHandler.isEventsourced
665
+ ? exports.formatEventSourcedCommandResponse
666
+ : exports.formatDomainModelCommandResponse);
667
+ const executePreProcessing = (state) => {
668
+ if (!command.preProcessing) {
669
+ return Promise.resolve(state);
670
+ }
671
+ return Promise.resolve(command.preProcessing(state))
672
+ .then((newData) => ({
673
+ ...state,
674
+ data: newData
675
+ }));
676
+ };
677
+ const executePipeline = () => Promise.resolve(handlerState)
678
+ .then(loadFunction)
679
+ .then(executePreProcessing)
680
+ .then(checkIdempotency(command.idempotencyChecks || []))
681
+ .then((0, exports.validateInvariants)(command.invariants || []))
682
+ .then((0, exports.handleCommand)(command.handler || (0, exports.defaultHandler)(command.events)))
683
+ .then(commitFunction)
684
+ .catch((err) => {
685
+ if (err.ignore === '--IdempotencyCheck--') {
686
+ // Pure side effect at the skip site — `add` is no-throw; control flow is
687
+ // unchanged (still resolve with `err.handlerState`). Low-cardinality labels:
688
+ // command + aggregate names only (never ids).
689
+ getIdempotencySkipCounter()?.add(1, { command: commandName, aggregate: commandHandler.name });
690
+ return err.handlerState;
691
+ }
692
+ return Promise.reject(err);
693
+ })
694
+ .then(formatFunction)
695
+ .then((result) => {
696
+ logger.log('Command', commandName, ' Processed in', ((Date.now() - start) / 1000).toFixed(2), 's');
697
+ return result;
698
+ });
699
+ return instrumentCommandExecution
700
+ ? instrumentCommandExecution({
701
+ commandName: commandName,
702
+ aggregateName: commandHandler.name,
703
+ stream,
704
+ isAggregate: !!commandHandler.isAggregate,
705
+ correlationId: handlerState.metadata?.correlationId,
706
+ causationId: handlerState.metadata?.causationId,
707
+ payload: handlerState.data
708
+ }, executePipeline)
709
+ : executePipeline();
710
+ };
711
+ const executeCommand = (commandHandler, commandName, transaction, schemas, retryAttempts = 0, occSavepoint) => async (actionParams) => {
712
+ const command = commandHandler.commands[commandName]
713
+ .build
714
+ ? commandHandler.commands[commandName].build()
715
+ : commandHandler.commands[commandName];
716
+ schemas = schemas || getCommandSchemas(commandHandler, command);
717
+ command.name = commandName;
718
+ // Resolved BEFORE anything is opened or executed, so a command declaring the one illegal
719
+ // combination (`unversioned` on an aggregate) fails at the door instead of half-way
720
+ // through a transaction it already wrote to.
721
+ const concurrency = resolveConcurrencyMode(commandHandler, command);
722
+ const innerTransactionOperation = async (transaction) => {
723
+ return Promise.resolve(actionParams)
724
+ .then((0, validation_1.validateEndpoint)(validation_1.validateSchema, schemas, true))
725
+ .then(internalExecuteCommand(commandHandler, commandName, transaction));
726
+ };
727
+ /* ── THE REWIND POINT, TAKEN ONCE, BEFORE THE FIRST ATTEMPT ──────────────────────────
728
+ *
729
+ * Only for a transaction the CALLER owns. When we open the transaction ourselves (below)
730
+ * a failed attempt is discarded wholesale by `initTransaction`'s rollback, and the retry
731
+ * starts a brand-new one — there is nothing to rewind.
732
+ *
733
+ * ESTABLISHED EXACTLY ONCE, AT `retryAttempts === 0`, and carried through the retries.
734
+ * `occSavepoint` is that carried token; it is set only by the recursive call, which is
735
+ * why it doubles as "an attempt already took one".
736
+ *
737
+ * The reason is ECONOMY, not correctness — be precise about this, because the obvious
738
+ * story is wrong. A per-attempt savepoint would NOT rewind less: the rollback below runs
739
+ * strictly BEFORE the recursive call, so each new savepoint would be taken against an
740
+ * already-clean state and would behave identically on the data. What it would cost is one
741
+ * extra round trip AND one extra Postgres SUBTRANSACTION per attempt. Subtransactions are
742
+ * the scarce thing: a top-level transaction keeps every subtransaction XID it ever
743
+ * assigned in its `PGPROC` list for its whole life — `RELEASE SAVEPOINT` ends the nesting
744
+ * but does NOT give the XID back — and past `PGPROC_MAX_CACHED_SUBXIDS` (64) its snapshot
745
+ * goes suboverflowed, pushing every other backend's visibility checks into the
746
+ * `pg_subtrans` SLRU. One caller-owned transaction that runs many commands (item merge's
747
+ * nested loops) is already close to that ceiling at one savepoint per COMMAND; one per
748
+ * ATTEMPT would multiply it by the retry budget exactly when contention is highest.
749
+ *
750
+ * AND ONLY FOR AN `optimistic` COMMAND. That is the only mode that can lose a conflict it
751
+ * did not cause — it asserts a head it read, so another writer's commit invalidates it and
752
+ * the retry needs a clean state to resume from. `rebase` asserts nothing and `unversioned`
753
+ * writes version-free rows the unique index cannot catch, so neither has a conflict a
754
+ * rewind would help with; a subtransaction spent on them buys nothing. The consequence is
755
+ * deliberate and is the same rule slice 3 set: no rewind means NO RETRY inside a
756
+ * caller-owned transaction, so a `rebase` command that does hit a genuine INSERT collision
757
+ * there propagates to the transaction's owner instead of re-executing on top of its own
758
+ * unrewound rows. On the pooled path — where `rebase`'s retry actually lives — nothing
759
+ * changes.
760
+ *
761
+ * WHAT THIS GATE DOES NOT DO, since `optimistic` is the DEFAULT: it excludes only commands
762
+ * that explicitly declare `rebase`/`unversioned` and non-aggregate External Systems. It
763
+ * does NOT bound the subtransaction accumulation described above for a caller-owned
764
+ * transaction that issues many DEFAULT commands (teselly's `itemMerge.endpoints.ts` opens
765
+ * one transaction and runs commands inside five data-driven nested loops) — that
766
+ * transaction still passes `PGPROC_MAX_CACHED_SUBXIDS` and still goes suboverflowed. That
767
+ * remains a carried risk of running many commands on one transaction, not something this
768
+ * narrowing solves.
769
+ *
770
+ * Nor does it exclude an aggregate command with a CUSTOM `load` — `multiStream` above all.
771
+ * Such a command never runs `defaultEventsourcingLoad`, so it derives no expectation from
772
+ * the mode, yet it declares nothing and therefore resolves to `optimistic` and spends a
773
+ * savepoint here. That is the one population where the resolved mode is not a literal
774
+ * description of what its append asserts, and it is not a rounding error: every
775
+ * `multiStream(…)` command in the known host is in it, and they are precisely the commands
776
+ * run inside caller-owned transactions. Left as-is deliberately — their per-stream
777
+ * expectation map DOES carry real expectations, so a rewind is not obviously wasted, and
778
+ * narrowing this further is a behavior change with no oracle behind it.
779
+ */
780
+ const rewindable = transaction && concurrency === 'optimistic' && canSavepoint(transaction) ? transaction : undefined;
781
+ const savepoint = occSavepoint ?? (rewindable ? await rewindable.savepoint() : undefined);
782
+ const establishedHere = !!savepoint && !occSavepoint;
783
+ const executionPromise = transaction ? innerTransactionOperation(transaction) : eventstore._adapter().initTransaction?.(innerTransactionOperation) || innerTransactionOperation();
784
+ const attempt = executionPromise.catch(async (err) => {
785
+ if (err instanceof pv3_types_1.ValidationError) {
786
+ logger.error('Validation Error executing command', commandName, 'in', commandHandler.name, err);
787
+ }
788
+ /* ── ONLY THE LIBRARY'S OWN EXPECTATION IS THE LIBRARY'S TO RETRY ───────────────────
789
+ *
790
+ * `!= null` — a NULL/UNDEFINED comparison, deliberately not a falsy one. `0` is a real
791
+ * expectation ("this stream must be EMPTY"), and a falsy test read it as "the caller
792
+ * supplied nothing", so a caller pinning 0 was retried into a stream that already had
793
+ * events in it — against an expectation that, unlike a derived one, can never become
794
+ * true on a later attempt. It burned the whole budget and then failed anyway.
795
+ *
796
+ * And it keys on the CALLER-SUPPLIED `query`, never on `handlerState.expectedVersion`,
797
+ * which slice 2 now fills in for every optimistic command — keying on the derived one
798
+ * would make retry unreachable for the entire default path. The split is the semantics:
799
+ * an expectation the library DERIVED from the head it just read is a race it can
800
+ * resolve by re-reading, so it retries; an expectation the caller PINNED encodes a
801
+ * decision the caller made about a specific version, so re-running the handler against
802
+ * a different version would answer a question nobody asked. That one propagates. */
803
+ const isOccRetryable = err.type === 'ConcurrencyError' && actionParams.query?.expectedVersion == null;
804
+ // The generic "gave up" line, kept for the tail case it still covers: `retryAttempts`
805
+ // only ever advances on a ConcurrencyError, so reaching the ceiling with some OTHER
806
+ // error means the final attempt failed for a different reason. When it IS an OCC
807
+ // exhaustion the dedicated line below says strictly more, so this one stands down —
808
+ // one failure, one error log.
809
+ if (retryAttempts >= OCC_RETRY_CEILING && !isOccRetryable) {
810
+ logger.error('Command', commandName, 'in', commandHandler.name, `failed after ${OCC_RETRY_CEILING} retries`, err);
811
+ }
812
+ if (isOccRetryable) {
813
+ // Bounded labels — see the instrument block at the top of this file for why the
814
+ // contended stream is logged rather than labelled.
815
+ const occLabels = { command: commandName, aggregate: commandHandler.name };
816
+ if (retryAttempts < OCC_RETRY_CEILING && transaction && !rewindable) {
817
+ /* ── A TRANSACTION WE CANNOT REWIND IS NOT RETRIED ─────────────────────────
818
+ *
819
+ * The transaction is the CALLER's and it is still open, holding whatever this
820
+ * attempt already wrote through it (the append that lost is not necessarily the
821
+ * only thing the command did). Re-executing here would run the whole command a
822
+ * second time ON TOP OF those uncommitted rows: the load would read them back as
823
+ * if they were somebody's committed history, and the append would number itself
824
+ * from work that the caller may be about to roll away.
825
+ *
826
+ * So the conflict goes to the caller, who OWNS the transaction and is the only
827
+ * party that can end it. Deliberately BEFORE the instruments below: this is not a
828
+ * retry and must not be counted as one. The absence of the capability can never
829
+ * silently become an unsafe retry — that is the whole point of detecting it.
830
+ *
831
+ * TWO ways to land here, and the log says which: the transaction cannot savepoint at
832
+ * all (MemoryDb, Mongo), or no rewind point was taken because this command is not
833
+ * `optimistic` (the gate above). Same refusal, same reason — nothing can rewind this
834
+ * attempt's partial rows — but they are diagnosed differently, so they are named.
835
+ *
836
+ * "RESOLVES TO", not "declares": the mode may be the command's own declaration or the
837
+ * one `resolveConcurrencyMode` assigns it, and a non-aggregate External System reads
838
+ * as `unversioned` having declared nothing at all. Saying "declares" would send the
839
+ * reader looking for a declaration that is not in the source. */
840
+ const noRewindReason = canSavepoint(transaction)
841
+ ? `the command resolves to concurrency: '${concurrency}', so no rewind point was taken`
842
+ : 'the caller-supplied transaction cannot SAVEPOINT';
843
+ logger.error('Command', commandName, 'in', commandHandler.name, 'lost an optimistic-concurrency check on stream', err.details?.stream, `— NOT retried: ${noRewindReason}, so a retry would re-execute on top of this attempt's own uncommitted rows. Propagating to the transaction's owner`, err);
844
+ }
845
+ else if (retryAttempts < OCC_RETRY_CEILING) {
846
+ /* ── BACKOFF ONLY WHEN WE OWN THE TRANSACTION ──────────────────────────────
847
+ *
848
+ * A caller-supplied `transaction` is still OPEN here: the rejection came from
849
+ * `innerTransactionOperation( transaction )` above, which — unlike the pooled
850
+ * path — does not commit-or-rollback-and-release before rejecting. The
851
+ * transaction is the caller's to end, so its BEGIN is live, and under PgBouncer
852
+ * TRANSACTION POOLING an open transaction PINS one server backend out of a
853
+ * small pool (`default_pool_size`). Sleeping there would pin a scarce backend
854
+ * while doing nothing at all, and the callers that take this path are exactly
855
+ * the fan-out ones — bulk item/stock writes, item merge, publication batch
856
+ * editing — where several such commands run concurrently. That converts a
857
+ * herd-breaking measure into a pool-exhaustion one.
858
+ *
859
+ * Nothing is lost by not sleeping: the caller-owned path now REWINDS below, so it
860
+ * re-executes from the state its first attempt began with rather than on top of
861
+ * its own partial rows.
862
+ *
863
+ * Recorded as `0` rather than skipped, so "how much of this command's latency
864
+ * was backoff" stays answerable — and so the two paths are distinguishable in
865
+ * the histogram instead of one of them silently vanishing from it. */
866
+ const backoffMs = transaction ? 0 : occBackoffMs(retryAttempts);
867
+ // Pure side effects — both instruments are no-throw, so control flow below is
868
+ // exactly what it was before.
869
+ getOccInstruments()?.retry.add(1, occLabels);
870
+ getOccInstruments()?.backoff.record(backoffMs, occLabels);
871
+ logger.debug('Retrying command', commandName, 'in', commandHandler.name, 'due to ConcurrencyError on stream', err.details?.stream, `— attempt ${retryAttempts + 1}/${OCC_RETRY_CEILING} after ${backoffMs}ms`, transaction ? 'with transaction' : 'without transaction');
872
+ // De-synchronize the losers before they collide again on the same tick.
873
+ if (backoffMs)
874
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
875
+ if (rewindable && savepoint) {
876
+ // Discard everything this attempt wrote through the caller's transaction, back to
877
+ // the point the FIRST attempt started from. The transaction survives it: the
878
+ // conflict was raised by us, not by Postgres — the statement completed (that is
879
+ // what `ON CONFLICT` buys) — so this is a healthy transaction, not an aborted one.
880
+ await rewindable.rollbackToSavepoint(savepoint);
881
+ // IMMEDIATELY after the rollback, and the ordering is the point: an eventstore may
882
+ // cache per-transaction state that was only true while those rows existed
883
+ // (`PostgresEventstore` caches the head version of every stream the transaction
884
+ // appended to). Left in place it would go on claiming rows the rollback deleted,
885
+ // and the next append would number itself from a version that no longer exists —
886
+ // a permanent gap, silently, on a run that otherwise looks green.
887
+ eventstore.forgetTransactionState?.(rewindable);
888
+ }
889
+ return executeCommand(commandHandler, commandName, transaction, schemas, retryAttempts + 1, savepoint)(actionParams);
890
+ }
891
+ else {
892
+ // The budget is spent and NOTHING was committed. This is the alertable event: the
893
+ // caller's intent — an order's stock decrement, a ledger posting — did not happen.
894
+ getOccInstruments()?.exhausted.add(1, occLabels);
895
+ logger.error('Command', commandName, 'in', commandHandler.name, `EXHAUSTED ${OCC_RETRY_CEILING} optimistic-concurrency retries on stream`, err.details?.stream, '— nothing was committed', err);
896
+ }
897
+ }
898
+ if (command.onErrorHandler)
899
+ return command.onErrorHandler(err, actionParams.body);
900
+ return Promise.reject(err);
901
+ });
902
+ if (!establishedHere || !rewindable || !savepoint)
903
+ return attempt;
904
+ const result = await attempt;
905
+ /* Release only the savepoint this call ESTABLISHED, and only once the whole retry chain
906
+ * has SUCCEEDED. Releasing merges the subtransaction into its parent and frees its
907
+ * resource owner — it undoes nothing, and it keeps the nesting flat so a later
908
+ * `ROLLBACK TO` cannot land on a stale inner point.
909
+ *
910
+ * It does NOT stop subtransactions from accumulating, and must not be read as if it did:
911
+ * the released subtransaction's XID stays in the top-level transaction's `PGPROC` subxid
912
+ * list until that transaction ends, so a caller-owned transaction issuing more than
913
+ * `PGPROC_MAX_CACHED_SUBXIDS` (64) commands still goes suboverflowed. That is a CARRIED
914
+ * RISK of running many commands on one transaction (`itemMerge.endpoints.ts`), recorded
915
+ * as such — releasing is hygiene, not a cure.
916
+ *
917
+ * Not released on the failure path on purpose: the transaction may be aborted by then, and
918
+ * `RELEASE SAVEPOINT` would throw and MASK the caller's real error. Postgres discards every
919
+ * savepoint when the transaction ends, so the only cost of skipping it is the memory of a
920
+ * transaction that is about to end anyway.
921
+ *
922
+ * A failure to release does NOT fail a command that already committed its events: the
923
+ * caller would see an error for work that actually happened and could reasonably re-issue
924
+ * it, duplicating the events. One leaked savepoint on a transaction its owner is about to
925
+ * end is the cheaper of the two. */
926
+ try {
927
+ await rewindable.releaseSavepoint(savepoint);
928
+ }
929
+ catch (releaseError) {
930
+ logger.warn('Command', commandName, 'in', commandHandler.name, 'could not release its optimistic-concurrency savepoint; the command itself succeeded', releaseError);
931
+ }
932
+ return result;
933
+ };
934
+ const getCommandSchemas = (commandHandler, command, name) => {
935
+ const eventsSchemas = command.events?.reduce((schemas, eventName) => {
936
+ if (!!commandHandler.events[eventName])
937
+ schemas[eventName] = commandHandler.events[eventName]().schema || jsonschema_definer_1.default.null();
938
+ if (schemas[eventName])
939
+ schemas[eventName] = schemas[eventName].id(eventName);
940
+ return schemas;
941
+ }, {});
942
+ const responses = !eventsSchemas || Object.keys(eventsSchemas).length === 0
943
+ ? {
944
+ 200: [{
945
+ schema: jsonschema_definer_1.default.shape({
946
+ state: commandHandler.schema.id(`${commandHandler.name}State`)
947
+ }),
948
+ name: 'OK'
949
+ }]
950
+ }
951
+ : {
952
+ 200: [{
953
+ schema: commandHandler.isAggregate
954
+ ? jsonschema_definer_1.default.shape({
955
+ state: commandHandler.schema.id(`${commandHandler.name}State`),
956
+ events: (0, pv3_types_1.CommittedEventSchema)(jsonschema_definer_1.default.anyOf(...Object.values(eventsSchemas)), Object.keys(eventsSchemas))
957
+ })
958
+ : jsonschema_definer_1.default.shape({
959
+ events: (0, pv3_types_1.CommittedEventSchema)(jsonschema_definer_1.default.anyOf(...Object.values(eventsSchemas)), Object.keys(eventsSchemas))
960
+ }),
961
+ name: 'OK'
962
+ }]
963
+ };
964
+ command.schema.id(command.name || name);
965
+ const query = pv3_types_1.CommandEndpointQuerySchema;
966
+ return {
967
+ query,
968
+ body: command.schema,
969
+ responses,
970
+ // If it has dataPropertyId, it is a multiStream command, so it does not need params
971
+ ...(commandHandler.isStreamable && !command.dataPropertyId
972
+ ? { params: pv3_types_1.SystemEndpointParamsSchema }
973
+ : {})
974
+ };
975
+ };
976
+ const registerCommandHandlerGetEndpoints = (commandHandler, name = commandHandler.name) => {
977
+ const isStreamable = !!commandHandler.eventReducers ||
978
+ commandHandler.isStreamable;
979
+ const [streamRoute, idRoute] = (0, utils_1.getCommandHandlerGetRoutes)(isStreamable ? 'aggregate' : 'system', commandHandler);
980
+ if (!commandHandler.isEventsourced && !commandHandler.outboxDatabase)
981
+ throw Error('Aggregate declared as Not Eventsourced without Outbox database.');
982
+ isStreamable &&
983
+ endpoint.registerEndpoint({
984
+ name: `Get ${name} state by Id`,
985
+ description: `Get current reduced ${name} state by Id`,
986
+ method: 'GET',
987
+ loggingModule: (0, change_case_1.paramCase)(name),
988
+ subdomain: commandHandler.subdomain,
989
+ artifact: {
990
+ type: commandHandler.isAggregate ? 'aggregate' : 'externalSystem',
991
+ name: commandHandler.name
992
+ },
993
+ route: idRoute,
994
+ tags: [],
995
+ schemas: {
996
+ params: pv3_types_1.SystemEndpointParamsSchema,
997
+ query: pv3_types_1.SystemGetQuerySchema
998
+ },
999
+ action: ({ params, query }) => (0, exports.loadAggregateState)(eventstore)(commandHandler, (0, utils_2.formatStream)(commandHandler.name, params?.id), (0, exports.formatAggregateGetQueryParams)(query)).then((response) => response && Object.values(response)[0])
1000
+ });
1001
+ endpoint.registerEndpoint({
1002
+ name: (0, utils_1.formatRouteForCommandHandler)(name, change_case_1.pascalCase),
1003
+ description: `Get the stream of events for ${name} by Id`,
1004
+ method: 'GET',
1005
+ loggingModule: (0, change_case_1.paramCase)(name),
1006
+ subdomain: commandHandler.subdomain,
1007
+ artifact: {
1008
+ type: commandHandler.isAggregate ? 'aggregate' : 'externalSystem',
1009
+ name: commandHandler.name
1010
+ },
1011
+ tags: commandHandler.isAggregate ? ['aggregate'] : ['system'],
1012
+ route: streamRoute,
1013
+ schemas: {
1014
+ params: isStreamable ? pv3_types_1.SystemEndpointParamsSchema : undefined,
1015
+ query: pv3_types_1.SystemGetQuerySchema
1016
+ },
1017
+ action: ({ params, query }) => (isStreamable
1018
+ ? (0, exports.loadStream)(eventstore)((0, utils_2.formatStream)(commandHandler.name, params?.id), query)
1019
+ : (0, exports.loadStream)(eventstore)(name, (0, exports.formatAggregateGetQueryParams)(query))).then((response) => (Array.isArray(response) ? response : []))
1020
+ });
1021
+ return [idRoute, streamRoute];
1022
+ };
1023
+ const registerCommandHandlerPostEndpoints = (commandHandler) => {
1024
+ const commandHandlerName = commandHandler.name;
1025
+ return !commandHandler.commands
1026
+ ? {}
1027
+ : (0, bett3r_utils_1.reduce)((result, name) => {
1028
+ const command = commandHandler.commands[name]?.build
1029
+ ? commandHandler.commands[name]?.build()
1030
+ : commandHandler.commands[name];
1031
+ const isStreamable = commandHandler.isStreamable && !command.dataPropertyId;
1032
+ const route = (0, utils_1.getCommandPostRoute)(isStreamable ? 'aggregate' : 'system', commandHandler, name);
1033
+ const schemas = getCommandSchemas(commandHandler, command, name);
1034
+ endpoint.registerEndpoint({
1035
+ loggingModule: (0, change_case_1.paramCase)(commandHandlerName),
1036
+ subdomain: commandHandler.subdomain,
1037
+ artifact: {
1038
+ type: commandHandler.isAggregate ? 'aggregate' : 'externalSystem',
1039
+ name: commandHandler.name
1040
+ },
1041
+ name: (0, utils_1.formatRouteForCommandHandler)(name, change_case_1.pascalCase),
1042
+ description: command.description,
1043
+ route,
1044
+ tags: [],
1045
+ schemas,
1046
+ ...(command.visibility ? { visibility: command.visibility } : {}),
1047
+ // It is not validated because the command handler will validate it as part of the command handling process. That way the error can be handled by the command handler.
1048
+ shouldValidate: false,
1049
+ method: 'POST',
1050
+ action: executeCommand(commandHandler, name, undefined, schemas)
1051
+ });
1052
+ result[name] = route;
1053
+ return result;
1054
+ }, {}, Object.keys(commandHandler.commands));
1055
+ };
1056
+ return {
1057
+ loadStream: (0, exports.loadStream)(eventstore),
1058
+ loadAggregateState: (0, exports.loadAggregateState)(eventstore),
1059
+ executeCommand,
1060
+ registerCommandHandlerGetEndpoints,
1061
+ registerCommandHandlerPostEndpoints
1062
+ };
1063
+ };
1064
+ exports.createCommandHandlers = createCommandHandlers;
1065
+ //# sourceMappingURL=index.js.map