@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,247 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Nodecrypto from "node:crypto";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
7
|
+
import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
|
|
8
|
+
|
|
9
|
+
let defaultUser_groups = ["User"];
|
|
10
|
+
|
|
11
|
+
let defaultUser = {
|
|
12
|
+
userId: "local-user",
|
|
13
|
+
username: "user",
|
|
14
|
+
groups: defaultUser_groups,
|
|
15
|
+
provider: "InMemory"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
let adminUser_groups = [
|
|
19
|
+
"Admin",
|
|
20
|
+
"User"
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
let adminUser = {
|
|
24
|
+
userId: "local-admin",
|
|
25
|
+
username: "admin",
|
|
26
|
+
groups: adminUser_groups,
|
|
27
|
+
provider: "InMemory"
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function initialUsers() {
|
|
31
|
+
return Object.fromEntries([
|
|
32
|
+
[
|
|
33
|
+
"user",
|
|
34
|
+
defaultUser
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
"admin",
|
|
38
|
+
adminUser
|
|
39
|
+
]
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let users = {
|
|
44
|
+
contents: initialUsers()
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function registerUser(username, identity) {
|
|
48
|
+
users.contents[username] = identity;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function resetUsers() {
|
|
52
|
+
users.contents = initialUsers();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function lookupUser(username) {
|
|
56
|
+
return users.contents[username];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseGroups(s) {
|
|
60
|
+
return s.split(",").map(g => g.trim()).filter(g => g !== "");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getHeader(headers, name) {
|
|
64
|
+
return headers[name.toLowerCase()];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let store = {
|
|
68
|
+
contents: {}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function setCredentials(username, password, identity) {
|
|
72
|
+
store.contents[username] = {
|
|
73
|
+
password: password,
|
|
74
|
+
identity: identity
|
|
75
|
+
};
|
|
76
|
+
users.contents[username] = identity;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function resetStore() {
|
|
80
|
+
store.contents = {};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let _secret = {
|
|
84
|
+
contents: undefined
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
function _getSecret() {
|
|
88
|
+
let s = _secret.contents;
|
|
89
|
+
if (s !== undefined) {
|
|
90
|
+
return s;
|
|
91
|
+
}
|
|
92
|
+
let envSecret = process.env["REVENTLESS_INMEMORY_TOKEN_SECRET"];
|
|
93
|
+
let s$1 = envSecret !== undefined && envSecret.length >= 16 ? envSecret : Nodecrypto.randomBytes(32).toString("hex");
|
|
94
|
+
_secret.contents = s$1;
|
|
95
|
+
return s$1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function setTokenSecret(s) {
|
|
99
|
+
_secret.contents = s;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function _sign(payload) {
|
|
103
|
+
return Nodecrypto.createHmac("sha256", _getSecret()).update(payload).digest("base64url");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function _b64urlEncode(s) {
|
|
107
|
+
return btoa(s).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function _b64urlDecode(s) {
|
|
111
|
+
let padLen = (4 - s.length % 4 | 0) % 4;
|
|
112
|
+
let padded = s + "=".repeat(padLen);
|
|
113
|
+
let std = padded.replaceAll("-", "+").replaceAll("_", "/");
|
|
114
|
+
try {
|
|
115
|
+
return atob(std);
|
|
116
|
+
} catch (exn) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function issue(username, password) {
|
|
122
|
+
let match = store.contents[username];
|
|
123
|
+
if (match === undefined) {
|
|
124
|
+
return {
|
|
125
|
+
TAG: "Error",
|
|
126
|
+
_0: "Invalid credentials"
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (match.password !== password) {
|
|
130
|
+
return {
|
|
131
|
+
TAG: "Error",
|
|
132
|
+
_0: "Invalid credentials"
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
let json = JSON.stringify(S.reverseConvertToJsonOrThrow(match.identity, Identity$Reventless.schema));
|
|
136
|
+
let payload = _b64urlEncode(json);
|
|
137
|
+
let sig = _sign(payload);
|
|
138
|
+
return {
|
|
139
|
+
TAG: "Ok",
|
|
140
|
+
_0: payload + `.` + sig
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function verifyAndDecode(token) {
|
|
145
|
+
let parts = token.split(".");
|
|
146
|
+
let match = parts[0];
|
|
147
|
+
let match$1 = parts[1];
|
|
148
|
+
if (match !== undefined && match$1 !== undefined && _sign(match) === match$1) {
|
|
149
|
+
return Stdlib_Option.flatMap(_b64urlDecode(match), json => {
|
|
150
|
+
try {
|
|
151
|
+
return S.parseOrThrow(JSON.parse(json), Identity$Reventless.schema);
|
|
152
|
+
} catch (exn) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let Login = {
|
|
160
|
+
store: store,
|
|
161
|
+
setCredentials: setCredentials,
|
|
162
|
+
resetStore: resetStore,
|
|
163
|
+
_secret: _secret,
|
|
164
|
+
_getSecret: _getSecret,
|
|
165
|
+
setTokenSecret: setTokenSecret,
|
|
166
|
+
_sign: _sign,
|
|
167
|
+
_b64urlEncode: _b64urlEncode,
|
|
168
|
+
_b64urlDecode: _b64urlDecode,
|
|
169
|
+
issue: issue,
|
|
170
|
+
verifyAndDecode: verifyAndDecode
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
function _bearerToken(header) {
|
|
174
|
+
if (header.startsWith("Bearer ")) {
|
|
175
|
+
return header.slice(7, header.length).trim();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function authenticate(ctx) {
|
|
180
|
+
let bearerHeader = Stdlib_Option.flatMap(ctx.headers["Authorization".toLowerCase()], _bearerToken);
|
|
181
|
+
if (bearerHeader !== undefined) {
|
|
182
|
+
let identity = verifyAndDecode(bearerHeader);
|
|
183
|
+
if (identity !== undefined) {
|
|
184
|
+
return {
|
|
185
|
+
TAG: "Authenticated",
|
|
186
|
+
_0: identity
|
|
187
|
+
};
|
|
188
|
+
} else {
|
|
189
|
+
return {
|
|
190
|
+
TAG: "AuthError",
|
|
191
|
+
_0: "Invalid bearer token"
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
let userHeader = ctx.headers["X-User".toLowerCase()];
|
|
196
|
+
let groupsHeader = ctx.headers["X-Groups".toLowerCase()];
|
|
197
|
+
if (userHeader !== undefined) {
|
|
198
|
+
let identity$1 = users.contents[userHeader];
|
|
199
|
+
if (identity$1 === undefined) {
|
|
200
|
+
return "Anonymous";
|
|
201
|
+
}
|
|
202
|
+
let withGroups;
|
|
203
|
+
if (groupsHeader !== undefined) {
|
|
204
|
+
let newrecord = {...identity$1};
|
|
205
|
+
newrecord.groups = parseGroups(groupsHeader);
|
|
206
|
+
withGroups = newrecord;
|
|
207
|
+
} else {
|
|
208
|
+
withGroups = identity$1;
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
TAG: "Authenticated",
|
|
212
|
+
_0: withGroups
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (groupsHeader === undefined) {
|
|
216
|
+
return {
|
|
217
|
+
TAG: "Authenticated",
|
|
218
|
+
_0: defaultUser
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
let newrecord$1 = {...defaultUser};
|
|
222
|
+
return {
|
|
223
|
+
TAG: "Authenticated",
|
|
224
|
+
_0: (newrecord$1.groups = parseGroups(groupsHeader), newrecord$1)
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function make(param, param$1) {
|
|
229
|
+
return Pulumi.output();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export {
|
|
233
|
+
defaultUser,
|
|
234
|
+
adminUser,
|
|
235
|
+
initialUsers,
|
|
236
|
+
users,
|
|
237
|
+
registerUser,
|
|
238
|
+
resetUsers,
|
|
239
|
+
lookupUser,
|
|
240
|
+
parseGroups,
|
|
241
|
+
getHeader,
|
|
242
|
+
Login,
|
|
243
|
+
_bearerToken,
|
|
244
|
+
authenticate,
|
|
245
|
+
make,
|
|
246
|
+
}
|
|
247
|
+
/* users Not a pure module */
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// In-memory user store loader. Hydrates `LocalAuth.Login.store` from
|
|
2
|
+
// three resolution paths (first match wins):
|
|
3
|
+
// 1. `~users` arg — explicit list passed by the caller
|
|
4
|
+
// 2. `~usersFile` arg — explicit YAML path
|
|
5
|
+
// 3. `.reventless/users.yaml` (relative to process.cwd()) — auto-discovery
|
|
6
|
+
//
|
|
7
|
+
// All three are silent on absence: when no path is provided and no default
|
|
8
|
+
// file exists, the store stays empty and `LocalAuth.Login.issue` rejects
|
|
9
|
+
// every credential. A one-line stdout hint is printed so developers know to
|
|
10
|
+
// either set the file or pass `~users` programmatically.
|
|
11
|
+
|
|
12
|
+
open Reventless
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* One YAML entry. `groups` is required (use `[]` for an unprivileged user);
|
|
16
|
+
* `userId` defaults to the username when omitted.
|
|
17
|
+
*/
|
|
18
|
+
@schema
|
|
19
|
+
type entry = {
|
|
20
|
+
username: string,
|
|
21
|
+
password: string,
|
|
22
|
+
groups: array<string>,
|
|
23
|
+
userId?: string,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ── YAML parsing (eemeli/yaml) ──────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
@module("yaml") external _yamlParse: string => unknown = "parse"
|
|
29
|
+
@module("node:fs") external _readFileSync: (string, string) => string = "readFileSync"
|
|
30
|
+
@module("node:fs") external _existsSync: string => bool = "existsSync"
|
|
31
|
+
@module("node:path") external _join: (string, string) => string = "join"
|
|
32
|
+
@val external _processCwd: unit => string = "process.cwd"
|
|
33
|
+
|
|
34
|
+
let _entriesSchema = S.array(entrySchema)
|
|
35
|
+
|
|
36
|
+
/** Parses a YAML document string into entries (best-effort). */
|
|
37
|
+
let parseString = (yamlText: string): result<array<entry>, string> =>
|
|
38
|
+
try {
|
|
39
|
+
let json = _yamlParse(yamlText)->Obj.magic
|
|
40
|
+
Ok(S.parseOrThrow(json, _entriesSchema))
|
|
41
|
+
} catch {
|
|
42
|
+
| JsExn(err) => Error(JsExn.message(err)->Option.getOr("YAML parse error"))
|
|
43
|
+
| _ => Error("YAML parse error")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Reads + parses a YAML file. */
|
|
47
|
+
let parseFile = (path: string): result<array<entry>, string> =>
|
|
48
|
+
try {
|
|
49
|
+
let text = _readFileSync(path, "utf8")
|
|
50
|
+
parseString(text)
|
|
51
|
+
} catch {
|
|
52
|
+
| JsExn(err) => Error(JsExn.message(err)->Option.getOr(`Cannot read ${path}`))
|
|
53
|
+
| _ => Error(`Cannot read ${path}`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Resolution & loading ────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
let _registerEntries = (entries: array<entry>): unit =>
|
|
59
|
+
entries->Array.forEach(({username, password, groups, ?userId}) => {
|
|
60
|
+
let id: Identity.t = {
|
|
61
|
+
userId: userId->Option.getOr(username),
|
|
62
|
+
username,
|
|
63
|
+
groups,
|
|
64
|
+
provider: InMemory,
|
|
65
|
+
}
|
|
66
|
+
LocalAuth.Login.setCredentials(~username, ~password, ~identity=id)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
let _defaultPath = (): string => _join(_processCwd(), ".reventless/users.yaml")
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Hydrates the Login store. Returns the resolution path actually used
|
|
73
|
+
* (`InlineUsers`, `UsersFile(path)`, `DefaultFile(path)`, or `Empty`).
|
|
74
|
+
* Errors from a *resolved* path are returned as `Error`; absence of the
|
|
75
|
+
* auto-discovered default file is silent.
|
|
76
|
+
*/
|
|
77
|
+
type resolution =
|
|
78
|
+
| InlineUsers
|
|
79
|
+
| UsersFile(string)
|
|
80
|
+
| DefaultFile(string)
|
|
81
|
+
| Empty
|
|
82
|
+
|
|
83
|
+
// Set on the first `load` call so `autoLoadOnce()` is a no-op once a caller
|
|
84
|
+
// has explicitly provided users. Tests can also flip it manually to suppress
|
|
85
|
+
// auto-discovery before `Platform.startServers`.
|
|
86
|
+
let resolved: ref<bool> = ref(false)
|
|
87
|
+
|
|
88
|
+
let resetResolution = (): unit => resolved := false
|
|
89
|
+
|
|
90
|
+
let load = (
|
|
91
|
+
~users: option<array<entry>>=?,
|
|
92
|
+
~usersFile: option<string>=?,
|
|
93
|
+
(),
|
|
94
|
+
): result<resolution, string> => {
|
|
95
|
+
resolved := true
|
|
96
|
+
switch users {
|
|
97
|
+
| Some(entries) =>
|
|
98
|
+
_registerEntries(entries)
|
|
99
|
+
Ok(InlineUsers)
|
|
100
|
+
| None =>
|
|
101
|
+
switch usersFile {
|
|
102
|
+
| Some(path) =>
|
|
103
|
+
parseFile(path)->Result.map(entries => {
|
|
104
|
+
_registerEntries(entries)
|
|
105
|
+
UsersFile(path)
|
|
106
|
+
})
|
|
107
|
+
| None =>
|
|
108
|
+
let defaultPath = _defaultPath()
|
|
109
|
+
if _existsSync(defaultPath) {
|
|
110
|
+
parseFile(defaultPath)->Result.map(entries => {
|
|
111
|
+
_registerEntries(entries)
|
|
112
|
+
DefaultFile(defaultPath)
|
|
113
|
+
})
|
|
114
|
+
} else {
|
|
115
|
+
Console.log(
|
|
116
|
+
"[LocalAuth] no users configured — POST /__inmemory/login will reject all. " ++
|
|
117
|
+
"Provide ~users / ~usersFile or create .reventless/users.yaml relative to cwd.",
|
|
118
|
+
)
|
|
119
|
+
Ok(Empty)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Idempotent auto-discovery. Platform.startServers calls this before
|
|
127
|
+
* `DomainGraphQL_Server.start`, so a `.reventless/users.yaml` in cwd
|
|
128
|
+
* hydrates the Login store automatically. No-op once `load` has been
|
|
129
|
+
* called from anywhere.
|
|
130
|
+
*/
|
|
131
|
+
let autoLoadOnce = (): unit =>
|
|
132
|
+
if !resolved.contents {
|
|
133
|
+
let _ = load()
|
|
134
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Yaml from "yaml";
|
|
5
|
+
import * as Nodefs from "node:fs";
|
|
6
|
+
import * as Nodepath from "node:path";
|
|
7
|
+
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
8
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
9
|
+
import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
|
|
10
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
11
|
+
import * as LocalAuth$ReventlessLocal from "./LocalAuth.res.mjs";
|
|
12
|
+
|
|
13
|
+
let entrySchema = S.schema(s => ({
|
|
14
|
+
username: s.m(S.string),
|
|
15
|
+
password: s.m(S.string),
|
|
16
|
+
groups: s.m(S.array(S.string)),
|
|
17
|
+
userId: s.m(S.option(S.string))
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
let _entriesSchema = S.array(entrySchema);
|
|
21
|
+
|
|
22
|
+
function parseString(yamlText) {
|
|
23
|
+
try {
|
|
24
|
+
let json = Yaml.parse(yamlText);
|
|
25
|
+
return {
|
|
26
|
+
TAG: "Ok",
|
|
27
|
+
_0: S.parseOrThrow(json, _entriesSchema)
|
|
28
|
+
};
|
|
29
|
+
} catch (raw_err) {
|
|
30
|
+
let err = Primitive_exceptions.internalToException(raw_err);
|
|
31
|
+
if (err.RE_EXN_ID === "JsExn") {
|
|
32
|
+
return {
|
|
33
|
+
TAG: "Error",
|
|
34
|
+
_0: Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), "YAML parse error")
|
|
35
|
+
};
|
|
36
|
+
} else {
|
|
37
|
+
return {
|
|
38
|
+
TAG: "Error",
|
|
39
|
+
_0: "YAML parse error"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function parseFile(path) {
|
|
46
|
+
try {
|
|
47
|
+
return parseString(Nodefs.readFileSync(path, "utf8"));
|
|
48
|
+
} catch (raw_err) {
|
|
49
|
+
let err = Primitive_exceptions.internalToException(raw_err);
|
|
50
|
+
if (err.RE_EXN_ID === "JsExn") {
|
|
51
|
+
return {
|
|
52
|
+
TAG: "Error",
|
|
53
|
+
_0: Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), `Cannot read ` + path)
|
|
54
|
+
};
|
|
55
|
+
} else {
|
|
56
|
+
return {
|
|
57
|
+
TAG: "Error",
|
|
58
|
+
_0: `Cannot read ` + path
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function _registerEntries(entries) {
|
|
65
|
+
entries.forEach(param => {
|
|
66
|
+
let username = param.username;
|
|
67
|
+
let id_userId = Stdlib_Option.getOr(param.userId, username);
|
|
68
|
+
let id_groups = param.groups;
|
|
69
|
+
let id = {
|
|
70
|
+
userId: id_userId,
|
|
71
|
+
username: username,
|
|
72
|
+
groups: id_groups,
|
|
73
|
+
provider: "InMemory"
|
|
74
|
+
};
|
|
75
|
+
LocalAuth$ReventlessLocal.Login.setCredentials(username, param.password, id);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function _defaultPath() {
|
|
80
|
+
return Nodepath.join(process.cwd(), ".reventless/users.yaml");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let resolved = {
|
|
84
|
+
contents: false
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
function resetResolution() {
|
|
88
|
+
resolved.contents = false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function load(users, usersFile, param) {
|
|
92
|
+
resolved.contents = true;
|
|
93
|
+
if (users !== undefined) {
|
|
94
|
+
_registerEntries(users);
|
|
95
|
+
return {
|
|
96
|
+
TAG: "Ok",
|
|
97
|
+
_0: "InlineUsers"
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (usersFile !== undefined) {
|
|
101
|
+
return Stdlib_Result.map(parseFile(usersFile), entries => {
|
|
102
|
+
_registerEntries(entries);
|
|
103
|
+
return {
|
|
104
|
+
TAG: "UsersFile",
|
|
105
|
+
_0: usersFile
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
let defaultPath = Nodepath.join(process.cwd(), ".reventless/users.yaml");
|
|
110
|
+
if (Nodefs.existsSync(defaultPath)) {
|
|
111
|
+
return Stdlib_Result.map(parseFile(defaultPath), entries => {
|
|
112
|
+
_registerEntries(entries);
|
|
113
|
+
return {
|
|
114
|
+
TAG: "DefaultFile",
|
|
115
|
+
_0: defaultPath
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
console.log("[LocalAuth] no users configured — POST /__inmemory/login will reject all. Provide ~users / ~usersFile or create .reventless/users.yaml relative to cwd.");
|
|
120
|
+
return {
|
|
121
|
+
TAG: "Ok",
|
|
122
|
+
_0: "Empty"
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function autoLoadOnce() {
|
|
128
|
+
if (!resolved.contents) {
|
|
129
|
+
load(undefined, undefined, undefined);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
entrySchema,
|
|
136
|
+
_entriesSchema,
|
|
137
|
+
parseString,
|
|
138
|
+
parseFile,
|
|
139
|
+
_registerEntries,
|
|
140
|
+
_defaultPath,
|
|
141
|
+
resolved,
|
|
142
|
+
resetResolution,
|
|
143
|
+
load,
|
|
144
|
+
autoLoadOnce,
|
|
145
|
+
}
|
|
146
|
+
/* entrySchema Not a pure module */
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Selects which storage backend the in-memory Platform uses.
|
|
2
|
+
//
|
|
3
|
+
// Memory — pure in-memory dicts/refs, current default behaviour, wiped on restart.
|
|
4
|
+
// Sqlite — opt-in on-disk SQLite file via SqliteDriver. Survives process restart.
|
|
5
|
+
// resetOnStart=true wipes the file when the Platform is constructed.
|
|
6
|
+
|
|
7
|
+
type t =
|
|
8
|
+
| Memory
|
|
9
|
+
| Sqlite({path: string, resetOnStart: bool})
|
|
10
|
+
|
|
11
|
+
let memory = Memory
|
|
12
|
+
let sqlite = (~path, ~resetOnStart=false) => Sqlite({path, resetOnStart})
|
|
13
|
+
|
|
14
|
+
@val external processEnv: dict<string> = "process.env"
|
|
15
|
+
|
|
16
|
+
// Deletes a file if it exists. No-op if the path is missing.
|
|
17
|
+
@module("node:fs") external _unlinkSync: string => unit = "unlinkSync"
|
|
18
|
+
|
|
19
|
+
let removeFileIfExists = (path: string) =>
|
|
20
|
+
try _unlinkSync(path) catch {
|
|
21
|
+
| _ => ()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Parses REVENTLESS_LOCAL_BACKEND. Recognised forms:
|
|
25
|
+
// sqlite:./local.db — Sqlite backend, no reset on start
|
|
26
|
+
// sqlite:./local.db?reset — Sqlite backend, wipes file at Platform.Make time
|
|
27
|
+
// memory — explicit Memory selector
|
|
28
|
+
// Anything else (including unset) yields Memory.
|
|
29
|
+
let fromEnv = () =>
|
|
30
|
+
switch processEnv->Dict.get("REVENTLESS_LOCAL_BACKEND") {
|
|
31
|
+
| None => Memory
|
|
32
|
+
| Some(raw) =>
|
|
33
|
+
let trimmed = raw->String.trim
|
|
34
|
+
if trimmed == "" || trimmed == "memory" {
|
|
35
|
+
Memory
|
|
36
|
+
} else if trimmed->String.startsWith("sqlite:") {
|
|
37
|
+
let rest = trimmed->String.slice(~start=String.length("sqlite:"), ~end=String.length(trimmed))
|
|
38
|
+
let (path, resetOnStart) = switch rest->String.split("?") {
|
|
39
|
+
| [p, q] => (p, q->String.split("&")->Array.includes("reset"))
|
|
40
|
+
| _ => (rest, false)
|
|
41
|
+
}
|
|
42
|
+
Sqlite({path, resetOnStart})
|
|
43
|
+
} else {
|
|
44
|
+
Memory
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodefs from "node:fs";
|
|
4
|
+
|
|
5
|
+
function sqlite(path, resetOnStartOpt) {
|
|
6
|
+
let resetOnStart = resetOnStartOpt !== undefined ? resetOnStartOpt : false;
|
|
7
|
+
return {
|
|
8
|
+
TAG: "Sqlite",
|
|
9
|
+
path: path,
|
|
10
|
+
resetOnStart: resetOnStart
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function removeFileIfExists(path) {
|
|
15
|
+
try {
|
|
16
|
+
Nodefs.unlinkSync(path);
|
|
17
|
+
return;
|
|
18
|
+
} catch (exn) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function fromEnv() {
|
|
24
|
+
let raw = process.env["REVENTLESS_LOCAL_BACKEND"];
|
|
25
|
+
if (raw === undefined) {
|
|
26
|
+
return "Memory";
|
|
27
|
+
}
|
|
28
|
+
let trimmed = raw.trim();
|
|
29
|
+
if (trimmed === "" || trimmed === "memory") {
|
|
30
|
+
return "Memory";
|
|
31
|
+
}
|
|
32
|
+
if (!trimmed.startsWith("sqlite:")) {
|
|
33
|
+
return "Memory";
|
|
34
|
+
}
|
|
35
|
+
let rest = trimmed.slice("sqlite:".length, trimmed.length);
|
|
36
|
+
let match = rest.split("?");
|
|
37
|
+
let match$1;
|
|
38
|
+
if (match.length !== 2) {
|
|
39
|
+
match$1 = [
|
|
40
|
+
rest,
|
|
41
|
+
false
|
|
42
|
+
];
|
|
43
|
+
} else {
|
|
44
|
+
let p = match[0];
|
|
45
|
+
let q = match[1];
|
|
46
|
+
match$1 = [
|
|
47
|
+
p,
|
|
48
|
+
q.split("&").includes("reset")
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
TAG: "Sqlite",
|
|
53
|
+
path: match$1[0],
|
|
54
|
+
resetOnStart: match$1[1]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let memory = "Memory";
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
memory,
|
|
62
|
+
sqlite,
|
|
63
|
+
removeFileIfExists,
|
|
64
|
+
fromEnv,
|
|
65
|
+
}
|
|
66
|
+
/* node:fs Not a pure module */
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Module-level state for the active storage backend.
|
|
2
|
+
//
|
|
3
|
+
// Platform.MakeWithConfig sets this once at construction based on Backend.t.
|
|
4
|
+
// Downstream adapters (EventLogStorage_InMemory, QueryDbStorage_InMemory, ...)
|
|
5
|
+
// read it inside their `make` to decide whether to allocate an in-memory dict
|
|
6
|
+
// or delegate to the SQLite-backed implementation.
|
|
7
|
+
//
|
|
8
|
+
// This trick exists because the core builder functors accept a single
|
|
9
|
+
// storageMaker module; we dispatch at runtime instead of at functor-application
|
|
10
|
+
// time so callers don't need to pick a builder per backend.
|
|
11
|
+
|
|
12
|
+
type active =
|
|
13
|
+
| Memory
|
|
14
|
+
| Sqlite({db: SqliteDriver.t, path: string})
|
|
15
|
+
|
|
16
|
+
let current: ref<active> = ref(Memory)
|
|
17
|
+
|
|
18
|
+
let setMemory = () => current := Memory
|
|
19
|
+
|
|
20
|
+
let setSqlite = (~db, ~path) => current := Sqlite({db, path})
|
|
21
|
+
|
|
22
|
+
let getDb = () =>
|
|
23
|
+
switch current.contents {
|
|
24
|
+
| Sqlite({db}) => Some(db)
|
|
25
|
+
| Memory => None
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// True when the active backend is SQLite — used by adapters that want to swap
|
|
29
|
+
// their implementation entirely, not just their data access.
|
|
30
|
+
let isSqlite = () =>
|
|
31
|
+
switch current.contents {
|
|
32
|
+
| Sqlite(_) => true
|
|
33
|
+
| Memory => false
|
|
34
|
+
}
|