@reventlessdev/reventless-aws 3.0.0-alpha.397 → 3.0.0-alpha.398

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 (83) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/package.json +9 -9
  3. package/scripts/BakeManifest.res +15 -15
  4. package/scripts/DeployApp.res +8 -9
  5. package/scripts/DeployApp.res.mjs +4 -13
  6. package/scripts/DeployManifest.res +4 -5
  7. package/scripts/DeployManifest.res.mjs +0 -1
  8. package/scripts/ProvisionAccounts.res +41 -33
  9. package/scripts/ProvisionAccounts.res.mjs +6 -9
  10. package/scripts/ProvisionAdmin.res +10 -10
  11. package/scripts/ProvisionIdentity.res +2 -2
  12. package/scripts/ResolveEnvironment.res +3 -3
  13. package/src/Platform.res +6 -4
  14. package/src/Platform.res.mjs +6 -4
  15. package/src/Platform_ProvidedGroups.res +4 -4
  16. package/src/Platform_Stack.res +2 -3
  17. package/src/Platform_Stack.res.mjs +1 -2
  18. package/src/adapter/Api/AppSyncEventsSigner_Ops.res +2 -2
  19. package/src/adapter/Api/AppSync_EventsApi.res +2 -2
  20. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +6 -6
  21. package/src/adapter/DcbEventLog/DcbBackend.res +3 -3
  22. package/src/adapter/DcbEventLog/DcbBackend.res.mjs +1 -3
  23. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +11 -9
  24. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +4 -6
  25. package/src/adapter/EventLog/EventLogBackend.res +3 -3
  26. package/src/adapter/EventLog/EventLogBackend.res.mjs +1 -3
  27. package/src/adapter/Geocoder/Geocoder_AwsLocation_Backend.res +1 -1
  28. package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +5 -5
  29. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +2 -2
  30. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +2 -2
  31. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +32 -32
  32. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +4 -3
  33. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +6 -6
  34. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -5
  35. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +3 -3
  36. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +5 -5
  37. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +24 -18
  38. package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res +16 -14
  39. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +2 -2
  40. package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +4 -4
  41. package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res +4 -4
  42. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +9 -9
  43. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +11 -9
  44. package/src/components/Api/AppSync_Adapter.res +4 -4
  45. package/src/components/InboundTranslationSlice_Builder.res +19 -0
  46. package/src/components/InboundTranslationSlice_Builder.res.mjs +12 -2
  47. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +4 -7
  48. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -4
  49. package/src/plugin/runtime/PluginRuntime_Builder.res +17 -26
  50. package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +7 -22
  51. package/tests/AppSyncEventsSigner_OpsTest.res +1 -1
  52. package/tests/AppSync_AdapterTest.res +4 -4
  53. package/tests/AppSync_AdapterTest.res.mjs +4 -8
  54. package/tests/Auth_ActiveRoleStoreTest.res +1 -1
  55. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +1 -1
  56. package/tests/AutomationSliceEntryPoint_OpsTest.res +0 -2
  57. package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +3 -6
  58. package/tests/BakeConvergenceTest.res +1 -8
  59. package/tests/BakeConvergenceTest.res.mjs +3 -23
  60. package/tests/BakeManifestTest.res +5 -10
  61. package/tests/BakeManifestTest.res.mjs +1 -6
  62. package/tests/CommandLineTest.res +3 -3
  63. package/tests/DeployAppTest.res +3 -4
  64. package/tests/DeployAppTest.res.mjs +6 -15
  65. package/tests/EpInboundTestSlice.res +1 -0
  66. package/tests/EpInboundTestSlice.res.mjs +3 -0
  67. package/tests/EventCollectorPluginDefinitionAssetTest.res +1 -2
  68. package/tests/EventCollectorPluginDefinitionAssetTest.res.mjs +11 -21
  69. package/tests/IdentityProvider_Cognito_BackendTest.res +0 -3
  70. package/tests/IdentityProvider_Cognito_BackendTest.res.mjs +0 -3
  71. package/tests/PgQueryResolver_LambdaTest.res +6 -10
  72. package/tests/PgQueryResolver_LambdaTest.res.mjs +4 -34
  73. package/tests/Platform_ProvidedGroupsTest.res +2 -2
  74. package/tests/Platform_ProvidedGroupsTest.res.mjs +1 -2
  75. package/tests/ProvisionAccountsTest.res +5 -10
  76. package/tests/ProvisionAccountsTest.res.mjs +0 -9
  77. package/tests/ProvisionAdminTest.res +4 -9
  78. package/tests/ProvisionAdminTest.res.mjs +0 -7
  79. package/tests/ProvisionIdentityTest.res +2 -4
  80. package/tests/ProvisionIdentityTest.res.mjs +0 -2
  81. package/tests/SideEffectEntryPoint_OpsTest.res +2 -2
  82. package/tests/Util_ShellConfigTest.res +3 -3
  83. package/tests/Util_ShellConfigTest.res.mjs +1 -2
