@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.
- package/CHANGELOG.md +1197 -0
- package/LICENSE +202 -0
- package/__mocks__/emptyModule.js +2 -0
- package/__mocks__/nodeSqlite.mjs +6 -0
- package/package.json +67 -0
- package/rescript.json +39 -0
- package/src/Platform.res +2162 -0
- package/src/Platform.res.mjs +3389 -0
- package/src/adapter/Api/LocalGraphQL_Adapter.res +29 -0
- package/src/adapter/Api/LocalGraphQL_Adapter.res.mjs +26 -0
- package/src/adapter/Api/LocalGraphQL_SubscriptionResolvers.res +146 -0
- package/src/adapter/Api/LocalGraphQL_SubscriptionResolvers.res.mjs +88 -0
- package/src/adapter/Auth/Auth_GraphqlContext.res +83 -0
- package/src/adapter/Auth/Auth_GraphqlContext.res.mjs +76 -0
- package/src/adapter/Auth/LocalAuth.res +239 -0
- package/src/adapter/Auth/LocalAuth.res.mjs +247 -0
- package/src/adapter/Auth/UserStore.res +134 -0
- package/src/adapter/Auth/UserStore.res.mjs +146 -0
- package/src/adapter/Backend.res +46 -0
- package/src/adapter/Backend.res.mjs +66 -0
- package/src/adapter/BackendState.res +34 -0
- package/src/adapter/BackendState.res.mjs +42 -0
- package/src/adapter/Cloner/LocalClonerRunner.res +13 -0
- package/src/adapter/Cloner/LocalClonerRunner.res.mjs +12 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_GraphQL.res +329 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_GraphQL.res.mjs +301 -0
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_GraphQL.res +76 -0
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_GraphQL.res.mjs +57 -0
- package/src/adapter/CommandGenerator/LocalCommandGeneratorResolvers.res +19 -0
- package/src/adapter/CommandGenerator/LocalCommandGeneratorResolvers.res.mjs +19 -0
- package/src/adapter/CommandTopic/LocalCommandTopicChannel.res +104 -0
- package/src/adapter/CommandTopic/LocalCommandTopicChannel.res.mjs +82 -0
- package/src/adapter/CommandTopic/LocalCommandTopicRemoteChannel.res +32 -0
- package/src/adapter/CommandTopic/LocalCommandTopicRemoteChannel.res.mjs +38 -0
- package/src/adapter/Counter/LocalCounterHandler.res +42 -0
- package/src/adapter/Counter/LocalCounterHandler.res.mjs +45 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res +131 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs +140 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res +334 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res.mjs +299 -0
- package/src/adapter/DomainGraphQL_Server.res +565 -0
- package/src/adapter/DomainGraphQL_Server.res.mjs +576 -0
- package/src/adapter/DomainMCP_Server.res +369 -0
- package/src/adapter/DomainMCP_Server.res.mjs +358 -0
- package/src/adapter/EventCollector/LocalEventCollectorChannel.res +87 -0
- package/src/adapter/EventCollector/LocalEventCollectorChannel.res.mjs +45 -0
- package/src/adapter/EventLog/EventLogStorage_InMemory.res +105 -0
- package/src/adapter/EventLog/EventLogStorage_InMemory.res.mjs +117 -0
- package/src/adapter/EventLog/EventLogStorage_Sqlite.res +145 -0
- package/src/adapter/EventLog/EventLogStorage_Sqlite.res.mjs +155 -0
- package/src/adapter/EventTopic/LocalEventTopicPublisher.res +36 -0
- package/src/adapter/EventTopic/LocalEventTopicPublisher.res.mjs +31 -0
- package/src/adapter/GraphQL_Server.res +6 -0
- package/src/adapter/GraphQL_Server.res.mjs +154 -0
- package/src/adapter/GraphQL_ServerInstance.res +310 -0
- package/src/adapter/GraphQL_ServerInstance.res.mjs +257 -0
- package/src/adapter/Heartbeat/LocalHeartbeatRunner.res +57 -0
- package/src/adapter/Heartbeat/LocalHeartbeatRunner.res.mjs +34 -0
- package/src/adapter/LocalBus.res +498 -0
- package/src/adapter/LocalBus.res.mjs +1011 -0
- package/src/adapter/LocalPluginSpec.res +16 -0
- package/src/adapter/LocalPluginSpec.res.mjs +33 -0
- package/src/adapter/LocalSideEffectHandler.res +44 -0
- package/src/adapter/LocalSideEffectHandler.res.mjs +34 -0
- package/src/adapter/MCP_Server.res +4 -0
- package/src/adapter/MCP_Server.res.mjs +67 -0
- package/src/adapter/MCP_ServerInstance.res +362 -0
- package/src/adapter/MCP_ServerInstance.res.mjs +313 -0
- package/src/adapter/PlatformGraphQL_Server.res +75 -0
- package/src/adapter/PlatformGraphQL_Server.res.mjs +84 -0
- package/src/adapter/PlatformMCP_Server.res +23 -0
- package/src/adapter/PlatformMCP_Server.res.mjs +46 -0
- package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res +793 -0
- package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs +569 -0
- package/src/adapter/QueryDb/QueryDbStorage_InMemory.res +242 -0
- package/src/adapter/QueryDb/QueryDbStorage_InMemory.res.mjs +241 -0
- package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res +339 -0
- package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res.mjs +318 -0
- package/src/adapter/QueryDb/SortKey_Filter.res +48 -0
- package/src/adapter/QueryDb/SortKey_Filter.res.mjs +46 -0
- package/src/adapter/QueryEngine/LocalQueryEngine.res +57 -0
- package/src/adapter/QueryEngine/LocalQueryEngine.res.mjs +56 -0
- package/src/adapter/Runtime/LocalAggregateRuntime_Builder.res +91 -0
- package/src/adapter/Runtime/LocalAggregateRuntime_Builder.res.mjs +50 -0
- package/src/adapter/Runtime/LocalEventCollectorRuntime_Builder.res +47 -0
- package/src/adapter/Runtime/LocalEventCollectorRuntime_Builder.res.mjs +37 -0
- package/src/adapter/Runtime/LocalPluginRuntime_Builder.res +11 -0
- package/src/adapter/Runtime/LocalPluginRuntime_Builder.res.mjs +30 -0
- package/src/adapter/Runtime/LocalRuntimeEnvironment.res +54 -0
- package/src/adapter/Runtime/LocalRuntimeEnvironment.res.mjs +40 -0
- package/src/adapter/Scheduler/LocalScheduledPublisher.res +102 -0
- package/src/adapter/Scheduler/LocalScheduledPublisher.res.mjs +84 -0
- package/src/adapter/SqliteDriver.res +52 -0
- package/src/adapter/SqliteDriver.res.mjs +76 -0
- package/src/adapter/SqliteDriver.resi +31 -0
- package/src/adapter/Task/LocalTaskBucket.res +75 -0
- package/src/adapter/Task/LocalTaskBucket.res.mjs +48 -0
- package/src/adapter/Task/TaskBucket_Sqlite.res +47 -0
- package/src/adapter/Task/TaskBucket_Sqlite.res.mjs +40 -0
- package/src/components/Aggregate_Builder.res +55 -0
- package/src/components/Aggregate_Builder.res.mjs +140 -0
- package/src/components/AutomationSlice_Builder.res +41 -0
- package/src/components/AutomationSlice_Builder.res.mjs +57 -0
- package/src/components/Counter_Builder.res +14 -0
- package/src/components/Counter_Builder.res.mjs +32 -0
- package/src/components/DcbEventLog_Builder.res +18 -0
- package/src/components/DcbEventLog_Builder.res.mjs +24 -0
- package/src/components/ExtensionPoint_Builder.res +25 -0
- package/src/components/ExtensionPoint_Builder.res.mjs +44 -0
- package/src/components/InboundTranslationSlice_Builder.res +34 -0
- package/src/components/InboundTranslationSlice_Builder.res.mjs +45 -0
- package/src/components/OutboundTranslationSlice_Builder.res +43 -0
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +59 -0
- package/src/components/Plugin_Builder.res +37 -0
- package/src/components/Plugin_Builder.res.mjs +67 -0
- package/src/components/ReadModel_Builder.res +47 -0
- package/src/components/ReadModel_Builder.res.mjs +54 -0
- package/src/components/StateChangeSlice_Builder.res +19 -0
- package/src/components/StateChangeSlice_Builder.res.mjs +21 -0
- package/src/components/StateViewSlice_Builder.res +42 -0
- package/src/components/StateViewSlice_Builder.res.mjs +58 -0
- package/src/components/Task_Builder.res +28 -0
- package/src/components/Task_Builder.res.mjs +41 -0
- package/src/reexport/CommandTopic.res +3 -0
- package/src/reexport/CommandTopic.res.mjs +55 -0
- package/src/test/Mocks/MockDcbEventLogStorage.res +136 -0
- package/src/test/Mocks/MockDcbEventLogStorage.res.mjs +146 -0
- package/src/test/Mocks/MockEventLogStorage.res +57 -0
- package/src/test/Mocks/MockEventLogStorage.res.mjs +65 -0
- package/src/test/Mocks/MockPublisher.res +29 -0
- package/src/test/Mocks/MockPublisher.res.mjs +28 -0
- package/src/test/Mocks/MockQueryDbStorage.res +104 -0
- package/src/test/Mocks/MockQueryDbStorage.res.mjs +136 -0
- package/src/test/TestRunner.res +96 -0
- package/src/test/TestRunner.res.mjs +71 -0
- package/tests/SplitApiFixtures.res +84 -0
- package/tests/SplitApiFixtures.res.mjs +88 -0
- package/tests/SplitApiTest.res +102 -0
- package/tests/SplitApiTest.res.mjs +82 -0
- package/tests/TestFixtures.res +54 -0
- package/tests/TestFixtures.res.mjs +65 -0
- package/tests/adapter/BackendParityTest.res +94 -0
- package/tests/adapter/BackendParityTest.res.mjs +96 -0
- package/tests/adapter/CollectNEventsTest.res +82 -0
- package/tests/adapter/CollectNEventsTest.res.mjs +83 -0
- package/tests/adapter/CommandAuthorizationTest.res +200 -0
- package/tests/adapter/CommandAuthorizationTest.res.mjs +190 -0
- package/tests/adapter/CommandTopicChannelTest.res +174 -0
- package/tests/adapter/CommandTopicChannelTest.res.mjs +170 -0
- package/tests/adapter/CounterHandlerTest.res +113 -0
- package/tests/adapter/CounterHandlerTest.res.mjs +96 -0
- package/tests/adapter/DcbEventLogStorageSqliteTest.res +157 -0
- package/tests/adapter/DcbEventLogStorageSqliteTest.res.mjs +165 -0
- package/tests/adapter/DcbEventLogStorageTest.res +187 -0
- package/tests/adapter/DcbEventLogStorageTest.res.mjs +195 -0
- package/tests/adapter/EventCollectorChannelTest.res +166 -0
- package/tests/adapter/EventCollectorChannelTest.res.mjs +178 -0
- package/tests/adapter/EventLogStorageSqliteTest.res +105 -0
- package/tests/adapter/EventLogStorageSqliteTest.res.mjs +116 -0
- package/tests/adapter/EventTapTest.res +102 -0
- package/tests/adapter/EventTapTest.res.mjs +94 -0
- package/tests/adapter/EventTopicPublisherTest.res +76 -0
- package/tests/adapter/EventTopicPublisherTest.res.mjs +86 -0
- package/tests/adapter/GraphQL_SchemaInspectorTest.res +763 -0
- package/tests/adapter/GraphQL_SchemaInspectorTest.res.mjs +578 -0
- package/tests/adapter/GraphQL_SubscriptionResolversTest.res +161 -0
- package/tests/adapter/GraphQL_SubscriptionResolversTest.res.mjs +134 -0
- package/tests/adapter/HeartbeatRunnerTest.res +136 -0
- package/tests/adapter/HeartbeatRunnerTest.res.mjs +96 -0
- package/tests/adapter/LocalAuthHttpTest.res +224 -0
- package/tests/adapter/LocalAuthHttpTest.res.mjs +237 -0
- package/tests/adapter/LocalAuthLoginTest.res +180 -0
- package/tests/adapter/LocalAuthLoginTest.res.mjs +207 -0
- package/tests/adapter/LocalAuthTest.res +106 -0
- package/tests/adapter/LocalAuthTest.res.mjs +145 -0
- package/tests/adapter/LocalAuthUserStoreTest.res +172 -0
- package/tests/adapter/LocalAuthUserStoreTest.res.mjs +208 -0
- package/tests/adapter/LocalBusBoundedTest.res +157 -0
- package/tests/adapter/LocalBusBoundedTest.res.mjs +168 -0
- package/tests/adapter/LocalBusPubSubTest.res +81 -0
- package/tests/adapter/LocalBusPubSubTest.res.mjs +81 -0
- package/tests/adapter/QueryDbGsiTtlTest.res +268 -0
- package/tests/adapter/QueryDbGsiTtlTest.res.mjs +209 -0
- package/tests/adapter/QueryDbListResolverTest.res +361 -0
- package/tests/adapter/QueryDbListResolverTest.res.mjs +426 -0
- package/tests/adapter/QueryDbStorageSqliteTest.res +159 -0
- package/tests/adapter/QueryDbStorageSqliteTest.res.mjs +126 -0
- package/tests/adapter/QueryDbStorageTest.res +171 -0
- package/tests/adapter/QueryDbStorageTest.res.mjs +170 -0
- package/tests/adapter/QueryEngineTest.res +152 -0
- package/tests/adapter/QueryEngineTest.res.mjs +148 -0
- package/tests/adapter/ScheduledPublisherTest.res +199 -0
- package/tests/adapter/ScheduledPublisherTest.res.mjs +203 -0
- package/tests/adapter/SortKey_FilterTest.res +103 -0
- package/tests/adapter/SortKey_FilterTest.res.mjs +135 -0
- package/tests/adapter/SqliteDriverTest.res +86 -0
- package/tests/adapter/SqliteDriverTest.res.mjs +101 -0
- package/tests/adapter/TaskBucketSqliteTest.res +44 -0
- package/tests/adapter/TaskBucketSqliteTest.res.mjs +40 -0
- package/tests/adapter/TaskBucketTest.res +106 -0
- package/tests/adapter/TaskBucketTest.res.mjs +118 -0
- package/tests/components/aggregate/AggregateFixtures.res +78 -0
- package/tests/components/aggregate/AggregateFixtures.res.mjs +109 -0
- package/tests/components/aggregate/AggregateTest.res +129 -0
- package/tests/components/aggregate/AggregateTest.res.mjs +129 -0
- package/tests/components/automationslice/AutomationSliceCallbackTest.res +212 -0
- package/tests/components/automationslice/AutomationSliceCallbackTest.res.mjs +233 -0
- package/tests/components/automationslice/AutomationSliceFixtures.res +189 -0
- package/tests/components/automationslice/AutomationSliceFixtures.res.mjs +276 -0
- package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res +289 -0
- package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res.mjs +453 -0
- package/tests/components/automationslice/AutomationSliceSelfDeadlockTest.res +47 -0
- package/tests/components/automationslice/AutomationSliceSelfDeadlockTest.res.mjs +31 -0
- package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res +213 -0
- package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res.mjs +268 -0
- package/tests/components/automationslice/MixedSourceAutomationSliceTest.res +118 -0
- package/tests/components/automationslice/MixedSourceAutomationSliceTest.res.mjs +99 -0
- package/tests/components/commandgenerator/CommandGeneratorFixtures.res +73 -0
- package/tests/components/commandgenerator/CommandGeneratorFixtures.res.mjs +109 -0
- package/tests/components/commandgenerator/CommandGeneratorTest.res +43 -0
- package/tests/components/commandgenerator/CommandGeneratorTest.res.mjs +46 -0
- package/tests/components/commandtopic/CommandTopicFixtures.res +37 -0
- package/tests/components/commandtopic/CommandTopicFixtures.res.mjs +68 -0
- package/tests/components/commandtopic/CommandTopicStreamFixtures.res +43 -0
- package/tests/components/commandtopic/CommandTopicStreamFixtures.res.mjs +91 -0
- package/tests/components/commandtopic/CommandTopicStreamTest.res +30 -0
- package/tests/components/commandtopic/CommandTopicStreamTest.res.mjs +35 -0
- package/tests/components/commandtopic/CommandTopicTest.res +55 -0
- package/tests/components/commandtopic/CommandTopicTest.res.mjs +62 -0
- package/tests/components/counter/CounterFixtures.res +42 -0
- package/tests/components/counter/CounterFixtures.res.mjs +34 -0
- package/tests/components/counter/CounterTest.res +46 -0
- package/tests/components/counter/CounterTest.res.mjs +61 -0
- package/tests/components/dcb/DcbCrossPartitionFixtures.res +170 -0
- package/tests/components/dcb/DcbCrossPartitionFixtures.res.mjs +276 -0
- package/tests/components/dcb/DcbCrossPartitionReadTest.res +68 -0
- package/tests/components/dcb/DcbCrossPartitionReadTest.res.mjs +78 -0
- package/tests/components/dcb/DcbEventLogAppendStreamTest.res +72 -0
- package/tests/components/dcb/DcbEventLogAppendStreamTest.res.mjs +82 -0
- package/tests/components/dcb/DcbEventLogStreamTest.res +103 -0
- package/tests/components/dcb/DcbEventLogStreamTest.res.mjs +91 -0
- package/tests/components/dcb/DcbFixtures.res +145 -0
- package/tests/components/dcb/DcbFixtures.res.mjs +221 -0
- package/tests/components/dcb/DcbTest.res +55 -0
- package/tests/components/dcb/DcbTest.res.mjs +55 -0
- package/tests/components/eventcollector/EventCollectorFixtures.res +42 -0
- package/tests/components/eventcollector/EventCollectorFixtures.res.mjs +49 -0
- package/tests/components/eventcollector/EventCollectorTest.res +37 -0
- package/tests/components/eventcollector/EventCollectorTest.res.mjs +36 -0
- package/tests/components/eventlog/EventLogAppendStreamTest.res +93 -0
- package/tests/components/eventlog/EventLogAppendStreamTest.res.mjs +113 -0
- package/tests/components/eventlog/EventLogConflictTest.res +86 -0
- package/tests/components/eventlog/EventLogConflictTest.res.mjs +81 -0
- package/tests/components/eventlog/EventLogFixtures.res +52 -0
- package/tests/components/eventlog/EventLogFixtures.res.mjs +80 -0
- package/tests/components/eventlog/EventLogStreamTest.res +98 -0
- package/tests/components/eventlog/EventLogStreamTest.res.mjs +142 -0
- package/tests/components/eventlog/EventLogTest.res +53 -0
- package/tests/components/eventlog/EventLogTest.res.mjs +74 -0
- package/tests/components/eventtopic/EventTopicFixtures.res +47 -0
- package/tests/components/eventtopic/EventTopicFixtures.res.mjs +77 -0
- package/tests/components/eventtopic/EventTopicStreamFixtures.res +27 -0
- package/tests/components/eventtopic/EventTopicStreamFixtures.res.mjs +62 -0
- package/tests/components/eventtopic/EventTopicStreamTest.res +35 -0
- package/tests/components/eventtopic/EventTopicStreamTest.res.mjs +44 -0
- package/tests/components/eventtopic/EventTopicTest.res +35 -0
- package/tests/components/eventtopic/EventTopicTest.res.mjs +43 -0
- package/tests/components/extensionpoint/ExtensionPointFixtures.res +145 -0
- package/tests/components/extensionpoint/ExtensionPointFixtures.res.mjs +188 -0
- package/tests/components/extensionpoint/ExtensionPointTest.res +62 -0
- package/tests/components/extensionpoint/ExtensionPointTest.res.mjs +55 -0
- package/tests/components/heartbeat/HeartbeatFixtures.res +48 -0
- package/tests/components/heartbeat/HeartbeatFixtures.res.mjs +46 -0
- package/tests/components/heartbeat/HeartbeatTest.res +67 -0
- package/tests/components/heartbeat/HeartbeatTest.res.mjs +65 -0
- package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res +241 -0
- package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res.mjs +239 -0
- package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res +36 -0
- package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res.mjs +73 -0
- package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res +191 -0
- package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res.mjs +297 -0
- package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res +78 -0
- package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res.mjs +137 -0
- package/tests/components/querydb/QueryDbFixtures.res +39 -0
- package/tests/components/querydb/QueryDbFixtures.res.mjs +73 -0
- package/tests/components/querydb/QueryDbSubIdFixtures.res +44 -0
- package/tests/components/querydb/QueryDbSubIdFixtures.res.mjs +80 -0
- package/tests/components/querydb/QueryDbSubIdTest.res +104 -0
- package/tests/components/querydb/QueryDbSubIdTest.res.mjs +104 -0
- package/tests/components/querydb/QueryDbTest.res +81 -0
- package/tests/components/querydb/QueryDbTest.res.mjs +126 -0
- package/tests/components/readmodel/DcbReadModelE2EFixtures.res +215 -0
- package/tests/components/readmodel/DcbReadModelE2EFixtures.res.mjs +308 -0
- package/tests/components/readmodel/DcbReadModelE2ETest.res +45 -0
- package/tests/components/readmodel/DcbReadModelE2ETest.res.mjs +37 -0
- package/tests/components/readmodel/DcbReadModelTypoFailFastTest.res +88 -0
- package/tests/components/readmodel/DcbReadModelTypoFailFastTest.res.mjs +152 -0
- package/tests/components/readmodel/MixedSourceReadModelFixtures.res +181 -0
- package/tests/components/readmodel/MixedSourceReadModelFixtures.res.mjs +277 -0
- package/tests/components/readmodel/MixedSourceReadModelTest.res +61 -0
- package/tests/components/readmodel/MixedSourceReadModelTest.res.mjs +68 -0
- package/tests/components/readmodel/ReadModelFixtures.res +138 -0
- package/tests/components/readmodel/ReadModelFixtures.res.mjs +169 -0
- package/tests/components/readmodel/ReadModelTest.res +46 -0
- package/tests/components/readmodel/ReadModelTest.res.mjs +36 -0
- package/tests/components/scheduler/SchedulerFixtures.res +59 -0
- package/tests/components/scheduler/SchedulerFixtures.res.mjs +63 -0
- package/tests/components/scheduler/SchedulerTest.res +76 -0
- package/tests/components/scheduler/SchedulerTest.res.mjs +86 -0
- package/tests/components/sideeffecthandler/SideEffectHandlerFixtures.res +133 -0
- package/tests/components/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +149 -0
- package/tests/components/sideeffecthandler/SideEffectHandlerTest.res +39 -0
- package/tests/components/sideeffecthandler/SideEffectHandlerTest.res.mjs +28 -0
- package/tests/components/stateviewslice/StateViewSliceFixtures.res +117 -0
- package/tests/components/stateviewslice/StateViewSliceFixtures.res.mjs +188 -0
- package/tests/components/stateviewslice/StateViewSliceSubIdFixtures.res +117 -0
- package/tests/components/stateviewslice/StateViewSliceSubIdFixtures.res.mjs +183 -0
- package/tests/components/stateviewslice/StateViewSliceSubIdTest.res +78 -0
- package/tests/components/stateviewslice/StateViewSliceSubIdTest.res.mjs +107 -0
- package/tests/components/stateviewslice/StateViewSliceTest.res +59 -0
- package/tests/components/stateviewslice/StateViewSliceTest.res.mjs +72 -0
- package/tests/components/task/TaskFixtures.res +87 -0
- package/tests/components/task/TaskFixtures.res.mjs +82 -0
- package/tests/components/task/TaskTest.res +98 -0
- package/tests/components/task/TaskTest.res.mjs +46 -0
- package/tests/plugin/PluginBehavior_GWT.res +146 -0
- package/tests/plugin/PluginBehavior_GWT.res.mjs +281 -0
- package/tests/plugin/Plugin_Fixtures.res +61 -0
- package/tests/plugin/Plugin_Fixtures.res.mjs +105 -0
- package/tests/plugin/PluginsProjection_GWT.res +95 -0
- package/tests/plugin/PluginsProjection_GWT.res.mjs +120 -0
- package/tests/plugin/UIFragmentRegistryProjection_GWT.res +72 -0
- package/tests/plugin/UIFragmentRegistryProjection_GWT.res.mjs +117 -0
- package/tests/setup/sqliteGlobal.cjs +12 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Stream from "effect/Stream";
|
|
7
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
8
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
9
|
+
import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
|
|
10
|
+
import * as BackendState$ReventlessLocal from "../BackendState.res.mjs";
|
|
11
|
+
import * as DcbEventLogStorage_Sqlite$ReventlessLocal from "./DcbEventLogStorage_Sqlite.res.mjs";
|
|
12
|
+
|
|
13
|
+
function posToInt(pos) {
|
|
14
|
+
return Stdlib_Option.getOr(Stdlib_Int.fromString(pos, undefined), 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function matchesQuery(event, query) {
|
|
18
|
+
if (query.length === 0) {
|
|
19
|
+
return true;
|
|
20
|
+
} else {
|
|
21
|
+
return query.some(queryItem => {
|
|
22
|
+
let types = queryItem.eventTypes;
|
|
23
|
+
let typeMatch = types !== undefined ? types.includes(event.eventType) : true;
|
|
24
|
+
let tags = queryItem.tags;
|
|
25
|
+
let tagMatch = tags !== undefined ? tags.every(tag => event.tags.some(et => {
|
|
26
|
+
if (et.key === tag.key) {
|
|
27
|
+
return et.value === tag.value;
|
|
28
|
+
} else {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
})) : true;
|
|
32
|
+
if (typeMatch) {
|
|
33
|
+
return tagMatch;
|
|
34
|
+
} else {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function makeStorage(_name, param, param$1, param$2) {
|
|
42
|
+
let events = {
|
|
43
|
+
contents: []
|
|
44
|
+
};
|
|
45
|
+
let position = {
|
|
46
|
+
contents: 0
|
|
47
|
+
};
|
|
48
|
+
let read = async (query, after) => {
|
|
49
|
+
let filtered = events.contents.filter(event => {
|
|
50
|
+
let afterMatch = after !== undefined ? posToInt(event.position) > posToInt(after) : true;
|
|
51
|
+
if (afterMatch) {
|
|
52
|
+
return matchesQuery(event, query);
|
|
53
|
+
} else {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
let headPosition = Stdlib_Option.map(events.contents[events.contents.length - 1 | 0], e => e.position);
|
|
58
|
+
return {
|
|
59
|
+
events: filtered,
|
|
60
|
+
headPosition: headPosition
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
let append = async (newEvents, condition) => {
|
|
64
|
+
let conflictDetected = condition !== undefined ? events.contents.some(event => {
|
|
65
|
+
let pos = condition.after;
|
|
66
|
+
let afterMatch = pos !== undefined ? posToInt(event.position) > posToInt(pos) : true;
|
|
67
|
+
if (afterMatch) {
|
|
68
|
+
return matchesQuery(event, condition.query);
|
|
69
|
+
} else {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}) : false;
|
|
73
|
+
if (conflictDetected) {
|
|
74
|
+
return {
|
|
75
|
+
TAG: "Error",
|
|
76
|
+
_0: "conflict: condition check failed"
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
let storedEvents = newEvents.map(event => {
|
|
80
|
+
position.contents = position.contents + 1 | 0;
|
|
81
|
+
let pos = position.contents.toString();
|
|
82
|
+
return {
|
|
83
|
+
position: pos,
|
|
84
|
+
eventType: event.eventType,
|
|
85
|
+
data: event.data,
|
|
86
|
+
tags: event.tags,
|
|
87
|
+
meta: event.meta,
|
|
88
|
+
recordedAt: Message$ReventlessCore.nowAsISOString()
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
events.contents = events.contents.concat(storedEvents);
|
|
92
|
+
return {
|
|
93
|
+
TAG: "Ok",
|
|
94
|
+
_0: position.contents.toString()
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
let readStream = (query, after, param) => Stream.flatMap(Stream.fromEffect(Effect.map(Effect.promise(() => read(query, after)), result => result.events)), arr => Stream.fromIterable(arr));
|
|
98
|
+
return [
|
|
99
|
+
_name,
|
|
100
|
+
read,
|
|
101
|
+
{
|
|
102
|
+
resources: [],
|
|
103
|
+
operations: Pulumi.output({
|
|
104
|
+
read: read,
|
|
105
|
+
append: append,
|
|
106
|
+
readStream: readStream
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function make(name, indexes, partitionTag, param, opts) {
|
|
113
|
+
return makeStorage(name, indexes, partitionTag, opts)[2];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function Make(Bus) {
|
|
117
|
+
let make = (name, indexes, partitionTag, param, opts) => {
|
|
118
|
+
let db = BackendState$ReventlessLocal.getDb();
|
|
119
|
+
if (db !== undefined) {
|
|
120
|
+
let match = DcbEventLogStorage_Sqlite$ReventlessLocal.makeStorage(Primitive_option.valFromOption(db), (param, param$1) => {}, (param, param$1) => {}, name, indexes, partitionTag, opts);
|
|
121
|
+
Bus.registerDcbEventLogRead(match[0], match[1]);
|
|
122
|
+
return match[2];
|
|
123
|
+
}
|
|
124
|
+
let match$1 = makeStorage(name, indexes, partitionTag, opts);
|
|
125
|
+
Bus.registerDcbEventLogRead(match$1[0], match$1[1]);
|
|
126
|
+
return match$1[2];
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
make: make
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
posToInt,
|
|
135
|
+
matchesQuery,
|
|
136
|
+
makeStorage,
|
|
137
|
+
make,
|
|
138
|
+
Make,
|
|
139
|
+
}
|
|
140
|
+
/* effect/Effect Not a pure module */
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
// SQLite-backed DCB event log storage.
|
|
2
|
+
//
|
|
3
|
+
// Schema:
|
|
4
|
+
// dcb_event(log_name, position INTEGER PRIMARY KEY auto, event_type, data, PRIMARY KEY(log_name,position))
|
|
5
|
+
// dcb_tag (log_name, position, tag_key, tag_value) with index on (log_name, tag_key, tag_value, position)
|
|
6
|
+
//
|
|
7
|
+
// Append:
|
|
8
|
+
// - opens a transaction
|
|
9
|
+
// - if a `condition` was supplied, runs the equivalent of `read(condition.query, after=condition.after)`;
|
|
10
|
+
// any returned event aborts the transaction with `Error("conflict: condition check failed")`
|
|
11
|
+
// - inserts each event under a freshly-allocated `position`
|
|
12
|
+
// - returns the last inserted `position` as a string
|
|
13
|
+
//
|
|
14
|
+
// Read:
|
|
15
|
+
// - applies `after` filter via `position > ?`
|
|
16
|
+
// - applies the OR-of-clauses `query` filter — clauses with both `eventTypes`
|
|
17
|
+
// and `tags` are matched via a tag-join + IN list; tag-only and type-only
|
|
18
|
+
// forms degrade to the simpler shape
|
|
19
|
+
//
|
|
20
|
+
// readStream is materialised eagerly via read for now; streaming via
|
|
21
|
+
// statement.iterate() would require a Stream.fromIteratorEffect that the
|
|
22
|
+
// current ReScript Stream module does not expose.
|
|
23
|
+
|
|
24
|
+
open ReventlessCore
|
|
25
|
+
open Reventless
|
|
26
|
+
|
|
27
|
+
let ensureSchema = (db: SqliteDriver.t) => {
|
|
28
|
+
db->SqliteDriver.exec(
|
|
29
|
+
"CREATE TABLE IF NOT EXISTS dcb_event (log_name TEXT NOT NULL, position INTEGER NOT NULL, event_type TEXT NOT NULL, data TEXT NOT NULL, meta TEXT NOT NULL, recorded_at TEXT NOT NULL, PRIMARY KEY (log_name, position))",
|
|
30
|
+
)
|
|
31
|
+
db->SqliteDriver.exec(
|
|
32
|
+
"CREATE TABLE IF NOT EXISTS dcb_tag (log_name TEXT NOT NULL, position INTEGER NOT NULL, tag_key TEXT NOT NULL, tag_value TEXT NOT NULL)",
|
|
33
|
+
)
|
|
34
|
+
db->SqliteDriver.exec(
|
|
35
|
+
"CREATE INDEX IF NOT EXISTS dcb_tag_by_kv ON dcb_tag(log_name, tag_key, tag_value, position)",
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let posToInt = (pos: string) => pos->Int.fromString->Option.getOr(0)
|
|
40
|
+
|
|
41
|
+
let parseDataPayload = (s: string): JSON.t =>
|
|
42
|
+
switch JSON.parseOrThrow(s) {
|
|
43
|
+
| json => json
|
|
44
|
+
| exception _ => JSON.Encode.null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Total DCB events persisted in this table. Used at startup to seed the
|
|
48
|
+
// event-tap counter so the timeline numbering continues across restarts.
|
|
49
|
+
let countAll = (db: SqliteDriver.t): int => {
|
|
50
|
+
ensureSchema(db)
|
|
51
|
+
switch db->SqliteDriver.prepare("SELECT COUNT(*) AS c FROM dcb_event")->SqliteDriver.get([]) {
|
|
52
|
+
| Some(row) =>
|
|
53
|
+
switch row->Dict.get("c") {
|
|
54
|
+
| Some(JSON.Number(n)) => Float.toInt(n)
|
|
55
|
+
| _ => 0
|
|
56
|
+
}
|
|
57
|
+
| None => 0
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Pull the integer position out of a row column that may be Number or String
|
|
62
|
+
// (node:sqlite returns INTEGER as either, depending on size).
|
|
63
|
+
let coercePosition = (v: JSON.t): int =>
|
|
64
|
+
switch v {
|
|
65
|
+
| JSON.Number(n) => Float.toInt(n)
|
|
66
|
+
| JSON.String(s) => posToInt(s)
|
|
67
|
+
| _ => 0
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// SQL string-literal escape — the queries below build event-type IN lists
|
|
71
|
+
// dynamically and our event types come from compile-time enums (no quotes).
|
|
72
|
+
// The escape is defensive belt-and-braces; never reached in practice.
|
|
73
|
+
let sqlEscape = (s: string) => s->String.replaceAll("'", "''")
|
|
74
|
+
|
|
75
|
+
// Build the WHERE clause and bound params for one query clause.
|
|
76
|
+
// Returns (whereSql, params) where whereSql includes a leading `(`/trailing `)`
|
|
77
|
+
// and uses `dcb_event` table aliases throughout.
|
|
78
|
+
let buildClauseSql = (
|
|
79
|
+
~logName: string,
|
|
80
|
+
~clause: DcbTag.queryItem,
|
|
81
|
+
~after: option<int>,
|
|
82
|
+
): (string, array<JSON.t>) => {
|
|
83
|
+
let parts = ref(["log_name = ?"])
|
|
84
|
+
let params = ref([JSON.Encode.string(logName)])
|
|
85
|
+
|
|
86
|
+
switch after {
|
|
87
|
+
| Some(p) =>
|
|
88
|
+
parts := parts.contents->Array.concat(["position > ?"])
|
|
89
|
+
params := params.contents->Array.concat([JSON.Encode.int(p)])
|
|
90
|
+
| None => ()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
switch clause.eventTypes {
|
|
94
|
+
| Some(types) if types->Array.length > 0 =>
|
|
95
|
+
let placeholders = types->Array.map(_ => "?")->Array.join(",")
|
|
96
|
+
parts := parts.contents->Array.concat([`event_type IN (${placeholders})`])
|
|
97
|
+
types->Array.forEach(t => params := params.contents->Array.concat([JSON.Encode.string(t)]))
|
|
98
|
+
| _ => ()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
switch clause.tags {
|
|
102
|
+
| Some(tags) if tags->Array.length > 0 =>
|
|
103
|
+
// For each tag, require an EXISTS subquery on dcb_tag.
|
|
104
|
+
tags->Array.forEach(tag => {
|
|
105
|
+
let sub = `EXISTS (SELECT 1 FROM dcb_tag t WHERE t.log_name = ? AND t.position = dcb_event.position AND t.tag_key = ? AND t.tag_value = ?)`
|
|
106
|
+
parts := parts.contents->Array.concat([sub])
|
|
107
|
+
params :=
|
|
108
|
+
params.contents->Array.concat([
|
|
109
|
+
JSON.Encode.string(logName),
|
|
110
|
+
JSON.Encode.string(tag.key),
|
|
111
|
+
JSON.Encode.string(tag.value),
|
|
112
|
+
])
|
|
113
|
+
})
|
|
114
|
+
| _ => ()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
("(" ++ parts.contents->Array.join(" AND ") ++ ")", params.contents)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let buildQuerySql = (
|
|
121
|
+
~logName: string,
|
|
122
|
+
~query: DcbTag.query,
|
|
123
|
+
~after: option<int>,
|
|
124
|
+
): (string, array<JSON.t>) => {
|
|
125
|
+
if query->Array.length == 0 {
|
|
126
|
+
let baseWhere = switch after {
|
|
127
|
+
| Some(_) => "log_name = ? AND position > ?"
|
|
128
|
+
| None => "log_name = ?"
|
|
129
|
+
}
|
|
130
|
+
let baseParams = switch after {
|
|
131
|
+
| Some(p) => [JSON.Encode.string(logName), JSON.Encode.int(p)]
|
|
132
|
+
| None => [JSON.Encode.string(logName)]
|
|
133
|
+
}
|
|
134
|
+
let _ = sqlEscape
|
|
135
|
+
(
|
|
136
|
+
`SELECT position, event_type, data, meta, recorded_at FROM dcb_event WHERE ${baseWhere} ORDER BY position ASC`,
|
|
137
|
+
baseParams,
|
|
138
|
+
)
|
|
139
|
+
} else {
|
|
140
|
+
let clauses = query->Array.map(c => buildClauseSql(~logName, ~clause=c, ~after))
|
|
141
|
+
let combinedWhere =
|
|
142
|
+
clauses->Array.map(((sql, _)) => sql)->Array.join(" OR ")
|
|
143
|
+
let combinedParams = clauses->Array.flatMap(((_, p)) => p)
|
|
144
|
+
(
|
|
145
|
+
`SELECT position, event_type, data, meta, recorded_at FROM dcb_event WHERE ${combinedWhere} ORDER BY position ASC`,
|
|
146
|
+
combinedParams,
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let makeStorage = (
|
|
152
|
+
~db: SqliteDriver.t,
|
|
153
|
+
~bus: ('a, JSON.t) => unit,
|
|
154
|
+
~publishToTopic: (~topicName: string, ~json: JSON.t) => unit,
|
|
155
|
+
~name: string,
|
|
156
|
+
~indexes as _,
|
|
157
|
+
~partitionTag as _,
|
|
158
|
+
~opts as _,
|
|
159
|
+
) => {
|
|
160
|
+
ensureSchema(db)
|
|
161
|
+
|
|
162
|
+
let insertEventStmt = db->SqliteDriver.prepare(
|
|
163
|
+
"INSERT INTO dcb_event(log_name, position, event_type, data, meta, recorded_at) VALUES(?,?,?,?,?,?)",
|
|
164
|
+
)
|
|
165
|
+
let insertTagStmt = db->SqliteDriver.prepare(
|
|
166
|
+
"INSERT INTO dcb_tag(log_name, position, tag_key, tag_value) VALUES(?,?,?,?)",
|
|
167
|
+
)
|
|
168
|
+
let maxPositionStmt = db->SqliteDriver.prepare(
|
|
169
|
+
"SELECT COALESCE(MAX(position), 0) AS m FROM dcb_event WHERE log_name = ?",
|
|
170
|
+
)
|
|
171
|
+
let headPositionStmt = db->SqliteDriver.prepare(
|
|
172
|
+
"SELECT MAX(position) AS m FROM dcb_event WHERE log_name = ?",
|
|
173
|
+
)
|
|
174
|
+
let tagsForPositionsStmt = db->SqliteDriver.prepare(
|
|
175
|
+
"SELECT position, tag_key, tag_value FROM dcb_tag WHERE log_name = ? AND position = ?",
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
let _ = bus
|
|
179
|
+
let _ = publishToTopic
|
|
180
|
+
|
|
181
|
+
let currentMaxPosition = (): int =>
|
|
182
|
+
switch maxPositionStmt->SqliteDriver.get([JSON.Encode.string(name)]) {
|
|
183
|
+
| Some(row) =>
|
|
184
|
+
switch row->Dict.get("m") {
|
|
185
|
+
| Some(v) => coercePosition(v)
|
|
186
|
+
| None => 0
|
|
187
|
+
}
|
|
188
|
+
| None => 0
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let tagsForPosition = (pos: int): array<DcbTag.tag> =>
|
|
192
|
+
tagsForPositionsStmt
|
|
193
|
+
->SqliteDriver.all([JSON.Encode.string(name), JSON.Encode.int(pos)])
|
|
194
|
+
->Array.map(row => {
|
|
195
|
+
let key = switch row->Dict.get("tag_key") {
|
|
196
|
+
| Some(JSON.String(s)) => s
|
|
197
|
+
| _ => ""
|
|
198
|
+
}
|
|
199
|
+
let value = switch row->Dict.get("tag_value") {
|
|
200
|
+
| Some(JSON.String(s)) => s
|
|
201
|
+
| _ => ""
|
|
202
|
+
}
|
|
203
|
+
({key, value}: DcbTag.tag)
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
let runQuery = (~query: DcbTag.query, ~after: option<int>): array<DcbEventLog_Adapter.rawSequencedEvent> => {
|
|
207
|
+
let (sql, params) = buildQuerySql(~logName=name, ~query, ~after)
|
|
208
|
+
let stmt = db->SqliteDriver.prepare(sql)
|
|
209
|
+
stmt
|
|
210
|
+
->SqliteDriver.all(params)
|
|
211
|
+
->Array.map(row => {
|
|
212
|
+
let position = switch row->Dict.get("position") {
|
|
213
|
+
| Some(v) => coercePosition(v)
|
|
214
|
+
| None => 0
|
|
215
|
+
}
|
|
216
|
+
let eventType = switch row->Dict.get("event_type") {
|
|
217
|
+
| Some(JSON.String(s)) => s
|
|
218
|
+
| _ => ""
|
|
219
|
+
}
|
|
220
|
+
let data = switch row->Dict.get("data") {
|
|
221
|
+
| Some(JSON.String(s)) => parseDataPayload(s)
|
|
222
|
+
| _ => JSON.Encode.null
|
|
223
|
+
}
|
|
224
|
+
let meta = switch row->Dict.get("meta") {
|
|
225
|
+
| Some(JSON.String(s)) =>
|
|
226
|
+
switch JSON.parseOrThrow(s) {
|
|
227
|
+
| metaJson => metaJson->S.parseJsonOrThrow(Reventless.Message.metaSchema)
|
|
228
|
+
| exception _ => JsError.throwWithMessage("invalid meta JSON in dcb_event row")
|
|
229
|
+
}
|
|
230
|
+
| _ => JsError.throwWithMessage("missing meta column in dcb_event row")
|
|
231
|
+
}
|
|
232
|
+
let recordedAt = switch row->Dict.get("recorded_at") {
|
|
233
|
+
| Some(JSON.String(s)) => s
|
|
234
|
+
| _ => ""
|
|
235
|
+
}
|
|
236
|
+
({
|
|
237
|
+
DcbEventLog_Adapter.position: Int.toString(position),
|
|
238
|
+
eventType,
|
|
239
|
+
data,
|
|
240
|
+
tags: tagsForPosition(position),
|
|
241
|
+
meta,
|
|
242
|
+
recordedAt,
|
|
243
|
+
}: DcbEventLog_Adapter.rawSequencedEvent)
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let read = async (
|
|
248
|
+
~query: DcbTag.query,
|
|
249
|
+
~after=?,
|
|
250
|
+
): DcbEventLog_Adapter.rawReadResult => {
|
|
251
|
+
let afterInt = after->Option.map(posToInt)
|
|
252
|
+
let events = runQuery(~query, ~after=afterInt)
|
|
253
|
+
let head = currentMaxPosition()
|
|
254
|
+
if head > 0 {
|
|
255
|
+
{DcbEventLog_Adapter.events, headPosition: Int.toString(head)}
|
|
256
|
+
} else {
|
|
257
|
+
({DcbEventLog_Adapter.events: events}: DcbEventLog_Adapter.rawReadResult)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let append = async (
|
|
262
|
+
newEvents: array<DcbEventLog_Adapter.rawStoredEvent>,
|
|
263
|
+
~condition=?,
|
|
264
|
+
): result<DcbTag.sequencePosition, string> => {
|
|
265
|
+
let result = ref(Ok(""))
|
|
266
|
+
try {
|
|
267
|
+
db->SqliteDriver.transaction(() => {
|
|
268
|
+
switch condition {
|
|
269
|
+
| Some(cond: DcbTag.appendCondition) =>
|
|
270
|
+
let afterInt = cond.after->Option.map(posToInt)
|
|
271
|
+
let conflicting = runQuery(~query=cond.query, ~after=afterInt)
|
|
272
|
+
if conflicting->Array.length > 0 {
|
|
273
|
+
throw(Failure("conflict: condition check failed"))
|
|
274
|
+
}
|
|
275
|
+
| None => ()
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let mutable_ = ref(currentMaxPosition())
|
|
279
|
+
let lastPos = ref(mutable_.contents)
|
|
280
|
+
newEvents->Array.forEach(event => {
|
|
281
|
+
mutable_ := mutable_.contents + 1
|
|
282
|
+
let pos = mutable_.contents
|
|
283
|
+
let metaJson = event.meta->S.reverseConvertToJsonOrThrow(Reventless.Message.metaSchema)
|
|
284
|
+
let recordedAt = ReventlessCore.Message.nowAsISOString()
|
|
285
|
+
insertEventStmt->SqliteDriver.run([
|
|
286
|
+
JSON.Encode.string(name),
|
|
287
|
+
JSON.Encode.int(pos),
|
|
288
|
+
JSON.Encode.string(event.eventType),
|
|
289
|
+
JSON.Encode.string(JSON.stringify(event.data)),
|
|
290
|
+
JSON.Encode.string(JSON.stringify(metaJson)),
|
|
291
|
+
JSON.Encode.string(recordedAt),
|
|
292
|
+
])
|
|
293
|
+
event.tags->Array.forEach(tag => {
|
|
294
|
+
insertTagStmt->SqliteDriver.run([
|
|
295
|
+
JSON.Encode.string(name),
|
|
296
|
+
JSON.Encode.int(pos),
|
|
297
|
+
JSON.Encode.string(tag.key),
|
|
298
|
+
JSON.Encode.string(tag.value),
|
|
299
|
+
])
|
|
300
|
+
})
|
|
301
|
+
lastPos := pos
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
result := Ok(Int.toString(lastPos.contents))
|
|
305
|
+
})
|
|
306
|
+
result.contents
|
|
307
|
+
} catch {
|
|
308
|
+
| Failure(msg) => Error(msg)
|
|
309
|
+
| _ => Error("conflict")
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let _ = headPositionStmt
|
|
314
|
+
|
|
315
|
+
// ~strongConsistency is a DynamoDB read-replica concept; the SQLite backend is
|
|
316
|
+
// always consistent, so it is accepted (interface parity) and ignored.
|
|
317
|
+
let readStream = (~query: DcbTag.query, ~after=?, ~strongConsistency as _=?) =>
|
|
318
|
+
Effect.promise(() => read(~query, ~after?))
|
|
319
|
+
->Effect.map(result => result.events)
|
|
320
|
+
->Stream.fromEffect
|
|
321
|
+
->Stream.flatMap(arr => Stream.fromIterable(arr))
|
|
322
|
+
|
|
323
|
+
(
|
|
324
|
+
name,
|
|
325
|
+
read,
|
|
326
|
+
{
|
|
327
|
+
DcbEventLog_Adapter.resources: [],
|
|
328
|
+
operations: Pulumi.Output.make({DcbEventLog_Adapter.read, append, readStream}),
|
|
329
|
+
},
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// No `Make(Bus)` functor here on purpose — dispatch is centralised in
|
|
334
|
+
// DcbEventLogStorage_InMemory.Make so callers only ever wire one module.
|