@reventlessdev/reventless-core 3.0.0-alpha.156 → 3.0.0-alpha.158
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/package.json +6 -6
- package/src/admin/AdminApi.res +80 -10
- package/src/admin/AdminApi.res.mjs +45 -7
- package/src/admin/ApiFragmentRegistry/StateChangeSlice/ApiFragmentRegistry.res +65 -0
- package/src/admin/ApiFragmentRegistry/StateChangeSlice/ApiFragmentRegistry.res.mjs +87 -0
- package/src/admin/ApiFragmentRegistry/StateChangeSlice/ApiFragmentRegistry_Behavior.res +58 -0
- package/src/admin/ApiFragmentRegistry/StateChangeSlice/ApiFragmentRegistry_Behavior.res.mjs +135 -0
- package/src/admin/ApiFragmentRegistry/StateViewSlice/ApiFragments.res +44 -0
- package/src/admin/ApiFragmentRegistry/StateViewSlice/ApiFragments.res.mjs +74 -0
- package/src/admin/ApiFragmentRegistry/StateViewSlice/ApiFragments_Projection.res +50 -0
- package/src/admin/ApiFragmentRegistry/StateViewSlice/ApiFragments_Projection.res.mjs +80 -0
- package/src/admin/Platform_Admin.res +46 -1
- package/src/admin/Platform_Admin.res.mjs +20 -6
- package/src/admin/Platform_ApiFragmentsApi.res +32 -0
- package/src/admin/Platform_ApiFragmentsApi.res.mjs +52 -0
- package/src/admin/Platform_UIFragmentsApi.res +1 -1
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res +50 -0
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +70 -0
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry_Behavior.res +33 -0
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry_Behavior.res.mjs +80 -0
- package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments.res +33 -0
- package/src/admin/{UIFragmentRegistryReadModelSpec.res.mjs → UiFragmentRegistry/StateViewSlice/UiFragments.res.mjs} +24 -2
- package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res +34 -0
- package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res.mjs +54 -0
- package/src/components/Api/Api_Naming.res +1 -1
- package/src/components/Api/GraphQL_FragmentGenerator.res +7 -11
- package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +8 -22
- package/src/components/Api/GraphQL_PushPlanner.res +65 -0
- package/src/components/Api/GraphQL_PushPlanner.res.mjs +46 -0
- package/src/components/Api/GraphQL_Stitcher.res +72 -1
- package/src/components/Api/GraphQL_Stitcher.res.mjs +53 -2
- package/src/components/Dcb/Dcb_Builder.res +16 -6
- package/src/components/Dcb/Dcb_Builder.res.mjs +10 -7
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +6 -1
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +1 -1
- package/src/plugin/api/PluginBaseFragment.res +5 -6
- package/src/plugin/api/PluginBaseFragment.res.mjs +0 -1
- package/src/plugin/component/Plugin_Builder.res +4 -1
- package/src/plugin/component/Plugin_Builder.res.mjs +7 -6
- package/src/plugin/component/Plugin_Helpers.res +30 -0
- package/src/plugin/component/Plugin_Helpers.res.mjs +13 -3
- package/src/plugin/component/Plugin_SubscriptionSchema.res +19 -9
- package/src/plugin/component/Plugin_SubscriptionSchema.res.mjs +23 -14
- package/src/plugin/connect/PluginConnectExtension_Mapping.res +28 -6
- package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +34 -14
- package/src/plugin/connect/PluginExtensionPoint_Builder.res +7 -1
- package/src/plugin/connect/PluginExtensionPoint_Builder.res.mjs +5 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res +3 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +4 -2
- package/src/plugin/connect/PluginExtensionPoint_UiFragment.res +52 -0
- package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +74 -0
- package/src/plugin/lifecycle/PluginBehavior.res +9 -51
- package/src/plugin/lifecycle/PluginBehavior.res.mjs +39 -68
- package/src/plugin/lifecycle/PluginSpec.res +0 -18
- package/src/plugin/lifecycle/PluginSpec.res.mjs +0 -30
- package/src/plugin/lifecycle/PluginsProjection.res +2 -6
- package/src/plugin/lifecycle/PluginsProjection.res.mjs +0 -2
- package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
- package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +0 -1
- package/tests/admin/Platform_ApiFragmentsApiTest.res +66 -0
- package/tests/admin/Platform_ApiFragmentsApiTest.res.mjs +68 -0
- package/tests/admin/Platform_UIFragmentsApiTest.res +1 -1
- package/tests/api/GraphQL_PushPlannerTest.res +62 -0
- package/tests/api/GraphQL_PushPlannerTest.res.mjs +80 -0
- package/tests/api/GraphQL_StitcherTest.res +63 -0
- package/tests/api/GraphQL_StitcherTest.res.mjs +75 -0
- package/tests/logger/LogFormatTest.res +1 -2
- package/tests/logger/LogFormatTest.res.mjs +1 -2
- package/tests/message/MessageTest.res +0 -3
- package/tests/message/MessageTest.res.mjs +0 -3
- package/src/admin/UIFragmentRegistryProjection.res +0 -43
- package/src/admin/UIFragmentRegistryProjection.res.mjs +0 -81
- package/src/admin/UIFragmentRegistryReadModelSpec.res +0 -13
|
@@ -68,6 +68,15 @@ module Make = (
|
|
|
68
68
|
let construct = (
|
|
69
69
|
~name: string,
|
|
70
70
|
~childName: string,
|
|
71
|
+
// API mutation-field prefix for a slice's GraphQL command fields. Defaults to `name`
|
|
72
|
+
// (`${plugin}_${command}`), so plugins are unchanged. The admin builder passes "Platform"
|
|
73
|
+
// so its exposed slice commands render as `Platform_RegisterApiFragment` — byte-equal to
|
|
74
|
+
// `Api_Naming.adminField("RegisterApiFragment")`, keeping the hand-declared admin SDL and
|
|
75
|
+
// the auto-bound DCB resolver field names aligned.
|
|
76
|
+
~apiNamePrefix: string=name,
|
|
77
|
+
// True for the platform admin build — routes the DCB mutation resolvers to the Platform API
|
|
78
|
+
// (via the provider hook's `hooks.adminApi`) in split mode. Plugins leave it false.
|
|
79
|
+
~onAdminApi: bool=false,
|
|
71
80
|
~environment: string="",
|
|
72
81
|
~platformName: string="",
|
|
73
82
|
~aggregateEventTopics: EventTopic.allOutputs=Dict.make(),
|
|
@@ -411,7 +420,7 @@ module Make = (
|
|
|
411
420
|
registerResolver(
|
|
412
421
|
~kind=Dcb,
|
|
413
422
|
~fields=Api_Naming.sliceMutationFields(
|
|
414
|
-
~plugin=
|
|
423
|
+
~plugin=apiNamePrefix,
|
|
415
424
|
~slice=S.Spec.name,
|
|
416
425
|
~commandSchema,
|
|
417
426
|
)->Array.map(((f, _)) => f),
|
|
@@ -428,7 +437,7 @@ module Make = (
|
|
|
428
437
|
registerResolver(
|
|
429
438
|
~kind=Dcb,
|
|
430
439
|
~fields=Api_Naming.sliceMutationFields(
|
|
431
|
-
~plugin=
|
|
440
|
+
~plugin=apiNamePrefix,
|
|
432
441
|
~slice=S.Spec.name,
|
|
433
442
|
~commandSchema,
|
|
434
443
|
)->Array.map(((f, _)) => f),
|
|
@@ -464,7 +473,7 @@ module Make = (
|
|
|
464
473
|
~componentKind=CommandGenerator_Callback.StateChangeSlice,
|
|
465
474
|
~stripIdFromParams=false,
|
|
466
475
|
)
|
|
467
|
-
Api_Naming.sliceMutationFields(~plugin=
|
|
476
|
+
Api_Naming.sliceMutationFields(~plugin=apiNamePrefix, ~slice=S.Spec.name, ~commandSchema)
|
|
468
477
|
->Array.forEach(((fieldName, _)) => bindHandler(~field=fieldName, ~generateCommand))
|
|
469
478
|
}
|
|
470
479
|
})
|
|
@@ -491,7 +500,7 @@ module Make = (
|
|
|
491
500
|
~componentKind=CommandGenerator_Callback.StateChangeSlice,
|
|
492
501
|
~stripIdFromParams=false,
|
|
493
502
|
)
|
|
494
|
-
Api_Naming.sliceMutationFields(~plugin=
|
|
503
|
+
Api_Naming.sliceMutationFields(~plugin=apiNamePrefix, ~slice=S.Spec.name, ~commandSchema)
|
|
495
504
|
->Array.forEach(((fieldName, _)) => bindHandler(~field=fieldName, ~generateCommand))
|
|
496
505
|
}
|
|
497
506
|
})
|
|
@@ -730,7 +739,7 @@ module Make = (
|
|
|
730
739
|
if ApiNoApiHelpers.isNoApi(commandSchema) {
|
|
731
740
|
[]
|
|
732
741
|
} else {
|
|
733
|
-
Api_Naming.sliceMutationFields(~plugin=
|
|
742
|
+
Api_Naming.sliceMutationFields(~plugin=apiNamePrefix, ~slice=S.Spec.name, ~commandSchema)
|
|
734
743
|
}
|
|
735
744
|
})
|
|
736
745
|
let dcbFieldNames = dcbMutationData->Array.map(((f, _)) => f)
|
|
@@ -759,6 +768,7 @@ module Make = (
|
|
|
759
768
|
runtime: runtime->Obj.magic,
|
|
760
769
|
fieldNames: dcbFieldNames,
|
|
761
770
|
tags: dcbTags,
|
|
771
|
+
onAdminApi,
|
|
762
772
|
opts,
|
|
763
773
|
})
|
|
764
774
|
| None => ()
|
|
@@ -825,7 +835,7 @@ module Make = (
|
|
|
825
835
|
) => {
|
|
826
836
|
let commandSchema = S.Spec.commandSchema->Reventless.DcbTag.toUnknownSchema
|
|
827
837
|
let fieldSpecs =
|
|
828
|
-
Api_Naming.sliceMutationFields(~plugin=
|
|
838
|
+
Api_Naming.sliceMutationFields(~plugin=apiNamePrefix, ~slice=S.Spec.name, ~commandSchema)
|
|
829
839
|
if ApiNoApiHelpers.isNoApi(commandSchema) || fieldSpecs->Array.length == 0 {
|
|
830
840
|
None
|
|
831
841
|
} else {
|
|
@@ -78,7 +78,9 @@ let emptyResult = {
|
|
|
78
78
|
|
|
79
79
|
function Make(DcbEventLogStorage) {
|
|
80
80
|
return DcbEventTopicPublisher => (DcbCommandTopicChannel => (DcbCommandTopicChannelAsync => (RuntimeBuilder => (HooksConfig => {
|
|
81
|
-
let construct = (name, childName, environmentOpt, platformNameOpt, aggregateEventTopicsOpt, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponentsOpt, pluginStructure, opts) => {
|
|
81
|
+
let construct = (name, childName, apiNamePrefixOpt, onAdminApiOpt, environmentOpt, platformNameOpt, aggregateEventTopicsOpt, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponentsOpt, pluginStructure, opts) => {
|
|
82
|
+
let apiNamePrefix = apiNamePrefixOpt !== undefined ? apiNamePrefixOpt : name;
|
|
83
|
+
let onAdminApi = onAdminApiOpt !== undefined ? onAdminApiOpt : false;
|
|
82
84
|
let environment = environmentOpt !== undefined ? environmentOpt : "";
|
|
83
85
|
let platformName = platformNameOpt !== undefined ? platformNameOpt : "";
|
|
84
86
|
let aggregateEventTopics = aggregateEventTopicsOpt !== undefined ? aggregateEventTopicsOpt : ({});
|
|
@@ -225,13 +227,13 @@ function Make(DcbEventLogStorage) {
|
|
|
225
227
|
syncSlices.forEach(S => {
|
|
226
228
|
let commandSchema = S.Spec.commandSchema;
|
|
227
229
|
if (!ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|
|
228
|
-
return registerResolver("Dcb", Api_Naming$ReventlessCore.sliceMutationFields(
|
|
230
|
+
return registerResolver("Dcb", Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema).map(param => param[0]), commandSchema, S.Spec.commandAuthorization);
|
|
229
231
|
}
|
|
230
232
|
});
|
|
231
233
|
asyncSlices.forEach(S => {
|
|
232
234
|
let commandSchema = S.Spec.commandSchema;
|
|
233
235
|
if (!ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|
|
234
|
-
return registerResolver("Dcb", Api_Naming$ReventlessCore.sliceMutationFields(
|
|
236
|
+
return registerResolver("Dcb", Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema).map(param => param[0]), commandSchema, S.Spec.commandAuthorization);
|
|
235
237
|
}
|
|
236
238
|
});
|
|
237
239
|
}
|
|
@@ -244,7 +246,7 @@ function Make(DcbEventLogStorage) {
|
|
|
244
246
|
return;
|
|
245
247
|
}
|
|
246
248
|
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(ops.publishJsons, ops.publishJsonsAndWait, S.Spec.name, S.Spec.commandSchema, "StateChangeSlice", false);
|
|
247
|
-
Api_Naming$ReventlessCore.sliceMutationFields(
|
|
249
|
+
Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema).forEach(param => bindHandler(param[0], generateCommand));
|
|
248
250
|
});
|
|
249
251
|
});
|
|
250
252
|
if (asyncDcbCommandTopicOpt !== undefined) {
|
|
@@ -255,7 +257,7 @@ function Make(DcbEventLogStorage) {
|
|
|
255
257
|
return;
|
|
256
258
|
}
|
|
257
259
|
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(asyncOps.publishJsons, asyncOps.publishJsonsAndWait, S.Spec.name, S.Spec.commandSchema, "StateChangeSlice", false);
|
|
258
|
-
Api_Naming$ReventlessCore.sliceMutationFields(
|
|
260
|
+
Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema).forEach(param => bindHandler(param[0], generateCommand));
|
|
259
261
|
});
|
|
260
262
|
});
|
|
261
263
|
}
|
|
@@ -397,7 +399,7 @@ function Make(DcbEventLogStorage) {
|
|
|
397
399
|
if (ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|
|
398
400
|
return [];
|
|
399
401
|
} else {
|
|
400
|
-
return Api_Naming$ReventlessCore.sliceMutationFields(
|
|
402
|
+
return Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema);
|
|
401
403
|
}
|
|
402
404
|
});
|
|
403
405
|
let dcbFieldNames = dcbMutationData.map(param => param[0]);
|
|
@@ -424,6 +426,7 @@ function Make(DcbEventLogStorage) {
|
|
|
424
426
|
runtime: runtime,
|
|
425
427
|
fieldNames: dcbFieldNames,
|
|
426
428
|
tags: dcbTags,
|
|
429
|
+
onAdminApi: onAdminApi,
|
|
427
430
|
opts: opts
|
|
428
431
|
});
|
|
429
432
|
}
|
|
@@ -451,7 +454,7 @@ function Make(DcbEventLogStorage) {
|
|
|
451
454
|
};
|
|
452
455
|
let mutationEntriesFromSlices = Stdlib_Array.filterMap(stateChangeSlices, S => {
|
|
453
456
|
let commandSchema = S.Spec.commandSchema;
|
|
454
|
-
let fieldSpecs = Api_Naming$ReventlessCore.sliceMutationFields(
|
|
457
|
+
let fieldSpecs = Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema);
|
|
455
458
|
if (ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema) || fieldSpecs.length === 0) {
|
|
456
459
|
return;
|
|
457
460
|
}
|
|
@@ -34,7 +34,12 @@ module Make = (
|
|
|
34
34
|
~tagKeysByEventType: Dict.t<array<string>>,
|
|
35
35
|
event: Spec.event,
|
|
36
36
|
): ReventlessInfra.DcbEventLog.rawEvent => {
|
|
37
|
-
|
|
37
|
+
// Encode through the event schema (like the Aggregate path's Message.encode),
|
|
38
|
+
// NOT JSON.stringifyAny: the runtime representation drops `None` option
|
|
39
|
+
// fields entirely, while the consumer side (DcbDecode) parses with the sury
|
|
40
|
+
// schema — a js_nullable option field would reject the missing key and the
|
|
41
|
+
// event would be dropped as schema drift.
|
|
42
|
+
let json = event->S.reverseConvertToJsonOrThrow(Spec.eventSchema)
|
|
38
43
|
let (eventType, data) = json->Message.splitMessage
|
|
39
44
|
// Use `extractTagsExpanded` (not `extractTags`) so per-element tags on
|
|
40
45
|
// `array<string>` fields are emitted — e.g. OrderPlaced's
|
|
@@ -182,7 +182,7 @@ function Make(Spec) {
|
|
|
182
182
|
}
|
|
183
183
|
let rawEvents = newEvents$1.map(e => {
|
|
184
184
|
let parentMeta = command$p.meta;
|
|
185
|
-
let json =
|
|
185
|
+
let json = S.reverseConvertToJsonOrThrow(e, Spec.eventSchema);
|
|
186
186
|
let match = Message$ReventlessCore.splitMessage(json);
|
|
187
187
|
let eventType = match[0];
|
|
188
188
|
let baseTags = DcbTag$Reventless.extractTagsExpanded(Spec.eventSchema, e);
|
|
@@ -18,13 +18,12 @@ let pluginExcludeFields: array<string> = [
|
|
|
18
18
|
|
|
19
19
|
// Additional fields the SDL exposes but the Plugin list view should NOT
|
|
20
20
|
// surface — they're option-of-nested-object types (e.g. apiSchemaFragment,
|
|
21
|
-
//
|
|
21
|
+
// structure) which AutoUI currently renders as scalar columns
|
|
22
22
|
// and queries without a sub-selection, failing schema validation. Other
|
|
23
|
-
// callers (host-shell's Platform_ComponentDefinitions
|
|
24
|
-
//
|
|
23
|
+
// callers (host-shell's Platform_ComponentDefinitions) keep querying them via
|
|
24
|
+
// dedicated fields and resolver paths.
|
|
25
25
|
let pluginUIOnlyExcludeFields: array<string> = pluginExcludeFields->Array.concat([
|
|
26
26
|
"apiSchemaFragment",
|
|
27
|
-
"uiFragments",
|
|
28
27
|
"structure",
|
|
29
28
|
])
|
|
30
29
|
|
|
@@ -40,10 +39,10 @@ let pluginUIOnlyExcludeFields: array<string> = pluginExcludeFields->Array.concat
|
|
|
40
39
|
let indexQueriesOfConfig = (config: Reventless.ReadModel.config) =>
|
|
41
40
|
config.indexes->Array.length > 0 ? Some(config.indexes) : None
|
|
42
41
|
|
|
43
|
-
// The
|
|
42
|
+
// The UiFragments StateViewSlice is queried exclusively via the explicit
|
|
44
43
|
// flat `Platform_UIFragments: [Platform_UIFragmentEntry!]!` field declared in
|
|
45
44
|
// `Platform_UIFragmentsApi.res` (and resolved by `Platform_UIFragments_Lambda.res`
|
|
46
|
-
// on AWS / the
|
|
45
|
+
// on AWS / the slice QueryDb in-memory). Reintroducing an auto-generated
|
|
47
46
|
// connection field here collides with that name on SDL composition.
|
|
48
47
|
let queryEntries: array<querySchemaEntry> = [
|
|
49
48
|
{
|
|
@@ -295,6 +295,7 @@ module Make = (
|
|
|
295
295
|
...parts,
|
|
296
296
|
types: Array.concat(parts.types, subResult.extraTypes),
|
|
297
297
|
subscriptions: subResult.subscriptionFields,
|
|
298
|
+
subscriptionSources: subResult.subscriptionSources,
|
|
298
299
|
})
|
|
299
300
|
}
|
|
300
301
|
|
|
@@ -750,7 +751,6 @@ module Make = (
|
|
|
750
751
|
extensionProtocols: [],
|
|
751
752
|
apiSchemaFragment: Some(apiSchemaFragment),
|
|
752
753
|
apiTarget: Some(capturedDeployTarget),
|
|
753
|
-
uiFragments,
|
|
754
754
|
structure: pluginStructure,
|
|
755
755
|
dcbEventLog: dcbEventLogDef,
|
|
756
756
|
// Business role from the deploy-time metadata registry (set via
|
|
@@ -807,6 +807,7 @@ module Make = (
|
|
|
807
807
|
connectPluginExtensionIncomingEventHandler,
|
|
808
808
|
) = createConnectPluginExtension(
|
|
809
809
|
~pluginDefinition,
|
|
810
|
+
~uiFragments,
|
|
810
811
|
~publishToPluginExtensionPoint,
|
|
811
812
|
~publishToAggregates,
|
|
812
813
|
~readModelNamesForSourceName,
|
|
@@ -821,6 +822,7 @@ module Make = (
|
|
|
821
822
|
~extensionsOutputs,
|
|
822
823
|
~pluginExtensionPointUnwrapped,
|
|
823
824
|
~pluginDefinition,
|
|
825
|
+
~uiFragments,
|
|
824
826
|
~connectPluginExtensionIncomingEventHandler,
|
|
825
827
|
~extensionsHandlers,
|
|
826
828
|
~extensionPointsHandlers,
|
|
@@ -840,6 +842,7 @@ module Make = (
|
|
|
840
842
|
~extensionPointsOutputs,
|
|
841
843
|
~extensionsOutputs,
|
|
842
844
|
~pluginDefinition,
|
|
845
|
+
~uiFragments,
|
|
843
846
|
~extensionsHandlers,
|
|
844
847
|
~extensionPointsHandlers,
|
|
845
848
|
~extensionRegistryInfos,
|
|
@@ -6,6 +6,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
6
6
|
import * as Pulumi from "@pulumi/pulumi";
|
|
7
7
|
import * as Belt_SetString from "@rescript/runtime/lib/es6/Belt_SetString.js";
|
|
8
8
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
9
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
9
10
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
10
11
|
import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
|
|
11
12
|
import * as Plugin$ReventlessCore from "./Plugin.res.mjs";
|
|
@@ -146,7 +147,7 @@ function Make(Spec) {
|
|
|
146
147
|
let DcbBuilder = Dcb_Builder$ReventlessCore.Make(DcbEventLogStorage)(DcbEventTopicPublisher)(DcbCommandTopicChannel)(DcbCommandTopicChannelAsync)(PluginRuntimeBuilder)({
|
|
147
148
|
hooks: Spec.hooks
|
|
148
149
|
});
|
|
149
|
-
let dcbResult = DcbBuilder.construct(extra$1, childName, Spec.environment, Spec.platformName, aggregateEventTopics, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponents, pluginStructure, opts);
|
|
150
|
+
let dcbResult = DcbBuilder.construct(extra$1, childName, undefined, undefined, Spec.environment, Spec.platformName, aggregateEventTopics, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponents, pluginStructure, opts);
|
|
150
151
|
let mutationEntriesFromAggregates = aggregates.flatMap(M => {
|
|
151
152
|
let commandSchema = M.Spec.commandSchema;
|
|
152
153
|
if (ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|
|
@@ -227,7 +228,8 @@ function Make(Spec) {
|
|
|
227
228
|
types: parts.types.concat(subResult.extraTypes),
|
|
228
229
|
mutations: parts.mutations,
|
|
229
230
|
queries: parts.queries,
|
|
230
|
-
subscriptions: subResult.subscriptionFields
|
|
231
|
+
subscriptions: subResult.subscriptionFields,
|
|
232
|
+
subscriptionSources: subResult.subscriptionSources
|
|
231
233
|
});
|
|
232
234
|
Stdlib_Option.forEach(Spec.hooks.schemaTypeRegistrationHook, registerTypes => {
|
|
233
235
|
let parts = GraphQL_Stitcher$ReventlessCore.decode(apiSchemaFragment);
|
|
@@ -496,7 +498,6 @@ function Make(Spec) {
|
|
|
496
498
|
extensionProtocols: [],
|
|
497
499
|
apiSchemaFragment: apiSchemaFragment,
|
|
498
500
|
apiTarget: capturedDeployTarget,
|
|
499
|
-
uiFragments: uiFragments,
|
|
500
501
|
structure: pluginStructure,
|
|
501
502
|
dcbEventLog: param[2],
|
|
502
503
|
kind: Stdlib_Option.getOr(Stdlib_Option.flatMap(Plugin_Helpers$ReventlessCore.pluginMetadataRegistry.contents, m => m.kind), "Domain")
|
|
@@ -528,10 +529,10 @@ function Make(Spec) {
|
|
|
528
529
|
readModelQueueUrls[param[0]] = urlOutput;
|
|
529
530
|
});
|
|
530
531
|
if (coreSetup !== undefined) {
|
|
531
|
-
let match$4 = Plugin_Helpers$ReventlessCore.createConnectPluginExtension(pluginDefinition, publishToPluginExtensionPoint, publishToAggregates, Plugin_Helpers$ReventlessCore.readModelNamesForSourceName, publishToReadModels, queryEngine, opts);
|
|
532
|
-
EventCollectorHelper.connect(eventCollector, eventTopics, extensionPointsOutputs, extensionsOutputs, coreSetup[0], pluginDefinition, match$4[1], extensionsHandlers, extensionPointsHandlers, match$4[0], extensionRegistryInfos, match$1[2], aggregateQueueUrls, readModelQueueUrls, Plugin_Helpers$ReventlessCore.readModelNamesForSourceName);
|
|
532
|
+
let match$4 = Plugin_Helpers$ReventlessCore.createConnectPluginExtension(pluginDefinition, uiFragments, publishToPluginExtensionPoint, publishToAggregates, Plugin_Helpers$ReventlessCore.readModelNamesForSourceName, publishToReadModels, queryEngine, opts);
|
|
533
|
+
EventCollectorHelper.connect(eventCollector, eventTopics, extensionPointsOutputs, extensionsOutputs, coreSetup[0], pluginDefinition, Primitive_option.some(uiFragments), match$4[1], extensionsHandlers, extensionPointsHandlers, match$4[0], extensionRegistryInfos, match$1[2], aggregateQueueUrls, readModelQueueUrls, Plugin_Helpers$ReventlessCore.readModelNamesForSourceName);
|
|
533
534
|
} else {
|
|
534
|
-
EventCollectorHelper.connect(eventCollector, eventTopics, extensionPointsOutputs, extensionsOutputs, undefined, pluginDefinition, undefined, extensionsHandlers, extensionPointsHandlers, undefined, extensionRegistryInfos, undefined, aggregateQueueUrls, readModelQueueUrls, Plugin_Helpers$ReventlessCore.readModelNamesForSourceName);
|
|
535
|
+
EventCollectorHelper.connect(eventCollector, eventTopics, extensionPointsOutputs, extensionsOutputs, undefined, pluginDefinition, Primitive_option.some(uiFragments), undefined, extensionsHandlers, extensionPointsHandlers, undefined, extensionRegistryInfos, undefined, aggregateQueueUrls, readModelQueueUrls, Plugin_Helpers$ReventlessCore.readModelNamesForSourceName);
|
|
535
536
|
}
|
|
536
537
|
let tasksOutputs = Plugin_Helpers$ReventlessCore.createTasks(tasks, aggregatesOutputs, scheduler, schedulerRoleUrn, publishToAggregates, queryEngine, Spec.resourceNaming, opts);
|
|
537
538
|
let resolvers = Plugin_Helpers$ReventlessCore.createResolvers(allQueryDbs);
|
|
@@ -146,6 +146,12 @@ type eventCollectorContext = {
|
|
|
146
146
|
// Pre-serialised JSON of the pluginDefinition (sury-encoded then JSON.stringify).
|
|
147
147
|
// Output because it's assembled from resolved component outputs at deploy time.
|
|
148
148
|
pluginDefinitionJson: Pulumi.Output.t<string>,
|
|
149
|
+
// Pre-serialised JSON of the plugin's UI-fragment manifest ("null" when the
|
|
150
|
+
// plugin ships none). Shipped as its own asset next to pluginDefinition.json —
|
|
151
|
+
// the manifest no longer rides pluginDefinition (the UiFragmentRegistry slice
|
|
152
|
+
// owns fragment state); the bundled Connect extension needs it at cold start
|
|
153
|
+
// to emit RegisterUiFragment in the handshake answer.
|
|
154
|
+
uiFragmentsJson: Pulumi.Output.t<string>,
|
|
149
155
|
// Outgoing EPs whose events this Lambda's mapping handles. Admin Lambda: 1
|
|
150
156
|
// entry (its own Plugin EP). Plugin Lambda: 0 (plugins don't process their own
|
|
151
157
|
// EP outgoing events here).
|
|
@@ -368,6 +374,7 @@ let extractExtensionDefinitions = (extensionsOutputs: array<Extension.outputs>)
|
|
|
368
374
|
|
|
369
375
|
let createConnectPluginExtension = (
|
|
370
376
|
~pluginDefinition,
|
|
377
|
+
~uiFragments: option<Reventless.Plugin.uiFragmentManifest>,
|
|
371
378
|
~publishToPluginExtensionPoint,
|
|
372
379
|
~publishToAggregates,
|
|
373
380
|
~readModelNamesForSourceName,
|
|
@@ -379,6 +386,7 @@ let createConnectPluginExtension = (
|
|
|
379
386
|
->Pulumi.Output.apply(pluginDefinition => {
|
|
380
387
|
module ConnectPluginExtension = PluginConnectExtension_Builder.Make({
|
|
381
388
|
let pluginDefinition = pluginDefinition
|
|
389
|
+
let uiFragments = uiFragments
|
|
382
390
|
})
|
|
383
391
|
let connectPluginExtension = ConnectPluginExtension.make(
|
|
384
392
|
~publishToPluginExtensionPoint,
|
|
@@ -472,6 +480,10 @@ module MakeEventCollectorHelper = (
|
|
|
472
480
|
~extensionsOutputs: array<Extension.outputs>,
|
|
473
481
|
~pluginExtensionPointUnwrapped: option<ReventlessInterop.ExtensionPoint.resolvedOutputs>=?,
|
|
474
482
|
~pluginDefinition,
|
|
483
|
+
// The plugin's UI-fragment manifest — serialised into the per-plugin
|
|
484
|
+
// eventCollectorContext (uiFragmentsJson) so the AWS adapter ships it as a
|
|
485
|
+
// uiFragments.json asset for the bundled Connect extension's cold start.
|
|
486
|
+
~uiFragments: option<Reventless.Plugin.uiFragmentManifest>=None,
|
|
475
487
|
~connectPluginExtensionIncomingEventHandler: option<Pulumi.Output.t<Pulumi.Output.t<Plugin_Callback.jsonEventsHandler>>>=?,
|
|
476
488
|
~extensionsHandlers,
|
|
477
489
|
~extensionPointsHandlers,
|
|
@@ -589,6 +601,11 @@ module MakeEventCollectorHelper = (
|
|
|
589
601
|
->S.reverseConvertToJsonOrThrow(Reventless.Plugin.pluginDefinitionSchema)
|
|
590
602
|
->JSON.stringify
|
|
591
603
|
->Pulumi.Output.make
|
|
604
|
+
let uiFragmentsJson =
|
|
605
|
+
uiFragments
|
|
606
|
+
->S.reverseConvertToJsonOrThrow(Reventless.Plugin.uiFragmentManifestOptionSchema)
|
|
607
|
+
->JSON.stringify
|
|
608
|
+
->Pulumi.Output.make
|
|
592
609
|
let pluginExtensionPointCmdTopicUrl = switch pluginExtensionPointUnwrapped {
|
|
593
610
|
| Some(unwrapped) =>
|
|
594
611
|
switch unwrapped.commandTopic.resources->Array.get(0) {
|
|
@@ -680,6 +697,7 @@ module MakeEventCollectorHelper = (
|
|
|
680
697
|
~componentName=ecName,
|
|
681
698
|
~context={
|
|
682
699
|
pluginDefinitionJson,
|
|
700
|
+
uiFragmentsJson,
|
|
683
701
|
extensionPoints: extensionPointEntries,
|
|
684
702
|
connectExtension,
|
|
685
703
|
extensions,
|
|
@@ -829,6 +847,11 @@ type dcbAppSyncResolverParams = {
|
|
|
829
847
|
runtime: Runtime.environment<unknown>,
|
|
830
848
|
fieldNames: array<string>,
|
|
831
849
|
tags: array<string>,
|
|
850
|
+
// True when the slice belongs to the platform admin build (Platform_Admin.construct). In split
|
|
851
|
+
// mode admin resolvers live on the Platform API, so the provider hook binds them to `hooks.adminApi`
|
|
852
|
+
// instead of `hooks.api` (which is the deploy-target/Domain API and is read in the same deferred
|
|
853
|
+
// callback by plugin builds). See platformHooks.adminApi.
|
|
854
|
+
onAdminApi: bool,
|
|
832
855
|
opts: Pulumi.ComponentResource.options,
|
|
833
856
|
}
|
|
834
857
|
|
|
@@ -952,6 +975,12 @@ type platformHooks = {
|
|
|
952
975
|
schedulerRoleUrn: ref<Pulumi.Output.t<string>>,
|
|
953
976
|
api: ref<option<hookedValue<unknown>>>,
|
|
954
977
|
apiRole: ref<option<hookedValue<unknown>>>,
|
|
978
|
+
// The API admin resolvers bind to (split mode: the Platform API; unified: same as `api`).
|
|
979
|
+
// Populated by makePlatform once the Platform API resource exists, and read — via the
|
|
980
|
+
// `onAdminApi` payload flag — by the DCB resolver hook so admin DCB mutations land on the
|
|
981
|
+
// Platform API even though `api` (read in the same deferred callback by plugin builds) points at
|
|
982
|
+
// the Domain/deploy-target API. `None` on platforms with no separate admin API (in-memory).
|
|
983
|
+
adminApi: ref<option<hookedValue<unknown>>>,
|
|
955
984
|
// Current deploy target, set by deployPlugin before plugin.make() is called.
|
|
956
985
|
// "Domain" (default) → resolvers/schema go to the DomainApi.
|
|
957
986
|
// "Platform" → resolvers/schema go to the PlatformApi.
|
|
@@ -967,6 +996,7 @@ let noHooks: platformHooks = {
|
|
|
967
996
|
schedulerRoleUrn: ref(Pulumi.Output.make("")),
|
|
968
997
|
api: ref(None),
|
|
969
998
|
apiRole: ref(None),
|
|
999
|
+
adminApi: ref(None),
|
|
970
1000
|
deployTarget: ref("Domain"),
|
|
971
1001
|
}
|
|
972
1002
|
|
|
@@ -11,6 +11,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
11
11
|
import * as Pulumi from "@pulumi/pulumi";
|
|
12
12
|
import * as Belt_SetString from "@rescript/runtime/lib/es6/Belt_SetString.js";
|
|
13
13
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
14
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
14
15
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
15
16
|
import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
|
|
16
17
|
import * as Task$ReventlessCore from "../../components/Task/Task.res.mjs";
|
|
@@ -222,10 +223,11 @@ function extractExtensionDefinitions(extensionsOutputs) {
|
|
|
222
223
|
}));
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
function createConnectPluginExtension(pluginDefinition, publishToPluginExtensionPoint, publishToAggregates, readModelNamesForSourceName, publishToReadModels, queryEngine, opts) {
|
|
226
|
+
function createConnectPluginExtension(pluginDefinition, uiFragments, publishToPluginExtensionPoint, publishToAggregates, readModelNamesForSourceName, publishToReadModels, queryEngine, opts) {
|
|
226
227
|
return Output$Pulumi.unzip(pluginDefinition.apply(pluginDefinition => {
|
|
227
228
|
let ConnectPluginExtension = PluginConnectExtension_Builder$ReventlessCore.Make({
|
|
228
|
-
pluginDefinition: pluginDefinition
|
|
229
|
+
pluginDefinition: pluginDefinition,
|
|
230
|
+
uiFragments: uiFragments
|
|
229
231
|
});
|
|
230
232
|
let connectPluginExtension = ConnectPluginExtension.make(publishToPluginExtensionPoint, publishToAggregates, readModelNamesForSourceName, publishToReadModels, queryEngine, opts);
|
|
231
233
|
let connectPluginExtensionOutputs = Component$ReventlessCore.outputs(connectPluginExtension);
|
|
@@ -264,7 +266,8 @@ function MakeEventCollectorHelper(RuntimeEnvironment) {
|
|
|
264
266
|
eventCollectorUrn
|
|
265
267
|
];
|
|
266
268
|
};
|
|
267
|
-
let connect = (eventCollector, eventTopics, extensionPointsOutputs, extensionsOutputs, pluginExtensionPointUnwrapped, pluginDefinition, connectPluginExtensionIncomingEventHandler, extensionsHandlers, extensionPointsHandlers, connectPluginExtensionOutputs, extensionRegistryInfosOpt, extensionPointRegistryInfosOpt, aggregateQueueUrlsOpt, readModelQueueUrlsOpt, readModelNamesForSourceNameOpt) => {
|
|
269
|
+
let connect = (eventCollector, eventTopics, extensionPointsOutputs, extensionsOutputs, pluginExtensionPointUnwrapped, pluginDefinition, uiFragmentsOpt, connectPluginExtensionIncomingEventHandler, extensionsHandlers, extensionPointsHandlers, connectPluginExtensionOutputs, extensionRegistryInfosOpt, extensionPointRegistryInfosOpt, aggregateQueueUrlsOpt, readModelQueueUrlsOpt, readModelNamesForSourceNameOpt) => {
|
|
270
|
+
let uiFragments = uiFragmentsOpt !== undefined ? Primitive_option.valFromOption(uiFragmentsOpt) : undefined;
|
|
268
271
|
let extensionRegistryInfos = extensionRegistryInfosOpt !== undefined ? extensionRegistryInfosOpt : [];
|
|
269
272
|
let extensionPointRegistryInfos = extensionPointRegistryInfosOpt !== undefined ? extensionPointRegistryInfosOpt : [];
|
|
270
273
|
let aggregateQueueUrls = aggregateQueueUrlsOpt !== undefined ? aggregateQueueUrlsOpt : ({});
|
|
@@ -314,6 +317,7 @@ function MakeEventCollectorHelper(RuntimeEnvironment) {
|
|
|
314
317
|
let ecResource = Component$ReventlessCore.toPulumiResource(eventCollector);
|
|
315
318
|
let ecName = ComponentType$ReventlessCore.nameOpt(ecResource.__name, EventCollector$ReventlessCore.componentType);
|
|
316
319
|
let pluginDefinitionJson = Pulumi.output(JSON.stringify(S.reverseConvertToJsonOrThrow(pluginDefinition, Plugin$Reventless.pluginDefinitionSchema)));
|
|
320
|
+
let uiFragmentsJson = Pulumi.output(JSON.stringify(S.reverseConvertToJsonOrThrow(uiFragments, Plugin$Reventless.uiFragmentManifestOptionSchema)));
|
|
317
321
|
let pluginExtensionPointCmdTopicUrl;
|
|
318
322
|
if (pluginExtensionPointUnwrapped !== undefined) {
|
|
319
323
|
let r = pluginExtensionPointUnwrapped.commandTopic.resources[0];
|
|
@@ -370,6 +374,7 @@ function MakeEventCollectorHelper(RuntimeEnvironment) {
|
|
|
370
374
|
}) : [];
|
|
371
375
|
registerEventCollectorContext(ecName, {
|
|
372
376
|
pluginDefinitionJson: pluginDefinitionJson,
|
|
377
|
+
uiFragmentsJson: uiFragmentsJson,
|
|
373
378
|
extensionPoints: extensionPointEntries,
|
|
374
379
|
connectExtension: connectExtension,
|
|
375
380
|
extensions: extensions,
|
|
@@ -468,6 +473,10 @@ let noHooks_apiRole = {
|
|
|
468
473
|
contents: undefined
|
|
469
474
|
};
|
|
470
475
|
|
|
476
|
+
let noHooks_adminApi = {
|
|
477
|
+
contents: undefined
|
|
478
|
+
};
|
|
479
|
+
|
|
471
480
|
let noHooks_deployTarget = {
|
|
472
481
|
contents: "Domain"
|
|
473
482
|
};
|
|
@@ -478,6 +487,7 @@ let noHooks = {
|
|
|
478
487
|
schedulerRoleUrn: noHooks_schedulerRoleUrn,
|
|
479
488
|
api: noHooks_api,
|
|
480
489
|
apiRole: noHooks_apiRole,
|
|
490
|
+
adminApi: noHooks_adminApi,
|
|
481
491
|
deployTarget: noHooks_deployTarget
|
|
482
492
|
};
|
|
483
493
|
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
open ReventlessInfra.Api
|
|
7
7
|
|
|
8
8
|
// ── Source C: mutation-triggered subscriptions ────────────────────────────────
|
|
9
|
-
// One field per command variant. Fires when the mutation is
|
|
10
|
-
//
|
|
9
|
+
// One field per command variant. Fires when the mutation is accepted.
|
|
10
|
+
// The SDL emitted here is provider-neutral; the subscription→mutation link is
|
|
11
|
+
// carried as structured `subscriptionSource` metadata on the fragment. Each
|
|
12
|
+
// provider adds its own wiring (AppSync appends `@aws_subscribe` at push time;
|
|
13
|
+
// the local platform routes its PubSub bridge from the same metadata).
|
|
11
14
|
//
|
|
12
15
|
// Generated from the same mutation entries as the query/mutation SDL so that
|
|
13
16
|
// field names and argument types are always in sync.
|
|
@@ -23,8 +26,13 @@ open ReventlessInfra.Api
|
|
|
23
26
|
// return type, so the subscription field has to declare CommandResult as well.
|
|
24
27
|
let sourceCFields = (
|
|
25
28
|
~mutationEntries: array<mutationSchemaEntry>,
|
|
26
|
-
): array<string> => {
|
|
29
|
+
): (array<string>, array<GraphQL_Stitcher.subscriptionSource>) => {
|
|
27
30
|
let fields: array<string> = []
|
|
31
|
+
let sources: array<GraphQL_Stitcher.subscriptionSource> = []
|
|
32
|
+
let pushField = (fieldName: string) => {
|
|
33
|
+
fields->Array.push(` on${fieldName}(id: ID): CommandResult`)
|
|
34
|
+
sources->Array.push({GraphQL_Stitcher.field: `on${fieldName}`, mutations: [fieldName]})
|
|
35
|
+
}
|
|
28
36
|
mutationEntries->Array.forEach(entry => {
|
|
29
37
|
let schema = entry.commandSchema
|
|
30
38
|
switch schema {
|
|
@@ -32,20 +40,18 @@ let sourceCFields = (
|
|
|
32
40
|
anyOf->Array.forEachWithIndex((_, i) => {
|
|
33
41
|
let fieldName = entry.fieldNames->Array.get(i)->Option.getOr("")
|
|
34
42
|
if fieldName->String.length > 0 {
|
|
35
|
-
|
|
36
|
-
fields->Array.push(sub)
|
|
43
|
+
pushField(fieldName)
|
|
37
44
|
}
|
|
38
45
|
})
|
|
39
46
|
| Object(_) =>
|
|
40
47
|
let fieldName = entry.fieldNames->Array.get(0)->Option.getOr("")
|
|
41
48
|
if fieldName->String.length > 0 {
|
|
42
|
-
|
|
43
|
-
fields->Array.push(sub)
|
|
49
|
+
pushField(fieldName)
|
|
44
50
|
}
|
|
45
51
|
| _ => ()
|
|
46
52
|
}
|
|
47
53
|
})
|
|
48
|
-
fields
|
|
54
|
+
(fields, sources)
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
// ── Source B: state-change subscriptions ─────────────────────────────────────
|
|
@@ -87,16 +93,20 @@ let sourceAFieldsAndTypes = (
|
|
|
87
93
|
type result = {
|
|
88
94
|
subscriptionFields: array<string>,
|
|
89
95
|
extraTypes: array<string>,
|
|
96
|
+
subscriptionSources: array<GraphQL_Stitcher.subscriptionSource>,
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
let generate = (
|
|
93
100
|
~mutationEntries: array<mutationSchemaEntry>,
|
|
94
101
|
~eventLogEntries: array<eventLogSchemaEntry>,
|
|
95
102
|
): result => {
|
|
96
|
-
let cFields = sourceCFields(~mutationEntries)
|
|
103
|
+
let (cFields, cSources) = sourceCFields(~mutationEntries)
|
|
97
104
|
let (aFields, aTypes) = sourceAFieldsAndTypes(~eventLogEntries)
|
|
105
|
+
// Source A fields carry no source mapping — they are pushed via the
|
|
106
|
+
// provider's events channel, not triggered by a mutation.
|
|
98
107
|
{
|
|
99
108
|
subscriptionFields: Array.flat([cFields, aFields]),
|
|
100
109
|
extraTypes: aTypes,
|
|
110
|
+
subscriptionSources: cSources,
|
|
101
111
|
}
|
|
102
112
|
}
|
|
@@ -4,32 +4,40 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
4
4
|
|
|
5
5
|
function sourceCFields(mutationEntries) {
|
|
6
6
|
let fields = [];
|
|
7
|
+
let sources = [];
|
|
8
|
+
let pushField = fieldName => {
|
|
9
|
+
fields.push(` on` + fieldName + `(id: ID): CommandResult`);
|
|
10
|
+
sources.push({
|
|
11
|
+
field: `on` + fieldName,
|
|
12
|
+
mutations: [fieldName]
|
|
13
|
+
});
|
|
14
|
+
};
|
|
7
15
|
mutationEntries.forEach(entry => {
|
|
8
16
|
let schema = entry.commandSchema;
|
|
9
17
|
switch (schema.type) {
|
|
10
18
|
case "object" :
|
|
11
19
|
let fieldName = Stdlib_Option.getOr(entry.fieldNames[0], "");
|
|
12
|
-
if (fieldName.length
|
|
20
|
+
if (fieldName.length > 0) {
|
|
21
|
+
return pushField(fieldName);
|
|
22
|
+
} else {
|
|
13
23
|
return;
|
|
14
24
|
}
|
|
15
|
-
let sub = ` on` + fieldName + `(id: ID): CommandResult\n @aws_subscribe(mutations: ["` + fieldName + `"])`;
|
|
16
|
-
fields.push(sub);
|
|
17
|
-
return;
|
|
18
25
|
case "union" :
|
|
19
26
|
schema.anyOf.forEach((param, i) => {
|
|
20
27
|
let fieldName = Stdlib_Option.getOr(entry.fieldNames[i], "");
|
|
21
|
-
if (fieldName.length
|
|
22
|
-
return;
|
|
28
|
+
if (fieldName.length > 0) {
|
|
29
|
+
return pushField(fieldName);
|
|
23
30
|
}
|
|
24
|
-
let sub = ` on` + fieldName + `(id: ID): CommandResult\n @aws_subscribe(mutations: ["` + fieldName + `"])`;
|
|
25
|
-
fields.push(sub);
|
|
26
31
|
});
|
|
27
32
|
return;
|
|
28
33
|
default:
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
});
|
|
32
|
-
return
|
|
37
|
+
return [
|
|
38
|
+
fields,
|
|
39
|
+
sources
|
|
40
|
+
];
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
function sourceAFieldsAndTypes(eventLogEntries) {
|
|
@@ -52,14 +60,15 @@ function sourceAFieldsAndTypes(eventLogEntries) {
|
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
function generate(mutationEntries, eventLogEntries) {
|
|
55
|
-
let
|
|
56
|
-
let match = sourceAFieldsAndTypes(eventLogEntries);
|
|
63
|
+
let match = sourceCFields(mutationEntries);
|
|
64
|
+
let match$1 = sourceAFieldsAndTypes(eventLogEntries);
|
|
57
65
|
return {
|
|
58
66
|
subscriptionFields: [
|
|
59
|
-
|
|
60
|
-
match[0]
|
|
67
|
+
match[0],
|
|
68
|
+
match$1[0]
|
|
61
69
|
].flat(),
|
|
62
|
-
extraTypes: match[1]
|
|
70
|
+
extraTypes: match$1[1],
|
|
71
|
+
subscriptionSources: match[1]
|
|
63
72
|
};
|
|
64
73
|
}
|
|
65
74
|
|
|
@@ -20,6 +20,10 @@ module ExtensionMapping = ReventlessInfra.ExtensionMapping
|
|
|
20
20
|
|
|
21
21
|
module type Spec = {
|
|
22
22
|
let pluginDefinition: Reventless.Plugin.pluginDefinition
|
|
23
|
+
// The plugin's UI-fragment manifest (no longer carried on pluginDefinition —
|
|
24
|
+
// the UiFragmentRegistry slice owns fragment state; the definition keeps
|
|
25
|
+
// lifecycle only). None for pure backend plugins.
|
|
26
|
+
let uiFragments: option<Reventless.Plugin.uiFragmentManifest>
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
module Make = (Spec: Spec) => {
|
|
@@ -46,12 +50,30 @@ module Make = (Spec: Spec) => {
|
|
|
46
50
|
let id = pluginDefinition.id
|
|
47
51
|
|
|
48
52
|
switch event {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
// Answer the handshake, and — when this plugin ships a UI-fragment manifest — register
|
|
54
|
+
// it with the admin UiFragmentRegistry slice in the same step (the admin EP's
|
|
55
|
+
// UI-fragment mapping routes RegisterUiFragment to the slice). Nested switch (not
|
|
56
|
+
// Array.concat) so the outer branch's expected type disambiguates the bare
|
|
57
|
+
// PublishExtensionPointCommand constructor.
|
|
58
|
+
| PluginExtensionPointSpec.UnknownPluginDetected if pluginId == id =>
|
|
59
|
+
switch Spec.uiFragments {
|
|
60
|
+
| Some(manifest) => [
|
|
61
|
+
PublishExtensionPointCommand(
|
|
62
|
+
id,
|
|
63
|
+
PluginExtensionPointSpec.ConnectPlugin(pluginDefinition),
|
|
64
|
+
),
|
|
65
|
+
PublishExtensionPointCommand(
|
|
66
|
+
id,
|
|
67
|
+
PluginExtensionPointSpec.RegisterUiFragment(manifest),
|
|
68
|
+
),
|
|
69
|
+
]
|
|
70
|
+
| None => [
|
|
71
|
+
PublishExtensionPointCommand(
|
|
72
|
+
id,
|
|
73
|
+
PluginExtensionPointSpec.ConnectPlugin(pluginDefinition),
|
|
74
|
+
),
|
|
75
|
+
]
|
|
76
|
+
}
|
|
55
77
|
// PluginConnected / PluginReconnected / PluginDeactivated for peer
|
|
56
78
|
// plugins used to call DoConnectPlugin / DoDisconnectPlugin here so
|
|
57
79
|
// each plugin's EC Lambda could subscribe / unsubscribe its own
|