@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.
Files changed (234) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +11 -11
  3. package/scripts/ProvisionIdentity.res +8 -3
  4. package/src/Platform.res +327 -328
  5. package/src/Platform.res.mjs +4 -2
  6. package/src/Platform_Casts.res +13 -4
  7. package/src/adapter/Api/AppSyncEventsSigner_Ops.res +8 -4
  8. package/src/adapter/Api/AppSync_EventsApi.res +12 -14
  9. package/src/adapter/Api/AppSync_Resolver_Native.res +3 -4
  10. package/src/adapter/Api/AppSync_Resolver_Retrying.res +78 -70
  11. package/src/adapter/Api/AppSync_SourceApiAssociation_Retrying.res +11 -8
  12. package/src/adapter/Api/Platform_AdminScan_Ops.res +15 -14
  13. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +10 -2
  14. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +40 -50
  15. package/src/adapter/Api/Platform_UIFragments_Lambda.res +39 -32
  16. package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +5 -2
  17. package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +0 -1
  18. package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -2
  19. package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +1 -4
  20. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +5 -2
  21. package/src/adapter/Auth/Auth_Cognito.res +3 -9
  22. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +1 -4
  23. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +3 -1
  24. package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +1 -4
  25. package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +7 -4
  26. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +6 -1
  27. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +7 -4
  28. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +24 -18
  29. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +9 -4
  30. package/src/adapter/CommandTopic/CommandTopicRegistry.res +1 -4
  31. package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +15 -15
  32. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +9 -5
  33. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +179 -213
  34. package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +5 -5
  35. package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +6 -2
  36. package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +14 -7
  37. package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +14 -7
  38. package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +6 -3
  39. package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +6 -1
  40. package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +13 -17
  41. package/src/adapter/EventLog/EventLogStorage_Postgres.res +7 -4
  42. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +12 -7
  43. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +4 -2
  44. package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +3 -2
  45. package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +20 -12
  46. package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +21 -9
  47. package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -3
  48. package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +6 -3
  49. package/src/adapter/Mcp/MCP_Lambda.res +31 -46
  50. package/src/adapter/Messaging/Messaging_Ses_Backend.res +11 -7
  51. package/src/adapter/Messaging/Messaging_Ses_Backend.res.mjs +2 -4
  52. package/src/adapter/Monitoring/Monitoring_CloudWatch.res +16 -16
  53. package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +5 -10
  54. package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +4 -2
  55. package/src/adapter/Postgres/PgConnection.res +6 -5
  56. package/src/adapter/Postgres/PgMigration_Builder.res +4 -8
  57. package/src/adapter/Postgres/PgRuntime.res +4 -7
  58. package/src/adapter/QueryDb/PgQueryResolver_Builder.res +9 -11
  59. package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +22 -21
  60. package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +114 -111
  61. package/src/adapter/QueryDb/QueryDbResolvers_Lambda.res +1 -7
  62. package/src/adapter/QueryDb/QueryDbStorage.res +4 -2
  63. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +23 -24
  64. package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +8 -2
  65. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +71 -73
  66. package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +5 -2
  67. package/src/adapter/QueryDb/QueryInterceptor_Provisioning.res +1 -4
  68. package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +8 -2
  69. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +73 -81
  70. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +72 -78
  71. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +44 -67
  72. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +44 -67
  73. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +53 -82
  74. package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +47 -77
  75. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +18 -11
  76. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -97
  77. package/src/adapter/Runtime/CounterEntryPoint_Ops.res +2 -7
  78. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -10
  79. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +24 -15
  80. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +17 -37
  81. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +31 -57
  82. package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +18 -24
  83. package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -5
  84. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +4 -3
  85. package/src/adapter/Runtime/HeartbeatEntryPoint.res +0 -1
  86. package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +4 -2
  87. package/src/adapter/Runtime/PgMigrationEntryPoint.res +0 -1
  88. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +3 -2
  89. package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -2
  90. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +4 -5
  91. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +22 -10
  92. package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +8 -2
  93. package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +14 -31
  94. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +16 -17
  95. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +10 -9
  96. package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +46 -52
  97. package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +36 -41
  98. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +31 -37
  99. package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +6 -7
  100. package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +4 -6
  101. package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +2 -6
  102. package/src/adapter/StateTopic/StateTopic_AppSync.res +21 -16
  103. package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +36 -32
  104. package/src/adapter/Task/TaskBucket_S3.res +6 -1
  105. package/src/adapter/Upload/Upload_Claim_S3.res +17 -20
  106. package/src/adapter/Upload/Upload_Claim_S3_Ops.res +5 -2
  107. package/src/adapter/Upload/Upload_Presign_S3.res +51 -49
  108. package/src/capability/Capability_Geocoding_AwsLocation.res +4 -1
  109. package/src/capability/Capability_Messaging.res +4 -5
  110. package/src/capability/Capability_Messaging_Ses.res +3 -1
  111. package/src/capability/Capability_ObjectStore_S3.res +1 -7
  112. package/src/components/Api/AppSync_Adapter.res +28 -41
  113. package/src/components/Api/AppSync_SdlDecorate.res +38 -30
  114. package/src/components/AutomationSlice_Builder.res +6 -4
  115. package/src/components/ExtensionPoint_Builder.res +9 -10
  116. package/src/components/InboundTranslationSlice_Builder.res +7 -8
  117. package/src/components/OutboundTranslationSlice_Builder.res +14 -8
  118. package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
  119. package/src/components/SideEffectHandler_Single.res +4 -4
  120. package/src/components/StateViewSlice_Builder.res +6 -4
  121. package/src/components/StateViewSlice_Builder_Stream.res +6 -4
  122. package/src/components/Task_Builder_PerBucket.res +10 -11
  123. package/src/plugin/cloner/ClonerRunner_Fargate.res +3 -10
  124. package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +1 -4
  125. package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +5 -5
  126. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +19 -21
  127. package/src/plugin/runtime/PluginRuntime_Builder.res +167 -188
  128. package/src/plugin/runtime/Util_PluginMessage_Runtime.res +6 -5
  129. package/src/plugin/stack/Plugin_Stack.res +104 -103
  130. package/src/util/Util_AlarmSpec.res +2 -1
  131. package/src/util/Util_AppSync.res +8 -2
  132. package/src/util/Util_AppSync_Caller.res +15 -14
  133. package/src/util/Util_Bundle.res +144 -67
  134. package/src/util/Util_Bundle.res.mjs +64 -13
  135. package/src/util/Util_CognitoGroupUser_Runtime.res +32 -34
  136. package/src/util/Util_Cognito_Runtime.res +11 -7
  137. package/src/util/Util_DeadLetterQueue.res +12 -2
  138. package/src/util/Util_DynamoDb.res +5 -3
  139. package/src/util/Util_DynamoDbStream.res +7 -3
  140. package/src/util/Util_DynamoDbStream_Runtime.res +1 -2
  141. package/src/util/Util_DynamoDb_Runtime.res +23 -41
  142. package/src/util/Util_HostUiDomain.res +6 -1
  143. package/src/util/Util_Kinesis_Runtime.res +10 -11
  144. package/src/util/Util_Lambda.res +12 -5
  145. package/src/util/Util_LambdaEnvBudget.res +5 -5
  146. package/src/util/Util_LambdaLogging.res +1 -2
  147. package/src/util/Util_LogGroup_Adopting.res +1 -4
  148. package/src/util/Util_ResourceNaming.res +1 -2
  149. package/src/util/Util_SNS.res +8 -3
  150. package/src/util/Util_SNS_FIFO.res +1 -1
  151. package/src/util/Util_SNS_Runtime.res +11 -10
  152. package/src/util/Util_SQS.res +4 -2
  153. package/src/util/Util_SQS_FIFO.res +5 -2
  154. package/src/util/Util_SQS_Runtime.res +37 -36
  155. package/src/util/Util_ShellConfig.res +3 -2
  156. package/src/util/Util_StaticBundle.res +1 -3
  157. package/src/util/Util_StoreLayout.res +4 -1
  158. package/tests/AWS_TagsTest.res +16 -5
  159. package/tests/AppSyncEventsSigner_OpsTest.res +11 -2
  160. package/tests/AppSync_AdapterTest.res +203 -224
  161. package/tests/AppSync_Resolver_RetryingTest.res +64 -44
  162. package/tests/AppSync_RetirementNarrowingTest.res +59 -46
  163. package/tests/AppSync_SdlDecorateTest.res +22 -20
  164. package/tests/AppSync_SourceApiAssociation_RetryingTest.res +40 -22
  165. package/tests/Auth_ActiveRolePoolAttachmentTest.res +114 -107
  166. package/tests/Auth_ActiveRoleStoreTest.res +12 -9
  167. package/tests/Auth_ActiveRoleStore_SchemaTest.res +2 -1
  168. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +20 -16
  169. package/tests/Auth_CognitoTest.res +31 -46
  170. package/tests/AutomationSliceEntryPoint_OpsTest.res +69 -67
  171. package/tests/BakeConvergenceTest.res +22 -25
  172. package/tests/Capability_MessagingTest.res +28 -12
  173. package/tests/CommandTopicQueuePolicyTest.res +1 -2
  174. package/tests/CounterEntryPoint_OpsTest.res +3 -7
  175. package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +306 -210
  176. package/tests/EventCollectorConnectLambdaPreviewTest.res +14 -7
  177. package/tests/EventCollectorEntryPoint_OpsTest.res +12 -4
  178. package/tests/EventCollectorPluginDefinitionAssetTest.res +18 -11
  179. package/tests/EventCollectorReadyGateTest.res +5 -4
  180. package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -2
  181. package/tests/EventMapperEntryPoint_OpsTest.res +1 -3
  182. package/tests/ExtensionPointEntryPoint_OpsTest.res +1 -4
  183. package/tests/HandlerFactoryDispatchTest.res +97 -70
  184. package/tests/MCP_LambdaTest.res +16 -27
  185. package/tests/PgChangeFeedRelay_IntegrationTest.res +123 -93
  186. package/tests/PgChangeFeedRelay_RuntimeTest.res +13 -10
  187. package/tests/PgMigrationEntryPoint_IntegrationTest.res +0 -1
  188. package/tests/PgPipeline_IntegrationTest.res +80 -66
  189. package/tests/PgQueryDbUnion_IntegrationTest.res +1 -2
  190. package/tests/PgQueryResolverEntryPoint_OpsTest.res +2 -6
  191. package/tests/PgQueryResolver_LambdaTest.res +41 -24
  192. package/tests/Platform_AdminScan_OpsTest.res +4 -1
  193. package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +137 -129
  194. package/tests/ProjectionEntryPoint_DisplayNameTest.res +7 -3
  195. package/tests/ProjectionEntryPoint_UnionStampTest.res +3 -2
  196. package/tests/ProvisionIdentityTest.res +2 -6
  197. package/tests/QueryDbOwnerIndexTableTest.res +6 -4
  198. package/tests/QueryDbResolvers_AppSyncTest.res +23 -16
  199. package/tests/QueryInterceptor_LambdaTest.res +11 -13
  200. package/tests/ReadModelEntryPoint_OpsTest.res +43 -41
  201. package/tests/RuntimeExtensionEntryPoint_OpsTest.res +4 -3
  202. package/tests/SideEffectEntryPoint_OpsTest.res +23 -18
  203. package/tests/StateChangeDescriptorParityTest.res +28 -26
  204. package/tests/StateTopicKeySchemaTest.res +18 -15
  205. package/tests/StateViewSliceEntryPoint_OpsTest.res +55 -44
  206. package/tests/TaskBucketEntryPoint_OpsTest.res +13 -13
  207. package/tests/Upload_ClaimTest.res +3 -3
  208. package/tests/Util_AwsErrorTest.res +4 -7
  209. package/tests/Util_BundleDependencyClosureTest.res +41 -3
  210. package/tests/Util_BundleDependencyClosureTest.res.mjs +11 -0
  211. package/tests/Util_BundleEsmLoaderTest.res +3 -3
  212. package/tests/Util_BundleResolveTest.res +4 -6
  213. package/tests/Util_BundleRuntimeExtensionTest.res +17 -18
  214. package/tests/Util_DcbMetricsTest.res +6 -6
  215. package/tests/Util_DynamoDbStreamTest.res +4 -5
  216. package/tests/Util_DynamoDbTest.res +3 -2
  217. package/tests/Util_LambdaEnvBudgetTest.res +22 -18
  218. package/tests/Util_LambdaLoggingTest.res +9 -8
  219. package/tests/Util_LogGroup_AdoptingTest.res +10 -5
  220. package/tests/Util_LogRetentionTest.res +6 -2
  221. package/tests/Util_OwnerScopeEnvTest.res +10 -8
  222. package/tests/Util_SQS_RuntimeTest.res +5 -7
  223. package/tests/Util_ShellConfigTest.res +7 -17
  224. package/tests/Util_StaticBundleTest.res +3 -8
  225. package/tests/Util_StoreLayoutTest.res +17 -12
  226. package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -4
  227. package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +15 -15
  228. package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +296 -232
  229. package/tests/integration/DcbIntegrationHarness.res +8 -8
  230. package/tests/integration/EpCompositeSlice.res +16 -8
  231. package/tests/integration/QueryDbUnion_DynamoDb_IntegrationTest.res +8 -10
  232. package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +10 -10
  233. package/tests/integration/SvsTestSlice_Projection.res +1 -3
  234. 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
