@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,358 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Http from "http";
5
+ import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
6
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
+ import * as McpSdk_Helpers from "@reventlessdev/rescript-mcp-sdk/src/McpSdk_Helpers.res.mjs";
8
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
+ import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
10
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
11
+ import * as Logger$ReventlessCore from "@reventlessdev/reventless-core/src/util/Logger.res.mjs";
12
+ import * as MCP_SchemaGenerator$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/MCP_SchemaGenerator.res.mjs";
13
+ import * as IndexJs from "@modelcontextprotocol/sdk/server/index.js";
14
+ import * as StreamableHttpJs from "@modelcontextprotocol/sdk/server/streamableHttp.js";
15
+
16
+ let log = Logger$ReventlessCore.fromEnv();
17
+
18
+ let tools = {
19
+ contents: {}
20
+ };
21
+
22
+ let resources = {
23
+ contents: {}
24
+ };
25
+
26
+ let resourceTemplates = {
27
+ contents: {}
28
+ };
29
+
30
+ function registerTool(name, definition, handler) {
31
+ tools.contents[name] = {
32
+ definition: definition,
33
+ handler: handler
34
+ };
35
+ }
36
+
37
+ function registerResource(name, definition, handler) {
38
+ resources.contents[name] = {
39
+ definition: definition,
40
+ handler: handler
41
+ };
42
+ }
43
+
44
+ function registerResourceTemplate(name, definition, handler) {
45
+ resourceTemplates.contents[name] = {
46
+ definition: definition,
47
+ handler: handler
48
+ };
49
+ }
50
+
51
+ function registerToolsFromEntries(pluginName, mutationEntries, commandHandler) {
52
+ let toolDefs = MCP_SchemaGenerator$ReventlessCore.generateTools(pluginName, mutationEntries);
53
+ toolDefs.forEach(def => {
54
+ let handler = async (args, identity) => {
55
+ try {
56
+ return McpSdk_Helpers.toolResult(await commandHandler(def.name, args, identity));
57
+ } catch (raw_exn) {
58
+ let exn = Primitive_exceptions.internalToException(raw_exn);
59
+ return McpSdk_Helpers.toolError(Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(exn), Stdlib_JsExn.message), "Command failed"));
60
+ }
61
+ };
62
+ registerTool(def.name, def, handler);
63
+ });
64
+ }
65
+
66
+ function registerResourcesFromEntries(pluginName, queryEntries, queryHandler) {
67
+ let resourceDefs = MCP_SchemaGenerator$ReventlessCore.generateResources(pluginName, queryEntries);
68
+ resourceDefs.forEach(def => {
69
+ let handler = async uri => {
70
+ let result = await queryHandler(def.name, uri);
71
+ return {
72
+ contents: [{
73
+ uri: uri,
74
+ text: JSON.stringify(result)
75
+ }]
76
+ };
77
+ };
78
+ if (def.uriTemplate.includes("{")) {
79
+ return registerResourceTemplate(def.name, def, handler);
80
+ } else {
81
+ return registerResource(def.name, def, handler);
82
+ }
83
+ });
84
+ }
85
+
86
+ function registerEventHistoryResourcesFromEntries(pluginName, eventLogEntries, eventLogHandler) {
87
+ let resourceDefs = MCP_SchemaGenerator$ReventlessCore.generateEventHistoryResources(pluginName, eventLogEntries);
88
+ resourceDefs.forEach(def => {
89
+ let handler = async uri => {
90
+ let result = await eventLogHandler(def.name, uri);
91
+ return {
92
+ contents: [{
93
+ uri: uri,
94
+ text: JSON.stringify(result)
95
+ }]
96
+ };
97
+ };
98
+ registerResourceTemplate(def.name, def, handler);
99
+ });
100
+ }
101
+
102
+ let activeServer = {
103
+ contents: undefined
104
+ };
105
+
106
+ let debug = Stdlib_Option.isSome(process.env["MCP_DEBUG"]);
107
+
108
+ function extractIdentity(req) {
109
+ try {
110
+ let headers = req.headers;
111
+ let json = headers["x-identity"];
112
+ if (json !== undefined) {
113
+ return S.parseOrThrow(JSON.parse(json), Identity$Reventless.schema);
114
+ } else {
115
+ return Identity$Reventless.anonymous;
116
+ }
117
+ } catch (exn) {
118
+ return Identity$Reventless.anonymous;
119
+ }
120
+ }
121
+
122
+ function createServerInstance(identity) {
123
+ let server = new IndexJs.Server({
124
+ name: "reventless-mcp",
125
+ version: "1.0.0"
126
+ }, {
127
+ capabilities: {
128
+ tools: {
129
+ _placeholder: false
130
+ },
131
+ resources: {
132
+ _placeholder: false
133
+ }
134
+ }
135
+ });
136
+ McpSdk_Helpers.onListTools(server, async () => {
137
+ let toolDefs = Object.values(tools.contents).map(param => {
138
+ let definition = param.definition;
139
+ return {
140
+ name: definition.name,
141
+ description: definition.description,
142
+ inputSchema: definition.inputSchema
143
+ };
144
+ });
145
+ return {
146
+ tools: toolDefs
147
+ };
148
+ });
149
+ McpSdk_Helpers.onCallTool(server, async req => {
150
+ let toolName = req.params.name;
151
+ let args = Stdlib_Option.getOr(req.params.arguments, null);
152
+ if (debug) {
153
+ log.info("MCP:Domain", undefined, `tools/call: ` + toolName);
154
+ }
155
+ let match = tools.contents[toolName];
156
+ if (match !== undefined) {
157
+ return await match.handler(args, identity);
158
+ } else {
159
+ return McpSdk_Helpers.toolError(`Unknown tool: ` + toolName);
160
+ }
161
+ });
162
+ McpSdk_Helpers.onListResources(server, async () => {
163
+ let resourceDefs = Object.values(resources.contents).map(param => {
164
+ let definition = param.definition;
165
+ return {
166
+ uri: definition.uriTemplate,
167
+ name: definition.name,
168
+ description: definition.description,
169
+ mimeType: definition.mimeType
170
+ };
171
+ });
172
+ return {
173
+ resources: resourceDefs
174
+ };
175
+ });
176
+ McpSdk_Helpers.onListResourceTemplates(server, async () => {
177
+ let templateDefs = Object.values(resourceTemplates.contents).map(param => {
178
+ let definition = param.definition;
179
+ return {
180
+ uriTemplate: definition.uriTemplate,
181
+ name: definition.name,
182
+ description: definition.description,
183
+ mimeType: definition.mimeType
184
+ };
185
+ });
186
+ return {
187
+ resourceTemplates: templateDefs
188
+ };
189
+ });
190
+ McpSdk_Helpers.onReadResource(server, async req => {
191
+ let uri = req.params.uri;
192
+ if (debug) {
193
+ log.info("MCP:Domain", undefined, `resources/read: ` + uri);
194
+ }
195
+ let matchedResource = Object.values(resources.contents).find(param => uri.includes(param.definition.name));
196
+ if (matchedResource !== undefined) {
197
+ if (debug) {
198
+ log.debug("MCP:Domain", undefined, `matched resource: ` + matchedResource.definition.name);
199
+ }
200
+ return await matchedResource.handler(uri);
201
+ }
202
+ let matchedTemplate = Object.values(resourceTemplates.contents).find(param => uri.includes(param.definition.name));
203
+ if (matchedTemplate !== undefined) {
204
+ if (debug) {
205
+ log.debug("MCP:Domain", undefined, `matched template: ` + matchedTemplate.definition.name);
206
+ }
207
+ return await matchedTemplate.handler(uri);
208
+ } else {
209
+ return {
210
+ contents: [{
211
+ uri: uri,
212
+ text: `{"error": "Resource not found: ` + uri + `"}`
213
+ }]
214
+ };
215
+ }
216
+ });
217
+ return server;
218
+ }
219
+
220
+ function start(portOpt, param) {
221
+ let port = portOpt !== undefined ? portOpt : 3001;
222
+ let httpServer = Http.createServer((req, res) => {
223
+ (async () => {
224
+ let reqMethod = req.method;
225
+ let reqUrl = req.url;
226
+ res.setHeader("Access-Control-Allow-Origin", "*");
227
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
228
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
229
+ if (reqUrl === "/mcp" || reqUrl.startsWith("/mcp?")) {
230
+ switch (reqMethod) {
231
+ case "DELETE" :
232
+ res.statusCode = 200;
233
+ res.end();
234
+ return;
235
+ case "GET" :
236
+ res.setHeader("Content-Type", "text/plain");
237
+ res.end("MCP server running");
238
+ return;
239
+ case "OPTIONS" :
240
+ res.statusCode = 204;
241
+ res.end();
242
+ return;
243
+ case "POST" :
244
+ let body = await McpSdk_Helpers.parseJsonBody(req);
245
+ let identity = extractIdentity(req);
246
+ let server = createServerInstance(identity);
247
+ let transport = new StreamableHttpJs.StreamableHTTPServerTransport({
248
+ enableJsonResponse: true
249
+ });
250
+ await server.connect(transport);
251
+ await transport.handleRequest(req, res, body);
252
+ return;
253
+ default:
254
+ res.statusCode = 405;
255
+ res.end("Method not allowed");
256
+ return;
257
+ }
258
+ } else {
259
+ res.statusCode = 404;
260
+ res.end("Not found");
261
+ return;
262
+ }
263
+ })();
264
+ });
265
+ httpServer.listen(port, () => {
266
+ log.info("MCP:Domain", undefined, `listening on http://localhost:` + port.toString() + `/mcp`);
267
+ if (!debug) {
268
+ return;
269
+ }
270
+ let toolNames = Object.keys(tools.contents);
271
+ let resourceNames = Object.keys(resources.contents);
272
+ let templateNames = Object.keys(resourceTemplates.contents);
273
+ log.info("MCP:Domain", undefined, `tools (` + toolNames.length.toString() + `):`);
274
+ toolNames.forEach(t => log.info("MCP:Domain", undefined, ` - ` + t));
275
+ log.info("MCP:Domain", undefined, `resources (` + resourceNames.length.toString() + `):`);
276
+ resourceNames.forEach(r => log.info("MCP:Domain", undefined, ` - ` + r));
277
+ log.info("MCP:Domain", undefined, `resource templates (` + templateNames.length.toString() + `):`);
278
+ templateNames.forEach(r => log.info("MCP:Domain", undefined, ` - ` + r));
279
+ });
280
+ activeServer.contents = Primitive_option.some(httpServer);
281
+ }
282
+
283
+ function stop() {
284
+ let server = activeServer.contents;
285
+ if (server !== undefined) {
286
+ Primitive_option.valFromOption(server).close(() => {});
287
+ activeServer.contents = undefined;
288
+ return;
289
+ }
290
+ }
291
+
292
+ function reset() {
293
+ tools.contents = {};
294
+ resources.contents = {};
295
+ resourceTemplates.contents = {};
296
+ }
297
+
298
+ function diagnostics() {
299
+ let toolNames = Object.keys(tools.contents);
300
+ let resourceNames = Object.keys(resources.contents).concat(Object.keys(resourceTemplates.contents));
301
+ return {
302
+ registeredTools: toolNames,
303
+ registeredResources: resourceNames,
304
+ toolCount: toolNames.length,
305
+ resourceCount: resourceNames.length,
306
+ serverRunning: Stdlib_Option.isSome(activeServer.contents)
307
+ };
308
+ }
309
+
310
+ function printDiagnostics() {
311
+ let d = diagnostics();
312
+ log.info("MCP:Domain", undefined, "diagnostics");
313
+ log.info("MCP:Domain", undefined, ` tools (` + d.toolCount.toString() + `):`);
314
+ d.registeredTools.forEach(t => log.info("MCP:Domain", undefined, ` - ` + t));
315
+ log.info("MCP:Domain", undefined, ` resources (` + d.resourceCount.toString() + `):`);
316
+ d.registeredResources.forEach(r => log.info("MCP:Domain", undefined, ` - ` + r));
317
+ log.info("MCP:Domain", undefined, ` server running: ` + (
318
+ d.serverRunning ? "yes" : "no"
319
+ ));
320
+ }
321
+
322
+ let asInterface = {
323
+ registerTool: registerTool,
324
+ registerResource: registerResource,
325
+ registerResourceTemplate: registerResourceTemplate,
326
+ registerToolsFromEntries: registerToolsFromEntries,
327
+ registerResourcesFromEntries: registerResourcesFromEntries,
328
+ registerEventHistoryResourcesFromEntries: registerEventHistoryResourcesFromEntries,
329
+ start: start,
330
+ stop: stop,
331
+ reset: reset,
332
+ diagnostics: diagnostics,
333
+ printDiagnostics: printDiagnostics
334
+ };
335
+
336
+ export {
337
+ log,
338
+ tools,
339
+ resources,
340
+ resourceTemplates,
341
+ registerTool,
342
+ registerResource,
343
+ registerResourceTemplate,
344
+ registerToolsFromEntries,
345
+ registerResourcesFromEntries,
346
+ registerEventHistoryResourcesFromEntries,
347
+ activeServer,
348
+ debug,
349
+ extractIdentity,
350
+ createServerInstance,
351
+ start,
352
+ stop,
353
+ reset,
354
+ diagnostics,
355
+ printDiagnostics,
356
+ asInterface,
357
+ }
358
+ /* log Not a pure module */
@@ -0,0 +1,87 @@
1
+ // In-memory EventCollector channel.
2
+ // connect subscribes to all event topics in the bus using the resource name as topic key.
3
+ // Each published event awaits the handler Deferred before delivery — eliminating the race
4
+ // where consumers see None and silently drop events.
5
+ // The runtime's subscriptionLatch is opened after each subscription is registered so
6
+ // callers can await it to know subscriptions are ready before publishing.
7
+
8
+ module Make = (Bus: LocalBus.T) => {
9
+ type callbackEvent = JSON.t
10
+ type channelParts = unit
11
+ type runtimeParts = LocalRuntimeEnvironment.parts
12
+
13
+ let make: ReventlessCore.EventCollector_Adapter.channelMaker<callbackEvent, 'context, channelParts> = (
14
+ ~name as _,
15
+ ~eventTopics,
16
+ ~opts as _,
17
+ ) => {
18
+ // Collect all event topic resources as our channel resources
19
+ let eventTopicResources =
20
+ eventTopics
21
+ ->Dict.valuesToArray
22
+ ->Array.flatMap((outputs: ReventlessCore.EventTopic.outputs) => outputs.resources)
23
+
24
+ {
25
+ parts: (),
26
+ resources: eventTopicResources,
27
+ enqueueEvent: ((_, _, _) => Promise.resolve())->Pulumi.Output.make,
28
+ handleChannelEvent: (handleEvents: ReventlessCore.EventCollector.jsonEventsHandler) =>
29
+ ((json: JSON.t, _ctx) =>
30
+ handleEvents(Stream.fromIterable([json]))->Effect.map(_ => ())
31
+ )->Pulumi.Output.make,
32
+ }
33
+ }
34
+
35
+ let connect: ReventlessCore.EventCollector_Adapter.connect<
36
+ callbackEvent,
37
+ 'context,
38
+ channelParts,
39
+ runtimeParts,
40
+ > = (~name, ~channelSpecs, ~runtime, ~opts as _) => {
41
+ // Register handler in Bus once resolved — allows makePlatform to wire cross-plugin
42
+ // Extension → EP EventTopic subscriptions after all plugins are built.
43
+ let _reg =
44
+ runtime.parts.handlerDeferred
45
+ ->Deferred.await_
46
+ ->Effect.flatMap(handler => Effect.sync(() => Bus.registerEventCollectorHandler(name, handler)))
47
+ ->Effect.runPromise
48
+ ->ignore
49
+
50
+ channelSpecs->Array.forEach(({eventTopics}: ReventlessCore.EventCollector_Adapter.channelSpec<
51
+ callbackEvent,
52
+ 'context,
53
+ channelParts,
54
+ >) => {
55
+ eventTopics
56
+ ->Dict.valuesToArray
57
+ ->Array.forEach((topicOutputs: ReventlessCore.EventTopic.outputs) => {
58
+ topicOutputs.resources->Array.forEach(resource => {
59
+ // resource.name is the bus topic key set by LocalEventTopicPublisher
60
+ let _ = resource.name->Pulumi.Output.apply(topicName => {
61
+ // Stream-based drain: subscribeToEventStream returns a scoped Effect that
62
+ // yields Stream<queuedEvent>. done_ is run explicitly after each handler call
63
+ // to unblock publishEvent.
64
+ let drainEffect = Effect.scoped(
65
+ Bus.subscribeToEventStream(topicName)
66
+ ->Effect.flatMap(stream =>
67
+ stream->Stream.runForEach(msg =>
68
+ Effect.promise(async () => {
69
+ let handler =
70
+ await runtime.parts.handlerDeferred->Deferred.await_->Effect.runPromise
71
+ await handler(msg.json, ())
72
+ })
73
+ ->Effect.zipRight(msg.done_)
74
+ )
75
+ ),
76
+ )
77
+ let _ = Effect.runFork(drainEffect)
78
+ // Signal that this topic's subscription is registered.
79
+ // Latch.open_ is idempotent — calling it for multiple topics is safe.
80
+ runtime.parts.subscriptionLatch->Latch.open_->Effect.runPromise->ignore
81
+ })
82
+ })
83
+ })
84
+ })
85
+ []
86
+ }
87
+ }
@@ -0,0 +1,45 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Effect from "effect/Effect";
4
+ import * as Stream from "effect/Stream";
5
+ import * as Pulumi from "@pulumi/pulumi";
6
+ import * as Deferred from "effect/Deferred";
7
+
8
+ function Make(Bus) {
9
+ let make = (param, eventTopics, param$1) => {
10
+ let eventTopicResources = Object.values(eventTopics).flatMap(outputs => outputs.resources);
11
+ return {
12
+ parts: undefined,
13
+ resources: eventTopicResources,
14
+ enqueueEvent: Pulumi.output((param, param$1, param$2) => Promise.resolve()),
15
+ handleChannelEvent: handleEvents => Pulumi.output((json, _ctx) => Effect.map(handleEvents(Stream.fromIterable([json])), () => {}))
16
+ };
17
+ };
18
+ let connect = (name, channelSpecs, runtime, param) => {
19
+ Effect.runPromise(Effect.flatMap(Deferred.await(runtime.parts.handlerDeferred), handler => Effect.sync(() => Bus.registerEventCollectorHandler(name, handler))));
20
+ channelSpecs.forEach(param => {
21
+ Object.values(param.eventTopics).forEach(topicOutputs => {
22
+ topicOutputs.resources.forEach(resource => {
23
+ resource.name.apply(topicName => {
24
+ let drainEffect = Effect.scoped(Effect.flatMap(Bus.subscribeToEventStream(topicName), stream => Stream.runForEach(stream, msg => Effect.zipRight(Effect.promise(async () => {
25
+ let handler = await Effect.runPromise(Deferred.await(runtime.parts.handlerDeferred));
26
+ return await handler(msg.json, undefined);
27
+ }), msg.done_))));
28
+ Effect.runFork(drainEffect);
29
+ Effect.runPromise(runtime.parts.subscriptionLatch.open);
30
+ });
31
+ });
32
+ });
33
+ });
34
+ return [];
35
+ };
36
+ return {
37
+ make: make,
38
+ connect: connect
39
+ };
40
+ }
41
+
42
+ export {
43
+ Make,
44
+ }
45
+ /* effect/Effect Not a pure module */
@@ -0,0 +1,105 @@
1
+ // In-memory event log storage.
2
+ // Uses Stm.TRef for transactional state management, preparing for future
3
+ // atomic append+publish spanning storage and the event bus.
4
+ //
5
+ // When BackendState is set to Sqlite, the `Make(Bus)` functor delegates to
6
+ // EventLogStorage_Sqlite at `make` time so the same builder wiring serves
7
+ // both backends.
8
+
9
+ let makeMemoryStorage = (~name as _name, ~opts as _) => {
10
+ let eventsRef =
11
+ Stm.TRef.make(Dict.make())
12
+ ->Stm.commit
13
+ ->Effect.runSync
14
+
15
+ let append: ReventlessCore.EventLog.append<string, JSON.t> = (seqNr, id, jsons) =>
16
+ Stm.TRef.modify(eventsRef, events => {
17
+ let existing = events->Dict.get(id)->Option.getOr([])
18
+ let currentCount = existing->Array.length
19
+ if seqNr != currentCount {
20
+ (Error("conflict"), events)
21
+ } else {
22
+ events->Dict.set(id, existing->Array.concat(jsons))
23
+ (Ok(), events)
24
+ }
25
+ })
26
+ ->Stm.commit
27
+ ->Effect.runPromise
28
+
29
+ // The in-memory array is already resident; expose it as a stream for API uniformity.
30
+ // The real performance gain from streaming comes from the DynamoDB adapter.
31
+ let replayStream: string => Stream.t<JSON.t, string, unit> = id =>
32
+ Stm.TRef.get(eventsRef)
33
+ ->Stm.commit
34
+ ->Effect.map(events => events->Dict.get(id)->Option.getOr([]))
35
+ ->Stream.fromEffect
36
+ ->Stream.flatMap(arr => Stream.fromIterable(arr))
37
+
38
+ // Eager replay derived from replayStream.
39
+ let replay: ReventlessCore.EventLog.replay<string, JSON.t> = id =>
40
+ replayStream(id)->Stream.runCollect->Effect.runPromise
41
+
42
+ // Appends each stream item sequentially to storage.
43
+ // Node.js is single-threaded so a plain ref is safe for the seqNr counter.
44
+ let appendStream: ReventlessCore.EventLog.appendStream<string, JSON.t> = (startingSeqNr, id, stream) => {
45
+ let seqNrRef = ref(startingSeqNr)
46
+ stream->Stream.runForEach(json =>
47
+ Stm.TRef.modify(eventsRef, events => {
48
+ let existing = events->Dict.get(id)->Option.getOr([])
49
+ let currentCount = existing->Array.length
50
+ if seqNrRef.contents != currentCount {
51
+ (Error("conflict"), events)
52
+ } else {
53
+ events->Dict.set(id, existing->Array.concat([json]))
54
+ (Ok(), events)
55
+ }
56
+ })
57
+ ->Stm.commit
58
+ ->Effect.flatMap(result =>
59
+ switch result {
60
+ | Ok() =>
61
+ seqNrRef := seqNrRef.contents + 1
62
+ Effect.succeed(())
63
+ | Error(msg) => Effect.fail(msg)
64
+ }
65
+ )
66
+ )
67
+ }
68
+
69
+ (
70
+ _name,
71
+ replay,
72
+ {
73
+ ReventlessCore.EventLog_Adapter.resources: [],
74
+ operations: Pulumi.Output.make({
75
+ ReventlessCore.EventLog_Adapter.append,
76
+ replay,
77
+ replayStream,
78
+ appendStream,
79
+ }),
80
+ },
81
+ )
82
+ }
83
+
84
+ // Alias retained for tests that still want the pure-memory implementation.
85
+ let makeStorage = makeMemoryStorage
86
+
87
+ let make: ReventlessCore.EventLog_Adapter.storageMaker = (~name, ~opts) => {
88
+ let (_, _, storage) = makeMemoryStorage(~name, ~opts)
89
+ storage
90
+ }
91
+
92
+ module Make = (Bus: LocalBus.T) => {
93
+ let make: ReventlessCore.EventLog_Adapter.storageMaker = (~name, ~opts) => {
94
+ switch BackendState.getDb() {
95
+ | Some(db) =>
96
+ let (storageName, replay, storage) = EventLogStorage_Sqlite.makeStorage(~db, ~name, ~opts)
97
+ Bus.registerEventLogReplay(storageName, replay)
98
+ storage
99
+ | None =>
100
+ let (storageName, replay, storage) = makeMemoryStorage(~name, ~opts)
101
+ Bus.registerEventLogReplay(storageName, replay)
102
+ storage
103
+ }
104
+ }
105
+ }