@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,213 @@
|
|
|
1
|
+
// Plan 04 fixtures — AutomationSlice with two sources (Aggregate + DCB).
|
|
2
|
+
// Verifies mixed-source dispatch: both sources feed the same slice's TODO list,
|
|
3
|
+
// each going through its own per-source `collect`/`resolve`, and `process`
|
|
4
|
+
// produces commands for the target.
|
|
5
|
+
|
|
6
|
+
open TestFixtures
|
|
7
|
+
open Reventless
|
|
8
|
+
|
|
9
|
+
// ─────────────────────────────────────────────────────────────
|
|
10
|
+
// Source 1: simulated Aggregate — emits OrderShipped events
|
|
11
|
+
// ─────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
module OrderAggregateSource = {
|
|
14
|
+
module Id = Id.String
|
|
15
|
+
let name = "OrderAggregateEventTopic"
|
|
16
|
+
@schema
|
|
17
|
+
type event =
|
|
18
|
+
| OrderShipped({orderId: string, productId: string})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ─────────────────────────────────────────────────────────────
|
|
22
|
+
// Source 2: simulated DCB EventLog — emits StockReserved events
|
|
23
|
+
// ─────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
module InventoryDcbSource = {
|
|
26
|
+
module Id = Id.String
|
|
27
|
+
let name = "InventoryDcbEventLog"
|
|
28
|
+
@schema
|
|
29
|
+
type event =
|
|
30
|
+
| StockReserved({orderId: string, productId: string})
|
|
31
|
+
| StockReleased({orderId: string, productId: string})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ─────────────────────────────────────────────────────────────
|
|
35
|
+
// AutomationSlice spec — joins both sources by composite key
|
|
36
|
+
// ─────────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
module AutoFulfillSpec = {
|
|
39
|
+
let name = "AutoFulfill"
|
|
40
|
+
let moduleUrl: string = %raw(`import.meta.url`)
|
|
41
|
+
|
|
42
|
+
@schema
|
|
43
|
+
type todoItem = {
|
|
44
|
+
orderId: string,
|
|
45
|
+
productId: string,
|
|
46
|
+
fromAggregate: bool, // tracks which source produced this item
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@schema
|
|
50
|
+
type command = MarkFulfilled({
|
|
51
|
+
orderId: @s.matches(DcbTag.string) string,
|
|
52
|
+
productId: @s.matches(DcbTag.string) string,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
let maxRetries = 3
|
|
56
|
+
let heartbeatInterval = 60
|
|
57
|
+
let targetName = "MarkFulfilled"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Forward-declared per-source mappings live below; the merged `Automation`
|
|
61
|
+
// module type also exposes `mappings` + `module type Mapping`, which we
|
|
62
|
+
// populate after `FromOrderAggregate` / `FromInventoryDcb` are in scope.
|
|
63
|
+
|
|
64
|
+
// ─────────────────────────────────────────────────────────────
|
|
65
|
+
// Mapping 1: Aggregate source → todoItem (with `fromAggregate=true`)
|
|
66
|
+
// ─────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
module FromOrderAggregate = AutomationSlice.Mapping.Make(
|
|
69
|
+
OrderAggregateSource,
|
|
70
|
+
AutoFulfillSpec,
|
|
71
|
+
{
|
|
72
|
+
let collect = (event: OrderAggregateSource.event, _ctx) =>
|
|
73
|
+
switch event {
|
|
74
|
+
| OrderShipped({orderId, productId}) => [
|
|
75
|
+
(
|
|
76
|
+
orderId ++ ":" ++ productId,
|
|
77
|
+
({orderId, productId, fromAggregate: true}: AutoFulfillSpec.todoItem),
|
|
78
|
+
),
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
let resolve = (_event: OrderAggregateSource.event) => None
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
// ─────────────────────────────────────────────────────────────
|
|
86
|
+
// Mapping 2: DCB source → todoItem (with `fromAggregate=false`)
|
|
87
|
+
// Also resolves on StockReleased — releases roll back any pending TODO.
|
|
88
|
+
// ─────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
module FromInventoryDcb = AutomationSlice.Mapping.Make(
|
|
91
|
+
InventoryDcbSource,
|
|
92
|
+
AutoFulfillSpec,
|
|
93
|
+
{
|
|
94
|
+
let collect = (event: InventoryDcbSource.event, _ctx) =>
|
|
95
|
+
switch event {
|
|
96
|
+
| StockReserved({orderId, productId}) => [
|
|
97
|
+
(
|
|
98
|
+
orderId ++ ":" ++ productId,
|
|
99
|
+
({orderId, productId, fromAggregate: false}: AutoFulfillSpec.todoItem),
|
|
100
|
+
),
|
|
101
|
+
]
|
|
102
|
+
| StockReleased(_) => []
|
|
103
|
+
}
|
|
104
|
+
let resolve = (event: InventoryDcbSource.event) =>
|
|
105
|
+
switch event {
|
|
106
|
+
| StockReleased({orderId, productId}) => Some(orderId ++ ":" ++ productId)
|
|
107
|
+
| StockReserved(_) => None
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// ─────────────────────────────────────────────────────────────
|
|
113
|
+
// Mappings collection
|
|
114
|
+
// ─────────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
module AutoFulfillAutomation: AutomationSlice.Automation
|
|
117
|
+
with module Spec := AutoFulfillSpec = {
|
|
118
|
+
let process = (id, item: AutoFulfillSpec.todoItem) =>
|
|
119
|
+
Some((id, AutoFulfillSpec.MarkFulfilled({orderId: item.orderId, productId: item.productId})))
|
|
120
|
+
let moduleUrl: string = %raw(`import.meta.url`)
|
|
121
|
+
module M = AutomationSlice.Mappings.Make(AutoFulfillSpec)
|
|
122
|
+
module type Mapping = M.Mapping
|
|
123
|
+
let mappings: array<module(Mapping)> = [module(FromOrderAggregate), module(FromInventoryDcb)]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ─────────────────────────────────────────────────────────────
|
|
127
|
+
// allEventTopics — two entries, one per source (matches mapping sourceNames)
|
|
128
|
+
// ─────────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
let aggregateResource: ReventlessInfra.Adapter.resource = ReventlessInfra.Adapter.make(
|
|
131
|
+
~name=OrderAggregateSource.name->Pulumi.Output.make,
|
|
132
|
+
~id=OrderAggregateSource.name->Pulumi.Output.make,
|
|
133
|
+
~urn=OrderAggregateSource.name->Pulumi.Output.make,
|
|
134
|
+
~service="memory:InMemory"->Pulumi.Output.make,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
let dcbResource: ReventlessInfra.Adapter.resource = ReventlessInfra.Adapter.make(
|
|
138
|
+
~name=InventoryDcbSource.name->Pulumi.Output.make,
|
|
139
|
+
~id=InventoryDcbSource.name->Pulumi.Output.make,
|
|
140
|
+
~urn=InventoryDcbSource.name->Pulumi.Output.make,
|
|
141
|
+
~service="memory:InMemory"->Pulumi.Output.make,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
let allEventTopics: ReventlessCore.EventTopic.allOutputs = Dict.fromArray([
|
|
145
|
+
(OrderAggregateSource.name, {ReventlessInfra.EventTopic.resources: [aggregateResource]}),
|
|
146
|
+
(InventoryDcbSource.name, {ReventlessInfra.EventTopic.resources: [dcbResource]}),
|
|
147
|
+
])
|
|
148
|
+
|
|
149
|
+
// ─────────────────────────────────────────────────────────────
|
|
150
|
+
// Isolated bus + Pulumi mock mode
|
|
151
|
+
// ─────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
module Bus = LocalBus.Make()
|
|
154
|
+
let _ = TestRunner.setup()
|
|
155
|
+
|
|
156
|
+
// ─────────────────────────────────────────────────────────────
|
|
157
|
+
// Build AutomationSlice
|
|
158
|
+
// ─────────────────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
module AutomationSliceMaker = AutomationSlice_Builder.Make(Bus)
|
|
161
|
+
module AutoFulfill = AutomationSliceMaker.Make(
|
|
162
|
+
AutoFulfillSpec,
|
|
163
|
+
AutoFulfillAutomation,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
// Mirrors the context that `Plugin_Builder` constructs for local deployments
|
|
167
|
+
// (environment from `LocalPluginSpec.environment`, platformName "local").
|
|
168
|
+
let testContext: Reventless.AutomationSlice.context = {
|
|
169
|
+
environment: "local",
|
|
170
|
+
platformName: "local",
|
|
171
|
+
pluginName: "TestPlugin",
|
|
172
|
+
sliceName: AutoFulfillSpec.name,
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// publishJsons — capture commands instead of round-tripping through a CommandTopic.
|
|
176
|
+
let publishedCommands: ref<array<Reventless.Message.commandJson>> = ref([])
|
|
177
|
+
let mockPublishJsons: ReventlessInfra.CommandTopic.publishJsons = async cmds => {
|
|
178
|
+
publishedCommands := publishedCommands.contents->Array.concat(cmds)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let slice = AutoFulfill.make(
|
|
182
|
+
~allEventTopics,
|
|
183
|
+
~publishJsons=mockPublishJsons->Pulumi.Output.make,
|
|
184
|
+
~context=testContext,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
// ─────────────────────────────────────────────────────────────
|
|
188
|
+
// Test helpers
|
|
189
|
+
// ─────────────────────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
let publishAggregateEvent = async (id, event: OrderAggregateSource.event) => {
|
|
192
|
+
let meta = makeTestMeta(~service=OrderAggregateSource.name)
|
|
193
|
+
let eventJson = JSON.Encode.object(
|
|
194
|
+
Dict.fromArray([
|
|
195
|
+
("id", id->JSON.Encode.string),
|
|
196
|
+
("meta", meta->S.reverseConvertToJsonOrThrow(Message.metaSchema)),
|
|
197
|
+
("event", event->S.reverseConvertToJsonOrThrow(OrderAggregateSource.eventSchema)),
|
|
198
|
+
]),
|
|
199
|
+
)
|
|
200
|
+
await Bus.publishEvent(OrderAggregateSource.name, "test", meta, eventJson)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let publishDcbEvent = async (id, event: InventoryDcbSource.event) => {
|
|
204
|
+
let meta = makeTestMeta(~service=InventoryDcbSource.name)
|
|
205
|
+
let eventJson = JSON.Encode.object(
|
|
206
|
+
Dict.fromArray([
|
|
207
|
+
("id", id->JSON.Encode.string),
|
|
208
|
+
("meta", meta->S.reverseConvertToJsonOrThrow(Message.metaSchema)),
|
|
209
|
+
("event", event->S.reverseConvertToJsonOrThrow(InventoryDcbSource.eventSchema)),
|
|
210
|
+
]),
|
|
211
|
+
)
|
|
212
|
+
await Bus.publishEvent(InventoryDcbSource.name, "test", meta, eventJson)
|
|
213
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
|
|
5
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
6
|
+
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
7
|
+
import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
|
|
8
|
+
import * as Adapter$ReventlessInfra from "@reventlessdev/reventless-infra/src/adapter/Adapter.res.mjs";
|
|
9
|
+
import * as LocalBus$ReventlessLocal from "../../../src/adapter/LocalBus.res.mjs";
|
|
10
|
+
import * as AutomationSlice$Reventless from "@reventlessdev/reventless-spec/src/components/AutomationSlice.res.mjs";
|
|
11
|
+
import * as TestRunner$ReventlessLocal from "../../../src/test/TestRunner.res.mjs";
|
|
12
|
+
import * as TestFixtures$ReventlessLocal from "../../TestFixtures.res.mjs";
|
|
13
|
+
import * as AutomationSlice_Builder$ReventlessLocal from "../../../src/components/AutomationSlice_Builder.res.mjs";
|
|
14
|
+
|
|
15
|
+
let name = "OrderAggregateEventTopic";
|
|
16
|
+
|
|
17
|
+
let eventSchema = S.schema(s => ({
|
|
18
|
+
TAG: "OrderShipped",
|
|
19
|
+
orderId: s.m(S.string),
|
|
20
|
+
productId: s.m(S.string)
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
let OrderAggregateSource = {
|
|
24
|
+
Id: undefined,
|
|
25
|
+
name: name,
|
|
26
|
+
eventSchema: eventSchema
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
let name$1 = "InventoryDcbEventLog";
|
|
30
|
+
|
|
31
|
+
let eventSchema$1 = S.union([
|
|
32
|
+
S.schema(s => ({
|
|
33
|
+
TAG: "StockReserved",
|
|
34
|
+
orderId: s.m(S.string),
|
|
35
|
+
productId: s.m(S.string)
|
|
36
|
+
})),
|
|
37
|
+
S.schema(s => ({
|
|
38
|
+
TAG: "StockReleased",
|
|
39
|
+
orderId: s.m(S.string),
|
|
40
|
+
productId: s.m(S.string)
|
|
41
|
+
}))
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
let InventoryDcbSource = {
|
|
45
|
+
Id: undefined,
|
|
46
|
+
name: name$1,
|
|
47
|
+
eventSchema: eventSchema$1
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
let name$2 = "AutoFulfill";
|
|
51
|
+
|
|
52
|
+
let moduleUrl = import.meta.url;
|
|
53
|
+
|
|
54
|
+
let todoItemSchema = S.schema(s => ({
|
|
55
|
+
orderId: s.m(S.string),
|
|
56
|
+
productId: s.m(S.string),
|
|
57
|
+
fromAggregate: s.m(S.bool)
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
let commandSchema = S.schema(s => ({
|
|
61
|
+
TAG: "MarkFulfilled",
|
|
62
|
+
orderId: s.m(DcbTag$Reventless.string),
|
|
63
|
+
productId: s.m(DcbTag$Reventless.string)
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
function commandAuthorization(param) {
|
|
67
|
+
return "AllowAuthenticated";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let AutoFulfillSpec = {
|
|
71
|
+
name: name$2,
|
|
72
|
+
moduleUrl: moduleUrl,
|
|
73
|
+
todoItemSchema: todoItemSchema,
|
|
74
|
+
commandSchema: commandSchema,
|
|
75
|
+
maxRetries: 3,
|
|
76
|
+
heartbeatInterval: 60,
|
|
77
|
+
targetName: "MarkFulfilled",
|
|
78
|
+
commandAuthorization: commandAuthorization
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
function collect(event, _ctx) {
|
|
82
|
+
let productId = event.productId;
|
|
83
|
+
let orderId = event.orderId;
|
|
84
|
+
return [[
|
|
85
|
+
orderId + ":" + productId,
|
|
86
|
+
{
|
|
87
|
+
orderId: orderId,
|
|
88
|
+
productId: productId,
|
|
89
|
+
fromAggregate: true
|
|
90
|
+
}
|
|
91
|
+
]];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function resolve(_event) {
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let FromOrderAggregate = AutomationSlice$Reventless.Mapping.Make({
|
|
99
|
+
Id: Id$Reventless.$$String,
|
|
100
|
+
name: name,
|
|
101
|
+
eventSchema: eventSchema
|
|
102
|
+
})(AutoFulfillSpec)({
|
|
103
|
+
collect: collect,
|
|
104
|
+
resolve: resolve
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
function collect$1(event, _ctx) {
|
|
108
|
+
if (event.TAG !== "StockReserved") {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
let productId = event.productId;
|
|
112
|
+
let orderId = event.orderId;
|
|
113
|
+
return [[
|
|
114
|
+
orderId + ":" + productId,
|
|
115
|
+
{
|
|
116
|
+
orderId: orderId,
|
|
117
|
+
productId: productId,
|
|
118
|
+
fromAggregate: false
|
|
119
|
+
}
|
|
120
|
+
]];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function resolve$1(event) {
|
|
124
|
+
if (event.TAG === "StockReserved") {
|
|
125
|
+
return;
|
|
126
|
+
} else {
|
|
127
|
+
return event.orderId + ":" + event.productId;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let FromInventoryDcb = AutomationSlice$Reventless.Mapping.Make({
|
|
132
|
+
Id: Id$Reventless.$$String,
|
|
133
|
+
name: name$1,
|
|
134
|
+
eventSchema: eventSchema$1
|
|
135
|
+
})(AutoFulfillSpec)({
|
|
136
|
+
collect: collect$1,
|
|
137
|
+
resolve: resolve$1
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
function process(id, item) {
|
|
141
|
+
return [
|
|
142
|
+
id,
|
|
143
|
+
{
|
|
144
|
+
TAG: "MarkFulfilled",
|
|
145
|
+
orderId: item.orderId,
|
|
146
|
+
productId: item.productId
|
|
147
|
+
}
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let moduleUrl$1 = import.meta.url;
|
|
152
|
+
|
|
153
|
+
AutomationSlice$Reventless.Mappings.Make(AutoFulfillSpec);
|
|
154
|
+
|
|
155
|
+
let mappings = [
|
|
156
|
+
FromOrderAggregate,
|
|
157
|
+
FromInventoryDcb
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
let AutoFulfillAutomation = {
|
|
161
|
+
process: process,
|
|
162
|
+
moduleUrl: moduleUrl$1,
|
|
163
|
+
mappings: mappings
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
let aggregateResource = Adapter$ReventlessInfra.make(Pulumi.output(name), Pulumi.output(name), Pulumi.output(name), Pulumi.output("memory:InMemory"), undefined, undefined, undefined, undefined, undefined, undefined);
|
|
167
|
+
|
|
168
|
+
let dcbResource = Adapter$ReventlessInfra.make(Pulumi.output(name$1), Pulumi.output(name$1), Pulumi.output(name$1), Pulumi.output("memory:InMemory"), undefined, undefined, undefined, undefined, undefined, undefined);
|
|
169
|
+
|
|
170
|
+
let allEventTopics = Object.fromEntries([
|
|
171
|
+
[
|
|
172
|
+
name,
|
|
173
|
+
{
|
|
174
|
+
resources: [aggregateResource]
|
|
175
|
+
}
|
|
176
|
+
],
|
|
177
|
+
[
|
|
178
|
+
name$1,
|
|
179
|
+
{
|
|
180
|
+
resources: [dcbResource]
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
]);
|
|
184
|
+
|
|
185
|
+
let Bus = LocalBus$ReventlessLocal.Make({});
|
|
186
|
+
|
|
187
|
+
TestRunner$ReventlessLocal.setup();
|
|
188
|
+
|
|
189
|
+
let AutomationSliceMaker = AutomationSlice_Builder$ReventlessLocal.Make(Bus);
|
|
190
|
+
|
|
191
|
+
let AutoFulfill = AutomationSliceMaker.Make(AutoFulfillSpec)(AutoFulfillAutomation);
|
|
192
|
+
|
|
193
|
+
let testContext = {
|
|
194
|
+
environment: "local",
|
|
195
|
+
platformName: "local",
|
|
196
|
+
pluginName: "TestPlugin",
|
|
197
|
+
sliceName: name$2
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
let publishedCommands = {
|
|
201
|
+
contents: []
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
async function mockPublishJsons(cmds) {
|
|
205
|
+
publishedCommands.contents = publishedCommands.contents.concat(cmds);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
let slice = AutoFulfill.make(allEventTopics, Pulumi.output(mockPublishJsons), testContext, undefined);
|
|
209
|
+
|
|
210
|
+
async function publishAggregateEvent(id, event) {
|
|
211
|
+
let meta = TestFixtures$ReventlessLocal.makeTestMeta(name);
|
|
212
|
+
let eventJson = Object.fromEntries([
|
|
213
|
+
[
|
|
214
|
+
"id",
|
|
215
|
+
id
|
|
216
|
+
],
|
|
217
|
+
[
|
|
218
|
+
"meta",
|
|
219
|
+
S.reverseConvertToJsonOrThrow(meta, Message$Reventless.metaSchema)
|
|
220
|
+
],
|
|
221
|
+
[
|
|
222
|
+
"event",
|
|
223
|
+
S.reverseConvertToJsonOrThrow(event, eventSchema)
|
|
224
|
+
]
|
|
225
|
+
]);
|
|
226
|
+
return await Bus.publishEvent(name, "test", meta, eventJson);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function publishDcbEvent(id, event) {
|
|
230
|
+
let meta = TestFixtures$ReventlessLocal.makeTestMeta(name$1);
|
|
231
|
+
let eventJson = Object.fromEntries([
|
|
232
|
+
[
|
|
233
|
+
"id",
|
|
234
|
+
id
|
|
235
|
+
],
|
|
236
|
+
[
|
|
237
|
+
"meta",
|
|
238
|
+
S.reverseConvertToJsonOrThrow(meta, Message$Reventless.metaSchema)
|
|
239
|
+
],
|
|
240
|
+
[
|
|
241
|
+
"event",
|
|
242
|
+
S.reverseConvertToJsonOrThrow(event, eventSchema$1)
|
|
243
|
+
]
|
|
244
|
+
]);
|
|
245
|
+
return await Bus.publishEvent(name$1, "test", meta, eventJson);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export {
|
|
249
|
+
OrderAggregateSource,
|
|
250
|
+
InventoryDcbSource,
|
|
251
|
+
AutoFulfillSpec,
|
|
252
|
+
FromOrderAggregate,
|
|
253
|
+
FromInventoryDcb,
|
|
254
|
+
AutoFulfillAutomation,
|
|
255
|
+
aggregateResource,
|
|
256
|
+
dcbResource,
|
|
257
|
+
allEventTopics,
|
|
258
|
+
Bus,
|
|
259
|
+
AutomationSliceMaker,
|
|
260
|
+
AutoFulfill,
|
|
261
|
+
testContext,
|
|
262
|
+
publishedCommands,
|
|
263
|
+
mockPublishJsons,
|
|
264
|
+
slice,
|
|
265
|
+
publishAggregateEvent,
|
|
266
|
+
publishDcbEvent,
|
|
267
|
+
}
|
|
268
|
+
/* eventSchema Not a pure module */
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Plan 04 integration test — AutomationSlice consumes events from two sources
|
|
2
|
+
// (Aggregate + DCB EventLog) and drives a single TODO list to MarkFulfilled
|
|
3
|
+
// commands. Verifies per-source decode dispatch, context plumbing, and that
|
|
4
|
+
// commands surface via publishJsons.
|
|
5
|
+
|
|
6
|
+
open JestGlobals
|
|
7
|
+
open MixedSourceAutomationSliceFixtures
|
|
8
|
+
|
|
9
|
+
describe("MixedSource AutomationSlice", () => {
|
|
10
|
+
let _ = beforeAllAsync(async () => {
|
|
11
|
+
let _ = await slice->ReventlessCore.Component.operations->TestRunner.resolve
|
|
12
|
+
let _ = await aggregateResource.name->TestRunner.resolve
|
|
13
|
+
let _ = await dcbResource.name->TestRunner.resolve
|
|
14
|
+
// Extra microtask flushes: subscription registration in
|
|
15
|
+
// LocalEventCollectorChannel.connect is fire-and-forget via
|
|
16
|
+
// `Effect.runPromise->ignore`, so we need the runtime to drain those
|
|
17
|
+
// microtasks before publishing events.
|
|
18
|
+
let _ = await Promise.resolve()
|
|
19
|
+
let _ = await Promise.resolve()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
let _ = beforeEach(() => {
|
|
23
|
+
publishedCommands := []
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
testPromise("Aggregate-source event creates a TODO and produces a command", async () => {
|
|
27
|
+
publishedCommands := []
|
|
28
|
+
let _ = await publishAggregateEvent(
|
|
29
|
+
"env-a1",
|
|
30
|
+
OrderShipped({orderId: "o1", productId: "p1"}),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
// Trigger phase2 manually since we don't have a heartbeat in this test.
|
|
34
|
+
let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
|
|
35
|
+
await ops.processPending()
|
|
36
|
+
|
|
37
|
+
expect(publishedCommands.contents->Array.length)->toBe(1)
|
|
38
|
+
let cmd = publishedCommands.contents->Array.getUnsafe(0)
|
|
39
|
+
expect(cmd.id)->toBe("o1:p1")
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
testPromise("DCB-source StockReserved creates a TODO and produces a command", async () => {
|
|
43
|
+
publishedCommands := []
|
|
44
|
+
let _ = await publishDcbEvent(
|
|
45
|
+
"env-d1",
|
|
46
|
+
StockReserved({orderId: "o2", productId: "p2"}),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
|
|
50
|
+
await ops.processPending()
|
|
51
|
+
|
|
52
|
+
expect(publishedCommands.contents->Array.length)->toBe(1)
|
|
53
|
+
let cmd = publishedCommands.contents->Array.getUnsafe(0)
|
|
54
|
+
expect(cmd.id)->toBe("o2:p2")
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
testPromise("DCB-source StockReleased after a Processing item is idempotent", async () => {
|
|
58
|
+
publishedCommands := []
|
|
59
|
+
// Reserve fires phase1+phase2 (inline) — produces 1 command, item becomes
|
|
60
|
+
// Processing. StockReleased then resolves the item to Completed —
|
|
61
|
+
// subsequent processPending calls produce no further commands for it.
|
|
62
|
+
let _ = await publishDcbEvent(
|
|
63
|
+
"env-d2",
|
|
64
|
+
StockReserved({orderId: "o3", productId: "p3"}),
|
|
65
|
+
)
|
|
66
|
+
let _ = await publishDcbEvent(
|
|
67
|
+
"env-d3",
|
|
68
|
+
StockReleased({orderId: "o3", productId: "p3"}),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
expect(publishedCommands.contents->Array.length)->toBe(1)
|
|
72
|
+
|
|
73
|
+
// Reset and call processPending again — already-Processing/Completed item
|
|
74
|
+
// shouldn't generate a duplicate.
|
|
75
|
+
publishedCommands := []
|
|
76
|
+
let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
|
|
77
|
+
await ops.processPending()
|
|
78
|
+
expect(publishedCommands.contents->Array.length)->toBe(0)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
testPromise("both sources can drive items into the same TODO list independently", async () => {
|
|
82
|
+
publishedCommands := []
|
|
83
|
+
let _ = await publishAggregateEvent(
|
|
84
|
+
"env-a2",
|
|
85
|
+
OrderShipped({orderId: "o4", productId: "p4"}),
|
|
86
|
+
)
|
|
87
|
+
let _ = await publishDcbEvent(
|
|
88
|
+
"env-d4",
|
|
89
|
+
StockReserved({orderId: "o5", productId: "p5"}),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
|
|
93
|
+
await ops.processPending()
|
|
94
|
+
|
|
95
|
+
expect(publishedCommands.contents->Array.length)->toBe(2)
|
|
96
|
+
let ids = publishedCommands.contents->Array.map(c => c.id)
|
|
97
|
+
expect(ids->Array.includes("o4:p4"))->toBe(true)
|
|
98
|
+
expect(ids->Array.includes("o5:p5"))->toBe(true)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
testPromise("first-writer-wins idempotency across mappings sharing an ID", async () => {
|
|
102
|
+
publishedCommands := []
|
|
103
|
+
// Both sources produce the same composite ID — second arrival is ignored.
|
|
104
|
+
let _ = await publishAggregateEvent(
|
|
105
|
+
"env-a3",
|
|
106
|
+
OrderShipped({orderId: "o6", productId: "p6"}),
|
|
107
|
+
)
|
|
108
|
+
let _ = await publishDcbEvent(
|
|
109
|
+
"env-d5",
|
|
110
|
+
StockReserved({orderId: "o6", productId: "p6"}),
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
let ops = await slice->ReventlessCore.Component.operations->TestRunner.resolve
|
|
114
|
+
await ops.processPending()
|
|
115
|
+
|
|
116
|
+
expect(publishedCommands.contents->Array.length)->toBe(1)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
|
|
4
|
+
import * as TestRunner$ReventlessLocal from "../../../src/test/TestRunner.res.mjs";
|
|
5
|
+
import * as MixedSourceAutomationSliceFixtures$ReventlessLocal from "./MixedSourceAutomationSliceFixtures.res.mjs";
|
|
6
|
+
|
|
7
|
+
globalThis.describe("MixedSource AutomationSlice", () => {
|
|
8
|
+
globalThis.beforeAll(async () => {
|
|
9
|
+
await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
|
|
10
|
+
await TestRunner$ReventlessLocal.resolve(MixedSourceAutomationSliceFixtures$ReventlessLocal.aggregateResource.name);
|
|
11
|
+
await TestRunner$ReventlessLocal.resolve(MixedSourceAutomationSliceFixtures$ReventlessLocal.dcbResource.name);
|
|
12
|
+
await Promise.resolve();
|
|
13
|
+
await Promise.resolve();
|
|
14
|
+
});
|
|
15
|
+
globalThis.beforeEach(() => {
|
|
16
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
17
|
+
});
|
|
18
|
+
globalThis.test("Aggregate-source event creates a TODO and produces a command", async () => {
|
|
19
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
20
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishAggregateEvent("env-a1", {
|
|
21
|
+
TAG: "OrderShipped",
|
|
22
|
+
orderId: "o1",
|
|
23
|
+
productId: "p1"
|
|
24
|
+
});
|
|
25
|
+
let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
|
|
26
|
+
await ops.processPending();
|
|
27
|
+
globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
|
|
28
|
+
let cmd = MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents[0];
|
|
29
|
+
globalThis.expect(cmd.id).toBe("o1:p1");
|
|
30
|
+
});
|
|
31
|
+
globalThis.test("DCB-source StockReserved creates a TODO and produces a command", async () => {
|
|
32
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
33
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d1", {
|
|
34
|
+
TAG: "StockReserved",
|
|
35
|
+
orderId: "o2",
|
|
36
|
+
productId: "p2"
|
|
37
|
+
});
|
|
38
|
+
let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
|
|
39
|
+
await ops.processPending();
|
|
40
|
+
globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
|
|
41
|
+
let cmd = MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents[0];
|
|
42
|
+
globalThis.expect(cmd.id).toBe("o2:p2");
|
|
43
|
+
});
|
|
44
|
+
globalThis.test("DCB-source StockReleased after a Processing item is idempotent", async () => {
|
|
45
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
46
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d2", {
|
|
47
|
+
TAG: "StockReserved",
|
|
48
|
+
orderId: "o3",
|
|
49
|
+
productId: "p3"
|
|
50
|
+
});
|
|
51
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d3", {
|
|
52
|
+
TAG: "StockReleased",
|
|
53
|
+
orderId: "o3",
|
|
54
|
+
productId: "p3"
|
|
55
|
+
});
|
|
56
|
+
globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
|
|
57
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
58
|
+
let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
|
|
59
|
+
await ops.processPending();
|
|
60
|
+
globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(0);
|
|
61
|
+
});
|
|
62
|
+
globalThis.test("both sources can drive items into the same TODO list independently", async () => {
|
|
63
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
64
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishAggregateEvent("env-a2", {
|
|
65
|
+
TAG: "OrderShipped",
|
|
66
|
+
orderId: "o4",
|
|
67
|
+
productId: "p4"
|
|
68
|
+
});
|
|
69
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d4", {
|
|
70
|
+
TAG: "StockReserved",
|
|
71
|
+
orderId: "o5",
|
|
72
|
+
productId: "p5"
|
|
73
|
+
});
|
|
74
|
+
let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
|
|
75
|
+
await ops.processPending();
|
|
76
|
+
globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(2);
|
|
77
|
+
let ids = MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.map(c => c.id);
|
|
78
|
+
globalThis.expect(ids.includes("o4:p4")).toBe(true);
|
|
79
|
+
globalThis.expect(ids.includes("o5:p5")).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
globalThis.test("first-writer-wins idempotency across mappings sharing an ID", async () => {
|
|
82
|
+
MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents = [];
|
|
83
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishAggregateEvent("env-a3", {
|
|
84
|
+
TAG: "OrderShipped",
|
|
85
|
+
orderId: "o6",
|
|
86
|
+
productId: "p6"
|
|
87
|
+
});
|
|
88
|
+
await MixedSourceAutomationSliceFixtures$ReventlessLocal.publishDcbEvent("env-d5", {
|
|
89
|
+
TAG: "StockReserved",
|
|
90
|
+
orderId: "o6",
|
|
91
|
+
productId: "p6"
|
|
92
|
+
});
|
|
93
|
+
let ops = await TestRunner$ReventlessLocal.resolve(Component$ReventlessCore.operations(MixedSourceAutomationSliceFixtures$ReventlessLocal.slice));
|
|
94
|
+
await ops.processPending();
|
|
95
|
+
globalThis.expect(MixedSourceAutomationSliceFixtures$ReventlessLocal.publishedCommands.contents.length).toBe(1);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/* Not a pure module */
|