@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,76 @@
|
|
|
1
|
+
// GraphQL mutation resolvers for in-memory InboundTranslationSlices.
|
|
2
|
+
// Registers one GraphQL mutation field per InboundTranslationSlice.
|
|
3
|
+
// Each resolver calls `receive(argsJson)` directly — the InboundTranslationSlice
|
|
4
|
+
// handles parsing, validation, translation, and command publishing internally.
|
|
5
|
+
|
|
6
|
+
@@warning("-44")
|
|
7
|
+
open ReventlessCore
|
|
8
|
+
|
|
9
|
+
// Mutable registry: fieldName → receive function.
|
|
10
|
+
// Pre-populated synchronously in Phase 1 via a queuing forwarder so callers
|
|
11
|
+
// (e.g. PlatformInspector's onPlatformDeployedHook) can invoke receive before
|
|
12
|
+
// Phase 2 bindReceive runs. Calls park in a Promise queue and drain once bound.
|
|
13
|
+
let receiveRegistry: dict<JSON.t => promise<result<array<string>, string>>> = Dict.make()
|
|
14
|
+
|
|
15
|
+
type pendingCall = {
|
|
16
|
+
inputJson: JSON.t,
|
|
17
|
+
resolve: result<array<string>, string> => unit,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Per-field pending-call queues — drained when bindReceive fires.
|
|
21
|
+
let pendingQueueRegistry: dict<ref<array<pendingCall>>> = Dict.make()
|
|
22
|
+
|
|
23
|
+
// Phase 1: Register SDL + resolver stub synchronously (before server starts).
|
|
24
|
+
// Also pre-registers a queuing forwarder in receiveRegistry so callers can
|
|
25
|
+
// invoke receive immediately; calls are parked until bindReceive drains them.
|
|
26
|
+
let register = (~fieldName: string, ~externalInputSchema: S.t<unknown>, ~server: GraphQL_ServerInstance.t) => {
|
|
27
|
+
let sdlFields = switch GraphQL_FragmentGenerator.deriveMutationFieldFromObject(
|
|
28
|
+
~fieldName,
|
|
29
|
+
~collectedTypes=[],
|
|
30
|
+
~seenTypes=Set.make(),
|
|
31
|
+
externalInputSchema,
|
|
32
|
+
) {
|
|
33
|
+
| Some(field) => [field]
|
|
34
|
+
| None => [` ${fieldName}: String!`]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Queue of pending calls when receive is not yet bound.
|
|
38
|
+
let pendingQueue: ref<array<pendingCall>> = ref([])
|
|
39
|
+
pendingQueueRegistry->Dict.set(fieldName, pendingQueue)
|
|
40
|
+
|
|
41
|
+
// Queuing forwarder: parks calls until bindReceive populates receiveRegistry.
|
|
42
|
+
let queuingReceive = (inputJson: JSON.t) =>
|
|
43
|
+
Promise.make((resolve, _reject) => {
|
|
44
|
+
pendingQueue.contents->Array.push({inputJson, resolve})
|
|
45
|
+
})
|
|
46
|
+
receiveRegistry->Dict.set(fieldName, queuingReceive)
|
|
47
|
+
|
|
48
|
+
let resolver: GraphQL_ServerInstance.resolverFn = async (_root, args, _ctx) => {
|
|
49
|
+
let inputJson: JSON.t = args->Obj.magic
|
|
50
|
+
let receive = receiveRegistry->Dict.getUnsafe(fieldName)
|
|
51
|
+
let result = await receive(inputJson)
|
|
52
|
+
switch result {
|
|
53
|
+
| Ok(targetIds) => targetIds->Array.map(JSON.Encode.string)->JSON.Encode.array
|
|
54
|
+
| Error(msg) => msg->JSON.Encode.string
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let resolvers = Dict.make()
|
|
59
|
+
resolvers->Dict.set(fieldName, resolver)
|
|
60
|
+
server.registerMutations(~sdlFields, ~resolvers)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Phase 2: Bind the real receive function once Output.apply resolves.
|
|
64
|
+
// Replaces the queuing forwarder in receiveRegistry and drains pending calls.
|
|
65
|
+
let bindReceive = (~fieldName: string, ~receive: JSON.t => promise<result<array<string>, string>>) => {
|
|
66
|
+
receiveRegistry->Dict.set(fieldName, receive)
|
|
67
|
+
switch pendingQueueRegistry->Dict.get(fieldName) {
|
|
68
|
+
| Some(pendingQueue) =>
|
|
69
|
+
let pending = pendingQueue.contents
|
|
70
|
+
pendingQueue.contents = []
|
|
71
|
+
pending->Array.forEach(({inputJson, resolve}) => {
|
|
72
|
+
let _ = receive(inputJson)->Promise.thenResolve(result => resolve(result))
|
|
73
|
+
})
|
|
74
|
+
| None => ()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as GraphQL_FragmentGenerator$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/GraphQL_FragmentGenerator.res.mjs";
|
|
4
|
+
|
|
5
|
+
let receiveRegistry = {};
|
|
6
|
+
|
|
7
|
+
let pendingQueueRegistry = {};
|
|
8
|
+
|
|
9
|
+
function register(fieldName, externalInputSchema, server) {
|
|
10
|
+
let field = GraphQL_FragmentGenerator$ReventlessCore.deriveMutationFieldFromObject(fieldName, [], new Set(), externalInputSchema);
|
|
11
|
+
let sdlFields = field !== undefined ? [field] : [` ` + fieldName + `: String!`];
|
|
12
|
+
let pendingQueue = {
|
|
13
|
+
contents: []
|
|
14
|
+
};
|
|
15
|
+
pendingQueueRegistry[fieldName] = pendingQueue;
|
|
16
|
+
let queuingReceive = inputJson => new Promise((resolve, _reject) => {
|
|
17
|
+
pendingQueue.contents.push({
|
|
18
|
+
inputJson: inputJson,
|
|
19
|
+
resolve: resolve
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
receiveRegistry[fieldName] = queuingReceive;
|
|
23
|
+
let resolver = async (_root, args, _ctx) => {
|
|
24
|
+
let receive = receiveRegistry[fieldName];
|
|
25
|
+
let result = await receive(args);
|
|
26
|
+
if (result.TAG === "Ok") {
|
|
27
|
+
return result._0.map(prim => prim);
|
|
28
|
+
} else {
|
|
29
|
+
return result._0;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
let resolvers = {};
|
|
33
|
+
resolvers[fieldName] = resolver;
|
|
34
|
+
server.registerMutations(sdlFields, resolvers);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function bindReceive(fieldName, receive) {
|
|
38
|
+
receiveRegistry[fieldName] = receive;
|
|
39
|
+
let pendingQueue = pendingQueueRegistry[fieldName];
|
|
40
|
+
if (pendingQueue === undefined) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
let pending = pendingQueue.contents;
|
|
44
|
+
pendingQueue.contents = [];
|
|
45
|
+
pending.forEach(param => {
|
|
46
|
+
let resolve = param.resolve;
|
|
47
|
+
receive(param.inputJson).then(result => resolve(result));
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
receiveRegistry,
|
|
53
|
+
pendingQueueRegistry,
|
|
54
|
+
register,
|
|
55
|
+
bindReceive,
|
|
56
|
+
}
|
|
57
|
+
/* GraphQL_FragmentGenerator-ReventlessCore Not a pure module */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// No-op CommandGenerator resolvers for in-memory (no AppSync).
|
|
2
|
+
|
|
3
|
+
open ReventlessCore
|
|
4
|
+
|
|
5
|
+
type api = unit
|
|
6
|
+
type runtimeParts = LocalRuntimeEnvironment.parts
|
|
7
|
+
|
|
8
|
+
let handleResolversEvent = (generateCommand: CommandGenerator.commandGenerator) =>
|
|
9
|
+
Pulumi.Output.make((event, _context) => event->generateCommand)
|
|
10
|
+
|
|
11
|
+
let make: CommandGenerator_Adapter.resolversMaker<unit, runtimeParts> = (
|
|
12
|
+
~name as _,
|
|
13
|
+
~api as _,
|
|
14
|
+
~fields as _,
|
|
15
|
+
~commandSchema as _,
|
|
16
|
+
~runtime as _,
|
|
17
|
+
~resources as _,
|
|
18
|
+
~opts as _,
|
|
19
|
+
) => {resources: []}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
4
|
+
|
|
5
|
+
function handleResolversEvent(generateCommand) {
|
|
6
|
+
return Pulumi.output((event, _context) => generateCommand(event));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function make(param, param$1, param$2, param$3, param$4, param$5, param$6) {
|
|
10
|
+
return {
|
|
11
|
+
resources: []
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
handleResolversEvent,
|
|
17
|
+
make,
|
|
18
|
+
}
|
|
19
|
+
/* @pulumi/pulumi Not a pure module */
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// In-memory CommandTopic channel.
|
|
2
|
+
// publishJsons encodes each command as {id, meta, command} (full message body) and dispatches via Bus.
|
|
3
|
+
// connect wires the channel to the runtime handler via Bus.registerCommandHandler.
|
|
4
|
+
// The full body format matches what CommandTopic_Callback.handleJsonCommands expects to decode.
|
|
5
|
+
|
|
6
|
+
module Make = (Bus: LocalBus.T) => {
|
|
7
|
+
type callbackEvent = JSON.t
|
|
8
|
+
type runtimeParts = LocalRuntimeEnvironment.parts
|
|
9
|
+
type channelParts = {name: string}
|
|
10
|
+
|
|
11
|
+
// Extract aggregate id (used as reference) from the full message body
|
|
12
|
+
let decodeId = (body: JSON.t): string =>
|
|
13
|
+
switch body {
|
|
14
|
+
| JSON.Object(d) =>
|
|
15
|
+
d
|
|
16
|
+
->Dict.get("id")
|
|
17
|
+
->Option.flatMap(j =>
|
|
18
|
+
switch j {
|
|
19
|
+
| JSON.String(s) => Some(s)
|
|
20
|
+
| _ => None
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
->Option.getOr("")
|
|
24
|
+
| _ => ""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let make: ReventlessCore.CommandTopic_Adapter.channelMaker<
|
|
28
|
+
callbackEvent,
|
|
29
|
+
'context,
|
|
30
|
+
channelParts,
|
|
31
|
+
runtimeParts,
|
|
32
|
+
> = (~name, ~opts as _=?) => {
|
|
33
|
+
// Captured when handleChannelEvent is called; used by publishJsonsAndWait to
|
|
34
|
+
// run the handler inline and collect typed outcomes without going through the bus.
|
|
35
|
+
let handleCmdsRef: ref<
|
|
36
|
+
option<ReventlessCore.CommandTopic.jsonCommandsHandler>,
|
|
37
|
+
> = ref(None)
|
|
38
|
+
|
|
39
|
+
let publishJsons: ReventlessInfra.CommandTopic.publishJsons = async jsons => {
|
|
40
|
+
let _ =
|
|
41
|
+
await jsons
|
|
42
|
+
->Array.map(async (cmdJson: Reventless.Message.commandJson) => {
|
|
43
|
+
await Bus.dispatchCommand(name, ReventlessCore.CommandTopic.encodeCommandJson(cmdJson))
|
|
44
|
+
})
|
|
45
|
+
->Promise.all
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let publishJsonsStream: ReventlessInfra.CommandTopic.publishJsonsStream = stream =>
|
|
49
|
+
stream
|
|
50
|
+
->Stream.grouped(10)
|
|
51
|
+
->Stream.runForEach(jsons => Effect.promise(() => publishJsons(jsons)))
|
|
52
|
+
|
|
53
|
+
let publishJsonsAndWait: ReventlessCore.CommandTopic.publishJsonsAndWait = async jsons => {
|
|
54
|
+
switch handleCmdsRef.contents {
|
|
55
|
+
| None =>
|
|
56
|
+
// Handler not yet registered — fall back to fire-and-forget, return Pending
|
|
57
|
+
let _ = await publishJsons(jsons)
|
|
58
|
+
jsons->Array.map(cmdJson =>
|
|
59
|
+
ReventlessCore.CommandTopic.Pending({msgId: cmdJson.meta.msgId})
|
|
60
|
+
)
|
|
61
|
+
| Some(handleCmds) =>
|
|
62
|
+
await ReventlessCore.CommandTopic.runInlineAndCollect(jsons, handleCmds)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let handleChannelEvent = (
|
|
67
|
+
handleCmds: ReventlessCore.CommandTopic.jsonCommandsHandler,
|
|
68
|
+
): Pulumi.Output.t<ReventlessCore.Runtime.effectHandler<callbackEvent, 'context, unit, string>> => {
|
|
69
|
+
handleCmdsRef.contents = Some(handleCmds)
|
|
70
|
+
(
|
|
71
|
+
(fullBody: JSON.t, _ctx) => {
|
|
72
|
+
// Pass the full body as `command` — that's what handleJsonCommands decodes
|
|
73
|
+
let reference = decodeId(fullBody)
|
|
74
|
+
let item: ReventlessInfra.CommandTopic.topicItem<JSON.t> = {command: fullBody, reference}
|
|
75
|
+
handleCmds(Stream.fromIterable([item]))->Effect.map(_ => ())
|
|
76
|
+
}
|
|
77
|
+
)->Pulumi.Output.make
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let connect: ReventlessCore.CommandTopic_Adapter.connect<
|
|
81
|
+
callbackEvent,
|
|
82
|
+
'context,
|
|
83
|
+
channelParts,
|
|
84
|
+
runtimeParts,
|
|
85
|
+
> = (~name as _, ~channel, ~runtime, ~resources as _, ~opts as _) => {
|
|
86
|
+
Bus.registerCommandHandler(channel.parts.name, async (json, ctx) => {
|
|
87
|
+
let handler =
|
|
88
|
+
await runtime.parts.handlerDeferred->Deferred.await_->Effect.runPromise
|
|
89
|
+
await handler(json, ctx)
|
|
90
|
+
})
|
|
91
|
+
[]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
{
|
|
95
|
+
parts: {name: name},
|
|
96
|
+
resources: [],
|
|
97
|
+
publishJsons: publishJsons->Pulumi.Output.make,
|
|
98
|
+
publishJsonsStream: publishJsonsStream->Pulumi.Output.make,
|
|
99
|
+
publishJsonsAndWait: Some(publishJsonsAndWait)->Pulumi.Output.make,
|
|
100
|
+
handleChannelEvent,
|
|
101
|
+
connect,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stream from "@reventlessdev/rescript-effect/src/Stream.res.mjs";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Stream$1 from "effect/Stream";
|
|
7
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
8
|
+
import * as Deferred from "effect/Deferred";
|
|
9
|
+
import * as CommandTopic$ReventlessCore from "@reventlessdev/reventless-core/src/components/CommandTopic/CommandTopic.res.mjs";
|
|
10
|
+
|
|
11
|
+
function Make(Bus) {
|
|
12
|
+
let decodeId = body => {
|
|
13
|
+
if (typeof body === "object" && body !== null && !Array.isArray(body)) {
|
|
14
|
+
return Stdlib_Option.getOr(Stdlib_Option.flatMap(body["id"], j => {
|
|
15
|
+
if (typeof j === "string") {
|
|
16
|
+
return j;
|
|
17
|
+
}
|
|
18
|
+
}), "");
|
|
19
|
+
} else {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
let make = (name, param) => {
|
|
24
|
+
let handleCmdsRef = {
|
|
25
|
+
contents: undefined
|
|
26
|
+
};
|
|
27
|
+
let publishJsons = async jsons => {
|
|
28
|
+
await Promise.all(jsons.map(async cmdJson => await Bus.dispatchCommand(name, CommandTopic$ReventlessCore.encodeCommandJson(cmdJson))));
|
|
29
|
+
};
|
|
30
|
+
let publishJsonsStream = stream => Stream$1.runForEach(Stream.grouped(stream, 10), jsons => Effect.promise(() => publishJsons(jsons)));
|
|
31
|
+
let publishJsonsAndWait = async jsons => {
|
|
32
|
+
let handleCmds = handleCmdsRef.contents;
|
|
33
|
+
if (handleCmds !== undefined) {
|
|
34
|
+
return await CommandTopic$ReventlessCore.runInlineAndCollect(jsons, handleCmds);
|
|
35
|
+
} else {
|
|
36
|
+
await publishJsons(jsons);
|
|
37
|
+
return jsons.map(cmdJson => ({
|
|
38
|
+
TAG: "Pending",
|
|
39
|
+
msgId: cmdJson.meta.msgId
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
let handleChannelEvent = handleCmds => {
|
|
44
|
+
handleCmdsRef.contents = handleCmds;
|
|
45
|
+
return Pulumi.output((fullBody, _ctx) => {
|
|
46
|
+
let reference = decodeId(fullBody);
|
|
47
|
+
let item = {
|
|
48
|
+
command: fullBody,
|
|
49
|
+
reference: reference
|
|
50
|
+
};
|
|
51
|
+
return Effect.map(handleCmds(Stream$1.fromIterable([item])), param => {});
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
let connect = (param, channel, runtime, param$1, param$2) => {
|
|
55
|
+
Bus.registerCommandHandler(channel.parts.name, async (json, ctx) => {
|
|
56
|
+
let handler = await Effect.runPromise(Deferred.await(runtime.parts.handlerDeferred));
|
|
57
|
+
return await handler(json, ctx);
|
|
58
|
+
});
|
|
59
|
+
return [];
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
parts: {
|
|
63
|
+
name: name
|
|
64
|
+
},
|
|
65
|
+
resources: [],
|
|
66
|
+
publishJsons: Pulumi.output(publishJsons),
|
|
67
|
+
publishJsonsStream: Pulumi.output(publishJsonsStream),
|
|
68
|
+
publishJsonsAndWait: Pulumi.output(publishJsonsAndWait),
|
|
69
|
+
handleChannelEvent: handleChannelEvent,
|
|
70
|
+
connect: connect
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
decodeId: decodeId,
|
|
75
|
+
make: make
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
Make,
|
|
81
|
+
}
|
|
82
|
+
/* Stream Not a pure module */
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// In-memory CommandTopic remote channel — satisfies CommandTopic_Adapter.RemoteChannel.
|
|
2
|
+
// Dispatches "remote" commands directly to the in-memory Bus.
|
|
3
|
+
|
|
4
|
+
module Make = (Bus: LocalBus.T) => {
|
|
5
|
+
let make: ReventlessCore.CommandTopic_Adapter.remoteChannelMaker = resources => {
|
|
6
|
+
resources,
|
|
7
|
+
remotePublish: async jsons => {
|
|
8
|
+
let _ =
|
|
9
|
+
await jsons
|
|
10
|
+
->Array.map(async (cmdJson: Reventless.Message.commandJson) => {
|
|
11
|
+
// Encode the same way LocalCommandTopicChannel does
|
|
12
|
+
let body = JSON.Encode.object(
|
|
13
|
+
Dict.fromArray([
|
|
14
|
+
("id", JSON.Encode.string(cmdJson.id)),
|
|
15
|
+
(
|
|
16
|
+
"meta",
|
|
17
|
+
cmdJson.meta->S.reverseConvertToJsonOrThrow(Reventless.Message.metaSchema),
|
|
18
|
+
),
|
|
19
|
+
("command", cmdJson.commandJson),
|
|
20
|
+
]),
|
|
21
|
+
)
|
|
22
|
+
// Dispatch to the first resource's name (the channel name)
|
|
23
|
+
let channelName = switch resources {
|
|
24
|
+
| [] => ""
|
|
25
|
+
| resources => (resources->Array.getUnsafe(0)).name
|
|
26
|
+
}
|
|
27
|
+
await Bus.dispatchCommand(channelName, body)
|
|
28
|
+
})
|
|
29
|
+
->Promise.all
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
|
|
5
|
+
|
|
6
|
+
function Make(Bus) {
|
|
7
|
+
let make = resources => ({
|
|
8
|
+
resources: resources,
|
|
9
|
+
remotePublish: async jsons => {
|
|
10
|
+
await Promise.all(jsons.map(async cmdJson => {
|
|
11
|
+
let body = Object.fromEntries([
|
|
12
|
+
[
|
|
13
|
+
"id",
|
|
14
|
+
cmdJson.id
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
"meta",
|
|
18
|
+
S.reverseConvertToJsonOrThrow(cmdJson.meta, Message$Reventless.metaSchema)
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
"command",
|
|
22
|
+
cmdJson.commandJson
|
|
23
|
+
]
|
|
24
|
+
]);
|
|
25
|
+
let channelName = resources.length !== 0 ? resources[0].name : "";
|
|
26
|
+
return await Bus.dispatchCommand(channelName, body);
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
make: make
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
Make,
|
|
37
|
+
}
|
|
38
|
+
/* S Not a pure module */
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// In-memory counter handler — tracks counter values in module-level dicts.
|
|
2
|
+
// Deduplicates: a given (counterId, targetRef) pair is only counted once.
|
|
3
|
+
//
|
|
4
|
+
// Call LocalCounterHandler.reset() in beforeEach to isolate tests.
|
|
5
|
+
|
|
6
|
+
open ReventlessCore
|
|
7
|
+
|
|
8
|
+
let counterStore: ref<dict<int>> = ref(Dict.make())
|
|
9
|
+
let targetRefStore: ref<dict<bool>> = ref(Dict.make())
|
|
10
|
+
|
|
11
|
+
let make: Counter_Adapter.handlerMaker = (
|
|
12
|
+
~name as _,
|
|
13
|
+
~referencesName as _,
|
|
14
|
+
~referencesDb as _,
|
|
15
|
+
~countsName as _,
|
|
16
|
+
~countsDb as _,
|
|
17
|
+
~counterHandler as _,
|
|
18
|
+
~specModulePath as _,
|
|
19
|
+
~mappingsModulePath as _,
|
|
20
|
+
~publishChannelId as _,
|
|
21
|
+
~opts as _,
|
|
22
|
+
) => {
|
|
23
|
+
addToCounterTarget: async ({ReventlessInfra.Counter.counterId, target, targetRef}) => {
|
|
24
|
+
let refKey = counterId ++ ":" ++ targetRef
|
|
25
|
+
switch targetRefStore.contents->Dict.get(refKey) {
|
|
26
|
+
| Some(_) => () // Already counted this (counterId, targetRef) pair — skip
|
|
27
|
+
| None =>
|
|
28
|
+
targetRefStore.contents->Dict.set(refKey, true)
|
|
29
|
+
let current = counterStore.contents->Dict.get(counterId)->Option.getOr(0)
|
|
30
|
+
counterStore.contents->Dict.set(counterId, current + target)
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Returns the current count for a given counterId.
|
|
36
|
+
let getCount = counterId => counterStore.contents->Dict.get(counterId)->Option.getOr(0)
|
|
37
|
+
|
|
38
|
+
// Reset all counters — call in beforeEach for test isolation.
|
|
39
|
+
let reset = () => {
|
|
40
|
+
counterStore.contents = Dict.make()
|
|
41
|
+
targetRefStore.contents = Dict.make()
|
|
42
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
|
|
5
|
+
let counterStore = {
|
|
6
|
+
contents: {}
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
let targetRefStore = {
|
|
10
|
+
contents: {}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function make(param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8, param$9) {
|
|
14
|
+
return {
|
|
15
|
+
addToCounterTarget: async param => {
|
|
16
|
+
let counterId = param.counterId;
|
|
17
|
+
let refKey = counterId + ":" + param.targetRef;
|
|
18
|
+
let match = targetRefStore.contents[refKey];
|
|
19
|
+
if (match !== undefined) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
targetRefStore.contents[refKey] = true;
|
|
23
|
+
let current = Stdlib_Option.getOr(counterStore.contents[counterId], 0);
|
|
24
|
+
counterStore.contents[counterId] = current + param.target | 0;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getCount(counterId) {
|
|
30
|
+
return Stdlib_Option.getOr(counterStore.contents[counterId], 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function reset() {
|
|
34
|
+
counterStore.contents = {};
|
|
35
|
+
targetRefStore.contents = {};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
counterStore,
|
|
40
|
+
targetRefStore,
|
|
41
|
+
make,
|
|
42
|
+
getCount,
|
|
43
|
+
reset,
|
|
44
|
+
}
|
|
45
|
+
/* No side effect */
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// In-memory DCB event log storage.
|
|
2
|
+
// Mirrors the mock storage in packages/reventless/tests/dcb/DcbFixtures.res
|
|
3
|
+
|
|
4
|
+
open ReventlessCore
|
|
5
|
+
|
|
6
|
+
let posToInt = (pos: string) => pos->Int.fromString->Option.getOr(0)
|
|
7
|
+
|
|
8
|
+
let matchesQuery = (event: DcbEventLog_Adapter.rawSequencedEvent, query: Reventless.DcbTag.query) =>
|
|
9
|
+
if query->Array.length == 0 {
|
|
10
|
+
true
|
|
11
|
+
} else {
|
|
12
|
+
query->Array.some(queryItem => {
|
|
13
|
+
let typeMatch = switch queryItem.eventTypes {
|
|
14
|
+
| Some(types) => types->Array.includes(event.eventType)
|
|
15
|
+
| None => true
|
|
16
|
+
}
|
|
17
|
+
let tagMatch = switch queryItem.tags {
|
|
18
|
+
| Some(tags) =>
|
|
19
|
+
tags->Array.every(tag =>
|
|
20
|
+
event.tags->Array.some(et => et.key == tag.key && et.value == tag.value)
|
|
21
|
+
)
|
|
22
|
+
| None => true
|
|
23
|
+
}
|
|
24
|
+
typeMatch && tagMatch
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let makeStorage = (~name as _name, ~indexes as _, ~partitionTag as _, ~opts as _) => {
|
|
29
|
+
let events: ref<array<DcbEventLog_Adapter.rawSequencedEvent>> = ref([])
|
|
30
|
+
let position = ref(0)
|
|
31
|
+
|
|
32
|
+
let read = async (~query, ~after=?) => {
|
|
33
|
+
let filtered = events.contents->Array.filter(event => {
|
|
34
|
+
let afterMatch = switch after {
|
|
35
|
+
| Some(afterPos) => event.position->posToInt > afterPos->posToInt
|
|
36
|
+
| None => true
|
|
37
|
+
}
|
|
38
|
+
afterMatch && matchesQuery(event, query)
|
|
39
|
+
})
|
|
40
|
+
let headPosition =
|
|
41
|
+
events.contents
|
|
42
|
+
->Array.get(events.contents->Array.length - 1)
|
|
43
|
+
->Option.map(e => e.position)
|
|
44
|
+
{
|
|
45
|
+
DcbEventLog_Adapter.events: filtered,
|
|
46
|
+
?headPosition,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let append = async (newEvents, ~condition=?) => {
|
|
51
|
+
let conflictDetected = switch condition {
|
|
52
|
+
| Some(cond: Reventless.DcbTag.appendCondition) =>
|
|
53
|
+
events.contents->Array.some(event => {
|
|
54
|
+
let afterMatch = switch cond.after {
|
|
55
|
+
| Some(pos) => event.position->posToInt > pos->posToInt
|
|
56
|
+
| None => true
|
|
57
|
+
}
|
|
58
|
+
afterMatch && matchesQuery(event, cond.query)
|
|
59
|
+
})
|
|
60
|
+
| None => false
|
|
61
|
+
}
|
|
62
|
+
if conflictDetected {
|
|
63
|
+
Error("conflict: condition check failed")
|
|
64
|
+
} else {
|
|
65
|
+
let storedEvents =
|
|
66
|
+
newEvents->Array.map((event: DcbEventLog_Adapter.rawStoredEvent) => {
|
|
67
|
+
position := position.contents + 1
|
|
68
|
+
let pos = position.contents->Int.toString
|
|
69
|
+
{
|
|
70
|
+
DcbEventLog_Adapter.position: pos,
|
|
71
|
+
eventType: event.eventType,
|
|
72
|
+
data: event.data,
|
|
73
|
+
tags: event.tags,
|
|
74
|
+
meta: event.meta,
|
|
75
|
+
recordedAt: Message.nowAsISOString(),
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
events := events.contents->Array.concat(storedEvents)
|
|
79
|
+
Ok(position.contents->Int.toString)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ~strongConsistency is a DynamoDB read-replica concept; the in-memory backend
|
|
84
|
+
// is always consistent, so it is accepted (interface parity) and ignored.
|
|
85
|
+
let readStream = (~query, ~after=?, ~strongConsistency as _=?) =>
|
|
86
|
+
Effect.promise(() => read(~query, ~after?))
|
|
87
|
+
->Effect.map(result => result.events)
|
|
88
|
+
->Stream.fromEffect
|
|
89
|
+
->Stream.flatMap(arr => Stream.fromIterable(arr))
|
|
90
|
+
|
|
91
|
+
(
|
|
92
|
+
_name,
|
|
93
|
+
read,
|
|
94
|
+
{
|
|
95
|
+
DcbEventLog_Adapter.resources: [],
|
|
96
|
+
operations: Pulumi.Output.make({DcbEventLog_Adapter.read, append, readStream}),
|
|
97
|
+
},
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Local backends evaluate the DCB condition literally against the event list
|
|
102
|
+
// (true DCB semantics), so a single-tag clause already matches every carrier of
|
|
103
|
+
// the tag regardless of partition — cross-partition reads work without special
|
|
104
|
+
// routing. The flag is accepted for interface parity and ignored.
|
|
105
|
+
let make: DcbEventLog_Adapter.storageMaker = (~name, ~indexes, ~partitionTag, ~crossPartitionTagKeys as _=?, ~opts) => {
|
|
106
|
+
let (_, _, storage) = makeStorage(~name, ~indexes, ~partitionTag, ~opts)
|
|
107
|
+
storage
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module Make = (Bus: LocalBus.T) => {
|
|
111
|
+
let make: DcbEventLog_Adapter.storageMaker = (~name, ~indexes, ~partitionTag, ~crossPartitionTagKeys as _=?, ~opts) => {
|
|
112
|
+
switch BackendState.getDb() {
|
|
113
|
+
| Some(db) =>
|
|
114
|
+
let (storageName, read, storage) = DcbEventLogStorage_Sqlite.makeStorage(
|
|
115
|
+
~db,
|
|
116
|
+
~bus=(_, _) => (),
|
|
117
|
+
~publishToTopic=(~topicName as _, ~json as _) => (),
|
|
118
|
+
~name,
|
|
119
|
+
~indexes,
|
|
120
|
+
~partitionTag,
|
|
121
|
+
~opts,
|
|
122
|
+
)
|
|
123
|
+
Bus.registerDcbEventLogRead(storageName, read)
|
|
124
|
+
storage
|
|
125
|
+
| None =>
|
|
126
|
+
let (storageName, read, storage) = makeStorage(~name, ~indexes, ~partitionTag, ~opts)
|
|
127
|
+
Bus.registerDcbEventLogRead(storageName, read)
|
|
128
|
+
storage
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|