@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,102 @@
|
|
|
1
|
+
// Integration tests for split API mode.
|
|
2
|
+
// Verifies that admin and plugin schemas register into separate server instances
|
|
3
|
+
// with no cross-contamination.
|
|
4
|
+
//
|
|
5
|
+
// Tests the split routing pattern used by Platform.makePlatform(splitApi=true):
|
|
6
|
+
// - Admin schema → GraphQL_ServerInstance (dedicated admin server)
|
|
7
|
+
// - Plugin schema → GraphQL_Server singleton (default plugin server)
|
|
8
|
+
//
|
|
9
|
+
// MCP split is structurally identical (MCP_ServerInstance mirrors
|
|
10
|
+
// GraphQL_ServerInstance) but is not tested here due to Jest ESM
|
|
11
|
+
// compatibility issues with the MCP SDK dependency chain.
|
|
12
|
+
|
|
13
|
+
open JestGlobals
|
|
14
|
+
|
|
15
|
+
// Force side-effect import (creates admin instance + registers schemas)
|
|
16
|
+
let adminGraphQL = SplitApiFixtures.adminGraphQL
|
|
17
|
+
|
|
18
|
+
// Derive field names from schema entries — single source of truth.
|
|
19
|
+
let adminQueryFields = SplitApiFixtures.adminQueryFieldNames
|
|
20
|
+
let adminMutationFields = SplitApiFixtures.adminMutationFieldNames
|
|
21
|
+
|
|
22
|
+
// Plugin field names
|
|
23
|
+
let pluginMutationPrefix = "SplitTestPlugin_SplitTestItem_"
|
|
24
|
+
let pluginQueryPrefix = "SplitTestPlugin_SplitTestItem"
|
|
25
|
+
|
|
26
|
+
describe("Split API Mode — Schema Separation", () => {
|
|
27
|
+
describe("Plugin GraphQL singleton", () => {
|
|
28
|
+
testPromise("contains plugin mutation fields", async () => {
|
|
29
|
+
let d = GraphQL_Server.diagnostics()
|
|
30
|
+
let hasPluginMutation =
|
|
31
|
+
d.registeredMutationFields->Array.some(f => f->String.startsWith(pluginMutationPrefix))
|
|
32
|
+
expect(hasPluginMutation)->toBe(true)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
testPromise("contains plugin query fields", async () => {
|
|
36
|
+
let d = GraphQL_Server.diagnostics()
|
|
37
|
+
let hasPluginQuery =
|
|
38
|
+
d.registeredQueryFields->Array.some(f => f->String.startsWith(pluginQueryPrefix))
|
|
39
|
+
expect(hasPluginQuery)->toBe(true)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
testPromise("does NOT contain admin mutation fields", async () => {
|
|
43
|
+
let d = GraphQL_Server.diagnostics()
|
|
44
|
+
let hasAdminField =
|
|
45
|
+
d.registeredMutationFields->Array.some(f =>
|
|
46
|
+
adminMutationFields->Array.includes(f)
|
|
47
|
+
)
|
|
48
|
+
expect(hasAdminField)->toBe(false)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
testPromise("does NOT contain admin query fields", async () => {
|
|
52
|
+
let d = GraphQL_Server.diagnostics()
|
|
53
|
+
let hasAdminQuery =
|
|
54
|
+
d.registeredQueryFields->Array.some(f =>
|
|
55
|
+
adminQueryFields->Array.includes(f)
|
|
56
|
+
)
|
|
57
|
+
expect(hasAdminQuery)->toBe(false)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe("Admin GraphQL instance", () => {
|
|
62
|
+
testPromise("contains admin mutation fields", async () => {
|
|
63
|
+
let d = adminGraphQL.diagnostics()
|
|
64
|
+
adminMutationFields->Array.forEach(field => {
|
|
65
|
+
let hasField = d.registeredMutationFields->Array.includes(field)
|
|
66
|
+
expect(hasField)->toBe(true)
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
testPromise("contains admin query fields", async () => {
|
|
71
|
+
let d = adminGraphQL.diagnostics()
|
|
72
|
+
adminQueryFields->Array.forEach(field => {
|
|
73
|
+
let hasField = d.registeredQueryFields->Array.includes(field)
|
|
74
|
+
expect(hasField)->toBe(true)
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
testPromise("does NOT contain plugin mutation fields", async () => {
|
|
79
|
+
let d = adminGraphQL.diagnostics()
|
|
80
|
+
let hasPluginMutation =
|
|
81
|
+
d.registeredMutationFields->Array.some(f => f->String.startsWith(pluginMutationPrefix))
|
|
82
|
+
expect(hasPluginMutation)->toBe(false)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
testPromise("does NOT contain plugin query fields", async () => {
|
|
86
|
+
let d = adminGraphQL.diagnostics()
|
|
87
|
+
let hasPluginQuery =
|
|
88
|
+
d.registeredQueryFields->Array.some(f => f->String.startsWith(pluginQueryPrefix))
|
|
89
|
+
expect(hasPluginQuery)->toBe(false)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
testPromise("has admin type definitions registered", async () => {
|
|
93
|
+
let d = adminGraphQL.diagnostics()
|
|
94
|
+
expect(d.typeCount > 0)->toBe(true)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
testPromise("has no SDL mismatches", async () => {
|
|
98
|
+
let d = adminGraphQL.diagnostics()
|
|
99
|
+
expect(d.mismatches->Array.length)->toBe(0)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as GraphQL_Server$ReventlessLocal from "../src/adapter/GraphQL_Server.res.mjs";
|
|
4
|
+
import * as SplitApiFixtures$ReventlessLocal from "./SplitApiFixtures.res.mjs";
|
|
5
|
+
|
|
6
|
+
let pluginMutationPrefix = "SplitTestPlugin_SplitTestItem_";
|
|
7
|
+
|
|
8
|
+
let pluginQueryPrefix = "SplitTestPlugin_SplitTestItem";
|
|
9
|
+
|
|
10
|
+
globalThis.describe("Split API Mode — Schema Separation", () => {
|
|
11
|
+
globalThis.describe("Plugin GraphQL singleton", () => {
|
|
12
|
+
globalThis.test("contains plugin mutation fields", async () => {
|
|
13
|
+
let d = GraphQL_Server$ReventlessLocal.diagnostics();
|
|
14
|
+
let hasPluginMutation = d.registeredMutationFields.some(f => f.startsWith(pluginMutationPrefix));
|
|
15
|
+
globalThis.expect(hasPluginMutation).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
globalThis.test("contains plugin query fields", async () => {
|
|
18
|
+
let d = GraphQL_Server$ReventlessLocal.diagnostics();
|
|
19
|
+
let hasPluginQuery = d.registeredQueryFields.some(f => f.startsWith(pluginQueryPrefix));
|
|
20
|
+
globalThis.expect(hasPluginQuery).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
globalThis.test("does NOT contain admin mutation fields", async () => {
|
|
23
|
+
let d = GraphQL_Server$ReventlessLocal.diagnostics();
|
|
24
|
+
let hasAdminField = d.registeredMutationFields.some(f => SplitApiFixtures$ReventlessLocal.adminMutationFieldNames.includes(f));
|
|
25
|
+
globalThis.expect(hasAdminField).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
globalThis.test("does NOT contain admin query fields", async () => {
|
|
28
|
+
let d = GraphQL_Server$ReventlessLocal.diagnostics();
|
|
29
|
+
let hasAdminQuery = d.registeredQueryFields.some(f => SplitApiFixtures$ReventlessLocal.adminQueryFieldNames.includes(f));
|
|
30
|
+
globalThis.expect(hasAdminQuery).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
globalThis.describe("Admin GraphQL instance", () => {
|
|
34
|
+
globalThis.test("contains admin mutation fields", async () => {
|
|
35
|
+
let d = SplitApiFixtures$ReventlessLocal.adminGraphQL.diagnostics();
|
|
36
|
+
SplitApiFixtures$ReventlessLocal.adminMutationFieldNames.forEach(field => {
|
|
37
|
+
let hasField = d.registeredMutationFields.includes(field);
|
|
38
|
+
globalThis.expect(hasField).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
globalThis.test("contains admin query fields", async () => {
|
|
42
|
+
let d = SplitApiFixtures$ReventlessLocal.adminGraphQL.diagnostics();
|
|
43
|
+
SplitApiFixtures$ReventlessLocal.adminQueryFieldNames.forEach(field => {
|
|
44
|
+
let hasField = d.registeredQueryFields.includes(field);
|
|
45
|
+
globalThis.expect(hasField).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
globalThis.test("does NOT contain plugin mutation fields", async () => {
|
|
49
|
+
let d = SplitApiFixtures$ReventlessLocal.adminGraphQL.diagnostics();
|
|
50
|
+
let hasPluginMutation = d.registeredMutationFields.some(f => f.startsWith(pluginMutationPrefix));
|
|
51
|
+
globalThis.expect(hasPluginMutation).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
globalThis.test("does NOT contain plugin query fields", async () => {
|
|
54
|
+
let d = SplitApiFixtures$ReventlessLocal.adminGraphQL.diagnostics();
|
|
55
|
+
let hasPluginQuery = d.registeredQueryFields.some(f => f.startsWith(pluginQueryPrefix));
|
|
56
|
+
globalThis.expect(hasPluginQuery).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
globalThis.test("has admin type definitions registered", async () => {
|
|
59
|
+
let d = SplitApiFixtures$ReventlessLocal.adminGraphQL.diagnostics();
|
|
60
|
+
globalThis.expect(d.typeCount > 0).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
globalThis.test("has no SDL mismatches", async () => {
|
|
63
|
+
let d = SplitApiFixtures$ReventlessLocal.adminGraphQL.diagnostics();
|
|
64
|
+
globalThis.expect(d.mismatches.length).toBe(0);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
let adminGraphQL = SplitApiFixtures$ReventlessLocal.adminGraphQL;
|
|
70
|
+
|
|
71
|
+
let adminQueryFields = SplitApiFixtures$ReventlessLocal.adminQueryFieldNames;
|
|
72
|
+
|
|
73
|
+
let adminMutationFields = SplitApiFixtures$ReventlessLocal.adminMutationFieldNames;
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
adminGraphQL,
|
|
77
|
+
adminQueryFields,
|
|
78
|
+
adminMutationFields,
|
|
79
|
+
pluginMutationPrefix,
|
|
80
|
+
pluginQueryPrefix,
|
|
81
|
+
}
|
|
82
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Shared test infrastructure for all component integration tests.
|
|
2
|
+
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
// Test metadata
|
|
5
|
+
// ─────────────────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
let testMeta: Reventless.Message.meta = {
|
|
8
|
+
service: "test",
|
|
9
|
+
time: "2024-01-01T00:00:00.000Z",
|
|
10
|
+
ip: "127.0.0.1",
|
|
11
|
+
user: "testuser",
|
|
12
|
+
msgId: "msg-001",
|
|
13
|
+
correlationId: "corr-001",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// For tests where meta.service must match a specific source name for routing.
|
|
17
|
+
let makeTestMeta = (~service): Reventless.Message.meta => {...testMeta, service}
|
|
18
|
+
|
|
19
|
+
// ─────────────────────────────────────────────────────────────
|
|
20
|
+
// Mock infrastructure
|
|
21
|
+
// ─────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
let mockQueryEngine: Reventless.QueryEngine.operations = {
|
|
24
|
+
scan: async (~readModelName as _, ~filterConfigs as _, ~limit as _) => [],
|
|
25
|
+
query: async (
|
|
26
|
+
~readModelName as _,
|
|
27
|
+
~key as _=?,
|
|
28
|
+
~id as _,
|
|
29
|
+
~subIdConfig as _=?,
|
|
30
|
+
~filterConfigs as _=?,
|
|
31
|
+
~ascending as _=?,
|
|
32
|
+
~limit as _=?,
|
|
33
|
+
) => [],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let mockScheduler: ReventlessInfra.Scheduler.operations = {
|
|
37
|
+
createSchedule: async (_, _) => (),
|
|
38
|
+
deleteSchedule: async (_, _) => (),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let mockResourceNaming: ReventlessInfra.ResourceNaming.operations = {
|
|
42
|
+
validateName: n => n,
|
|
43
|
+
urnName: n => n,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─────────────────────────────────────────────────────────────
|
|
47
|
+
// Jest fake timer bindings
|
|
48
|
+
// ─────────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
type jestObj
|
|
51
|
+
@module("@jest/globals") external jest: jestObj = "jest"
|
|
52
|
+
@send external useFakeTimers: jestObj => unit = "useFakeTimers"
|
|
53
|
+
@send external useRealTimers: jestObj => unit = "useRealTimers"
|
|
54
|
+
@send external advanceTimersByTime: (jestObj, int) => unit = "advanceTimersByTime"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let testMeta = {
|
|
5
|
+
service: "test",
|
|
6
|
+
time: "2024-01-01T00:00:00.000Z",
|
|
7
|
+
ip: "127.0.0.1",
|
|
8
|
+
user: "testuser",
|
|
9
|
+
msgId: "msg-001",
|
|
10
|
+
correlationId: "corr-001"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function makeTestMeta(service) {
|
|
14
|
+
let newrecord = {...testMeta};
|
|
15
|
+
newrecord.service = service;
|
|
16
|
+
return newrecord;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function mockQueryEngine_scan(param, param$1, param$2) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function mockQueryEngine_query(param, param$1, param$2, param$3, param$4, param$5, param$6) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let mockQueryEngine = {
|
|
28
|
+
scan: mockQueryEngine_scan,
|
|
29
|
+
query: mockQueryEngine_query
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
async function mockScheduler_createSchedule(param, param$1) {
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function mockScheduler_deleteSchedule(param, param$1) {
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let mockScheduler = {
|
|
41
|
+
createSchedule: mockScheduler_createSchedule,
|
|
42
|
+
deleteSchedule: mockScheduler_deleteSchedule
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function mockResourceNaming_validateName(n) {
|
|
46
|
+
return n;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function mockResourceNaming_urnName(n) {
|
|
50
|
+
return n;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let mockResourceNaming = {
|
|
54
|
+
validateName: mockResourceNaming_validateName,
|
|
55
|
+
urnName: mockResourceNaming_urnName
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
testMeta,
|
|
60
|
+
makeTestMeta,
|
|
61
|
+
mockQueryEngine,
|
|
62
|
+
mockScheduler,
|
|
63
|
+
mockResourceNaming,
|
|
64
|
+
}
|
|
65
|
+
/* No side effect */
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Behavioural parity between Memory and Sqlite backends at the adapter layer.
|
|
2
|
+
// Each test runs the same scenario against both BackendState settings.
|
|
3
|
+
|
|
4
|
+
open JestGlobals
|
|
5
|
+
|
|
6
|
+
let _ = TestRunner.setup()
|
|
7
|
+
let opts: Pulumi.CustomResourceOptions.t = {}
|
|
8
|
+
|
|
9
|
+
let runUnderMemory = async fn => {
|
|
10
|
+
BackendState.setMemory()
|
|
11
|
+
await fn()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let runUnderSqlite = async fn => {
|
|
15
|
+
let db = SqliteDriver.openDb(~path=":memory:")
|
|
16
|
+
BackendState.setSqlite(~db, ~path=":memory:")
|
|
17
|
+
await fn()
|
|
18
|
+
BackendState.setMemory()
|
|
19
|
+
db->SqliteDriver.close
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("Backend parity (Memory vs Sqlite)", () => {
|
|
23
|
+
testPromise("EventLog: append + replay returns the same events under both", async () => {
|
|
24
|
+
let scenario = async () => {
|
|
25
|
+
module TestBus = LocalBus.Make()
|
|
26
|
+
module Storage = EventLogStorage_InMemory.Make(TestBus)
|
|
27
|
+
let s = Storage.make(~name="parity-events", ~opts)
|
|
28
|
+
let ops = await s.operations->TestRunner.resolve
|
|
29
|
+
|
|
30
|
+
let e1 = JSON.Encode.object(Dict.fromArray([("t", JSON.Encode.string("A"))]))
|
|
31
|
+
let e2 = JSON.Encode.object(Dict.fromArray([("t", JSON.Encode.string("B"))]))
|
|
32
|
+
|
|
33
|
+
let _ = await ops.append(0, "id-x", [e1])
|
|
34
|
+
let _ = await ops.append(1, "id-x", [e2])
|
|
35
|
+
|
|
36
|
+
let replayed = await ops.replay("id-x")
|
|
37
|
+
expect(replayed->Array.length)->toBe(2)
|
|
38
|
+
expect(replayed->Array.getUnsafe(0))->toEqual(e1)
|
|
39
|
+
expect(replayed->Array.getUnsafe(1))->toEqual(e2)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await runUnderMemory(scenario)
|
|
43
|
+
await runUnderSqlite(scenario)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
testPromise("QueryDb: save + loadStream returns the same item under both", async () => {
|
|
47
|
+
let scenario = async () => {
|
|
48
|
+
module TestBus = LocalBus.Make()
|
|
49
|
+
module Storage = QueryDbStorage_InMemory.Make(TestBus)
|
|
50
|
+
let s = Storage.make(~name="parity-qdb", ~indexes=[], ~api=(), ~apiRole=(), ~opts)
|
|
51
|
+
let ops = await s.operations->TestRunner.resolve
|
|
52
|
+
|
|
53
|
+
let _ = await ops.save(
|
|
54
|
+
"k",
|
|
55
|
+
JSON.Encode.string("val"),
|
|
56
|
+
ReventlessCore.QueryDb.Any,
|
|
57
|
+
None,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
let items =
|
|
61
|
+
await ops.loadStream("k")
|
|
62
|
+
->Stream.runCollect
|
|
63
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
64
|
+
->Effect.runPromise
|
|
65
|
+
expect(items->Array.length)->toBe(1)
|
|
66
|
+
expect(items->Array.getUnsafe(0))->toEqual(JSON.Encode.string("val"))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await runUnderMemory(scenario)
|
|
70
|
+
await runUnderSqlite(scenario)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
testPromise("EventLog: conflict detection works under both", async () => {
|
|
74
|
+
let scenario = async () => {
|
|
75
|
+
module TestBus = LocalBus.Make()
|
|
76
|
+
module Storage = EventLogStorage_InMemory.Make(TestBus)
|
|
77
|
+
let s = Storage.make(~name="parity-conflict", ~opts)
|
|
78
|
+
let ops = await s.operations->TestRunner.resolve
|
|
79
|
+
|
|
80
|
+
let e = JSON.Encode.object(Dict.fromArray([("t", JSON.Encode.string("C"))]))
|
|
81
|
+
let _ = await ops.append(0, "cid", [e])
|
|
82
|
+
|
|
83
|
+
// Reusing seqNr=0 must conflict under both backends.
|
|
84
|
+
let result = await ops.append(0, "cid", [e])
|
|
85
|
+
switch result {
|
|
86
|
+
| Error(_) => expect(true)->toBe(true)
|
|
87
|
+
| Ok() => expect("expected conflict")->toBe("actual Ok")
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await runUnderMemory(scenario)
|
|
92
|
+
await runUnderSqlite(scenario)
|
|
93
|
+
})
|
|
94
|
+
})
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stream from "@reventlessdev/rescript-effect/src/Stream.res.mjs";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as LocalBus$ReventlessLocal from "../../src/adapter/LocalBus.res.mjs";
|
|
6
|
+
import * as TestRunner$ReventlessLocal from "../../src/test/TestRunner.res.mjs";
|
|
7
|
+
import * as BackendState$ReventlessLocal from "../../src/adapter/BackendState.res.mjs";
|
|
8
|
+
import * as SqliteDriver$ReventlessLocal from "../../src/adapter/SqliteDriver.res.mjs";
|
|
9
|
+
import * as QueryDbStorage_InMemory$ReventlessLocal from "../../src/adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
|
|
10
|
+
import * as EventLogStorage_InMemory$ReventlessLocal from "../../src/adapter/EventLog/EventLogStorage_InMemory.res.mjs";
|
|
11
|
+
|
|
12
|
+
TestRunner$ReventlessLocal.setup();
|
|
13
|
+
|
|
14
|
+
let opts = {};
|
|
15
|
+
|
|
16
|
+
async function runUnderMemory(fn) {
|
|
17
|
+
BackendState$ReventlessLocal.setMemory();
|
|
18
|
+
return await fn();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function runUnderSqlite(fn) {
|
|
22
|
+
let db = SqliteDriver$ReventlessLocal.openDb(":memory:");
|
|
23
|
+
BackendState$ReventlessLocal.setSqlite(db, ":memory:");
|
|
24
|
+
await fn();
|
|
25
|
+
BackendState$ReventlessLocal.setMemory();
|
|
26
|
+
return SqliteDriver$ReventlessLocal.close(db);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
|
|
30
|
+
globalThis.test("EventLog: append + replay returns the same events under both", async () => {
|
|
31
|
+
let scenario = async () => {
|
|
32
|
+
let TestBus = LocalBus$ReventlessLocal.Make({});
|
|
33
|
+
let Storage = EventLogStorage_InMemory$ReventlessLocal.Make(TestBus);
|
|
34
|
+
let s = Storage.make("parity-events", opts);
|
|
35
|
+
let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
|
|
36
|
+
let e1 = Object.fromEntries([[
|
|
37
|
+
"t",
|
|
38
|
+
"A"
|
|
39
|
+
]]);
|
|
40
|
+
let e2 = Object.fromEntries([[
|
|
41
|
+
"t",
|
|
42
|
+
"B"
|
|
43
|
+
]]);
|
|
44
|
+
await ops.append(0, "id-x", [e1]);
|
|
45
|
+
await ops.append(1, "id-x", [e2]);
|
|
46
|
+
let replayed = await ops.replay("id-x");
|
|
47
|
+
globalThis.expect(replayed.length).toBe(2);
|
|
48
|
+
globalThis.expect(replayed[0]).toEqual(e1);
|
|
49
|
+
globalThis.expect(replayed[1]).toEqual(e2);
|
|
50
|
+
};
|
|
51
|
+
await runUnderMemory(scenario);
|
|
52
|
+
return await runUnderSqlite(scenario);
|
|
53
|
+
});
|
|
54
|
+
globalThis.test("QueryDb: save + loadStream returns the same item under both", async () => {
|
|
55
|
+
let scenario = async () => {
|
|
56
|
+
let TestBus = LocalBus$ReventlessLocal.Make({});
|
|
57
|
+
let Storage = QueryDbStorage_InMemory$ReventlessLocal.Make(TestBus);
|
|
58
|
+
let s = Storage.make("parity-qdb", [], undefined, undefined, undefined, undefined, opts);
|
|
59
|
+
let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
|
|
60
|
+
await ops.save("k", "val", "Any", undefined);
|
|
61
|
+
let items = await Effect.runPromise(Effect.catchAll(Stream.runCollect(ops.loadStream("k")), param => Effect.succeed([])));
|
|
62
|
+
globalThis.expect(items.length).toBe(1);
|
|
63
|
+
globalThis.expect(items[0]).toEqual("val");
|
|
64
|
+
};
|
|
65
|
+
await runUnderMemory(scenario);
|
|
66
|
+
return await runUnderSqlite(scenario);
|
|
67
|
+
});
|
|
68
|
+
globalThis.test("EventLog: conflict detection works under both", async () => {
|
|
69
|
+
let scenario = async () => {
|
|
70
|
+
let TestBus = LocalBus$ReventlessLocal.Make({});
|
|
71
|
+
let Storage = EventLogStorage_InMemory$ReventlessLocal.Make(TestBus);
|
|
72
|
+
let s = Storage.make("parity-conflict", opts);
|
|
73
|
+
let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
|
|
74
|
+
let e = Object.fromEntries([[
|
|
75
|
+
"t",
|
|
76
|
+
"C"
|
|
77
|
+
]]);
|
|
78
|
+
await ops.append(0, "cid", [e]);
|
|
79
|
+
let result = await ops.append(0, "cid", [e]);
|
|
80
|
+
if (result.TAG === "Ok") {
|
|
81
|
+
globalThis.expect("expected conflict").toBe("actual Ok");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
globalThis.expect(true).toBe(true);
|
|
85
|
+
};
|
|
86
|
+
await runUnderMemory(scenario);
|
|
87
|
+
return await runUnderSqlite(scenario);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
opts,
|
|
93
|
+
runUnderMemory,
|
|
94
|
+
runUnderSqlite,
|
|
95
|
+
}
|
|
96
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Tests for TestRunner.collectNEvents utility (Phase J of stream-handler-implementation plan).
|
|
2
|
+
|
|
3
|
+
open JestGlobals
|
|
4
|
+
|
|
5
|
+
let _ = TestRunner.setup()
|
|
6
|
+
|
|
7
|
+
let meta: Reventless.Message.meta = {
|
|
8
|
+
service: "svc",
|
|
9
|
+
time: "",
|
|
10
|
+
ip: "",
|
|
11
|
+
user: "u",
|
|
12
|
+
msgId: "",
|
|
13
|
+
correlationId: "",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("TestRunner.collectNEvents", () => {
|
|
17
|
+
testPromise("resolves after exactly n events", async () => {
|
|
18
|
+
module Bus = LocalBus.Make()
|
|
19
|
+
let collecting = TestRunner.collectNEvents(Bus.subscribeToEvents, "T", 3)
|
|
20
|
+
let json = JSON.parseOrThrow("{}")
|
|
21
|
+
await Bus.publishEvent("T", "svc", meta, json)
|
|
22
|
+
await Bus.publishEvent("T", "svc", meta, json)
|
|
23
|
+
await Bus.publishEvent("T", "svc", meta, json)
|
|
24
|
+
let events = await collecting
|
|
25
|
+
expect(events->Array.length)->toBe(3)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
testPromise("captures service, meta, and json from each event", async () => {
|
|
29
|
+
module Bus = LocalBus.Make()
|
|
30
|
+
let collecting = TestRunner.collectNEvents(Bus.subscribeToEvents, "T", 2)
|
|
31
|
+
let j1 = JSON.parseOrThrow(`{"id":1}`)
|
|
32
|
+
let j2 = JSON.parseOrThrow(`{"id":2}`)
|
|
33
|
+
await Bus.publishEvent("T", "svc", meta, j1)
|
|
34
|
+
await Bus.publishEvent("T", "svc", meta, j2)
|
|
35
|
+
let events = await collecting
|
|
36
|
+
let e0 = events->Array.getUnsafe(0)
|
|
37
|
+
let e1 = events->Array.getUnsafe(1)
|
|
38
|
+
expect(e0.json)->toEqual(j1)
|
|
39
|
+
expect(e1.json)->toEqual(j2)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
testPromise("resolves immediately for n = 0", async () => {
|
|
43
|
+
module Bus = LocalBus.Make()
|
|
44
|
+
let events = await TestRunner.collectNEvents(Bus.subscribeToEvents, "T", 0)
|
|
45
|
+
expect(events->Array.length)->toBe(0)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
testPromise("does not resolve before n events arrive", async () => {
|
|
49
|
+
module Bus = LocalBus.Make()
|
|
50
|
+
let collecting = TestRunner.collectNEvents(Bus.subscribeToEvents, "T", 3)
|
|
51
|
+
let json = JSON.parseOrThrow("{}")
|
|
52
|
+
let resolved = ref(false)
|
|
53
|
+
let _ = collecting->Promise.then(events => {
|
|
54
|
+
resolved := true
|
|
55
|
+
Promise.resolve(events)
|
|
56
|
+
})
|
|
57
|
+
await Bus.publishEvent("T", "svc", meta, json)
|
|
58
|
+
await Bus.publishEvent("T", "svc", meta, json)
|
|
59
|
+
// Only 2 events so far — promise should not yet be resolved.
|
|
60
|
+
// One extra tick to let any spurious resolution propagate.
|
|
61
|
+
let _ = await Promise.resolve()
|
|
62
|
+
expect(resolved.contents)->toBe(false)
|
|
63
|
+
// Third event resolves it.
|
|
64
|
+
await Bus.publishEvent("T", "svc", meta, json)
|
|
65
|
+
let _ = await collecting
|
|
66
|
+
expect(resolved.contents)->toBe(true)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
testPromise("works with multiple independent topics", async () => {
|
|
70
|
+
module Bus = LocalBus.Make()
|
|
71
|
+
let collectingA = TestRunner.collectNEvents(Bus.subscribeToEvents, "A", 1)
|
|
72
|
+
let collectingB = TestRunner.collectNEvents(Bus.subscribeToEvents, "B", 2)
|
|
73
|
+
let json = JSON.parseOrThrow("{}")
|
|
74
|
+
await Bus.publishEvent("A", "svc", meta, json)
|
|
75
|
+
await Bus.publishEvent("B", "svc", meta, json)
|
|
76
|
+
await Bus.publishEvent("B", "svc", meta, json)
|
|
77
|
+
let eventsA = await collectingA
|
|
78
|
+
let eventsB = await collectingB
|
|
79
|
+
expect(eventsA->Array.length)->toBe(1)
|
|
80
|
+
expect(eventsB->Array.length)->toBe(2)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as LocalBus$ReventlessLocal from "../../src/adapter/LocalBus.res.mjs";
|
|
4
|
+
import * as TestRunner$ReventlessLocal from "../../src/test/TestRunner.res.mjs";
|
|
5
|
+
|
|
6
|
+
TestRunner$ReventlessLocal.setup();
|
|
7
|
+
|
|
8
|
+
let meta = {
|
|
9
|
+
service: "svc",
|
|
10
|
+
time: "",
|
|
11
|
+
ip: "",
|
|
12
|
+
user: "u",
|
|
13
|
+
msgId: "",
|
|
14
|
+
correlationId: ""
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
globalThis.describe("TestRunner.collectNEvents", () => {
|
|
18
|
+
globalThis.test("resolves after exactly n events", async () => {
|
|
19
|
+
let Bus = LocalBus$ReventlessLocal.Make({});
|
|
20
|
+
let collecting = TestRunner$ReventlessLocal.collectNEvents(Bus.subscribeToEvents, "T", 3);
|
|
21
|
+
let json = JSON.parse("{}");
|
|
22
|
+
await Bus.publishEvent("T", "svc", meta, json);
|
|
23
|
+
await Bus.publishEvent("T", "svc", meta, json);
|
|
24
|
+
await Bus.publishEvent("T", "svc", meta, json);
|
|
25
|
+
let events = await collecting;
|
|
26
|
+
globalThis.expect(events.length).toBe(3);
|
|
27
|
+
});
|
|
28
|
+
globalThis.test("captures service, meta, and json from each event", async () => {
|
|
29
|
+
let Bus = LocalBus$ReventlessLocal.Make({});
|
|
30
|
+
let collecting = TestRunner$ReventlessLocal.collectNEvents(Bus.subscribeToEvents, "T", 2);
|
|
31
|
+
let j1 = JSON.parse(`{"id":1}`);
|
|
32
|
+
let j2 = JSON.parse(`{"id":2}`);
|
|
33
|
+
await Bus.publishEvent("T", "svc", meta, j1);
|
|
34
|
+
await Bus.publishEvent("T", "svc", meta, j2);
|
|
35
|
+
let events = await collecting;
|
|
36
|
+
let e0 = events[0];
|
|
37
|
+
let e1 = events[1];
|
|
38
|
+
globalThis.expect(e0.json).toEqual(j1);
|
|
39
|
+
globalThis.expect(e1.json).toEqual(j2);
|
|
40
|
+
});
|
|
41
|
+
globalThis.test("resolves immediately for n = 0", async () => {
|
|
42
|
+
let Bus = LocalBus$ReventlessLocal.Make({});
|
|
43
|
+
let events = await TestRunner$ReventlessLocal.collectNEvents(Bus.subscribeToEvents, "T", 0);
|
|
44
|
+
globalThis.expect(events.length).toBe(0);
|
|
45
|
+
});
|
|
46
|
+
globalThis.test("does not resolve before n events arrive", async () => {
|
|
47
|
+
let Bus = LocalBus$ReventlessLocal.Make({});
|
|
48
|
+
let collecting = TestRunner$ReventlessLocal.collectNEvents(Bus.subscribeToEvents, "T", 3);
|
|
49
|
+
let json = JSON.parse("{}");
|
|
50
|
+
let resolved = {
|
|
51
|
+
contents: false
|
|
52
|
+
};
|
|
53
|
+
collecting.then(events => {
|
|
54
|
+
resolved.contents = true;
|
|
55
|
+
return Promise.resolve(events);
|
|
56
|
+
});
|
|
57
|
+
await Bus.publishEvent("T", "svc", meta, json);
|
|
58
|
+
await Bus.publishEvent("T", "svc", meta, json);
|
|
59
|
+
await Promise.resolve();
|
|
60
|
+
globalThis.expect(resolved.contents).toBe(false);
|
|
61
|
+
await Bus.publishEvent("T", "svc", meta, json);
|
|
62
|
+
await collecting;
|
|
63
|
+
globalThis.expect(resolved.contents).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
globalThis.test("works with multiple independent topics", async () => {
|
|
66
|
+
let Bus = LocalBus$ReventlessLocal.Make({});
|
|
67
|
+
let collectingA = TestRunner$ReventlessLocal.collectNEvents(Bus.subscribeToEvents, "A", 1);
|
|
68
|
+
let collectingB = TestRunner$ReventlessLocal.collectNEvents(Bus.subscribeToEvents, "B", 2);
|
|
69
|
+
let json = JSON.parse("{}");
|
|
70
|
+
await Bus.publishEvent("A", "svc", meta, json);
|
|
71
|
+
await Bus.publishEvent("B", "svc", meta, json);
|
|
72
|
+
await Bus.publishEvent("B", "svc", meta, json);
|
|
73
|
+
let eventsA = await collectingA;
|
|
74
|
+
let eventsB = await collectingB;
|
|
75
|
+
globalThis.expect(eventsA.length).toBe(1);
|
|
76
|
+
globalThis.expect(eventsB.length).toBe(2);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
meta,
|
|
82
|
+
}
|
|
83
|
+
/* Not a pure module */
|