@reventlessdev/reventless-core 3.0.0-alpha.256 → 3.0.0-alpha.258
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 +28 -0
- package/package.json +8 -8
- package/src/adapter/Monitoring/Monitoring.res +79 -5
- package/src/adapter/Monitoring/Monitoring.res.mjs +42 -2
- package/src/admin/Platform_Admin_Structure.res.mjs +1 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res +5 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
- package/src/admin/Platform_UiSlots.res +21 -0
- package/src/admin/Platform_UiSlots.res.mjs +15 -0
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +1 -1
- package/src/components/Aggregate/Aggregate_Callback.res +13 -4
- package/src/components/Aggregate/Aggregate_Callback.res.mjs +6 -5
- package/src/components/Api/GraphQL_FragmentGenerator.res +2 -0
- package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +4 -0
- package/src/components/Api/MCP_SchemaGenerator.res.mjs +2 -2
- package/src/components/Api/SchemaType.res +8 -0
- package/src/components/Api/SchemaType.res.mjs +15 -5
- package/src/components/Api/SuryToJsonSchema.res +70 -12
- package/src/components/Api/SuryToJsonSchema.res.mjs +43 -16
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +6 -1
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +1 -1
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +7 -2
- package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +4 -1
- package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
- package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +1 -1
- package/src/plugin/component/Plugin.res +1 -0
- package/src/plugin/component/Plugin_Builder.res +2 -0
- package/src/plugin/component/Plugin_Builder.res.mjs +3 -2
- package/src/plugin/component/Plugin_Structure.res +105 -10
- package/src/plugin/component/Plugin_Structure.res.mjs +71 -27
- package/src/util/Validation.res +1 -1
- package/src/util/Validation.res.mjs +2 -2
- package/tests/adapter/MonitoringTest.res +46 -7
- package/tests/adapter/MonitoringTest.res.mjs +47 -5
- package/tests/admin/AdminApiSchemaDriftTest.res +1 -0
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +3 -0
- package/tests/admin/Platform_Admin_StructureTest.res.mjs +2 -14
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +1 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +2 -0
- package/tests/aggregate/AggregateCacheTest.res.mjs +1 -1
- package/tests/aggregate/AggregateConflictTest.res.mjs +1 -1
- package/tests/aggregate/AggregateFixtures.res.mjs +1 -1
- package/tests/aggregate/AggregateSnapshotTest.res.mjs +1 -1
- package/tests/api/GraphQL_FragmentGeneratorTest.res +6 -4
- package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +5 -5
- package/tests/api/SuryToJsonSchemaTest.res.mjs +57 -57
- package/tests/api/TaggedUnionSchemaTest.res.mjs +1 -1
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +1 -1
- package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +1 -1
- package/tests/dcb/DcbFixtures.res.mjs +1 -1
- package/tests/eventmapper/EventMapperFixtures.res.mjs +1 -1
- package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +1 -1
- package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +1 -1
- package/tests/plugin/ManifestVisibilityTest.res.mjs +1 -1
- package/tests/plugin/PluginStructureAccessTest.res.mjs +1 -1
- package/tests/plugin/PluginStructureTest.res +184 -0
- package/tests/plugin/PluginStructureTest.res.mjs +142 -17
- package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsReserveStock.res +14 -1
- package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +9 -2
- package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +1 -1
- package/tests/util/CommandPublisherTest.res.mjs +1 -1
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
let log = Logger.fromEnv()
|
|
6
6
|
|
|
7
|
+
// Set by `check:lifecycle`, and by nothing else. See the note where it is read.
|
|
8
|
+
@val external _declaredTransitionsOnly: option<string> = "process.env.REVENTLESS_DECLARED_TRANSITIONS_ONLY"
|
|
9
|
+
let declaredTransitionsOnly = _declaredTransitionsOnly->Option.isSome
|
|
10
|
+
|
|
7
11
|
// Whether a field can name a record, stated over `SchemaType`'s IR so every
|
|
8
12
|
// shape it grows is excluded before it exists. `Nullable` unwraps; a `Semantic`
|
|
9
13
|
// wrapper is refused — a bucket key or URL is not prose.
|
|
@@ -413,6 +417,15 @@ let checkDeclaredTransitions = (
|
|
|
413
417
|
if Array.length(known) == 0 {
|
|
414
418
|
unvalidated := unvalidated.contents + 1
|
|
415
419
|
} else {
|
|
420
|
+
// Said, because the two are fixed differently: an authored edge is
|
|
421
|
+
// edited, a harvested one is re-derived. A harvested state the view no
|
|
422
|
+
// longer declares means the committed model went stale, and stopping is
|
|
423
|
+
// right — published, it would offer the command on no row at all.
|
|
424
|
+
let hint = switch cmd.allowedStatesSource {
|
|
425
|
+
| Some("derived") =>
|
|
426
|
+
" This edge came from the component's own scenarios, so the committed lifecycle model is stale."
|
|
427
|
+
| _ => ""
|
|
428
|
+
}
|
|
416
429
|
declared
|
|
417
430
|
->Array.filter(state => !(known->Array.includes(state)))
|
|
418
431
|
->Array.forEach(state =>
|
|
@@ -421,7 +434,7 @@ let checkDeclaredTransitions = (
|
|
|
421
434
|
`${w.name}.${cmd.name} declares state "${state}", which none of its ` ++
|
|
422
435
|
`linked views declare — ${w.linkedViews->Array.join(
|
|
423
436
|
", ",
|
|
424
|
-
)} know ${known->Array.join(", ")}
|
|
437
|
+
)} know ${known->Array.join(", ")}.${hint}`,
|
|
425
438
|
)
|
|
426
439
|
->ignore
|
|
427
440
|
)
|
|
@@ -443,7 +456,7 @@ let checkDeclaredTransitions = (
|
|
|
443
456
|
|
|
444
457
|
if Array.length(failures) > 0 {
|
|
445
458
|
JsError.throwWithMessage(
|
|
446
|
-
`${pluginName}: a
|
|
459
|
+
`${pluginName}: a transition names states that do not exist.\n` ++
|
|
447
460
|
failures->Array.join("\n"),
|
|
448
461
|
)
|
|
449
462
|
}
|
|
@@ -580,10 +593,18 @@ let extractReferences = (properties: dict<S.t<unknown>>): array<
|
|
|
580
593
|
> =>
|
|
581
594
|
properties
|
|
582
595
|
->Dict.toArray
|
|
583
|
-
->Array.
|
|
584
|
-
|
|
596
|
+
->Array.flatMap(((fieldName, fieldSchema)) =>
|
|
597
|
+
// `collectFieldTargets`, not `getFieldTarget`: a reference declared on a field
|
|
598
|
+
// of a record the field holds (an order line's `productId`) is one this
|
|
599
|
+
// command declares, and it arrives named by its own path. Commands and events
|
|
600
|
+
// both come through here, which is what stops one of them learning about
|
|
601
|
+
// nesting and the other not.
|
|
602
|
+
Reventless.Reference.collectFieldTargets(fieldName, fieldSchema)->Array.map(((
|
|
603
|
+
path,
|
|
604
|
+
target,
|
|
605
|
+
)) => (
|
|
585
606
|
{
|
|
586
|
-
Reventless.Plugin.fieldName,
|
|
607
|
+
Reventless.Plugin.fieldName: path,
|
|
587
608
|
entity: target.entity,
|
|
588
609
|
plugin: target.plugin,
|
|
589
610
|
}: Reventless.Plugin.fieldReference
|
|
@@ -637,6 +658,10 @@ let extractErrorDefs = (errorSchema: S.t<unknown>): array<Reventless.Plugin.erro
|
|
|
637
658
|
|
|
638
659
|
// Aggregate commands that initialize a new aggregate instance are Collection-level
|
|
639
660
|
// (shown as table-top buttons); all others are Instance-level (shown per-row).
|
|
661
|
+
//
|
|
662
|
+
// A guess from the command's name stem, and it misreads `Enroll`, `Provision`,
|
|
663
|
+
// `Onboard`. It answers only where the harvested model does not: a plugin with no
|
|
664
|
+
// corpus, or one whose linked views declare no lifecycle to label a history with.
|
|
640
665
|
let isCreateCommandName = name =>
|
|
641
666
|
["Add", "Create", "Register", "Open", "Initialize", "Submit", "Start", "Place"]->Array.some(p =>
|
|
642
667
|
name->String.startsWith(p)
|
|
@@ -724,13 +749,17 @@ let toCommandDef = (
|
|
|
724
749
|
// (see the call sites below), so `Transition` itself asserts nothing about
|
|
725
750
|
// representation and stays parameterised all the way down.
|
|
726
751
|
~commandTransition: unknown => Reventless.Transition.t<string>,
|
|
752
|
+
// What this component's own scenarios say about each command, harvested at
|
|
753
|
+
// build time and committed beside the plugin. `None` for a command no corpus
|
|
754
|
+
// covers, which is most of them in a plugin that ships no tests.
|
|
755
|
+
~derivedEdgeFor: string => option<Reventless.Plugin.derivedEdge>,
|
|
727
756
|
v: S.t<unknown>,
|
|
728
757
|
): option<Reventless.Plugin.commandDef> => {
|
|
729
758
|
// Build a commandDef for one variant. `properties` is the variant's field dict —
|
|
730
759
|
// empty for a payload-less variant (e.g. `| Archive`), which compiles to a bare
|
|
731
760
|
// `S.literal("Archive")` string rather than an `{TAG, ...}` object.
|
|
732
761
|
let mkDef = (~variantName, ~properties) => {
|
|
733
|
-
let (
|
|
762
|
+
let (guessedLevel, aggregateIdField) = commandLevelAndId(~isAggregate, ~variantName, properties)
|
|
734
763
|
let references = extractReferences(properties)
|
|
735
764
|
// Evaluated against a synthetic value per constructor, the same shape the
|
|
736
765
|
// resolver builds at call time: a payload-bearing variant compiles to
|
|
@@ -742,12 +771,57 @@ let toCommandDef = (
|
|
|
742
771
|
// The spec's own switch, which is exhaustive — so it also speaks for a
|
|
743
772
|
// constructor the host did not declare but spliced from a trait.
|
|
744
773
|
//
|
|
745
|
-
// An edge is ONE declaration, so the two fields are read off it together.
|
|
746
774
|
// `targetState: None` ⇒ AutoUI's board resolver falls back to its name-stem
|
|
747
775
|
// heuristic.
|
|
748
776
|
let declared = commandTransition(syntheticCommand)
|
|
749
|
-
let
|
|
750
|
-
|
|
777
|
+
let derived = derivedEdgeFor(variantName)
|
|
778
|
+
|
|
779
|
+
// Where the scenarios answer, they answer; where they are silent, the
|
|
780
|
+
// annotation stands. The halves are resolved separately because they are
|
|
781
|
+
// silent separately — a corpus routinely shows a command taking effect
|
|
782
|
+
// without ever showing where it lands — and because an empty derivation is
|
|
783
|
+
// not a derivation: `Some([])` matches no row's lifecycle tag, so publishing
|
|
784
|
+
// one offers the command on no row at all while the annotation that would
|
|
785
|
+
// have been right sits unread beside it.
|
|
786
|
+
//
|
|
787
|
+
// The one claim the scenarios may not answer for is `Unrestricted`: it says
|
|
788
|
+
// the command is legal in EVERY state, and a corpus only covers the states
|
|
789
|
+
// somebody wrote a scenario for, so deriving a from-set there would shrink a
|
|
790
|
+
// deliberate claim to an accident of coverage and withdraw the command from
|
|
791
|
+
// the rows nobody tested. `Undeclared` — the ppx's injected default — erases
|
|
792
|
+
// to the same pair of `None`s and is silence, which the scenarios may answer.
|
|
793
|
+
let unrestricted = Reventless.Transition.isUnrestricted(declared)
|
|
794
|
+
let (allowedStates, allowedStatesSource) = switch (
|
|
795
|
+
unrestricted
|
|
796
|
+
? None
|
|
797
|
+
: derived->Option.flatMap(d =>
|
|
798
|
+
Array.length(d.allowedStates) > 0 ? Some(d.allowedStates) : None
|
|
799
|
+
),
|
|
800
|
+
Reventless.Transition.allowedStates(declared),
|
|
801
|
+
) {
|
|
802
|
+
| (Some(observed), _) => (Some(observed), Some("derived"))
|
|
803
|
+
| (None, Some(states)) => (Some(states), Some("declared"))
|
|
804
|
+
| (None, None) => (None, unrestricted ? Some("unrestricted") : None)
|
|
805
|
+
}
|
|
806
|
+
// The target is not protected the same way, because the two halves fail
|
|
807
|
+
// differently: a from-set RESTRICTS, and narrowing one wrongly takes a
|
|
808
|
+
// command away from rows it belongs on, while a target only tells a diagram
|
|
809
|
+
// where an edge lands. Supplying one the author left unstated adds
|
|
810
|
+
// information and withdraws nothing — which is what `Customer.Register`'s
|
|
811
|
+
// "the row's status is the view's to derive" asks for.
|
|
812
|
+
let targetState = switch derived->Option.flatMap(d =>
|
|
813
|
+
// Two observed targets are an edge `targetState` cannot express. Reported
|
|
814
|
+
// as a contradiction by the harvest; here the declaration is left to speak
|
|
815
|
+
// rather than one of the two picked.
|
|
816
|
+
switch d.targets {
|
|
817
|
+
| [only] => Some(only)
|
|
818
|
+
| _ => None
|
|
819
|
+
}
|
|
820
|
+
) {
|
|
821
|
+
| Some(observed) => Some(observed)
|
|
822
|
+
| None => Reventless.Transition.targetState(declared)
|
|
823
|
+
}
|
|
824
|
+
let level = derived->Option.flatMap(d => d.level)->Option.getOr(guessedLevel)
|
|
751
825
|
// API-exposed iff the whole command isn't @noApi and this variant
|
|
752
826
|
// isn't in its @noApi-variants set — mirrors the API-generation filter
|
|
753
827
|
// (Plugin_Helpers / PluginBaseFragment). Drives the event-graph API badge.
|
|
@@ -763,7 +837,12 @@ let toCommandDef = (
|
|
|
763
837
|
// argument type names are composed *from* that field name, so there is
|
|
764
838
|
// nothing to publish for it either.
|
|
765
839
|
let mutationField = apiExposed ? mutationFieldFor(variantName) : ""
|
|
766
|
-
|
|
840
|
+
// Rooted at the mutation field, and asking for the input type names, so an
|
|
841
|
+
// object nested inside an argument (an order line inside `lineItems`) carries
|
|
842
|
+
// the name the SDL declares it under — which `x-reventless-graphql-type`, keyed
|
|
843
|
+
// by top-level argument, has no place to put.
|
|
844
|
+
let jsonSchema =
|
|
845
|
+
v->SuryToJsonSchema.deriveObjectSchema(~inputNames=apiExposed, ~typeName=mutationField)
|
|
767
846
|
let annotatedSchema = if apiExposed {
|
|
768
847
|
GraphQL_FragmentGenerator.mutationArgTypes(~fieldName=mutationField, v)->Option.mapOr(
|
|
769
848
|
jsonSchema,
|
|
@@ -785,6 +864,7 @@ let toCommandDef = (
|
|
|
785
864
|
references,
|
|
786
865
|
allowedStates,
|
|
787
866
|
targetState,
|
|
867
|
+
allowedStatesSource: ?allowedStatesSource,
|
|
788
868
|
apiExposed: Some(apiExposed),
|
|
789
869
|
requiredAccess,
|
|
790
870
|
// Resolved from this constructor's own properties, not the union's: two
|
|
@@ -817,6 +897,7 @@ let extractCommandDefs = (
|
|
|
817
897
|
~mutationFieldFor: string => string,
|
|
818
898
|
~commandAuthorization: unknown => Reventless.Authorization.permission,
|
|
819
899
|
~commandTransition: unknown => Reventless.Transition.t<string>,
|
|
900
|
+
~derivedEdgeFor: string => option<Reventless.Plugin.derivedEdge>=_ => None,
|
|
820
901
|
commandSchema: S.t<unknown>,
|
|
821
902
|
): array<Reventless.Plugin.commandDef> =>
|
|
822
903
|
switch commandSchema {
|
|
@@ -828,6 +909,7 @@ let extractCommandDefs = (
|
|
|
828
909
|
~parentSchema=commandSchema,
|
|
829
910
|
~commandAuthorization,
|
|
830
911
|
~commandTransition,
|
|
912
|
+
~derivedEdgeFor,
|
|
831
913
|
v,
|
|
832
914
|
)
|
|
833
915
|
)
|
|
@@ -839,6 +921,7 @@ let extractCommandDefs = (
|
|
|
839
921
|
~parentSchema=commandSchema,
|
|
840
922
|
~commandAuthorization,
|
|
841
923
|
~commandTransition,
|
|
924
|
+
~derivedEdgeFor,
|
|
842
925
|
commandSchema,
|
|
843
926
|
)->Option.mapOr([], def => [def])
|
|
844
927
|
}
|
|
@@ -911,8 +994,18 @@ let make = (
|
|
|
911
994
|
// Component name → chapter, captured from each component's source folder by the
|
|
912
995
|
// plugin generator. Keyed by `Spec.name`; no entry renders flat.
|
|
913
996
|
~componentChapters: dict<string>=Dict.make(),
|
|
997
|
+
// What the plugin's own scenarios say about each command's lifecycle edge,
|
|
998
|
+
// harvested by `check:lifecycle` and committed as `src/LifecycleModel.res`.
|
|
999
|
+
~lifecycleModel: array<Reventless.Plugin.derivedEdge>=[],
|
|
914
1000
|
): Reventless.Plugin.pluginStructure => {
|
|
915
1001
|
let chapterOf = (compName: string): option<string> => componentChapters->Dict.get(compName)
|
|
1002
|
+
// The harvest compares its own reading of the corpus with the DECLARATION, so
|
|
1003
|
+
// it needs a structure the model has not already been folded into. Reading a
|
|
1004
|
+
// derived value back as though it were the claim would confirm every edge and
|
|
1005
|
+
// hide exactly the disagreements the check exists to find.
|
|
1006
|
+
let model = declaredTransitionsOnly ? [] : lifecycleModel
|
|
1007
|
+
let derivedEdgeFor = (~component: string, command: string) =>
|
|
1008
|
+
model->Array.find(e => e.component == component && e.command == command)
|
|
916
1009
|
// Payload-less variants dropped: the graph must not claim an edge a DCB lookup
|
|
917
1010
|
// cannot WHERE-clause on.
|
|
918
1011
|
let eventVariantNames = schema => Reventless.DcbTag.extractVariantNames(schema)
|
|
@@ -1391,6 +1484,7 @@ let make = (
|
|
|
1391
1484
|
),
|
|
1392
1485
|
~commandAuthorization=SCS.Spec.commandAuthorization->Obj.magic,
|
|
1393
1486
|
~commandTransition=SCS.Spec.commandTransition->Obj.magic,
|
|
1487
|
+
~derivedEdgeFor=derivedEdgeFor(~component=SCS.Spec.name, ...),
|
|
1394
1488
|
SCS.Spec.commandSchema->S.castToUnknown,
|
|
1395
1489
|
),
|
|
1396
1490
|
producedEventTypes: produced,
|
|
@@ -1416,6 +1510,7 @@ let make = (
|
|
|
1416
1510
|
~mutationFieldFor=variantName => Api_Naming.aggregateMutationField(~plugin=name, ~aggregate=A.Spec.name, ~command=variantName),
|
|
1417
1511
|
~commandAuthorization=A.Spec.commandAuthorization->Obj.magic,
|
|
1418
1512
|
~commandTransition=A.Spec.commandTransition->Obj.magic,
|
|
1513
|
+
~derivedEdgeFor=derivedEdgeFor(~component=A.Spec.name, ...),
|
|
1419
1514
|
A.Spec.commandSchema->S.castToUnknown,
|
|
1420
1515
|
),
|
|
1421
1516
|
producedEventTypes: produced,
|
|
@@ -29,6 +29,8 @@ import * as GraphQL_FragmentGenerator$ReventlessCore from "../../components/Api/
|
|
|
29
29
|
|
|
30
30
|
let log = Logger$ReventlessCore.fromEnv();
|
|
31
31
|
|
|
32
|
+
let declaredTransitionsOnly = Stdlib_Option.isSome(process.env.REVENTLESS_DECLARED_TRANSITIONS_ONLY);
|
|
33
|
+
|
|
32
34
|
function isLabelShape(_t) {
|
|
33
35
|
while (true) {
|
|
34
36
|
let t = _t;
|
|
@@ -342,18 +344,20 @@ function checkDeclaredTransitions(pluginName, writables, lifecycleStatesByView)
|
|
|
342
344
|
});
|
|
343
345
|
if (known.length === 0) {
|
|
344
346
|
unvalidated.contents = unvalidated.contents + 1 | 0;
|
|
345
|
-
|
|
346
|
-
declared.filter(state => !known.includes(state)).forEach(state => {
|
|
347
|
-
failures.push(w.name + `.` + cmd.name + ` declares state "` + state + `", which none of its ` + (`linked views declare — ` + w.linkedViews.join(", ") + ` know ` + known.join(", ") + `.`));
|
|
348
|
-
});
|
|
347
|
+
return;
|
|
349
348
|
}
|
|
349
|
+
let match = cmd.allowedStatesSource;
|
|
350
|
+
let hint = match === "derived" ? " This edge came from the component's own scenarios, so the committed lifecycle model is stale." : "";
|
|
351
|
+
declared.filter(state => !known.includes(state)).forEach(state => {
|
|
352
|
+
failures.push(w.name + `.` + cmd.name + ` declares state "` + state + `", which none of its ` + (`linked views declare — ` + w.linkedViews.join(", ") + ` know ` + known.join(", ") + `.` + hint));
|
|
353
|
+
});
|
|
350
354
|
});
|
|
351
355
|
});
|
|
352
356
|
if (unvalidated.contents > 0) {
|
|
353
357
|
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.`);
|
|
354
358
|
}
|
|
355
359
|
if (failures.length !== 0) {
|
|
356
|
-
return Stdlib_JsError.throwWithMessage(pluginName + `: a
|
|
360
|
+
return Stdlib_JsError.throwWithMessage(pluginName + `: a transition names states that do not exist.\n` + failures.join("\n"));
|
|
357
361
|
}
|
|
358
362
|
}
|
|
359
363
|
|
|
@@ -449,14 +453,14 @@ function labelFieldsFromStateSchema(entityName, stateSchema) {
|
|
|
449
453
|
}
|
|
450
454
|
|
|
451
455
|
function extractReferences(properties) {
|
|
452
|
-
return
|
|
453
|
-
let
|
|
454
|
-
return
|
|
455
|
-
fieldName:
|
|
456
|
+
return Object.entries(properties).flatMap(param => Reference$Reventless.collectFieldTargets(param[0], param[1]).map(param => {
|
|
457
|
+
let target = param[1];
|
|
458
|
+
return {
|
|
459
|
+
fieldName: param[0],
|
|
456
460
|
entity: target.entity,
|
|
457
461
|
plugin: target.plugin
|
|
458
|
-
}
|
|
459
|
-
});
|
|
462
|
+
};
|
|
463
|
+
}));
|
|
460
464
|
}
|
|
461
465
|
|
|
462
466
|
function toEventDef(v) {
|
|
@@ -464,7 +468,7 @@ function toEventDef(v) {
|
|
|
464
468
|
let references = extractReferences(properties);
|
|
465
469
|
return {
|
|
466
470
|
name: variantName,
|
|
467
|
-
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(v)),
|
|
471
|
+
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, v)),
|
|
468
472
|
references: references
|
|
469
473
|
};
|
|
470
474
|
};
|
|
@@ -592,7 +596,7 @@ function annotateArgTypes(schema, argTypes) {
|
|
|
592
596
|
return schema;
|
|
593
597
|
}
|
|
594
598
|
|
|
595
|
-
function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthorization, commandTransition, v) {
|
|
599
|
+
function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthorization, commandTransition, derivedEdgeFor, v) {
|
|
596
600
|
let mkDef = (variantName, properties) => {
|
|
597
601
|
let match = commandLevelAndId(isAggregate, variantName, properties);
|
|
598
602
|
let references = extractReferences(properties);
|
|
@@ -600,8 +604,36 @@ function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthor
|
|
|
600
604
|
TAG: variantName
|
|
601
605
|
}) : variantName;
|
|
602
606
|
let declared = commandTransition(syntheticCommand);
|
|
603
|
-
let
|
|
604
|
-
let
|
|
607
|
+
let derived = derivedEdgeFor(variantName);
|
|
608
|
+
let unrestricted = Transition$Reventless.isUnrestricted(declared);
|
|
609
|
+
let match$1 = unrestricted ? undefined : Stdlib_Option.flatMap(derived, d => {
|
|
610
|
+
if (d.allowedStates.length !== 0) {
|
|
611
|
+
return d.allowedStates;
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
let match$2 = Transition$Reventless.allowedStates(declared);
|
|
615
|
+
let match$3 = match$1 !== undefined ? [
|
|
616
|
+
match$1,
|
|
617
|
+
"derived"
|
|
618
|
+
] : (
|
|
619
|
+
match$2 !== undefined ? [
|
|
620
|
+
match$2,
|
|
621
|
+
"declared"
|
|
622
|
+
] : [
|
|
623
|
+
undefined,
|
|
624
|
+
unrestricted ? "unrestricted" : undefined
|
|
625
|
+
]
|
|
626
|
+
);
|
|
627
|
+
let observed = Stdlib_Option.flatMap(derived, d => {
|
|
628
|
+
let match = d.targets;
|
|
629
|
+
if (match.length !== 1) {
|
|
630
|
+
return;
|
|
631
|
+
} else {
|
|
632
|
+
return match[0];
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
let targetState = observed !== undefined ? observed : Transition$Reventless.targetState(declared);
|
|
636
|
+
let level = Stdlib_Option.getOr(Stdlib_Option.flatMap(derived, d => d.level), match[0]);
|
|
605
637
|
let apiExposed = false;
|
|
606
638
|
if (!ApiNoApiHelpers$ReventlessCore.isNoApi(parentSchema)) {
|
|
607
639
|
let excluded = ApiNoApiHelpers$ReventlessCore.getExcludedVariants(parentSchema);
|
|
@@ -609,17 +641,18 @@ function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthor
|
|
|
609
641
|
}
|
|
610
642
|
let requiredAccess = accessKeysFor(commandAuthorization(syntheticCommand));
|
|
611
643
|
let mutationField = apiExposed ? mutationFieldFor(variantName) : "";
|
|
612
|
-
let jsonSchema = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(v);
|
|
644
|
+
let jsonSchema = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(apiExposed, mutationField, v);
|
|
613
645
|
let annotatedSchema = apiExposed ? Stdlib_Option.mapOr(GraphQL_FragmentGenerator$ReventlessCore.mutationArgTypes(mutationField, v), jsonSchema, __x => annotateArgTypes(jsonSchema, __x)) : jsonSchema;
|
|
614
646
|
return {
|
|
615
647
|
name: variantName,
|
|
616
648
|
schema: JSON.stringify(annotatedSchema),
|
|
617
|
-
level:
|
|
649
|
+
level: level,
|
|
618
650
|
aggregateIdField: match[1],
|
|
619
651
|
mutationField: mutationField,
|
|
620
652
|
references: references,
|
|
621
|
-
allowedStates:
|
|
653
|
+
allowedStates: match$3[0],
|
|
622
654
|
targetState: targetState,
|
|
655
|
+
allowedStatesSource: match$3[1],
|
|
623
656
|
apiExposed: apiExposed,
|
|
624
657
|
requiredAccess: requiredAccess,
|
|
625
658
|
ownerField: Owner$Reventless.fieldNamesOfProperties(properties)[0]
|
|
@@ -649,11 +682,12 @@ function toCommandDef(isAggregate, mutationFieldFor, parentSchema, commandAuthor
|
|
|
649
682
|
}
|
|
650
683
|
}
|
|
651
684
|
|
|
652
|
-
function extractCommandDefs(isAggregate, mutationFieldFor, commandAuthorization, commandTransition, commandSchema) {
|
|
685
|
+
function extractCommandDefs(isAggregate, mutationFieldFor, commandAuthorization, commandTransition, derivedEdgeForOpt, commandSchema) {
|
|
686
|
+
let derivedEdgeFor = derivedEdgeForOpt !== undefined ? derivedEdgeForOpt : param => {};
|
|
653
687
|
if (commandSchema.type === "anyOf") {
|
|
654
|
-
return Stdlib_Array.filterMap(commandSchema.anyOf, v => toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandTransition, v));
|
|
688
|
+
return Stdlib_Array.filterMap(commandSchema.anyOf, v => toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandTransition, derivedEdgeFor, v));
|
|
655
689
|
} else {
|
|
656
|
-
return Stdlib_Option.mapOr(toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandTransition, commandSchema), [], def => [def]);
|
|
690
|
+
return Stdlib_Option.mapOr(toCommandDef(isAggregate, mutationFieldFor, commandSchema, commandAuthorization, commandTransition, derivedEdgeFor, commandSchema), [], def => [def]);
|
|
657
691
|
}
|
|
658
692
|
}
|
|
659
693
|
|
|
@@ -675,7 +709,7 @@ function queryableDefFromSpec(plugin, name, stateSchema, authorization, visibili
|
|
|
675
709
|
return {
|
|
676
710
|
name: name,
|
|
677
711
|
queryField: qf.listFieldName,
|
|
678
|
-
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(stateSchema)),
|
|
712
|
+
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, stateSchema)),
|
|
679
713
|
consumedEventTypes: consumedEventTypes,
|
|
680
714
|
linkedWriteSide: linkedWriteSide,
|
|
681
715
|
labelField: label.field,
|
|
@@ -695,7 +729,7 @@ function queryableDefFromSpec(plugin, name, stateSchema, authorization, visibili
|
|
|
695
729
|
};
|
|
696
730
|
}
|
|
697
731
|
|
|
698
|
-
function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChangeSlicesOpt, automationSlicesOpt, outboundTranslationSlicesOpt, inboundTranslationSlicesOpt, extensionsOpt, extensionPointsOpt, componentChaptersOpt) {
|
|
732
|
+
function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChangeSlicesOpt, automationSlicesOpt, outboundTranslationSlicesOpt, inboundTranslationSlicesOpt, extensionsOpt, extensionPointsOpt, componentChaptersOpt, lifecycleModelOpt) {
|
|
699
733
|
let aggregates = aggregatesOpt !== undefined ? aggregatesOpt : [];
|
|
700
734
|
let readModels = readModelsOpt !== undefined ? readModelsOpt : [];
|
|
701
735
|
let stateViewSlices = stateViewSlicesOpt !== undefined ? stateViewSlicesOpt : [];
|
|
@@ -706,6 +740,15 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
706
740
|
let extensions = extensionsOpt !== undefined ? extensionsOpt : [];
|
|
707
741
|
let extensionPoints = extensionPointsOpt !== undefined ? extensionPointsOpt : [];
|
|
708
742
|
let componentChapters = componentChaptersOpt !== undefined ? componentChaptersOpt : ({});
|
|
743
|
+
let lifecycleModel = lifecycleModelOpt !== undefined ? lifecycleModelOpt : [];
|
|
744
|
+
let model = declaredTransitionsOnly ? [] : lifecycleModel;
|
|
745
|
+
let derivedEdgeFor = (component, command) => model.find(e => {
|
|
746
|
+
if (e.component === component) {
|
|
747
|
+
return e.command === command;
|
|
748
|
+
} else {
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
});
|
|
709
752
|
let qualify = (prefix, names) => names.map(n => prefix + "." + n);
|
|
710
753
|
let scsProduced = stateChangeSlices.map(SCS => [
|
|
711
754
|
SCS.Spec.name,
|
|
@@ -975,7 +1018,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
975
1018
|
return {
|
|
976
1019
|
name: R.Spec.name,
|
|
977
1020
|
queryField: qf.listFieldName,
|
|
978
|
-
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(stateSchema)),
|
|
1021
|
+
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, stateSchema)),
|
|
979
1022
|
consumedEventTypes: consumed,
|
|
980
1023
|
linkedWriteSide: linkedWriteSideFor(consumed),
|
|
981
1024
|
labelField: label.field,
|
|
@@ -1007,7 +1050,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
1007
1050
|
return {
|
|
1008
1051
|
name: SVS.Spec.name,
|
|
1009
1052
|
queryField: qf.listFieldName,
|
|
1010
|
-
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(stateSchema)),
|
|
1053
|
+
schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, stateSchema)),
|
|
1011
1054
|
consumedEventTypes: consumed,
|
|
1012
1055
|
linkedWriteSide: linkedWriteSideFor(consumed),
|
|
1013
1056
|
labelField: label.field,
|
|
@@ -1033,7 +1076,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
1033
1076
|
let consumed = match$1[1];
|
|
1034
1077
|
return {
|
|
1035
1078
|
name: SCS.Spec.name,
|
|
1036
|
-
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),
|
|
1079
|
+
commands: extractCommandDefs(false, variantName => Api_Naming$ReventlessCore.sliceMutationFieldFor(name, SCS.Spec.name, SCS.Spec.commandSchema, variantName), SCS.Spec.commandAuthorization, SCS.Spec.commandTransition, extra => derivedEdgeFor(SCS.Spec.name, extra), SCS.Spec.commandSchema),
|
|
1037
1080
|
producedEventTypes: produced,
|
|
1038
1081
|
consumedEventTypes: consumed,
|
|
1039
1082
|
linkedViews: linkedSvsFor(produced),
|
|
@@ -1048,7 +1091,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
1048
1091
|
let produced = match[1];
|
|
1049
1092
|
return {
|
|
1050
1093
|
name: A.Spec.name,
|
|
1051
|
-
commands: extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.aggregateMutationField(name, A.Spec.name, variantName), A.Spec.commandAuthorization, A.Spec.commandTransition, A.Spec.commandSchema),
|
|
1094
|
+
commands: extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.aggregateMutationField(name, A.Spec.name, variantName), A.Spec.commandAuthorization, A.Spec.commandTransition, extra => derivedEdgeFor(A.Spec.name, extra), A.Spec.commandSchema),
|
|
1052
1095
|
producedEventTypes: produced,
|
|
1053
1096
|
consumedEventTypes: [],
|
|
1054
1097
|
linkedViews: linkedSvsFor(produced).concat(linkedReadModelsFor(A.Spec.name)),
|
|
@@ -1342,6 +1385,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
1342
1385
|
|
|
1343
1386
|
export {
|
|
1344
1387
|
log,
|
|
1388
|
+
declaredTransitionsOnly,
|
|
1345
1389
|
isLabelShape,
|
|
1346
1390
|
isLifecycleShape,
|
|
1347
1391
|
conventionalLabelNames,
|
package/src/util/Validation.res
CHANGED
|
@@ -31,7 +31,7 @@ let merge: (t<'a, 'b>, t<'a, 'b>) => t<'a, 'b> = (v1, v2) => {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
let defaultErrorHandler = err => {
|
|
34
|
-
EffectLogger.logError(~comp=__MODULE__, err->
|
|
34
|
+
EffectLogger.logError(~comp=__MODULE__, err->Reventless.Util_Sury.exnMessage)->Effect.runSync
|
|
35
35
|
Failure("Couldn't resolve promise.")
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
3
|
import * as Effect from "effect/Effect";
|
|
5
4
|
import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
|
|
5
|
+
import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
|
|
6
6
|
import * as EffectLogger$ReventlessCore from "./EffectLogger.res.mjs";
|
|
7
7
|
|
|
8
8
|
function merge(v1, v2) {
|
|
@@ -105,7 +105,7 @@ function merge(v1, v2) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
function defaultErrorHandler(err) {
|
|
108
|
-
Effect.runSync(EffectLogger$ReventlessCore.logError("Validation-ReventlessCore", undefined,
|
|
108
|
+
Effect.runSync(EffectLogger$ReventlessCore.logError("Validation-ReventlessCore", undefined, Util_Sury$Reventless.exnMessage(err, undefined)));
|
|
109
109
|
return {
|
|
110
110
|
TAG: "Failure",
|
|
111
111
|
_0: "Couldn't resolve promise."
|
|
@@ -6,10 +6,49 @@ open JestGlobals
|
|
|
6
6
|
let stubResource: ReventlessInfra.Adapter.resource = %raw(`{}`)
|
|
7
7
|
|
|
8
8
|
describe("Monitoring", () => {
|
|
9
|
-
testSync("
|
|
10
|
-
// No backend registered — the default Noop backend swallows the call.
|
|
9
|
+
testSync("no backend registered: notify is silent and does not throw", () => {
|
|
11
10
|
Monitoring.notify(~kind=CommandHandler, ~name="before", ~component=stubResource)
|
|
12
11
|
expect(true)->toBe(true)
|
|
12
|
+
Monitoring.reset()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
// The case the dead-letter sink is: a module that provisions at import time announces
|
|
16
|
+
// itself before any statement of the deploy program has run, so it is *always* earlier
|
|
17
|
+
// than the `use` call. Dropping those announcements made that one unit unmonitorable no
|
|
18
|
+
// matter what a backend did.
|
|
19
|
+
testSync("an announcement made before any backend is registered reaches the first one", () => {
|
|
20
|
+
let recorded: array<(Monitoring.unitKind, string, option<string>)> = []
|
|
21
|
+
module Late: Monitoring.Backend = {
|
|
22
|
+
let onProvisioned = (~kind, ~name, ~component as _, ~plugin, ~platform as _, ~logLocator as _) =>
|
|
23
|
+
recorded->Array.push((kind, name, plugin))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Provisioned at import time, inside a construct scope that is long gone by the time
|
|
27
|
+
// anyone registers — so the owner must be captured now, not at delivery.
|
|
28
|
+
let prev = ResourceAttribution.enter(~platform="online-shop", ~plugin="Ordering")
|
|
29
|
+
Monitoring.notify(~kind=DeadLetterSink, ~name="DeadLetterQueue", ~component=stubResource)
|
|
30
|
+
ResourceAttribution.restore(prev)
|
|
31
|
+
Monitoring.notify(~kind=Scheduler, ~name="Heartbeat", ~component=stubResource)
|
|
32
|
+
|
|
33
|
+
expect(recorded)->toEqual([])
|
|
34
|
+
|
|
35
|
+
Monitoring.use(module(Late: Monitoring.Backend))
|
|
36
|
+
|
|
37
|
+
expect(recorded)->toEqual([
|
|
38
|
+
(Monitoring.DeadLetterSink, "DeadLetterQueue", Some("Ordering")),
|
|
39
|
+
(Monitoring.Scheduler, "Heartbeat", None),
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
// Drained: a second registration does not receive them again.
|
|
43
|
+
let second: array<string> = []
|
|
44
|
+
module Other: Monitoring.Backend = {
|
|
45
|
+
let onProvisioned = (~kind as _, ~name, ~component as _, ~plugin as _, ~platform as _, ~logLocator as _) =>
|
|
46
|
+
second->Array.push(name)
|
|
47
|
+
}
|
|
48
|
+
Monitoring.use(module(Other: Monitoring.Backend))
|
|
49
|
+
expect(second)->toEqual([])
|
|
50
|
+
|
|
51
|
+
Monitoring.reset()
|
|
13
52
|
})
|
|
14
53
|
|
|
15
54
|
testSync("use registers a backend that receives every notify, role and name", () => {
|
|
@@ -32,8 +71,8 @@ describe("Monitoring", () => {
|
|
|
32
71
|
(Monitoring.Other("Counter"), "ProductCounter"),
|
|
33
72
|
])
|
|
34
73
|
|
|
35
|
-
// Restore the
|
|
36
|
-
Monitoring.
|
|
74
|
+
// Restore the initial state so registry and buffer don't leak to other cases.
|
|
75
|
+
Monitoring.reset()
|
|
37
76
|
})
|
|
38
77
|
|
|
39
78
|
testSync("notify forwards the static name and component resource to the backend", () => {
|
|
@@ -50,7 +89,7 @@ describe("Monitoring", () => {
|
|
|
50
89
|
| None => expect("no notify received")->toBe("a notify")
|
|
51
90
|
}
|
|
52
91
|
|
|
53
|
-
Monitoring.
|
|
92
|
+
Monitoring.reset()
|
|
54
93
|
})
|
|
55
94
|
|
|
56
95
|
testSync("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
|
|
@@ -78,7 +117,7 @@ describe("Monitoring", () => {
|
|
|
78
117
|
(None, None),
|
|
79
118
|
])
|
|
80
119
|
|
|
81
|
-
Monitoring.
|
|
120
|
+
Monitoring.reset()
|
|
82
121
|
})
|
|
83
122
|
|
|
84
123
|
// Unlike the owner, the locator is not ambient — the seam only forwards what the provisioning
|
|
@@ -105,6 +144,6 @@ describe("Monitoring", () => {
|
|
|
105
144
|
|
|
106
145
|
expect(seen)->toEqual([true, false])
|
|
107
146
|
|
|
108
|
-
Monitoring.
|
|
147
|
+
Monitoring.reset()
|
|
109
148
|
})
|
|
110
149
|
})
|
|
@@ -7,9 +7,51 @@ import * as ResourceAttribution$ReventlessCore from "../../src/ResourceAttributi
|
|
|
7
7
|
let stubResource = {};
|
|
8
8
|
|
|
9
9
|
globalThis.describe("Monitoring", () => {
|
|
10
|
-
globalThis.test("
|
|
10
|
+
globalThis.test("no backend registered: notify is silent and does not throw", () => {
|
|
11
11
|
Monitoring$ReventlessCore.notify("CommandHandler", "before", stubResource, undefined);
|
|
12
12
|
globalThis.expect(true).toBe(true);
|
|
13
|
+
Monitoring$ReventlessCore.reset();
|
|
14
|
+
});
|
|
15
|
+
globalThis.test("an announcement made before any backend is registered reaches the first one", () => {
|
|
16
|
+
let recorded = [];
|
|
17
|
+
let onProvisioned = (kind, name, param, plugin, param$1, param$2) => {
|
|
18
|
+
recorded.push([
|
|
19
|
+
kind,
|
|
20
|
+
name,
|
|
21
|
+
plugin
|
|
22
|
+
]);
|
|
23
|
+
};
|
|
24
|
+
let Late = {
|
|
25
|
+
onProvisioned: onProvisioned
|
|
26
|
+
};
|
|
27
|
+
let prev = ResourceAttribution$ReventlessCore.enter("online-shop", "Ordering");
|
|
28
|
+
Monitoring$ReventlessCore.notify("DeadLetterSink", "DeadLetterQueue", stubResource, undefined);
|
|
29
|
+
ResourceAttribution$ReventlessCore.restore(prev);
|
|
30
|
+
Monitoring$ReventlessCore.notify("Scheduler", "Heartbeat", stubResource, undefined);
|
|
31
|
+
globalThis.expect(recorded).toEqual([]);
|
|
32
|
+
Monitoring$ReventlessCore.use(Late);
|
|
33
|
+
globalThis.expect(recorded).toEqual([
|
|
34
|
+
[
|
|
35
|
+
"DeadLetterSink",
|
|
36
|
+
"DeadLetterQueue",
|
|
37
|
+
"Ordering"
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
"Scheduler",
|
|
41
|
+
"Heartbeat",
|
|
42
|
+
undefined
|
|
43
|
+
]
|
|
44
|
+
]);
|
|
45
|
+
let second = [];
|
|
46
|
+
let onProvisioned$1 = (param, name, param$1, param$2, param$3, param$4) => {
|
|
47
|
+
second.push(name);
|
|
48
|
+
};
|
|
49
|
+
let Other = {
|
|
50
|
+
onProvisioned: onProvisioned$1
|
|
51
|
+
};
|
|
52
|
+
Monitoring$ReventlessCore.use(Other);
|
|
53
|
+
globalThis.expect(second).toEqual([]);
|
|
54
|
+
Monitoring$ReventlessCore.reset();
|
|
13
55
|
});
|
|
14
56
|
globalThis.test("use registers a backend that receives every notify, role and name", () => {
|
|
15
57
|
let recorded = [];
|
|
@@ -51,7 +93,7 @@ globalThis.describe("Monitoring", () => {
|
|
|
51
93
|
"ProductCounter"
|
|
52
94
|
]
|
|
53
95
|
]);
|
|
54
|
-
Monitoring$ReventlessCore.
|
|
96
|
+
Monitoring$ReventlessCore.reset();
|
|
55
97
|
});
|
|
56
98
|
globalThis.test("notify forwards the static name and component resource to the backend", () => {
|
|
57
99
|
let seen = {
|
|
@@ -74,7 +116,7 @@ globalThis.describe("Monitoring", () => {
|
|
|
74
116
|
} else {
|
|
75
117
|
globalThis.expect("no notify received").toBe("a notify");
|
|
76
118
|
}
|
|
77
|
-
Monitoring$ReventlessCore.
|
|
119
|
+
Monitoring$ReventlessCore.reset();
|
|
78
120
|
});
|
|
79
121
|
globalThis.test("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
|
|
80
122
|
let seen = [];
|
|
@@ -107,7 +149,7 @@ globalThis.describe("Monitoring", () => {
|
|
|
107
149
|
undefined
|
|
108
150
|
]
|
|
109
151
|
]);
|
|
110
|
-
Monitoring$ReventlessCore.
|
|
152
|
+
Monitoring$ReventlessCore.reset();
|
|
111
153
|
});
|
|
112
154
|
globalThis.test("notify forwards the log locator when given one, None when omitted", () => {
|
|
113
155
|
let stubLocator = {};
|
|
@@ -125,7 +167,7 @@ globalThis.describe("Monitoring", () => {
|
|
|
125
167
|
true,
|
|
126
168
|
false
|
|
127
169
|
]);
|
|
128
|
-
Monitoring$ReventlessCore.
|
|
170
|
+
Monitoring$ReventlessCore.reset();
|
|
129
171
|
});
|
|
130
172
|
});
|
|
131
173
|
|