@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.
Files changed (66) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +7 -7
  3. package/src/admin/Platform_Admin_Structure.res +4 -1
  4. package/src/admin/Platform_Admin_Structure.res.mjs +4 -2
  5. package/src/admin/Platform_BakedManifest.res.mjs +3 -1
  6. package/src/admin/Platform_PluginStructuresApi.res +43 -7
  7. package/src/admin/Platform_PluginStructuresApi.res.mjs +47 -1
  8. package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +8 -0
  9. package/src/components/Api/ApiNoApiHelpers.res +37 -3
  10. package/src/components/Api/ApiNoApiHelpers.res.mjs +29 -2
  11. package/src/components/AutomationSlice/AutomationSlice_Callback.res +4 -4
  12. package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +3 -3
  13. package/src/plugin/api/PluginBaseFragment.res +3 -3
  14. package/src/plugin/component/Plugin_Structure.res +175 -22
  15. package/src/plugin/component/Plugin_Structure.res.mjs +89 -17
  16. package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +3 -1
  17. package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +3 -1
  18. package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +3 -1
  19. package/src/plugin/lifecycle/PluginBehavior.res +11 -11
  20. package/src/plugin/lifecycle/PluginBehavior.res.mjs +11 -11
  21. package/src/plugin/lifecycle/PluginSpec.res +11 -3
  22. package/src/plugin/lifecycle/PluginSpec.res.mjs +11 -3
  23. package/tests/admin/AdminApiSchemaDriftTest.res +27 -1
  24. package/tests/admin/AdminApiSchemaDriftTest.res.mjs +22 -2
  25. package/tests/admin/Platform_Admin_StructureTest.res +8 -3
  26. package/tests/admin/Platform_Admin_StructureTest.res.mjs +8 -2
  27. package/tests/admin/Platform_BakedManifestTest.res +2 -0
  28. package/tests/admin/Platform_BakedManifestTest.res.mjs +3 -1
  29. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +4 -0
  30. package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +21 -7
  31. package/tests/admin/Platform_PluginStructuresApiTest.res +16 -0
  32. package/tests/admin/Platform_PluginStructuresApiTest.res.mjs +17 -3
  33. package/tests/aggregate/AggregateCacheTest.res.mjs +15 -3
  34. package/tests/aggregate/AggregateConflictTest.res.mjs +15 -3
  35. package/tests/aggregate/AggregateFixtures.res.mjs +15 -3
  36. package/tests/aggregate/AggregateSnapshotTest.res.mjs +21 -5
  37. package/tests/api/ApiNoApiTest.res +46 -0
  38. package/tests/api/ApiNoApiTest.res.mjs +49 -1
  39. package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +27 -3
  40. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +12 -2
  41. package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +2 -0
  42. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +12 -2
  43. package/tests/dcb/DcbFixtures.res.mjs +8 -0
  44. package/tests/dcb/DcbStateChangeSliceTest.res.mjs +18 -0
  45. package/tests/eventmapper/EventMapperFixtures.res.mjs +15 -3
  46. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +9 -1
  47. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +9 -1
  48. package/tests/message/MessageTest.res +2 -0
  49. package/tests/message/MessageTest.res.mjs +3 -1
  50. package/tests/plugin/PluginStructureAccessTest.res.mjs +2 -0
  51. package/tests/plugin/PluginStructureTest.res +185 -1
  52. package/tests/plugin/PluginStructureTest.res.mjs +246 -3
  53. package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +8 -0
  54. package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +8 -0
  55. package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +8 -0
  56. package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +8 -0
  57. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +8 -0
  58. package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +8 -0
  59. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +8 -0
  60. package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res +59 -0
  61. package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs +115 -0
  62. package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +8 -0
  63. package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +8 -0
  64. package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +8 -0
  65. package/tests/plugin/pluginDefinitionRequiredScalars.txt +18 -0
  66. 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$14(param, param$1, param$2) {
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$14
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 !== "photoUrl"))).toBe(true);
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 */