@reventlessdev/reventless-local 3.0.0-alpha.113

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 (334) hide show
  1. package/CHANGELOG.md +1197 -0
  2. package/LICENSE +202 -0
  3. package/__mocks__/emptyModule.js +2 -0
  4. package/__mocks__/nodeSqlite.mjs +6 -0
  5. package/package.json +67 -0
  6. package/rescript.json +39 -0
  7. package/src/Platform.res +2162 -0
  8. package/src/Platform.res.mjs +3389 -0
  9. package/src/adapter/Api/LocalGraphQL_Adapter.res +29 -0
  10. package/src/adapter/Api/LocalGraphQL_Adapter.res.mjs +26 -0
  11. package/src/adapter/Api/LocalGraphQL_SubscriptionResolvers.res +146 -0
  12. package/src/adapter/Api/LocalGraphQL_SubscriptionResolvers.res.mjs +88 -0
  13. package/src/adapter/Auth/Auth_GraphqlContext.res +83 -0
  14. package/src/adapter/Auth/Auth_GraphqlContext.res.mjs +76 -0
  15. package/src/adapter/Auth/LocalAuth.res +239 -0
  16. package/src/adapter/Auth/LocalAuth.res.mjs +247 -0
  17. package/src/adapter/Auth/UserStore.res +134 -0
  18. package/src/adapter/Auth/UserStore.res.mjs +146 -0
  19. package/src/adapter/Backend.res +46 -0
  20. package/src/adapter/Backend.res.mjs +66 -0
  21. package/src/adapter/BackendState.res +34 -0
  22. package/src/adapter/BackendState.res.mjs +42 -0
  23. package/src/adapter/Cloner/LocalClonerRunner.res +13 -0
  24. package/src/adapter/Cloner/LocalClonerRunner.res.mjs +12 -0
  25. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_GraphQL.res +329 -0
  26. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_GraphQL.res.mjs +301 -0
  27. package/src/adapter/CommandGenerator/InboundTranslationResolvers_GraphQL.res +76 -0
  28. package/src/adapter/CommandGenerator/InboundTranslationResolvers_GraphQL.res.mjs +57 -0
  29. package/src/adapter/CommandGenerator/LocalCommandGeneratorResolvers.res +19 -0
  30. package/src/adapter/CommandGenerator/LocalCommandGeneratorResolvers.res.mjs +19 -0
  31. package/src/adapter/CommandTopic/LocalCommandTopicChannel.res +104 -0
  32. package/src/adapter/CommandTopic/LocalCommandTopicChannel.res.mjs +82 -0
  33. package/src/adapter/CommandTopic/LocalCommandTopicRemoteChannel.res +32 -0
  34. package/src/adapter/CommandTopic/LocalCommandTopicRemoteChannel.res.mjs +38 -0
  35. package/src/adapter/Counter/LocalCounterHandler.res +42 -0
  36. package/src/adapter/Counter/LocalCounterHandler.res.mjs +45 -0
  37. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res +131 -0
  38. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs +140 -0
  39. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res +334 -0
  40. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res.mjs +299 -0
  41. package/src/adapter/DomainGraphQL_Server.res +565 -0
  42. package/src/adapter/DomainGraphQL_Server.res.mjs +576 -0
  43. package/src/adapter/DomainMCP_Server.res +369 -0
  44. package/src/adapter/DomainMCP_Server.res.mjs +358 -0
  45. package/src/adapter/EventCollector/LocalEventCollectorChannel.res +87 -0
  46. package/src/adapter/EventCollector/LocalEventCollectorChannel.res.mjs +45 -0
  47. package/src/adapter/EventLog/EventLogStorage_InMemory.res +105 -0
  48. package/src/adapter/EventLog/EventLogStorage_InMemory.res.mjs +117 -0
  49. package/src/adapter/EventLog/EventLogStorage_Sqlite.res +145 -0
  50. package/src/adapter/EventLog/EventLogStorage_Sqlite.res.mjs +155 -0
  51. package/src/adapter/EventTopic/LocalEventTopicPublisher.res +36 -0
  52. package/src/adapter/EventTopic/LocalEventTopicPublisher.res.mjs +31 -0
  53. package/src/adapter/GraphQL_Server.res +6 -0
  54. package/src/adapter/GraphQL_Server.res.mjs +154 -0
  55. package/src/adapter/GraphQL_ServerInstance.res +310 -0
  56. package/src/adapter/GraphQL_ServerInstance.res.mjs +257 -0
  57. package/src/adapter/Heartbeat/LocalHeartbeatRunner.res +57 -0
  58. package/src/adapter/Heartbeat/LocalHeartbeatRunner.res.mjs +34 -0
  59. package/src/adapter/LocalBus.res +498 -0
  60. package/src/adapter/LocalBus.res.mjs +1011 -0
  61. package/src/adapter/LocalPluginSpec.res +16 -0
  62. package/src/adapter/LocalPluginSpec.res.mjs +33 -0
  63. package/src/adapter/LocalSideEffectHandler.res +44 -0
  64. package/src/adapter/LocalSideEffectHandler.res.mjs +34 -0
  65. package/src/adapter/MCP_Server.res +4 -0
  66. package/src/adapter/MCP_Server.res.mjs +67 -0
  67. package/src/adapter/MCP_ServerInstance.res +362 -0
  68. package/src/adapter/MCP_ServerInstance.res.mjs +313 -0
  69. package/src/adapter/PlatformGraphQL_Server.res +75 -0
  70. package/src/adapter/PlatformGraphQL_Server.res.mjs +84 -0
  71. package/src/adapter/PlatformMCP_Server.res +23 -0
  72. package/src/adapter/PlatformMCP_Server.res.mjs +46 -0
  73. package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res +793 -0
  74. package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs +569 -0
  75. package/src/adapter/QueryDb/QueryDbStorage_InMemory.res +242 -0
  76. package/src/adapter/QueryDb/QueryDbStorage_InMemory.res.mjs +241 -0
  77. package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res +339 -0
  78. package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res.mjs +318 -0
  79. package/src/adapter/QueryDb/SortKey_Filter.res +48 -0
  80. package/src/adapter/QueryDb/SortKey_Filter.res.mjs +46 -0
  81. package/src/adapter/QueryEngine/LocalQueryEngine.res +57 -0
  82. package/src/adapter/QueryEngine/LocalQueryEngine.res.mjs +56 -0
  83. package/src/adapter/Runtime/LocalAggregateRuntime_Builder.res +91 -0
  84. package/src/adapter/Runtime/LocalAggregateRuntime_Builder.res.mjs +50 -0
  85. package/src/adapter/Runtime/LocalEventCollectorRuntime_Builder.res +47 -0
  86. package/src/adapter/Runtime/LocalEventCollectorRuntime_Builder.res.mjs +37 -0
  87. package/src/adapter/Runtime/LocalPluginRuntime_Builder.res +11 -0
  88. package/src/adapter/Runtime/LocalPluginRuntime_Builder.res.mjs +30 -0
  89. package/src/adapter/Runtime/LocalRuntimeEnvironment.res +54 -0
  90. package/src/adapter/Runtime/LocalRuntimeEnvironment.res.mjs +40 -0
  91. package/src/adapter/Scheduler/LocalScheduledPublisher.res +102 -0
  92. package/src/adapter/Scheduler/LocalScheduledPublisher.res.mjs +84 -0
  93. package/src/adapter/SqliteDriver.res +52 -0
  94. package/src/adapter/SqliteDriver.res.mjs +76 -0
  95. package/src/adapter/SqliteDriver.resi +31 -0
  96. package/src/adapter/Task/LocalTaskBucket.res +75 -0
  97. package/src/adapter/Task/LocalTaskBucket.res.mjs +48 -0
  98. package/src/adapter/Task/TaskBucket_Sqlite.res +47 -0
  99. package/src/adapter/Task/TaskBucket_Sqlite.res.mjs +40 -0
  100. package/src/components/Aggregate_Builder.res +55 -0
  101. package/src/components/Aggregate_Builder.res.mjs +140 -0
  102. package/src/components/AutomationSlice_Builder.res +41 -0
  103. package/src/components/AutomationSlice_Builder.res.mjs +57 -0
  104. package/src/components/Counter_Builder.res +14 -0
  105. package/src/components/Counter_Builder.res.mjs +32 -0
  106. package/src/components/DcbEventLog_Builder.res +18 -0
  107. package/src/components/DcbEventLog_Builder.res.mjs +24 -0
  108. package/src/components/ExtensionPoint_Builder.res +25 -0
  109. package/src/components/ExtensionPoint_Builder.res.mjs +44 -0
  110. package/src/components/InboundTranslationSlice_Builder.res +34 -0
  111. package/src/components/InboundTranslationSlice_Builder.res.mjs +45 -0
  112. package/src/components/OutboundTranslationSlice_Builder.res +43 -0
  113. package/src/components/OutboundTranslationSlice_Builder.res.mjs +59 -0
  114. package/src/components/Plugin_Builder.res +37 -0
  115. package/src/components/Plugin_Builder.res.mjs +67 -0
  116. package/src/components/ReadModel_Builder.res +47 -0
  117. package/src/components/ReadModel_Builder.res.mjs +54 -0
  118. package/src/components/StateChangeSlice_Builder.res +19 -0
  119. package/src/components/StateChangeSlice_Builder.res.mjs +21 -0
  120. package/src/components/StateViewSlice_Builder.res +42 -0
  121. package/src/components/StateViewSlice_Builder.res.mjs +58 -0
  122. package/src/components/Task_Builder.res +28 -0
  123. package/src/components/Task_Builder.res.mjs +41 -0
  124. package/src/reexport/CommandTopic.res +3 -0
  125. package/src/reexport/CommandTopic.res.mjs +55 -0
  126. package/src/test/Mocks/MockDcbEventLogStorage.res +136 -0
  127. package/src/test/Mocks/MockDcbEventLogStorage.res.mjs +146 -0
  128. package/src/test/Mocks/MockEventLogStorage.res +57 -0
  129. package/src/test/Mocks/MockEventLogStorage.res.mjs +65 -0
  130. package/src/test/Mocks/MockPublisher.res +29 -0
  131. package/src/test/Mocks/MockPublisher.res.mjs +28 -0
  132. package/src/test/Mocks/MockQueryDbStorage.res +104 -0
  133. package/src/test/Mocks/MockQueryDbStorage.res.mjs +136 -0
  134. package/src/test/TestRunner.res +96 -0
  135. package/src/test/TestRunner.res.mjs +71 -0
  136. package/tests/SplitApiFixtures.res +84 -0
  137. package/tests/SplitApiFixtures.res.mjs +88 -0
  138. package/tests/SplitApiTest.res +102 -0
  139. package/tests/SplitApiTest.res.mjs +82 -0
  140. package/tests/TestFixtures.res +54 -0
  141. package/tests/TestFixtures.res.mjs +65 -0
  142. package/tests/adapter/BackendParityTest.res +94 -0
  143. package/tests/adapter/BackendParityTest.res.mjs +96 -0
  144. package/tests/adapter/CollectNEventsTest.res +82 -0
  145. package/tests/adapter/CollectNEventsTest.res.mjs +83 -0
  146. package/tests/adapter/CommandAuthorizationTest.res +200 -0
  147. package/tests/adapter/CommandAuthorizationTest.res.mjs +190 -0
  148. package/tests/adapter/CommandTopicChannelTest.res +174 -0
  149. package/tests/adapter/CommandTopicChannelTest.res.mjs +170 -0
  150. package/tests/adapter/CounterHandlerTest.res +113 -0
  151. package/tests/adapter/CounterHandlerTest.res.mjs +96 -0
  152. package/tests/adapter/DcbEventLogStorageSqliteTest.res +157 -0
  153. package/tests/adapter/DcbEventLogStorageSqliteTest.res.mjs +165 -0
  154. package/tests/adapter/DcbEventLogStorageTest.res +187 -0
  155. package/tests/adapter/DcbEventLogStorageTest.res.mjs +195 -0
  156. package/tests/adapter/EventCollectorChannelTest.res +166 -0
  157. package/tests/adapter/EventCollectorChannelTest.res.mjs +178 -0
  158. package/tests/adapter/EventLogStorageSqliteTest.res +105 -0
  159. package/tests/adapter/EventLogStorageSqliteTest.res.mjs +116 -0
  160. package/tests/adapter/EventTapTest.res +102 -0
  161. package/tests/adapter/EventTapTest.res.mjs +94 -0
  162. package/tests/adapter/EventTopicPublisherTest.res +76 -0
  163. package/tests/adapter/EventTopicPublisherTest.res.mjs +86 -0
  164. package/tests/adapter/GraphQL_SchemaInspectorTest.res +763 -0
  165. package/tests/adapter/GraphQL_SchemaInspectorTest.res.mjs +578 -0
  166. package/tests/adapter/GraphQL_SubscriptionResolversTest.res +161 -0
  167. package/tests/adapter/GraphQL_SubscriptionResolversTest.res.mjs +134 -0
  168. package/tests/adapter/HeartbeatRunnerTest.res +136 -0
  169. package/tests/adapter/HeartbeatRunnerTest.res.mjs +96 -0
  170. package/tests/adapter/LocalAuthHttpTest.res +224 -0
  171. package/tests/adapter/LocalAuthHttpTest.res.mjs +237 -0
  172. package/tests/adapter/LocalAuthLoginTest.res +180 -0
  173. package/tests/adapter/LocalAuthLoginTest.res.mjs +207 -0
  174. package/tests/adapter/LocalAuthTest.res +106 -0
  175. package/tests/adapter/LocalAuthTest.res.mjs +145 -0
  176. package/tests/adapter/LocalAuthUserStoreTest.res +172 -0
  177. package/tests/adapter/LocalAuthUserStoreTest.res.mjs +208 -0
  178. package/tests/adapter/LocalBusBoundedTest.res +157 -0
  179. package/tests/adapter/LocalBusBoundedTest.res.mjs +168 -0
  180. package/tests/adapter/LocalBusPubSubTest.res +81 -0
  181. package/tests/adapter/LocalBusPubSubTest.res.mjs +81 -0
  182. package/tests/adapter/QueryDbGsiTtlTest.res +268 -0
  183. package/tests/adapter/QueryDbGsiTtlTest.res.mjs +209 -0
  184. package/tests/adapter/QueryDbListResolverTest.res +361 -0
  185. package/tests/adapter/QueryDbListResolverTest.res.mjs +426 -0
  186. package/tests/adapter/QueryDbStorageSqliteTest.res +159 -0
  187. package/tests/adapter/QueryDbStorageSqliteTest.res.mjs +126 -0
  188. package/tests/adapter/QueryDbStorageTest.res +171 -0
  189. package/tests/adapter/QueryDbStorageTest.res.mjs +170 -0
  190. package/tests/adapter/QueryEngineTest.res +152 -0
  191. package/tests/adapter/QueryEngineTest.res.mjs +148 -0
  192. package/tests/adapter/ScheduledPublisherTest.res +199 -0
  193. package/tests/adapter/ScheduledPublisherTest.res.mjs +203 -0
  194. package/tests/adapter/SortKey_FilterTest.res +103 -0
  195. package/tests/adapter/SortKey_FilterTest.res.mjs +135 -0
  196. package/tests/adapter/SqliteDriverTest.res +86 -0
  197. package/tests/adapter/SqliteDriverTest.res.mjs +101 -0
  198. package/tests/adapter/TaskBucketSqliteTest.res +44 -0
  199. package/tests/adapter/TaskBucketSqliteTest.res.mjs +40 -0
  200. package/tests/adapter/TaskBucketTest.res +106 -0
  201. package/tests/adapter/TaskBucketTest.res.mjs +118 -0
  202. package/tests/components/aggregate/AggregateFixtures.res +78 -0
  203. package/tests/components/aggregate/AggregateFixtures.res.mjs +109 -0
  204. package/tests/components/aggregate/AggregateTest.res +129 -0
  205. package/tests/components/aggregate/AggregateTest.res.mjs +129 -0
  206. package/tests/components/automationslice/AutomationSliceCallbackTest.res +212 -0
  207. package/tests/components/automationslice/AutomationSliceCallbackTest.res.mjs +233 -0
  208. package/tests/components/automationslice/AutomationSliceFixtures.res +189 -0
  209. package/tests/components/automationslice/AutomationSliceFixtures.res.mjs +276 -0
  210. package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res +289 -0
  211. package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res.mjs +453 -0
  212. package/tests/components/automationslice/AutomationSliceSelfDeadlockTest.res +47 -0
  213. package/tests/components/automationslice/AutomationSliceSelfDeadlockTest.res.mjs +31 -0
  214. package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res +213 -0
  215. package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res.mjs +268 -0
  216. package/tests/components/automationslice/MixedSourceAutomationSliceTest.res +118 -0
  217. package/tests/components/automationslice/MixedSourceAutomationSliceTest.res.mjs +99 -0
  218. package/tests/components/commandgenerator/CommandGeneratorFixtures.res +73 -0
  219. package/tests/components/commandgenerator/CommandGeneratorFixtures.res.mjs +109 -0
  220. package/tests/components/commandgenerator/CommandGeneratorTest.res +43 -0
  221. package/tests/components/commandgenerator/CommandGeneratorTest.res.mjs +46 -0
  222. package/tests/components/commandtopic/CommandTopicFixtures.res +37 -0
  223. package/tests/components/commandtopic/CommandTopicFixtures.res.mjs +68 -0
  224. package/tests/components/commandtopic/CommandTopicStreamFixtures.res +43 -0
  225. package/tests/components/commandtopic/CommandTopicStreamFixtures.res.mjs +91 -0
  226. package/tests/components/commandtopic/CommandTopicStreamTest.res +30 -0
  227. package/tests/components/commandtopic/CommandTopicStreamTest.res.mjs +35 -0
  228. package/tests/components/commandtopic/CommandTopicTest.res +55 -0
  229. package/tests/components/commandtopic/CommandTopicTest.res.mjs +62 -0
  230. package/tests/components/counter/CounterFixtures.res +42 -0
  231. package/tests/components/counter/CounterFixtures.res.mjs +34 -0
  232. package/tests/components/counter/CounterTest.res +46 -0
  233. package/tests/components/counter/CounterTest.res.mjs +61 -0
  234. package/tests/components/dcb/DcbCrossPartitionFixtures.res +170 -0
  235. package/tests/components/dcb/DcbCrossPartitionFixtures.res.mjs +276 -0
  236. package/tests/components/dcb/DcbCrossPartitionReadTest.res +68 -0
  237. package/tests/components/dcb/DcbCrossPartitionReadTest.res.mjs +78 -0
  238. package/tests/components/dcb/DcbEventLogAppendStreamTest.res +72 -0
  239. package/tests/components/dcb/DcbEventLogAppendStreamTest.res.mjs +82 -0
  240. package/tests/components/dcb/DcbEventLogStreamTest.res +103 -0
  241. package/tests/components/dcb/DcbEventLogStreamTest.res.mjs +91 -0
  242. package/tests/components/dcb/DcbFixtures.res +145 -0
  243. package/tests/components/dcb/DcbFixtures.res.mjs +221 -0
  244. package/tests/components/dcb/DcbTest.res +55 -0
  245. package/tests/components/dcb/DcbTest.res.mjs +55 -0
  246. package/tests/components/eventcollector/EventCollectorFixtures.res +42 -0
  247. package/tests/components/eventcollector/EventCollectorFixtures.res.mjs +49 -0
  248. package/tests/components/eventcollector/EventCollectorTest.res +37 -0
  249. package/tests/components/eventcollector/EventCollectorTest.res.mjs +36 -0
  250. package/tests/components/eventlog/EventLogAppendStreamTest.res +93 -0
  251. package/tests/components/eventlog/EventLogAppendStreamTest.res.mjs +113 -0
  252. package/tests/components/eventlog/EventLogConflictTest.res +86 -0
  253. package/tests/components/eventlog/EventLogConflictTest.res.mjs +81 -0
  254. package/tests/components/eventlog/EventLogFixtures.res +52 -0
  255. package/tests/components/eventlog/EventLogFixtures.res.mjs +80 -0
  256. package/tests/components/eventlog/EventLogStreamTest.res +98 -0
  257. package/tests/components/eventlog/EventLogStreamTest.res.mjs +142 -0
  258. package/tests/components/eventlog/EventLogTest.res +53 -0
  259. package/tests/components/eventlog/EventLogTest.res.mjs +74 -0
  260. package/tests/components/eventtopic/EventTopicFixtures.res +47 -0
  261. package/tests/components/eventtopic/EventTopicFixtures.res.mjs +77 -0
  262. package/tests/components/eventtopic/EventTopicStreamFixtures.res +27 -0
  263. package/tests/components/eventtopic/EventTopicStreamFixtures.res.mjs +62 -0
  264. package/tests/components/eventtopic/EventTopicStreamTest.res +35 -0
  265. package/tests/components/eventtopic/EventTopicStreamTest.res.mjs +44 -0
  266. package/tests/components/eventtopic/EventTopicTest.res +35 -0
  267. package/tests/components/eventtopic/EventTopicTest.res.mjs +43 -0
  268. package/tests/components/extensionpoint/ExtensionPointFixtures.res +145 -0
  269. package/tests/components/extensionpoint/ExtensionPointFixtures.res.mjs +188 -0
  270. package/tests/components/extensionpoint/ExtensionPointTest.res +62 -0
  271. package/tests/components/extensionpoint/ExtensionPointTest.res.mjs +55 -0
  272. package/tests/components/heartbeat/HeartbeatFixtures.res +48 -0
  273. package/tests/components/heartbeat/HeartbeatFixtures.res.mjs +46 -0
  274. package/tests/components/heartbeat/HeartbeatTest.res +67 -0
  275. package/tests/components/heartbeat/HeartbeatTest.res.mjs +65 -0
  276. package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res +241 -0
  277. package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res.mjs +239 -0
  278. package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res +36 -0
  279. package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res.mjs +73 -0
  280. package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res +191 -0
  281. package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res.mjs +297 -0
  282. package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res +78 -0
  283. package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res.mjs +137 -0
  284. package/tests/components/querydb/QueryDbFixtures.res +39 -0
  285. package/tests/components/querydb/QueryDbFixtures.res.mjs +73 -0
  286. package/tests/components/querydb/QueryDbSubIdFixtures.res +44 -0
  287. package/tests/components/querydb/QueryDbSubIdFixtures.res.mjs +80 -0
  288. package/tests/components/querydb/QueryDbSubIdTest.res +104 -0
  289. package/tests/components/querydb/QueryDbSubIdTest.res.mjs +104 -0
  290. package/tests/components/querydb/QueryDbTest.res +81 -0
  291. package/tests/components/querydb/QueryDbTest.res.mjs +126 -0
  292. package/tests/components/readmodel/DcbReadModelE2EFixtures.res +215 -0
  293. package/tests/components/readmodel/DcbReadModelE2EFixtures.res.mjs +308 -0
  294. package/tests/components/readmodel/DcbReadModelE2ETest.res +45 -0
  295. package/tests/components/readmodel/DcbReadModelE2ETest.res.mjs +37 -0
  296. package/tests/components/readmodel/DcbReadModelTypoFailFastTest.res +88 -0
  297. package/tests/components/readmodel/DcbReadModelTypoFailFastTest.res.mjs +152 -0
  298. package/tests/components/readmodel/MixedSourceReadModelFixtures.res +181 -0
  299. package/tests/components/readmodel/MixedSourceReadModelFixtures.res.mjs +277 -0
  300. package/tests/components/readmodel/MixedSourceReadModelTest.res +61 -0
  301. package/tests/components/readmodel/MixedSourceReadModelTest.res.mjs +68 -0
  302. package/tests/components/readmodel/ReadModelFixtures.res +138 -0
  303. package/tests/components/readmodel/ReadModelFixtures.res.mjs +169 -0
  304. package/tests/components/readmodel/ReadModelTest.res +46 -0
  305. package/tests/components/readmodel/ReadModelTest.res.mjs +36 -0
  306. package/tests/components/scheduler/SchedulerFixtures.res +59 -0
  307. package/tests/components/scheduler/SchedulerFixtures.res.mjs +63 -0
  308. package/tests/components/scheduler/SchedulerTest.res +76 -0
  309. package/tests/components/scheduler/SchedulerTest.res.mjs +86 -0
  310. package/tests/components/sideeffecthandler/SideEffectHandlerFixtures.res +133 -0
  311. package/tests/components/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +149 -0
  312. package/tests/components/sideeffecthandler/SideEffectHandlerTest.res +39 -0
  313. package/tests/components/sideeffecthandler/SideEffectHandlerTest.res.mjs +28 -0
  314. package/tests/components/stateviewslice/StateViewSliceFixtures.res +117 -0
  315. package/tests/components/stateviewslice/StateViewSliceFixtures.res.mjs +188 -0
  316. package/tests/components/stateviewslice/StateViewSliceSubIdFixtures.res +117 -0
  317. package/tests/components/stateviewslice/StateViewSliceSubIdFixtures.res.mjs +183 -0
  318. package/tests/components/stateviewslice/StateViewSliceSubIdTest.res +78 -0
  319. package/tests/components/stateviewslice/StateViewSliceSubIdTest.res.mjs +107 -0
  320. package/tests/components/stateviewslice/StateViewSliceTest.res +59 -0
  321. package/tests/components/stateviewslice/StateViewSliceTest.res.mjs +72 -0
  322. package/tests/components/task/TaskFixtures.res +87 -0
  323. package/tests/components/task/TaskFixtures.res.mjs +82 -0
  324. package/tests/components/task/TaskTest.res +98 -0
  325. package/tests/components/task/TaskTest.res.mjs +46 -0
  326. package/tests/plugin/PluginBehavior_GWT.res +146 -0
  327. package/tests/plugin/PluginBehavior_GWT.res.mjs +281 -0
  328. package/tests/plugin/Plugin_Fixtures.res +61 -0
  329. package/tests/plugin/Plugin_Fixtures.res.mjs +105 -0
  330. package/tests/plugin/PluginsProjection_GWT.res +95 -0
  331. package/tests/plugin/PluginsProjection_GWT.res.mjs +120 -0
  332. package/tests/plugin/UIFragmentRegistryProjection_GWT.res +72 -0
  333. package/tests/plugin/UIFragmentRegistryProjection_GWT.res.mjs +117 -0
  334. package/tests/setup/sqliteGlobal.cjs +12 -0
