@reventlessdev/reventless-aws 3.0.0-alpha.167
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 +1564 -0
- package/README.md +62 -0
- package/__mocks__/emptyModule.js +1 -0
- package/all-licenses.csv +565 -0
- package/docker-compose.dynamodb-local.yml +12 -0
- package/jest.setup.cjs +5 -0
- package/licenses-analysis.ods +0 -0
- package/package.json +73 -0
- package/rescript.json +39 -0
- package/reventless-licenses-analysis.xls +0 -0
- package/scripts/run-integration-tests.sh +43 -0
- package/src/Platform.res +1940 -0
- package/src/Platform.res.mjs +2281 -0
- package/src/Platform_Casts.res +106 -0
- package/src/Platform_Casts.res.mjs +13 -0
- package/src/Platform_Stack.res +153 -0
- package/src/Platform_Stack.res.mjs +121 -0
- package/src/Types.res +39 -0
- package/src/Types.res.mjs +21 -0
- package/src/adapter/AWS.res +96 -0
- package/src/adapter/AWS.res.mjs +186 -0
- package/src/adapter/AWS_Tags.res +16 -0
- package/src/adapter/AWS_Tags.res.mjs +48 -0
- package/src/adapter/Adapter_Helpers.res +19 -0
- package/src/adapter/Adapter_Helpers.res.mjs +37 -0
- package/src/adapter/Api/AppSync_EventsApi.res +172 -0
- package/src/adapter/Api/AppSync_EventsApi.res.mjs +96 -0
- package/src/adapter/Api/AppSync_Resolver_Native.res +93 -0
- package/src/adapter/Api/AppSync_Resolver_Native.res.mjs +67 -0
- package/src/adapter/Api/AppSync_Resolver_Retrying.res +653 -0
- package/src/adapter/Api/AppSync_Resolver_Retrying.res.mjs +462 -0
- package/src/adapter/Api/CommandSubscriptionResolvers_AppSync.res +29 -0
- package/src/adapter/Api/CommandSubscriptionResolvers_AppSync.res.mjs +15 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +238 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +179 -0
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +229 -0
- package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +245 -0
- package/src/adapter/Auth/Auth_Cognito.res +209 -0
- package/src/adapter/Auth/Auth_Cognito.res.mjs +135 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers.res +2 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers.res.mjs +12 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +251 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res.mjs +126 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +20 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res.mjs +23 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_Runtime.res +1 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_Runtime.res.mjs +11 -0
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +95 -0
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res.mjs +50 -0
- package/src/adapter/CommandTopic/CommandTopicChannel.res +6 -0
- package/src/adapter/CommandTopic/CommandTopicChannel.res.mjs +21 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_Helpers.res +196 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_Helpers.res.mjs +145 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +91 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res.mjs +74 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +69 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res.mjs +62 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +60 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res.mjs +56 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +73 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res.mjs +65 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +88 -0
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res.mjs +76 -0
- package/src/adapter/CommandTopic/CommandTopicRemoteChannel.res +1 -0
- package/src/adapter/CommandTopic/CommandTopicRemoteChannel.res.mjs +9 -0
- package/src/adapter/CommandTopic/CommandTopicRemoteChannel_SQS.res +7 -0
- package/src/adapter/CommandTopic/CommandTopicRemoteChannel_SQS.res.mjs +17 -0
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +103 -0
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res.mjs +68 -0
- package/src/adapter/Counter/CounterHandler_DynamoDbStream_Runtime.res +107 -0
- package/src/adapter/Counter/CounterHandler_DynamoDbStream_Runtime.res.mjs +145 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage.res +1 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage.res.mjs +9 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +84 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res.mjs +52 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +1436 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +1143 -0
- package/src/adapter/EventCollector/EventCollectorChannel.res +6 -0
- package/src/adapter/EventCollector/EventCollectorChannel.res.mjs +21 -0
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +63 -0
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res.mjs +56 -0
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res +20 -0
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res.mjs +32 -0
- package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +266 -0
- package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res.mjs +166 -0
- package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +81 -0
- package/src/adapter/EventCollector/EventCollectorChannel_SQS.res.mjs +54 -0
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +59 -0
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res.mjs +45 -0
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +91 -0
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res.mjs +89 -0
- package/src/adapter/EventLog/EventLogStorage.res +3 -0
- package/src/adapter/EventLog/EventLogStorage.res.mjs +15 -0
- package/src/adapter/EventLog/EventLogStorage_DynamoDb.res +25 -0
- package/src/adapter/EventLog/EventLogStorage_DynamoDb.res.mjs +34 -0
- package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +26 -0
- package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res.mjs +35 -0
- package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +121 -0
- package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res.mjs +137 -0
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +265 -0
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +185 -0
- package/src/adapter/EventTopic/EventTopicPublisher.res +6 -0
- package/src/adapter/EventTopic/EventTopicPublisher.res.mjs +21 -0
- package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +25 -0
- package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res.mjs +28 -0
- package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +40 -0
- package/src/adapter/EventTopic/EventTopicPublisher_SNS.res.mjs +39 -0
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +39 -0
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res.mjs +38 -0
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -0
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res.mjs +18 -0
- package/src/adapter/Mcp/MCP_Lambda.res +502 -0
- package/src/adapter/Mcp/MCP_Lambda.res.mjs +289 -0
- package/src/adapter/QueryDb/NodeResolver_AppSync.res +71 -0
- package/src/adapter/QueryDb/NodeResolver_AppSync.res.mjs +44 -0
- package/src/adapter/QueryDb/QueryDbResolvers.res +2 -0
- package/src/adapter/QueryDb/QueryDbResolvers.res.mjs +12 -0
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +434 -0
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs +243 -0
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync_NoOp.res +21 -0
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync_NoOp.res.mjs +14 -0
- package/src/adapter/QueryDb/QueryDbResolvers_NoOp.res +21 -0
- package/src/adapter/QueryDb/QueryDbResolvers_NoOp.res.mjs +14 -0
- package/src/adapter/QueryDb/QueryDbStorage.res +5 -0
- package/src/adapter/QueryDb/QueryDbStorage.res.mjs +18 -0
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +115 -0
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res.mjs +100 -0
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +52 -0
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res.mjs +38 -0
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +271 -0
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res.mjs +306 -0
- package/src/adapter/QueryDb/QueryInterceptor_Lambda.res +20 -0
- package/src/adapter/QueryDb/QueryInterceptor_Lambda.res.mjs +22 -0
- package/src/adapter/QueryEngine/QueryEngine.res +3 -0
- package/src/adapter/QueryEngine/QueryEngine.res.mjs +12 -0
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +184 -0
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res.mjs +221 -0
- package/src/adapter/Runtime/AdminEventCollectorEntryPoint.mjs +879 -0
- package/src/adapter/Runtime/AggregateEntryPoint.mjs +313 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +327 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +239 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +331 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res.mjs +240 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +247 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res.mjs +185 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +244 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res.mjs +185 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +347 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +244 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +285 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res.mjs +212 -0
- package/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +124 -0
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +187 -0
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +147 -0
- package/src/adapter/Runtime/CounterEntryPoint.mjs +91 -0
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +265 -0
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +122 -0
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +89 -0
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +193 -0
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +137 -0
- package/src/adapter/Runtime/EventMapperEntryPoint.mjs +97 -0
- package/src/adapter/Runtime/ExtensionPointEntryPoint.mjs +101 -0
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +83 -0
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +59 -0
- package/src/adapter/Runtime/HandlerFactoryHelpers.mjs +142 -0
- package/src/adapter/Runtime/HeartbeatEntryPoint.mjs +38 -0
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.mjs +137 -0
- package/src/adapter/Runtime/ReadModelEntryPoint.mjs +143 -0
- package/src/adapter/Runtime/RuntimeEnvironment.res +1 -0
- package/src/adapter/Runtime/RuntimeEnvironment.res.mjs +9 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +254 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +169 -0
- package/src/adapter/Runtime/SideEffectEntryPoint.mjs +81 -0
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +178 -0
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res.mjs +129 -0
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +166 -0
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +87 -0
- package/src/adapter/Runtime/StateViewSliceEntryPoint.mjs +136 -0
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +344 -0
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs +242 -0
- package/src/adapter/Runtime/TaskBucketEntryPoint.mjs +150 -0
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +123 -0
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res.mjs +74 -0
- package/src/adapter/ScheduledPublisher/ScheduledPublisher.res +2 -0
- package/src/adapter/ScheduledPublisher/ScheduledPublisher.res.mjs +12 -0
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +54 -0
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res.mjs +41 -0
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +97 -0
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res.mjs +85 -0
- package/src/adapter/StateTopic/StateTopic_AppSync.res +418 -0
- package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +295 -0
- package/src/adapter/Task/TaskBucket.res +1 -0
- package/src/adapter/Task/TaskBucket.res.mjs +9 -0
- package/src/adapter/Task/TaskBucket_S3.res +157 -0
- package/src/adapter/Task/TaskBucket_S3.res.mjs +108 -0
- package/src/adapter/Task/TaskBucket_S3_Runtime.res +11 -0
- package/src/adapter/Task/TaskBucket_S3_Runtime.res.mjs +15 -0
- package/src/components/Aggregate_Builder.res +1 -0
- package/src/components/Aggregate_Builder.res.mjs +25 -0
- package/src/components/Aggregate_Builder_Micro.res +63 -0
- package/src/components/Aggregate_Builder_Micro.res.mjs +80 -0
- package/src/components/Aggregate_Builder_NoResolver.res +61 -0
- package/src/components/Aggregate_Builder_NoResolver.res.mjs +80 -0
- package/src/components/Aggregate_Builder_PerAggregate.res +57 -0
- package/src/components/Aggregate_Builder_PerAggregate.res.mjs +80 -0
- package/src/components/Aggregate_Builder_Single.res +59 -0
- package/src/components/Aggregate_Builder_Single.res.mjs +80 -0
- package/src/components/Aggregate_Builder_Single_Async.res +59 -0
- package/src/components/Aggregate_Builder_Single_Async.res.mjs +80 -0
- package/src/components/Api/AppSync_Adapter.res +500 -0
- package/src/components/Api/AppSync_Adapter.res.mjs +396 -0
- package/src/components/AutomationSlice_Builder.res +52 -0
- package/src/components/AutomationSlice_Builder.res.mjs +72 -0
- package/src/components/AutomationSlice_Builder_Bundled.res.mjs +70 -0
- package/src/components/Counter_Builder.res +10 -0
- package/src/components/Counter_Builder.res.mjs +16 -0
- package/src/components/DataCleaner.res +170 -0
- package/src/components/DataCleaner.res.mjs +2 -0
- package/src/components/DcbEventLog_Builder.res +8 -0
- package/src/components/DcbEventLog_Builder.res.mjs +14 -0
- package/src/components/ExtensionPoint_Builder.res +16 -0
- package/src/components/ExtensionPoint_Builder.res.mjs +37 -0
- package/src/components/ForeignReadModel_Builder.res +19 -0
- package/src/components/ForeignReadModel_Builder.res.mjs +48 -0
- package/src/components/InboundTranslationSlice_Builder.res +25 -0
- package/src/components/InboundTranslationSlice_Builder.res.mjs +31 -0
- package/src/components/OutboundTranslationSlice_Builder.res +60 -0
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +76 -0
- package/src/components/OutboundTranslationSlice_Builder_Bundled.res.mjs +75 -0
- package/src/components/Plugin.res +29 -0
- package/src/components/Plugin.res.mjs +63 -0
- package/src/components/ReadModel_Builder.res +1 -0
- package/src/components/ReadModel_Builder.res.mjs +19 -0
- package/src/components/ReadModel_Builder_NoResolver.res +55 -0
- package/src/components/ReadModel_Builder_NoResolver.res.mjs +64 -0
- package/src/components/ReadModel_Builder_NoResolver_Stream.res +60 -0
- package/src/components/ReadModel_Builder_NoResolver_Stream.res.mjs +64 -0
- package/src/components/ReadModel_Builder_PerReadModel.res +53 -0
- package/src/components/ReadModel_Builder_PerReadModel.res.mjs +66 -0
- package/src/components/ReadModel_Builder_Single.res +52 -0
- package/src/components/ReadModel_Builder_Single.res.mjs +66 -0
- package/src/components/ReadModel_Builder_Single_Stream.res +60 -0
- package/src/components/ReadModel_Builder_Single_Stream.res.mjs +66 -0
- package/src/components/Scheduler.res +1 -0
- package/src/components/Scheduler.res.mjs +13 -0
- package/src/components/SideEffectHandler.res +1 -0
- package/src/components/SideEffectHandler.res.mjs +19 -0
- package/src/components/SideEffectHandler_PerSideEffectHandler.res +13 -0
- package/src/components/SideEffectHandler_PerSideEffectHandler.res.mjs +52 -0
- package/src/components/SideEffectHandler_Single.res +54 -0
- package/src/components/SideEffectHandler_Single.res.mjs +60 -0
- package/src/components/StateChangeSlice_Builder.res +17 -0
- package/src/components/StateChangeSlice_Builder.res.mjs +23 -0
- package/src/components/StateViewSlice_Builder.res +46 -0
- package/src/components/StateViewSlice_Builder.res.mjs +68 -0
- package/src/components/StateViewSlice_Builder_Bundled.res.mjs +69 -0
- package/src/components/StateViewSlice_Builder_Stream.res +50 -0
- package/src/components/StateViewSlice_Builder_Stream.res.mjs +68 -0
- package/src/components/Task_Builder.res +1 -0
- package/src/components/Task_Builder.res.mjs +28 -0
- package/src/components/Task_Builder_PerBucket.res +22 -0
- package/src/components/Task_Builder_PerBucket.res.mjs +63 -0
- package/src/components/Vpc.res +214 -0
- package/src/components/Vpc.res.mjs +117 -0
- package/src/components/Vpc.resi +22 -0
- package/src/errors/AppSync_Error.res +36 -0
- package/src/errors/AppSync_Error.res.mjs +38 -0
- package/src/errors/Cognito_Error.res +36 -0
- package/src/errors/Cognito_Error.res.mjs +38 -0
- package/src/errors/DynamoDb_Error.res +75 -0
- package/src/errors/DynamoDb_Error.res.mjs +86 -0
- package/src/errors/Kinesis_Error.res +36 -0
- package/src/errors/Kinesis_Error.res.mjs +38 -0
- package/src/errors/SNS_Error.res +34 -0
- package/src/errors/SNS_Error.res.mjs +38 -0
- package/src/errors/SQS_Error.res +40 -0
- package/src/errors/SQS_Error.res.mjs +41 -0
- package/src/plugin/cloner/ClonerRunner.res +1 -0
- package/src/plugin/cloner/ClonerRunner.res.mjs +9 -0
- package/src/plugin/cloner/ClonerRunner_Fargate.res +362 -0
- package/src/plugin/cloner/ClonerRunner_Fargate.res.mjs +246 -0
- package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +42 -0
- package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res.mjs +45 -0
- package/src/plugin/heartbeat/HeartbeatRunner.res +1 -0
- package/src/plugin/heartbeat/HeartbeatRunner.res.mjs +9 -0
- package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +96 -0
- package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res.mjs +69 -0
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +115 -0
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +88 -0
- package/src/plugin/runtime/PluginRuntimeOperations.res +5 -0
- package/src/plugin/runtime/PluginRuntimeOperations.res.mjs +14 -0
- package/src/plugin/runtime/PluginRuntime_Builder.res +769 -0
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +464 -0
- package/src/plugin/runtime/Util_PluginMessage_Runtime.res +13 -0
- package/src/plugin/runtime/Util_PluginMessage_Runtime.res.mjs +19 -0
- package/src/plugin/stack/Plugin_ExtensionPoint_Builder.res +28 -0
- package/src/plugin/stack/Plugin_ExtensionPoint_Builder.res.mjs +67 -0
- package/src/plugin/stack/Plugin_Stack.res +439 -0
- package/src/plugin/stack/Plugin_Stack.res.mjs +263 -0
- package/src/util/Util.res +29 -0
- package/src/util/Util.res.mjs +93 -0
- package/src/util/Util_AppSync.res +36 -0
- package/src/util/Util_AppSync.res.mjs +35 -0
- package/src/util/Util_AppSync_Caller.res +213 -0
- package/src/util/Util_AppSync_Caller.res.mjs +170 -0
- package/src/util/Util_Bundle.res +255 -0
- package/src/util/Util_Bundle.res.mjs +179 -0
- package/src/util/Util_Cloudwatch.res +14 -0
- package/src/util/Util_Cloudwatch.res.mjs +19 -0
- package/src/util/Util_CognitoGroupUser.res +39 -0
- package/src/util/Util_CognitoGroupUser.res.mjs +32 -0
- package/src/util/Util_CognitoGroupUser_Runtime.res +65 -0
- package/src/util/Util_CognitoGroupUser_Runtime.res.mjs +50 -0
- package/src/util/Util_Cognito_Runtime.res +52 -0
- package/src/util/Util_Cognito_Runtime.res.mjs +35 -0
- package/src/util/Util_DeadLetterQueue.res +154 -0
- package/src/util/Util_DeadLetterQueue.res.mjs +158 -0
- package/src/util/Util_DynamoDb.res +210 -0
- package/src/util/Util_DynamoDb.res.mjs +218 -0
- package/src/util/Util_DynamoDbStream.res +138 -0
- package/src/util/Util_DynamoDbStream.res.mjs +134 -0
- package/src/util/Util_DynamoDbStream_Runtime.res +94 -0
- package/src/util/Util_DynamoDbStream_Runtime.res.mjs +131 -0
- package/src/util/Util_DynamoDb_Runtime.res +216 -0
- package/src/util/Util_DynamoDb_Runtime.res.mjs +257 -0
- package/src/util/Util_DynamoDb_TableManager.res +23 -0
- package/src/util/Util_DynamoDb_TableManager.res.mjs +35 -0
- package/src/util/Util_DynamoDb_TableManager.resi +3 -0
- package/src/util/Util_Env.res +5 -0
- package/src/util/Util_Env.res.mjs +2 -0
- package/src/util/Util_EventSourceMapping.res +49 -0
- package/src/util/Util_EventSourceMapping.res.mjs +32 -0
- package/src/util/Util_HostUiDomain.res +28 -0
- package/src/util/Util_HostUiDomain.res.mjs +26 -0
- package/src/util/Util_IAM_Role.res +14 -0
- package/src/util/Util_IAM_Role.res.mjs +28 -0
- package/src/util/Util_Kinesis_Runtime.res +20 -0
- package/src/util/Util_Kinesis_Runtime.res.mjs +24 -0
- package/src/util/Util_Lambda.res +39 -0
- package/src/util/Util_Lambda.res.mjs +45 -0
- package/src/util/Util_LocalConfig.res +119 -0
- package/src/util/Util_LocalConfig.res.mjs +112 -0
- package/src/util/Util_ResourceNaming.res +15 -0
- package/src/util/Util_ResourceNaming.res.mjs +26 -0
- package/src/util/Util_S3.res +17 -0
- package/src/util/Util_S3.res.mjs +30 -0
- package/src/util/Util_S3_Runtime.res +11 -0
- package/src/util/Util_S3_Runtime.res.mjs +15 -0
- package/src/util/Util_SNS.res +33 -0
- package/src/util/Util_SNS.res.mjs +50 -0
- package/src/util/Util_SNS_FIFO.res +21 -0
- package/src/util/Util_SNS_FIFO.res.mjs +27 -0
- package/src/util/Util_SNS_Runtime.res +33 -0
- package/src/util/Util_SNS_Runtime.res.mjs +27 -0
- package/src/util/Util_SQS.res +70 -0
- package/src/util/Util_SQS.res.mjs +83 -0
- package/src/util/Util_SQS_FIFO.res +16 -0
- package/src/util/Util_SQS_FIFO.res.mjs +28 -0
- package/src/util/Util_SQS_Runtime.res +169 -0
- package/src/util/Util_SQS_Runtime.res.mjs +150 -0
- package/src/util/Util_SesPolicy_Runtime.res +54 -0
- package/src/util/Util_SesPolicy_Runtime.res.mjs +55 -0
- package/src/util/Util_StaticBundle.res +124 -0
- package/src/util/Util_StaticBundle.res.mjs +132 -0
- package/src/util/Util_Vpc.res +22 -0
- package/src/util/Util_Vpc.res.mjs +27 -0
- package/tests/AppSync_AdapterTest.res +396 -0
- package/tests/AppSync_AdapterTest.res.mjs +326 -0
- package/tests/AppSync_Resolver_RetryingTest.res +59 -0
- package/tests/AppSync_Resolver_RetryingTest.res.mjs +66 -0
- package/tests/Auth_CognitoTest.res +203 -0
- package/tests/Auth_CognitoTest.res.mjs +248 -0
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +602 -0
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res.mjs +742 -0
- package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +57 -0
- package/tests/EventLogStorage_DynamoDb_RuntimeTest.res.mjs +68 -0
- package/tests/MCP_LambdaTest.res +101 -0
- package/tests/MCP_LambdaTest.res.mjs +56 -0
- package/tests/Util_HostUiDomainTest.res +90 -0
- package/tests/Util_HostUiDomainTest.res.mjs +50 -0
- package/tests/Util_SQS_RuntimeTest.res +46 -0
- package/tests/Util_SQS_RuntimeTest.res.mjs +45 -0
- package/tests/Util_StaticBundleTest.res +136 -0
- package/tests/Util_StaticBundleTest.res.mjs +149 -0
- package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +101 -0
- package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res.mjs +91 -0
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +315 -0
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res.mjs +435 -0
- package/tests/integration/DcbIntegrationHarness.res +102 -0
- package/tests/integration/DcbIntegrationHarness.res.mjs +163 -0
- package/tests/integration/EpTestSlice.res +28 -0
- package/tests/integration/EpTestSlice.res.mjs +43 -0
- package/tests/integration/EpTestSliceBehavior.res +18 -0
- package/tests/integration/EpTestSliceBehavior.res.mjs +35 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// ReadModel Lambda entry point.
|
|
2
|
+
// At cold start: reads HANDLER_CONFIG, dynamically imports Spec/Mappings modules,
|
|
3
|
+
// wires ReadModel_Callback.Make, builds handler map keyed by source URN.
|
|
4
|
+
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import { patchSpecId, makeTableRef, log, pluginName } from "./HandlerFactoryHelpers.mjs";
|
|
7
|
+
import { tag as requestContextTag } from "@reventlessdev/reventless-core/src/RequestContext.res.mjs";
|
|
8
|
+
import { Make as readModelCallbackMake } from "@reventlessdev/reventless-core/src/components/ReadModel/ReadModel_Callback.res.mjs";
|
|
9
|
+
import { load as qdbLoad, loadStream as qdbLoadStream, save as qdbSave, saveBatch as qdbSaveBatch, count as qdbCount, $$delete as qdbDelete, deleteBatch as qdbDeleteBatch } from "@reventlessdev/reventless-aws/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res.mjs";
|
|
10
|
+
import { handleStreamEvent } from "@reventlessdev/reventless-aws/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res.mjs";
|
|
11
|
+
|
|
12
|
+
const dynamicImport = (specifier) => import('/var/task/node_modules/' + specifier);
|
|
13
|
+
|
|
14
|
+
// Inject 'id' key into saved state objects
|
|
15
|
+
function mkInjectIdSave(rawSave) {
|
|
16
|
+
return (id, state, saveMode, ttl) => {
|
|
17
|
+
const injected = (state && typeof state === "object" && !Array.isArray(state))
|
|
18
|
+
? { ...state, id }
|
|
19
|
+
: state;
|
|
20
|
+
return rawSave(id, injected, saveMode, ttl);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function mkInjectIdSaveBatch(rawSaveBatch) {
|
|
25
|
+
return (items) =>
|
|
26
|
+
rawSaveBatch(items.map(([id, state, ttl]) => {
|
|
27
|
+
const injected = (state && typeof state === "object" && !Array.isArray(state))
|
|
28
|
+
? { ...state, id }
|
|
29
|
+
: state;
|
|
30
|
+
return [id, injected, ttl];
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Fix mappings module: ensure it has a `mappings` array
|
|
35
|
+
function fixMappingsModule(mod) {
|
|
36
|
+
if (mod.mappings) return mod;
|
|
37
|
+
const mappingValues = Object.values(mod).filter(
|
|
38
|
+
(v) => v && typeof v === "object" && "sourceName" in v && "map" in v
|
|
39
|
+
);
|
|
40
|
+
if (mappingValues.length > 0) {
|
|
41
|
+
return { ...mod, mappings: mappingValues };
|
|
42
|
+
}
|
|
43
|
+
return mod;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Set at handler entry; read by runEffect to tag logs with the Lambda request id.
|
|
47
|
+
let _currentRequestId = "unknown";
|
|
48
|
+
|
|
49
|
+
function runEffect(correlationId, effect) {
|
|
50
|
+
let e = effect
|
|
51
|
+
// Promote correlationId/requestId/plugin to top-level JSON log fields —
|
|
52
|
+
// decoded by EffectLogger.install() from Effect log annotations. Harmless
|
|
53
|
+
// no-op if the unified logger isn't installed.
|
|
54
|
+
.pipe(Effect.annotateLogs("correlationId", correlationId || "unknown"))
|
|
55
|
+
.pipe(Effect.annotateLogs("requestId", _currentRequestId));
|
|
56
|
+
if (pluginName) e = e.pipe(Effect.annotateLogs("plugin", pluginName));
|
|
57
|
+
return e
|
|
58
|
+
.pipe(Effect.provideService(requestContextTag, { correlationId: correlationId || "unknown" }))
|
|
59
|
+
.pipe(Effect.runPromise);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function groupBySource(records) {
|
|
63
|
+
const dict = {};
|
|
64
|
+
records.forEach(record => {
|
|
65
|
+
const arn = record.eventSourceARN;
|
|
66
|
+
const existing = dict[arn] || [];
|
|
67
|
+
dict[arn] = existing.concat([record]);
|
|
68
|
+
});
|
|
69
|
+
return dict;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function buildReadModelHandler(specModule, mappingsModule, queryDbTableName) {
|
|
73
|
+
const patchedSpec = patchSpecId(specModule);
|
|
74
|
+
const table = makeTableRef(queryDbTableName);
|
|
75
|
+
const rawSave = qdbSave(table);
|
|
76
|
+
const rawSaveBatch = qdbSaveBatch(table);
|
|
77
|
+
|
|
78
|
+
const operations = {
|
|
79
|
+
load: qdbLoad(table),
|
|
80
|
+
loadStream: qdbLoadStream(table),
|
|
81
|
+
save: mkInjectIdSave(rawSave),
|
|
82
|
+
saveBatch: mkInjectIdSaveBatch(rawSaveBatch),
|
|
83
|
+
count: qdbCount(table),
|
|
84
|
+
delete: qdbDelete(table),
|
|
85
|
+
deleteBatch: qdbDeleteBatch(table),
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const effectiveMappings = fixMappingsModule(mappingsModule);
|
|
89
|
+
const callback = readModelCallbackMake(patchedSpec)(effectiveMappings)({
|
|
90
|
+
ReadModelSpec: patchedSpec,
|
|
91
|
+
operations,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return (event, context) => handleStreamEvent(callback.handleJsonEvents, event, context);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function buildAllHandlers() {
|
|
98
|
+
const configStr = process.env["HANDLER_CONFIG"] || '{"handlers":[]}';
|
|
99
|
+
const config = JSON.parse(configStr);
|
|
100
|
+
const handlers = {};
|
|
101
|
+
|
|
102
|
+
await Promise.all(config.handlers.map(async h => {
|
|
103
|
+
const specModule = await dynamicImport(h.specModule);
|
|
104
|
+
const mappingsModule = await dynamicImport(h.mappingsModule);
|
|
105
|
+
const handler = buildReadModelHandler(specModule, mappingsModule, h.queryDbTableName);
|
|
106
|
+
// Multiple read models can share one source stream — e.g. every admin read
|
|
107
|
+
// model (Plugins, PluginHistory, PlatformEventGraph, UIFragmentRegistry)
|
|
108
|
+
// projects the Plugin aggregate's EventLog stream. Accumulate ALL handlers
|
|
109
|
+
// per source ARN; a plain `handlers[urn] = handler` collapses them to one
|
|
110
|
+
// (whichever async builder wins the Promise.all race), silently dropping the
|
|
111
|
+
// rest — which leaves their QueryDbs empty.
|
|
112
|
+
(handlers[h.sourceUrn] ||= []).push(handler);
|
|
113
|
+
}));
|
|
114
|
+
|
|
115
|
+
return handlers;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const initPromise = buildAllHandlers();
|
|
119
|
+
|
|
120
|
+
export async function handler(event, context) {
|
|
121
|
+
_currentRequestId = context?.awsRequestId || "unknown";
|
|
122
|
+
const handlers = await initPromise;
|
|
123
|
+
const records = event.Records || [];
|
|
124
|
+
const grouped = groupBySource(records);
|
|
125
|
+
|
|
126
|
+
await Promise.all(Object.entries(grouped).map(async ([arn, subRecords]) => {
|
|
127
|
+
const streamHandlers = handlers[arn];
|
|
128
|
+
if (streamHandlers !== undefined && streamHandlers.length > 0) {
|
|
129
|
+
log.debug("found " + streamHandlers.length + " handler(s) for " + arn, { comp: "ReadModelRuntime" });
|
|
130
|
+
// Run every read model registered for this source stream (independent
|
|
131
|
+
// QueryDbs, so concurrent is safe).
|
|
132
|
+
await Promise.all(
|
|
133
|
+
streamHandlers.map(streamHandler =>
|
|
134
|
+
runEffect(undefined, streamHandler({ Records: subRecords }, context))
|
|
135
|
+
)
|
|
136
|
+
);
|
|
137
|
+
} else {
|
|
138
|
+
log.warn("no handler found: " + arn, { comp: "ReadModelRuntime" });
|
|
139
|
+
}
|
|
140
|
+
}));
|
|
141
|
+
|
|
142
|
+
return "";
|
|
143
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module Lambda = RuntimeEnvironment_Lambda
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
type event = PulumiAws.Lambda.CallbackFunction.event
|
|
2
|
+
type context = PulumiAws.Lambda.context
|
|
3
|
+
type parts = Util.Lambda.runtimeParts
|
|
4
|
+
|
|
5
|
+
// Generic env vars and IAM policies for all Lambdas created by makeFromCodeAsset.
|
|
6
|
+
// Consumers register additional config before deployPlugin triggers builder finish().
|
|
7
|
+
let additionalEnvVars: dict<Pulumi.Input.t<string>> = Dict.make()
|
|
8
|
+
|
|
9
|
+
type iamPolicy = {
|
|
10
|
+
suffix: string,
|
|
11
|
+
actions: string,
|
|
12
|
+
resourceArn: Pulumi.Output.t<string>,
|
|
13
|
+
}
|
|
14
|
+
let additionalIamPolicies: array<iamPolicy> = []
|
|
15
|
+
|
|
16
|
+
// Legacy CallbackFunction path — retained for module type compatibility.
|
|
17
|
+
// Not called at runtime; all Lambda deployments now use makeFromCodeAsset.
|
|
18
|
+
// Can be removed once the module type no longer requires environmentMaker.
|
|
19
|
+
let make: ReventlessCore.Runtime.environmentMaker<'event, context, 'result, parts> = (
|
|
20
|
+
~name,
|
|
21
|
+
~handler,
|
|
22
|
+
~memorySize: int=1024,
|
|
23
|
+
~timeout: int=30,
|
|
24
|
+
~opts=?,
|
|
25
|
+
) => {
|
|
26
|
+
open PulumiAws
|
|
27
|
+
let opts =
|
|
28
|
+
opts->Option.map(ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions)
|
|
29
|
+
|
|
30
|
+
let lambdaRole = IAM.Role.makeWithDefaultPolicy(
|
|
31
|
+
~name,
|
|
32
|
+
~servicePrincipal=AWS.Lambda.principal->Pulumi.Output.make,
|
|
33
|
+
~opts?,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
let tags = AWS.Tags.make(~name, ReventlessCore.CommandTopic.componentType)
|
|
37
|
+
let lambda =
|
|
38
|
+
handler->Pulumi.Output.apply(handler =>
|
|
39
|
+
Lambda.CallbackFunction.make(
|
|
40
|
+
~name,
|
|
41
|
+
~args=Lambda.CallbackFunction.Args.make(
|
|
42
|
+
~callback=handler,
|
|
43
|
+
~role=lambdaRole,
|
|
44
|
+
~memorySize=memorySize->Pulumi.Input.make,
|
|
45
|
+
~timeout=timeout->Pulumi.Input.make,
|
|
46
|
+
~tags,
|
|
47
|
+
),
|
|
48
|
+
~opts?,
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
// Coerce CallbackFunction.t → Function.t (structurally compatible: both have arn, id, name).
|
|
53
|
+
// This legacy path is only retained for module type compatibility.
|
|
54
|
+
let lambdaAsFunction: Pulumi.Output.t<PulumiAws.Lambda.Function.t> = lambda->Obj.magic
|
|
55
|
+
|
|
56
|
+
{
|
|
57
|
+
parts: {lambda: lambdaAsFunction, lambdaRole},
|
|
58
|
+
resources: [
|
|
59
|
+
lambdaAsFunction
|
|
60
|
+
->Pulumi.Output.apply(lambda => lambda->Util.Lambda.toResource(~tags=tags->Pulumi.Output.fromInput))
|
|
61
|
+
->ReventlessCore.Adapter.outputToResource,
|
|
62
|
+
Util_IAM_Role.toResource(lambdaRole),
|
|
63
|
+
],
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let makeFromCodeAsset: (
|
|
68
|
+
~name: string,
|
|
69
|
+
~code: Pulumi.Archive.t,
|
|
70
|
+
~sourceCodeHash: string,
|
|
71
|
+
~envVars: dict<Pulumi.Input.t<string>>=?,
|
|
72
|
+
~memorySize: int=?,
|
|
73
|
+
~timeout: int=?,
|
|
74
|
+
~reservedConcurrency: int=?,
|
|
75
|
+
~ephemeralStorageMb: int=?,
|
|
76
|
+
~logRetentionDays: int=?,
|
|
77
|
+
/** Provision the DCB append-retry/conflict CloudWatch metric filters on this
|
|
78
|
+
Lambda's log group (command-handler Lambdas only). Requires a managed log
|
|
79
|
+
group, so it only takes effect when `~logRetentionDays` is also set. */
|
|
80
|
+
~dcbMetrics: bool=?,
|
|
81
|
+
~opts: Pulumi.ComponentResource.options=?,
|
|
82
|
+
) => ReventlessCore.Runtime.environment<parts> = (
|
|
83
|
+
~name,
|
|
84
|
+
~code,
|
|
85
|
+
~sourceCodeHash,
|
|
86
|
+
~envVars=Dict.make(),
|
|
87
|
+
~memorySize: int=ReventlessCore.Runtime.CommandHandlerDefaults.memorySize,
|
|
88
|
+
~timeout: int=ReventlessCore.Runtime.CommandHandlerDefaults.timeout,
|
|
89
|
+
~reservedConcurrency=?,
|
|
90
|
+
~ephemeralStorageMb=?,
|
|
91
|
+
~logRetentionDays=?,
|
|
92
|
+
~dcbMetrics=false,
|
|
93
|
+
~opts=?,
|
|
94
|
+
) => {
|
|
95
|
+
open PulumiAws
|
|
96
|
+
let opts =
|
|
97
|
+
opts->Option.map(ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions)
|
|
98
|
+
|
|
99
|
+
let lambdaRole = IAM.Role.makeWithDefaultPolicy(
|
|
100
|
+
~name,
|
|
101
|
+
~servicePrincipal=AWS.Lambda.principal->Pulumi.Output.make,
|
|
102
|
+
~opts?,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
// Create additional IAM policies registered by consumers.
|
|
106
|
+
additionalIamPolicies->Array.forEach(({suffix, actions, resourceArn}) => {
|
|
107
|
+
let _ = resourceArn->Pulumi.Output.apply(arn => {
|
|
108
|
+
let _ = PulumiAws.IAM.RolePolicy.make(
|
|
109
|
+
~name=`${name}${suffix}`,
|
|
110
|
+
~args={
|
|
111
|
+
policy: PolicyDocument.make(
|
|
112
|
+
~id=`${name}${suffix}Policy`,
|
|
113
|
+
~statements=[
|
|
114
|
+
{
|
|
115
|
+
sid: `Allow${suffix}`,
|
|
116
|
+
effect: Allow,
|
|
117
|
+
actions: Action(actions),
|
|
118
|
+
resources: Resource(arn),
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
)
|
|
122
|
+
->PolicyDocument.toJsonString
|
|
123
|
+
->Pulumi.Input.make,
|
|
124
|
+
role: lambdaRole.id->Pulumi.Output.asInput,
|
|
125
|
+
},
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
let layers =
|
|
131
|
+
Lambda.reventlessLayerArn
|
|
132
|
+
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
133
|
+
->Option.getOr([])
|
|
134
|
+
->Pulumi.Input.make
|
|
135
|
+
|
|
136
|
+
let variables = Dict.fromArray([
|
|
137
|
+
("Environment", Pulumi.Pulumi.getStackName()->Pulumi.Input.make),
|
|
138
|
+
])
|
|
139
|
+
envVars->Dict.forEachWithKey((value, key) => {
|
|
140
|
+
variables->Dict.set(key, value)
|
|
141
|
+
})
|
|
142
|
+
additionalEnvVars->Dict.forEachWithKey((value, key) => {
|
|
143
|
+
variables->Dict.set(key, value)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
let tags = AWS.Tags.make(~name, ReventlessCore.CommandTopic.componentType)
|
|
147
|
+
let lambda = Lambda.Function.make(
|
|
148
|
+
~name,
|
|
149
|
+
~args={
|
|
150
|
+
handler: "index.handler"->Pulumi.Input.make,
|
|
151
|
+
runtime: "nodejs22.x"->Pulumi.Input.make,
|
|
152
|
+
code: code->Pulumi.Input.make,
|
|
153
|
+
sourceCodeHash: sourceCodeHash->Pulumi.Input.make,
|
|
154
|
+
role: lambdaRole.arn->Pulumi.Output.asInput,
|
|
155
|
+
memorySize: memorySize->Pulumi.Input.make,
|
|
156
|
+
timeout: timeout->Pulumi.Input.make,
|
|
157
|
+
reservedConcurrentExecutions: ?reservedConcurrency->Option.map(Pulumi.Input.make),
|
|
158
|
+
ephemeralStorage: ?ephemeralStorageMb->Option.map(mb =>
|
|
159
|
+
({size: mb->Pulumi.Input.make}: Lambda.Function.ephemeralStorage)->Pulumi.Input.make
|
|
160
|
+
),
|
|
161
|
+
layers,
|
|
162
|
+
tags,
|
|
163
|
+
environment: ({Lambda.Function.variables: variables}: Lambda.Function.functionEnvironment)
|
|
164
|
+
->Pulumi.Input.make,
|
|
165
|
+
},
|
|
166
|
+
~opts?,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
// Optional CloudWatch log-group with explicit retention. When not set, Lambda
|
|
170
|
+
// auto-creates a log group with no retention (logs accumulate indefinitely).
|
|
171
|
+
logRetentionDays->Option.forEach(days => {
|
|
172
|
+
let logGroup = Cloudwatch.LogGroup.make(
|
|
173
|
+
~name=`${name}LogGroup`,
|
|
174
|
+
~args={
|
|
175
|
+
name: `/aws/lambda/${name}`->Pulumi.Input.make,
|
|
176
|
+
retentionInDays: days->Pulumi.Input.make,
|
|
177
|
+
},
|
|
178
|
+
~opts?,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
// DCB command-handler Lambdas: extract the provider-neutral metric lines
|
|
182
|
+
// emitted by StateChangeSlice_Callback (`{reventlessMetric, slice, value}`)
|
|
183
|
+
// into CloudWatch metrics. Attached to the managed log group above so there
|
|
184
|
+
// is no race against Lambda's lazy auto-created group. Namespace/dimension
|
|
185
|
+
// are CloudWatch-specific and live here, not in core (provider-neutral).
|
|
186
|
+
if dcbMetrics {
|
|
187
|
+
["AppendRetry", "AppendConflict"]->Array.forEach(metricName => {
|
|
188
|
+
let _ = Cloudwatch.LogMetricFilter.make(
|
|
189
|
+
~name=`${name}${metricName}Filter`,
|
|
190
|
+
~args={
|
|
191
|
+
pattern: `{ $.reventlessMetric = "${metricName}" }`->Pulumi.Input.make,
|
|
192
|
+
logGroupName: logGroup.name->Pulumi.Output.asInput,
|
|
193
|
+
metricTransformation: ({
|
|
194
|
+
name: metricName->Pulumi.Input.make,
|
|
195
|
+
namespace: "Reventless/DCB"->Pulumi.Input.make,
|
|
196
|
+
value: "$.value"->Pulumi.Input.make,
|
|
197
|
+
defaultValue: "0"->Pulumi.Input.make,
|
|
198
|
+
unit: "Count"->Pulumi.Input.make,
|
|
199
|
+
dimensions: Dict.fromArray([("slice", "$.slice")])->Pulumi.Input.make,
|
|
200
|
+
}: Cloudwatch.LogMetricFilter.metricTransformation)->Pulumi.Input.make,
|
|
201
|
+
},
|
|
202
|
+
~opts?,
|
|
203
|
+
)
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
{
|
|
209
|
+
parts: {lambda: lambda->Pulumi.Output.make, lambdaRole},
|
|
210
|
+
resources: [
|
|
211
|
+
lambda->Util.Lambda.functionToResource(~tags=tags->Pulumi.Output.fromInput),
|
|
212
|
+
Util_IAM_Role.toResource(lambdaRole),
|
|
213
|
+
],
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let groupBySource = (event: event) => {
|
|
218
|
+
let dict: dict<event> = Dict.make()
|
|
219
|
+
event.records->Array.forEach(record => {
|
|
220
|
+
let eventSourceArn = record.eventSourceARN
|
|
221
|
+
let currentEvent = dict->Dict.get(eventSourceArn)->Option.getOr({records: []})
|
|
222
|
+
dict->Dict.set(eventSourceArn, {records: currentEvent.records->Array.concat([record])})
|
|
223
|
+
})
|
|
224
|
+
dict
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// SQS records carry a `body` string field not included in the minimal record type.
|
|
228
|
+
@get external recordBody: PulumiAws.Lambda.CallbackFunction.record => option<string> = "body"
|
|
229
|
+
|
|
230
|
+
let extractCorrelationId = (event: event) =>
|
|
231
|
+
event.records
|
|
232
|
+
->Array.get(0)
|
|
233
|
+
->Option.flatMap(r =>
|
|
234
|
+
r
|
|
235
|
+
->recordBody
|
|
236
|
+
->Option.flatMap(body => {
|
|
237
|
+
try body->JSON.parseOrThrow->JSON.Decode.object catch {
|
|
238
|
+
| _ => None
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
)
|
|
242
|
+
->Option.flatMap(obj => obj->Dict.get("meta"))
|
|
243
|
+
->Option.flatMap(JSON.Decode.object)
|
|
244
|
+
->Option.flatMap(meta => meta->Dict.get("correlationId"))
|
|
245
|
+
->Option.flatMap(JSON.Decode.string)
|
|
246
|
+
|
|
247
|
+
external asEventHandler: 'a => ReventlessCore.Runtime.eventHandler<event, context, 'result> =
|
|
248
|
+
"%identity"
|
|
249
|
+
external asEffectHandler: 'a => ReventlessCore.Runtime.effectHandler<
|
|
250
|
+
event,
|
|
251
|
+
context,
|
|
252
|
+
'result,
|
|
253
|
+
'error,
|
|
254
|
+
> = "%identity"
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Aws from "@pulumi/aws";
|
|
4
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
5
|
+
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
6
|
+
import * as IAM$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/IAM.res.mjs";
|
|
7
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
8
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
9
|
+
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
10
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
11
|
+
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
12
|
+
import * as AWS_Tags$ReventlessAws from "../AWS_Tags.res.mjs";
|
|
13
|
+
import * as Adapter$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Adapter.res.mjs";
|
|
14
|
+
import * as Runtime$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Runtime/Runtime.res.mjs";
|
|
15
|
+
import * as PolicyDocument$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/PolicyDocument.res.mjs";
|
|
16
|
+
import * as Util_Lambda$ReventlessAws from "../../util/Util_Lambda.res.mjs";
|
|
17
|
+
import * as Util_Pulumi$ReventlessCore from "@reventlessdev/reventless-core/src/util/Util_Pulumi.res.mjs";
|
|
18
|
+
import * as CommandTopic$ReventlessCore from "@reventlessdev/reventless-core/src/components/CommandTopic/CommandTopic.res.mjs";
|
|
19
|
+
import * as Util_IAM_Role$ReventlessAws from "../../util/Util_IAM_Role.res.mjs";
|
|
20
|
+
|
|
21
|
+
let additionalEnvVars = {};
|
|
22
|
+
|
|
23
|
+
let additionalIamPolicies = [];
|
|
24
|
+
|
|
25
|
+
function make(name, handler, memorySizeOpt, timeoutOpt, opts) {
|
|
26
|
+
let memorySize = memorySizeOpt !== undefined ? memorySizeOpt : 1024;
|
|
27
|
+
let timeout = timeoutOpt !== undefined ? timeoutOpt : 30;
|
|
28
|
+
let opts$1 = Stdlib_Option.map(opts, Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions);
|
|
29
|
+
let lambdaRole = IAM$PulumiAws.Role.makeWithDefaultPolicy(name, Pulumi.output(AWS$ReventlessAws.Lambda.principal), opts$1);
|
|
30
|
+
let tags = AWS_Tags$ReventlessAws.make(name, CommandTopic$ReventlessCore.componentType);
|
|
31
|
+
let lambda = handler.apply(handler => new (Aws.lambda.CallbackFunction)(name, Lambda$PulumiAws.CallbackFunction.Args.make(handler, lambdaRole, undefined, undefined, undefined, memorySize, timeout, undefined, undefined, undefined, tags, undefined), opts$1 !== undefined ? Primitive_option.valFromOption(opts$1) : undefined));
|
|
32
|
+
return {
|
|
33
|
+
parts: {
|
|
34
|
+
lambda: lambda,
|
|
35
|
+
lambdaRole: lambdaRole
|
|
36
|
+
},
|
|
37
|
+
resources: [
|
|
38
|
+
Adapter$ReventlessCore.outputToResource(lambda.apply(lambda => Util_Lambda$ReventlessAws.toResource(tags, lambda))),
|
|
39
|
+
Util_IAM_Role$ReventlessAws.toResource(lambdaRole)
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function makeFromCodeAsset(name, code, sourceCodeHash, envVarsOpt, memorySizeOpt, timeoutOpt, reservedConcurrency, ephemeralStorageMb, logRetentionDays, dcbMetricsOpt, opts) {
|
|
45
|
+
let envVars = envVarsOpt !== undefined ? envVarsOpt : ({});
|
|
46
|
+
let memorySize = memorySizeOpt !== undefined ? memorySizeOpt : Runtime$ReventlessCore.CommandHandlerDefaults.memorySize;
|
|
47
|
+
let timeout = timeoutOpt !== undefined ? timeoutOpt : Runtime$ReventlessCore.CommandHandlerDefaults.timeout;
|
|
48
|
+
let dcbMetrics = dcbMetricsOpt !== undefined ? dcbMetricsOpt : false;
|
|
49
|
+
let opts$1 = Stdlib_Option.map(opts, Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions);
|
|
50
|
+
let lambdaRole = IAM$PulumiAws.Role.makeWithDefaultPolicy(name, Pulumi.output(AWS$ReventlessAws.Lambda.principal), opts$1);
|
|
51
|
+
additionalIamPolicies.forEach(param => {
|
|
52
|
+
let actions = param.actions;
|
|
53
|
+
let suffix = param.suffix;
|
|
54
|
+
param.resourceArn.apply(arn => {
|
|
55
|
+
new (Aws.iam.RolePolicy)(name + suffix, {
|
|
56
|
+
policy: PolicyDocument$PulumiAws.toJsonString(PolicyDocument$PulumiAws.make(undefined, name + suffix + `Policy`, [{
|
|
57
|
+
Sid: `Allow` + suffix,
|
|
58
|
+
Effect: "Allow",
|
|
59
|
+
Action: actions,
|
|
60
|
+
Resource: arn
|
|
61
|
+
}])),
|
|
62
|
+
role: lambdaRole.id
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
let layers = Stdlib_Option.getOr(Stdlib_Option.map(Lambda$PulumiAws.reventlessLayerArn, arn => [arn]), []);
|
|
67
|
+
let variables = Object.fromEntries([[
|
|
68
|
+
"Environment",
|
|
69
|
+
Pulumi.getStack()
|
|
70
|
+
]]);
|
|
71
|
+
Stdlib_Dict.forEachWithKey(envVars, (value, key) => {
|
|
72
|
+
variables[key] = value;
|
|
73
|
+
});
|
|
74
|
+
Stdlib_Dict.forEachWithKey(additionalEnvVars, (value, key) => {
|
|
75
|
+
variables[key] = value;
|
|
76
|
+
});
|
|
77
|
+
let tags = AWS_Tags$ReventlessAws.make(name, CommandTopic$ReventlessCore.componentType);
|
|
78
|
+
let lambda = new (Aws.lambda.Function)(name, {
|
|
79
|
+
handler: "index.handler",
|
|
80
|
+
runtime: "nodejs22.x",
|
|
81
|
+
code: code,
|
|
82
|
+
role: lambdaRole.arn,
|
|
83
|
+
memorySize: memorySize,
|
|
84
|
+
timeout: timeout,
|
|
85
|
+
layers: layers,
|
|
86
|
+
tags: tags,
|
|
87
|
+
environment: {
|
|
88
|
+
variables: variables
|
|
89
|
+
},
|
|
90
|
+
sourceCodeHash: sourceCodeHash,
|
|
91
|
+
reservedConcurrentExecutions: Stdlib_Option.map(reservedConcurrency, prim => prim),
|
|
92
|
+
ephemeralStorage: Stdlib_Option.map(ephemeralStorageMb, mb => ({
|
|
93
|
+
size: mb
|
|
94
|
+
}))
|
|
95
|
+
}, opts$1 !== undefined ? Primitive_option.valFromOption(opts$1) : undefined);
|
|
96
|
+
Stdlib_Option.forEach(logRetentionDays, days => {
|
|
97
|
+
let logGroup = new (Aws.cloudwatch.LogGroup)(name + `LogGroup`, {
|
|
98
|
+
name: `/aws/lambda/` + name,
|
|
99
|
+
retentionInDays: days
|
|
100
|
+
}, opts$1 !== undefined ? Primitive_option.valFromOption(opts$1) : undefined);
|
|
101
|
+
if (dcbMetrics) {
|
|
102
|
+
[
|
|
103
|
+
"AppendRetry",
|
|
104
|
+
"AppendConflict"
|
|
105
|
+
].forEach(metricName => {
|
|
106
|
+
new (Aws.cloudwatch.LogMetricFilter)(name + metricName + `Filter`, {
|
|
107
|
+
pattern: `{ $.reventlessMetric = "` + metricName + `" }`,
|
|
108
|
+
logGroupName: logGroup.name,
|
|
109
|
+
metricTransformation: {
|
|
110
|
+
name: metricName,
|
|
111
|
+
namespace: "Reventless/DCB",
|
|
112
|
+
value: "$.value",
|
|
113
|
+
defaultValue: "0",
|
|
114
|
+
unit: "Count",
|
|
115
|
+
dimensions: Object.fromEntries([[
|
|
116
|
+
"slice",
|
|
117
|
+
"$.slice"
|
|
118
|
+
]])
|
|
119
|
+
}
|
|
120
|
+
}, opts$1 !== undefined ? Primitive_option.valFromOption(opts$1) : undefined);
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
parts: {
|
|
127
|
+
lambda: Pulumi.output(lambda),
|
|
128
|
+
lambdaRole: lambdaRole
|
|
129
|
+
},
|
|
130
|
+
resources: [
|
|
131
|
+
Util_Lambda$ReventlessAws.functionToResource(tags, lambda),
|
|
132
|
+
Util_IAM_Role$ReventlessAws.toResource(lambdaRole)
|
|
133
|
+
]
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function groupBySource(event) {
|
|
138
|
+
let dict = {};
|
|
139
|
+
event.Records.forEach(record => {
|
|
140
|
+
let eventSourceArn = record.eventSourceARN;
|
|
141
|
+
let currentEvent = Stdlib_Option.getOr(dict[eventSourceArn], {
|
|
142
|
+
Records: []
|
|
143
|
+
});
|
|
144
|
+
dict[eventSourceArn] = {
|
|
145
|
+
Records: currentEvent.Records.concat([record])
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
return dict;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function extractCorrelationId(event) {
|
|
152
|
+
return Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(event.Records[0], r => Stdlib_Option.flatMap(r.body, body => {
|
|
153
|
+
try {
|
|
154
|
+
return Stdlib_JSON.Decode.object(JSON.parse(body));
|
|
155
|
+
} catch (exn) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
})), obj => obj["meta"]), Stdlib_JSON.Decode.object), meta => meta["correlationId"]), Stdlib_JSON.Decode.string);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export {
|
|
162
|
+
additionalEnvVars,
|
|
163
|
+
additionalIamPolicies,
|
|
164
|
+
make,
|
|
165
|
+
makeFromCodeAsset,
|
|
166
|
+
groupBySource,
|
|
167
|
+
extractCorrelationId,
|
|
168
|
+
}
|
|
169
|
+
/* @pulumi/aws Not a pure module */
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// SideEffectHandler Lambda entry point.
|
|
2
|
+
// At cold start: reads HANDLER_CONFIG, dynamically imports SideEffect modules,
|
|
3
|
+
// wires SideEffectHandler_Callback.Make, builds handler map keyed by source URN.
|
|
4
|
+
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import { log, pluginName } from "./HandlerFactoryHelpers.mjs";
|
|
7
|
+
import { tag as requestContextTag } from "@reventlessdev/reventless-core/src/RequestContext.res.mjs";
|
|
8
|
+
import { Make as sideEffectHandlerCallbackMake } from "@reventlessdev/reventless-core/src/components/SideEffectHandler/SideEffectHandler_Callback.res.mjs";
|
|
9
|
+
import { handleStreamEvent } from "@reventlessdev/reventless-aws/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res.mjs";
|
|
10
|
+
|
|
11
|
+
const dynamicImport = (specifier) => import('/var/task/node_modules/' + specifier);
|
|
12
|
+
|
|
13
|
+
// Set at handler entry; read by runEffect to tag logs with the Lambda request id.
|
|
14
|
+
let _currentRequestId = "unknown";
|
|
15
|
+
|
|
16
|
+
function runEffect(correlationId, effect) {
|
|
17
|
+
let e = effect
|
|
18
|
+
// Promote correlationId/requestId/plugin to top-level JSON log fields —
|
|
19
|
+
// decoded by EffectLogger.install() from Effect log annotations. Harmless
|
|
20
|
+
// no-op if the unified logger isn't installed.
|
|
21
|
+
.pipe(Effect.annotateLogs("correlationId", correlationId || "unknown"))
|
|
22
|
+
.pipe(Effect.annotateLogs("requestId", _currentRequestId));
|
|
23
|
+
if (pluginName) e = e.pipe(Effect.annotateLogs("plugin", pluginName));
|
|
24
|
+
return e
|
|
25
|
+
.pipe(Effect.provideService(requestContextTag, { correlationId: correlationId || "unknown" }))
|
|
26
|
+
.pipe(Effect.runPromise);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function groupBySource(records) {
|
|
30
|
+
const dict = {};
|
|
31
|
+
records.forEach(record => {
|
|
32
|
+
const arn = record.eventSourceARN;
|
|
33
|
+
const existing = dict[arn] || [];
|
|
34
|
+
dict[arn] = existing.concat([record]);
|
|
35
|
+
});
|
|
36
|
+
return dict;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function buildAllHandlers() {
|
|
40
|
+
const configStr = process.env["HANDLER_CONFIG"] || '{"handlers":[]}';
|
|
41
|
+
const config = JSON.parse(configStr);
|
|
42
|
+
const handlers = {};
|
|
43
|
+
|
|
44
|
+
await Promise.all(config.handlers.map(async h => {
|
|
45
|
+
const sideEffectModules = await Promise.all(
|
|
46
|
+
h.sideEffectModules.map(async modPath => await dynamicImport(modPath))
|
|
47
|
+
);
|
|
48
|
+
const noOpQueryEngine = { scan: async () => [], query: async () => [] };
|
|
49
|
+
const callback = sideEffectHandlerCallbackMake({ sideEffects: sideEffectModules, queryEngine: noOpQueryEngine });
|
|
50
|
+
const handler = (event, context) => handleStreamEvent(callback.handleJsonEvents, event, context);
|
|
51
|
+
// Multiple side-effect handlers can share one source stream. Accumulate all
|
|
52
|
+
// per source ARN; a plain assignment collapses them to one (Promise.all
|
|
53
|
+
// race), silently dropping the rest.
|
|
54
|
+
(handlers[h.sourceUrn] ||= []).push(handler);
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
return handlers;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const initPromise = buildAllHandlers();
|
|
61
|
+
|
|
62
|
+
export async function handler(event, context) {
|
|
63
|
+
_currentRequestId = context?.awsRequestId || "unknown";
|
|
64
|
+
const handlers = await initPromise;
|
|
65
|
+
const records = event.Records || [];
|
|
66
|
+
const grouped = groupBySource(records);
|
|
67
|
+
|
|
68
|
+
await Promise.all(Object.entries(grouped).map(async ([arn, subRecords]) => {
|
|
69
|
+
const streamHandlers = handlers[arn];
|
|
70
|
+
if (streamHandlers !== undefined && streamHandlers.length > 0) {
|
|
71
|
+
log.debug("found " + streamHandlers.length + " handler(s) for " + arn, { comp: "SideEffectRuntime" });
|
|
72
|
+
await Promise.all(streamHandlers.map(h =>
|
|
73
|
+
runEffect(undefined, h({ Records: subRecords }, context))
|
|
74
|
+
));
|
|
75
|
+
} else {
|
|
76
|
+
log.warn("no handler found: " + arn, { comp: "SideEffectRuntime" });
|
|
77
|
+
}
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
return "";
|
|
81
|
+
}
|