@reventlessdev/reventless-aws 3.0.0-alpha.344 → 3.0.0-alpha.346
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 +36 -0
- package/package.json +15 -12
- package/run-provision-accounts.mjs +3 -0
- package/run-provision-admin.mjs +3 -0
- package/scripts/ProvisionAccounts.res +325 -0
- package/scripts/ProvisionAccounts.res.mjs +337 -0
- package/scripts/ProvisionAdmin.res +275 -0
- package/scripts/ProvisionAdmin.res.mjs +289 -0
- package/scripts/ProvisionCognito.res +149 -0
- package/scripts/ProvisionCognito.res.mjs +98 -0
- package/scripts/ProvisionIdentity.res +84 -14
- package/scripts/ProvisionIdentity.res.mjs +72 -7
- package/scripts/ProvisionProvider.res +104 -0
- package/scripts/ProvisionProvider.res.mjs +123 -0
- package/src/Platform.res +358 -329
- package/src/Platform.res.mjs +24 -12
- package/src/Platform_Casts.res +13 -4
- package/src/Platform_Stack.res +119 -9
- package/src/Platform_Stack.res.mjs +42 -4
- package/src/adapter/Api/AppSyncEventsSigner_Ops.res +8 -4
- package/src/adapter/Api/AppSync_EventsApi.res +12 -14
- package/src/adapter/Api/AppSync_Resolver_Native.res +3 -4
- package/src/adapter/Api/AppSync_Resolver_Retrying.res +78 -70
- package/src/adapter/Api/AppSync_SourceApiAssociation_Retrying.res +11 -8
- package/src/adapter/Api/Platform_AdminScan_Ops.res +15 -14
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +10 -2
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +40 -50
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +39 -32
- package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +5 -2
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +0 -1
- package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +1 -4
- package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +5 -2
- package/src/adapter/Auth/Auth_Cognito.res +3 -9
- package/src/adapter/Auth/Auth_LoginIdentifier.res +66 -0
- package/src/adapter/Auth/Auth_LoginIdentifier.res.mjs +70 -0
- package/src/adapter/Auth/Auth_SignUpMode.res +78 -0
- package/src/adapter/Auth/Auth_SignUpMode.res.mjs +56 -0
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +1 -4
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +3 -1
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +1 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +7 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +6 -1
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +7 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +24 -18
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +9 -4
- package/src/adapter/CommandTopic/CommandTopicRegistry.res +1 -4
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +15 -15
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +9 -5
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +179 -213
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +5 -5
- package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +6 -2
- package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +14 -7
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +14 -7
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +6 -3
- package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +6 -1
- package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +13 -17
- package/src/adapter/EventLog/EventLogStorage_Postgres.res +7 -4
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +12 -7
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +4 -2
- package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +3 -2
- package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +20 -12
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +21 -9
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -3
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +6 -3
- package/src/adapter/Mcp/MCP_Lambda.res +31 -46
- package/src/adapter/Messaging/Messaging_Ses_Backend.res +11 -7
- package/src/adapter/Messaging/Messaging_Ses_Backend.res.mjs +2 -4
- package/src/adapter/Monitoring/Monitoring_CloudWatch.res +16 -16
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +5 -10
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +4 -2
- package/src/adapter/Postgres/PgConnection.res +6 -5
- package/src/adapter/Postgres/PgMigration_Builder.res +4 -8
- package/src/adapter/Postgres/PgRuntime.res +4 -7
- package/src/adapter/QueryDb/PgQueryResolver_Builder.res +9 -11
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +22 -21
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +114 -111
- package/src/adapter/QueryDb/QueryDbResolvers_Lambda.res +1 -7
- package/src/adapter/QueryDb/QueryDbStorage.res +4 -2
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +23 -24
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +8 -2
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +71 -73
- package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +5 -2
- package/src/adapter/QueryDb/QueryInterceptor_Provisioning.res +1 -4
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +8 -2
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +73 -81
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +72 -78
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +44 -67
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +44 -67
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +53 -82
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +47 -77
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +23 -11
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +5 -1
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -97
- package/src/adapter/Runtime/CounterEntryPoint_Ops.res +2 -7
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -10
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +24 -15
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +17 -37
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +31 -57
- package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +18 -24
- package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -5
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +4 -3
- package/src/adapter/Runtime/HeartbeatEntryPoint.res +0 -1
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +4 -2
- package/src/adapter/Runtime/PgMigrationEntryPoint.res +0 -1
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +3 -2
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -2
- package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +4 -5
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +22 -10
- package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +8 -2
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +14 -31
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +16 -17
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +10 -9
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +46 -52
- package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +36 -41
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +31 -37
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +6 -7
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +4 -6
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +2 -6
- package/src/adapter/StateTopic/StateTopic_AppSync.res +21 -16
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +36 -32
- package/src/adapter/Task/TaskBucket_S3.res +6 -1
- package/src/adapter/Upload/Upload_Claim_S3.res +17 -20
- package/src/adapter/Upload/Upload_Claim_S3_Ops.res +5 -2
- package/src/adapter/Upload/Upload_Presign_S3.res +51 -49
- package/src/capability/Capability_Geocoding_AwsLocation.res +4 -1
- package/src/capability/Capability_Messaging.res +4 -5
- package/src/capability/Capability_Messaging_Ses.res +3 -1
- package/src/capability/Capability_ObjectStore_S3.res +1 -7
- package/src/components/Api/AppSync_Adapter.res +80 -109
- package/src/components/Api/AppSync_Adapter.res.mjs +26 -60
- package/src/components/Api/AppSync_SdlDecorate.res +118 -31
- package/src/components/Api/AppSync_SdlDecorate.res.mjs +45 -0
- package/src/components/AutomationSlice_Builder.res +6 -4
- package/src/components/ExtensionPoint_Builder.res +9 -10
- package/src/components/InboundTranslationSlice_Builder.res +7 -8
- package/src/components/OutboundTranslationSlice_Builder.res +14 -8
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
- package/src/components/SideEffectHandler_Single.res +4 -4
- package/src/components/StateViewSlice_Builder.res +6 -4
- package/src/components/StateViewSlice_Builder_Stream.res +6 -4
- package/src/components/Task_Builder_PerBucket.res +10 -11
- package/src/plugin/cloner/ClonerRunner_Fargate.res +3 -10
- package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +1 -4
- package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +5 -5
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +19 -21
- package/src/plugin/runtime/PluginRuntime_Builder.res +167 -188
- package/src/plugin/runtime/Util_PluginMessage_Runtime.res +6 -5
- package/src/plugin/stack/Plugin_Stack.res +104 -103
- package/src/util/Util_AlarmSpec.res +2 -1
- package/src/util/Util_AppSync.res +8 -2
- package/src/util/Util_AppSync_Caller.res +15 -14
- package/src/util/Util_Bundle.res +46 -42
- package/src/util/Util_CognitoGroupUser_Runtime.res +32 -34
- package/src/util/Util_Cognito_Runtime.res +11 -7
- package/src/util/Util_DeadLetterQueue.res +12 -2
- package/src/util/Util_DynamoDb.res +5 -3
- package/src/util/Util_DynamoDbStream.res +7 -3
- package/src/util/Util_DynamoDbStream_Runtime.res +1 -2
- package/src/util/Util_DynamoDb_Runtime.res +23 -41
- package/src/util/Util_HostUiDomain.res +6 -1
- package/src/util/Util_Kinesis_Runtime.res +10 -11
- package/src/util/Util_Lambda.res +12 -5
- package/src/util/Util_LambdaEnvBudget.res +5 -5
- package/src/util/Util_LambdaLogging.res +1 -2
- package/src/util/Util_LogGroup_Adopting.res +1 -4
- package/src/util/Util_ResourceNaming.res +1 -2
- package/src/util/Util_SNS.res +8 -3
- package/src/util/Util_SNS_FIFO.res +1 -1
- package/src/util/Util_SNS_Runtime.res +11 -10
- package/src/util/Util_SQS.res +4 -2
- package/src/util/Util_SQS_FIFO.res +5 -2
- package/src/util/Util_SQS_Runtime.res +37 -36
- package/src/util/Util_ShellConfig.res +3 -2
- package/src/util/Util_StaticBundle.res +1 -3
- package/src/util/Util_StoreLayout.res +4 -1
- package/tests/AWS_TagsTest.res +16 -5
- package/tests/AppSyncEventsSigner_OpsTest.res +11 -2
- package/tests/AppSync_AdapterTest.res +286 -224
- package/tests/AppSync_AdapterTest.res.mjs +69 -0
- package/tests/AppSync_Resolver_RetryingTest.res +64 -44
- package/tests/AppSync_RetirementNarrowingTest.res +59 -46
- package/tests/AppSync_SdlDecorateTest.res +22 -20
- package/tests/AppSync_SourceApiAssociation_RetryingTest.res +40 -22
- package/tests/Auth_ActiveRolePoolAttachmentTest.res +114 -107
- package/tests/Auth_ActiveRoleStoreTest.res +12 -9
- package/tests/Auth_ActiveRoleStore_SchemaTest.res +2 -1
- package/tests/Auth_ActiveRoleTrigger_OpsTest.res +20 -16
- package/tests/Auth_CognitoTest.res +31 -46
- package/tests/Auth_LoginIdentifierTest.res +51 -0
- package/tests/Auth_LoginIdentifierTest.res.mjs +51 -0
- package/tests/Auth_SignUpModeTest.res +56 -0
- package/tests/Auth_SignUpModeTest.res.mjs +53 -0
- package/tests/AutomationSliceEntryPoint_OpsTest.res +69 -67
- package/tests/BakeConvergenceTest.res +22 -25
- package/tests/Capability_MessagingTest.res +28 -12
- package/tests/CommandTopicQueuePolicyTest.res +1 -2
- package/tests/CounterEntryPoint_OpsTest.res +3 -7
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +306 -210
- package/tests/EventCollectorConnectLambdaPreviewTest.res +14 -7
- package/tests/EventCollectorEntryPoint_OpsTest.res +12 -4
- package/tests/EventCollectorPluginDefinitionAssetTest.res +18 -11
- package/tests/EventCollectorReadyGateTest.res +5 -4
- package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -2
- package/tests/EventMapperEntryPoint_OpsTest.res +1 -3
- package/tests/ExtensionPointEntryPoint_OpsTest.res +1 -4
- package/tests/HandlerFactoryDispatchTest.res +97 -70
- package/tests/MCP_LambdaTest.res +16 -27
- package/tests/PgChangeFeedRelay_IntegrationTest.res +123 -93
- package/tests/PgChangeFeedRelay_RuntimeTest.res +13 -10
- package/tests/PgMigrationEntryPoint_IntegrationTest.res +0 -1
- package/tests/PgPipeline_IntegrationTest.res +80 -66
- package/tests/PgQueryDbUnion_IntegrationTest.res +1 -2
- package/tests/PgQueryResolverEntryPoint_OpsTest.res +2 -6
- package/tests/PgQueryResolver_LambdaTest.res +41 -24
- package/tests/Platform_AdminScan_OpsTest.res +4 -1
- package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +137 -129
- package/tests/ProjectionEntryPoint_DisplayNameTest.res +7 -3
- package/tests/ProjectionEntryPoint_UnionStampTest.res +3 -2
- package/tests/ProvisionAccountsTest.res +142 -0
- package/tests/ProvisionAccountsTest.res.mjs +153 -0
- package/tests/ProvisionAdminTest.res +55 -0
- package/tests/ProvisionAdminTest.res.mjs +66 -0
- package/tests/ProvisionIdentityTest.res +91 -9
- package/tests/ProvisionIdentityTest.res.mjs +66 -1
- package/tests/QueryDbOwnerIndexTableTest.res +6 -4
- package/tests/QueryDbResolvers_AppSyncTest.res +23 -16
- package/tests/QueryInterceptor_LambdaTest.res +11 -13
- package/tests/ReadModelEntryPoint_OpsTest.res +43 -41
- package/tests/RuntimeExtensionEntryPoint_OpsTest.res +4 -3
- package/tests/SideEffectEntryPoint_OpsTest.res +23 -18
- package/tests/StateChangeDescriptorParityTest.res +28 -26
- package/tests/StateTopicKeySchemaTest.res +18 -15
- package/tests/StateViewSliceEntryPoint_OpsTest.res +55 -44
- package/tests/TaskBucketEntryPoint_OpsTest.res +13 -13
- package/tests/Upload_ClaimTest.res +3 -3
- package/tests/Util_AwsErrorTest.res +4 -7
- package/tests/Util_BundleDependencyClosureTest.res +15 -3
- package/tests/Util_BundleEsmLoaderTest.res +3 -3
- package/tests/Util_BundleResolveTest.res +4 -6
- package/tests/Util_BundleRuntimeExtensionTest.res +17 -18
- package/tests/Util_DcbMetricsTest.res +6 -6
- package/tests/Util_DynamoDbStreamTest.res +4 -5
- package/tests/Util_DynamoDbTest.res +3 -2
- package/tests/Util_LambdaEnvBudgetTest.res +22 -18
- package/tests/Util_LambdaLoggingTest.res +9 -8
- package/tests/Util_LogGroup_AdoptingTest.res +10 -5
- package/tests/Util_LogRetentionTest.res +6 -2
- package/tests/Util_OwnerScopeEnvTest.res +35 -8
- package/tests/Util_OwnerScopeEnvTest.res.mjs +13 -0
- package/tests/Util_SQS_RuntimeTest.res +5 -7
- package/tests/Util_ShellConfigTest.res +7 -17
- package/tests/Util_StaticBundleTest.res +3 -8
- package/tests/Util_StoreLayoutTest.res +17 -12
- package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -4
- package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +15 -15
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +296 -232
- package/tests/integration/DcbIntegrationHarness.res +8 -8
- package/tests/integration/EpCompositeSlice.res +16 -8
- package/tests/integration/QueryDbUnion_DynamoDb_IntegrationTest.res +8 -10
- package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +10 -10
- package/tests/integration/SvsTestSlice_Projection.res +1 -3
- package/tests/util/Util_AlarmSpecTest.res +62 -49
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
adopted in-place on first deploy (no delete+recreate).
|
|
18
18
|
|
|
19
19
|
See docs/plans/done/appsync-resolver-aws-native-retry.md. */
|
|
20
|
-
|
|
21
|
-
// ── AWS SDK bindings ─────────────────────────────────────────────────────────
|
|
20
|
+
let // ── AWS SDK bindings ─────────────────────────────────────────────────────────
|
|
22
21
|
//
|
|
23
22
|
// Pulumi dynamic providers serialise the provider object (and its captured
|
|
24
23
|
// closure of imports) into stack state. A static `@module("@aws-sdk/client-appsync")`
|
|
@@ -31,7 +30,7 @@
|
|
|
31
30
|
// so the SDK module is NOT part of the captured closure. Each provider method
|
|
32
31
|
// resolves the SDK on first use and caches an initialised client.
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
log = ReventlessCore.Logger.fromEnv()
|
|
35
34
|
|
|
36
35
|
type appSyncClient
|
|
37
36
|
|
|
@@ -231,11 +230,12 @@ let rec runWithRaceRetry = async (
|
|
|
231
230
|
let msg = jsExn->Option.flatMap(JsExn.message)->Option.getOr("(no message)")
|
|
232
231
|
let isRetryable =
|
|
233
232
|
attempt < maxAttempts &&
|
|
234
|
-
|
|
233
|
+
jsExn->Option.mapOr(false, e => isFieldNotFoundError(e) || isSchemaAlteringError(e))
|
|
235
234
|
if isRetryable {
|
|
236
235
|
log.info(
|
|
237
236
|
~comp="AppSync_Resolver_Retrying",
|
|
238
|
-
`attempt ${(attempt + 1)
|
|
237
|
+
`attempt ${(attempt + 1)
|
|
238
|
+
->Int.toString}/${maxAttempts->Int.toString} failed, retrying in ${delayMs->Int.toString}ms: ${name}: ${msg}`,
|
|
239
239
|
)
|
|
240
240
|
let _ = await Promise.make((resolve, _) => setTimeout(resolve, delayMs)->ignore)
|
|
241
241
|
let nextDelay = delayMs * 2
|
|
@@ -353,65 +353,62 @@ let makeOuts = (resolverArn: string, inputs: providerInputs): createOuts => {
|
|
|
353
353
|
let create = async (inputs: providerInputs): createResult => {
|
|
354
354
|
let sdk = await getSdk()
|
|
355
355
|
let client = await getClient()
|
|
356
|
-
let arn =
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
| Some(e) => jsThrow(e)
|
|
377
|
-
| None => throw(exn)
|
|
378
|
-
}
|
|
356
|
+
let arn = try {
|
|
357
|
+
await runWithRaceRetry(() =>
|
|
358
|
+
client
|
|
359
|
+
->sendCreate(newOf1(sdk.createCtor, inputs->buildSdkInput))
|
|
360
|
+
->Promise.thenResolve(extractArn)
|
|
361
|
+
)
|
|
362
|
+
} catch {
|
|
363
|
+
| exn =>
|
|
364
|
+
// If the resolver already exists (AppSync / Pulumi state divergence from a
|
|
365
|
+
// previous partial deploy), update it to match desired config and adopt its ARN.
|
|
366
|
+
// This makes create idempotent and lets stuck stacks recover without manual intervention.
|
|
367
|
+
let handled = exn->JsExn.fromException->Option.mapOr(false, isAlreadyExistsError)
|
|
368
|
+
if handled {
|
|
369
|
+
let resp = await client->sendUpdate(newOf1(sdk.updateCtor, inputs->buildSdkInput))
|
|
370
|
+
extractArn(resp)
|
|
371
|
+
} else {
|
|
372
|
+
let jsExn = exn->JsExn.fromException
|
|
373
|
+
switch jsExn {
|
|
374
|
+
| Some(e) => jsThrow(e)
|
|
375
|
+
| None => throw(exn)
|
|
379
376
|
}
|
|
380
377
|
}
|
|
378
|
+
}
|
|
381
379
|
{id: arn, outs: makeOuts(arn, inputs)}
|
|
382
380
|
}
|
|
383
381
|
|
|
384
382
|
let update = async (id: string, _olds: providerInputs, news: providerInputs): updateResult => {
|
|
385
383
|
let sdk = await getSdk()
|
|
386
384
|
let client = await getClient()
|
|
387
|
-
let arn =
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
385
|
+
let arn = try {
|
|
386
|
+
let _ = await runWithRaceRetry(() =>
|
|
387
|
+
client->sendUpdate(newOf1(sdk.updateCtor, news->buildSdkInput))
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
// ARN is stable across updates — reuse the existing id
|
|
391
|
+
id
|
|
392
|
+
} catch {
|
|
393
|
+
| exn =>
|
|
394
|
+
// If the resolver was deleted from AppSync (e.g. by a schema replacement),
|
|
395
|
+
// fall back to CreateResolver so the resource is transparently recreated.
|
|
396
|
+
let handled = exn->JsExn.fromException->Option.mapOr(false, isAlreadyDeletedError)
|
|
397
|
+
if handled {
|
|
398
|
+
let resp = await runWithRaceRetry(() =>
|
|
399
|
+
client
|
|
400
|
+
->sendCreate(newOf1(sdk.createCtor, news->buildSdkInput))
|
|
401
|
+
->Promise.thenResolve(extractArn)
|
|
391
402
|
)
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
let handled =
|
|
399
|
-
exn->JsExn.fromException->Option.mapOr(false, isAlreadyDeletedError)
|
|
400
|
-
if handled {
|
|
401
|
-
let resp = await runWithRaceRetry(() =>
|
|
402
|
-
client
|
|
403
|
-
->sendCreate(newOf1(sdk.createCtor, news->buildSdkInput))
|
|
404
|
-
->Promise.thenResolve(extractArn)
|
|
405
|
-
)
|
|
406
|
-
resp
|
|
407
|
-
} else {
|
|
408
|
-
let jsExn = exn->JsExn.fromException
|
|
409
|
-
switch jsExn {
|
|
410
|
-
| Some(e) => jsThrow(e)
|
|
411
|
-
| None => throw(exn)
|
|
412
|
-
}
|
|
403
|
+
resp
|
|
404
|
+
} else {
|
|
405
|
+
let jsExn = exn->JsExn.fromException
|
|
406
|
+
switch jsExn {
|
|
407
|
+
| Some(e) => jsThrow(e)
|
|
408
|
+
| None => throw(exn)
|
|
413
409
|
}
|
|
414
410
|
}
|
|
411
|
+
}
|
|
415
412
|
{outs: makeOuts(arn, news)}
|
|
416
413
|
}
|
|
417
414
|
|
|
@@ -451,13 +448,28 @@ let isDefined: string => bool = %raw(`x => x !== undefined && x !== null`)
|
|
|
451
448
|
/** Returns `true` for fields whose change requires delete+recreate.
|
|
452
449
|
AppSync does not allow renaming the API, type, field, or kind in-place. */
|
|
453
450
|
let diff_ = (_id: string, olds: providerInputs, news: providerInputs): diffResult => {
|
|
454
|
-
let replaces =
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
451
|
+
let replaces = [
|
|
452
|
+
if isDefined(olds.apiId) && olds.apiId != news.apiId {
|
|
453
|
+
Some("apiId")
|
|
454
|
+
} else {
|
|
455
|
+
None
|
|
456
|
+
},
|
|
457
|
+
if isDefined(olds.typeName) && olds.typeName != news.typeName {
|
|
458
|
+
Some("typeName")
|
|
459
|
+
} else {
|
|
460
|
+
None
|
|
461
|
+
},
|
|
462
|
+
if isDefined(olds.fieldName) && olds.fieldName != news.fieldName {
|
|
463
|
+
Some("fieldName")
|
|
464
|
+
} else {
|
|
465
|
+
None
|
|
466
|
+
},
|
|
467
|
+
if isDefined(olds.kind) && olds.kind != news.kind {
|
|
468
|
+
Some("kind")
|
|
469
|
+
} else {
|
|
470
|
+
None
|
|
471
|
+
},
|
|
472
|
+
]->Array.filterMap(x => x)
|
|
461
473
|
// For in-place update detection (non-replace changes): compare as-is.
|
|
462
474
|
// If olds is from old state (missing fields), this may trigger an unnecessary
|
|
463
475
|
// update, but that is safe — the update simply re-applies the resolver.
|
|
@@ -541,8 +553,7 @@ type constructorProps = {
|
|
|
541
553
|
// Use the explicit /index.js path because @pulumi/pulumi/dynamic is a
|
|
542
554
|
// directory import not resolvable in ESM mode.
|
|
543
555
|
@module("@pulumi/pulumi/dynamic/index.js") @new
|
|
544
|
-
external _newResource: ('provider, string, 'props, Pulumi.CustomResourceOptions.t) => t =
|
|
545
|
-
"Resource"
|
|
556
|
+
external _newResource: ('provider, string, 'props, Pulumi.CustomResourceOptions.t) => t = "Resource"
|
|
546
557
|
|
|
547
558
|
let makeResolver = (
|
|
548
559
|
~name: string,
|
|
@@ -551,11 +562,7 @@ let makeResolver = (
|
|
|
551
562
|
): t => {
|
|
552
563
|
// Always include an alias for the aws-native resource previously in state —
|
|
553
564
|
// prevents delete+recreate on first deploy (in-place adoption).
|
|
554
|
-
let migrationAlias = Pulumi.Alias.make(
|
|
555
|
-
~type_="aws-native:appsync/resolver:Resolver",
|
|
556
|
-
~name,
|
|
557
|
-
(),
|
|
558
|
-
)
|
|
565
|
+
let migrationAlias = Pulumi.Alias.make(~type_="aws-native:appsync/resolver:Resolver", ~name, ())
|
|
559
566
|
let finalOpts: Pulumi.CustomResourceOptions.t = switch opts {
|
|
560
567
|
| Some(o) => {...o, aliases: [migrationAlias]}
|
|
561
568
|
| None => {aliases: [migrationAlias]}
|
|
@@ -576,7 +583,8 @@ let makeSubscriptionResolverCode = (~filter: option<string>): string =>
|
|
|
576
583
|
export function response(ctx) {
|
|
577
584
|
return ctx.result;
|
|
578
585
|
}`
|
|
579
|
-
| Some(f) =>
|
|
586
|
+
| Some(f) =>
|
|
587
|
+
`export function request(ctx) {
|
|
580
588
|
extensions.setSubscriptionFilter(${f});
|
|
581
589
|
return {};
|
|
582
590
|
}
|
|
@@ -584,7 +592,7 @@ export function response(ctx) {
|
|
|
584
592
|
export function response(ctx) {
|
|
585
593
|
return ctx.result;
|
|
586
594
|
}`
|
|
587
|
-
}
|
|
595
|
+
}
|
|
588
596
|
|
|
589
597
|
let makeSubscriptionResolver = (
|
|
590
598
|
~name,
|
|
@@ -623,7 +631,7 @@ let makeUnitJsResolver = (
|
|
|
623
631
|
apiId: api->Pulumi.Output.flatMap(a => a.id)->Pulumi.Output.asInput,
|
|
624
632
|
typeName: type_,
|
|
625
633
|
fieldName: field,
|
|
626
|
-
dataSourceName
|
|
634
|
+
dataSourceName,
|
|
627
635
|
kind: "UNIT"->Pulumi.Input.make,
|
|
628
636
|
code,
|
|
629
637
|
},
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
state, and `Effect` (used by the in-process `AppSync_Error` retry) fails
|
|
34
34
|
that serialisation, so the SDK is lazily imported and the backoff loop is
|
|
35
35
|
hand-rolled here. */
|
|
36
|
-
|
|
37
36
|
let log = ReventlessCore.Logger.fromEnv()
|
|
38
37
|
|
|
39
38
|
// ── AWS SDK bindings (lazily imported — see AppSync_Resolver_Retrying) ─────────
|
|
@@ -187,17 +186,23 @@ let rec runWithRetry = async (
|
|
|
187
186
|
let name = jsExn->Option.flatMap(exnName)->Option.getOr("(no name)")
|
|
188
187
|
let msg = jsExn->Option.flatMap(JsExn.message)->Option.getOr("(no message)")
|
|
189
188
|
let isRetryable =
|
|
190
|
-
attempt < maxAttempts &&
|
|
191
|
-
jsExn->Option.mapOr(false, isRetryableAssociationError)
|
|
189
|
+
attempt < maxAttempts && jsExn->Option.mapOr(false, isRetryableAssociationError)
|
|
192
190
|
if isRetryable {
|
|
193
191
|
log.info(
|
|
194
192
|
~comp="AppSync_SourceApiAssociation_Retrying",
|
|
195
|
-
`attempt ${(attempt + 1)
|
|
193
|
+
`attempt ${(attempt + 1)
|
|
194
|
+
->Int.toString}/${maxAttempts->Int.toString} failed, retrying in ${delayMs->Int.toString}ms: ${name}: ${msg}`,
|
|
196
195
|
)
|
|
197
196
|
let _ = await Promise.make((resolve, _) => setTimeout(resolve, delayMs)->ignore)
|
|
198
197
|
let nextDelay = delayMs * 2
|
|
199
198
|
let cappedDelay = nextDelay > maxDelayMs ? maxDelayMs : nextDelay
|
|
200
|
-
await runWithRetry(
|
|
199
|
+
await runWithRetry(
|
|
200
|
+
~attempt=attempt + 1,
|
|
201
|
+
~maxAttempts,
|
|
202
|
+
~delayMs=cappedDelay,
|
|
203
|
+
~maxDelayMs,
|
|
204
|
+
makeCall,
|
|
205
|
+
)
|
|
201
206
|
} else {
|
|
202
207
|
if attempt > 0 {
|
|
203
208
|
log.warn(
|
|
@@ -286,9 +291,7 @@ let extractIds = (resp: createResult): (string, string) =>
|
|
|
286
291
|
switch resp.sourceApiAssociation {
|
|
287
292
|
| Some({associationArn: ?Some(arn), associationId: ?Some(aid)}) => (arn, aid)
|
|
288
293
|
| _ =>
|
|
289
|
-
JsError.throwWithMessage(
|
|
290
|
-
"AssociateSourceGraphqlApi returned no associationArn / associationId",
|
|
291
|
-
)
|
|
294
|
+
JsError.throwWithMessage("AssociateSourceGraphqlApi returned no associationArn / associationId")
|
|
292
295
|
}
|
|
293
296
|
|
|
294
297
|
let create = async (inputs: providerInputs): createResultOut => {
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
type ddbClient
|
|
14
14
|
type docClient
|
|
15
|
-
@module("@aws-sdk/client-dynamodb") @new
|
|
15
|
+
@module("@aws-sdk/client-dynamodb") @new
|
|
16
|
+
external makeDdbClient: unit => ddbClient = "DynamoDBClient"
|
|
16
17
|
@module("@aws-sdk/lib-dynamodb") @scope("DynamoDBDocumentClient")
|
|
17
18
|
external docFrom: ddbClient => docClient = "from"
|
|
18
19
|
|
|
@@ -25,7 +26,8 @@ type scanInput = {
|
|
|
25
26
|
@as("ExpressionAttributeValues") expressionAttributeValues?: dict<JSON.t>,
|
|
26
27
|
}
|
|
27
28
|
type scanCommand
|
|
28
|
-
@module("@aws-sdk/lib-dynamodb") @new
|
|
29
|
+
@module("@aws-sdk/lib-dynamodb") @new
|
|
30
|
+
external makeScanCommand: scanInput => scanCommand = "ScanCommand"
|
|
29
31
|
type scanOutput = {
|
|
30
32
|
@as("Items") items?: array<dict<JSON.t>>,
|
|
31
33
|
@as("LastEvaluatedKey") lastEvaluatedKey?: JSON.t,
|
|
@@ -46,17 +48,16 @@ let scanAll = async (
|
|
|
46
48
|
let startKey = ref(None)
|
|
47
49
|
let more = ref(true)
|
|
48
50
|
while more.contents {
|
|
49
|
-
let out =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
51
|
+
let out = await doc->send(
|
|
52
|
+
makeScanCommand({
|
|
53
|
+
tableName,
|
|
54
|
+
limit: 1000,
|
|
55
|
+
exclusiveStartKey: ?startKey.contents,
|
|
56
|
+
?filterExpression,
|
|
57
|
+
?expressionAttributeNames,
|
|
58
|
+
?expressionAttributeValues,
|
|
59
|
+
}),
|
|
60
|
+
)
|
|
60
61
|
out.items->Option.forEach(is => is->Array.forEach(i => items->Array.push(i)))
|
|
61
62
|
switch out.lastEvaluatedKey {
|
|
62
63
|
| Some(k) => startKey := Some(k)
|
|
@@ -76,7 +77,7 @@ let scanAll = async (
|
|
|
76
77
|
// numeric segments compared as numbers, others lexically). Mirrors the platform
|
|
77
78
|
// invariant "one version per plugin at a time" ordering. Returns 1/-1/0.
|
|
78
79
|
let compareVersions = (a: string, b: string): int => {
|
|
79
|
-
let norm = s => s->String.replaceRegExp(
|
|
80
|
+
let norm = s => s->String.replaceRegExp(/[-+]/g, ".")->String.split(".")
|
|
80
81
|
let pa = norm(a)
|
|
81
82
|
let pb = norm(b)
|
|
82
83
|
let len = Math.Int.max(pa->Array.length, pb->Array.length)
|
|
@@ -205,7 +205,10 @@ let make = (
|
|
|
205
205
|
// 4096-byte UpdateFunctionConfiguration limit. Its content participates in
|
|
206
206
|
// `sourceCodeHash`, so a change to the admin structure redeploys the code.
|
|
207
207
|
let packageDirs = Dict.fromArray([
|
|
208
|
-
(
|
|
208
|
+
(
|
|
209
|
+
"@reventlessdev/reventless-aws",
|
|
210
|
+
Util_Bundle.resolvePackageRoot("@reventlessdev/reventless-aws"),
|
|
211
|
+
),
|
|
209
212
|
])
|
|
210
213
|
let {code, sourceCodeHash} = Util_Bundle.buildCodeArchive(
|
|
211
214
|
~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res.mjs",
|
|
@@ -245,7 +248,12 @@ let make = (
|
|
|
245
248
|
memorySize: 512->Pulumi.Input.make,
|
|
246
249
|
timeout: 30->Pulumi.Input.make,
|
|
247
250
|
layers,
|
|
248
|
-
tags: AWS.Tags.make(
|
|
251
|
+
tags: AWS.Tags.make(
|
|
252
|
+
~name=name ++ "Lambda",
|
|
253
|
+
~kind=ReventlessCore.ComponentType.Platform,
|
|
254
|
+
~role=Runtime,
|
|
255
|
+
~scope=Platform,
|
|
256
|
+
),
|
|
249
257
|
environment: (
|
|
250
258
|
{
|
|
251
259
|
Lambda.Function.variables: Dict.fromArray([
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
// sury-encoded with the same shape as the in-memory adapter's
|
|
13
13
|
// encodePluginStructureEntry, so it is wrapped with `pluginId` without decoding.
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
let str = (item: dict<JSON.t>, key: string): option<string> =>
|
|
17
16
|
item->Dict.get(key)->Option.flatMap(JSON.Decode.string)
|
|
18
17
|
|
|
@@ -37,7 +36,14 @@ type healSpec = {lists: array<string>, nested: array<(string, array<string>)>}
|
|
|
37
36
|
let refLists = ["references"]
|
|
38
37
|
|
|
39
38
|
let writeSideHeal = {
|
|
40
|
-
lists: [
|
|
39
|
+
lists: [
|
|
40
|
+
"commands",
|
|
41
|
+
"linkedViews",
|
|
42
|
+
"producedEventTypes",
|
|
43
|
+
"consumedEventTypes",
|
|
44
|
+
"events",
|
|
45
|
+
"errors",
|
|
46
|
+
],
|
|
41
47
|
nested: [("commands", refLists), ("events", refLists), ("errors", refLists)],
|
|
42
48
|
}
|
|
43
49
|
|
|
@@ -52,10 +58,7 @@ let healByCollection: array<(string, healSpec)> = [
|
|
|
52
58
|
("stateChangeSlices", writeSideHeal),
|
|
53
59
|
("aggregates", writeSideHeal),
|
|
54
60
|
("automationSlices", {lists: ["consumedEventTypes", "producedCommandTypes"], nested: []}),
|
|
55
|
-
(
|
|
56
|
-
"outboundTranslationSlices",
|
|
57
|
-
{lists: ["consumedEventTypes", "inboundCommandTypes"], nested: []},
|
|
58
|
-
),
|
|
61
|
+
("outboundTranslationSlices", {lists: ["consumedEventTypes", "inboundCommandTypes"], nested: []}),
|
|
59
62
|
("inboundTranslationSlices", {lists: ["commandTypes"], nested: []}),
|
|
60
63
|
("extensions", {lists: ["delegateNames", "eventTypes", "commandTypes"], nested: []}),
|
|
61
64
|
]
|
|
@@ -116,21 +119,22 @@ let healStructure = (structure: dict<JSON.t>): dict<JSON.t> => {
|
|
|
116
119
|
healByCollection->Array.forEach(((collection, spec)) =>
|
|
117
120
|
out->mapMembers(collection, component => {
|
|
118
121
|
component->fillLists(spec.lists)
|
|
119
|
-
spec.nested->Array.forEach(
|
|
120
|
-
component->mapMembers(key, member => member->fillLists(keys))
|
|
122
|
+
spec.nested->Array.forEach(
|
|
123
|
+
((key, keys)) => component->mapMembers(key, member => member->fillLists(keys)),
|
|
121
124
|
)
|
|
122
125
|
})
|
|
123
126
|
)
|
|
124
|
-
readSideCollections->Array.forEach(collection =>
|
|
125
|
-
out->mapMembers(collection, fillLifecycleField)
|
|
126
|
-
)
|
|
127
|
+
readSideCollections->Array.forEach(collection => out->mapMembers(collection, fillLifecycleField))
|
|
127
128
|
out
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
// Mirror ReventlessCore.Platform_ComponentDefinitionsApi.isPublicQueryable on
|
|
131
132
|
// the read path: a component is public unless its visibility is "Internal".
|
|
132
133
|
let isPublicQueryable = (q: JSON.t): bool =>
|
|
133
|
-
switch q
|
|
134
|
+
switch q
|
|
135
|
+
->JSON.Decode.object
|
|
136
|
+
->Option.flatMap(o => o->Dict.get("visibility"))
|
|
137
|
+
->Option.flatMap(JSON.Decode.string) {
|
|
134
138
|
| Some("Internal") => false
|
|
135
139
|
| _ => true
|
|
136
140
|
}
|
|
@@ -147,8 +151,7 @@ let isPublicQueryable = (q: JSON.t): bool =>
|
|
|
147
151
|
// duplicate list.
|
|
148
152
|
let filterStructure = (structure: dict<JSON.t>): dict<JSON.t> => {
|
|
149
153
|
let out = Dict.fromArray(structure->Dict.toArray)
|
|
150
|
-
let arrAt = key =>
|
|
151
|
-
out->Dict.get(key)->Option.flatMap(JSON.Decode.array)->Option.getOr([])
|
|
154
|
+
let arrAt = key => out->Dict.get(key)->Option.flatMap(JSON.Decode.array)->Option.getOr([])
|
|
152
155
|
let readModels = arrAt("readModels")
|
|
153
156
|
let stateViewSlices = arrAt("stateViewSlices")
|
|
154
157
|
out->Dict.set("readModels", readModels->Array.filter(isPublicQueryable)->JSON.Encode.array)
|
|
@@ -192,7 +195,6 @@ let toEntryWith = (~filter: bool, item: dict<JSON.t>, ~name: string): option<JSO
|
|
|
192
195
|
}
|
|
193
196
|
}
|
|
194
197
|
|
|
195
|
-
|
|
196
198
|
// The built-in Platform_Admin entry, written at deploy time as an asset file in
|
|
197
199
|
// the code archive (the admin never Connects to itself, so its structure never
|
|
198
200
|
// enters the Plugin read model). It rides the archive rather than an env var
|
|
@@ -204,27 +206,25 @@ let toEntryWith = (~filter: bool, item: dict<JSON.t>, ~name: string): option<JSO
|
|
|
204
206
|
// extension points, so its filtered and complete encodings carry the same
|
|
205
207
|
// components; the structure-level fields the complete entry adds are absent from
|
|
206
208
|
// this JSON and resolve to null, which is what `extensionPoints: None` means.
|
|
207
|
-
let adminEntry: option<JSON.t> =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
| json => Some(json)
|
|
214
|
-
}
|
|
215
|
-
} catch {
|
|
216
|
-
| _ => None
|
|
209
|
+
let adminEntry: option<JSON.t> = try {
|
|
210
|
+
switch NodePath.join([NodeProcess.cwd(), "adminEntry.json"])
|
|
211
|
+
->NodeFs.readFileSync
|
|
212
|
+
->JSON.parseOrThrow {
|
|
213
|
+
| JSON.Null => None
|
|
214
|
+
| json => Some(json)
|
|
217
215
|
}
|
|
216
|
+
} catch {
|
|
217
|
+
| _ => None
|
|
218
|
+
}
|
|
218
219
|
|
|
219
220
|
// Resolve an offloaded `structure`: a large structure is content-addressed to the
|
|
220
221
|
// offload bucket at deploy time and persisted as an `{$offload: {...}}` reference,
|
|
221
222
|
// so fetch the object's bytes and substitute the real structure JSON before it is
|
|
222
223
|
// filtered. Inline (or absent) structures pass through untouched. The `fetch` is
|
|
223
224
|
// per-hash cached, so an identical structure shared across versions is read once.
|
|
224
|
-
let resolveStructure = (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
): promise<dict<JSON.t>> =>
|
|
225
|
+
let resolveStructure = (fetch: string => promise<string>, item: dict<JSON.t>): promise<
|
|
226
|
+
dict<JSON.t>,
|
|
227
|
+
> =>
|
|
228
228
|
switch item
|
|
229
229
|
->Dict.get("structure")
|
|
230
230
|
->Option.flatMap(JSON.Decode.object)
|
|
@@ -302,8 +302,7 @@ let structureOf = (item: dict<JSON.t>, ~name as _: string): option<(
|
|
|
302
302
|
| exception _ =>
|
|
303
303
|
JsError.throwWithMessage(
|
|
304
304
|
`baked manifest: the structure persisted for "${pluginId}" cannot be decoded — ` ++
|
|
305
|
-
`it was written by a framework version this platform can no longer read. ` ++
|
|
306
|
-
`Redeploy that plugin, or drop it from the include-list.`,
|
|
305
|
+
`it was written by a framework version this platform can no longer read. ` ++ `Redeploy that plugin, or drop it from the include-list.`,
|
|
307
306
|
)
|
|
308
307
|
}
|
|
309
308
|
| _ => None
|
|
@@ -357,8 +356,7 @@ let bakeSelections = (): array<ReventlessCore.Platform_BakedManifest.selection>
|
|
|
357
356
|
| Some(raw) =>
|
|
358
357
|
switch raw->JSON.parseOrThrow {
|
|
359
358
|
| json => json->decodeSelections
|
|
360
|
-
| exception _ =>
|
|
361
|
-
JsError.throwWithMessage("baked manifest: BAKE_SELECTIONS is not a JSON array")
|
|
359
|
+
| exception _ => JsError.throwWithMessage("baked manifest: BAKE_SELECTIONS is not a JSON array")
|
|
362
360
|
}
|
|
363
361
|
}
|
|
364
362
|
|
|
@@ -612,8 +610,7 @@ let runBake = async (
|
|
|
612
610
|
let selections = bakeSelections()
|
|
613
611
|
if selections->Array.length == 0 {
|
|
614
612
|
JsError.throwWithMessage(
|
|
615
|
-
"baked manifest: BAKE_SELECTIONS is empty — this platform declares no bake, " ++
|
|
616
|
-
"so there is nothing to write and a shell pointed at the file would find none.",
|
|
613
|
+
"baked manifest: BAKE_SELECTIONS is empty — this platform declares no bake, " ++ "so there is nothing to write and a shell pointed at the file would find none.",
|
|
617
614
|
)
|
|
618
615
|
}
|
|
619
616
|
// The default journey first and always — the caller supplies its key, because
|
|
@@ -677,8 +674,7 @@ let handler = async (event: JSON.t): array<JSON.t> => {
|
|
|
677
674
|
switch bakeTarget {
|
|
678
675
|
| Some(_) =>
|
|
679
676
|
JsError.throwWithMessage(
|
|
680
|
-
"baked manifest: PLUGIN_RM_TABLE env var not set — the bake would write an " ++
|
|
681
|
-
"empty shop rather than fail.",
|
|
677
|
+
"baked manifest: PLUGIN_RM_TABLE env var not set — the bake would write an " ++ "empty shop rather than fail.",
|
|
682
678
|
)
|
|
683
679
|
| None => admin
|
|
684
680
|
}
|
|
@@ -699,11 +695,7 @@ let handler = async (event: JSON.t): array<JSON.t> => {
|
|
|
699
695
|
| Some(target) =>
|
|
700
696
|
// Checked on the raw rows: the refs are what the deploy can predict, and a
|
|
701
697
|
// row that is behind should not have its structure fetched at all.
|
|
702
|
-
let regs = registrations(
|
|
703
|
-
rawItems,
|
|
704
|
-
~expect=bakeExpectations(event),
|
|
705
|
-
~since=bakeSince(event),
|
|
706
|
-
)
|
|
698
|
+
let regs = registrations(rawItems, ~expect=bakeExpectations(event), ~since=bakeSince(event))
|
|
707
699
|
switch regs->Array.filter(isPending) {
|
|
708
700
|
| [] =>
|
|
709
701
|
// The built-in admin entry is deliberately absent: it never enters the
|
|
@@ -720,8 +712,7 @@ let handler = async (event: JSON.t): array<JSON.t> => {
|
|
|
720
712
|
// file. What the summary adds is orthogonal to the files — it says what
|
|
721
713
|
// the convergence check proved, not what the bake wrote.
|
|
722
714
|
Array.concat(written, [encodeSummary(regs)])
|
|
723
|
-
| pending =>
|
|
724
|
-
// Not an error — the deploy just has not finished arriving. Reported so the
|
|
715
|
+
| pending => // Not an error — the deploy just has not finished arriving. Reported so the
|
|
725
716
|
// caller can invoke again rather than bake the previous deployment, and
|
|
726
717
|
// reported with both keys and the row's date so that when it never does
|
|
727
718
|
// arrive, the job says which of the causes it was.
|
|
@@ -734,12 +725,11 @@ let handler = async (event: JSON.t): array<JSON.t> => {
|
|
|
734
725
|
]
|
|
735
726
|
}
|
|
736
727
|
| None =>
|
|
737
|
-
let userEntries =
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
)
|
|
728
|
+
let userEntries = Platform_AdminScan_Ops.latestByName(
|
|
729
|
+
await resolveAll(),
|
|
730
|
+
~nameVersionOf=item => item->str("name"),
|
|
731
|
+
~toEntry,
|
|
732
|
+
)
|
|
743
733
|
Array.concat(admin, userEntries)
|
|
744
734
|
}
|
|
745
735
|
}
|
|
@@ -44,42 +44,44 @@ let make = (
|
|
|
44
44
|
~opts,
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
-
let _ =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
})
|
|
47
|
+
let _ = uiFragmentRegistryTableName->Pulumi.Output.apply(tableName => {
|
|
48
|
+
open PolicyDocument
|
|
49
|
+
let _rolePolicy = IAM.RolePolicy.make(
|
|
50
|
+
~name=name ++ "LambdaPolicy",
|
|
51
|
+
~args={
|
|
52
|
+
IAM.RolePolicy.policy: PolicyDocument.make(
|
|
53
|
+
~id=name ++ "LambdaPolicy",
|
|
54
|
+
~statements=[
|
|
55
|
+
{
|
|
56
|
+
sid: "AllowLambdaLogging",
|
|
57
|
+
effect: Allow,
|
|
58
|
+
actions: Action("logs:*"),
|
|
59
|
+
resources: Resource("arn:aws:logs:*:*:*"),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
sid: "AllowScanUiFragmentsTable",
|
|
63
|
+
effect: Allow,
|
|
64
|
+
actions: Actions(["dynamodb:Scan"]),
|
|
65
|
+
resources: Resource("arn:aws:dynamodb:*:*:table/" ++ tableName),
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
)
|
|
69
|
+
->PolicyDocument.toJsonString
|
|
70
|
+
->Pulumi.Input.make,
|
|
71
|
+
role: lambdaRole.id->Pulumi.Output.asInput,
|
|
72
|
+
},
|
|
73
|
+
~opts,
|
|
74
|
+
)
|
|
75
|
+
})
|
|
77
76
|
|
|
78
77
|
// Bundle reventless-aws (the compiled `_Ops` handler lives inside it) and
|
|
79
78
|
// re-export its `handler`; buildCodeArchive also ships the ESM resolve-hook so
|
|
80
79
|
// the handler's bare @aws-sdk/* specifiers resolve from the managed runtime.
|
|
81
80
|
let packageDirs = Dict.fromArray([
|
|
82
|
-
(
|
|
81
|
+
(
|
|
82
|
+
"@reventlessdev/reventless-aws",
|
|
83
|
+
Util_Bundle.resolvePackageRoot("@reventlessdev/reventless-aws"),
|
|
84
|
+
),
|
|
83
85
|
])
|
|
84
86
|
let {code, sourceCodeHash} = Util_Bundle.buildCodeArchive(
|
|
85
87
|
~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res.mjs",
|
|
@@ -118,7 +120,12 @@ let make = (
|
|
|
118
120
|
memorySize: 512->Pulumi.Input.make,
|
|
119
121
|
timeout: 30->Pulumi.Input.make,
|
|
120
122
|
layers,
|
|
121
|
-
tags: AWS.Tags.make(
|
|
123
|
+
tags: AWS.Tags.make(
|
|
124
|
+
~name=name ++ "Lambda",
|
|
125
|
+
~kind=ReventlessCore.ComponentType.Platform,
|
|
126
|
+
~role=Runtime,
|
|
127
|
+
~scope=Platform,
|
|
128
|
+
),
|
|
122
129
|
environment: (
|
|
123
130
|
{
|
|
124
131
|
Lambda.Function.variables: Dict.fromArray([
|