@@ -0,0 +1,213 @@
1
+ // Plan 04 fixtures — AutomationSlice with two sources (Aggregate + DCB).
2
+ // Verifies mixed-source dispatch: both sources feed the same slice's TODO list,
3
+ // each going through its own per-source `collect`/`resolve`, and `process`
4
+ // produces commands for the target.
5
+
6
+ open TestFixtures
7
+ open Reventless
8
+
9
+ // ─────────────────────────────────────────────────────────────
10
+ // Source 1: simulated Aggregate — emits OrderShipped events
11
+ // ─────────────────────────────────────────────────────────────
12
+
13
+ module OrderAggregateSource = {
14
+ module Id = Id.String
15
+ let name = "OrderAggregateEventTopic"
16
+ @schema
17
+ type event =
18
+ | OrderShipped({orderId: string, productId: string})
19
+ }
20
+
21
+ // ─────────────────────────────────────────────────────────────
22
+ // Source 2: simulated DCB EventLog — emits StockReserved events
23
+ // ─────────────────────────────────────────────────────────────
24
+
25
+ module InventoryDcbSource = {
26
+ module Id = Id.String
27
+ let name = "InventoryDcbEventLog"
28
+ @schema
29
+ type event =
30
+ | StockReserved({orderId: string, productId: string})
31
+ | StockReleased({orderId: string, productId: string})
32
+ }
33
+
34
+ // ─────────────────────────────────────────────────────────────
35
+ // AutomationSlice spec — joins both sources by composite key
36
+ // ─────────────────────────────────────────────────────────────
37
+
38
+ module AutoFulfillSpec = {
39
+ let name = "AutoFulfill"
40
+ let moduleUrl: string = %raw(`import.meta.url`)
41
+
42
+ @schema
43
+ type todoItem = {
44
+ orderId: string,
45
+ productId: string,
46
+ fromAggregate: bool, // tracks which source produced this item
47
+ }
48
+
49
+ @schema
50
+ type command = MarkFulfilled({
51
+ orderId: @s.matches(DcbTag.string) string,
52
+ productId: @s.matches(DcbTag.string) string,
53
+ })
54
+
55
+ let maxRetries = 3
56
+ let heartbeatInterval = 60
57
+ let targetName = "MarkFulfilled"
58
+ }
59
+
60
+ // Forward-declared per-source mappings live below; the merged `Automation`
61
+ // module type also exposes `mappings` + `module type Mapping`, which we
62
+ // populate after `FromOrderAggregate` / `FromInventoryDcb` are in scope.
63
+
64
+ // ─────────────────────────────────────────────────────────────
65
+ // Mapping 1: Aggregate source → todoItem (with `fromAggregate=true`)
66
+ // ─────────────────────────────────────────────────────────────
67
+
68
+ module FromOrderAggregate = AutomationSlice.Mapping.Make(
69
+ OrderAggregateSource,
70
+ AutoFulfillSpec,
71
+ {
72
+ let collect = (event: OrderAggregateSource.event, _ctx) =>
73
+ switch event {
74
+ | OrderShipped({orderId, productId}) => [
75
+ (
76
+ orderId ++ ":" ++ productId,
77
+ ({orderId, productId, fromAggregate: true}: AutoFulfillSpec.todoItem),
78
+ ),
79
+ ]
80
+ }
81
+ let resolve = (_event: OrderAggregateSource.event) => None
82
+ },
83
+ )
84
+
85
+ // ─────────────────────────────────────────────────────────────
86
+ // Mapping 2: DCB source → todoItem (with `fromAggregate=false`)
87
+ // Also resolves on StockReleased — releases roll back any pending TODO.
88
+ // ─────────────────────────────────────────────────────────────
89
+
90
+ module FromInventoryDcb = AutomationSlice.Mapping.Make(
91
+ InventoryDcbSource,
92
+ AutoFulfillSpec,
93
+ {
94
+ let collect = (event: InventoryDcbSource.event, _ctx) =>
95
+ switch event {
96
+ | StockReserved({orderId, productId}) => [
97
+ (
98
+ orderId ++ ":" ++ productId,
99
+ ({orderId, productId, fromAggregate: false}: AutoFulfillSpec.todoItem),
100
+ ),
101
+ ]
102
+ | StockReleased(_) => []
103
+ }
104
+ let resolve = (event: InventoryDcbSource.event) =>
105
+ switch event {
106
+ | StockReleased({orderId, productId}) => Some(orderId ++ ":" ++ productId)
107
+ | StockReserved(_) => None
108
+ }
109
+ },
110
+ )
111
+
112
+ // ─────────────────────────────────────────────────────────────
113
+ // Mappings collection
114
+ // ─────────────────────────────────────────────────────────────
115
+
116
+ module AutoFulfillAutomation: AutomationSlice.Automation
117
+ with module Spec := AutoFulfillSpec = {
118
+ let process = (id, item: AutoFulfillSpec.todoItem) =>
119
+ Some((id, AutoFulfillSpec.MarkFulfilled({orderId: item.orderId, productId: item.productId})))
120
+ let moduleUrl: string = %raw(`import.meta.url`)
121
+ module M = AutomationSlice.Mappings.Make(AutoFulfillSpec)
122
+ module type Mapping = M.Mapping
123
+ let mappings: array<module(Mapping)> = [module(FromOrderAggregate), module(FromInventoryDcb)]
124
+ }
125
+
126
+ // ─────────────────────────────────────────────────────────────
127
+ // allEventTopics — two entries, one per source (matches mapping sourceNames)
128
+ // ─────────────────────────────────────────────────────────────
129
+
130
+ let aggregateResource: ReventlessInfra.Adapter.resource = ReventlessInfra.Adapter.make(
131
+ ~name=OrderAggregateSource.name->Pulumi.Output.make,
132
+ ~id=OrderAggregateSource.name->Pulumi.Output.make,
133
+ ~urn=OrderAggregateSource.name->Pulumi.Output.make,
134
+ ~service="memory:InMemory"->Pulumi.Output.make,
135
+ )
136
+
137
+ let dcbResource: ReventlessInfra.Adapter.resource = ReventlessInfra.Adapter.make(
138
+ ~name=InventoryDcbSource.name->Pulumi.Output.make,
139
+ ~id=InventoryDcbSource.name->Pulumi.Output.make,
140
+ ~urn=InventoryDcbSource.name->Pulumi.Output.make,
141
+ ~service="memory:InMemory"->Pulumi.Output.make,
142
+ )
143
+
144
+ let allEventTopics: ReventlessCore.EventTopic.allOutputs = Dict.fromArray([
145
+ (OrderAggregateSource.name, {ReventlessInfra.EventTopic.resources: [aggregateResource]}),
146
+ (InventoryDcbSource.name, {ReventlessInfra.EventTopic.resources: [dcbResource]}),
147
+ ])
148
+
149
+ // ─────────────────────────────────────────────────────────────
150
+ // Isolated bus + Pulumi mock mode
151
+ // ─────────────────────────────────────────────────────────────
152
+
153
+ module Bus = LocalBus.Make()
154
+ let _ = TestRunner.setup()
155
+
156
+ // ─────────────────────────────────────────────────────────────
157
+ // Build AutomationSlice
158
+ // ─────────────────────────────────────────────────────────────
159
+
160
+ module AutomationSliceMaker = AutomationSlice_Builder.Make(Bus)
161
+ module AutoFulfill = AutomationSliceMaker.Make(
162
+ AutoFulfillSpec,
163
+ AutoFulfillAutomation,
164
+ )
165
+
166
+ // Mirrors the context that `Plugin_Builder` constructs for local deployments
167
+ // (environment from `LocalPluginSpec.environment`, platformName "local").
168
+ let testContext: Reventless.AutomationSlice.context = {
169
+ environment: "local",
170
+ platformName: "local",
171
+ pluginName: "TestPlugin",
172
+ sliceName: AutoFulfillSpec.name,
173
+ }
174
+
175
+ // publishJsons — capture commands instead of round-tripping through a CommandTopic.
176
+ let publishedCommands: ref<array<Reventless.Message.commandJson>> = ref([])
177
+ let mockPublishJsons: ReventlessInfra.CommandTopic.publishJsons = async cmds => {
178
+ publishedCommands := publishedCommands.contents->Array.concat(cmds)
179
+ }
180
+
181
+ let slice = AutoFulfill.make(
182
+ ~allEventTopics,
183
+ ~publishJsons=mockPublishJsons->Pulumi.Output.make,
184
+ ~context=testContext,
185
+ )
186
+
187
+ // ─────────────────────────────────────────────────────────────
188
+ // Test helpers
189
+ // ─────────────────────────────────────────────────────────────
190
+
191
+ let publishAggregateEvent = async (id, event: OrderAggregateSource.event) => {
192
+ let meta = makeTestMeta(~service=OrderAggregateSource.name)
193
+ let eventJson = JSON.Encode.object(
194
+ Dict.fromArray([
195
+ ("id", id->JSON.Encode.string),
196
+ ("meta", meta->S.reverseConvertToJsonOrThrow(Message.metaSchema)),
197
+ ("event", event->S.reverseConvertToJsonOrThrow(OrderAggregateSource.eventSchema)),
198
+ ]),
199
+ )
200
+ await Bus.publishEvent(OrderAggregateSource.name, "test", meta, eventJson)
201
+ }
202
+
203
+ let publishDcbEvent = async (id, event: InventoryDcbSource.event) => {
204
+ let meta = makeTestMeta(~service=InventoryDcbSource.name)
205
+ let eventJson = JSON.Encode.object(
206
+ Dict.fromArray([
207
+ ("id", id->JSON.Encode.string),
208
+ ("meta", meta->S.reverseConvertToJsonOrThrow(Message.metaSchema)),
209
+ ("event", event->S.reverseConvertToJsonOrThrow(InventoryDcbSource.eventSchema)),
210
+ ]),
211
+ )
212
+ await Bus.publishEvent(InventoryDcbSource.name, "test", meta, eventJson)
213
+ }
@@ -0,0 +1,268 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
5
+ import * as Pulumi from "@pulumi/pulumi";
6
+ import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
7
+ import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
8
+ import * as Adapter$ReventlessInfra from "@reventlessdev/reventless-infra/src/adapter/Adapter.res.mjs";
9
+ import * as LocalBus$ReventlessLocal from "../../../src/adapter/LocalBus.res.mjs";
10
+ import * as AutomationSlice$Reventless from "@reventlessdev/reventless-spec/src/components/AutomationSlice.res.mjs";
11
+ import * as TestRunner$ReventlessLocal from "../../../src/test/TestRunner.res.mjs";
12
+ import * as TestFixtures$ReventlessLocal from "../../TestFixtures.res.mjs";
13
+ import * as AutomationSlice_Builder$ReventlessLocal from "../../../src/components/AutomationSlice_Builder.res.mjs";
14
+
15
+ let name = "OrderAggregateEventTopic";
16
+
17
+ let eventSchema = S.schema(s => ({
18
+ TAG: "OrderShipped",
19
+ orderId: s.m(S.string),
20
+ productId: s.m(S.string)
21
+ }));
22
+
23
+ let OrderAggregateSource = {
24
+ Id: undefined,
25
+ name: name,
26
+ eventSchema: eventSchema
27
+ };
28
+
29
+ let name$1 = "InventoryDcbEventLog";
30
+
31
+ let eventSchema$1 = S.union([
32
+ S.schema(s => ({
33
+ TAG: "StockReserved",
34
+ orderId: s.m(S.string),
35
+ productId: s.m(S.string)
36
+ })),
37
+ S.schema(s => ({
38
+ TAG: "StockReleased",
39
+ orderId: s.m(S.string),
40
+ productId: s.m(S.string)
41
+ }))
42
+ ]);
43
+
44
+ let InventoryDcbSource = {
45
+ Id: undefined,
46
+ name: name$1,
47
+ eventSchema: eventSchema$1
48
+ };
49
+
50
+ let name$2 = "AutoFulfill";
51
+
52
+ let moduleUrl = import.meta.url;
53
+
54
+ let todoItemSchema = S.schema(s => ({
55
+ orderId: s.m(S.string),
56
+ productId: s.m(S.string),
57
+ fromAggregate: s.m(S.bool)
58
+ }));
59
+
60
+ let commandSchema = S.schema(s => ({
61
+ TAG: "MarkFulfilled",
62
+ orderId: s.m(DcbTag$Reventless.string),
63
+ productId: s.m(DcbTag$Reventless.string)
64
+ }));
65
+
66
+ function commandAuthorization(param) {
67
+ return "AllowAuthenticated";
68
+ }
69
+
70
+ let AutoFulfillSpec = {
71
+ name: name$2,
72
+ moduleUrl: moduleUrl,
73
+ todoItemSchema: todoItemSchema,
74
+ commandSchema: commandSchema,
75
+ maxRetries: 3,
76
+ heartbeatInterval: 60,
77
+ targetName: "MarkFulfilled",
78
+ commandAuthorization: commandAuthorization
79
+ };
80
+
81
+ function collect(event, _ctx) {
82
+ let productId = event.productId;
83
+ let orderId = event.orderId;
84
+ return [[
85
+ orderId + ":" + productId,
86
+ {
87
+ orderId: orderId,
88
+ productId: productId,
89
+ fromAggregate: true
90
+ }
91
+ ]];
92
+ }
93
+
94
+ function resolve(_event) {
95
+
96
+ }
97
+
98
+ let FromOrderAggregate = AutomationSlice$Reventless.Mapping.Make({
99
+ Id: Id$Reventless.$$String,
100
+ name: name,
101
+ eventSchema: eventSchema
102
+ })(AutoFulfillSpec)({
103
+ collect: collect,
104
+ resolve: resolve
105
+ });
106
+
107
+ function collect$1(event, _ctx) {
108
+ if (event.TAG !== "StockReserved") {
109
+ return [];
110
+ }
111
+ let productId = event.productId;
112
+ let orderId = event.orderId;
113
+ return [[
114
+ orderId + ":" + productId,
115
+ {
116
+ orderId: orderId,
117
+ productId: productId,
118
+ fromAggregate: false
119
+ }
120
+ ]];
121
+ }
122
+
123
+ function resolve$1(event) {
124
+ if (event.TAG === "StockReserved") {
125
+ return;
126
+ } else {
127
+ return event.orderId + ":" + event.productId;
128
+ }
129
+ }
130
+
131
+ let FromInventoryDcb = AutomationSlice$Reventless.Mapping.Make({
132
+ Id: Id$Reventless.$$String,
133
+ name: name$1,
134
+ eventSchema: eventSchema$1
135
+ })(AutoFulfillSpec)({
136
+ collect: collect$1,
137
+ resolve: resolve$1
138
+ });
139
+
140
+ function process(id, item) {
141
+ return [
142
+ id,
143
+ {
144
+ TAG: "MarkFulfilled",
145
+ orderId: item.orderId,
146
+ productId: item.productId
147
+ }
148
+ ];
149
+ }
150
+
151
+ let moduleUrl$1 = import.meta.url;
152
+
153
+ AutomationSlice$Reventless.Mappings.Make(AutoFulfillSpec);
154
+
155
+ let mappings = [
156
+ FromOrderAggregate,
157
+ FromInventoryDcb
158
+ ];
159
+
160
+ let AutoFulfillAutomation = {
161
+ process: process,
162
+ moduleUrl: moduleUrl$1,
163
+ mappings: mappings
164
+ };
165
+
166
+ let aggregateResource = Adapter$ReventlessInfra.make(Pulumi.output(name), Pulumi.output(name), Pulumi.output(name), Pulumi.output("memory:InMemory"), undefined, undefined, undefined, undefined, undefined, undefined);
167
+
168
+ let dcbResource = Adapter$ReventlessInfra.make(Pulumi.output(name$1), Pulumi.output(name$1), Pulumi.output(name$1), Pulumi.output("memory:InMemory"), undefined, undefined, undefined, undefined, undefined, undefined);
169
+
170
+ let allEventTopics = Object.fromEntries([
171
+ [
172
+ name,
173
+ {
174
+ resources: [aggregateResource]
175
+ }
176
+ ],
177
+ [
178
+ name$1,
179
+ {
180
+ resources: [dcbResource]
181
+ }
182
+ ]
183
+ ]);
184
+
185
+ let Bus = LocalBus$ReventlessLocal.Make({});
186
+
187
+ TestRunner$ReventlessLocal.setup();
188
+
189
+ let AutomationSliceMaker = AutomationSlice_Builder$ReventlessLocal.Make(Bus);
190
+
191
+ let AutoFulfill = AutomationSliceMaker.Make(AutoFulfillSpec)(AutoFulfillAutomation);
192
+
193
+ let testContext = {
194
+ environment: "local",
195
+ platformName: "local",
196
+ pluginName: "TestPlugin",
197
+ sliceName: name$2
198
+ };
199
+
200
+ let publishedCommands = {
201
+ contents: []
202
+ };
203
+
204
+ async function mockPublishJsons(cmds) {
205
+ publishedCommands.contents = publishedCommands.contents.concat(cmds);
206
+ }
207
+
208
+ let slice = AutoFulfill.make(allEventTopics, Pulumi.output(mockPublishJsons), testContext, undefined);
209
+
210
+ async function publishAggregateEvent(id, event) {
211
+ let meta = TestFixtures$ReventlessLocal.makeTestMeta(name);
212
+ let eventJson = Object.fromEntries([
213
+ [
214
+ "id",
215
+ id
216
+ ],
217
+ [
218
+ "meta",
219
+ S.reverseConvertToJsonOrThrow(meta, Message$Reventless.metaSchema)
220
+ ],
221
+ [
222
+ "event",
223
+ S.reverseConvertToJsonOrThrow(event, eventSchema)
224
+ ]
225
+ ]);
226
+ return await Bus.publishEvent(name, "test", meta, eventJson);
227
+ }
228
+
229
+ async function publishDcbEvent(id, event) {
230
+ let meta = TestFixtures$ReventlessLocal.makeTestMeta(name$1);
231
+ let eventJson = Object.fromEntries([
232
+ [
233
+ "id",
234
+ id
235
+ ],
236
+ [
237
+ "meta",
238
+ S.reverseConvertToJsonOrThrow(meta, Message$Reventless.metaSchema)
239
+ ],
240
+ [
241
+ "event",
242
+ S.reverseConvertToJsonOrThrow(event, eventSchema$1)
243
+ ]
244
+ ]);
245
+ return await Bus.publishEvent(name$1, "test", meta, eventJson);
246
+ }
247
+
248
+ export {
249
+ OrderAggregateSource,
250
+ InventoryDcbSource,
251
+ AutoFulfillSpec,
252
+ FromOrderAggregate,
253
+ FromInventoryDcb,
254
+ AutoFulfillAutomation,
255
+ aggregateResource,
256
+ dcbResource,
257
+ allEventTopics,
258
+ Bus,
259
+ AutomationSliceMaker,
260
+ AutoFulfill,
261
+ testContext,
262
+ publishedCommands,
263
+ mockPublishJsons,
264
+ slice,
265
+ publishAggregateEvent,
266
+ publishDcbEvent,
267
+ }
268
+ /* eventSchema Not a pure module */
@@ -0,0 +1,118 @@
1
+ // Plan 04 integration test — AutomationSlice consumes events from two sources
2
+ // (Aggregate + DCB EventLog) and drives a single TODO list to MarkFulfilled
3
+ // commands. Verifies per-source decode dispatch, context plumbing, and that
4
+ // commands surface via publishJsons.
5
+
6
+ open JestGlobals
7
+ open MixedSourceAutomationSliceFixtures
8
+
9
+ describe("MixedSource AutomationSlice", () => {
10
+ let _ = beforeAllAsync(async () => {
11
+ let _ = await slice->ReventlessCore.Component.operations->TestRunner.resolve
12
+ let _ = await aggregateResource.name->TestRunner.resolve
13
+ let _ = await dcbResource.name->TestRunner.resolve
14
+ // Extra microtask flushes: subscription registration in
15
+ // LocalEventCollectorChannel.connect is fire-and-forget via
16
+ // `Effect.runPromise->ignore`, so we need the runtime to drain those
17
+ // microtasks before publishing events.
18
+ let _ = await Promise.resolve()
19
+ let _ = await Promise.resolve()
20
+ })
21
+
22
+ let _ = beforeEach(() => {
23
+ publishedCommands := []
24
+ })
25
+
26
+ testPromise("Aggregate-source event creates a TODO and produces a command", async () => {
27
+ publishedCommands := []
28
+ let _ = await publishAggregateEvent(
29
+ "env-a1",
30
+ OrderShipped({orderId: "o1", productId: "p1"}),
31
+ )
32
+
33
+ // Trigger phase2 manually since we don't have a heartbeat in this test.
34
+ let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
35
+ await ops.processPending()
36
+
37
+ expect(publishedCommands.contents->Array.length)->toBe(1)
38
+ let cmd = publishedCommands.contents->Array.getUnsafe(0)
39
+ expect(cmd.id)->toBe("o1:p1")
40
+ })
41
+
42
+ testPromise("DCB-source StockReserved creates a TODO and produces a command", async () => {
43
+ publishedCommands := []
44
+ let _ = await publishDcbEvent(
45
+ "env-d1",
46
+ StockReserved({orderId: "o2", productId: "p2"}),
47
+ )
48
+
49
+ let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
50
+ await ops.processPending()
51
+
52
+ expect(publishedCommands.contents->Array.length)->toBe(1)
53
+ let cmd = publishedCommands.contents->Array.getUnsafe(0)
54
+ expect(cmd.id)->toBe("o2:p2")
55
+ })
56
+
57
+ testPromise("DCB-source StockReleased after a Processing item is idempotent", async () => {
58
+ publishedCommands := []
59
+ // Reserve fires phase1+phase2 (inline) — produces 1 command, item becomes
60
+ // Processing. StockReleased then resolves the item to Completed —
61
+ // subsequent processPending calls produce no further commands for it.
62
+ let _ = await publishDcbEvent(
63
+ "env-d2",
64
+ StockReserved({orderId: "o3", productId: "p3"}),
65
+ )
66
+ let _ = await publishDcbEvent(
67
+ "env-d3",
68
+ StockReleased({orderId: "o3", productId: "p3"}),
69
+ )
70
+
71
+ expect(publishedCommands.contents->Array.length)->toBe(1)
72
+
73
+ // Reset and call processPending again — already-Processing/Completed item
74
+ // shouldn't generate a duplicate.
75
+ publishedCommands := []
76
+ let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
77
+ await ops.processPending()
78
+ expect(publishedCommands.contents->Array.length)->toBe(0)
79
+ })
80
+
81
+ testPromise("both sources can drive items into the same TODO list independently", async () => {
82
+ publishedCommands := []
83
+ let _ = await publishAggregateEvent(
84
+ "env-a2",
85
+ OrderShipped({orderId: "o4", productId: "p4"}),
86
+ )
87
+ let _ = await publishDcbEvent(
88
+ "env-d4",
89
+ StockReserved({orderId: "o5", productId: "p5"}),
90
+ )
91
+
92
+ let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
93
+ await ops.processPending()
94
+
95
+ expect(publishedCommands.contents->Array.length)->toBe(2)
96
+ let ids = publishedCommands.contents->Array.map(c => c.id)
97
+ expect(ids->Array.includes("o4:p4"))->toBe(true)
98
+ expect(ids->Array.includes("o5:p5"))->toBe(true)
99
+ })
100
+
101
+ testPromise("first-writer-wins idempotency across mappings sharing an ID", async () => {
102
+ publishedCommands := []
103
+ // Both sources produce the same composite ID — second arrival is ignored.
104
+ let _ = await publishAggregateEvent(
105
+ "env-a3",
106
+ OrderShipped({orderId: "o6", productId: "p6"}),
107
+ )
108
+ let _ = await publishDcbEvent(
109
+ "env-d5",
110
+ StockReserved({orderId: "o6", productId: "p6"}),
111
+ )
112
+
113
+ let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
114
+ await ops.processPending()
115
+
116
+ expect(publishedCommands.contents->Array.length)->toBe(1)
117
+ })
118
+ })
@@ -0,0 +1,99 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
4
+ import * as TestRunner$ReventlessLocal from "../../../src/test/TestRunner.res.mjs";
5
+ import * as MixedSourceAutomationSliceFixtures$ReventlessLocal from "./MixedSourceAutomationSliceFixtures.res.mjs";
6
+
7
+ globalThis.describe("MixedSource AutomationSlice", () => {
8
+ globalThis.beforeAll(async () => {
9
+ await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
10
+ await TestRunner$ReventlessLocal.resolve(MixedSourceAutomationSliceFixtures$ReventlessLocal.aggregateResource.name);
11
+ await TestRunner$ReventlessLocal.resolve(MixedSourceAutomationSliceFixtures$ReventlessLocal.dcbResource.name);
12
+ await Promise.resolve();
13
+ await Promise.resolve();
14
+ });
15
+ globalThis.beforeEach(() => {
16
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
17
+ });
18
+ globalThis.test("Aggregate-source event creates a TODO and produces a command", async () => {
19
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
20
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishAggregateEvent("env-a1", {
21
+ TAG: "OrderShipped",
22
+ orderId: "o1",
23
+ productId: "p1"
24
+ });
25
+ let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
26
+ await ops.processPending();
27
+ globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
28
+ let cmd = MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents[0];
29
+ globalThis.expect(cmd.id).toBe("o1:p1");
30
+ });
31
+ globalThis.test("DCB-source StockReserved creates a TODO and produces a command", async () => {
32
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
33
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d1", {
34
+ TAG: "StockReserved",
35
+ orderId: "o2",
36
+ productId: "p2"
37
+ });
38
+ let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
39
+ await ops.processPending();
40
+ globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
41
+ let cmd = MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents[0];
42
+ globalThis.expect(cmd.id).toBe("o2:p2");
43
+ });
44
+ globalThis.test("DCB-source StockReleased after a Processing item is idempotent", async () => {
45
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
46
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d2", {
47
+ TAG: "StockReserved",
48
+ orderId: "o3",
49
+ productId: "p3"
50
+ });
51
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d3", {
52
+ TAG: "StockReleased",
53
+ orderId: "o3",
54
+ productId: "p3"
55
+ });
56
+ globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
57
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
58
+ let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
59
+ await ops.processPending();
60
+ globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(0);
61
+ });
62
+ globalThis.test("both sources can drive items into the same TODO list independently", async () => {
63
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
64
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishAggregateEvent("env-a2", {
65
+ TAG: "OrderShipped",
66
+ orderId: "o4",
67
+ productId: "p4"
68
+ });
69
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d4", {
70
+ TAG: "StockReserved",
71
+ orderId: "o5",
72
+ productId: "p5"
73
+ });
74
+ let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
75
+ await ops.processPending();
76
+ globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(2);
77
+ let ids = MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.map(c => c.id);
78
+ globalThis.expect(ids.includes("o4:p4")).toBe(true);
79
+ globalThis.expect(ids.includes("o5:p5")).toBe(true);
80
+ });
81
+ globalThis.test("first-writer-wins idempotency across mappings sharing an ID", async () => {
82
+ MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
83
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishAggregateEvent("env-a3", {
84
+ TAG: "OrderShipped",
85
+ orderId: "o6",
86
+ productId: "p6"
87
+ });
88
+ await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d5", {
89
+ TAG: "StockReserved",
90
+ orderId: "o6",
91
+ productId: "p6"
92
+ });
93
+ let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
94
+ await ops.processPending();
95
+ globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
96
+ });
97
+ });
98
+
99
+ /* Not a pure module */