@reventlessdev/reventless-core 3.0.0-alpha.301 → 3.0.0-alpha.302
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 +18 -0
- package/package.json +6 -6
- package/src/adapter/Runtime/AggregateRuntime_Builder.res +2 -2
- package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +10 -5
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +2 -2
- package/src/adapter/Runtime/EventCollectorRuntime_Builder.res +1 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +8 -3
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder.res +1 -1
- package/src/adapter/Runtime/PluginRuntime_Builder.res +3 -3
- package/src/adapter/Runtime/Runtime.res +10 -9
- package/src/adapter/Runtime/TaskRuntime_Builder.res +1 -1
- package/src/admin/Platform_Admin_Structure.res +3 -3
- package/src/admin/Platform_Admin_Structure.res.mjs +1 -1
- package/src/admin/Platform_BakedManifest.res +7 -7
- package/src/admin/Platform_BakedManifest.res.mjs +2 -2
- package/src/admin/Platform_ComponentDefinitionsApi.res +12 -12
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +11 -11
- package/src/admin/Platform_PluginStructuresApi.res +6 -6
- package/src/admin/Platform_PluginStructuresApi.res.mjs +4 -4
- package/src/admin/UiFragmentRegistry/StateView/UiFragments.res.mjs +1 -4
- package/src/components/Api/SuryToJsonSchema.res +1 -1
- package/src/components/CommandGenerator/CommandGenerator.res +1 -1
- package/src/components/CommandGenerator/CommandGenerator_Adapter.res +6 -1
- package/src/components/CommandTopic/CommandTopic.res +2 -2
- package/src/components/CommandTopic/CommandTopic_Adapter.res +1 -1
- package/src/components/EventCollector/EventCollector.res +1 -1
- package/src/components/EventCollector/EventCollector_Adapter.res +1 -1
- package/src/components/Heartbeat/Heartbeat.res +1 -1
- package/src/components/ReadModel/ReadModel.res +1 -1
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +2 -2
- package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +1 -1
- package/src/components/StateViewSlice/StateViewSlice_Callback.res +2 -2
- package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +1 -1
- package/src/components/Task/Task_Adapter.res +1 -1
- package/src/components/Task/Task_Builder.res +1 -1
- package/src/plugin/component/Plugin_Builder.res +7 -7
- package/src/plugin/component/Plugin_Builder.res.mjs +3 -3
- package/src/plugin/component/Plugin_BuiltHook.res +1 -1
- package/src/plugin/component/Plugin_Structure.res +18 -18
- package/src/plugin/component/Plugin_Structure.res.mjs +8 -8
- package/tests/admin/AdminApiSchemaDriftTest.res +8 -8
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +54 -54
- package/tests/admin/Platform_Admin_StructureTest.res +10 -10
- package/tests/admin/Platform_Admin_StructureTest.res.mjs +5 -5
- package/tests/admin/Platform_BakedManifestTest.res +7 -7
- package/tests/admin/Platform_BakedManifestTest.res.mjs +9 -9
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +11 -11
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +5 -5
- package/tests/admin/Platform_PluginStructuresApiTest.res +3 -3
- package/tests/message/MessageTest.res +1 -1
- package/tests/plugin/ManifestVisibilityTest.res +2 -2
- package/tests/plugin/PluginStructureAccessTest.res.mjs +2 -2
- package/tests/plugin/PluginStructureTest.res +9 -9
- package/tests/plugin/PluginStructureTest.res.mjs +7 -7
- package/tests/plugin/StateView/PsAnnotatedView.res +1 -1
- package/tests/plugin/StateView/PsAnnotatedView.res.mjs +1 -4
- package/tests/plugin/StateView/PsAvailableProductsView.res.mjs +1 -4
- package/tests/plugin/StateView/PsCategoriesView.res.mjs +1 -4
- package/tests/plugin/StateView/PsCustomersView.res.mjs +1 -4
- package/tests/plugin/StateView/PsGatedView.res.mjs +1 -4
- package/tests/plugin/StateView/PsOrdersView.res.mjs +1 -4
- package/tests/plugin/StateView/PsShipmentsView.res.mjs +1 -4
|
@@ -12,7 +12,7 @@ and channel<'callbackEvent, 'context, 'channelParts, 'runtimeParts> = {
|
|
|
12
12
|
publishJsonsStream: Pulumi.Output.t<ReventlessInfra.CommandTopic.publishJsonsStream>,
|
|
13
13
|
publishJsonsAndWait: Pulumi.Output.t<option<CommandTopic.publishJsonsAndWait>>,
|
|
14
14
|
handleChannelEvent: CommandTopic.jsonCommandsHandler => Pulumi.Output.t<
|
|
15
|
-
Runtime.
|
|
15
|
+
Runtime.effectInvocationHandler<'callbackEvent, 'context, unit, string>,
|
|
16
16
|
>,
|
|
17
17
|
connect: connect<'callbackEvent, 'context, 'channelParts, 'runtimeParts>,
|
|
18
18
|
}
|
|
@@ -24,7 +24,7 @@ module type T = {
|
|
|
24
24
|
let makeHandler: (
|
|
25
25
|
~eventCollector: component,
|
|
26
26
|
~jsonEventsHandler: jsonEventsHandler,
|
|
27
|
-
) => Pulumi.Output.t<Runtime.
|
|
27
|
+
) => Pulumi.Output.t<Runtime.effectInvocationHandler<callbackEvent, 'context, unit, string>>
|
|
28
28
|
|
|
29
29
|
let make: (
|
|
30
30
|
~name: string,
|
|
@@ -3,7 +3,7 @@ type channel<'callbackEvent, 'context, 'channelParts> = {
|
|
|
3
3
|
resources: array<ReventlessInfra.Adapter.resource>,
|
|
4
4
|
enqueueEvent: Pulumi.Output.t<EventCollector.enqueueEvent>,
|
|
5
5
|
handleChannelEvent: EventCollector.jsonEventsHandler => Pulumi.Output.t<
|
|
6
|
-
Runtime.
|
|
6
|
+
Runtime.effectInvocationHandler<'callbackEvent, 'context, unit, string>,
|
|
7
7
|
>,
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -19,7 +19,7 @@ module type T = {
|
|
|
19
19
|
~id: string,
|
|
20
20
|
~timeout: int,
|
|
21
21
|
~publishToPluginExtensionPoint: CommandTopic.publishJsons,
|
|
22
|
-
) => Pulumi.Output.t<Runtime.
|
|
22
|
+
) => Pulumi.Output.t<Runtime.invocationHandler<unit, 'context, unit>>
|
|
23
23
|
|
|
24
24
|
let make: (~name: string, ~opts: Pulumi.ComponentResource.options=?) => component
|
|
25
25
|
}
|
|
@@ -23,7 +23,7 @@ module type T = {
|
|
|
23
23
|
/** Bare event-variant names consumed across every projection mapping's source event
|
|
24
24
|
schema — names the actual events (so a DCB-log-sourced mapping is captured), unlike
|
|
25
25
|
`sourceNames` which only lists source aggregate / DCB-log names. Surfaced by
|
|
26
|
-
Plugin_Structure as `
|
|
26
|
+
Plugin_Structure as `readSideDef.consumedEventTypes`. */
|
|
27
27
|
let consumedEventNames: array<string>
|
|
28
28
|
let outputs: component => outputs
|
|
29
29
|
let operations: component => Pulumi.Output.t<operations>
|
|
@@ -109,7 +109,7 @@ function Make(RuntimeEnvironment) {
|
|
|
109
109
|
event: Primitive_option.valFromOption(event),
|
|
110
110
|
meta: meta,
|
|
111
111
|
recordedAt: recordedAt
|
|
112
|
-
}).map(__x => Projection$Reventless.mapActionId(__x, Spec.
|
|
112
|
+
}).map(__x => Projection$Reventless.mapActionId(__x, Spec.Id.toString, Spec.Id.makeFromString));
|
|
113
113
|
} catch (raw_exn) {
|
|
114
114
|
let exn$1 = Primitive_exceptions.internalToException(raw_exn);
|
|
115
115
|
let errMsg = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(exn$1), Stdlib_JsExn.message), "unknown");
|
|
@@ -44,8 +44,8 @@ module Make = (
|
|
|
44
44
|
Projection.project({event, meta: raw.meta, recordedAt: raw.recordedAt})->Array.map(
|
|
45
45
|
Reventless.Projection.mapActionId(
|
|
46
46
|
_,
|
|
47
|
-
~to_=Spec.
|
|
48
|
-
~from=Spec.
|
|
47
|
+
~to_=Spec.Id.toString,
|
|
48
|
+
~from=Spec.Id.makeFromString,
|
|
49
49
|
),
|
|
50
50
|
)
|
|
51
51
|
let actionsStr = LogFormat.actionNames(actions)
|
|
@@ -33,7 +33,7 @@ function Make(Spec) {
|
|
|
33
33
|
event: event,
|
|
34
34
|
meta: raw.meta,
|
|
35
35
|
recordedAt: raw.recordedAt
|
|
36
|
-
}).map(__x => Projection$Reventless.mapActionId(__x, Spec.
|
|
36
|
+
}).map(__x => Projection$Reventless.mapActionId(__x, Spec.Id.toString, Spec.Id.makeFromString));
|
|
37
37
|
let actionsStr = LogFormat$ReventlessCore.actionNames(actions);
|
|
38
38
|
Effect.runSync(EffectLogger$ReventlessCore.logInfo(comp, raw.data, `handling event ` + idx.contents.toString() + `/` + count + `: ` + LogFormat$ReventlessCore.bold(raw.eventType) + `(` + id + `) ` + actionsStr));
|
|
39
39
|
allActions.push(...actions.map(__x => Projection$ReventlessCore.rewriteAction(__x, raw.meta.time, Spec.stateSchema)));
|
|
@@ -24,7 +24,7 @@ module type Bucket = {
|
|
|
24
24
|
type bucketParts
|
|
25
25
|
|
|
26
26
|
let connect: connect<bucketParts, runtimeParts>
|
|
27
|
-
let makeHandler: Task.bucketCallback => Runtime.
|
|
27
|
+
let makeHandler: Task.bucketCallback => Runtime.invocationHandler<
|
|
28
28
|
callbackEvent,
|
|
29
29
|
context,
|
|
30
30
|
array<Task.taskAction>,
|
|
@@ -97,7 +97,7 @@ module Make = (
|
|
|
97
97
|
): Task.T => {
|
|
98
98
|
module Spec = Spec
|
|
99
99
|
type component = Task.component
|
|
100
|
-
// type handler = Runtime.
|
|
100
|
+
// type handler = Runtime.invocationHandler<
|
|
101
101
|
// TaskRuntimeBuilder.callbackEvent,
|
|
102
102
|
// TaskRuntimeBuilder.context,
|
|
103
103
|
// array<Task.taskAction>,
|
|
@@ -1050,31 +1050,31 @@ module Make = (
|
|
|
1050
1050
|
~aggregatePositions: array<string>=[],
|
|
1051
1051
|
): Reventless.Plugin.uiFragmentManifest => {
|
|
1052
1052
|
// Internal queryable components are hidden from the AutoUI manifest. They
|
|
1053
|
-
// remain fully wired (resolvers, GraphQL schema,
|
|
1053
|
+
// remain fully wired (resolvers, GraphQL schema, read-side defs,
|
|
1054
1054
|
// authorization) — visibility is a UX hint, not a security boundary. See
|
|
1055
1055
|
// docs/plans/done/component-visibility-annotations.md
|
|
1056
|
-
let
|
|
1056
|
+
let isVisibleReadSide = (q: Reventless.Plugin.readSideDef) =>
|
|
1057
1057
|
switch q.visibility {
|
|
1058
1058
|
| Some("Internal") => false
|
|
1059
1059
|
| _ => true
|
|
1060
1060
|
}
|
|
1061
|
-
let visibleReadModels = pluginStructure.readModels->Array.filter(
|
|
1062
|
-
let visibleStateViewSlices = pluginStructure.stateViewSlices->Array.filter(
|
|
1063
|
-
let listPanel = (q: Reventless.Plugin.
|
|
1061
|
+
let visibleReadModels = pluginStructure.readModels->Array.filter(isVisibleReadSide)
|
|
1062
|
+
let visibleStateViewSlices = pluginStructure.stateViewSlices->Array.filter(isVisibleReadSide)
|
|
1063
|
+
let listPanel = (q: Reventless.Plugin.readSideDef): Reventless.Plugin.panelManifestEntry => {
|
|
1064
1064
|
fragmentId: name ++ "." ++ q.name ++ ".list",
|
|
1065
1065
|
title: q.name,
|
|
1066
1066
|
description: "",
|
|
1067
1067
|
positions: readModelPositions,
|
|
1068
1068
|
requiredAccess: None,
|
|
1069
1069
|
}
|
|
1070
|
-
let detailPanel = (w: Reventless.Plugin.
|
|
1070
|
+
let detailPanel = (w: Reventless.Plugin.writeSideDef): Reventless.Plugin.panelManifestEntry => {
|
|
1071
1071
|
fragmentId: name ++ "." ++ w.name ++ ".detail",
|
|
1072
1072
|
title: w.name,
|
|
1073
1073
|
description: "",
|
|
1074
1074
|
positions: aggregatePositions,
|
|
1075
1075
|
requiredAccess: None,
|
|
1076
1076
|
}
|
|
1077
|
-
let listPage = (q: Reventless.Plugin.
|
|
1077
|
+
let listPage = (q: Reventless.Plugin.readSideDef): Reventless.Plugin.pageManifestEntry => {
|
|
1078
1078
|
fragmentId: name ++ "." ++ q.name ++ ".list",
|
|
1079
1079
|
title: q.name,
|
|
1080
1080
|
menuEntry: {label: q.name, icon: None, group: None, sortOrder: 0},
|
|
@@ -47,7 +47,7 @@ function Make(Spec) {
|
|
|
47
47
|
let makeAutoUIManifest = (remoteEntryUrl, name, pluginStructure, readModelPositionsOpt, aggregatePositionsOpt) => {
|
|
48
48
|
let readModelPositions = readModelPositionsOpt !== undefined ? readModelPositionsOpt : [];
|
|
49
49
|
let aggregatePositions = aggregatePositionsOpt !== undefined ? aggregatePositionsOpt : [];
|
|
50
|
-
let
|
|
50
|
+
let isVisibleReadSide = q => {
|
|
51
51
|
let match = q.visibility;
|
|
52
52
|
if (match !== undefined) {
|
|
53
53
|
return match !== "Internal";
|
|
@@ -55,8 +55,8 @@ function Make(Spec) {
|
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
|
-
let visibleReadModels = pluginStructure.readModels.filter(
|
|
59
|
-
let visibleStateViewSlices = pluginStructure.stateViewSlices.filter(
|
|
58
|
+
let visibleReadModels = pluginStructure.readModels.filter(isVisibleReadSide);
|
|
59
|
+
let visibleStateViewSlices = pluginStructure.stateViewSlices.filter(isVisibleReadSide);
|
|
60
60
|
let listPanel = q => ({
|
|
61
61
|
fragmentId: name + "." + q.name + ".list",
|
|
62
62
|
title: q.name,
|
|
@@ -97,7 +97,7 @@ type pluginDeployedSchema = {
|
|
|
97
97
|
/** Intra-plugin grouping band (the "chapter") this component belongs to, mirrored
|
|
98
98
|
from the static `pluginStructure` for parity on the hook surface. Absent when the
|
|
99
99
|
component carries no chapter (lives directly under a kind-folder). See
|
|
100
|
-
`Reventless.Plugin.
|
|
100
|
+
`Reventless.Plugin.readSideDef.chapter`. */
|
|
101
101
|
chapter?: string,
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -392,13 +392,13 @@ let extensionPartitionFailure = (
|
|
|
392
392
|
// forces a spec to pick its linked view's enum.
|
|
393
393
|
let checkDeclaredTransitions = (
|
|
394
394
|
~pluginName: string,
|
|
395
|
-
~
|
|
395
|
+
~writeSides: array<Reventless.Plugin.writeSideDef>,
|
|
396
396
|
~lifecycleStatesByView: dict<array<string>>,
|
|
397
397
|
): unit => {
|
|
398
398
|
let unvalidated = ref(0)
|
|
399
399
|
let failures = []
|
|
400
400
|
|
|
401
|
-
|
|
401
|
+
writeSides->Array.forEach(w =>
|
|
402
402
|
w.commands->Array.forEach(cmd => {
|
|
403
403
|
let declared = Array.concat(
|
|
404
404
|
cmd.allowedStates->Option.getOr([]),
|
|
@@ -469,7 +469,7 @@ let checkDeclaredTransitions = (
|
|
|
469
469
|
// and one that stops a deploy gets silenced rather than fixed. Pure, so the rule
|
|
470
470
|
// tests without a log; `checkLifecycleTopology` reports.
|
|
471
471
|
let lifecycleTopologyFindings = (
|
|
472
|
-
~
|
|
472
|
+
~writeSides: array<Reventless.Plugin.writeSideDef>,
|
|
473
473
|
~lifecycleStatesByView: dict<array<string>>,
|
|
474
474
|
): array<(string, string)> => {
|
|
475
475
|
let findings = []
|
|
@@ -479,7 +479,7 @@ let lifecycleTopologyFindings = (
|
|
|
479
479
|
// Arrival only, so a creating command (a target and no from-set) counts
|
|
480
480
|
// towards reachability like any other edge.
|
|
481
481
|
let reachable =
|
|
482
|
-
|
|
482
|
+
writeSides->Array.reduce([], (acc, w) =>
|
|
483
483
|
w.linkedViews->Array.includes(view)
|
|
484
484
|
? Array.concat(acc, w.commands->Array.filterMap(cmd => cmd.targetState))
|
|
485
485
|
: acc
|
|
@@ -508,10 +508,10 @@ let lifecycleTopologyFindings = (
|
|
|
508
508
|
|
|
509
509
|
let checkLifecycleTopology = (
|
|
510
510
|
~pluginName: string,
|
|
511
|
-
~
|
|
511
|
+
~writeSides: array<Reventless.Plugin.writeSideDef>,
|
|
512
512
|
~lifecycleStatesByView: dict<array<string>>,
|
|
513
513
|
): unit =>
|
|
514
|
-
lifecycleTopologyFindings(~
|
|
514
|
+
lifecycleTopologyFindings(~writeSides, ~lifecycleStatesByView)->Array.forEach(((view, message)) =>
|
|
515
515
|
log.warn(~comp="Plugin_Structure", `${pluginName}/${view}: ${message}`)
|
|
516
516
|
)
|
|
517
517
|
|
|
@@ -1074,12 +1074,12 @@ let visibilityTag = (v: Reventless.Visibility.t): option<string> =>
|
|
|
1074
1074
|
}
|
|
1075
1075
|
|
|
1076
1076
|
/**
|
|
1077
|
-
A read model's `
|
|
1077
|
+
A read model's `readSideDef` assembled from its spec, for the platform's own
|
|
1078
1078
|
components: `make` takes `module(ReadModel.T)` values, and at structure-assembly
|
|
1079
1079
|
time the platform has no built module to hand itself. Every extractor here is the
|
|
1080
1080
|
one `make` calls, so the two cannot drift — a hand-written record did, four times.
|
|
1081
1081
|
*/
|
|
1082
|
-
let
|
|
1082
|
+
let readSideDefFromSpec = (
|
|
1083
1083
|
~plugin: string,
|
|
1084
1084
|
~name: string,
|
|
1085
1085
|
~stateSchema: S.t<unknown>,
|
|
@@ -1088,7 +1088,7 @@ let queryableDefFromSpec = (
|
|
|
1088
1088
|
~consumedEventTypes: array<string>=[],
|
|
1089
1089
|
~linkedWriteSide: array<string>=[],
|
|
1090
1090
|
~chapter: option<string>=?,
|
|
1091
|
-
): Reventless.Plugin.
|
|
1091
|
+
): Reventless.Plugin.readSideDef => {
|
|
1092
1092
|
let qf = Api_Naming.queryFieldNamesForReadModel(~plugin, ~name)
|
|
1093
1093
|
let label = labelFieldsFromStateSchema(~entityName=name, stateSchema)
|
|
1094
1094
|
// The published key is always filterable; not every filterable field is the key.
|
|
@@ -1498,9 +1498,9 @@ let make = (
|
|
|
1498
1498
|
)
|
|
1499
1499
|
)
|
|
1500
1500
|
|
|
1501
|
-
// ── Build
|
|
1501
|
+
// ── Build read-side defs ───────────────────────────────────────────────────
|
|
1502
1502
|
//
|
|
1503
|
-
// Internal views are carried here, tagged via `
|
|
1503
|
+
// Internal views are carried here, tagged via `readSideDef.visibility`, so
|
|
1504
1504
|
// developer tools see them; AutoUI's consumers re-filter on the tag.
|
|
1505
1505
|
// View name -> the states its lifecycle field can hold, collected as the view
|
|
1506
1506
|
// defs are built so the transition check below has both sides in one place.
|
|
@@ -1576,7 +1576,7 @@ let make = (
|
|
|
1576
1576
|
idFieldSource: keyField->Option.map(((_, rung)) => rung),
|
|
1577
1577
|
requiredAccess: accessKeysFor(R.Spec.authorization->Reventless.Authorization.named),
|
|
1578
1578
|
requiredRoles: ?rolesFor(R.Spec.authorization->Reventless.Authorization.named),
|
|
1579
|
-
}: Reventless.Plugin.
|
|
1579
|
+
}: Reventless.Plugin.readSideDef
|
|
1580
1580
|
)
|
|
1581
1581
|
})
|
|
1582
1582
|
|
|
@@ -1617,11 +1617,11 @@ let make = (
|
|
|
1617
1617
|
idFieldSource: keyField->Option.map(((_, rung)) => rung),
|
|
1618
1618
|
requiredAccess: accessKeysFor(SVS.Spec.authorization->Reventless.Authorization.named),
|
|
1619
1619
|
requiredRoles: ?rolesFor(SVS.Spec.authorization->Reventless.Authorization.named),
|
|
1620
|
-
}: Reventless.Plugin.
|
|
1620
|
+
}: Reventless.Plugin.readSideDef
|
|
1621
1621
|
)
|
|
1622
1622
|
})
|
|
1623
1623
|
|
|
1624
|
-
// ── Build
|
|
1624
|
+
// ── Build write-side defs ──────────────────────────────────────────────────
|
|
1625
1625
|
|
|
1626
1626
|
// Non-throwing: this is a description of the plugin, and the builder is what
|
|
1627
1627
|
// refuses a boundary whose partitions do not resolve.
|
|
@@ -1728,7 +1728,7 @@ let make = (
|
|
|
1728
1728
|
events: extractEventDefs(~identityViews, SCS.Spec.eventSchema->S.castToUnknown),
|
|
1729
1729
|
errors: extractErrorDefs(SCS.Spec.errorSchema->S.castToUnknown),
|
|
1730
1730
|
chapter: chapterOf(SCS.Spec.name),
|
|
1731
|
-
}: Reventless.Plugin.
|
|
1731
|
+
}: Reventless.Plugin.writeSideDef
|
|
1732
1732
|
)
|
|
1733
1733
|
})
|
|
1734
1734
|
|
|
@@ -1762,7 +1762,7 @@ let make = (
|
|
|
1762
1762
|
events: extractEventDefs(~identityViews, A.Spec.eventSchema->S.castToUnknown),
|
|
1763
1763
|
errors: extractErrorDefs(A.Spec.errorSchema->S.castToUnknown),
|
|
1764
1764
|
chapter: chapterOf(A.Spec.name),
|
|
1765
|
-
}: Reventless.Plugin.
|
|
1765
|
+
}: Reventless.Plugin.writeSideDef
|
|
1766
1766
|
)
|
|
1767
1767
|
})
|
|
1768
1768
|
|
|
@@ -2258,12 +2258,12 @@ let make = (
|
|
|
2258
2258
|
// assembled, so the check cannot run inline where the defs are made.
|
|
2259
2259
|
checkDeclaredTransitions(
|
|
2260
2260
|
~pluginName=name,
|
|
2261
|
-
~
|
|
2261
|
+
~writeSides=Array.concat(stateChangeDefs, aggregateDefs),
|
|
2262
2262
|
~lifecycleStatesByView,
|
|
2263
2263
|
)
|
|
2264
2264
|
checkLifecycleTopology(
|
|
2265
2265
|
~pluginName=name,
|
|
2266
|
-
~
|
|
2266
|
+
~writeSides=Array.concat(stateChangeDefs, aggregateDefs),
|
|
2267
2267
|
~lifecycleStatesByView,
|
|
2268
2268
|
)
|
|
2269
2269
|
// Also a second pass, for a different reason: the failures are gathered per
|
|
@@ -318,12 +318,12 @@ function extensionPartitionFailure(label, delegate, expected, actual) {
|
|
|
318
318
|
return label + `: the extension ` + seen + `, but the plugin partitions ` + delegate + ` by ` + describePartition(expected) + `. An extension sees only the slice's command and events, not what it reads or its chapter — ` + (`add @partitionTag ` + describePartition(expected) + ` to ` + delegate + `'s event.`);
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
function checkDeclaredTransitions(pluginName,
|
|
321
|
+
function checkDeclaredTransitions(pluginName, writeSides, lifecycleStatesByView) {
|
|
322
322
|
let unvalidated = {
|
|
323
323
|
contents: 0
|
|
324
324
|
};
|
|
325
325
|
let failures = [];
|
|
326
|
-
|
|
326
|
+
writeSides.forEach(w => {
|
|
327
327
|
w.commands.forEach(cmd => {
|
|
328
328
|
let t = cmd.targetState;
|
|
329
329
|
let declared = Stdlib_Option.getOr(cmd.allowedStates, []).concat(t !== undefined ? [t] : []);
|
|
@@ -357,12 +357,12 @@ function checkDeclaredTransitions(pluginName, writables, lifecycleStatesByView)
|
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
-
function lifecycleTopologyFindings(
|
|
360
|
+
function lifecycleTopologyFindings(writeSides, lifecycleStatesByView) {
|
|
361
361
|
let findings = [];
|
|
362
362
|
Object.entries(lifecycleStatesByView).forEach(param => {
|
|
363
363
|
let states = param[1];
|
|
364
364
|
let view = param[0];
|
|
365
|
-
let reachable = Stdlib_Array.reduce(
|
|
365
|
+
let reachable = Stdlib_Array.reduce(writeSides, [], (acc, w) => {
|
|
366
366
|
if (w.linkedViews.includes(view)) {
|
|
367
367
|
return acc.concat(Stdlib_Array.filterMap(w.commands, cmd => cmd.targetState));
|
|
368
368
|
} else {
|
|
@@ -386,8 +386,8 @@ function lifecycleTopologyFindings(writables, lifecycleStatesByView) {
|
|
|
386
386
|
return findings;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
function checkLifecycleTopology(pluginName,
|
|
390
|
-
lifecycleTopologyFindings(
|
|
389
|
+
function checkLifecycleTopology(pluginName, writeSides, lifecycleStatesByView) {
|
|
390
|
+
lifecycleTopologyFindings(writeSides, lifecycleStatesByView).forEach(param => log.warn("Plugin_Structure", undefined, pluginName + `/` + param[0] + `: ` + param[1]));
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
function labelFieldSourceToString(s) {
|
|
@@ -772,7 +772,7 @@ function visibilityTag(v) {
|
|
|
772
772
|
}
|
|
773
773
|
}
|
|
774
774
|
|
|
775
|
-
function
|
|
775
|
+
function readSideDefFromSpec(plugin, name, stateSchema, authorization, visibilityOpt, consumedEventTypesOpt, linkedWriteSideOpt, chapter) {
|
|
776
776
|
let visibility = visibilityOpt !== undefined ? visibilityOpt : "Public";
|
|
777
777
|
let consumedEventTypes = consumedEventTypesOpt !== undefined ? consumedEventTypesOpt : [];
|
|
778
778
|
let linkedWriteSide = linkedWriteSideOpt !== undefined ? linkedWriteSideOpt : [];
|
|
@@ -1591,7 +1591,7 @@ export {
|
|
|
1591
1591
|
toCommandDef,
|
|
1592
1592
|
extractCommandDefs,
|
|
1593
1593
|
visibilityTag,
|
|
1594
|
-
|
|
1594
|
+
readSideDefFromSpec,
|
|
1595
1595
|
make,
|
|
1596
1596
|
}
|
|
1597
1597
|
/* log Not a pure module */
|
|
@@ -80,7 +80,7 @@ let cmd: commandDef = {
|
|
|
80
80
|
let evt: eventDef = {name: "ProductAdded", schema: "{}", references: [fieldRef]}
|
|
81
81
|
let err: errorDef = {name: "ProductAlreadyExists", schema: "{}", references: []}
|
|
82
82
|
|
|
83
|
-
let
|
|
83
|
+
let writeSide: writeSideDef = {
|
|
84
84
|
name: "Product",
|
|
85
85
|
commands: [cmd],
|
|
86
86
|
producedEventTypes: ["ProductAdded"],
|
|
@@ -92,7 +92,7 @@ let writable: writableDef = {
|
|
|
92
92
|
chapter: Some("Catalogue"),
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
let
|
|
95
|
+
let readSide: readSideDef = {
|
|
96
96
|
name: "Products",
|
|
97
97
|
queryField: "Catalog_Products",
|
|
98
98
|
schema: "{}",
|
|
@@ -174,10 +174,10 @@ let capabilityDecl: requiredCapabilityDeclaration = {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
let structure: pluginStructure = {
|
|
177
|
-
readModels: [
|
|
177
|
+
readModels: [readSide],
|
|
178
178
|
stateViewSlices: [],
|
|
179
179
|
stateChangeSlices: [],
|
|
180
|
-
aggregates: [
|
|
180
|
+
aggregates: [writeSide],
|
|
181
181
|
automationSlices: [automation],
|
|
182
182
|
outboundTranslationSlices: [outbound],
|
|
183
183
|
inboundTranslationSlices: [inbound],
|
|
@@ -278,16 +278,16 @@ let guards: array<guard> = [
|
|
|
278
278
|
{
|
|
279
279
|
gqlType: "Platform_WriteSideDef",
|
|
280
280
|
sdlTypes: componentSdl,
|
|
281
|
-
recordFields: schemaKeys(
|
|
282
|
-
wireFields: jsonKeys(Platform_ComponentDefinitionsApi.
|
|
281
|
+
recordFields: schemaKeys(writeSideDefSchema),
|
|
282
|
+
wireFields: jsonKeys(Platform_ComponentDefinitionsApi.encodeWriteSideDef(writeSide)),
|
|
283
283
|
wireOnly: [],
|
|
284
284
|
recordOnly: [],
|
|
285
285
|
},
|
|
286
286
|
{
|
|
287
287
|
gqlType: "Platform_ReadSideDef",
|
|
288
288
|
sdlTypes: componentSdl,
|
|
289
|
-
recordFields: schemaKeys(
|
|
290
|
-
wireFields: jsonKeys(Platform_ComponentDefinitionsApi.
|
|
289
|
+
recordFields: schemaKeys(readSideDefSchema),
|
|
290
|
+
wireFields: jsonKeys(Platform_ComponentDefinitionsApi.encodeReadSideDef(readSide)),
|
|
291
291
|
wireOnly: [],
|
|
292
292
|
// The roles behind `requiredAccess`, read by the deploy check in-process.
|
|
293
293
|
// A client gates on the mapped groups and has no use for role names.
|
|
@@ -100,82 +100,82 @@ let err = {
|
|
|
100
100
|
references: err_references
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
let
|
|
103
|
+
let writeSide_commands = [cmd];
|
|
104
104
|
|
|
105
|
-
let
|
|
105
|
+
let writeSide_producedEventTypes = ["ProductAdded"];
|
|
106
106
|
|
|
107
|
-
let
|
|
107
|
+
let writeSide_consumedEventTypes = [];
|
|
108
108
|
|
|
109
|
-
let
|
|
109
|
+
let writeSide_linkedViews = ["Products"];
|
|
110
110
|
|
|
111
|
-
let
|
|
111
|
+
let writeSide_consistencyRead = "Products";
|
|
112
112
|
|
|
113
|
-
let
|
|
113
|
+
let writeSide_events = [evt];
|
|
114
114
|
|
|
115
|
-
let
|
|
115
|
+
let writeSide_errors = [err];
|
|
116
116
|
|
|
117
|
-
let
|
|
117
|
+
let writeSide_chapter = "Catalogue";
|
|
118
118
|
|
|
119
|
-
let
|
|
119
|
+
let writeSide = {
|
|
120
120
|
name: "Product",
|
|
121
|
-
commands:
|
|
122
|
-
producedEventTypes:
|
|
123
|
-
consumedEventTypes:
|
|
124
|
-
linkedViews:
|
|
125
|
-
consistencyRead:
|
|
126
|
-
events:
|
|
127
|
-
errors:
|
|
128
|
-
chapter:
|
|
121
|
+
commands: writeSide_commands,
|
|
122
|
+
producedEventTypes: writeSide_producedEventTypes,
|
|
123
|
+
consumedEventTypes: writeSide_consumedEventTypes,
|
|
124
|
+
linkedViews: writeSide_linkedViews,
|
|
125
|
+
consistencyRead: writeSide_consistencyRead,
|
|
126
|
+
events: writeSide_events,
|
|
127
|
+
errors: writeSide_errors,
|
|
128
|
+
chapter: writeSide_chapter
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
let
|
|
131
|
+
let readSide_consumedEventTypes = ["ProductAdded"];
|
|
132
132
|
|
|
133
|
-
let
|
|
133
|
+
let readSide_linkedWriteSide = ["Product"];
|
|
134
134
|
|
|
135
|
-
let
|
|
135
|
+
let readSide_searchableFields = ["displayName"];
|
|
136
136
|
|
|
137
|
-
let
|
|
137
|
+
let readSide_labelFieldSource = "annotation";
|
|
138
138
|
|
|
139
|
-
let
|
|
139
|
+
let readSide_lifecycleField = "lifecycle";
|
|
140
140
|
|
|
141
|
-
let
|
|
141
|
+
let readSide_ownerField = "ownerId";
|
|
142
142
|
|
|
143
|
-
let
|
|
143
|
+
let readSide_retiredField = "archived";
|
|
144
144
|
|
|
145
|
-
let
|
|
145
|
+
let readSide_retiredValues = ["Archived"];
|
|
146
146
|
|
|
147
|
-
let
|
|
147
|
+
let readSide_namedWhenRetired = true;
|
|
148
148
|
|
|
149
|
-
let
|
|
149
|
+
let readSide_chapter = "Catalogue";
|
|
150
150
|
|
|
151
|
-
let
|
|
151
|
+
let readSide_singleQueryField = "Catalog_Product";
|
|
152
152
|
|
|
153
|
-
let
|
|
153
|
+
let readSide_idField = "productId";
|
|
154
154
|
|
|
155
|
-
let
|
|
155
|
+
let readSide_idFieldSource = "convention";
|
|
156
156
|
|
|
157
|
-
let
|
|
157
|
+
let readSide_requiredAccess = ["catalog.read"];
|
|
158
158
|
|
|
159
|
-
let
|
|
159
|
+
let readSide = {
|
|
160
160
|
name: "Products",
|
|
161
161
|
queryField: "Catalog_Products",
|
|
162
162
|
schema: "{}",
|
|
163
|
-
consumedEventTypes:
|
|
164
|
-
linkedWriteSide:
|
|
163
|
+
consumedEventTypes: readSide_consumedEventTypes,
|
|
164
|
+
linkedWriteSide: readSide_linkedWriteSide,
|
|
165
165
|
labelField: "displayName",
|
|
166
|
-
searchableFields:
|
|
167
|
-
labelFieldSource:
|
|
168
|
-
lifecycleField:
|
|
169
|
-
ownerField:
|
|
170
|
-
retiredField:
|
|
171
|
-
retiredValues:
|
|
172
|
-
namedWhenRetired:
|
|
166
|
+
searchableFields: readSide_searchableFields,
|
|
167
|
+
labelFieldSource: readSide_labelFieldSource,
|
|
168
|
+
lifecycleField: readSide_lifecycleField,
|
|
169
|
+
ownerField: readSide_ownerField,
|
|
170
|
+
retiredField: readSide_retiredField,
|
|
171
|
+
retiredValues: readSide_retiredValues,
|
|
172
|
+
namedWhenRetired: readSide_namedWhenRetired,
|
|
173
173
|
visibility: undefined,
|
|
174
|
-
chapter:
|
|
175
|
-
singleQueryField:
|
|
176
|
-
idField:
|
|
177
|
-
idFieldSource:
|
|
178
|
-
requiredAccess:
|
|
174
|
+
chapter: readSide_chapter,
|
|
175
|
+
singleQueryField: readSide_singleQueryField,
|
|
176
|
+
idField: readSide_idField,
|
|
177
|
+
idFieldSource: readSide_idFieldSource,
|
|
178
|
+
requiredAccess: readSide_requiredAccess
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
let automation_consumedEventTypes = ["StockLow"];
|
|
@@ -293,13 +293,13 @@ let capabilityDecl = {
|
|
|
293
293
|
component: "GeocodeAddress"
|
|
294
294
|
};
|
|
295
295
|
|
|
296
|
-
let structure_readModels = [
|
|
296
|
+
let structure_readModels = [readSide];
|
|
297
297
|
|
|
298
298
|
let structure_stateViewSlices = [];
|
|
299
299
|
|
|
300
300
|
let structure_stateChangeSlices = [];
|
|
301
301
|
|
|
302
|
-
let structure_aggregates = [
|
|
302
|
+
let structure_aggregates = [writeSide];
|
|
303
303
|
|
|
304
304
|
let structure_automationSlices = [automation];
|
|
305
305
|
|
|
@@ -414,16 +414,16 @@ let guards = [
|
|
|
414
414
|
{
|
|
415
415
|
gqlType: "Platform_WriteSideDef",
|
|
416
416
|
sdlTypes: Platform_ComponentDefinitionsApi$ReventlessCore.sdlTypes,
|
|
417
|
-
recordFields: schemaKeys(Plugin$Reventless.
|
|
418
|
-
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.
|
|
417
|
+
recordFields: schemaKeys(Plugin$Reventless.writeSideDefSchema),
|
|
418
|
+
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.encodeWriteSideDef(writeSide)),
|
|
419
419
|
wireOnly: [],
|
|
420
420
|
recordOnly: []
|
|
421
421
|
},
|
|
422
422
|
{
|
|
423
423
|
gqlType: "Platform_ReadSideDef",
|
|
424
424
|
sdlTypes: Platform_ComponentDefinitionsApi$ReventlessCore.sdlTypes,
|
|
425
|
-
recordFields: schemaKeys(Plugin$Reventless.
|
|
426
|
-
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.
|
|
425
|
+
recordFields: schemaKeys(Plugin$Reventless.readSideDefSchema),
|
|
426
|
+
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.encodeReadSideDef(readSide)),
|
|
427
427
|
wireOnly: [],
|
|
428
428
|
recordOnly: ["requiredRoles"]
|
|
429
429
|
},
|
|
@@ -604,8 +604,8 @@ export {
|
|
|
604
604
|
cmd,
|
|
605
605
|
evt,
|
|
606
606
|
err,
|
|
607
|
-
|
|
608
|
-
|
|
607
|
+
writeSide,
|
|
608
|
+
readSide,
|
|
609
609
|
automation,
|
|
610
610
|
outbound,
|
|
611
611
|
inbound,
|