- (stackRef->Pulumi.StackReference.getOutput("objectStores"): Pulumi.Output.t<option<JSON.t>>)
205
- ->Pulumi.Output.apply(objectStores =>
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(o =>
214
- switch (
215
- o->Dict.get("bucketName")->Option.flatMap(JSON.Decode.string),
216
- o->Dict.get("keyPrefix")->Option.flatMap(JSON.Decode.string),
217
- ) {
218
- | (Some(bucketName), Some(servedPrefix)) =>
219
- Some({Upload_Claim_S3.qualified: qualified, bucketName, servedPrefix})
220
- | _ => None
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(~fragment=baseFragment)
277
- ->AppSync_SdlDecorate.stampCanonicalTypes
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 => assembleCanonicalSourceSdl(~baseFragment=domainBaseFragment)
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
- (((directProviderId, directProviderRegion), (directPoolId, directRegion), default)) => {
342
- let getFromDefault = key =>
343
- default
344
- ->Option.flatMap(d => d->JSON.Decode.object)
345
- ->Option.flatMap(d => d->Dict.get(key))
346
- ->Option.flatMap(v => v->JSON.Decode.string)
347
- // New spelling first at both levels, then the deprecated one. In ESM
348
- // mode exports arrive nested under "default", hence each pair.
349
- let userPoolId =
350
- directProviderId
351
- ->Option.orElse(getFromDefault("identityProviderId"))
352
- ->Option.orElse(directPoolId)
353
- ->Option.orElse(getFromDefault("cognitoUserPoolId"))
354
- ->Option.getOrThrow(
355
- ~message="Platform stack exports neither 'identityProviderId' nor 'cognitoUserPoolId' — redeploy the platform stack first",
356
- )
357
- let awsRegion =
358
- directProviderRegion
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 () = apiConfigRef := Some({
388
- domainApi: domainApi,
389
- domainApiRole: domainApiRole,
390
- platformApi: platformApi,
391
- platformApiRole: platformApiRole,
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
- switch platformStackRef {
399
- | None =>
400
- // Browser host-shell subscribes over WebSocket with a Cognito IdToken,
401
- // so the Events API must carry a Cognito auth provider. The pool is the
402
- // same process-cached one the GraphQL API + config.json use.
403
- let cognitoPool = Platform_Stack.resolveCognitoUserPool()
404
- let awsRegion =
405
- Pulumi.Config.make(Some("aws"))->Pulumi.Config.get("region")->Option.getOr("unknown")
406
- Some(
407
- AppSync_EventsApi.make(
408
- ~name="DomainEventsApi",
409
- ~cognitoUserPoolId=cognitoPool.poolId->Pulumi.Output.asInput,
410
- ~awsRegion,
411
- ~opts={},
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
- | Some(stackRef) =>
415
- let eventsApiArnOutput: Pulumi.Output.t<option<string>> =
416
- stackRef->Pulumi.StackReference.getOutput("eventsApiArn")
417
- let eventsApiDnsOutput: Pulumi.Output.t<option<string>> =
418
- stackRef->Pulumi.StackReference.getOutput("eventsApiDns")
419
- let defaultEventsOutput: Pulumi.Output.t<option<JSON.t>> =
420
- stackRef->Pulumi.StackReference.getOutput("default")
421
- let getFromDefault = (default, key) =>
422
- default
423
- ->Option.flatMap(d => d->JSON.Decode.object)
424
- ->Option.flatMap(d => d->Dict.get(key))
425
- ->Option.flatMap(v => v->JSON.Decode.string)
426
- let apiArn =
427
- (eventsApiArnOutput, defaultEventsOutput)
428
- ->Pulumi.Output.all2
429
- ->Pulumi.Output.apply(((direct, default)) =>
430
- direct->Option.orElse(getFromDefault(default, "eventsApiArn"))
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
- ): (ReventlessInfra.StateChangeSlice.T with module Spec = Spec) =>
662
- StateChangeSlice_Builder.Make(Spec, Behavior)
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
- domainApi->Pulumi.Output.flatMap(api =>
807
- api.id->Pulumi.Output.flatMap(apiId => {
808
- log.info(
809
- ~comp="preResolversSchemaHook",
810
- `Pushing subgraph schema for ${name}@${version} to source API ${apiId}`,
811
- )
812
- let client = AppSync_Adapter.getClient()
813
- client
814
- ->AppSync_Adapter.startSchemaCreationRetrying({apiId, definition: sdl})
815
- ->Promise.then(async _ => {
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
- ->Pulumi.Output.fromPromise
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: ?domainEventsApiOpt->Option.map(eventsApi =>
875
- (params: ReventlessCore.Plugin_Helpers.subscriptionInfraParams) => {
876
- let {pluginName, allQueryDbs, allEventTopics, eventLogEntries, opts} = params
877
- let customOpts =
878
- opts->ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions
879
- // StateTopic Lambda per stream-enabled QueryDb — publishes row changes
880
- // to AppSync Events channels. No GraphQL Subscription resolver is
881
- // wired: Source B uses the Events WebSocket directly, not @aws_subscribe.
882
- allQueryDbs->Dict.forEachWithKey((_queryDbOutputs, readModelName) => {
883
- if QueryDbStorage_DynamoDbStream.streamRegistry->Set.has(readModelName) {
884
- // Channel root MUST equal what the host-shell subscribes to. The
885
- // AutoUI manifest sets queryableDef.queryField = listFieldName
886
- // (plural, e.g. "Catalog_Products") and AutoLive subscribes on that.
887
- // Publishing on the singular returnTypeName ("Catalog_Product")
888
- // would land descriptors on a channel no client listens to.
889
- let topicName =
890
- ReventlessCore.Plugin_Helpers.queryFieldNamesRegistry
891
- ->Dict.get(readModelName)
892
- ->Option.map(qn => qn.listFieldName)
893
- ->Option.getOr(readModelName)
894
- StateTopic_AppSync.make(
895
- ~readModelName,
896
- ~topicName,
897
- ~allQueryDbs,
898
- ~eventsApi,
899
- ~opts=customOpts,
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
- // Phase 5: EventLogSubscription per SNS-backed event log entry.
905
- // DynamoDB stream event topics (Category, DCB) are skipped — no SNS subscription needed.
906
- eventLogEntries->Array.forEach(entry => {
907
- // Aggregate EventTopics are keyed by Spec.name (= displayName).
908
- // DCB EventTopic is keyed by busKey (= pluginName ++ "DcbEventLog").
909
- let isSns =
910
- EventTopicPublisher_SNS.snsRegistry->Set.has(entry.displayName) ||
911
- EventTopicPublisher_SNS.snsRegistry->Set.has(entry.busKey)
912
- let topicOutputs =
913
- allEventTopics
914
- ->Dict.get(entry.displayName)
915
- ->Option.orElse(allEventTopics->Dict.get(entry.busKey))
916
- isSns
917
- ? topicOutputs->Option.forEach(outputs =>
918
- EventLogSubscription_AppSync.make(
919
- ~name=entry.displayName,
920
- ~topicName=entry.displayName,
921
- ~eventTopicOutputs=outputs,
922
- ~eventsApi,
923
- ~opts=customOpts,
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
- // Register this event log with the upload claimer if — and only if —
928
- // its events declare a `@storageRef` field. An event log that declares
929
- // none is not registered, so a platform whose plugins declare no store
930
- // provisions no claimer at all. `isSns` is the same synchronous answer
931
- // the subscription above turns on, so the two cannot disagree about
932
- // which channel an event log publishes through.
933
- topicOutputs->Option.forEach(outputs =>
934
- Upload_Claim_S3.make(
935
- ~plugin=pluginName,
936
- ~eventLogName=entry.displayName,
937
- ~eventSchema=entry.eventSchema,
938
- ~eventTopicOutputs=outputs,
939
- ~isStreamBacked=!isSns,
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
- // Finalize the shared StateTopic Lambda + IAM + per-stream ESMs from the
944
- // entries the loop above just registered. Must run INSIDE this hook because
945
- // Plugin_Builder fires it from inside a Pulumi.Output.apply chain — calling
946
- // `finish` from deployPlugin (after P.make returns) would see the registry
947
- // empty because the hook hasn't run yet. Admin's hook fires synchronously,
948
- // but the call site is unified here so admin and plugins share one path.
949
- StateTopic_AppSync.finish(~eventsApi, ~opts={})
950
- // Same timing constraint, same reason: the claimer's registry is filled
951
- // by the loop just above and drained here.
952
- Upload_Claim_S3.finish(~plugin=pluginName, ~stores=claimStores, ~opts=customOpts)
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({let hooks = hooks})
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
- ReventlessInfra.Aggregate.T with type api = Types.AppSync.api
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
- (isClassic ? fq.includeClassic : fq.includeDcb)
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 := Some({
1362
- domainApi: c.domainApi,
1363
- domainApiRole: c.domainApiRole,
1364
- platformApi: platformApi,
1365
- platformApiRole: platformApiRole,
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
- admin.extensionPointsOutputs->Pulumi.Output.flatMap(eps =>
1439
- switch eps->Array.find(ep =>
1440
- ep.name == ReventlessInfra.PluginExtensionPointSpec.name
1441
- ) {
1442
- | Some(ep) =>
1443
- ep.eventTopic->Pulumi.Output.flatMap(et =>
1444
- switch et.resources->Array.get(0) {
1445
- | Some(r) => r.urn
1446
- | None => Pulumi.Output.make("NOT_AVAILABLE")
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("platformApiRoleArn", platformApiRole->Pulumi.Output.flatMap(role => role.arn))
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("platformApiRoleArn", domainApiRole->Pulumi.Output.flatMap(role => role.arn))
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 = clientDomainApi->Pulumi.Output.flatMap(api =>
1667
- api.uris->Pulumi.Output.apply(uris => uris.graphQL)
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 = clientPlatformApi->Pulumi.Output.flatMap(api =>
1671
- api.uris->Pulumi.Output.apply(uris => uris.graphQL)
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(((domainApiEndpoint, domainApiRoleArn, platformApiEndpoint, platformApiRoleArn, adminResources)) => {
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 => None
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
- ->Array.filterMap(((_, prefix, bn, _)) => bn == bucketName ? Some(prefix) : None),
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: 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((e.bucketName, e.baseUrl->Pulumi.Output.allOpt))->Pulumi.Output.apply(((
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 := switch apiTarget { | Domain => "Domain" | Platform => "Platform" }
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
- (stackRef->Pulumi.StackReference.getOutput("offloadBucket"): Pulumi.Output.t<option<string>>)
2536
- ->Pulumi.Output.apply(o => o->Option.getOr("OFFLOAD_BUCKET_PENDING_PLATFORM_DEPLOY"))
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
- Pulumi.Output.t<option<string>>
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
- Pulumi.Output.t<option<string>>
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
- Pulumi.Output.t<option<string>>
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((((structure, objectStores, placeIndex, emailSender): (
2782
- _,
2783
- option<JSON.t>,
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(", ")} but the platform stack provisions no object stores — ` ++
2853
- `add them to the platform's ~capabilities and redeploy the platform first, ` ++
2854
- `or uploads will fall back to the legacy service and write to the wrong bucket`,
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(", ")}.\n` ++
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
- (pluginOutputs.heartbeat, PluginRuntime_Builder.eventCollectorReadyRef.contents)
2930
- ->Pulumi.Output.all2
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) {