@@ -106,7 +106,7 @@ type handlerConfig = {
106
106
  schedulerQueueArn: string,
107
107
  schedulerQueueName: string,
108
108
  extensionPoints: array<extensionPointConfig>,
109
- connectExtension: option<connectExtensionConfig>,
109
+ connectExtension?: connectExtensionConfig,
110
110
  extensions: array<extensionConfig>,
111
111
  readModelNamesForSourceName: dict<array<string>>,
112
112
  }
@@ -234,7 +234,7 @@ let parseHandlerConfig = (rawJson: string): handlerConfig => {
234
234
  schedulerQueueArn: obj->strOf("schedulerQueueArn")->Option.getOr(""),
235
235
  schedulerQueueName: obj->strOf("schedulerQueueName")->Option.getOr(""),
236
236
  extensionPoints,
237
- connectExtension,
237
+ ?connectExtension,
238
238
  extensions,
239
239
  readModelNamesForSourceName,
240
240
  }
@@ -253,7 +253,7 @@ type pluginProjection = {
253
253
  eventCollector: string,
254
254
  extensions: array<Reventless.Plugin.extensionDefinition>,
255
255
  extensionPoints: array<Reventless.Plugin.extensionPointDefinition>,
256
- dcbEventLog: option<Reventless.Plugin.dcbEventLogDefinition>,
256
+ dcbEventLog?: Reventless.Plugin.dcbEventLogDefinition,
257
257
  }
258
258
 
259
259
  let projectPluginRow = (row: JSON.t): option<pluginProjection> =>
@@ -323,7 +323,7 @@ let projectPluginRow = (row: JSON.t): option<pluginProjection> =>
323
323
  eventCollector: obj->strOf("eventCollector")->Option.getOr(""),
324
324
  extensions,
325
325
  extensionPoints,
326
- dcbEventLog,
326
+ ?dcbEventLog,
327
327
  })
328
328
  | _ => None
329
329
  }
@@ -339,7 +339,7 @@ let projectionOfDefinition = (d: Reventless.Plugin.pluginDefinition): pluginProj
339
339
  eventCollector: d.eventCollector,
340
340
  extensions: d.extensions,
341
341
  extensionPoints: d.extensionPoints,
342
- dcbEventLog: d.dcbEventLog->jsOption,
342
+ dcbEventLog: ?(d.dcbEventLog->jsOption),
343
343
  }
344
344
 
345
345
  // ── Cross-plugin SNS subscription manager ───────────────────────────────────
@@ -26,7 +26,7 @@ type handlerEntry = {
26
26
  }
27
27
 
28
28
  type resolverConfig = {
29
- pgConnection: option<PgConnection.connectionConfig>,
29
+ pgConnection?: PgConnection.connectionConfig,
30
30
  handlers: array<handlerEntry>,
31
31
  nodeTypes: dict<string>,
32
32
  }
