@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,277 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Stream from "@reventlessdev/rescript-effect/src/Stream.res.mjs";
5
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
6
+ import * as Effect from "effect/Effect";
7
+ import * as Pulumi from "@pulumi/pulumi";
8
+ import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
9
+ import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
10
+ import * as Projection$Reventless from "@reventlessdev/reventless-spec/src/types/Projection.res.mjs";
11
+ import * as Adapter$ReventlessInfra from "@reventlessdev/reventless-infra/src/adapter/Adapter.res.mjs";
12
+ import * as LocalBus$ReventlessLocal from "../../../src/adapter/LocalBus.res.mjs";
13
+ import * as TestRunner$ReventlessLocal from "../../../src/test/TestRunner.res.mjs";
14
+ import * as TestFixtures$ReventlessLocal from "../../TestFixtures.res.mjs";
15
+ import * as ReadModel_Builder$ReventlessLocal from "../../../src/components/ReadModel_Builder.res.mjs";
16
+
17
+ let name = "TestMixedReadModel";
18
+
19
+ let moduleUrl = import.meta.url;
20
+
21
+ let stateSchema = S.schema(s => ({
22
+ name: s.m(S.string),
23
+ source: s.m(S.string)
24
+ }));
25
+
26
+ let config = ReadModel$Reventless.config(undefined, undefined, undefined);
27
+
28
+ let MixedReadModelSpec = {
29
+ Id: undefined,
30
+ name: name,
31
+ moduleUrl: moduleUrl,
32
+ stateSchema: stateSchema,
33
+ config: config,
34
+ subIdConfig: undefined,
35
+ authorization: "AllowAuthenticated",
36
+ visibility: "Public"
37
+ };
38
+
39
+ let name$1 = "TestAggregateEventTopic";
40
+
41
+ let eventSchema = S.union([
42
+ S.schema(s => ({
43
+ TAG: "AggregateItemCreated",
44
+ name: s.m(S.string)
45
+ })),
46
+ S.schema(s => ({
47
+ TAG: "AggregateItemRenamed",
48
+ name: s.m(S.string)
49
+ }))
50
+ ]);
51
+
52
+ let AggregateSource = {
53
+ Id: undefined,
54
+ name: name$1,
55
+ eventSchema: eventSchema
56
+ };
57
+
58
+ let name$2 = "TestDcbEventTopic";
59
+
60
+ let eventSchema$1 = S.union([
61
+ S.schema(s => ({
62
+ TAG: "DcbItemAdded",
63
+ name: s.m(S.string)
64
+ })),
65
+ S.schema(s => ({
66
+ TAG: "DcbItemNameChanged",
67
+ name: s.m(S.string)
68
+ }))
69
+ ]);
70
+
71
+ let DcbSource = {
72
+ Id: undefined,
73
+ name: name$2,
74
+ eventSchema: eventSchema$1
75
+ };
76
+
77
+ function project(msg) {
78
+ let match = msg.event;
79
+ if (match.TAG === "AggregateItemCreated") {
80
+ return {
81
+ TAG: "Create",
82
+ _0: msg.id,
83
+ _1: {
84
+ name: match.name,
85
+ source: "aggregate"
86
+ }
87
+ };
88
+ }
89
+ let name = match.name;
90
+ return {
91
+ TAG: "Update",
92
+ _0: msg.id,
93
+ _1: state => ({
94
+ name: name,
95
+ source: state.source
96
+ })
97
+ };
98
+ }
99
+
100
+ let AggregateMapping = Projection$Reventless.Mapping.Make({
101
+ Id: Id$Reventless.$$String,
102
+ name: name$1,
103
+ eventSchema: eventSchema
104
+ })({
105
+ Id: Id$Reventless.$$String,
106
+ name: name,
107
+ stateSchema: stateSchema,
108
+ subIdConfig: undefined
109
+ })({
110
+ project: project
111
+ });
112
+
113
+ function project$1(msg) {
114
+ let match = msg.event;
115
+ if (match.TAG === "DcbItemAdded") {
116
+ return {
117
+ TAG: "Create",
118
+ _0: msg.id,
119
+ _1: {
120
+ name: match.name,
121
+ source: "dcb"
122
+ }
123
+ };
124
+ }
125
+ let name = match.name;
126
+ return {
127
+ TAG: "Update",
128
+ _0: msg.id,
129
+ _1: state => ({
130
+ name: name,
131
+ source: state.source
132
+ })
133
+ };
134
+ }
135
+
136
+ let DcbMapping = Projection$Reventless.Mapping.Make({
137
+ Id: Id$Reventless.$$String,
138
+ name: name$2,
139
+ eventSchema: eventSchema$1
140
+ })({
141
+ Id: Id$Reventless.$$String,
142
+ name: name,
143
+ stateSchema: stateSchema,
144
+ subIdConfig: undefined
145
+ })({
146
+ project: project$1
147
+ });
148
+
149
+ Projection$Reventless.Mappings.Make({
150
+ Id: Id$Reventless.$$String,
151
+ name: name,
152
+ stateSchema: stateSchema,
153
+ subIdConfig: undefined
154
+ });
155
+
156
+ let moduleUrl$1 = import.meta.url;
157
+
158
+ let mappings = [
159
+ AggregateMapping,
160
+ DcbMapping
161
+ ];
162
+
163
+ let MixedMappings = {
164
+ moduleUrl: moduleUrl$1,
165
+ mappings: mappings
166
+ };
167
+
168
+ let aggregateTopicName = "TestAggregateEventTopic";
169
+
170
+ let dcbTopicName = "TestDcbEventTopic";
171
+
172
+ let aggregateResource = Adapter$ReventlessInfra.make(Pulumi.output(aggregateTopicName), Pulumi.output(aggregateTopicName), Pulumi.output(aggregateTopicName), Pulumi.output("memory:InMemory"), undefined, undefined, undefined, undefined, undefined, undefined);
173
+
174
+ let dcbResource = Adapter$ReventlessInfra.make(Pulumi.output(dcbTopicName), Pulumi.output(dcbTopicName), Pulumi.output(dcbTopicName), Pulumi.output("memory:InMemory"), undefined, undefined, undefined, undefined, undefined, undefined);
175
+
176
+ let allEventTopics = Object.fromEntries([
177
+ [
178
+ aggregateTopicName,
179
+ {
180
+ resources: [aggregateResource]
181
+ }
182
+ ],
183
+ [
184
+ dcbTopicName,
185
+ {
186
+ resources: [dcbResource]
187
+ }
188
+ ]
189
+ ]);
190
+
191
+ let Bus = LocalBus$ReventlessLocal.Make({});
192
+
193
+ TestRunner$ReventlessLocal.setup();
194
+
195
+ let ReadModelMaker = ReadModel_Builder$ReventlessLocal.Make(Bus);
196
+
197
+ let MixedRM = ReadModelMaker.Make({
198
+ Id: Id$Reventless.$$String,
199
+ name: name,
200
+ moduleUrl: moduleUrl,
201
+ stateSchema: stateSchema,
202
+ config: config,
203
+ subIdConfig: undefined,
204
+ authorization: "AllowAuthenticated",
205
+ visibility: "Public"
206
+ })(MixedMappings);
207
+
208
+ let rm = MixedRM.make(undefined, undefined, allEventTopics, undefined);
209
+
210
+ async function publishAggregateEvent(id, event) {
211
+ let meta = TestFixtures$ReventlessLocal.makeTestMeta("TestAggregateEventTopic");
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(aggregateTopicName, "test", meta, eventJson);
227
+ }
228
+
229
+ async function publishDcbEvent(id, event) {
230
+ let meta = TestFixtures$ReventlessLocal.makeTestMeta("TestDcbEventTopic");
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(dcbTopicName, "test", meta, eventJson);
246
+ }
247
+
248
+ async function loadState(id) {
249
+ let ops = Bus.getQueryDb("TestMixedReadModel");
250
+ if (ops === undefined) {
251
+ return [];
252
+ }
253
+ let states = await Effect.runPromise(Effect.catchAll(Stream.runCollect(ops.loadStream(id)), param => Effect.succeed([])));
254
+ return states.map(json => S.parseJsonOrThrow(json, stateSchema));
255
+ }
256
+
257
+ export {
258
+ MixedReadModelSpec,
259
+ AggregateSource,
260
+ DcbSource,
261
+ AggregateMapping,
262
+ DcbMapping,
263
+ MixedMappings,
264
+ aggregateTopicName,
265
+ dcbTopicName,
266
+ aggregateResource,
267
+ dcbResource,
268
+ allEventTopics,
269
+ Bus,
270
+ ReadModelMaker,
271
+ MixedRM,
272
+ rm,
273
+ publishAggregateEvent,
274
+ publishDcbEvent,
275
+ loadState,
276
+ }
277
+ /* moduleUrl Not a pure module */
@@ -0,0 +1,61 @@
1
+ // Integration test: ReadModel with mixed event sources.
2
+ // Verifies that a single ReadModel can project events from two independent
3
+ // EventTopics (simulating aggregate + DCB sources merged by Plugin_Builder).
4
+
5
+ open JestGlobals
6
+ open MixedSourceReadModelFixtures
7
+
8
+ describe("MixedSource ReadModel", () => {
9
+ let _ = beforeAllAsync(async () => {
10
+ let _ = await rm->MixedRM.operations->TestRunner.resolve
11
+ let _ = await aggregateResource.name->TestRunner.resolve
12
+ let _ = await dcbResource.name->TestRunner.resolve
13
+ })
14
+
15
+ testPromise("aggregate event projects with source 'aggregate'", async () => {
16
+ let _ = await publishAggregateEvent("agg-1", AggregateItemCreated({name: "Widget"}))
17
+ let states = await loadState("agg-1")
18
+ expect(states->Array.length)->toBe(1)
19
+ let state = states->Array.getUnsafe(0)
20
+ expect(state.name)->toBe("Widget")
21
+ expect(state.source)->toBe("aggregate")
22
+ })
23
+
24
+ testPromise("DCB event projects with source 'dcb'", async () => {
25
+ let _ = await publishDcbEvent("dcb-1", DcbItemAdded({name: "Gadget"}))
26
+ let states = await loadState("dcb-1")
27
+ expect(states->Array.length)->toBe(1)
28
+ let state = states->Array.getUnsafe(0)
29
+ expect(state.name)->toBe("Gadget")
30
+ expect(state.source)->toBe("dcb")
31
+ })
32
+
33
+ testPromise("both sources coexist independently", async () => {
34
+ let aggStates = await loadState("agg-1")
35
+ let dcbStates = await loadState("dcb-1")
36
+ expect(aggStates->Array.length)->toBe(1)
37
+ expect(dcbStates->Array.length)->toBe(1)
38
+ let agg = aggStates->Array.getUnsafe(0)
39
+ let dcb = dcbStates->Array.getUnsafe(0)
40
+ expect(agg.source)->toBe("aggregate")
41
+ expect(dcb.source)->toBe("dcb")
42
+ })
43
+
44
+ testPromise("aggregate update modifies existing entry", async () => {
45
+ let _ = await publishAggregateEvent("agg-1", AggregateItemRenamed({name: "Super Widget"}))
46
+ let states = await loadState("agg-1")
47
+ expect(states->Array.length)->toBe(1)
48
+ let state = states->Array.getUnsafe(0)
49
+ expect(state.name)->toBe("Super Widget")
50
+ expect(state.source)->toBe("aggregate")
51
+ })
52
+
53
+ testPromise("DCB update modifies existing entry", async () => {
54
+ let _ = await publishDcbEvent("dcb-1", DcbItemNameChanged({name: "Super Gadget"}))
55
+ let states = await loadState("dcb-1")
56
+ expect(states->Array.length)->toBe(1)
57
+ let state = states->Array.getUnsafe(0)
58
+ expect(state.name)->toBe("Super Gadget")
59
+ expect(state.source)->toBe("dcb")
60
+ })
61
+ })
@@ -0,0 +1,68 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as TestRunner$ReventlessLocal from "../../../src/test/TestRunner.res.mjs";
4
+ import * as MixedSourceReadModelFixtures$ReventlessLocal from "./MixedSourceReadModelFixtures.res.mjs";
5
+
6
+ globalThis.describe("MixedSource ReadModel", () => {
7
+ globalThis.beforeAll(async () => {
8
+ await TestRunner$ReventlessLocal.resolve(MixedSourceReadModelFixtures$ReventlessLocal.MixedRM.operations(MixedSourceReadModelFixtures$ReventlessLocal.rm));
9
+ await TestRunner$ReventlessLocal.resolve(MixedSourceReadModelFixtures$ReventlessLocal.aggregateResource.name);
10
+ await TestRunner$ReventlessLocal.resolve(MixedSourceReadModelFixtures$ReventlessLocal.dcbResource.name);
11
+ });
12
+ globalThis.test("aggregate event projects with source 'aggregate'", async () => {
13
+ await MixedSourceReadModelFixtures$ReventlessLocal.publishAggregateEvent("agg-1", {
14
+ TAG: "AggregateItemCreated",
15
+ name: "Widget"
16
+ });
17
+ let states = await MixedSourceReadModelFixtures$ReventlessLocal.loadState("agg-1");
18
+ globalThis.expect(states.length).toBe(1);
19
+ let state = states[0];
20
+ globalThis.expect(state.name).toBe("Widget");
21
+ globalThis.expect(state.source).toBe("aggregate");
22
+ });
23
+ globalThis.test("DCB event projects with source 'dcb'", async () => {
24
+ await MixedSourceReadModelFixtures$ReventlessLocal.publishDcbEvent("dcb-1", {
25
+ TAG: "DcbItemAdded",
26
+ name: "Gadget"
27
+ });
28
+ let states = await MixedSourceReadModelFixtures$ReventlessLocal.loadState("dcb-1");
29
+ globalThis.expect(states.length).toBe(1);
30
+ let state = states[0];
31
+ globalThis.expect(state.name).toBe("Gadget");
32
+ globalThis.expect(state.source).toBe("dcb");
33
+ });
34
+ globalThis.test("both sources coexist independently", async () => {
35
+ let aggStates = await MixedSourceReadModelFixtures$ReventlessLocal.loadState("agg-1");
36
+ let dcbStates = await MixedSourceReadModelFixtures$ReventlessLocal.loadState("dcb-1");
37
+ globalThis.expect(aggStates.length).toBe(1);
38
+ globalThis.expect(dcbStates.length).toBe(1);
39
+ let agg = aggStates[0];
40
+ let dcb = dcbStates[0];
41
+ globalThis.expect(agg.source).toBe("aggregate");
42
+ globalThis.expect(dcb.source).toBe("dcb");
43
+ });
44
+ globalThis.test("aggregate update modifies existing entry", async () => {
45
+ await MixedSourceReadModelFixtures$ReventlessLocal.publishAggregateEvent("agg-1", {
46
+ TAG: "AggregateItemRenamed",
47
+ name: "Super Widget"
48
+ });
49
+ let states = await MixedSourceReadModelFixtures$ReventlessLocal.loadState("agg-1");
50
+ globalThis.expect(states.length).toBe(1);
51
+ let state = states[0];
52
+ globalThis.expect(state.name).toBe("Super Widget");
53
+ globalThis.expect(state.source).toBe("aggregate");
54
+ });
55
+ globalThis.test("DCB update modifies existing entry", async () => {
56
+ await MixedSourceReadModelFixtures$ReventlessLocal.publishDcbEvent("dcb-1", {
57
+ TAG: "DcbItemNameChanged",
58
+ name: "Super Gadget"
59
+ });
60
+ let states = await MixedSourceReadModelFixtures$ReventlessLocal.loadState("dcb-1");
61
+ globalThis.expect(states.length).toBe(1);
62
+ let state = states[0];
63
+ globalThis.expect(state.name).toBe("Super Gadget");
64
+ globalThis.expect(state.source).toBe("dcb");
65
+ });
66
+ });
67
+
68
+ /* Not a pure module */
@@ -0,0 +1,138 @@
1
+ // E2E test fixtures for ReadModel builder.
2
+ // Builds a ReadModel from a manually constructed allEventTopics and publishes
3
+ // events directly via the bus to verify projection into the QueryDb.
4
+
5
+ open TestFixtures
6
+ open Reventless
7
+ open Reventless.Projection
8
+
9
+ // ─────────────────────────────────────────────────────────────
10
+ // Minimal ReadModel spec
11
+ // ─────────────────────────────────────────────────────────────
12
+
13
+ module ItemReadModelSpec = {
14
+ module Id = Reventless.Id.String
15
+ let name = "TestItemReadModel"
16
+ let moduleUrl: string = %raw(`import.meta.url`)
17
+
18
+ @schema
19
+ type state = {name: string}
20
+
21
+ let config = ReadModel.config()
22
+ let subIdConfig = None
23
+ }
24
+
25
+ // ─────────────────────────────────────────────────────────────
26
+ // Minimal source event
27
+ // Used as the projection source — topic name doubles as mapping.sourceName
28
+ // ─────────────────────────────────────────────────────────────
29
+
30
+ module ItemEventSource = {
31
+ module Id = Reventless.Id.String
32
+ let name = "TestItemEventTopic" // must match allEventTopics key AND meta.service in published events
33
+
34
+ @schema
35
+ type event = | ItemCreated({name: string})
36
+ }
37
+
38
+ // ─────────────────────────────────────────────────────────────
39
+ // Mapping: ItemCreated → Create ReadModel state
40
+ // ─────────────────────────────────────────────────────────────
41
+
42
+ module ItemMapping = Mapping.Make(
43
+ ItemEventSource,
44
+ ItemReadModelSpec,
45
+ {
46
+ let project = (msg: Message.event'<string, ItemEventSource.event>) =>
47
+ switch msg.event {
48
+ | ItemCreated({name}) => Create(msg.id, ({name: name}: ItemReadModelSpec.state))
49
+ }
50
+ },
51
+ )
52
+
53
+ // ─────────────────────────────────────────────────────────────
54
+ // Mappings module required by ReadModel_Builder.Make
55
+ // ─────────────────────────────────────────────────────────────
56
+
57
+ module ItemMappings: Mappings with module Target := ItemReadModelSpec = {
58
+ module Mappings = Mappings.Make(ItemReadModelSpec)
59
+ module type Mapping = Mappings.Mapping
60
+ let moduleUrl: string = %raw(`import.meta.url`)
61
+ let mappings: array<module(Mapping)> = [module(ItemMapping)]
62
+ }
63
+
64
+ // ─────────────────────────────────────────────────────────────
65
+ // allEventTopics — constructed manually (no aggregate needed)
66
+ // resource.name is the bus topic key that EventCollectorChannel subscribes to.
67
+ // ─────────────────────────────────────────────────────────────
68
+
69
+ let topicName = "TestItemEventTopic"
70
+ let topicResource: ReventlessInfra.Adapter.resource = ReventlessInfra.Adapter.make(
71
+ ~name=topicName->Pulumi.Output.make,
72
+ ~id=topicName->Pulumi.Output.make,
73
+ ~urn=topicName->Pulumi.Output.make,
74
+ ~service="memory:InMemory"->Pulumi.Output.make,
75
+ )
76
+ let allEventTopics: ReventlessInfra.EventTopic.allOutputs = Dict.fromArray([
77
+ (topicName, {ReventlessInfra.EventTopic.resources: [topicResource]}),
78
+ ])
79
+
80
+ // ─────────────────────────────────────────────────────────────
81
+ // Isolated bus for this test suite
82
+ // ─────────────────────────────────────────────────────────────
83
+
84
+ module Bus = LocalBus.Make()
85
+
86
+ // ─────────────────────────────────────────────────────────────
87
+ // Activate Pulumi mock mode (must be before any Component.make)
88
+ // ─────────────────────────────────────────────────────────────
89
+
90
+ let _ = TestRunner.setup()
91
+
92
+ // ─────────────────────────────────────────────────────────────
93
+ // Build ReadModel
94
+ // ─────────────────────────────────────────────────────────────
95
+
96
+ module ReadModelMaker = ReadModel_Builder.Make(Bus)
97
+ module ItemReadModel = ReadModelMaker.Make(ItemReadModelSpec, ItemMappings)
98
+ let rm = ItemReadModel.make(~api=(), ~apiRole=(), ~allEventTopics)
99
+
100
+ // ─────────────────────────────────────────────────────────────
101
+ // Test helpers
102
+ // ─────────────────────────────────────────────────────────────
103
+
104
+ // meta.service MUST match Mapping.sourceName ("TestItemEventTopic") for
105
+ // ReadModel_Callback to route the event to the correct mapping.
106
+ let testMeta = makeTestMeta(~service="TestItemEventTopic")
107
+
108
+ // Publish a typed event to the bus topic.
109
+ // The event JSON must be {id, meta, event} format for Message.decodeEvent' to parse.
110
+ let publishItemCreated = async (id, name) => {
111
+ let eventJson = JSON.Encode.object(
112
+ Dict.fromArray([
113
+ ("id", id->JSON.Encode.string),
114
+ ("meta", testMeta->S.reverseConvertToJsonOrThrow(Message.metaSchema)),
115
+ (
116
+ "event",
117
+ ItemEventSource.ItemCreated({name: name})
118
+ ->S.reverseConvertToJsonOrThrow(ItemEventSource.eventSchema),
119
+ ),
120
+ ]),
121
+ )
122
+ await Bus.publishEvent(topicName, "test", testMeta, eventJson)
123
+ }
124
+
125
+ // Query projected state from the in-memory QueryDb.
126
+ // QueryDb is registered with the ReadModel Spec.name = "TestItemReadModel".
127
+ let loadState = async id => {
128
+ switch Bus.getQueryDb("TestItemReadModel") {
129
+ | None => []
130
+ | Some(ops) =>
131
+ let states =
132
+ await ops.loadStream(id)
133
+ ->Stream.runCollect
134
+ ->Effect.catchAll(_ => Effect.succeed([]))
135
+ ->Effect.runPromise
136
+ states->Array.map(json => json->S.parseJsonOrThrow(ItemReadModelSpec.stateSchema))
137
+ }
138
+ }