@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
|
@@ -30,6 +30,7 @@ import * as PsShipmentsView$ReventlessCore from "./StateViewSlice/PsShipmentsVie
|
|
|
30
30
|
import * as Plugin_Structure$ReventlessCore from "../../src/plugin/component/Plugin_Structure.res.mjs";
|
|
31
31
|
import * as PsCategoriesView$ReventlessCore from "./StateViewSlice/PsCategoriesView.res.mjs";
|
|
32
32
|
import * as PsDispatchShipment$ReventlessCore from "./StateChangeSlice/PsDispatchShipment.res.mjs";
|
|
33
|
+
import * as PsTransitionSwitch$ReventlessCore from "./StateChangeSlice/PsTransitionSwitch.res.mjs";
|
|
33
34
|
import * as Capability_Inference$ReventlessCore from "../../src/plugin/component/Capability_Inference.res.mjs";
|
|
34
35
|
import * as PsAvailableProductsView$ReventlessCore from "./StateViewSlice/PsAvailableProductsView.res.mjs";
|
|
35
36
|
|
|
@@ -53,6 +54,8 @@ let PsPlaceOrderSlice_Spec = {
|
|
|
53
54
|
eventSchema: PsPlaceOrder$ReventlessCore.eventSchema,
|
|
54
55
|
commandSchema: PsPlaceOrder$ReventlessCore.commandSchema,
|
|
55
56
|
commandAuthorization: PsPlaceOrder$ReventlessCore.commandAuthorization,
|
|
57
|
+
commandTransition: PsPlaceOrder$ReventlessCore.commandTransition,
|
|
58
|
+
traits: PsPlaceOrder$ReventlessCore.traits,
|
|
56
59
|
readConsistency: PsPlaceOrder$ReventlessCore.readConsistency
|
|
57
60
|
};
|
|
58
61
|
|
|
@@ -83,6 +86,8 @@ let PsShipOrderSlice_Spec = {
|
|
|
83
86
|
eventSchema: PsShipOrder$ReventlessCore.eventSchema,
|
|
84
87
|
commandSchema: PsShipOrder$ReventlessCore.commandSchema,
|
|
85
88
|
commandAuthorization: PsShipOrder$ReventlessCore.commandAuthorization,
|
|
89
|
+
commandTransition: PsShipOrder$ReventlessCore.commandTransition,
|
|
90
|
+
traits: PsShipOrder$ReventlessCore.traits,
|
|
86
91
|
readConsistency: PsShipOrder$ReventlessCore.readConsistency
|
|
87
92
|
};
|
|
88
93
|
|
|
@@ -243,6 +248,8 @@ let PsAttachInvoiceSlice_Spec = {
|
|
|
243
248
|
eventSchema: PsAttachInvoice$ReventlessCore.eventSchema,
|
|
244
249
|
commandSchema: PsAttachInvoice$ReventlessCore.commandSchema,
|
|
245
250
|
commandAuthorization: PsAttachInvoice$ReventlessCore.commandAuthorization,
|
|
251
|
+
commandTransition: PsAttachInvoice$ReventlessCore.commandTransition,
|
|
252
|
+
traits: PsAttachInvoice$ReventlessCore.traits,
|
|
246
253
|
readConsistency: PsAttachInvoice$ReventlessCore.readConsistency
|
|
247
254
|
};
|
|
248
255
|
|
|
@@ -273,6 +280,8 @@ let PsUploadAvatarSlice_Spec = {
|
|
|
273
280
|
eventSchema: PsUploadAvatar$ReventlessCore.eventSchema,
|
|
274
281
|
commandSchema: PsUploadAvatar$ReventlessCore.commandSchema,
|
|
275
282
|
commandAuthorization: PsUploadAvatar$ReventlessCore.commandAuthorization,
|
|
283
|
+
commandTransition: PsUploadAvatar$ReventlessCore.commandTransition,
|
|
284
|
+
traits: PsUploadAvatar$ReventlessCore.traits,
|
|
276
285
|
readConsistency: PsUploadAvatar$ReventlessCore.readConsistency
|
|
277
286
|
};
|
|
278
287
|
|
|
@@ -303,6 +312,8 @@ let PsUploadImagesSlice_Spec = {
|
|
|
303
312
|
eventSchema: PsUploadImages$ReventlessCore.eventSchema,
|
|
304
313
|
commandSchema: PsUploadImages$ReventlessCore.commandSchema,
|
|
305
314
|
commandAuthorization: PsUploadImages$ReventlessCore.commandAuthorization,
|
|
315
|
+
commandTransition: PsUploadImages$ReventlessCore.commandTransition,
|
|
316
|
+
traits: PsUploadImages$ReventlessCore.traits,
|
|
306
317
|
readConsistency: PsUploadImages$ReventlessCore.readConsistency
|
|
307
318
|
};
|
|
308
319
|
|
|
@@ -333,6 +344,8 @@ let PsTypoStoreSlice_Spec = {
|
|
|
333
344
|
eventSchema: PsTypoStore$ReventlessCore.eventSchema,
|
|
334
345
|
commandSchema: PsTypoStore$ReventlessCore.commandSchema,
|
|
335
346
|
commandAuthorization: PsTypoStore$ReventlessCore.commandAuthorization,
|
|
347
|
+
commandTransition: PsTypoStore$ReventlessCore.commandTransition,
|
|
348
|
+
traits: PsTypoStore$ReventlessCore.traits,
|
|
336
349
|
readConsistency: PsTypoStore$ReventlessCore.readConsistency
|
|
337
350
|
};
|
|
338
351
|
|
|
@@ -363,6 +376,8 @@ let PsChangePhotoSlice_Spec = {
|
|
|
363
376
|
eventSchema: PsChangePhoto$ReventlessCore.eventSchema,
|
|
364
377
|
commandSchema: PsChangePhoto$ReventlessCore.commandSchema,
|
|
365
378
|
commandAuthorization: PsChangePhoto$ReventlessCore.commandAuthorization,
|
|
379
|
+
commandTransition: PsChangePhoto$ReventlessCore.commandTransition,
|
|
380
|
+
traits: PsChangePhoto$ReventlessCore.traits,
|
|
366
381
|
readConsistency: PsChangePhoto$ReventlessCore.readConsistency
|
|
367
382
|
};
|
|
368
383
|
|
|
@@ -393,6 +408,8 @@ let PsReserveStockSlice_Spec = {
|
|
|
393
408
|
eventSchema: PsReserveStock$ReventlessCore.eventSchema,
|
|
394
409
|
commandSchema: PsReserveStock$ReventlessCore.commandSchema,
|
|
395
410
|
commandAuthorization: PsReserveStock$ReventlessCore.commandAuthorization,
|
|
411
|
+
commandTransition: PsReserveStock$ReventlessCore.commandTransition,
|
|
412
|
+
traits: PsReserveStock$ReventlessCore.traits,
|
|
396
413
|
readConsistency: PsReserveStock$ReventlessCore.readConsistency
|
|
397
414
|
};
|
|
398
415
|
|
|
@@ -423,6 +440,8 @@ let PsDispatchShipmentSlice_Spec = {
|
|
|
423
440
|
eventSchema: PsDispatchShipment$ReventlessCore.eventSchema,
|
|
424
441
|
commandSchema: PsDispatchShipment$ReventlessCore.commandSchema,
|
|
425
442
|
commandAuthorization: PsDispatchShipment$ReventlessCore.commandAuthorization,
|
|
443
|
+
commandTransition: PsDispatchShipment$ReventlessCore.commandTransition,
|
|
444
|
+
traits: PsDispatchShipment$ReventlessCore.traits,
|
|
426
445
|
readConsistency: PsDispatchShipment$ReventlessCore.readConsistency
|
|
427
446
|
};
|
|
428
447
|
|
|
@@ -433,12 +452,44 @@ let PsDispatchShipmentSlice = {
|
|
|
433
452
|
make: make$13
|
|
434
453
|
};
|
|
435
454
|
|
|
455
|
+
let Behavior$9 = {
|
|
456
|
+
initialState: false,
|
|
457
|
+
evolve: PsTransitionSwitch$ReventlessCore.evolve,
|
|
458
|
+
decide: PsTransitionSwitch$ReventlessCore.decide,
|
|
459
|
+
moduleUrl: PsTransitionSwitch$ReventlessCore.moduleUrl
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
function make$14(param, param$1, param$2, param$3, param$4, param$5) {
|
|
463
|
+
return 0;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
let PsTransitionSwitchSlice_Spec = {
|
|
467
|
+
name: PsTransitionSwitch$ReventlessCore.name,
|
|
468
|
+
moduleUrl: PsTransitionSwitch$ReventlessCore.moduleUrl,
|
|
469
|
+
Id: Id$Reventless.$$String,
|
|
470
|
+
consumedEventSchema: PsTransitionSwitch$ReventlessCore.consumedEventSchema,
|
|
471
|
+
errorSchema: PsTransitionSwitch$ReventlessCore.errorSchema,
|
|
472
|
+
eventSchema: PsTransitionSwitch$ReventlessCore.eventSchema,
|
|
473
|
+
commandSchema: PsTransitionSwitch$ReventlessCore.commandSchema,
|
|
474
|
+
commandAuthorization: PsTransitionSwitch$ReventlessCore.commandAuthorization,
|
|
475
|
+
commandTransition: PsTransitionSwitch$ReventlessCore.commandTransition,
|
|
476
|
+
traits: PsTransitionSwitch$ReventlessCore.traits,
|
|
477
|
+
readConsistency: PsTransitionSwitch$ReventlessCore.readConsistency
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
let PsTransitionSwitchSlice = {
|
|
481
|
+
Spec: PsTransitionSwitchSlice_Spec,
|
|
482
|
+
Behavior: Behavior$9,
|
|
483
|
+
isAsync: false,
|
|
484
|
+
make: make$14
|
|
485
|
+
};
|
|
486
|
+
|
|
436
487
|
let Projection$5 = {
|
|
437
488
|
project: PsShipmentsView$ReventlessCore.project,
|
|
438
489
|
moduleUrl: PsShipmentsView$ReventlessCore.moduleUrl
|
|
439
490
|
};
|
|
440
491
|
|
|
441
|
-
function make$
|
|
492
|
+
function make$15(param, param$1, param$2) {
|
|
442
493
|
return 0;
|
|
443
494
|
}
|
|
444
495
|
|
|
@@ -456,7 +507,7 @@ let PsShipmentsViewSlice_Spec = {
|
|
|
456
507
|
let PsShipmentsViewSlice = {
|
|
457
508
|
Spec: PsShipmentsViewSlice_Spec,
|
|
458
509
|
Projection: Projection$5,
|
|
459
|
-
make: make$
|
|
510
|
+
make: make$15
|
|
460
511
|
};
|
|
461
512
|
|
|
462
513
|
let structure = Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, [
|
|
@@ -529,6 +580,72 @@ globalThis.describe("lifecycle topology", () => {
|
|
|
529
580
|
});
|
|
530
581
|
});
|
|
531
582
|
|
|
583
|
+
globalThis.describe("commandTransition — the edge as a switch", () => {
|
|
584
|
+
let structure = Plugin_Structure$ReventlessCore.make("TransitionSwitchPlugin", undefined, undefined, [], [PsTransitionSwitchSlice], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
585
|
+
let slice = structure.stateChangeSlices[0];
|
|
586
|
+
let byName = name => slice.commands.find(c => c.name === name);
|
|
587
|
+
globalThis.test("the switch fills allowedStates and targetState", () => {
|
|
588
|
+
globalThis.expect([
|
|
589
|
+
Stdlib_Option.flatMap(byName("Book"), c => c.allowedStates),
|
|
590
|
+
Stdlib_Option.flatMap(byName("Book"), c => c.targetState)
|
|
591
|
+
]).toEqual([
|
|
592
|
+
["Draft"],
|
|
593
|
+
"Booked"
|
|
594
|
+
]);
|
|
595
|
+
});
|
|
596
|
+
globalThis.test("a guard declares its from-set and no target", () => {
|
|
597
|
+
globalThis.expect([
|
|
598
|
+
Stdlib_Option.flatMap(byName("Rebook"), c => c.allowedStates),
|
|
599
|
+
Stdlib_Option.flatMap(byName("Rebook"), c => c.targetState)
|
|
600
|
+
]).toEqual([
|
|
601
|
+
["Booked"],
|
|
602
|
+
undefined
|
|
603
|
+
]);
|
|
604
|
+
});
|
|
605
|
+
globalThis.test("the switch wins over an @transition on the same command", () => {
|
|
606
|
+
globalThis.expect(Stdlib_Option.flatMap(byName("Rebook"), c => c.allowedStates)).toEqual(["Booked"]);
|
|
607
|
+
});
|
|
608
|
+
globalThis.test("Unrestricted declares nothing, leaving the command unconstrained", () => {
|
|
609
|
+
globalThis.expect([
|
|
610
|
+
Stdlib_Option.flatMap(byName("Abandon"), c => c.allowedStates),
|
|
611
|
+
Stdlib_Option.flatMap(byName("Abandon"), c => c.targetState)
|
|
612
|
+
]).toEqual([
|
|
613
|
+
undefined,
|
|
614
|
+
undefined
|
|
615
|
+
]);
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
globalThis.describe("traitDeclarations — a graft leaves a trace", () => {
|
|
620
|
+
let structure = Plugin_Structure$ReventlessCore.make("TraitPlugin", undefined, undefined, [], [
|
|
621
|
+
PsTransitionSwitchSlice,
|
|
622
|
+
PsShipOrderSlice
|
|
623
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
624
|
+
globalThis.test("a declaring component's trait reaches the structure", () => {
|
|
625
|
+
globalThis.expect(Stdlib_Option.getOr(structure.traitDeclarations, []).map(d => [
|
|
626
|
+
d.trait,
|
|
627
|
+
d.component
|
|
628
|
+
])).toEqual([[
|
|
629
|
+
"@reventlessdev/trait-booking",
|
|
630
|
+
"TransitionSwitch"
|
|
631
|
+
]]);
|
|
632
|
+
});
|
|
633
|
+
globalThis.test("the component name is filled in by the structure, not declared", () => {
|
|
634
|
+
globalThis.expect(Stdlib_Option.getOr(structure.traitDeclarations, []).map(d => [
|
|
635
|
+
d.version,
|
|
636
|
+
d.posture,
|
|
637
|
+
d.component
|
|
638
|
+
])).toEqual([[
|
|
639
|
+
"9.9.9",
|
|
640
|
+
"SelfContained",
|
|
641
|
+
"TransitionSwitch"
|
|
642
|
+
]]);
|
|
643
|
+
});
|
|
644
|
+
globalThis.test("a component that is nobody's graft contributes nothing", () => {
|
|
645
|
+
globalThis.expect(Stdlib_Option.getOr(structure.traitDeclarations, []).length).toBe(1);
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
|
|
532
649
|
globalThis.describe("@transition cross-check", () => {
|
|
533
650
|
let buildBad = () => {
|
|
534
651
|
try {
|
|
@@ -1448,6 +1565,78 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
1448
1565
|
globalThis.test("a structure declaring nothing yields an empty list, not a missing manifest", () => {
|
|
1449
1566
|
globalThis.expect(CapabilityManifest$Reventless.fromStructure(structure).capabilities).toEqual([]);
|
|
1450
1567
|
});
|
|
1568
|
+
globalThis.describe("declared capabilities", () => {
|
|
1569
|
+
let withCapability_readModels = structure.readModels;
|
|
1570
|
+
let withCapability_stateViewSlices = structure.stateViewSlices;
|
|
1571
|
+
let withCapability_stateChangeSlices = structure.stateChangeSlices;
|
|
1572
|
+
let withCapability_aggregates = structure.aggregates;
|
|
1573
|
+
let withCapability_automationSlices = structure.automationSlices;
|
|
1574
|
+
let withCapability_outboundTranslationSlices = structure.outboundTranslationSlices;
|
|
1575
|
+
let withCapability_inboundTranslationSlices = structure.inboundTranslationSlices;
|
|
1576
|
+
let withCapability_extensions = structure.extensions;
|
|
1577
|
+
let withCapability_extensionPoints = structure.extensionPoints;
|
|
1578
|
+
let withCapability_requiredStores = structure.requiredStores;
|
|
1579
|
+
let withCapability_requiredStoreDeclarations = structure.requiredStoreDeclarations;
|
|
1580
|
+
let withCapability_requiredCapabilities = [
|
|
1581
|
+
{
|
|
1582
|
+
capability: "Geocoding",
|
|
1583
|
+
component: "GeocodeAddress"
|
|
1584
|
+
},
|
|
1585
|
+
{
|
|
1586
|
+
capability: "Geocoding",
|
|
1587
|
+
component: "GeocodeDropOff"
|
|
1588
|
+
}
|
|
1589
|
+
];
|
|
1590
|
+
let withCapability = {
|
|
1591
|
+
readModels: withCapability_readModels,
|
|
1592
|
+
stateViewSlices: withCapability_stateViewSlices,
|
|
1593
|
+
stateChangeSlices: withCapability_stateChangeSlices,
|
|
1594
|
+
aggregates: withCapability_aggregates,
|
|
1595
|
+
automationSlices: withCapability_automationSlices,
|
|
1596
|
+
outboundTranslationSlices: withCapability_outboundTranslationSlices,
|
|
1597
|
+
inboundTranslationSlices: withCapability_inboundTranslationSlices,
|
|
1598
|
+
extensions: withCapability_extensions,
|
|
1599
|
+
extensionPoints: withCapability_extensionPoints,
|
|
1600
|
+
requiredStores: withCapability_requiredStores,
|
|
1601
|
+
requiredStoreDeclarations: withCapability_requiredStoreDeclarations,
|
|
1602
|
+
requiredCapabilities: withCapability_requiredCapabilities,
|
|
1603
|
+
traitDeclarations: undefined
|
|
1604
|
+
};
|
|
1605
|
+
let entries = CapabilityManifest$Reventless.fromStructure(withCapability).capabilities;
|
|
1606
|
+
globalThis.test("two components needing one capability yield one entry", () => {
|
|
1607
|
+
globalThis.expect(entries.map(e => e.key)).toEqual(["Geocoding"]);
|
|
1608
|
+
});
|
|
1609
|
+
globalThis.test("both declaring components are kept, with no field", () => {
|
|
1610
|
+
globalThis.expect(entries[0].declaredBy).toEqual([
|
|
1611
|
+
{
|
|
1612
|
+
component: "GeocodeAddress"
|
|
1613
|
+
},
|
|
1614
|
+
{
|
|
1615
|
+
component: "GeocodeDropOff"
|
|
1616
|
+
}
|
|
1617
|
+
]);
|
|
1618
|
+
});
|
|
1619
|
+
globalThis.test("a capability this build does not know is dropped", () => {
|
|
1620
|
+
globalThis.expect(CapabilityManifest$Reventless.fromStructure({
|
|
1621
|
+
readModels: structure.readModels,
|
|
1622
|
+
stateViewSlices: structure.stateViewSlices,
|
|
1623
|
+
stateChangeSlices: structure.stateChangeSlices,
|
|
1624
|
+
aggregates: structure.aggregates,
|
|
1625
|
+
automationSlices: structure.automationSlices,
|
|
1626
|
+
outboundTranslationSlices: structure.outboundTranslationSlices,
|
|
1627
|
+
inboundTranslationSlices: structure.inboundTranslationSlices,
|
|
1628
|
+
extensions: structure.extensions,
|
|
1629
|
+
extensionPoints: structure.extensionPoints,
|
|
1630
|
+
requiredStores: structure.requiredStores,
|
|
1631
|
+
requiredStoreDeclarations: structure.requiredStoreDeclarations,
|
|
1632
|
+
requiredCapabilities: [{
|
|
1633
|
+
capability: "Telepathy",
|
|
1634
|
+
component: "Guess"
|
|
1635
|
+
}],
|
|
1636
|
+
traitDeclarations: undefined
|
|
1637
|
+
}).capabilities).toEqual([]);
|
|
1638
|
+
});
|
|
1639
|
+
});
|
|
1451
1640
|
globalThis.test("rendering is deterministic and newline-terminated", () => {
|
|
1452
1641
|
let rendered = CapabilityManifest$Reventless.renderForStructure(withStores);
|
|
1453
1642
|
globalThis.expect(rendered).toBe(`{
|
|
@@ -1662,7 +1851,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
1662
1851
|
let withHeuristicField = Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [PsChangePhotoSlice], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
1663
1852
|
globalThis.expect(withHeuristicField.requiredStores).toEqual(["TestPlugin.productPhotos"]);
|
|
1664
1853
|
let manifest = CapabilityManifest$Reventless.fromStructure(withHeuristicField);
|
|
1665
|
-
globalThis.expect(manifest.capabilities.every(entry => entry.declaredBy.every(site => site.field
|
|
1854
|
+
globalThis.expect(manifest.capabilities.every(entry => entry.declaredBy.every(site => Primitive_object.notequal(site.field, "photoUrl")))).toBe(true);
|
|
1666
1855
|
});
|
|
1667
1856
|
globalThis.test("the warning names the field and the settling annotation", () => {
|
|
1668
1857
|
let text = Capability_Inference$ReventlessCore.message(commandWarnings[0]);
|
|
@@ -1858,6 +2047,59 @@ globalThis.describe("the subscriber's half of the table", () => {
|
|
|
1858
2047
|
});
|
|
1859
2048
|
});
|
|
1860
2049
|
|
|
2050
|
+
globalThis.describe("duplicate DCB command names", () => {
|
|
2051
|
+
globalThis.test("two slices declaring one command are refused", () => {
|
|
2052
|
+
let tmp;
|
|
2053
|
+
try {
|
|
2054
|
+
Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [
|
|
2055
|
+
PsShipOrderSlice,
|
|
2056
|
+
PsShipOrderSlice
|
|
2057
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
2058
|
+
tmp = false;
|
|
2059
|
+
} catch (exn) {
|
|
2060
|
+
tmp = true;
|
|
2061
|
+
}
|
|
2062
|
+
globalThis.expect(tmp).toBe(true);
|
|
2063
|
+
});
|
|
2064
|
+
globalThis.test("the refusal names the command and both slices", () => {
|
|
2065
|
+
let val;
|
|
2066
|
+
try {
|
|
2067
|
+
val = Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [
|
|
2068
|
+
PsShipOrderSlice,
|
|
2069
|
+
PsShipOrderSlice
|
|
2070
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
2071
|
+
} catch (raw_e) {
|
|
2072
|
+
let e = Primitive_exceptions.internalToException(raw_e);
|
|
2073
|
+
if (e.RE_EXN_ID === "JsExn") {
|
|
2074
|
+
let message = Stdlib_Option.getOr(Stdlib_JsExn.message(e._1), "");
|
|
2075
|
+
globalThis.expect([
|
|
2076
|
+
message.includes("ShipOrder"),
|
|
2077
|
+
message.includes("routes a command by its bare name")
|
|
2078
|
+
]).toEqual([
|
|
2079
|
+
true,
|
|
2080
|
+
true
|
|
2081
|
+
]);
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
throw e;
|
|
2085
|
+
}
|
|
2086
|
+
globalThis.expect("no refusal").toBe("a refusal naming the command");
|
|
2087
|
+
});
|
|
2088
|
+
globalThis.test("distinct command names are fine", () => {
|
|
2089
|
+
let tmp;
|
|
2090
|
+
try {
|
|
2091
|
+
Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [
|
|
2092
|
+
PsPlaceOrderSlice,
|
|
2093
|
+
PsShipOrderSlice
|
|
2094
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
2095
|
+
tmp = true;
|
|
2096
|
+
} catch (exn) {
|
|
2097
|
+
tmp = false;
|
|
2098
|
+
}
|
|
2099
|
+
globalThis.expect(tmp).toBe(true);
|
|
2100
|
+
});
|
|
2101
|
+
});
|
|
2102
|
+
|
|
1861
2103
|
export {
|
|
1862
2104
|
PsPlaceOrderSlice,
|
|
1863
2105
|
PsShipOrderSlice,
|
|
@@ -1873,6 +2115,7 @@ export {
|
|
|
1873
2115
|
PsChangePhotoSlice,
|
|
1874
2116
|
PsReserveStockSlice,
|
|
1875
2117
|
PsDispatchShipmentSlice,
|
|
2118
|
+
PsTransitionSwitchSlice,
|
|
1876
2119
|
PsShipmentsViewSlice,
|
|
1877
2120
|
structure,
|
|
1878
2121
|
}
|
|
@@ -36,6 +36,12 @@ function commandAuthorization(param) {
|
|
|
36
36
|
return "AllowAuthenticated";
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
function commandTransition(param) {
|
|
40
|
+
return "Unrestricted";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let traits = [];
|
|
44
|
+
|
|
39
45
|
let name = "AttachInvoice";
|
|
40
46
|
|
|
41
47
|
let Id;
|
|
@@ -59,5 +65,7 @@ export {
|
|
|
59
65
|
moduleUrl,
|
|
60
66
|
commandAuthorization,
|
|
61
67
|
readConsistency,
|
|
68
|
+
commandTransition,
|
|
69
|
+
traits,
|
|
62
70
|
}
|
|
63
71
|
/* consumedEventSchema Not a pure module */
|
|
@@ -37,6 +37,12 @@ function commandAuthorization(param) {
|
|
|
37
37
|
return "AllowAuthenticated";
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
function commandTransition(param) {
|
|
41
|
+
return "Unrestricted";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let traits = [];
|
|
45
|
+
|
|
40
46
|
let name = "ChangePhoto";
|
|
41
47
|
|
|
42
48
|
let Id;
|
|
@@ -60,5 +66,7 @@ export {
|
|
|
60
66
|
moduleUrl,
|
|
61
67
|
commandAuthorization,
|
|
62
68
|
readConsistency,
|
|
69
|
+
commandTransition,
|
|
70
|
+
traits,
|
|
63
71
|
}
|
|
64
72
|
/* consumedEventSchema Not a pure module */
|
|
@@ -46,6 +46,12 @@ function commandAuthorization(param) {
|
|
|
46
46
|
return "AllowAuthenticated";
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
function commandTransition(param) {
|
|
50
|
+
return "Unrestricted";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let traits = [];
|
|
54
|
+
|
|
49
55
|
let name = "DispatchShipment";
|
|
50
56
|
|
|
51
57
|
let Id;
|
|
@@ -69,5 +75,7 @@ export {
|
|
|
69
75
|
moduleUrl,
|
|
70
76
|
commandAuthorization,
|
|
71
77
|
readConsistency,
|
|
78
|
+
commandTransition,
|
|
79
|
+
traits,
|
|
72
80
|
}
|
|
73
81
|
/* consumedEventSchema Not a pure module */
|
|
@@ -57,6 +57,12 @@ function commandAuthorization(command) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
function commandTransition(param) {
|
|
61
|
+
return "Unrestricted";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let traits = [];
|
|
65
|
+
|
|
60
66
|
let name = "GatedCommands";
|
|
61
67
|
|
|
62
68
|
let Id;
|
|
@@ -80,5 +86,7 @@ export {
|
|
|
80
86
|
moduleUrl,
|
|
81
87
|
commandAuthorization,
|
|
82
88
|
readConsistency,
|
|
89
|
+
commandTransition,
|
|
90
|
+
traits,
|
|
83
91
|
}
|
|
84
92
|
/* consumedEventSchema Not a pure module */
|
|
@@ -35,6 +35,12 @@ function commandAuthorization(param) {
|
|
|
35
35
|
return "AllowAuthenticated";
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function commandTransition(param) {
|
|
39
|
+
return "Unrestricted";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let traits = [];
|
|
43
|
+
|
|
38
44
|
let name = "PlaceOrder";
|
|
39
45
|
|
|
40
46
|
let Id;
|
|
@@ -58,5 +64,7 @@ export {
|
|
|
58
64
|
moduleUrl,
|
|
59
65
|
commandAuthorization,
|
|
60
66
|
readConsistency,
|
|
67
|
+
commandTransition,
|
|
68
|
+
traits,
|
|
61
69
|
}
|
|
62
70
|
/* consumedEventSchema Not a pure module */
|
|
@@ -40,6 +40,12 @@ function commandAuthorization(param) {
|
|
|
40
40
|
return "AllowAuthenticated";
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
function commandTransition(param) {
|
|
44
|
+
return "Unrestricted";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let traits = [];
|
|
48
|
+
|
|
43
49
|
let name = "ReserveStock";
|
|
44
50
|
|
|
45
51
|
let Id;
|
|
@@ -63,5 +69,7 @@ export {
|
|
|
63
69
|
moduleUrl,
|
|
64
70
|
commandAuthorization,
|
|
65
71
|
readConsistency,
|
|
72
|
+
commandTransition,
|
|
73
|
+
traits,
|
|
66
74
|
}
|
|
67
75
|
/* consumedEventSchema Not a pure module */
|
|
@@ -61,6 +61,12 @@ function commandAuthorization(param) {
|
|
|
61
61
|
return "AllowAuthenticated";
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
function commandTransition(param) {
|
|
65
|
+
return "Unrestricted";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let traits = [];
|
|
69
|
+
|
|
64
70
|
let name = "ShipOrder";
|
|
65
71
|
|
|
66
72
|
let Id;
|
|
@@ -84,5 +90,7 @@ export {
|
|
|
84
90
|
moduleUrl,
|
|
85
91
|
commandAuthorization,
|
|
86
92
|
readConsistency,
|
|
93
|
+
commandTransition,
|
|
94
|
+
traits,
|
|
87
95
|
}
|
|
88
96
|
/* consumedEventSchema Not a pure module */
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Test fixture spec for `commandTransition` — the edge declared as a switch
|
|
2
|
+
// rather than as an attribute.
|
|
3
|
+
//
|
|
4
|
+
// Three cases in one command type:
|
|
5
|
+
//
|
|
6
|
+
// `Book` declares only through the switch, which is the case
|
|
7
|
+
// `@transition` cannot serve for a spliced constructor.
|
|
8
|
+
// `Rebook` carries BOTH. The switch says `Booked`, the attribute says
|
|
9
|
+
// `Draft`; the switch is what must reach the commandDef, because
|
|
10
|
+
// two sources of truth need a stated winner.
|
|
11
|
+
// `Abandon` declares nothing in either, and must stay unconstrained.
|
|
12
|
+
//
|
|
13
|
+
// The states go in as constructors of this file's own enum, so the compiler
|
|
14
|
+
// resolves them. `@transition` on `Rebook` cannot — it is stripped before the
|
|
15
|
+
// typechecker runs, which is why `PsDispatchShipment` can carry a typo at all.
|
|
16
|
+
|
|
17
|
+
@@reventless.spec("TransitionSwitch")
|
|
18
|
+
|
|
19
|
+
type bookingStatus = Draft | Booked | Abandoned
|
|
20
|
+
|
|
21
|
+
@schema
|
|
22
|
+
type consumedEvent = BookingDrafted({bookingId: string})
|
|
23
|
+
|
|
24
|
+
let evolve = (_state, _event) => true
|
|
25
|
+
|
|
26
|
+
type state = bool
|
|
27
|
+
let initialState = false
|
|
28
|
+
|
|
29
|
+
@schema
|
|
30
|
+
type command =
|
|
31
|
+
| Book({bookingId: string})
|
|
32
|
+
| @transition(([Draft]) => Draft) Rebook({bookingId: string})
|
|
33
|
+
| Abandon({bookingId: string})
|
|
34
|
+
|
|
35
|
+
@schema
|
|
36
|
+
type error = BookingNotFound
|
|
37
|
+
|
|
38
|
+
@schema
|
|
39
|
+
type event = BookingBooked({bookingId: string}) | BookingAbandoned({bookingId: string})
|
|
40
|
+
|
|
41
|
+
let decide = (_state, _command): result<array<event>, error> => Ok([])
|
|
42
|
+
|
|
43
|
+
type lifecycleState = bookingStatus
|
|
44
|
+
|
|
45
|
+
let commandTransition = (command: command): Reventless.Transition.t<lifecycleState> => {
|
|
46
|
+
open Reventless.Transition
|
|
47
|
+
switch command {
|
|
48
|
+
| Book(_) => Moves([Draft], Booked)
|
|
49
|
+
| Rebook(_) => Guards([Booked])
|
|
50
|
+
| Abandon(_) => Unrestricted
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Declared, so the structure has a graft to record. The value stands in for a
|
|
55
|
+
// trait package's own `declaration` — a fixture cannot depend on one, and what is
|
|
56
|
+
// under test is the collection, not where the value came from.
|
|
57
|
+
let traits: array<Reventless.Trait.t> = [
|
|
58
|
+
{trait: "@reventlessdev/trait-booking", version: "9.9.9", posture: SelfContained},
|
|
59
|
+
]
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Sury from "sury";
|
|
4
|
+
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
5
|
+
import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
|
|
6
|
+
|
|
7
|
+
let consumedEventSchema = Sury.$schema(s => ({
|
|
8
|
+
TAG: "BookingDrafted",
|
|
9
|
+
bookingId: s.m(DcbTag$Reventless.string)
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
function evolve(_state, _event) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let commandSchema = Sury.union([
|
|
17
|
+
Sury.$schema(s => ({
|
|
18
|
+
TAG: "Book",
|
|
19
|
+
bookingId: s.m(DcbTag$Reventless.string)
|
|
20
|
+
})),
|
|
21
|
+
Sury.$schema(s => ({
|
|
22
|
+
TAG: "Rebook",
|
|
23
|
+
bookingId: s.m(DcbTag$Reventless.string)
|
|
24
|
+
})),
|
|
25
|
+
Sury.$schema(s => ({
|
|
26
|
+
TAG: "Abandon",
|
|
27
|
+
bookingId: s.m(DcbTag$Reventless.string)
|
|
28
|
+
}))
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
let errorSchema = Sury.literal("BookingNotFound");
|
|
32
|
+
|
|
33
|
+
let eventSchema = Sury.union([
|
|
34
|
+
Sury.$schema(s => ({
|
|
35
|
+
TAG: "BookingBooked",
|
|
36
|
+
bookingId: s.m(DcbTag$Reventless.string)
|
|
37
|
+
})),
|
|
38
|
+
Sury.$schema(s => ({
|
|
39
|
+
TAG: "BookingAbandoned",
|
|
40
|
+
bookingId: s.m(DcbTag$Reventless.string)
|
|
41
|
+
}))
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
function decide(_state, _command) {
|
|
45
|
+
return {
|
|
46
|
+
TAG: "Ok",
|
|
47
|
+
_0: []
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function commandTransition(command) {
|
|
52
|
+
switch (command.TAG) {
|
|
53
|
+
case "Book" :
|
|
54
|
+
return {
|
|
55
|
+
TAG: "Moves",
|
|
56
|
+
_0: ["Draft"],
|
|
57
|
+
_1: "Booked"
|
|
58
|
+
};
|
|
59
|
+
case "Rebook" :
|
|
60
|
+
return {
|
|
61
|
+
TAG: "Guards",
|
|
62
|
+
_0: ["Booked"]
|
|
63
|
+
};
|
|
64
|
+
case "Abandon" :
|
|
65
|
+
return "Unrestricted";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let traits = [{
|
|
70
|
+
trait: "@reventlessdev/trait-booking",
|
|
71
|
+
version: "9.9.9",
|
|
72
|
+
posture: "SelfContained"
|
|
73
|
+
}];
|
|
74
|
+
|
|
75
|
+
let commandSchema$1 = Api$ReventlessInfra.markAllowedStates(commandSchema, [[
|
|
76
|
+
"Rebook",
|
|
77
|
+
["Draft"]
|
|
78
|
+
]]);
|
|
79
|
+
|
|
80
|
+
let commandSchema$2 = Api$ReventlessInfra.markTargetState(commandSchema$1, [[
|
|
81
|
+
"Rebook",
|
|
82
|
+
"Draft"
|
|
83
|
+
]]);
|
|
84
|
+
|
|
85
|
+
function commandAuthorization(param) {
|
|
86
|
+
return "AllowAuthenticated";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let name = "TransitionSwitch";
|
|
90
|
+
|
|
91
|
+
let Id;
|
|
92
|
+
|
|
93
|
+
let initialState = false;
|
|
94
|
+
|
|
95
|
+
let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs";
|
|
96
|
+
|
|
97
|
+
let readConsistency = "EscalateOnRetry";
|
|
98
|
+
|
|
99
|
+
export {
|
|
100
|
+
name,
|
|
101
|
+
Id,
|
|
102
|
+
consumedEventSchema,
|
|
103
|
+
evolve,
|
|
104
|
+
initialState,
|
|
105
|
+
errorSchema,
|
|
106
|
+
eventSchema,
|
|
107
|
+
decide,
|
|
108
|
+
commandTransition,
|
|
109
|
+
traits,
|
|
110
|
+
commandSchema$2 as commandSchema,
|
|
111
|
+
moduleUrl,
|
|
112
|
+
commandAuthorization,
|
|
113
|
+
readConsistency,
|
|
114
|
+
}
|
|
115
|
+
/* consumedEventSchema Not a pure module */
|