@@ -59,10 +59,12 @@ let parseResolverConfig = (rawJson: string): resolverConfig => {
59
59
  ->JSON.Decode.object
60
60
  ->Option.getOr(Dict.make())
61
61
  {
62
- pgConnection: obj
63
- ->Dict.get("pgConnection")
64
- ->Option.filter(j => j != JSON.Null)
65
- ->Option.map(asPgConnection),
62
+ pgConnection: ?(
63
+ obj
64
+ ->Dict.get("pgConnection")
65
+ ->Option.filter(j => j != JSON.Null)
66
+ ->Option.map(asPgConnection)
67
+ ),
66
68
  handlers: obj
67
69
  ->Dict.get("handlers")
68
70
  ->Option.flatMap(JSON.Decode.array)
@@ -118,8 +120,8 @@ let makePushdowns = (
118
120
  // Reventless.Authorization.isAllowed matches on.
119
121
 
120
122
  type specInfo = {
121
- config: option<ProjectionEntryPoint_Ops.specConfig>,
122
- subIdConfig: option<Reventless.ReadModel.subIdConfig<JSON.t>>,
123
+ config?: ProjectionEntryPoint_Ops.specConfig,
124
+ subIdConfig?: Reventless.ReadModel.subIdConfig<JSON.t>,
123
125
  stateSchema: S.t<unknown>,
124
126
  authorization: Reventless.Authorization.permission,
125
127
  }
@@ -143,7 +145,7 @@ let registerBinding = (
143
145
  ),
144
146
  pushdowns,
145
147
  indexes,
146
- subIdField,
148
+ ?subIdField,
147
149
  capability: ReventlessCore.GraphQL_FragmentGenerator.deriveServerCapability(
148
150
  ~entityName=entry.readModelName,
149
151
  spec.stateSchema,
@@ -153,24 +155,28 @@ let registerBinding = (
153
155
  authorization: spec.authorization->Reventless.Authorization.named,
154
156
  // From the same schema `capability` is derived from, one line above, so the
155
157
  // two cannot end up disagreeing about this read model's fields.
156
- ownerField: Reventless.Owner.fieldNames(spec.stateSchema)->Array.get(0),
157
- retiredField: spec.stateSchema
158
- ->Reventless.StateAnnotations.getSpec
159
- ->Option.flatMap(a => a.retired)
160
- ->Option.map(r => r.field),
158
+ ownerField: ?(Reventless.Owner.fieldNames(spec.stateSchema)->Array.get(0)),
159
+ retiredField: ?(
160
+ spec.stateSchema
161
+ ->Reventless.StateAnnotations.getSpec
162
+ ->Option.flatMap(a => a.retired)
163
+ ->Option.map(r => r.field)
164
+ ),
161
165
  // The state form's other half. Carried beside the field rather than
162
166
  // re-derived at predicate time, so one place decides which rows are retired.
163
- retiredValues: spec.stateSchema
164
- ->Reventless.StateAnnotations.getSpec
165
- ->Option.flatMap(a => a.retired)
166
- ->Option.flatMap(r => r.values),
167
+ retiredValues: ?(
168
+ spec.stateSchema
169
+ ->Reventless.StateAnnotations.getSpec
170
+ ->Option.flatMap(a => a.retired)
171
+ ->Option.flatMap(r => r.values)
172
+ ),
167
173
  // Read off the retirement rather than from a second annotation: a record
168
174
  // cannot declare the reach of a retirement it does not have.
169
175
  namedWhenRetired: spec.stateSchema
170
176
  ->Reventless.StateAnnotations.getSpec
171
177
  ->Option.flatMap(a => a.retired)
172
178
  ->Option.mapOr(false, r => r.namedWhenRetired),
173
- imageSource: spec.stateSchema->Reventless.RowImage.sourceFrom,
179
+ imageSource: ?(spec.stateSchema->Reventless.RowImage.sourceFrom),
174
180
  },
175
181
  )
176
182
  logDebug("registered resolver binding for " ++ entry.readModelName, {comp: "PgQueryResolver"})
@@ -22,10 +22,10 @@ type handlerEntry = {
22
22
  // ReScript dispatch boundary's `EventCollector(<Name>)` byte for byte. This
23
23
  // Lambda hosts every read model, so the comp is what separates their log
24
24
  // lines; the plugin beats the Lambda-name-derived fallback in runEffect.
25
- comp: option<string>,
26
- plugin: option<string>,
27
- pgConnection: option<PgConnection.connectionConfig>,
28
- stateTopicName: option<string>,
25
+ comp?: string,
26
+ plugin?: string,
27
+ pgConnection?: PgConnection.connectionConfig,
28
+ stateTopicName?: string,
29
29
  }
30
30
 
31
31
  // The builder writes `pgConnection` via PgConnection.connectionConfigToJson, so
@@ -44,13 +44,15 @@ let decodeEntry = (json: JSON.t): option<handlerEntry> =>
44
44
  mappingsModule: h->strOf("mappingsModule")->Option.getOr(""),
45
45
  queryDbTableName: h->strOf("queryDbTableName")->Option.getOr(""),
46
46
  sourceUrn: h->strOf("sourceUrn")->Option.getOr(""),
47
- comp: h->strOf("comp"),
48
- plugin: h->strOf("plugin"),
49
- pgConnection: h
50
- ->Dict.get("pgConnection")
51
- ->Option.filter(j => j != JSON.Null)
52
- ->Option.map(asPgConnection),
53
- stateTopicName: h->strOf("stateTopicName"),
47
+ comp: ?(h->strOf("comp")),
48
+ plugin: ?(h->strOf("plugin")),
49
+ pgConnection: ?(
50
+ h
51
+ ->Dict.get("pgConnection")
52
+ ->Option.filter(j => j != JSON.Null)
53
+ ->Option.map(asPgConnection)
54
+ ),
55
+ stateTopicName: ?(h->strOf("stateTopicName")),
54
56
  })
55
57
 
56
58
  let parseHandlerConfig = (rawJson: string): array<handlerEntry> =>
@@ -88,10 +90,10 @@ let withInjectedId = (
88
90
  }
89
91
 
90
92
  type specInfo = {
91
- config: option<ProjectionEntryPoint_Ops.specConfig>,
92
- subIdConfig: option<Reventless.ReadModel.subIdConfig<JSON.t>>,
93
+ config?: ProjectionEntryPoint_Ops.specConfig,
94
+ subIdConfig?: Reventless.ReadModel.subIdConfig<JSON.t>,
93
95
  // Read off the runtime-loaded spec module; `None` on a module that predates it.
94
- stateSchema: option<S.t<unknown>>,
96
+ stateSchema?: S.t<unknown>,
95
97
  }
96
98
 
97
99
  let buildOperations = (
@@ -269,8 +269,8 @@ let makeFromCodeAsset: (
269
269
  // registered — an extension-free deployment gets the env it always had.
270
270
  if !ReventlessCore.RuntimeExtension.isEmpty() {
271
271
  let {
272
- ReventlessCore.ResourceAttribution.plugin: plugin,
273
- platform,
272
+ ReventlessCore.ResourceAttribution.plugin: ?plugin,
273
+ ?platform,
274
274
  } = ReventlessCore.ResourceAttribution.current.contents
275
275
  let orNull = o => o->Option.mapOr(JSON.Null, s => JSON.String(s))
276
276
  let config = JSON.Object(
@@ -29,8 +29,8 @@ type config = {
29
29
  modules: array<string>,
30
30
  runtimeKind: string,
31
31
  component: string,
32
- plugin: option<string>,
33
- platform: option<string>,
32
+ plugin?: string,
33
+ platform?: string,
34
34
  }
35
35
 
36
36
  let decodeString = (obj: dict<JSON.t>, key: string): option<string> =>
@@ -70,8 +70,8 @@ let parseConfig = (raw: option<string>): option<config> =>
70
70
  modules,
71
71
  runtimeKind,
72
72
  component,
73
- plugin: obj->decodeString("plugin"),
74
- platform: obj->decodeString("platform"),
73
+ plugin: ?(obj->decodeString("plugin")),
74
+ platform: ?(obj->decodeString("platform")),
75
75
  })
76
76
  | _ =>
77
77
  log.error(
@@ -14,8 +14,8 @@ type handlerEntry = {
14
14
  // Resolved at deploy time and baked into HANDLER_CONFIG
15
15
  // (SideEffectHandlerRuntime_Builder_Single) — the shell has only module paths
16
16
  // to identify a handler by.
17
- comp: option<string>,
18
- plugin: option<string>,
17
+ comp?: string,
18
+ plugin?: string,
19
19
  }
20
20
 
21
21
  let strOf = (obj: dict<JSON.t>, key: string): option<string> =>
@@ -31,8 +31,8 @@ let decodeEntry = (json: JSON.t): option<handlerEntry> =>
31
31
  ->Option.flatMap(JSON.Decode.array)
32
32
  ->Option.getOr([])
33
33
  ->Array.filterMap(JSON.Decode.string),
34
- comp: h->strOf("comp"),
35
- plugin: h->strOf("plugin"),
34
+ comp: ?(h->strOf("comp")),
35
+ plugin: ?(h->strOf("plugin")),
36
36
  })
37
37
 
38
38
  let parseHandlerConfig = (rawJson: string): array<handlerEntry> =>
@@ -17,8 +17,8 @@ type handlerEntry = {
17
17
  sourceUrn: string,
18
18
  // B3.3: per-slice AppSync Events channel root (list field name). Present only
19
19
  // for subscription-enabled (Stream) Postgres view slices.
20
- stateTopicName: option<string>,
21
- pgConnection: option<PgConnection.connectionConfig>,
20
+ stateTopicName?: string,
21
+ pgConnection?: PgConnection.connectionConfig,
22
22
  }
23
23
 
24
24
  // The builder writes `pgConnection` via PgConnection.connectionConfigToJson, so
@@ -67,16 +67,16 @@ let parseHandlerConfig = (rawJson: string): array<handlerEntry> =>
67
67
  projectionModule: h->strOf("projectionModule")->Option.getOr(""),
68
68
  queryDbTableName: h->strOf("queryDbTableName")->Option.getOr(""),
69
69
  sourceUrn: h->strOf("sourceUrn")->Option.getOr(""),
70
- stateTopicName: h->strOf("stateTopicName"),
71
- pgConnection: h->pgConnectionOf,
70
+ stateTopicName: ?(h->strOf("stateTopicName")),
71
+ pgConnection: ?(h->pgConnectionOf),
72
72
  }
73
73
  | None => {
74
74
  specModule: base ++ h->strOf("s")->Option.getOr(""),
75
75
  projectionModule: base ++ h->strOf("p")->Option.getOr(""),
76
76
  queryDbTableName: h->strOf("q")->Option.getOr(""),
77
77
  sourceUrn: h->strOf("u")->Option.getOr(sharedUrn),
78
- stateTopicName: h->strOf("t"),
79
- pgConnection: sharedPgConnection,
78
+ stateTopicName: ?(h->strOf("t")),
79
+ pgConnection: ?sharedPgConnection,
80
80
  }
81
81
  }
