@reventlessdev/reventless-aws 3.0.0-alpha.343 → 3.0.0-alpha.345
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 +15 -0
- package/package.json +11 -11
- package/scripts/ProvisionIdentity.res +8 -3
- package/src/Platform.res +327 -328
- package/src/Platform.res.mjs +4 -2
- package/src/Platform_Casts.res +13 -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/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 +18 -11
- 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 +28 -41
- package/src/components/Api/AppSync_SdlDecorate.res +38 -30
- 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 +144 -67
- package/src/util/Util_Bundle.res.mjs +64 -13
- 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 +203 -224
- 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/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/ProvisionIdentityTest.res +2 -6
- 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 +41 -3
- package/tests/Util_BundleDependencyClosureTest.res.mjs +11 -0
- 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 +10 -8
- 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
package/src/Platform.res
CHANGED
|
@@ -201,8 +201,10 @@ module MakeWithConfig = (
|
|
|
201
201
|
// A platform that provisions none omits the export entirely, which reads
|
|
202
202
|
// as "no store to claim in" — the claimer then builds nothing, rather
|
|
203
203
|
// than building something that can reach nothing.
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
|
|
205
|
+
(
|
|
206
|
+
stackRef->Pulumi.StackReference.getOutput("objectStores"): Pulumi.Output.t<option<JSON.t>>
|
|
207
|
+
)->Pulumi.Output.apply(objectStores =>
|
|
206
208
|
objectStores
|
|
207
209
|
->Option.flatMap(JSON.Decode.object)
|
|
208
210
|
->Option.getOr(Dict.make())
|
|
@@ -210,15 +212,16 @@ module MakeWithConfig = (
|
|
|
210
212
|
->Array.filterMap(((qualified, v)) =>
|
|
211
213
|
v
|
|
212
214
|
->JSON.Decode.object
|
|
213
|
-
->Option.flatMap(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
Some(
|
|
220
|
-
|
|
221
|
-
|
|
215
|
+
->Option.flatMap(
|
|
216
|
+
o =>
|
|
217
|
+
switch (
|
|
218
|
+
o->Dict.get("bucketName")->Option.flatMap(JSON.Decode.string),
|
|
219
|
+
o->Dict.get("keyPrefix")->Option.flatMap(JSON.Decode.string),
|
|
220
|
+
) {
|
|
221
|
+
| (Some(bucketName), Some(servedPrefix)) =>
|
|
222
|
+
Some({Upload_Claim_S3.qualified, bucketName, servedPrefix})
|
|
223
|
+
| _ => None
|
|
224
|
+
},
|
|
222
225
|
)
|
|
223
226
|
)
|
|
224
227
|
)
|
|
@@ -273,8 +276,9 @@ module MakeWithConfig = (
|
|
|
273
276
|
// shared types win over every plugin source's standalone copy (divergence
|
|
274
277
|
// is shadowed, not MERGE_FAILED — Phase-0 finding 1).
|
|
275
278
|
let assembleCanonicalSourceSdl = (~baseFragment): string =>
|
|
276
|
-
AppSync_Adapter.stitchStandaloneWithAwsDirectives(
|
|
277
|
-
|
|
279
|
+
AppSync_Adapter.stitchStandaloneWithAwsDirectives(
|
|
280
|
+
~fragment=baseFragment,
|
|
281
|
+
)->AppSync_SdlDecorate.stampCanonicalTypes
|
|
278
282
|
|
|
279
283
|
// Admin base as a source-API document — auth-decorated (all fields Admin,
|
|
280
284
|
// Cognito-only; the deploy-time SigV4 system-caller fields died with the
|
|
@@ -289,7 +293,8 @@ module MakeWithConfig = (
|
|
|
289
293
|
|
|
290
294
|
// Split-mode Domain source document: relay base types + Platform_ping — the
|
|
291
295
|
// Domain merged API's canonical owner (plugin fields come from plugin sources).
|
|
292
|
-
let domainBaseSourceSdl = (): string =>
|
|
296
|
+
let domainBaseSourceSdl = (): string =>
|
|
297
|
+
assembleCanonicalSourceSdl(~baseFragment=domainBaseFragment)
|
|
293
298
|
|
|
294
299
|
let (domainApi, domainApiRole, platformApi, platformApiRole) = switch platformStackRef {
|
|
295
300
|
| None =>
|
|
@@ -337,37 +342,40 @@ module MakeWithConfig = (
|
|
|
337
342
|
defaultOutput,
|
|
338
343
|
)
|
|
339
344
|
->Pulumi.Output.all3
|
|
340
|
-
->Pulumi.Output.apply(
|
|
341
|
-
(
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
->Option.orElse(getFromDefault("identityProviderRegion"))
|
|
360
|
-
->Option.orElse(directRegion)
|
|
361
|
-
->Option.orElse(getFromDefault("cognitoRegion"))
|
|
362
|
-
(
|
|
363
|
-
{
|
|
364
|
-
userPoolId,
|
|
365
|
-
?awsRegion,
|
|
366
|
-
defaultAction: PulumiAws.AppSync.GraphQLApi.ALLOW,
|
|
367
|
-
}: PulumiAws.AppSync.GraphQLApi.userPoolConfig
|
|
345
|
+
->Pulumi.Output.apply(((
|
|
346
|
+
(directProviderId, directProviderRegion),
|
|
347
|
+
(directPoolId, directRegion),
|
|
348
|
+
default,
|
|
349
|
+
)) => {
|
|
350
|
+
let getFromDefault = key =>
|
|
351
|
+
default
|
|
352
|
+
->Option.flatMap(d => d->JSON.Decode.object)
|
|
353
|
+
->Option.flatMap(d => d->Dict.get(key))
|
|
354
|
+
->Option.flatMap(v => v->JSON.Decode.string)
|
|
355
|
+
// New spelling first at both levels, then the deprecated one. In ESM
|
|
356
|
+
// mode exports arrive nested under "default", hence each pair.
|
|
357
|
+
let userPoolId =
|
|
358
|
+
directProviderId
|
|
359
|
+
->Option.orElse(getFromDefault("identityProviderId"))
|
|
360
|
+
->Option.orElse(directPoolId)
|
|
361
|
+
->Option.orElse(getFromDefault("cognitoUserPoolId"))
|
|
362
|
+
->Option.getOrThrow(
|
|
363
|
+
~message="Platform stack exports neither 'identityProviderId' nor 'cognitoUserPoolId' — redeploy the platform stack first",
|
|
368
364
|
)
|
|
369
|
-
|
|
370
|
-
|
|
365
|
+
let awsRegion =
|
|
366
|
+
directProviderRegion
|
|
367
|
+
->Option.orElse(getFromDefault("identityProviderRegion"))
|
|
368
|
+
->Option.orElse(directRegion)
|
|
369
|
+
->Option.orElse(getFromDefault("cognitoRegion"))
|
|
370
|
+
|
|
371
|
+
(
|
|
372
|
+
{
|
|
373
|
+
userPoolId,
|
|
374
|
+
?awsRegion,
|
|
375
|
+
defaultAction: PulumiAws.AppSync.GraphQLApi.ALLOW,
|
|
376
|
+
}: PulumiAws.AppSync.GraphQLApi.userPoolConfig
|
|
377
|
+
)
|
|
378
|
+
})
|
|
371
379
|
let (api, role) = AppSync_Adapter.makePluginSourceApiResource(
|
|
372
380
|
~name="PluginSourceApi",
|
|
373
381
|
~userPoolConfig,
|
|
@@ -384,72 +392,73 @@ module MakeWithConfig = (
|
|
|
384
392
|
// Populate apiConfig with both domain and platform API references.
|
|
385
393
|
// In platform/monolithic mode, platformApi starts as domainApi and is updated
|
|
386
394
|
// by deployPlatform/makePlatform once the platform API resource is created (split mode).
|
|
387
|
-
let () =
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
395
|
+
let () =
|
|
396
|
+
apiConfigRef :=
|
|
397
|
+
Some({
|
|
398
|
+
domainApi,
|
|
399
|
+
domainApiRole,
|
|
400
|
+
platformApi,
|
|
401
|
+
platformApiRole,
|
|
402
|
+
})
|
|
393
403
|
|
|
394
404
|
// AppSync Events API — companion to the GraphQL API for Sources A and B subscriptions.
|
|
395
405
|
// In platform/monolithic mode: created here as a real resource.
|
|
396
406
|
// In plugin mode: reconstructed as a phantom from platform stack exports (eventsApiArn, eventsApiDns).
|
|
397
|
-
let domainEventsApiOpt: option<AppSync_EventsApi.t> =
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
407
|
+
let domainEventsApiOpt: option<AppSync_EventsApi.t> = switch platformStackRef {
|
|
408
|
+
| None =>
|
|
409
|
+
// Browser host-shell subscribes over WebSocket with a Cognito IdToken,
|
|
410
|
+
// so the Events API must carry a Cognito auth provider. The pool is the
|
|
411
|
+
// same process-cached one the GraphQL API + config.json use.
|
|
412
|
+
let cognitoPool = Platform_Stack.resolveCognitoUserPool()
|
|
413
|
+
let awsRegion =
|
|
414
|
+
Pulumi.Config.make(Some("aws"))->Pulumi.Config.get("region")->Option.getOr("unknown")
|
|
415
|
+
Some(
|
|
416
|
+
AppSync_EventsApi.make(
|
|
417
|
+
~name="DomainEventsApi",
|
|
418
|
+
~cognitoUserPoolId=cognitoPool.poolId->Pulumi.Output.asInput,
|
|
419
|
+
~awsRegion,
|
|
420
|
+
~opts={},
|
|
421
|
+
),
|
|
422
|
+
)
|
|
423
|
+
| Some(stackRef) =>
|
|
424
|
+
let eventsApiArnOutput: Pulumi.Output.t<option<string>> =
|
|
425
|
+
stackRef->Pulumi.StackReference.getOutput("eventsApiArn")
|
|
426
|
+
let eventsApiDnsOutput: Pulumi.Output.t<option<string>> =
|
|
427
|
+
stackRef->Pulumi.StackReference.getOutput("eventsApiDns")
|
|
428
|
+
let defaultEventsOutput: Pulumi.Output.t<option<JSON.t>> =
|
|
429
|
+
stackRef->Pulumi.StackReference.getOutput("default")
|
|
430
|
+
let getFromDefault = (default, key) =>
|
|
431
|
+
default
|
|
432
|
+
->Option.flatMap(d => d->JSON.Decode.object)
|
|
433
|
+
->Option.flatMap(d => d->Dict.get(key))
|
|
434
|
+
->Option.flatMap(v => v->JSON.Decode.string)
|
|
435
|
+
let apiArn =
|
|
436
|
+
(eventsApiArnOutput, defaultEventsOutput)
|
|
437
|
+
->Pulumi.Output.all2
|
|
438
|
+
->Pulumi.Output.apply(((direct, default)) =>
|
|
439
|
+
direct->Option.orElse(getFromDefault(default, "eventsApiArn"))
|
|
413
440
|
)
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
let dns =
|
|
433
|
-
(eventsApiDnsOutput, defaultEventsOutput)
|
|
434
|
-
->Pulumi.Output.all2
|
|
435
|
-
->Pulumi.Output.apply(((direct, default)) =>
|
|
436
|
-
direct->Option.orElse(getFromDefault(default, "eventsApiDns"))
|
|
437
|
-
)
|
|
438
|
-
let api: PulumiAws.AwsNative.AppSync.Api.t = {
|
|
439
|
-
apiId: Pulumi.Output.make(""),
|
|
440
|
-
apiArn: apiArn->Pulumi.Output.apply(v => v->Option.getOr("")),
|
|
441
|
-
dns: dns->Pulumi.Output.apply(dnsHttp => ({
|
|
442
|
-
PulumiAws.AwsNative.AppSync.Api.http: ?dnsHttp,
|
|
443
|
-
}: PulumiAws.AwsNative.AppSync.Api.dns)),
|
|
444
|
-
name: Pulumi.Output.make(""),
|
|
445
|
-
}
|
|
446
|
-
let eventsApi: AppSync_EventsApi.t = {
|
|
447
|
-
name: "DomainEventsApi",
|
|
448
|
-
api,
|
|
449
|
-
defaultNamespace: None,
|
|
450
|
-
}
|
|
451
|
-
Some(eventsApi)
|
|
441
|
+
let dns =
|
|
442
|
+
(eventsApiDnsOutput, defaultEventsOutput)
|
|
443
|
+
->Pulumi.Output.all2
|
|
444
|
+
->Pulumi.Output.apply(((direct, default)) =>
|
|
445
|
+
direct->Option.orElse(getFromDefault(default, "eventsApiDns"))
|
|
446
|
+
)
|
|
447
|
+
let api: PulumiAws.AwsNative.AppSync.Api.t = {
|
|
448
|
+
apiId: Pulumi.Output.make(""),
|
|
449
|
+
apiArn: apiArn->Pulumi.Output.apply(v => v->Option.getOr("")),
|
|
450
|
+
dns: dns->Pulumi.Output.apply((dnsHttp): PulumiAws.AwsNative.AppSync.Api.dns => {
|
|
451
|
+
PulumiAws.AwsNative.AppSync.Api.http: ?dnsHttp,
|
|
452
|
+
}),
|
|
453
|
+
name: Pulumi.Output.make(""),
|
|
454
|
+
}
|
|
455
|
+
let eventsApi: AppSync_EventsApi.t = {
|
|
456
|
+
name: "DomainEventsApi",
|
|
457
|
+
api,
|
|
458
|
+
defaultNamespace: None,
|
|
452
459
|
}
|
|
460
|
+
Some(eventsApi)
|
|
461
|
+
}
|
|
453
462
|
|
|
454
463
|
// B3.3: publish the events-API endpoint + ARN to the projection-Lambda runtime
|
|
455
464
|
// builders, so a subscription-enabled Postgres read model / view slice gets the
|
|
@@ -509,8 +518,7 @@ module MakeWithConfig = (
|
|
|
509
518
|
EventMappings: ReventlessInfra.EventMapper.Mappings with module Target := Spec,
|
|
510
519
|
): (
|
|
511
520
|
ReventlessInfra.Aggregate.T with type api = Types.AppSync.api
|
|
512
|
-
) =>
|
|
513
|
-
Aggregate_Builder_Single.Make(Spec, Behavior, EventMappings)
|
|
521
|
+
) => Aggregate_Builder_Single.Make(Spec, Behavior, EventMappings)
|
|
514
522
|
/** Async variant — uses FIFO SQS channel, commands return `CommandPending`. */
|
|
515
523
|
module MakeAsync = (
|
|
516
524
|
Spec: Reventless.Aggregate.Spec,
|
|
@@ -518,8 +526,7 @@ module MakeWithConfig = (
|
|
|
518
526
|
EventMappings: ReventlessInfra.EventMapper.Mappings with module Target := Spec,
|
|
519
527
|
): (
|
|
520
528
|
ReventlessInfra.Aggregate.T with type api = Types.AppSync.api
|
|
521
|
-
) =>
|
|
522
|
-
Aggregate_Builder_Single_Async.Make(Spec, Behavior, EventMappings)
|
|
529
|
+
) => Aggregate_Builder_Single_Async.Make(Spec, Behavior, EventMappings)
|
|
523
530
|
}
|
|
524
531
|
|
|
525
532
|
module ReadModel = {
|
|
@@ -531,8 +538,7 @@ module MakeWithConfig = (
|
|
|
531
538
|
with module Spec = Spec
|
|
532
539
|
and type api = Types.AppSync.api
|
|
533
540
|
and type role = Types.AppSync.role
|
|
534
|
-
) =>
|
|
535
|
-
ReadModel_Builder_Single.Make(Spec, Mappings)
|
|
541
|
+
) => ReadModel_Builder_Single.Make(Spec, Mappings)
|
|
536
542
|
}
|
|
537
543
|
|
|
538
544
|
/** Stream-enabled read model — DynamoDB Stream + StateTopic Lambda for
|
|
@@ -546,8 +552,7 @@ module MakeWithConfig = (
|
|
|
546
552
|
with module Spec = Spec
|
|
547
553
|
and type api = Types.AppSync.api
|
|
548
554
|
and type role = Types.AppSync.role
|
|
549
|
-
) =>
|
|
550
|
-
ReadModel_Builder_Single_Stream.Make(Spec, Mappings)
|
|
555
|
+
) => ReadModel_Builder_Single_Stream.Make(Spec, Mappings)
|
|
551
556
|
}
|
|
552
557
|
|
|
553
558
|
module ExtensionPoint = {
|
|
@@ -584,8 +589,7 @@ module MakeWithConfig = (
|
|
|
584
589
|
module Mappings: ReventlessInfra.ExtensionPoint.Mappings with module Spec := Spec = {
|
|
585
590
|
module type Mapping = ReventlessInfra.ExtensionPointMapping.T
|
|
586
591
|
with module ExtensionPoint := Spec
|
|
587
|
-
let name =
|
|
588
|
-
Mapping1.Delegate.name ++ "+" ++ Mapping2.Delegate.name
|
|
592
|
+
let name = Mapping1.Delegate.name ++ "+" ++ Mapping2.Delegate.name
|
|
589
593
|
// First mapping's URL — matches the user-extension merge convention.
|
|
590
594
|
// See Make's moduleUrl comment for the %raw rationale.
|
|
591
595
|
let moduleUrl = Mapping1.moduleUrl
|
|
@@ -610,11 +614,7 @@ module MakeWithConfig = (
|
|
|
610
614
|
module type Mapping = ReventlessInfra.ExtensionPointMapping.T
|
|
611
615
|
with module ExtensionPoint := Spec
|
|
612
616
|
let name =
|
|
613
|
-
Mapping1.Delegate.name ++
|
|
614
|
-
"+" ++
|
|
615
|
-
Mapping2.Delegate.name ++
|
|
616
|
-
"+" ++
|
|
617
|
-
Mapping3.Delegate.name
|
|
617
|
+
Mapping1.Delegate.name ++ "+" ++ Mapping2.Delegate.name ++ "+" ++ Mapping3.Delegate.name
|
|
618
618
|
// First mapping's URL — matches the user-extension merge convention.
|
|
619
619
|
// See Make's moduleUrl comment for the %raw rationale.
|
|
620
620
|
let moduleUrl = Mapping1.moduleUrl
|
|
@@ -636,14 +636,12 @@ module MakeWithConfig = (
|
|
|
636
636
|
): ReventlessInfra.Extension.Blueprint => {
|
|
637
637
|
module Spec = Mapping.ExtensionPoint
|
|
638
638
|
module CompiledMapping = ReventlessInfra.ExtensionMapping.Make(Mapping)
|
|
639
|
-
module type Mapping = ReventlessInfra.ExtensionMapping.T
|
|
640
|
-
with module ExtensionPoint := Spec
|
|
639
|
+
module type Mapping = ReventlessInfra.ExtensionMapping.T with module ExtensionPoint := Spec
|
|
641
640
|
let name = Mapping.Delegate.name
|
|
642
641
|
let moduleUrl = Mapping.moduleUrl
|
|
643
642
|
let delegateModuleUrl = Mapping.delegateModuleUrl
|
|
644
643
|
let mappings: array<module(Mapping)> = [module(CompiledMapping)]
|
|
645
644
|
}
|
|
646
|
-
|
|
647
645
|
}
|
|
648
646
|
|
|
649
647
|
module Task = {
|
|
@@ -658,8 +656,9 @@ module MakeWithConfig = (
|
|
|
658
656
|
module Make = (
|
|
659
657
|
Spec: Reventless.StateChangeSlice.Spec,
|
|
660
658
|
Behavior: Reventless.StateChangeSlice.Behavior with module Spec := Spec,
|
|
661
|
-
): (
|
|
662
|
-
|
|
659
|
+
): (
|
|
660
|
+
ReventlessInfra.StateChangeSlice.T with module Spec = Spec
|
|
661
|
+
) => StateChangeSlice_Builder.Make(Spec, Behavior)
|
|
663
662
|
/** Async variant — uses FIFO SQS channel, commands return `CommandPending`. */
|
|
664
663
|
module MakeAsync = (
|
|
665
664
|
Spec: Reventless.StateChangeSlice.Spec,
|
|
@@ -742,7 +741,6 @@ module MakeWithConfig = (
|
|
|
742
741
|
| None => resolveHookedApi()
|
|
743
742
|
}
|
|
744
743
|
|
|
745
|
-
|
|
746
744
|
let hooks: ReventlessCore.Plugin_Helpers.platformHooks = {
|
|
747
745
|
// AWS uses Interstack for admin extension points — leave ref at empty dict.
|
|
748
746
|
adminExtensionPoints: ref(Pulumi.Output.make(Dict.make())),
|
|
@@ -776,7 +774,6 @@ module MakeWithConfig = (
|
|
|
776
774
|
~opts,
|
|
777
775
|
)
|
|
778
776
|
},
|
|
779
|
-
|
|
780
777
|
// Admin-side schema push, gated on admin DataSources via adminBarrier.
|
|
781
778
|
// Platform_Admin.construct invokes this and chains createResolvers behind
|
|
782
779
|
// the returned Output — so admin CreateResolver calls fire only after
|
|
@@ -793,7 +790,6 @@ module MakeWithConfig = (
|
|
|
793
790
|
// before the resource resolves, so admin resolvers chained on the API are
|
|
794
791
|
// already ordered after the schema is ACTIVE. No push.
|
|
795
792
|
preAdminResolversSchemaHook: (~adminBarrier) => adminBarrier,
|
|
796
|
-
|
|
797
793
|
// Push the plugin's standalone subgraph document to the plugin's OWN
|
|
798
794
|
// source API — a single writer by construction. The returned Output gates
|
|
799
795
|
// resolver creation and deployPlugin additionally sequences the
|
|
@@ -802,23 +798,24 @@ module MakeWithConfig = (
|
|
|
802
798
|
// re-merges automatically.
|
|
803
799
|
preResolversSchemaHook: (~name, ~version, pluginFragment) => {
|
|
804
800
|
let sdl = AppSync_Adapter.stitchStandaloneWithAwsDirectives(~fragment=pluginFragment)
|
|
805
|
-
let pushed =
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
801
|
+
let pushed = domainApi->Pulumi.Output.flatMap(api =>
|
|
802
|
+
api.id->Pulumi.Output.flatMap(apiId => {
|
|
803
|
+
log.info(
|
|
804
|
+
~comp="preResolversSchemaHook",
|
|
805
|
+
`Pushing subgraph schema for ${name}@${version} to source API ${apiId}`,
|
|
806
|
+
)
|
|
807
|
+
let client = AppSync_Adapter.getClient()
|
|
808
|
+
client
|
|
809
|
+
->AppSync_Adapter.startSchemaCreationRetrying({apiId, definition: sdl})
|
|
810
|
+
->Promise.then(
|
|
811
|
+
async _ => {
|
|
816
812
|
await AppSync_Adapter.waitForSchemaActive(client, apiId)
|
|
817
813
|
log.info(~comp="preResolversSchemaHook", "subgraph schema is ACTIVE")
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
)
|
|
814
|
+
},
|
|
815
|
+
)
|
|
816
|
+
->Pulumi.Output.fromPromise
|
|
817
|
+
})
|
|
818
|
+
)
|
|
822
819
|
mergedSchemaPushedRef := Some(pushed)
|
|
823
820
|
pushed
|
|
824
821
|
},
|
|
@@ -864,98 +861,102 @@ module MakeWithConfig = (
|
|
|
864
861
|
~epQueueUrl=resource.id->Pulumi.Output.make,
|
|
865
862
|
(),
|
|
866
863
|
)
|
|
867
|
-
| None =>
|
|
868
|
-
log.warn(~comp="Platform", "heartbeat EP channel has no resources")
|
|
864
|
+
| None => log.warn(~comp="Platform", "heartbeat EP channel has no resources")
|
|
869
865
|
}
|
|
870
866
|
},
|
|
871
|
-
|
|
872
867
|
// Phase 4 + 5: wire StateTopic and EventLogSubscription Lambdas per plugin.
|
|
873
868
|
// Only active when the Events API resource exists (platform/monolithic mode).
|
|
874
|
-
subscriptionInfraHook: ?
|
|
875
|
-
(
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
869
|
+
subscriptionInfraHook: ?(
|
|
870
|
+
domainEventsApiOpt->Option.map(eventsApi =>
|
|
871
|
+
(params: ReventlessCore.Plugin_Helpers.subscriptionInfraParams) => {
|
|
872
|
+
let {pluginName, allQueryDbs, allEventTopics, eventLogEntries, opts} = params
|
|
873
|
+
let customOpts =
|
|
874
|
+
opts->ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions
|
|
875
|
+
// StateTopic Lambda per stream-enabled QueryDb — publishes row changes
|
|
876
|
+
// to AppSync Events channels. No GraphQL Subscription resolver is
|
|
877
|
+
// wired: Source B uses the Events WebSocket directly, not @aws_subscribe.
|
|
878
|
+
allQueryDbs->Dict.forEachWithKey((_queryDbOutputs, readModelName) => {
|
|
879
|
+
if QueryDbStorage_DynamoDbStream.streamRegistry->Set.has(readModelName) {
|
|
880
|
+
// Channel root MUST equal what the host-shell subscribes to. The
|
|
881
|
+
// AutoUI manifest sets queryableDef.queryField = listFieldName
|
|
882
|
+
// (plural, e.g. "Catalog_Products") and AutoLive subscribes on that.
|
|
883
|
+
// Publishing on the singular returnTypeName ("Catalog_Product")
|
|
884
|
+
// would land descriptors on a channel no client listens to.
|
|
885
|
+
let topicName =
|
|
886
|
+
ReventlessCore.Plugin_Helpers.queryFieldNamesRegistry
|
|
887
|
+
->Dict.get(readModelName)
|
|
888
|
+
->Option.map(qn => qn.listFieldName)
|
|
889
|
+
->Option.getOr(readModelName)
|
|
890
|
+
StateTopic_AppSync.make(
|
|
891
|
+
~readModelName,
|
|
892
|
+
~topicName,
|
|
893
|
+
~allQueryDbs,
|
|
894
|
+
~eventsApi,
|
|
895
|
+
~opts=customOpts,
|
|
896
|
+
)
|
|
897
|
+
}
|
|
898
|
+
})
|
|
903
899
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
900
|
+
// Phase 5: EventLogSubscription per SNS-backed event log entry.
|
|
901
|
+
// DynamoDB stream event topics (Category, DCB) are skipped — no SNS subscription needed.
|
|
902
|
+
eventLogEntries->Array.forEach(entry => {
|
|
903
|
+
// Aggregate EventTopics are keyed by Spec.name (= displayName).
|
|
904
|
+
// DCB EventTopic is keyed by busKey (= pluginName ++ "DcbEventLog").
|
|
905
|
+
let isSns =
|
|
906
|
+
EventTopicPublisher_SNS.snsRegistry->Set.has(entry.displayName) ||
|
|
907
|
+
EventTopicPublisher_SNS.snsRegistry->Set.has(entry.busKey)
|
|
908
|
+
let topicOutputs =
|
|
909
|
+
allEventTopics
|
|
910
|
+
->Dict.get(entry.displayName)
|
|
911
|
+
->Option.orElse(allEventTopics->Dict.get(entry.busKey))
|
|
912
|
+
isSns
|
|
913
|
+
? topicOutputs->Option.forEach(
|
|
914
|
+
outputs =>
|
|
915
|
+
EventLogSubscription_AppSync.make(
|
|
916
|
+
~name=entry.displayName,
|
|
917
|
+
~topicName=entry.displayName,
|
|
918
|
+
~eventTopicOutputs=outputs,
|
|
919
|
+
~eventsApi,
|
|
920
|
+
~opts=customOpts,
|
|
921
|
+
),
|
|
924
922
|
)
|
|
925
|
-
)
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
923
|
+
: ()
|
|
924
|
+
// Register this event log with the upload claimer if — and only if —
|
|
925
|
+
// its events declare a `@storageRef` field. An event log that declares
|
|
926
|
+
// none is not registered, so a platform whose plugins declare no store
|
|
927
|
+
// provisions no claimer at all. `isSns` is the same synchronous answer
|
|
928
|
+
// the subscription above turns on, so the two cannot disagree about
|
|
929
|
+
// which channel an event log publishes through.
|
|
930
|
+
topicOutputs->Option.forEach(
|
|
931
|
+
outputs =>
|
|
932
|
+
Upload_Claim_S3.make(
|
|
933
|
+
~plugin=pluginName,
|
|
934
|
+
~eventLogName=entry.displayName,
|
|
935
|
+
~eventSchema=entry.eventSchema,
|
|
936
|
+
~eventTopicOutputs=outputs,
|
|
937
|
+
~isStreamBacked=!isSns,
|
|
938
|
+
),
|
|
940
939
|
)
|
|
941
|
-
)
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
940
|
+
})
|
|
941
|
+
// Finalize the shared StateTopic Lambda + IAM + per-stream ESMs from the
|
|
942
|
+
// entries the loop above just registered. Must run INSIDE this hook because
|
|
943
|
+
// Plugin_Builder fires it from inside a Pulumi.Output.apply chain — calling
|
|
944
|
+
// `finish` from deployPlugin (after P.make returns) would see the registry
|
|
945
|
+
// empty because the hook hasn't run yet. Admin's hook fires synchronously,
|
|
946
|
+
// but the call site is unified here so admin and plugins share one path.
|
|
947
|
+
StateTopic_AppSync.finish(~eventsApi, ~opts={})
|
|
948
|
+
// Same timing constraint, same reason: the claimer's registry is filled
|
|
949
|
+
// by the loop just above and drained here.
|
|
950
|
+
Upload_Claim_S3.finish(~plugin=pluginName, ~stores=claimStores, ~opts=customOpts)
|
|
951
|
+
}
|
|
952
|
+
)
|
|
954
953
|
),
|
|
955
954
|
}
|
|
956
955
|
|
|
957
956
|
// Apply Plugin functor with the platform hooks, then constrain the result to Plugin.T.
|
|
958
|
-
module PluginBuilderImpl = Plugin.Make({
|
|
957
|
+
module PluginBuilderImpl = Plugin.Make({
|
|
958
|
+
let hooks = hooks
|
|
959
|
+
})
|
|
959
960
|
module Plugin: ReventlessInfra.Plugin.T
|
|
960
961
|
with type api = Types.AppSync.api
|
|
961
962
|
and type role = Types.AppSync.role
|
|
@@ -995,9 +996,8 @@ module MakeWithConfig = (
|
|
|
995
996
|
// via the auto-resolver flow. Internal-protocol variants (Heartbeat, Connect,
|
|
996
997
|
// Disconnect, ReportIncompatibility) carry `@noApi` and are filtered out before
|
|
997
998
|
// SDL/resolver generation.
|
|
998
|
-
module PluginAggregate:
|
|
999
|
-
|
|
1000
|
-
) = Aggregate_Builder_Single.Make(
|
|
999
|
+
module PluginAggregate: ReventlessInfra.Aggregate.T
|
|
1000
|
+
with type api = Types.AppSync.api = Aggregate_Builder_Single.Make(
|
|
1001
1001
|
ReventlessCore.PluginSpec,
|
|
1002
1002
|
ReventlessCore.PluginBehavior,
|
|
1003
1003
|
ReventlessInfra.NoEventMappings.Make(ReventlessCore.PluginSpec),
|
|
@@ -1061,8 +1061,9 @@ module MakeWithConfig = (
|
|
|
1061
1061
|
// this is how RM/SVS projections are fed. One subscriber per (feed, log)
|
|
1062
1062
|
// keeps checkpoints isolated.
|
|
1063
1063
|
let feedTargets = (~connectionConfig, ~logName, ~feed, ~isClassic) =>
|
|
1064
|
-
PgProjectionFeed.getFeedQueues()->Array.filterMap(fq =>
|
|
1065
|
-
|
|
1064
|
+
PgProjectionFeed.getFeedQueues()->Array.filterMap(fq => {
|
|
1065
|
+
let included = isClassic ? fq.includeClassic : fq.includeDcb
|
|
1066
|
+
included
|
|
1066
1067
|
? Some({
|
|
1067
1068
|
PgChangeFeedRelay_Builder.connectionConfig,
|
|
1068
1069
|
logName,
|
|
@@ -1072,7 +1073,7 @@ module MakeWithConfig = (
|
|
|
1072
1073
|
targetQueueArn: fq.arn,
|
|
1073
1074
|
})
|
|
1074
1075
|
: None
|
|
1075
|
-
)
|
|
1076
|
+
})
|
|
1076
1077
|
let dcbLogs = switch DcbBackend.get() {
|
|
1077
1078
|
| Some({connectionConfig}) =>
|
|
1078
1079
|
DcbBackend.getRelayLogs()->Array.flatMap(entry => {
|
|
@@ -1249,12 +1250,10 @@ module MakeWithConfig = (
|
|
|
1249
1250
|
// deployPlatform (staged) and each plugin with deployPlugin — makePlatform
|
|
1250
1251
|
// predates the merge path and never gained merged wiring.
|
|
1251
1252
|
failwith(
|
|
1252
|
-
"makePlatform is not supported on AWS — deploy the platform with deployPlatform and " ++
|
|
1253
|
-
"each plugin with deployPlugin (merged-API composition).",
|
|
1253
|
+
"makePlatform is not supported on AWS — deploy the platform with deployPlatform and " ++ "each plugin with deployPlugin (merged-API composition).",
|
|
1254
1254
|
)
|
|
1255
1255
|
}
|
|
1256
1256
|
|
|
1257
|
-
|
|
1258
1257
|
// Merged-mode outputs of deployPlatform — the merged API(s), plus the
|
|
1259
1258
|
// deploy-time merge gates (Outputs that resolve on MERGE_SUCCESS and fail
|
|
1260
1259
|
// the deploy on MERGE_FAILED; folded into the ARN exports so they are
|
|
@@ -1358,12 +1357,13 @@ module MakeWithConfig = (
|
|
|
1358
1357
|
splitApiOutputsRef := Some({platformApi, platformApiRole})
|
|
1359
1358
|
switch apiConfigRef.contents {
|
|
1360
1359
|
| Some(c) =>
|
|
1361
|
-
apiConfigRef :=
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1360
|
+
apiConfigRef :=
|
|
1361
|
+
Some({
|
|
1362
|
+
domainApi: c.domainApi,
|
|
1363
|
+
domainApiRole: c.domainApiRole,
|
|
1364
|
+
platformApi,
|
|
1365
|
+
platformApiRole,
|
|
1366
|
+
})
|
|
1367
1367
|
| None => ()
|
|
1368
1368
|
}
|
|
1369
1369
|
}
|
|
@@ -1434,21 +1434,18 @@ module MakeWithConfig = (
|
|
|
1434
1434
|
// targets a non-existent ARN, breaking the
|
|
1435
1435
|
// admin → plugin EventCollector → ConnectPlugin round-trip and leaving
|
|
1436
1436
|
// the Plugin read model empty.
|
|
1437
|
-
let pluginEpEventTopicArn =
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
| None => Pulumi.Output.make("NOT_AVAILABLE")
|
|
1450
|
-
}
|
|
1451
|
-
)
|
|
1437
|
+
let pluginEpEventTopicArn = admin.extensionPointsOutputs->Pulumi.Output.flatMap(eps =>
|
|
1438
|
+
switch eps->Array.find(ep => ep.name == ReventlessInfra.PluginExtensionPointSpec.name) {
|
|
1439
|
+
| Some(ep) =>
|
|
1440
|
+
ep.eventTopic->Pulumi.Output.flatMap(et =>
|
|
1441
|
+
switch et.resources->Array.get(0) {
|
|
1442
|
+
| Some(r) => r.urn
|
|
1443
|
+
| None => Pulumi.Output.make("NOT_AVAILABLE")
|
|
1444
|
+
}
|
|
1445
|
+
)
|
|
1446
|
+
| None => Pulumi.Output.make("NOT_AVAILABLE")
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
1452
1449
|
|
|
1453
1450
|
PluginRuntime_Builder.registerConfig(
|
|
1454
1451
|
~eventTopicArn=pluginEpEventTopicArn,
|
|
@@ -1555,7 +1552,10 @@ module MakeWithConfig = (
|
|
|
1555
1552
|
api.uris->Pulumi.Output.apply(uris => uris.graphQL)
|
|
1556
1553
|
),
|
|
1557
1554
|
)
|
|
1558
|
-
Pulumi.Pulumi.export(
|
|
1555
|
+
Pulumi.Pulumi.export(
|
|
1556
|
+
"platformApiRoleArn",
|
|
1557
|
+
platformApiRole->Pulumi.Output.flatMap(role => role.arn),
|
|
1558
|
+
)
|
|
1559
1559
|
} else {
|
|
1560
1560
|
// Platform API exports (unified mode — same resource as Domain API).
|
|
1561
1561
|
Pulumi.Pulumi.export("platformApiId", domainApi->Pulumi.Output.flatMap(api => api.id))
|
|
@@ -1565,16 +1565,17 @@ module MakeWithConfig = (
|
|
|
1565
1565
|
api.uris->Pulumi.Output.apply(uris => uris.graphQL)
|
|
1566
1566
|
),
|
|
1567
1567
|
)
|
|
1568
|
-
Pulumi.Pulumi.export(
|
|
1568
|
+
Pulumi.Pulumi.export(
|
|
1569
|
+
"platformApiRoleArn",
|
|
1570
|
+
domainApiRole->Pulumi.Output.flatMap(role => role.arn),
|
|
1571
|
+
)
|
|
1569
1572
|
}
|
|
1570
1573
|
|
|
1571
1574
|
// Domain API exports.
|
|
1572
1575
|
Pulumi.Pulumi.export("domainApiId", domainApi->Pulumi.Output.flatMap(api => api.id))
|
|
1573
1576
|
Pulumi.Pulumi.export(
|
|
1574
1577
|
"domainApiEndpoint",
|
|
1575
|
-
domainApi->Pulumi.Output.flatMap(api =>
|
|
1576
|
-
api.uris->Pulumi.Output.apply(uris => uris.graphQL)
|
|
1577
|
-
),
|
|
1578
|
+
domainApi->Pulumi.Output.flatMap(api => api.uris->Pulumi.Output.apply(uris => uris.graphQL)),
|
|
1578
1579
|
)
|
|
1579
1580
|
Pulumi.Pulumi.export("domainApiRoleArn", domainApiRole->Pulumi.Output.flatMap(role => role.arn))
|
|
1580
1581
|
|
|
@@ -1587,10 +1588,7 @@ module MakeWithConfig = (
|
|
|
1587
1588
|
switch mergedOutputs {
|
|
1588
1589
|
| Some({domainMerged, platformMerged, domainMergeGate, platformMergeGate}) =>
|
|
1589
1590
|
let mergeGatedArn = (merged: AppSync_MergedApi.t, gate: Pulumi.Output.t<unit>) =>
|
|
1590
|
-
(
|
|
1591
|
-
merged.api->Pulumi.Output.flatMap((api: PulumiAws.AppSync.GraphQLApi.t) => api.arn),
|
|
1592
|
-
gate,
|
|
1593
|
-
)
|
|
1591
|
+
(merged.api->Pulumi.Output.flatMap((api: PulumiAws.AppSync.GraphQLApi.t) => api.arn), gate)
|
|
1594
1592
|
->Pulumi.Output.all2
|
|
1595
1593
|
->Pulumi.Output.apply(((arn, _)) => arn)
|
|
1596
1594
|
let mergedEndpoint = (merged: AppSync_MergedApi.t) =>
|
|
@@ -1663,13 +1661,15 @@ module MakeWithConfig = (
|
|
|
1663
1661
|
| Some({platformMerged}) => platformMerged.api
|
|
1664
1662
|
| None => platformApi
|
|
1665
1663
|
}
|
|
1666
|
-
let resolvedDomainApiEndpoint =
|
|
1667
|
-
|
|
1668
|
-
|
|
1664
|
+
let resolvedDomainApiEndpoint =
|
|
1665
|
+
clientDomainApi->Pulumi.Output.flatMap(api =>
|
|
1666
|
+
api.uris->Pulumi.Output.apply(uris => uris.graphQL)
|
|
1667
|
+
)
|
|
1669
1668
|
let resolvedDomainApiRoleArn = domainApiRole->Pulumi.Output.flatMap(role => role.arn)
|
|
1670
|
-
let resolvedPlatformApiEndpoint =
|
|
1671
|
-
|
|
1672
|
-
|
|
1669
|
+
let resolvedPlatformApiEndpoint =
|
|
1670
|
+
clientPlatformApi->Pulumi.Output.flatMap(api =>
|
|
1671
|
+
api.uris->Pulumi.Output.apply(uris => uris.graphQL)
|
|
1672
|
+
)
|
|
1673
1673
|
let resolvedPlatformApiRoleArn = platformApiRole->Pulumi.Output.flatMap(role => role.arn)
|
|
1674
1674
|
// Collect admin aggregate + read model resources.
|
|
1675
1675
|
let adminResourcesOutput =
|
|
@@ -1709,7 +1709,13 @@ module MakeWithConfig = (
|
|
|
1709
1709
|
adminResourcesOutput,
|
|
1710
1710
|
)
|
|
1711
1711
|
->Pulumi.Output.all5
|
|
1712
|
-
->Pulumi.Output.apply(((
|
|
1712
|
+
->Pulumi.Output.apply(((
|
|
1713
|
+
domainApiEndpoint,
|
|
1714
|
+
domainApiRoleArn,
|
|
1715
|
+
platformApiEndpoint,
|
|
1716
|
+
platformApiRoleArn,
|
|
1717
|
+
adminResources,
|
|
1718
|
+
)) => {
|
|
1713
1719
|
let region =
|
|
1714
1720
|
Pulumi.Config.make(Some("aws"))->Pulumi.Config.get("region")->Option.getOr("unknown")
|
|
1715
1721
|
ReventlessCore.Plugin_Helpers.firePlatformDeployedHook({
|
|
@@ -1753,7 +1759,8 @@ module MakeWithConfig = (
|
|
|
1753
1759
|
switch c {
|
|
1754
1760
|
| ObjectStore({plugin, store}) => Some((plugin, store))
|
|
1755
1761
|
| Geocoding
|
|
1756
|
-
| Messaging =>
|
|
1762
|
+
| Messaging =>
|
|
1763
|
+
None
|
|
1757
1764
|
}
|
|
1758
1765
|
)
|
|
1759
1766
|
->Array.reduce([], (acc, (plugin, store)) =>
|
|
@@ -1843,8 +1850,7 @@ module MakeWithConfig = (
|
|
|
1843
1850
|
log.info(
|
|
1844
1851
|
~comp="Platform:deployPlatform",
|
|
1845
1852
|
`object store ${plugin}.${store}: never-claimed uploads under ${prefix}/ expire after ` ++
|
|
1846
|
-
`${days->Int.toString} days. Claimed objects and objects minted before the claim ` ++
|
|
1847
|
-
`component existed carry no pending tag and are outside the rule.`,
|
|
1853
|
+
`${days->Int.toString} days. Claimed objects and objects minted before the claim ` ++ `component existed carry no pending tag and are outside the rule.`,
|
|
1848
1854
|
)
|
|
1849
1855
|
})
|
|
1850
1856
|
)
|
|
@@ -1897,8 +1903,9 @@ module MakeWithConfig = (
|
|
|
1897
1903
|
->Dict.get(bucketName)
|
|
1898
1904
|
->Option.map(b => {
|
|
1899
1905
|
ReventlessInfra.Platform.id: bucketName,
|
|
1900
|
-
prefixes: declaredStoreServices
|
|
1901
|
-
|
|
1906
|
+
prefixes: declaredStoreServices->Array.filterMap(
|
|
1907
|
+
((_, prefix, bn, _)) => bn == bucketName ? Some(prefix) : None,
|
|
1908
|
+
),
|
|
1902
1909
|
bucketId: b.bucketId,
|
|
1903
1910
|
bucketArn: b.bucketArn,
|
|
1904
1911
|
bucketRegionalDomainName: b.bucketRegionalDomainName,
|
|
@@ -1956,7 +1963,7 @@ module MakeWithConfig = (
|
|
|
1956
1963
|
let uploadServiceStores =
|
|
1957
1964
|
declaredStoreServices
|
|
1958
1965
|
->Array.map(((qualified, keyPrefix, _logical, physicalBucketName)) => {
|
|
1959
|
-
Upload_Presign_S3.qualified
|
|
1966
|
+
Upload_Presign_S3.qualified,
|
|
1960
1967
|
bucketName: physicalBucketName,
|
|
1961
1968
|
servedPrefix: keyPrefix,
|
|
1962
1969
|
})
|
|
@@ -1993,10 +2000,10 @@ module MakeWithConfig = (
|
|
|
1993
2000
|
"objectStores",
|
|
1994
2001
|
declaredStoreEndpoints
|
|
1995
2002
|
->Array.map(e =>
|
|
1996
|
-
Pulumi.Output.all2((
|
|
1997
|
-
bucketName,
|
|
1998
|
-
baseUrl,
|
|
1999
|
-
)) => (e, bucketName, baseUrl))
|
|
2003
|
+
Pulumi.Output.all2((
|
|
2004
|
+
e.bucketName,
|
|
2005
|
+
e.baseUrl->Pulumi.Output.allOpt,
|
|
2006
|
+
))->Pulumi.Output.apply(((bucketName, baseUrl)) => (e, bucketName, baseUrl))
|
|
2000
2007
|
)
|
|
2001
2008
|
->Pulumi.Output.all
|
|
2002
2009
|
->Pulumi.Output.apply(resolved =>
|
|
@@ -2053,12 +2060,7 @@ module MakeWithConfig = (
|
|
|
2053
2060
|
Util_LocalConfig.get("hostUiProdStacks")
|
|
2054
2061
|
->Option.map(Util_HostUiDomain.parseProdStacks)
|
|
2055
2062
|
->Option.getOr(Util_HostUiDomain.defaultProdStacks)
|
|
2056
|
-
let fqdn = Util_HostUiDomain.deriveFqdn(
|
|
2057
|
-
~baseName,
|
|
2058
|
-
~stack,
|
|
2059
|
-
~baseDomain=bd,
|
|
2060
|
-
~prodStacks,
|
|
2061
|
-
)
|
|
2063
|
+
let fqdn = Util_HostUiDomain.deriveFqdn(~baseName, ~stack, ~baseDomain=bd, ~prodStacks)
|
|
2062
2064
|
Some({Plugin_Stack.fqdn, hostedZoneId: hz})
|
|
2063
2065
|
| _ => None
|
|
2064
2066
|
}
|
|
@@ -2186,8 +2188,7 @@ module MakeWithConfig = (
|
|
|
2186
2188
|
`provisions no place index.\n` ++
|
|
2187
2189
|
` Add \`let placeIndex = ReventlessAws.Capability_Geocoding_AwsLocation.make(~name=…)\` ` ++
|
|
2188
2190
|
`and pass \`~geocoderPlaceIndex=placeIndex\` in \`~hostUiBundle\`.\n` ++
|
|
2189
|
-
` The declaration is generated from the plugins' capabilities.json — regenerate with ` ++
|
|
2190
|
-
`\`pnpm run generate:platform\` if it is stale.`,
|
|
2191
|
+
` The declaration is generated from the plugins' capabilities.json — regenerate with ` ++ `\`pnpm run generate:platform\` if it is stale.`,
|
|
2191
2192
|
)
|
|
2192
2193
|
}
|
|
2193
2194
|
|
|
@@ -2250,8 +2251,7 @@ module MakeWithConfig = (
|
|
|
2250
2251
|
`instead — every message is logged and none is sent, and the address is optional.\n` ++
|
|
2251
2252
|
` The root must also pass \`~messagingSender\` in \`~hostUiBundle\`, from ` ++
|
|
2252
2253
|
`\`ReventlessAws.Capability_Messaging.make(~name=…)\`.\n` ++
|
|
2253
|
-
` The declaration is generated from the plugins' capabilities.json — regenerate with ` ++
|
|
2254
|
-
`\`pnpm run generate:platform\` if it is stale.`,
|
|
2254
|
+
` The declaration is generated from the plugins' capabilities.json — regenerate with ` ++ `\`pnpm run generate:platform\` if it is stale.`,
|
|
2255
2255
|
)
|
|
2256
2256
|
}
|
|
2257
2257
|
|
|
@@ -2514,7 +2514,11 @@ module MakeWithConfig = (
|
|
|
2514
2514
|
// Expose deploy target via hooks so Plugin_Builder can stamp pluginDefinition.apiTarget.
|
|
2515
2515
|
// This must be set before P.make() and is captured synchronously by Plugin_Builder
|
|
2516
2516
|
// (same timing requirement as hooks.api/apiRole).
|
|
2517
|
-
hooks.deployTarget :=
|
|
2517
|
+
hooks.deployTarget :=
|
|
2518
|
+
switch apiTarget {
|
|
2519
|
+
| Domain => "Domain"
|
|
2520
|
+
| Platform => "Platform"
|
|
2521
|
+
}
|
|
2518
2522
|
// Each plugin stack creates its own scheduler (closures can't cross stacks).
|
|
2519
2523
|
let scheduler = makeScheduler()
|
|
2520
2524
|
hooks.scheduler := Some(scheduler)
|
|
@@ -2532,8 +2536,9 @@ module MakeWithConfig = (
|
|
|
2532
2536
|
// The bucket name comes from the platform stack (deploy the platform first).
|
|
2533
2537
|
let offloadBucketName: Pulumi.Output.t<string> = switch platformStackRef {
|
|
2534
2538
|
| Some(stackRef) =>
|
|
2535
|
-
(
|
|
2536
|
-
|
|
2539
|
+
(
|
|
2540
|
+
stackRef->Pulumi.StackReference.getOutput("offloadBucket"): Pulumi.Output.t<option<string>>
|
|
2541
|
+
)->Pulumi.Output.apply(o => o->Option.getOr("OFFLOAD_BUCKET_PENDING_PLATFORM_DEPLOY"))
|
|
2537
2542
|
| None => Pulumi.Output.make("OFFLOAD_BUCKET_PENDING_PLATFORM_DEPLOY")
|
|
2538
2543
|
}
|
|
2539
2544
|
// The key this deploy wrote for the plugin's structure, exported below. The
|
|
@@ -2600,8 +2605,9 @@ module MakeWithConfig = (
|
|
|
2600
2605
|
let geocoderPlaceIndex: Pulumi.Output.t<string> = switch platformStackRef {
|
|
2601
2606
|
| Some(stackRef) =>
|
|
2602
2607
|
(
|
|
2603
|
-
stackRef->Pulumi.StackReference.getOutput("geocoderPlaceIndex"):
|
|
2604
|
-
|
|
2608
|
+
stackRef->Pulumi.StackReference.getOutput("geocoderPlaceIndex"): Pulumi.Output.t<
|
|
2609
|
+
option<string>,
|
|
2610
|
+
>
|
|
2605
2611
|
)->Pulumi.Output.apply(o => o->Option.getOr(""))
|
|
2606
2612
|
| None => geocoderPlaceIndexRef.contents
|
|
2607
2613
|
}
|
|
@@ -2615,8 +2621,9 @@ module MakeWithConfig = (
|
|
|
2615
2621
|
let messagingEmailSender: Pulumi.Output.t<string> = switch platformStackRef {
|
|
2616
2622
|
| Some(stackRef) =>
|
|
2617
2623
|
(
|
|
2618
|
-
stackRef->Pulumi.StackReference.getOutput("messagingEmailSender"):
|
|
2619
|
-
|
|
2624
|
+
stackRef->Pulumi.StackReference.getOutput("messagingEmailSender"): Pulumi.Output.t<
|
|
2625
|
+
option<string>,
|
|
2626
|
+
>
|
|
2620
2627
|
)->Pulumi.Output.apply(o => o->Option.getOr(""))
|
|
2621
2628
|
| None => messagingEmailSenderRef.contents
|
|
2622
2629
|
}
|
|
@@ -2630,15 +2637,13 @@ module MakeWithConfig = (
|
|
|
2630
2637
|
let messagingEmailProvider: Pulumi.Output.t<string> = switch platformStackRef {
|
|
2631
2638
|
| Some(stackRef) =>
|
|
2632
2639
|
(
|
|
2633
|
-
stackRef->Pulumi.StackReference.getOutput("messagingEmailProvider"):
|
|
2634
|
-
|
|
2640
|
+
stackRef->Pulumi.StackReference.getOutput("messagingEmailProvider"): Pulumi.Output.t<
|
|
2641
|
+
option<string>,
|
|
2642
|
+
>
|
|
2635
2643
|
)->Pulumi.Output.apply(o => o->Option.getOr(""))
|
|
2636
2644
|
| None => messagingEmailProviderRef.contents
|
|
2637
2645
|
}
|
|
2638
|
-
PluginRuntime_Builder.registerCapabilityEnv(
|
|
2639
|
-
"MESSAGING_EMAIL_PROVIDER",
|
|
2640
|
-
messagingEmailProvider,
|
|
2641
|
-
)
|
|
2646
|
+
PluginRuntime_Builder.registerCapabilityEnv("MESSAGING_EMAIL_PROVIDER", messagingEmailProvider)
|
|
2642
2647
|
|
|
2643
2648
|
module P = unpack(plugin)
|
|
2644
2649
|
let pluginComponent = P.make()
|
|
@@ -2687,8 +2692,7 @@ module MakeWithConfig = (
|
|
|
2687
2692
|
let defaultOutput: Pulumi.Output.t<option<JSON.t>> =
|
|
2688
2693
|
stackRef->Pulumi.StackReference.getOutput("default")
|
|
2689
2694
|
let getMergedExport = (key: string): Pulumi.Output.t<string> => {
|
|
2690
|
-
let direct: Pulumi.Output.t<option<string>> =
|
|
2691
|
-
stackRef->Pulumi.StackReference.getOutput(key)
|
|
2695
|
+
let direct: Pulumi.Output.t<option<string>> = stackRef->Pulumi.StackReference.getOutput(key)
|
|
2692
2696
|
(direct, defaultOutput)
|
|
2693
2697
|
->Pulumi.Output.all2
|
|
2694
2698
|
->Pulumi.Output.apply(((direct, default)) =>
|
|
@@ -2778,12 +2782,9 @@ module MakeWithConfig = (
|
|
|
2778
2782
|
messagingEmailSender,
|
|
2779
2783
|
)
|
|
2780
2784
|
->Pulumi.Output.all4
|
|
2781
|
-
->Pulumi.Output.apply((
|
|
2782
|
-
_,
|
|
2783
|
-
|
|
2784
|
-
string,
|
|
2785
|
-
string,
|
|
2786
|
-
))) => {
|
|
2785
|
+
->Pulumi.Output.apply((
|
|
2786
|
+
(structure, objectStores, placeIndex, emailSender): (_, option<JSON.t>, string, string),
|
|
2787
|
+
) => {
|
|
2787
2788
|
// ── Declared capabilities ──────────────────────────────────────────
|
|
2788
2789
|
//
|
|
2789
2790
|
// A slice that names `Geocoding` in `capabilityNeeds` says its
|
|
@@ -2819,14 +2820,12 @@ module MakeWithConfig = (
|
|
|
2819
2820
|
->Array.map(u =>
|
|
2820
2821
|
switch u.need {
|
|
2821
2822
|
| Geocoding =>
|
|
2822
|
-
`\n Geocoding is \`Capability_Geocoding_AwsLocation.make\`, passed to the ` ++
|
|
2823
|
-
`platform as \`~geocoderPlaceIndex\`.`
|
|
2823
|
+
`\n Geocoding is \`Capability_Geocoding_AwsLocation.make\`, passed to the ` ++ `platform as \`~geocoderPlaceIndex\`.`
|
|
2824
2824
|
| Messaging =>
|
|
2825
2825
|
`\n Messaging is \`Capability_Messaging.make\`, passed to the platform ` ++
|
|
2826
2826
|
`as \`~messagingSender\`. The sender itself is configuration and has no ` ++
|
|
2827
2827
|
`default: set \`platform:messagingEmailSender\` in Pulumi.<stack>.yaml (or ` ++
|
|
2828
|
-
`REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES — or ` ++
|
|
2829
|
-
`\`platform:messagingEmailProvider: log\` to log every message and send none.`
|
|
2828
|
+
`REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES — or ` ++ `\`platform:messagingEmailProvider: log\` to log every message and send none.`
|
|
2830
2829
|
}
|
|
2831
2830
|
)
|
|
2832
2831
|
// One line per capability, not per declaring component: two slices
|
|
@@ -2837,8 +2836,7 @@ module MakeWithConfig = (
|
|
|
2837
2836
|
)
|
|
2838
2837
|
}
|
|
2839
2838
|
|
|
2840
|
-
let required =
|
|
2841
|
-
structure->Option.flatMap(s => s.requiredStores)->Option.getOr([])
|
|
2839
|
+
let required = structure->Option.flatMap(s => s.requiredStores)->Option.getOr([])
|
|
2842
2840
|
let provisioned =
|
|
2843
2841
|
objectStores
|
|
2844
2842
|
->Option.flatMap(JSON.Decode.object)
|
|
@@ -2849,17 +2847,19 @@ module MakeWithConfig = (
|
|
|
2849
2847
|
| NotAdopted(missing) =>
|
|
2850
2848
|
log.warn(
|
|
2851
2849
|
~comp="Platform:deployPlugin",
|
|
2852
|
-
`declares ${missing->Array.join(
|
|
2853
|
-
|
|
2854
|
-
|
|
2850
|
+
`declares ${missing->Array.join(
|
|
2851
|
+
", ",
|
|
2852
|
+
)} but the platform stack provisions no object stores — ` ++
|
|
2853
|
+
`add them to the platform's ~capabilities and redeploy the platform first, ` ++ `or uploads will fall back to the legacy service and write to the wrong bucket`,
|
|
2855
2854
|
)
|
|
2856
2855
|
| Missing({missing, provisioned}) =>
|
|
2857
2856
|
JsError.throwWithMessage(
|
|
2858
|
-
`Plugin requires object store(s) the platform does not provision: ${missing->Array.join(
|
|
2857
|
+
`Plugin requires object store(s) the platform does not provision: ${missing->Array.join(
|
|
2858
|
+
", ",
|
|
2859
|
+
)}.\n` ++
|
|
2859
2860
|
` The platform stack provisions: ${provisioned->Array.join(", ")}.\n` ++
|
|
2860
2861
|
` A store's key is {plugin}.{store}, where {plugin} is the name the plugin registers — ` ++
|
|
2861
|
-
`check the capability's spelling and case against it.\n` ++
|
|
2862
|
-
` Add the missing entr(ies) to the platform's ~capabilities and redeploy the platform stack first.`,
|
|
2862
|
+
`check the capability's spelling and case against it.\n` ++ ` Add the missing entr(ies) to the platform's ~capabilities and redeploy the platform stack first.`,
|
|
2863
2863
|
)
|
|
2864
2864
|
}
|
|
2865
2865
|
})
|
|
@@ -2870,10 +2870,7 @@ module MakeWithConfig = (
|
|
|
2870
2870
|
->Pulumi.Output.all3
|
|
2871
2871
|
->Pulumi.Output.apply(((id, _, _)) => id),
|
|
2872
2872
|
)
|
|
2873
|
-
Pulumi.Pulumi.export(
|
|
2874
|
-
"pluginSourceApiId",
|
|
2875
|
-
domainApi->Pulumi.Output.flatMap(api => api.id),
|
|
2876
|
-
)
|
|
2873
|
+
Pulumi.Pulumi.export("pluginSourceApiId", domainApi->Pulumi.Output.flatMap(api => api.id))
|
|
2877
2874
|
Pulumi.Pulumi.export(
|
|
2878
2875
|
"pluginSourceApiEndpoint",
|
|
2879
2876
|
domainApi->Pulumi.Output.flatMap(api =>
|
|
@@ -2926,8 +2923,10 @@ module MakeWithConfig = (
|
|
|
2926
2923
|
// re-detect coming to correct it. Waiting on the heartbeat alone gated on a
|
|
2927
2924
|
// Lambda that has no part in the answer.
|
|
2928
2925
|
let redetectReady =
|
|
2929
|
-
(
|
|
2930
|
-
|
|
2926
|
+
(
|
|
2927
|
+
pluginOutputs.heartbeat,
|
|
2928
|
+
PluginRuntime_Builder.eventCollectorReadyRef.contents,
|
|
2929
|
+
)->Pulumi.Output.all2
|
|
2931
2930
|
let _ = redetectReady->Pulumi.Output.apply(_ => {
|
|
2932
2931
|
let hbConfig = PluginRuntime_Builder.heartbeatConfigRef.contents
|
|
2933
2932
|
switch (Pulumi.Pulumi.isDryRun(), hbConfig.epQueueUrl) {
|