@reventlessdev/reventless-core 3.0.0-alpha.251 → 3.0.0-alpha.252
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/package.json +7 -7
- package/src/admin/Platform_Admin_Structure.res +4 -1
- package/src/admin/Platform_Admin_Structure.res.mjs +4 -2
- package/src/admin/Platform_BakedManifest.res.mjs +3 -1
- package/src/admin/Platform_PluginStructuresApi.res +43 -7
- package/src/admin/Platform_PluginStructuresApi.res.mjs +47 -1
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +8 -0
- package/src/components/Api/ApiNoApiHelpers.res +37 -3
- package/src/components/Api/ApiNoApiHelpers.res.mjs +29 -2
- package/src/components/AutomationSlice/AutomationSlice_Callback.res +4 -4
- package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +3 -3
- package/src/plugin/api/PluginBaseFragment.res +3 -3
- package/src/plugin/component/Plugin_Structure.res +175 -22
- package/src/plugin/component/Plugin_Structure.res.mjs +89 -17
- package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +3 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +3 -1
- package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +3 -1
- package/src/plugin/lifecycle/PluginBehavior.res +11 -11
- package/src/plugin/lifecycle/PluginBehavior.res.mjs +11 -11
- package/src/plugin/lifecycle/PluginSpec.res +11 -3
- package/src/plugin/lifecycle/PluginSpec.res.mjs +11 -3
- package/tests/admin/AdminApiSchemaDriftTest.res +27 -1
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +22 -2
- package/tests/admin/Platform_Admin_StructureTest.res +8 -3
- package/tests/admin/Platform_Admin_StructureTest.res.mjs +8 -2
- package/tests/admin/Platform_BakedManifestTest.res +2 -0
- package/tests/admin/Platform_BakedManifestTest.res.mjs +3 -1
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +4 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +21 -7
- package/tests/admin/Platform_PluginStructuresApiTest.res +16 -0
- package/tests/admin/Platform_PluginStructuresApiTest.res.mjs +17 -3
- package/tests/aggregate/AggregateCacheTest.res.mjs +15 -3
- package/tests/aggregate/AggregateConflictTest.res.mjs +15 -3
- package/tests/aggregate/AggregateFixtures.res.mjs +15 -3
- package/tests/aggregate/AggregateSnapshotTest.res.mjs +21 -5
- package/tests/api/ApiNoApiTest.res +46 -0
- package/tests/api/ApiNoApiTest.res.mjs +49 -1
- package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +27 -3
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +12 -2
- package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +2 -0
- package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +12 -2
- package/tests/dcb/DcbFixtures.res.mjs +8 -0
- package/tests/dcb/DcbStateChangeSliceTest.res.mjs +18 -0
- package/tests/eventmapper/EventMapperFixtures.res.mjs +15 -3
- package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +9 -1
- package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +9 -1
- package/tests/message/MessageTest.res +2 -0
- package/tests/message/MessageTest.res.mjs +3 -1
- package/tests/plugin/PluginStructureAccessTest.res.mjs +2 -0
- package/tests/plugin/PluginStructureTest.res +185 -1
- package/tests/plugin/PluginStructureTest.res.mjs +246 -3
- package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res +59 -0
- package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs +115 -0
- package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +8 -0
- package/tests/plugin/pluginDefinitionRequiredScalars.txt +18 -0
- package/tests/util/CommandPublisherTest.res.mjs +9 -1
|
@@ -373,12 +373,18 @@ let reportTranslationTables = (
|
|
|
373
373
|
}
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
-
//
|
|
377
|
-
// only ever sees
|
|
378
|
-
// legal in a state no row is in. Both sides are in hand
|
|
379
|
-
// views do not declare raises (this runs at assembly,
|
|
380
|
-
// a failed deploy); no resolvable view only warns.
|
|
381
|
-
// linked views: a slice feeding two is not
|
|
376
|
+
// A command's declared edge names states belonging to another component's enum.
|
|
377
|
+
// From `@transition` the PPX only ever sees names, so a misspelling compiles clean
|
|
378
|
+
// and produces a command legal in a state no row is in. Both sides are in hand
|
|
379
|
+
// here. A state the linked views do not declare raises (this runs at assembly,
|
|
380
|
+
// never in a Lambda, so that is a failed deploy); no resolvable view only warns.
|
|
381
|
+
// Checked against the UNION of the linked views: a slice feeding two is not
|
|
382
|
+
// claiming which one.
|
|
383
|
+
//
|
|
384
|
+
// A `commandTransition` switch comes through the same `commandDef` fields and is
|
|
385
|
+
// checked the same way. The compiler has already resolved its constructors, so
|
|
386
|
+
// what survives to here is naming the wrong enum rather than misspelling one —
|
|
387
|
+
// which this catches for the same reason and with the same message.
|
|
382
388
|
let checkDeclaredTransitions = (
|
|
383
389
|
~pluginName: string,
|
|
384
390
|
~writables: array<Reventless.Plugin.writableDef>,
|
|
@@ -412,7 +418,7 @@ let checkDeclaredTransitions = (
|
|
|
412
418
|
->Array.forEach(state =>
|
|
413
419
|
failures
|
|
414
420
|
->Array.push(
|
|
415
|
-
`${w.name}.${cmd.name}
|
|
421
|
+
`${w.name}.${cmd.name} declares state "${state}", which none of its ` ++
|
|
416
422
|
`linked views declare — ${w.linkedViews->Array.join(
|
|
417
423
|
", ",
|
|
418
424
|
)} know ${known->Array.join(", ")}.`,
|
|
@@ -430,14 +436,14 @@ let checkDeclaredTransitions = (
|
|
|
430
436
|
if unvalidated.contents > 0 {
|
|
431
437
|
log.warn(
|
|
432
438
|
~comp="Plugin_Structure",
|
|
433
|
-
`${pluginName}: ${unvalidated.contents->Int.toString} command(s) declare a
|
|
439
|
+
`${pluginName}: ${unvalidated.contents->Int.toString} command(s) declare a transition ` ++
|
|
434
440
|
`but no linked view declares a lifecycle to check it against.`,
|
|
435
441
|
)
|
|
436
442
|
}
|
|
437
443
|
|
|
438
444
|
if Array.length(failures) > 0 {
|
|
439
445
|
JsError.throwWithMessage(
|
|
440
|
-
`${pluginName}:
|
|
446
|
+
`${pluginName}: a declared transition names states that do not exist.\n` ++
|
|
441
447
|
failures->Array.join("\n"),
|
|
442
448
|
)
|
|
443
449
|
}
|
|
@@ -707,6 +713,18 @@ let toCommandDef = (
|
|
|
707
713
|
// one aggregate carries commands with very different audiences, and a
|
|
708
714
|
// component-level shortcut would gate `AddProduct` and `PlaceOrder` alike.
|
|
709
715
|
~commandAuthorization: unknown => Reventless.Authorization.permission,
|
|
716
|
+
// The spec's `command => Transition.t<_>`, evaluated per variant the same way
|
|
717
|
+
// `commandAuthorization` is. It wins over the `@transition` metadata where it
|
|
718
|
+
// declares an edge, and stands aside where it says `Unrestricted` — which is
|
|
719
|
+
// what the PPX injects for a spec that never wrote the switch.
|
|
720
|
+
//
|
|
721
|
+
// Read at `t<string>` because this is the erasure boundary: the spec declares
|
|
722
|
+
// its edges over the linked view's own lifecycle enum, whose arms are
|
|
723
|
+
// payload-less and therefore ARE their own names at run time. The one cast
|
|
724
|
+
// that says so is the same `->Obj.magic` every spec member arrives through
|
|
725
|
+
// (see the call sites below), so `Transition` itself asserts nothing about
|
|
726
|
+
// representation and stays parameterised all the way down.
|
|
727
|
+
~commandTransition: unknown => Reventless.Transition.t<string>,
|
|
710
728
|
v: S.t<unknown>,
|
|
711
729
|
): option<Reventless.Plugin.commandDef> => {
|
|
712
730
|
// Build a commandDef for one variant. `properties` is the variant's field dict —
|
|
@@ -715,12 +733,41 @@ let toCommandDef = (
|
|
|
715
733
|
let mkDef = (~variantName, ~properties) => {
|
|
716
734
|
let (level, aggregateIdField) = commandLevelAndId(~isAggregate, ~variantName, properties)
|
|
717
735
|
let references = extractReferences(properties)
|
|
718
|
-
//
|
|
719
|
-
|
|
720
|
-
//
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
736
|
+
// Evaluated against a synthetic value per constructor, the same shape the
|
|
737
|
+
// resolver builds at call time: a payload-bearing variant compiles to
|
|
738
|
+
// `{TAG, ...}`, a payload-less one to a bare string.
|
|
739
|
+
let syntheticCommand: unknown =
|
|
740
|
+
Reventless.DcbTag.isVariantPayloadBearing(parentSchema, variantName)
|
|
741
|
+
? {"TAG": variantName}->Obj.magic
|
|
742
|
+
: variantName->Obj.magic
|
|
743
|
+
// The spec's own switch, which is the only form that can speak for a
|
|
744
|
+
// constructor the host did not declare: `@transition` lowers to a dict on
|
|
745
|
+
// the parent union, and a variant spread splices members, so a spliced
|
|
746
|
+
// command reaches the metadata below carrying nothing.
|
|
747
|
+
let declared = commandTransition(syntheticCommand)
|
|
748
|
+
// An edge is ONE declaration, so the two fields are chosen together. Taking
|
|
749
|
+
// them separately would let `Guards(…)` — which positively claims the
|
|
750
|
+
// command moves the row nowhere — inherit a target from an annotation it
|
|
751
|
+
// was written to replace.
|
|
752
|
+
//
|
|
753
|
+
// The `@transition` metadata is per-variant but attached by the PPX to the
|
|
754
|
+
// *parent* schema as one dict. It is consulted only where the switch
|
|
755
|
+
// declares no edge at all: a spec that never wrote one answers
|
|
756
|
+
// `Unrestricted` for every command, which is how the annotation stays in
|
|
757
|
+
// charge for the hosts that still use it.
|
|
758
|
+
//
|
|
759
|
+
// `targetState: None` ⇒ AutoUI's board resolver falls back to its name-stem
|
|
760
|
+
// heuristic.
|
|
761
|
+
let (allowedStates, targetState) = switch declared {
|
|
762
|
+
| Unrestricted => (
|
|
763
|
+
ApiAllowedStatesHelpers.getAllowedStates(parentSchema, ~variantName),
|
|
764
|
+
ApiTargetStateHelpers.getTargetState(parentSchema, ~variantName),
|
|
765
|
+
)
|
|
766
|
+
| _ => (
|
|
767
|
+
Reventless.Transition.allowedStates(declared),
|
|
768
|
+
Reventless.Transition.targetState(declared),
|
|
769
|
+
)
|
|
770
|
+
}
|
|
724
771
|
// API-exposed iff the whole command isn't @noApi and this variant
|
|
725
772
|
// isn't in its @noApi-variants set — mirrors the API-generation filter
|
|
726
773
|
// (Plugin_Helpers / PluginBaseFragment). Drives the event-graph API badge.
|
|
@@ -730,13 +777,6 @@ let toCommandDef = (
|
|
|
730
777
|
| Some(excluded) => !(excluded->Set.has(variantName))
|
|
731
778
|
| None => true
|
|
732
779
|
}
|
|
733
|
-
// Evaluated against a synthetic value per constructor, the same shape the
|
|
734
|
-
// resolver builds at call time: a payload-bearing variant compiles to
|
|
735
|
-
// `{TAG, ...}`, a payload-less one to a bare string.
|
|
736
|
-
let syntheticCommand: unknown =
|
|
737
|
-
Reventless.DcbTag.isVariantPayloadBearing(parentSchema, variantName)
|
|
738
|
-
? {"TAG": variantName}->Obj.magic
|
|
739
|
-
: variantName->Obj.magic
|
|
740
780
|
let requiredAccess = accessKeysFor(commandAuthorization(syntheticCommand))
|
|
741
781
|
// See the note on the record's `mutationField` for why a non-exposed
|
|
742
782
|
// variant gets the empty sentinel. It has no callable field, and the
|
|
@@ -796,6 +836,7 @@ let extractCommandDefs = (
|
|
|
796
836
|
~isAggregate,
|
|
797
837
|
~mutationFieldFor: string => string,
|
|
798
838
|
~commandAuthorization: unknown => Reventless.Authorization.permission,
|
|
839
|
+
~commandTransition: unknown => Reventless.Transition.t<string>,
|
|
799
840
|
commandSchema: S.t<unknown>,
|
|
800
841
|
): array<Reventless.Plugin.commandDef> =>
|
|
801
842
|
switch commandSchema {
|
|
@@ -806,6 +847,7 @@ let extractCommandDefs = (
|
|
|
806
847
|
~mutationFieldFor,
|
|
807
848
|
~parentSchema=commandSchema,
|
|
808
849
|
~commandAuthorization,
|
|
850
|
+
~commandTransition,
|
|
809
851
|
v,
|
|
810
852
|
)
|
|
811
853
|
)
|
|
@@ -816,6 +858,7 @@ let extractCommandDefs = (
|
|
|
816
858
|
~mutationFieldFor,
|
|
817
859
|
~parentSchema=commandSchema,
|
|
818
860
|
~commandAuthorization,
|
|
861
|
+
~commandTransition,
|
|
819
862
|
commandSchema,
|
|
820
863
|
)->Option.mapOr([], def => [def])
|
|
821
864
|
}
|
|
@@ -1061,6 +1104,49 @@ let make = (
|
|
|
1061
1104
|
}
|
|
1062
1105
|
}
|
|
1063
1106
|
|
|
1107
|
+
// ── One command name, one handler ──────────────────────────────────────────
|
|
1108
|
+
//
|
|
1109
|
+
// A DCB plugin routes a command by its bare type name: the runtime builds
|
|
1110
|
+
// `handlersByType[typeName]` across every StateChangeSlice in the plugin and
|
|
1111
|
+
// dispatches on the incoming command's TAG alone. Two slices declaring one name
|
|
1112
|
+
// therefore have one handler between them — the second registration overwrites
|
|
1113
|
+
// the first, and the plugin deploys.
|
|
1114
|
+
//
|
|
1115
|
+
// Refused here rather than logged there. The runtime notices only when it goes
|
|
1116
|
+
// to stamp owner fields, by which point the deploy has succeeded and the losing
|
|
1117
|
+
// slice is silently unreachable; a name is a compile-time fact and this is the
|
|
1118
|
+
// last place that can see all of them at once.
|
|
1119
|
+
//
|
|
1120
|
+
// Aggregates are exempt and are not checked: their commands are addressed per
|
|
1121
|
+
// component channel, so two aggregates sharing a command name is ordinary.
|
|
1122
|
+
let dcbCommandOwners: dict<array<string>> = Dict.make()
|
|
1123
|
+
stateChangeSlices->Array.forEach((module(SCS: ReventlessInfra.StateChangeSlice.T)) =>
|
|
1124
|
+
Reventless.DcbTag.extractAllVariantNames(
|
|
1125
|
+
SCS.Spec.commandSchema->S.castToUnknown,
|
|
1126
|
+
)->Array.forEach(cmd => {
|
|
1127
|
+
let owners = dcbCommandOwners->Dict.get(cmd)->Option.getOr([])
|
|
1128
|
+
dcbCommandOwners->Dict.set(cmd, Array.concat(owners, [SCS.Spec.name]))
|
|
1129
|
+
})
|
|
1130
|
+
)
|
|
1131
|
+
let clashes =
|
|
1132
|
+
dcbCommandOwners
|
|
1133
|
+
->Dict.toArray
|
|
1134
|
+
->Array.filter(((_, owners)) => owners->Array.length > 1)
|
|
1135
|
+
->Array.toSorted((((a, _)), ((b, _))) => String.compare(a, b))
|
|
1136
|
+
if clashes->Array.length > 0 {
|
|
1137
|
+
JsError.throwWithMessage(
|
|
1138
|
+
`${name}: ` ++
|
|
1139
|
+
clashes
|
|
1140
|
+
->Array.map((((cmd, owners))) =>
|
|
1141
|
+
`${owners->Array.join(" and ")} both declare the command "${cmd}"`
|
|
1142
|
+
)
|
|
1143
|
+
->Array.join("; ") ++
|
|
1144
|
+
`.\n A DCB plugin routes a command by its bare name, so one of these would never run. ` ++
|
|
1145
|
+
`Qualify them — the shipped traits' emitters prefix every name with the host they are ` ++
|
|
1146
|
+
`grafted onto, for exactly this reason.`,
|
|
1147
|
+
)
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1064
1150
|
// One list feeds both the store collection and the lint below, so a field is
|
|
1065
1151
|
// read exactly once by either.
|
|
1066
1152
|
let storeDeclarationSites: array<(string, S.t<unknown>)> =
|
|
@@ -1118,6 +1204,69 @@ let make = (
|
|
|
1118
1204
|
)
|
|
1119
1205
|
}
|
|
1120
1206
|
|
|
1207
|
+
// Capabilities a slice declares its `translate` reaches for. Sorted and
|
|
1208
|
+
// deduplicated for the same reason the store declarations are: the manifest is
|
|
1209
|
+
// committed, so it must not churn on a re-build. Only outbound translation
|
|
1210
|
+
// slices are handed `Capabilities.t`, so only they can declare.
|
|
1211
|
+
let requiredCapabilities =
|
|
1212
|
+
outboundTranslationSlices
|
|
1213
|
+
->Array.flatMap((module(OTS: ReventlessInfra.OutboundTranslationSlice.T)) =>
|
|
1214
|
+
OTS.Spec.capabilityNeeds->Array.map(need => (
|
|
1215
|
+
{
|
|
1216
|
+
Reventless.Plugin.capability: Reventless.CapabilityNeed.toString(need),
|
|
1217
|
+
component: OTS.Spec.name,
|
|
1218
|
+
}: Reventless.Plugin.requiredCapabilityDeclaration
|
|
1219
|
+
))
|
|
1220
|
+
)
|
|
1221
|
+
->Array.toSorted((a, b) =>
|
|
1222
|
+
a.capability == b.capability
|
|
1223
|
+
? String.compare(a.component, b.component)
|
|
1224
|
+
: String.compare(a.capability, b.capability)
|
|
1225
|
+
)
|
|
1226
|
+
->Array.reduce([], (acc, d) =>
|
|
1227
|
+
switch acc->Array.last {
|
|
1228
|
+
| Some(prev) if prev == d => acc
|
|
1229
|
+
| _ => acc->Array.concat([d])
|
|
1230
|
+
}
|
|
1231
|
+
)
|
|
1232
|
+
|
|
1233
|
+
// The traits grafted into this plugin, one entry per declaring component. The
|
|
1234
|
+
// component name is added here rather than declared: a trait cannot know which
|
|
1235
|
+
// component a host grafted it onto, and a host writing it down would be the one
|
|
1236
|
+
// hand-typed string this whole mechanism exists to avoid. Sorted and
|
|
1237
|
+
// deduplicated for the same reason the two declarations above are.
|
|
1238
|
+
let traitDeclarations = {
|
|
1239
|
+
let entry = (~component, decl: Reventless.Trait.t) => (
|
|
1240
|
+
{
|
|
1241
|
+
Reventless.Plugin.trait: decl.trait,
|
|
1242
|
+
version: decl.version,
|
|
1243
|
+
posture: Reventless.Trait.postureToString(decl.posture),
|
|
1244
|
+
component,
|
|
1245
|
+
}: Reventless.Plugin.traitDeclaration
|
|
1246
|
+
)
|
|
1247
|
+
[
|
|
1248
|
+
aggregates->Array.flatMap((module(A: ReventlessInfra.Aggregate.T with type api = api)) =>
|
|
1249
|
+
A.Spec.traits->Array.map(entry(~component=A.Spec.name, ...))
|
|
1250
|
+
),
|
|
1251
|
+
stateChangeSlices->Array.flatMap((module(SCS: ReventlessInfra.StateChangeSlice.T)) =>
|
|
1252
|
+
SCS.Spec.traits->Array.map(entry(~component=SCS.Spec.name, ...))
|
|
1253
|
+
),
|
|
1254
|
+
outboundTranslationSlices->Array.flatMap((
|
|
1255
|
+
module(OTS: ReventlessInfra.OutboundTranslationSlice.T),
|
|
1256
|
+
) => OTS.Spec.traits->Array.map(entry(~component=OTS.Spec.name, ...))),
|
|
1257
|
+
]
|
|
1258
|
+
->Array.flat
|
|
1259
|
+
->Array.toSorted((a, b) =>
|
|
1260
|
+
a.trait == b.trait ? String.compare(a.component, b.component) : String.compare(a.trait, b.trait)
|
|
1261
|
+
)
|
|
1262
|
+
->Array.reduce([], (acc, d) =>
|
|
1263
|
+
switch acc->Array.last {
|
|
1264
|
+
| Some(prev) if prev == d => acc
|
|
1265
|
+
| _ => acc->Array.concat([d])
|
|
1266
|
+
}
|
|
1267
|
+
)
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1121
1270
|
// Heuristic-only matches — a field *named* like a stored-object ref with no
|
|
1122
1271
|
// `@storageRef` — warn and provision nothing. Declaration outranks inference;
|
|
1123
1272
|
// the warning names the annotation that would settle it.
|
|
@@ -1252,6 +1401,7 @@ let make = (
|
|
|
1252
1401
|
~variant=variantName,
|
|
1253
1402
|
),
|
|
1254
1403
|
~commandAuthorization=SCS.Spec.commandAuthorization->Obj.magic,
|
|
1404
|
+
~commandTransition=SCS.Spec.commandTransition->Obj.magic,
|
|
1255
1405
|
SCS.Spec.commandSchema->S.castToUnknown,
|
|
1256
1406
|
),
|
|
1257
1407
|
producedEventTypes: produced,
|
|
@@ -1276,6 +1426,7 @@ let make = (
|
|
|
1276
1426
|
~isAggregate=true,
|
|
1277
1427
|
~mutationFieldFor=variantName => Api_Naming.aggregateMutationField(~plugin=name, ~aggregate=A.Spec.name, ~command=variantName),
|
|
1278
1428
|
~commandAuthorization=A.Spec.commandAuthorization->Obj.magic,
|
|
1429
|
+
~commandTransition=A.Spec.commandTransition->Obj.magic,
|
|
1279
1430
|
A.Spec.commandSchema->S.castToUnknown,
|
|
1280
1431
|
),
|
|
1281
1432
|
producedEventTypes: produced,
|
|
@@ -1747,5 +1898,7 @@ let make = (
|
|
|
1747
1898
|
extensionPoints: Some(extensionPointDefs),
|
|
1748
1899
|
requiredStores: Some(requiredStores),
|
|
1749
1900
|
requiredStoreDeclarations: Some(requiredStoreDeclarations),
|
|
1901
|
+
traitDeclarations: Some(traitDeclarations),
|
|
1902
|
+
requiredCapabilities: Some(requiredCapabilities),
|
|
1750
1903
|
}
|
|
1751
1904
|
}
|
|
@@ -9,14 +9,17 @@ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
|
9
9
|
import * as Owner$Reventless from "@reventlessdev/reventless-spec/src/components/Owner.res.mjs";
|
|
10
10
|
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
11
11
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
12
|
+
import * as Trait$Reventless from "@reventlessdev/reventless-spec/src/types/Trait.res.mjs";
|
|
12
13
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
13
14
|
import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
|
|
14
15
|
import * as Reference$Reventless from "@reventlessdev/reventless-spec/src/components/Reference.res.mjs";
|
|
15
16
|
import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
|
|
16
17
|
import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
|
|
17
18
|
import * as StorageRef$Reventless from "@reventlessdev/reventless-spec/src/semantic/StorageRef.res.mjs";
|
|
19
|
+
import * as Transition$Reventless from "@reventlessdev/reventless-spec/src/types/Transition.res.mjs";
|
|
18
20
|
import * as DisplayName$Reventless from "@reventlessdev/reventless-spec/src/components/DisplayName.res.mjs";
|
|
19
21
|
import * as Api_Naming$ReventlessCore from "../../components/Api/Api_Naming.res.mjs";
|
|
22
|
+
import * as CapabilityNeed$Reventless from "@reventlessdev/reventless-spec/src/semantic/CapabilityNeed.res.mjs";
|
|
20
23
|
import * as SchemaType$ReventlessCore from "../../components/Api/SchemaType.res.mjs";
|
|
21
24
|
import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
|
|
22
25
|
import * as ApiNoApiHelpers$ReventlessCore from "../../components/Api/ApiNoApiHelpers.res.mjs";
|
|
@@ -343,16 +346,16 @@ function checkDeclaredTransitions(pluginName, writables, lifecycleStatesByView)
|
|
|
343
346
|
unvalidated.contents = unvalidated.contents + 1 | 0;
|
|
344
347
|
} else {
|
|
345
348
|
declared.filter(state => !known.includes(state)).forEach(state => {
|
|
346
|
-
failures.push(w.name + `.` + cmd.name +
|
|
349
|
+
failures.push(w.name + `.` + cmd.name + ` declares state "` + state + `", which none of its ` + (`linked views declare — ` + w.linkedViews.join(", ") + ` know ` + known.join(", ") + `.`));
|
|
347
350
|
});
|
|
348
351
|
}
|
|
349
352
|
});
|
|
350
353
|
});
|
|
351
354
|
if (unvalidated.contents > 0) {
|
|
352
|
-
log.warn("Plugin_Structure", undefined, pluginName + `: ` + unvalidated.contents.toString() + ` command(s) declare a
|
|
355
|
+
log.warn("Plugin_Structure", undefined, pluginName + `: ` + unvalidated.contents.toString() + ` command(s) declare a transition but no linked view declares a lifecycle to check it against.`);
|
|
353
356
|
}
|
|
354
357
|
if (failures.length !== 0) {
|
|
355
|
-
return Stdlib_JsError.throwWithMessage(pluginName + `:
|
|
358
|
+
return Stdlib_JsError.throwWithMessage(pluginName + `: a declared transition names states that do not exist.\n` + failures.join("\n"));
|
|
356
359
|
}
|
|
357
360
|
}
|
|
358
361
|
|
|
@@ -591,20 +594,27 @@ function annotateArgTypes(schema, argTypes) {
|
|
|
591
594
|
return schema;
|
|
592
595
|
}
|
|
593
596
|
|
|
594
|
-
function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthorization, v) {
|
|
597
|
+
function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthorization, commandTransition, v) {
|
|
595
598
|
let mkDef = (variantName, properties) => {
|
|
596
599
|
let match = commandLevelAndId(isAggregate, variantName, properties);
|
|
597
600
|
let references = extractReferences(properties);
|
|
598
|
-
let
|
|
599
|
-
|
|
601
|
+
let syntheticCommand = DcbTag$Reventless.isVariantPayloadBearing(parentSchema, variantName) ? ({
|
|
602
|
+
TAG: variantName
|
|
603
|
+
}) : variantName;
|
|
604
|
+
let declared = commandTransition(syntheticCommand);
|
|
605
|
+
let match$1;
|
|
606
|
+
match$1 = typeof declared !== "object" ? [
|
|
607
|
+
ApiAllowedStatesHelpers$ReventlessCore.getAllowedStates(parentSchema, variantName),
|
|
608
|
+
ApiTargetStateHelpers$ReventlessCore.getTargetState(parentSchema, variantName)
|
|
609
|
+
] : [
|
|
610
|
+
Transition$Reventless.allowedStates(declared),
|
|
611
|
+
Transition$Reventless.targetState(declared)
|
|
612
|
+
];
|
|
600
613
|
let apiExposed = false;
|
|
601
614
|
if (!ApiNoApiHelpers$ReventlessCore.isNoApi(parentSchema)) {
|
|
602
615
|
let excluded = ApiNoApiHelpers$ReventlessCore.getExcludedVariants(parentSchema);
|
|
603
616
|
apiExposed = excluded !== undefined ? !excluded.has(variantName) : true;
|
|
604
617
|
}
|
|
605
|
-
let syntheticCommand = DcbTag$Reventless.isVariantPayloadBearing(parentSchema, variantName) ? ({
|
|
606
|
-
TAG: variantName
|
|
607
|
-
}) : variantName;
|
|
608
618
|
let requiredAccess = accessKeysFor(commandAuthorization(syntheticCommand));
|
|
609
619
|
let mutationField = apiExposed ? mutationFieldFor(variantName) : "";
|
|
610
620
|
let jsonSchema = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(v);
|
|
@@ -616,8 +626,8 @@ function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthor
|
|
|
616
626
|
aggregateIdField: match[1],
|
|
617
627
|
mutationField: mutationField,
|
|
618
628
|
references: references,
|
|
619
|
-
allowedStates:
|
|
620
|
-
targetState:
|
|
629
|
+
allowedStates: match$1[0],
|
|
630
|
+
targetState: match$1[1],
|
|
621
631
|
apiExposed: apiExposed,
|
|
622
632
|
requiredAccess: requiredAccess,
|
|
623
633
|
ownerField: Owner$Reventless.fieldNamesOfProperties(properties)[0]
|
|
@@ -647,11 +657,11 @@ function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthor
|
|
|
647
657
|
}
|
|
648
658
|
}
|
|
649
659
|
|
|
650
|
-
function extractCommandDefs(isAggregate, mutationFieldFor, commandAuthorization, commandSchema) {
|
|
660
|
+
function extractCommandDefs(isAggregate, mutationFieldFor, commandAuthorization, commandTransition, commandSchema) {
|
|
651
661
|
if (commandSchema.type === "anyOf") {
|
|
652
|
-
return Stdlib_Array.filterMap(commandSchema.anyOf, v => toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, v));
|
|
662
|
+
return Stdlib_Array.filterMap(commandSchema.anyOf, v => toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandTransition, v));
|
|
653
663
|
} else {
|
|
654
|
-
return Stdlib_Option.mapOr(toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandSchema), [], def => [def]);
|
|
664
|
+
return Stdlib_Option.mapOr(toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandTransition, commandSchema), [], def => [def]);
|
|
655
665
|
}
|
|
656
666
|
}
|
|
657
667
|
|
|
@@ -791,6 +801,17 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
791
801
|
return Primitive_string.compare(a.field, b.field);
|
|
792
802
|
}
|
|
793
803
|
};
|
|
804
|
+
let dcbCommandOwners = {};
|
|
805
|
+
stateChangeSlices.forEach(SCS => {
|
|
806
|
+
DcbTag$Reventless.extractAllVariantNames(SCS.Spec.commandSchema).forEach(cmd => {
|
|
807
|
+
let owners = Stdlib_Option.getOr(dcbCommandOwners[cmd], []);
|
|
808
|
+
dcbCommandOwners[cmd] = owners.concat([SCS.Spec.name]);
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
let clashes = Object.entries(dcbCommandOwners).filter(param => param[1].length > 1).toSorted((param, param$1) => Primitive_string.compare(param[0], param$1[0]));
|
|
812
|
+
if (clashes.length !== 0) {
|
|
813
|
+
Stdlib_JsError.throwWithMessage(name + `: ` + clashes.map(param => param[1].join(" and ") + ` both declare the command "` + param[0] + `"`).join("; ") + `.\n A DCB plugin routes a command by its bare name, so one of these would never run. Qualify them — the shipped traits' emitters prefix every name with the host they are grafted onto, for exactly this reason.`);
|
|
814
|
+
}
|
|
794
815
|
let storeDeclarationSites = [
|
|
795
816
|
aggregates.flatMap(A => [
|
|
796
817
|
[
|
|
@@ -874,6 +895,55 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
874
895
|
if (found.length !== 0) {
|
|
875
896
|
Stdlib_JsError.throwWithMessage(name + `: two declared object stores look like one store misspelled.\n` + found.map(Capability_Inference$ReventlessCore.collisionMessage).join("\n"));
|
|
876
897
|
}
|
|
898
|
+
let requiredCapabilities = Stdlib_Array.reduce(outboundTranslationSlices.flatMap(OTS => OTS.Spec.capabilityNeeds.map(need => ({
|
|
899
|
+
capability: CapabilityNeed$Reventless.toString(need),
|
|
900
|
+
component: OTS.Spec.name
|
|
901
|
+
}))).toSorted((a, b) => {
|
|
902
|
+
if (a.capability === b.capability) {
|
|
903
|
+
return Primitive_string.compare(a.component, b.component);
|
|
904
|
+
} else {
|
|
905
|
+
return Primitive_string.compare(a.capability, b.capability);
|
|
906
|
+
}
|
|
907
|
+
}), [], (acc, d) => {
|
|
908
|
+
let prev = Stdlib_Array.last(acc);
|
|
909
|
+
if (prev !== undefined) {
|
|
910
|
+
if (Primitive_object.equal(prev, d)) {
|
|
911
|
+
return acc;
|
|
912
|
+
} else {
|
|
913
|
+
return acc.concat([d]);
|
|
914
|
+
}
|
|
915
|
+
} else {
|
|
916
|
+
return acc.concat([d]);
|
|
917
|
+
}
|
|
918
|
+
});
|
|
919
|
+
let entry = (component, decl) => ({
|
|
920
|
+
trait: decl.trait,
|
|
921
|
+
version: decl.version,
|
|
922
|
+
posture: Trait$Reventless.postureToString(decl.posture),
|
|
923
|
+
component: component
|
|
924
|
+
});
|
|
925
|
+
let traitDeclarations = Stdlib_Array.reduce([
|
|
926
|
+
aggregates.flatMap(A => A.Spec.traits.map(extra => entry(A.Spec.name, extra))),
|
|
927
|
+
stateChangeSlices.flatMap(SCS => SCS.Spec.traits.map(extra => entry(SCS.Spec.name, extra))),
|
|
928
|
+
outboundTranslationSlices.flatMap(OTS => OTS.Spec.traits.map(extra => entry(OTS.Spec.name, extra)))
|
|
929
|
+
].flat().toSorted((a, b) => {
|
|
930
|
+
if (a.trait === b.trait) {
|
|
931
|
+
return Primitive_string.compare(a.component, b.component);
|
|
932
|
+
} else {
|
|
933
|
+
return Primitive_string.compare(a.trait, b.trait);
|
|
934
|
+
}
|
|
935
|
+
}), [], (acc, d) => {
|
|
936
|
+
let prev = Stdlib_Array.last(acc);
|
|
937
|
+
if (prev !== undefined) {
|
|
938
|
+
if (Primitive_object.equal(prev, d)) {
|
|
939
|
+
return acc;
|
|
940
|
+
} else {
|
|
941
|
+
return acc.concat([d]);
|
|
942
|
+
}
|
|
943
|
+
} else {
|
|
944
|
+
return acc.concat([d]);
|
|
945
|
+
}
|
|
946
|
+
});
|
|
877
947
|
storeDeclarationSites.forEach(param => {
|
|
878
948
|
Capability_Inference$ReventlessCore.scanSchema(param[0], param[1]).forEach(w => log.warn("Plugin_Structure", undefined, Capability_Inference$ReventlessCore.message(w)));
|
|
879
949
|
});
|
|
@@ -968,7 +1038,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
968
1038
|
let consumed = match$1[1];
|
|
969
1039
|
return {
|
|
970
1040
|
name: SCS.Spec.name,
|
|
971
|
-
commands: extractCommandDefs(false, variantName => Api_Naming$ReventlessCore.sliceMutationFieldFor(name, SCS.Spec.name, SCS.Spec.commandSchema, variantName), SCS.Spec.commandAuthorization, SCS.Spec.commandSchema),
|
|
1041
|
+
commands: extractCommandDefs(false, variantName => Api_Naming$ReventlessCore.sliceMutationFieldFor(name, SCS.Spec.name, SCS.Spec.commandSchema, variantName), SCS.Spec.commandAuthorization, SCS.Spec.commandTransition, SCS.Spec.commandSchema),
|
|
972
1042
|
producedEventTypes: produced,
|
|
973
1043
|
consumedEventTypes: consumed,
|
|
974
1044
|
linkedViews: linkedSvsFor(produced),
|
|
@@ -983,7 +1053,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
983
1053
|
let produced = match[1];
|
|
984
1054
|
return {
|
|
985
1055
|
name: A.Spec.name,
|
|
986
|
-
commands: extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.aggregateMutationField(name, A.Spec.name, variantName), A.Spec.commandAuthorization, A.Spec.commandSchema),
|
|
1056
|
+
commands: extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.aggregateMutationField(name, A.Spec.name, variantName), A.Spec.commandAuthorization, A.Spec.commandTransition, A.Spec.commandSchema),
|
|
987
1057
|
producedEventTypes: produced,
|
|
988
1058
|
consumedEventTypes: [],
|
|
989
1059
|
linkedViews: linkedSvsFor(produced).concat(linkedReadModelsFor(A.Spec.name)),
|
|
@@ -1268,7 +1338,9 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
1268
1338
|
extensions: extensionDefs,
|
|
1269
1339
|
extensionPoints: extensionPointDefs,
|
|
1270
1340
|
requiredStores: requiredStores,
|
|
1271
|
-
requiredStoreDeclarations: requiredStoreDeclarations
|
|
1341
|
+
requiredStoreDeclarations: requiredStoreDeclarations,
|
|
1342
|
+
requiredCapabilities: requiredCapabilities,
|
|
1343
|
+
traitDeclarations: traitDeclarations
|
|
1272
1344
|
};
|
|
1273
1345
|
}
|
|
1274
1346
|
|
|
@@ -75,7 +75,9 @@ function Make(Spec) {
|
|
|
75
75
|
errorSchema: ExtensionMapping$ReventlessInfra.NoDelegate.errorSchema,
|
|
76
76
|
commandSchema: ExtensionMapping$ReventlessInfra.NoDelegate.commandSchema,
|
|
77
77
|
moduleUrl: ExtensionMapping$ReventlessInfra.NoDelegate.moduleUrl,
|
|
78
|
-
commandAuthorization: ExtensionMapping$ReventlessInfra.NoDelegate.commandAuthorization
|
|
78
|
+
commandAuthorization: ExtensionMapping$ReventlessInfra.NoDelegate.commandAuthorization,
|
|
79
|
+
commandTransition: ExtensionMapping$ReventlessInfra.NoDelegate.commandTransition,
|
|
80
|
+
traits: ExtensionMapping$ReventlessInfra.NoDelegate.traits
|
|
79
81
|
},
|
|
80
82
|
moduleUrl: PluginExtensionPointSpec$ReventlessInfra.moduleUrl,
|
|
81
83
|
delegateModuleUrl: delegateModuleUrl,
|
|
@@ -405,7 +405,9 @@ function Make(Spec) {
|
|
|
405
405
|
errorSchema: PluginSpec$ReventlessCore.errorSchema,
|
|
406
406
|
commandSchema: PluginSpec$ReventlessCore.commandSchema,
|
|
407
407
|
moduleUrl: PluginSpec$ReventlessCore.moduleUrl,
|
|
408
|
-
commandAuthorization: PluginSpec$ReventlessCore.commandAuthorization
|
|
408
|
+
commandAuthorization: PluginSpec$ReventlessCore.commandAuthorization,
|
|
409
|
+
commandTransition: PluginSpec$ReventlessCore.commandTransition,
|
|
410
|
+
traits: PluginSpec$ReventlessCore.traits
|
|
409
411
|
},
|
|
410
412
|
moduleUrl: PluginExtensionPointSpec$ReventlessInfra.moduleUrl,
|
|
411
413
|
mapIncomingCommand: mapIncomingCommand,
|
|
@@ -72,7 +72,9 @@ let Mapping = ExtensionPointMapping$ReventlessInfra.Make({
|
|
|
72
72
|
errorSchema: UiFragmentRegistry$ReventlessCore.errorSchema,
|
|
73
73
|
commandSchema: UiFragmentRegistry$ReventlessCore.commandSchema,
|
|
74
74
|
moduleUrl: UiFragmentRegistry$ReventlessCore.moduleUrl,
|
|
75
|
-
commandAuthorization: UiFragmentRegistry$ReventlessCore.commandAuthorization
|
|
75
|
+
commandAuthorization: UiFragmentRegistry$ReventlessCore.commandAuthorization,
|
|
76
|
+
commandTransition: UiFragmentRegistry$ReventlessCore.commandTransition,
|
|
77
|
+
traits: UiFragmentRegistry$ReventlessCore.traits
|
|
76
78
|
},
|
|
77
79
|
moduleUrl: moduleUrl,
|
|
78
80
|
mapIncomingCommand: mapIncomingCommand,
|
|
@@ -159,19 +159,19 @@ let decide = (state, command) =>
|
|
|
159
159
|
Ok(Array.concat([VersionDisconnected(definition)], promoteEvents(state, v)))
|
|
160
160
|
| _ => Ok([]) // not connected / unknown → tolerate stray disconnect
|
|
161
161
|
}
|
|
162
|
-
| Activate(
|
|
163
|
-
switch state.known->Dict.get(
|
|
162
|
+
| Activate({version}) =>
|
|
163
|
+
switch state.known->Dict.get(version) {
|
|
164
164
|
| Some({status: Inactive | Retired, definition}) =>
|
|
165
165
|
let base = [VersionActivated(definition)]
|
|
166
|
-
let supersede = if currentAfterConnect(state.known,
|
|
166
|
+
let supersede = if currentAfterConnect(state.known, version) == version {
|
|
167
167
|
switch state.current {
|
|
168
|
-
| Some(c) if c !=
|
|
168
|
+
| Some(c) if c != version =>
|
|
169
169
|
switch state.known->Dict.get(c) {
|
|
170
170
|
| Some({definition: defC}) => [
|
|
171
171
|
VersionSuperseded({
|
|
172
172
|
supersededVersion: c,
|
|
173
173
|
supersededDefinition: defC,
|
|
174
|
-
newVersion:
|
|
174
|
+
newVersion: version,
|
|
175
175
|
newDefinition: definition,
|
|
176
176
|
}),
|
|
177
177
|
]
|
|
@@ -187,18 +187,18 @@ let decide = (state, command) =>
|
|
|
187
187
|
| Some({status: Disconnected}) => Error(IsDisconnected)
|
|
188
188
|
| None => Error(UnknownVersion)
|
|
189
189
|
}
|
|
190
|
-
| Deactivate(
|
|
191
|
-
switch state.known->Dict.get(
|
|
190
|
+
| Deactivate({version}) =>
|
|
191
|
+
switch state.known->Dict.get(version) {
|
|
192
192
|
| Some({status: Connected | Disconnected, definition}) =>
|
|
193
|
-
Ok(Array.concat([VersionDeactivated(definition)], promoteEvents(state,
|
|
193
|
+
Ok(Array.concat([VersionDeactivated(definition)], promoteEvents(state, version)))
|
|
194
194
|
| Some({status: Inactive | Retired}) => Ok([]) // idempotent / archived no-op
|
|
195
195
|
| None => Error(UnknownVersion)
|
|
196
196
|
}
|
|
197
|
-
| Retire(
|
|
198
|
-
switch state.known->Dict.get(
|
|
197
|
+
| Retire({version}) =>
|
|
198
|
+
switch state.known->Dict.get(version) {
|
|
199
199
|
| Some({status: Retired}) => Ok([]) // idempotent
|
|
200
200
|
| Some({definition}) =>
|
|
201
|
-
Ok(Array.concat([VersionRetired(definition)], promoteEvents(state,
|
|
201
|
+
Ok(Array.concat([VersionRetired(definition)], promoteEvents(state, version)))
|
|
202
202
|
| None => Error(UnknownVersion)
|
|
203
203
|
}
|
|
204
204
|
| ReportIncompatibility(def) => Ok([IncompatiblePluginDetected(def)])
|
|
@@ -232,8 +232,8 @@ function decide(state, command) {
|
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
234
|
case "Activate" :
|
|
235
|
-
let
|
|
236
|
-
let match$4 = state.known[
|
|
235
|
+
let version = command.version;
|
|
236
|
+
let match$4 = state.known[version];
|
|
237
237
|
if (match$4 === undefined) {
|
|
238
238
|
return {
|
|
239
239
|
TAG: "Error",
|
|
@@ -261,17 +261,17 @@ function decide(state, command) {
|
|
|
261
261
|
_0: definition
|
|
262
262
|
}];
|
|
263
263
|
let supersede;
|
|
264
|
-
if (currentAfterConnect(state.known,
|
|
264
|
+
if (currentAfterConnect(state.known, version) === version) {
|
|
265
265
|
let c = state.current;
|
|
266
266
|
if (c !== undefined) {
|
|
267
|
-
if (c !==
|
|
267
|
+
if (c !== version) {
|
|
268
268
|
let match$5 = state.known[c];
|
|
269
269
|
supersede = match$5 !== undefined ? [{
|
|
270
270
|
TAG: "VersionSuperseded",
|
|
271
271
|
_0: {
|
|
272
272
|
supersededVersion: c,
|
|
273
273
|
supersededDefinition: match$5.definition,
|
|
274
|
-
newVersion:
|
|
274
|
+
newVersion: version,
|
|
275
275
|
newDefinition: definition
|
|
276
276
|
}
|
|
277
277
|
}] : [];
|
|
@@ -290,8 +290,8 @@ function decide(state, command) {
|
|
|
290
290
|
};
|
|
291
291
|
break;
|
|
292
292
|
case "Deactivate" :
|
|
293
|
-
let
|
|
294
|
-
let match$6 = state.known[
|
|
293
|
+
let version$1 = command.version;
|
|
294
|
+
let match$6 = state.known[version$1];
|
|
295
295
|
if (match$6 === undefined) {
|
|
296
296
|
return {
|
|
297
297
|
TAG: "Error",
|
|
@@ -314,12 +314,12 @@ function decide(state, command) {
|
|
|
314
314
|
_0: [{
|
|
315
315
|
TAG: "VersionDeactivated",
|
|
316
316
|
_0: match$6.definition
|
|
317
|
-
}].concat(promoteEvents(state,
|
|
317
|
+
}].concat(promoteEvents(state, version$1))
|
|
318
318
|
};
|
|
319
319
|
break;
|
|
320
320
|
case "Retire" :
|
|
321
|
-
let
|
|
322
|
-
let match$7 = state.known[
|
|
321
|
+
let version$2 = command.version;
|
|
322
|
+
let match$7 = state.known[version$2];
|
|
323
323
|
if (match$7 !== undefined) {
|
|
324
324
|
if (match$7.status === "Retired") {
|
|
325
325
|
return {
|
|
@@ -332,7 +332,7 @@ function decide(state, command) {
|
|
|
332
332
|
_0: [{
|
|
333
333
|
TAG: "VersionRetired",
|
|
334
334
|
_0: match$7.definition
|
|
335
|
-
}].concat(promoteEvents(state,
|
|
335
|
+
}].concat(promoteEvents(state, version$2))
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
338
|
} else {
|