82
82
  )
@@ -197,10 +197,10 @@ type sliceModules<'event> = {
197
197
  project: Reventless.StateViewSlice.consumed<'event> => array<
198
198
  Reventless.Projection.action<string, JSON.t>,
199
199
  >,
200
- config: option<ProjectionEntryPoint_Ops.specConfig>,
201
- subIdConfig: option<Reventless.ReadModel.subIdConfig<JSON.t>>,
200
+ config?: ProjectionEntryPoint_Ops.specConfig,
201
+ subIdConfig?: Reventless.ReadModel.subIdConfig<JSON.t>,
202
202
  // Same union stamp the read-model path needs; a slice's state can hold one too.
203
- stateSchema: option<S.t<unknown>>,
203
+ stateSchema?: S.t<unknown>,
204
204
  }
205
205
 
206
206
  let makeRegisteredHandler = (
@@ -24,7 +24,7 @@ type handlerConfig = {
24
24
  callbackModule: string,
25
25
  // aggregateName → env-var name holding the aggregate's cmd-topic SQS URL.
26
26
  publishToAggregates: dict<string>,
27
- scheduler: option<schedulerEnvConfig>,
27
+ scheduler?: schedulerEnvConfig,
28
28
  }
29
29
 
30
30
  let strOf = (obj: dict<JSON.t>, key: string): option<string> =>
@@ -45,14 +45,16 @@ let parseHandlerConfig = (rawJson: string): handlerConfig => {
45
45
  ->Dict.toArray
46
46
  ->Array.filterMap(((k, v)) => v->JSON.Decode.string->Option.map(s => (k, s)))
47
47
  ->Dict.fromArray,
48
- scheduler: obj
49
- ->Dict.get("scheduler")
50
- ->Option.flatMap(JSON.Decode.object)
51
- ->Option.map(s => {
52
- roleArnEnv: s->strOf("roleArnEnv")->Option.getOr(""),
53
- targetArnEnv: s->strOf("targetArnEnv")->Option.getOr(""),
54
- targetNameEnv: s->strOf("targetNameEnv")->Option.getOr(""),
55
- }),
48
+ scheduler: ?(
49
+ obj
50
+ ->Dict.get("scheduler")
51
+ ->Option.flatMap(JSON.Decode.object)
52
+ ->Option.map(s => {
53
+ roleArnEnv: s->strOf("roleArnEnv")->Option.getOr(""),
54
+ targetArnEnv: s->strOf("targetArnEnv")->Option.getOr(""),
55
+ targetNameEnv: s->strOf("targetNameEnv")->Option.getOr(""),
56
+ })
57
+ ),
56
58
  }
57
59
  }
58
60
 
@@ -68,7 +68,7 @@ let startSchemaCreationRetrying = (client: appSyncClient, input: startSchemaCrea
68
68
  // GetSchemaCreationStatus — poll until schema is ACTIVE
69
69
  type getSchemaCreationStatusInput = {apiId: string}
70
70
  type getSchemaCreationStatusCommand
71
- type getSchemaCreationStatusResult = {status: string, details: option<string>}
71
+ type getSchemaCreationStatusResult = {status: string, details?: string}
72
72
 
73
73
  @module("@aws-sdk/client-appsync") @new
74
74
  external makeGetSchemaCreationStatusCommand: getSchemaCreationStatusInput => getSchemaCreationStatusCommand =
@@ -119,10 +119,10 @@ type getSourceApiAssociationInput = {
119
119
  }
120
120
  type getSourceApiAssociationCommand
121
121
  type sourceApiAssociationSummary = {
122
- sourceApiAssociationStatus: option<string>,
123
- sourceApiAssociationStatusDetail: option<string>,
122
+ sourceApiAssociationStatus?: string,
123
+ sourceApiAssociationStatusDetail?: string,
124
124
  }
125
- type getSourceApiAssociationResult = {sourceApiAssociation: option<sourceApiAssociationSummary>}
125
+ type getSourceApiAssociationResult = {sourceApiAssociation?: sourceApiAssociationSummary}
126
126
 
127
127
  @module("@aws-sdk/client-appsync") @new
128
128
  external makeGetSourceApiAssociationCommand: getSourceApiAssociationInput => getSourceApiAssociationCommand =
@@ -7,16 +7,35 @@ module Make = (
7
7
  let apiRole: unit => Types.AppSync.role
8
8
  },
9
9
  ) => {
10
+ // The deployed slice runs in the shared DCB command Lambda, which builds its
11
+ // own callback and is handed no capabilities; this in-process path answers the
12
+ // same, so the two cannot differ. A spec that declares a need is refused below.
10
13
  module Inner = ReventlessCore.InboundTranslationSlice_Builder.Make(
11
14
  QueryDbStorage.DynamoDb,
12
15
  QueryDbResolvers.AppSync,
13
16
  Api,
17
+ {
18
+ let capabilities = () => Reventless.Capabilities.none
19
+ },
14
20
  )
15
21
 
16
22
  module Make = (
17
23
  Spec: Reventless.InboundTranslationSlice.Spec,
18
24
  Translation: Reventless.InboundTranslationSlice.Translation with module Spec := Spec,
19
25
  ): (ReventlessCore.InboundTranslationSlice.T with module Spec = Spec) => {
26
+ // Refused rather than deployed to fail quietly: the DCB command Lambda this
27
+ // slice runs in has neither the capability settings nor the grants the
28
+ // automation Lambda gets, so every call would answer `Unavailable` at run
29
+ // time with nothing at deploy time to say why.
30
+ if Spec.capabilityNeeds != [] {
31
+ JsError.throwWithMessage(
32
+ `${Spec.name}: an inbound translation slice that declares capability needs (${Spec.capabilityNeeds
33
+ ->Array.map(Reventless.CapabilityNeed.toString)
34
+ ->Array.join(
35
+ ", ",
36
+ )}) cannot be deployed to AWS yet — the DCB command Lambda it runs in is handed no capabilities. Host it on the local platform.`,
37
+ )
38
+ }
20
39
  // Register spec + translation module paths so the shared DCB command Lambda's
21
40
  // entry point can import them and route `__inboundTranslation` payloads to this
22
41
  // slice's `receive` (mirrors StateChangeSlice_Builder's path registration).
@@ -1,6 +1,10 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
4
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
5
+ import * as Capabilities$Reventless from "@reventlessdev/reventless-spec/src/semantic/Capabilities.res.mjs";
3
6
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
7
+ import * as CapabilityNeed$Reventless from "@reventlessdev/reventless-spec/src/semantic/CapabilityNeed.res.mjs";
4
8
  import * as Util_Bundle$ReventlessAws from "../util/Util_Bundle.res.mjs";
5
9
  import * as PluginRuntime_Builder$ReventlessAws from "../plugin/runtime/PluginRuntime_Builder.res.mjs";
6
10
  import * as QueryDbStorage_DynamoDb$ReventlessAws from "../adapter/QueryDb/QueryDbStorage_DynamoDb.res.mjs";
@@ -8,12 +12,18 @@ import * as QueryDbResolvers_AppSync$ReventlessAws from "../adapter/QueryDb/Quer
8
12
  import * as InboundTranslationSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs";
9
13
 
10
14
  function Make(Api) {
15
+ let capabilities = () => Capabilities$Reventless.none;
11
16
  let Inner = InboundTranslationSlice_Builder$ReventlessCore.Make({
12
17
  make: QueryDbStorage_DynamoDb$ReventlessAws.make
13
18
  })({
14
19
  make: QueryDbResolvers_AppSync$ReventlessAws.make
15
- })(Api);
20
+ })(Api)({
21
+ capabilities: capabilities
22
+ });
16
23
  let Make$1 = Spec => (Translation => {
24
+ if (Primitive_object.notequal(Spec.capabilityNeeds, [])) {
25
+ Stdlib_JsError.throwWithMessage(Spec.name + `: an inbound translation slice that declares capability needs (` + Spec.capabilityNeeds.map(CapabilityNeed$Reventless.toString).join(", ") + `) cannot be deployed to AWS yet — the DCB command Lambda it runs in is handed no capabilities. Host it on the local platform.`);
26
+ }
17
27
  PluginRuntime_Builder$ReventlessAws.registerInboundTranslationSliceSpec(Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Translation.moduleUrl));
18
28
  let match = Spec.endpoint;
19
29
  if (match !== undefined) {
@@ -50,4 +60,4 @@ function Make(Api) {
50
60
  export {
51
61
  Make,
52
62
  }
53
- /* Component-ReventlessCore Not a pure module */
63
+ /* Capabilities-Reventless Not a pure module */
@@ -10,17 +10,14 @@ type runtimeParts = Util.Lambda.runtimeParts
10
10
  // scheduler resources; consumed lazily at deploy-resolve time when
11
11
  // `forCommandTopic` runs inside its `Pulumi.Output.apply`.
12
12
  type adminExtras = {
13
- pluginReadModelTableName: option<Pulumi.Output.t<string>>,
14
- schedulerRoleArn: option<Pulumi.Output.t<string>>,
13
+ pluginReadModelTableName?: Pulumi.Output.t<string>,
14
+ schedulerRoleArn?: Pulumi.Output.t<string>,
15
15
  }
16
16
 
17
- let adminExtras: ref<adminExtras> = ref({
18
- pluginReadModelTableName: None,
19
- schedulerRoleArn: None,
20
- })
17
+ let adminExtras: ref<adminExtras> = ref(({}: adminExtras))
21
18
 
22
19
  let registerPluginExtensionPoint = (~pluginReadModelTableName=?, ~schedulerRoleArn=?, ()) =>
23
- adminExtras := {pluginReadModelTableName, schedulerRoleArn}
20
+ adminExtras := {?pluginReadModelTableName, ?schedulerRoleArn}
24
21
 
25
22
  let forCommandTopic = (
26
23
  ~handler as _,
@@ -8,10 +8,7 @@ import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
8
8
  import * as RuntimeEnvironment_Lambda$ReventlessAws from "../../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
9
9
 
10
10
  let adminExtras = {
11
- contents: {
12
- pluginReadModelTableName: undefined,
13
- schedulerRoleArn: undefined
14
- }
11
+ contents: {}
15
12
  };
16
13
 
17
14
  function registerPluginExtensionPoint(pluginReadModelTableName, schedulerRoleArn, param) {
@@ -1,22 +1,16 @@
1
1
  let log = ReventlessCore.Logger.fromEnv()
2
2
 
3
3
  type adminConfig = {
4
- eventTopicArn: option<Pulumi.Output.t<string>>,
5
- pluginReadModelTableName: option<Pulumi.Output.t<string>>,
6
- schedulerRoleArn: option<Pulumi.Output.t<string>>,
7
- schedulerQueueArn: option<Pulumi.Output.t<string>>,
8
- schedulerQueueName: option<Pulumi.Output.t<string>>,
9
- appSyncApiId: option<Pulumi.Output.t<string>>,
4
+ eventTopicArn?: Pulumi.Output.t<string>,
5
+ pluginReadModelTableName?: Pulumi.Output.t<string>,
6
+ schedulerRoleArn?: Pulumi.Output.t<string>,
7
+ schedulerQueueArn?: Pulumi.Output.t<string>,
8
+ schedulerQueueName?: Pulumi.Output.t<string>,
9
+ appSyncApiId?: Pulumi.Output.t<string>,
10
10
  clonerEnabled: bool,
11
11
  }
12
12
 
13
13
  let configRef: ref<adminConfig> = ref({
14
- eventTopicArn: None,
15
- pluginReadModelTableName: None,
16
- schedulerRoleArn: None,
17
- schedulerQueueArn: None,
18
- schedulerQueueName: None,
19
- appSyncApiId: None,
20
14
  clonerEnabled: false,
21
15
  })
22
16
 
@@ -121,13 +115,12 @@ type sliceModulePaths = {
121
115
 
122
116
  type dcbConfig = {
123
117
  pluginName: string,
124
- dcbTableName: option<Pulumi.Output.t<string>>,
118
+ dcbTableName?: Pulumi.Output.t<string>,
125
119
  stateChangeSliceModulePaths: array<sliceModulePaths>,
126
120
  }
127
121
 
128
122
  let dcbConfigRef: ref<dcbConfig> = ref({
129
123
  pluginName: "",
130
- dcbTableName: None,
131
124
  stateChangeSliceModulePaths: [],
132
125
  })
133
126
 
@@ -219,23 +212,22 @@ compiles; slated for removal.
219
212
  "pluginName is auto-registered by Plugin_Builder.make; use registerDcbTableName / registerStateChangeSliceSpec for the other fields. This call is unnecessary and will be removed."
220
213
  )
221
214
  let registerDcbConfig = (~pluginName, ~dcbTableName=?, ~stateChangeSliceModulePaths=[], ()) => {
222
- dcbConfigRef := {pluginName, dcbTableName, stateChangeSliceModulePaths}
215
+ dcbConfigRef := {pluginName, ?dcbTableName, stateChangeSliceModulePaths}
223
216
  stateChangeSliceModulePaths->Array.length
224
217
  }
225
218
 
226
219
  let registerDcbTableName = (dcbTableName: Pulumi.Output.t<string>) =>
227
- dcbConfigRef := {...dcbConfigRef.contents, dcbTableName: Some(dcbTableName)}
220
+ dcbConfigRef := {...dcbConfigRef.contents, dcbTableName}
228
221
 
229
222
  type heartbeatConfig = {
230
223
  pluginId: string,
231
224
  heartbeatTimeout: int,
232
- epQueueUrl: option<Pulumi.Output.t<string>>,
225
+ epQueueUrl?: Pulumi.Output.t<string>,
233
226
  }
234
227
 
235
228
  let heartbeatConfigRef: ref<heartbeatConfig> = ref({
236
229
  pluginId: "",
237
230
  heartbeatTimeout: 10,
238
- epQueueUrl: None,
239
231
  })
240
232
 
241
233
  // heartbeatTimeout is mandatory: it drives the HEARTBEAT_TIMEOUT env var (and thus
@@ -244,7 +236,7 @@ let heartbeatConfigRef: ref<heartbeatConfig> = ref({
244
236
  // silently decoupled the two (schedule every 60min, Heartbeat(10) → 12min grace →
245
237
  // flapping); make callers supply it so the values can't diverge.
246
238
  let registerHeartbeatConfig = (~pluginId, ~heartbeatTimeout, ~epQueueUrl=?, ()) =>
247
- heartbeatConfigRef := {pluginId, heartbeatTimeout, epQueueUrl}
239
+ heartbeatConfigRef := {pluginId, heartbeatTimeout, ?epQueueUrl}
248
240
 
249
241
  // Resolves once this plugin's EventCollector Lambda exists at its new code.
250
242
  // `Platform.deployPlugin` gates the deploy-time re-detect on it: the re-detect
@@ -285,12 +277,12 @@ let registerConfig = (
285
277
  (),
286
278
  ) =>
287
279
  configRef := {
288
- eventTopicArn,
289
- pluginReadModelTableName,
290
- schedulerRoleArn,
291
- schedulerQueueArn,
292
- schedulerQueueName,
293
- appSyncApiId,
280
+ ?eventTopicArn,
281
+ ?pluginReadModelTableName,
282
+ ?schedulerRoleArn,
283
+ ?schedulerQueueArn,
284
+ ?schedulerQueueName,
285
+ ?appSyncApiId,
294
286
  clonerEnabled,
295
287
  }
296
288
 
@@ -351,7 +343,6 @@ module Make = (
351
343
  aggregateNames: [ReventlessCore.PluginSpec.name],
352
344
  },
353
345
  ],
354
- connectExtension: None,
355
346
  extensions: [],
356
347
  pluginExtensionPointCmdTopicUrl: Pulumi.Output.make(""),
357
348
  publishToAggregates: Dict.make(),
@@ -29,12 +29,6 @@ let log = Logger$ReventlessCore.fromEnv();
29
29
 
30
30
  let configRef = {
31
31
  contents: {
32
- eventTopicArn: undefined,
33
- pluginReadModelTableName: undefined,
34
- schedulerRoleArn: undefined,
35
- schedulerQueueArn: undefined,
36
- schedulerQueueName: undefined,
37
- appSyncApiId: undefined,
38
32
  clonerEnabled: false
39
33
  }
40
34
  };
@@ -118,7 +112,6 @@ function identityProviderProvisioned() {
118
112
  let dcbConfigRef = {
119
113
  contents: {
120
114
  pluginName: "",
121
- dcbTableName: undefined,
122
115
  stateChangeSliceModulePaths: []
123
116
  }
124
117
  };
@@ -192,19 +185,15 @@ function registerDcbConfig(pluginName, dcbTableName, stateChangeSliceModulePaths
192
185
  }
193
186
 
194
187
  function registerDcbTableName(dcbTableName) {
195
- let init = dcbConfigRef.contents;
196
- dcbConfigRef.contents = {
197
- pluginName: init.pluginName,
198
- dcbTableName: dcbTableName,
199
- stateChangeSliceModulePaths: init.stateChangeSliceModulePaths
200
- };
188
+ let newrecord = {...dcbConfigRef.contents};
189
+ newrecord.dcbTableName = dcbTableName;
190
+ dcbConfigRef.contents = newrecord;
201
191
  }
202
192
 
203
193
  let heartbeatConfigRef = {
204
194
  contents: {
205
195
  pluginId: "",
206
- heartbeatTimeout: 10,
207
- epQueueUrl: undefined
196
+ heartbeatTimeout: 10
208
197
  }
209
198
  };
210
199
 
@@ -252,12 +241,9 @@ function registerConfig(eventTopicArn, pluginReadModelTableName, schedulerRoleAr
252
241
 
253
242
  function Make(EventCollectorChannel) {
254
243
  let registerPluginName = pluginName => {
255
- let init = dcbConfigRef.contents;
256
- dcbConfigRef.contents = {
257
- pluginName: pluginName,
258
- dcbTableName: init.dcbTableName,
259
- stateChangeSliceModulePaths: init.stateChangeSliceModulePaths
260
- };
244
+ let newrecord = {...dcbConfigRef.contents};
245
+ newrecord.pluginName = pluginName;
246
+ dcbConfigRef.contents = newrecord;
261
247
  };
262
248
  let outputOrPlaceholder = opt => {
263
249
  if (opt !== undefined) {
@@ -280,7 +266,6 @@ function Make(EventCollectorChannel) {
280
266
  eventTopicArn: adminEpEventTopicArn,
281
267
  aggregateNames: [PluginSpec$ReventlessCore.name]
282
268
  }],
283
- connectExtension: undefined,
284
269
  extensions: [],
285
270
  pluginExtensionPointCmdTopicUrl: Pulumi.output(""),
286
271
  publishToAggregates: {},
@@ -33,7 +33,7 @@ let assertParity = (
33
33
  ~secretAccessKey,
34
34
  ~sessionToken,
35
35
  ) => {
36
- let creds: AppSyncEventsSigner_Ops.creds = {accessKeyId, secretAccessKey, sessionToken}
36
+ let creds: AppSyncEventsSigner_Ops.creds = {accessKeyId, secretAccessKey, ?sessionToken}
37
37
  let mine = AppSyncEventsSigner_Ops.signedHeaders(~host, ~path, ~body, ~region, ~isoNow, ~creds)
38
38
  let jsCreds: jsCreds = {accessKeyId, secretAccessKey, ?sessionToken}
39
39
  let ref = signedHeadersJs(~host, ~path, ~body, ~region, ~isoNow, ~creds=jsCreds)
@@ -961,10 +961,10 @@ describe("AppSync_Adapter.waitForMergeSuccess", () => {
961
961
  }
962
962
 
963
963
  let response = (~status, ~detail=?): AppSync_Adapter.getSourceApiAssociationResult => {
964
- sourceApiAssociation: Some({
965
- sourceApiAssociationStatus: Some(status),
966
- sourceApiAssociationStatusDetail: detail,
967
- }),
964
+ sourceApiAssociation: {
965
+ sourceApiAssociationStatus: status,
966
+ sourceApiAssociationStatusDetail: ?detail,
967
+ },
968
968
  }
969
969
 
970
970
  test("resolves once the association reports MERGE_SUCCESS", async () => {