@reventlessdev/reventless-core 3.0.0-alpha.251 → 3.0.0-alpha.253

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 (73) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/package.json +8 -8
  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 +158 -25
  15. package/src/plugin/component/Plugin_Structure.res.mjs +82 -18
  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 +39 -16
  22. package/src/plugin/lifecycle/PluginSpec.res.mjs +54 -56
  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 +191 -12
  52. package/tests/plugin/PluginStructureTest.res.mjs +246 -6
  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 +17 -7
  56. package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +12 -11
  57. package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +8 -0
  58. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +8 -0
  59. package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +8 -0
  60. package/tests/plugin/StateChangeSlice/PsShipOrder.res +17 -13
  61. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +17 -11
  62. package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res +54 -0
  63. package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs +104 -0
  64. package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +8 -0
  65. package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +8 -0
  66. package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +8 -0
  67. package/tests/plugin/StateViewSlice/PsShipmentsView.res +1 -1
  68. package/tests/plugin/pluginDefinitionRequiredScalars.txt +18 -0
  69. package/tests/util/CommandPublisherTest.res.mjs +9 -1
  70. package/src/components/Api/ApiAllowedStatesHelpers.res +0 -18
  71. package/src/components/Api/ApiAllowedStatesHelpers.res.mjs +0 -16
  72. package/src/components/Api/ApiTargetStateHelpers.res +0 -21
  73. package/src/components/Api/ApiTargetStateHelpers.res.mjs +0 -16
@@ -1,15 +1,16 @@
1
- // Test fixture spec for the @transition cross-check — the failing case.
1
+ // Test fixture spec for the declared-edge cross-check — the failing case.
2
2
  //
3
- // `Dispatchd` is a deliberate typo. It compiles: the PPX strips the attribute
4
- // before the typechecker sees it, so a misspelled state is a well-formed string
5
- // all the way down. That is exactly the hole the structure-side check closes,
6
- // and a fixture that could not compile would not demonstrate it.
3
+ // The switch names constructors of THIS file's own enum, and `Dispatchd` is a
4
+ // real case of it, so the compiler is satisfied. The linked `Shipments` view
5
+ // declares `Booked | Dispatched`, and nothing forces a spec to pick its linked
6
+ // view's enum — which is the hole the structure-side check closes, and the half
7
+ // the typechecker cannot reach.
7
8
 
8
9
  @@reventless.spec("DispatchShipment")
9
10
 
10
11
  type shipmentStatus =
11
12
  | Booked
12
- | Dispatched
13
+ | Dispatchd
13
14
 
14
15
  @schema
15
16
  type consumedEvent = ShipmentBooked({shipmentId: string})
@@ -20,7 +21,7 @@ type state = bool
20
21
  let initialState = false
21
22
 
22
23
  @schema
23
- type command = @transition(([Booked]) => Dispatchd) DispatchShipment({shipmentId: string})
24
+ type command = DispatchShipment({shipmentId: string})
24
25
 
25
26
  @schema
26
27
  type error = ShipmentNotFound
@@ -29,3 +30,12 @@ type error = ShipmentNotFound
29
30
  type event = ShipmentDispatched({shipmentId: string})
30
31
 
31
32
  let decide = (_state, _command): result<array<event>, error> => Ok([])
33
+
34
+ type lifecycleState = shipmentStatus
35
+
36
+ let commandTransition = (command: command): Reventless.Transition.t<lifecycleState> => {
37
+ open Reventless.Transition
38
+ switch command {
39
+ | DispatchShipment(_) => Moves([Booked], Dispatchd)
40
+ }
41
+ }
@@ -2,7 +2,6 @@
2
2
 
3
3
  import * as Sury from "sury";
4
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
5
 
7
6
  let consumedEventSchema = Sury.$schema(s => ({
8
7
  TAG: "ShipmentBooked",
@@ -32,20 +31,20 @@ function decide(_state, _command) {
32
31
  };
33
32
  }
34
33
 
35
- let commandSchema$1 = Api$ReventlessInfra.markAllowedStates(commandSchema, [[
36
- "DispatchShipment",
37
- ["Booked"]
38
- ]]);
39
-
40
- let commandSchema$2 = Api$ReventlessInfra.markTargetState(commandSchema$1, [[
41
- "DispatchShipment",
42
- "Dispatchd"
43
- ]]);
34
+ function commandTransition(command) {
35
+ return {
36
+ TAG: "Moves",
37
+ _0: ["Booked"],
38
+ _1: "Dispatchd"
39
+ };
40
+ }
44
41
 
45
42
  function commandAuthorization(param) {
46
43
  return "AllowAuthenticated";
47
44
  }
48
45
 
46
+ let traits = [];
47
+
49
48
  let name = "DispatchShipment";
50
49
 
51
50
  let Id;
@@ -62,12 +61,14 @@ export {
62
61
  consumedEventSchema,
63
62
  evolve,
64
63
  initialState,
64
+ commandSchema,
65
65
  errorSchema,
66
66
  eventSchema,
67
67
  decide,
68
- commandSchema$2 as commandSchema,
68
+ commandTransition,
69
69
  moduleUrl,
70
70
  commandAuthorization,
71
71
  readConsistency,
72
+ traits,
72
73
  }
73
74
  /* 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 */
@@ -13,27 +13,21 @@ type consumedEvent = OrderPlaced | OrderShipped | OrderCancelled
13
13
 
14
14
  let evolve = (_state, _event) => true
15
15
 
16
- // CancelShipment is payload-less — it compiles to a bare string literal, so it
17
- // exercises toCommandDef's payload-less branch (still surfaced in `commands`).
18
- // It is also `@noApi` (internal/admin only): a two-variant slice with exactly
19
- // one API-exposed command, which is the case that used to leak the exposed
20
- // command's slice mutation field onto the non-exposed variant.
21
- // The lifecycle this slice's commands move a shipment through. The PPX strips
22
- // @transition before the typechecker sees it, so this enum is not what makes the
23
- // reference below valid — the structure-side check against the linked view is.
24
- // It is here because a state is a constructor, and naming one in a string is a
25
- // reference nothing can check at any layer.
16
+ // The lifecycle this slice's commands move a shipment through. Declared here
17
+ // rather than on a linked view because this fixture's plugin has none: the
18
+ // structure-side check warns instead of failing when a component's views declare
19
+ // no lifecycle, and that is the path this exercises.
26
20
  type shipmentStatus = Placed | Shipped | Cancelled
27
21
 
28
22
  // CancelShipment is payload-less — it compiles to a bare string literal, so it
29
23
  // exercises toCommandDef's payload-less branch (still surfaced in `commands`).
30
24
  // It is also `@noApi` (internal/admin only): a two-variant slice with exactly
31
25
  // one API-exposed command, which is the case that used to leak the exposed
32
- // command's slice mutation field onto the non-exposed variant. It carries no
33
- // @transition, which is the un-annotated case the resolver still guesses for.
26
+ // command's slice mutation field onto the non-exposed variant. It declares no
27
+ // edge, which is the case the board resolver still guesses for.
34
28
  @schema
35
29
  type command =
36
- | @transition(([Placed]) => Shipped) ShipOrder({orderId: string})
30
+ | ShipOrder({orderId: string})
37
31
  | @noApi CancelShipment
38
32
 
39
33
  // Two variants, one payload-less and one carrying a field — the same two branches
@@ -47,3 +41,13 @@ type error = OrderNotFound | NotShippable({reason: string})
47
41
  type event = OrderShipped({orderId: string}) | ShipmentVoided
48
42
 
49
43
  let decide = (_state, _command): result<array<event>, error> => Ok([])
44
+
45
+ type lifecycleState = shipmentStatus
46
+
47
+ let commandTransition = (command: command): Reventless.Transition.t<lifecycleState> => {
48
+ open Reventless.Transition
49
+ switch command {
50
+ | ShipOrder(_) => Moves([Placed], Shipped)
51
+ | CancelShipment => Unrestricted
52
+ }
53
+ }
@@ -45,22 +45,26 @@ function decide(_state, _command) {
45
45
  };
46
46
  }
47
47
 
48
- let commandSchema$1 = Api$ReventlessInfra.markNoApiVariants(commandSchema, ["CancelShipment"]);
49
-
50
- let commandSchema$2 = Api$ReventlessInfra.markAllowedStates(commandSchema$1, [[
51
- "ShipOrder",
52
- ["Placed"]
53
- ]]);
48
+ function commandTransition(command) {
49
+ if (typeof command !== "object") {
50
+ return "Unrestricted";
51
+ } else {
52
+ return {
53
+ TAG: "Moves",
54
+ _0: ["Placed"],
55
+ _1: "Shipped"
56
+ };
57
+ }
58
+ }
54
59
 
55
- let commandSchema$3 = Api$ReventlessInfra.markTargetState(commandSchema$2, [[
56
- "ShipOrder",
57
- "Shipped"
58
- ]]);
60
+ let commandSchema$1 = Api$ReventlessInfra.markNoApiVariants(commandSchema, ["CancelShipment"]);
59
61
 
60
62
  function commandAuthorization(param) {
61
63
  return "AllowAuthenticated";
62
64
  }
63
65
 
66
+ let traits = [];
67
+
64
68
  let name = "ShipOrder";
65
69
 
66
70
  let Id;
@@ -80,9 +84,11 @@ export {
80
84
  errorSchema,
81
85
  eventSchema,
82
86
  decide,
83
- commandSchema$3 as commandSchema,
87
+ commandTransition,
88
+ commandSchema$1 as commandSchema,
84
89
  moduleUrl,
85
90
  commandAuthorization,
86
91
  readConsistency,
92
+ traits,
87
93
  }
88
94
  /* consumedEventSchema Not a pure module */
@@ -0,0 +1,54 @@
1
+ // Test fixture spec for `commandTransition` — the three shapes of a declared
2
+ // edge, in one command type:
3
+ //
4
+ // `Book` moves the row: a from-set and a target.
5
+ // `Rebook` guards only: a from-set and no target, which is the positive
6
+ // claim that the command moves the row nowhere.
7
+ // `Abandon` declares nothing, and must stay unconstrained.
8
+ //
9
+ // The states go in as constructors of this file's own enum, so the compiler
10
+ // resolves them.
11
+
12
+ @@reventless.spec("TransitionSwitch")
13
+
14
+ type bookingStatus = Draft | Booked | Abandoned
15
+
16
+ @schema
17
+ type consumedEvent = BookingDrafted({bookingId: string})
18
+
19
+ let evolve = (_state, _event) => true
20
+
21
+ type state = bool
22
+ let initialState = false
23
+
24
+ @schema
25
+ type command =
26
+ | Book({bookingId: string})
27
+ | Rebook({bookingId: string})
28
+ | Abandon({bookingId: string})
29
+
30
+ @schema
31
+ type error = BookingNotFound
32
+
33
+ @schema
34
+ type event = BookingBooked({bookingId: string}) | BookingAbandoned({bookingId: string})
35
+
36
+ let decide = (_state, _command): result<array<event>, error> => Ok([])
37
+
38
+ type lifecycleState = bookingStatus
39
+
40
+ let commandTransition = (command: command): Reventless.Transition.t<lifecycleState> => {
41
+ open Reventless.Transition
42
+ switch command {
43
+ | Book(_) => Moves([Draft], Booked)
44
+ | Rebook(_) => Guards([Booked])
45
+ | Abandon(_) => Unrestricted
46
+ }
47
+ }
48
+
49
+ // Declared, so the structure has a graft to record. The value stands in for a
50
+ // trait package's own `declaration` — a fixture cannot depend on one, and what is
51
+ // under test is the collection, not where the value came from.
52
+ let traits: array<Reventless.Trait.t> = [
53
+ {trait: "@reventlessdev/trait-booking", version: "9.9.9", posture: SelfContained},
54
+ ]
@@ -0,0 +1,104 @@
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
+
6
+ let consumedEventSchema = Sury.$schema(s => ({
7
+ TAG: "BookingDrafted",
8
+ bookingId: s.m(DcbTag$Reventless.string)
9
+ }));
10
+
11
+ function evolve(_state, _event) {
12
+ return true;
13
+ }
14
+
15
+ let commandSchema = Sury.union([
16
+ Sury.$schema(s => ({
17
+ TAG: "Book",
18
+ bookingId: s.m(DcbTag$Reventless.string)
19
+ })),
20
+ Sury.$schema(s => ({
21
+ TAG: "Rebook",
22
+ bookingId: s.m(DcbTag$Reventless.string)
23
+ })),
24
+ Sury.$schema(s => ({
25
+ TAG: "Abandon",
26
+ bookingId: s.m(DcbTag$Reventless.string)
27
+ }))
28
+ ]);
29
+
30
+ let errorSchema = Sury.literal("BookingNotFound");
31
+
32
+ let eventSchema = Sury.union([
33
+ Sury.$schema(s => ({
34
+ TAG: "BookingBooked",
35
+ bookingId: s.m(DcbTag$Reventless.string)
36
+ })),
37
+ Sury.$schema(s => ({
38
+ TAG: "BookingAbandoned",
39
+ bookingId: s.m(DcbTag$Reventless.string)
40
+ }))
41
+ ]);
42
+
43
+ function decide(_state, _command) {
44
+ return {
45
+ TAG: "Ok",
46
+ _0: []
47
+ };
48
+ }
49
+
50
+ function commandTransition(command) {
51
+ switch (command.TAG) {
52
+ case "Book" :
53
+ return {
54
+ TAG: "Moves",
55
+ _0: ["Draft"],
56
+ _1: "Booked"
57
+ };
58
+ case "Rebook" :
59
+ return {
60
+ TAG: "Guards",
61
+ _0: ["Booked"]
62
+ };
63
+ case "Abandon" :
64
+ return "Unrestricted";
65
+ }
66
+ }
67
+
68
+ let traits = [{
69
+ trait: "@reventlessdev/trait-booking",
70
+ version: "9.9.9",
71
+ posture: "SelfContained"
72
+ }];
73
+
74
+ function commandAuthorization(param) {
75
+ return "AllowAuthenticated";
76
+ }
77
+
78
+ let name = "TransitionSwitch";
79
+
80
+ let Id;
81
+
82
+ let initialState = false;
83
+
84
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs";
85
+
86
+ let readConsistency = "EscalateOnRetry";
87
+
88
+ export {
89
+ name,
90
+ Id,
91
+ consumedEventSchema,
92
+ evolve,
93
+ initialState,
94
+ commandSchema,
95
+ errorSchema,
96
+ eventSchema,
97
+ decide,
98
+ commandTransition,
99
+ traits,
100
+ moduleUrl,
101
+ commandAuthorization,
102
+ readConsistency,
103
+ }
104
+ /* 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 = "TypoStore";
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 */
@@ -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 = "UploadAvatar";
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 */
@@ -39,6 +39,12 @@ function commandAuthorization(param) {
39
39
  return "AllowAuthenticated";
40
40
  }
41
41
 
42
+ function commandTransition(param) {
43
+ return "Unrestricted";
44
+ }
45
+
46
+ let traits = [];
47
+
42
48
  let name = "UploadImages";
43
49
 
44
50
  let Id;
@@ -62,5 +68,7 @@ export {
62
68
  moduleUrl,
63
69
  commandAuthorization,
64
70
  readConsistency,
71
+ commandTransition,
72
+ traits,
65
73
  }
66
74
  /* consumedEventSchema Not a pure module */
@@ -1,4 +1,4 @@
1
- // Test fixture spec for the @transition cross-check.
1
+ // Test fixture spec for the declared-edge cross-check.
2
2
  // A view that declares a lifecycle, so a command's declared states have
3
3
  // something to be checked against. `PsOrdersView` deliberately declares none —
4
4
  // the two together cover both the checked and the unvalidated path.
@@ -105,6 +105,24 @@
105
105
  .structure.readModels[].retiredValues[]: string
106
106
  .structure.readModels[].schema: string
107
107
  .structure.readModels[].searchableFields[]: string
108
+ # `requiredCapabilities` is itself `js_nullable` and is NEW, so no persisted payload
109
+ # carries the array: a stored structure heals to null and these two are never reached.
110
+ # Required inside it because a declaration naming no capability, or no declaring
111
+ # component, is not a declaration — the same call `requiredStoreDeclarations` made for
112
+ # `store`/`component`/`field`.
113
+ .structure.requiredCapabilities[].capability: string
114
+ .structure.requiredCapabilities[].component: string
115
+ # `traitDeclarations` is itself `js_nullable` and is NEW, so no persisted payload
116
+ # carries the array: a stored structure heals to null and these four are never
117
+ # reached. Required inside it for the same reason the two above are — a graft
118
+ # naming no trait, no version, no posture or no component is not a record of a
119
+ # graft, and a fabricated `""` here would read as "grafted from nothing", which is
120
+ # worse than absent. The version is read from the trait's own package rather than
121
+ # written by hand, so it cannot be the empty string in practice either.
122
+ .structure.traitDeclarations[].component: string
123
+ .structure.traitDeclarations[].posture: string
124
+ .structure.traitDeclarations[].trait: string
125
+ .structure.traitDeclarations[].version: string
108
126
  .structure.requiredStoreDeclarations[].component: string
109
127
  .structure.requiredStoreDeclarations[].field: string
110
128
  .structure.requiredStoreDeclarations[].store: string
@@ -15,10 +15,18 @@ function commandAuthorization(param) {
15
15
  return "AllowAuthenticated";
16
16
  }
17
17
 
18
+ function commandTransition(param) {
19
+ return "Unrestricted";
20
+ }
21
+
22
+ let traits = [];
23
+
18
24
  let TestSpec = {
19
25
  name: "TestCmd",
20
26
  commandSchema: commandSchema,
21
- commandAuthorization: commandAuthorization
27
+ commandAuthorization: commandAuthorization,
28
+ commandTransition: commandTransition,
29
+ traits: traits
22
30
  };
23
31
 
24
32
  function publishCommands(_name, cmds) {
@@ -1,18 +0,0 @@
1
- // Read per-variant `allowedStates` metadata that the reventless-ppx
2
- // an `@transition` from-set attaches to a command schema. Consumed by
3
- // `Plugin_Structure.toCommandDef` when building the `commandDef` records that
4
- // land in `Platform_ComponentDefinitions` so AutoUI can filter the per-row command
5
- // menu by the row's status.
6
-
7
- open ReventlessInfra.Api
8
-
9
- /** Returns the allowed-state list for a given command-variant name, or None
10
- when the variant declares no `@transition` (the command shows on every row). */
11
- let getAllowedStates = (
12
- commandSchema: S.t<unknown>,
13
- ~variantName: string,
14
- ): option<array<string>> =>
15
- switch commandSchema->S.Metadata.get(~id=allowedStatesId) {
16
- | None => None
17
- | Some(entries) => entries->Dict.get(variantName)
18
- }
@@ -1,16 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Sury from "sury";
4
- import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
5
-
6
- function getAllowedStates(commandSchema, variantName) {
7
- let entries = Sury.$Metadata_get(commandSchema, Api$ReventlessInfra.allowedStatesId);
8
- if (entries !== undefined) {
9
- return entries[variantName];
10
- }
11
- }
12
-
13
- export {
14
- getAllowedStates,
15
- }
16
- /* sury Not a pure module */
@@ -1,21 +0,0 @@
1
- // Read per-variant `targetState` metadata that the reventless-ppx
2
- // an `@transition` target attaches to a command schema. Consumed by
3
- // `Plugin_Structure.toCommandDef` when building the `commandDef` records that
4
- // land in `Platform_ComponentDefinitions`, so AutoUI's board drag resolver can
5
- // move a row by a *declared* transition instead of a name-stem guess. Mirrors
6
- // `ApiAllowedStatesHelpers.getAllowedStates`.
7
-
8
- open ReventlessInfra.Api
9
-
10
- /** Returns the declared target state for a given command-variant name, or None
11
- when the variant declares no target — either because it carries no
12
- `@transition` at all, or because it declares a from-set only, which is a
13
- command saying it does not move the row. */
14
- let getTargetState = (
15
- commandSchema: S.t<unknown>,
16
- ~variantName: string,
17
- ): option<string> =>
18
- switch commandSchema->S.Metadata.get(~id=targetStateId) {
19
- | None => None
20
- | Some(entries) => entries->Dict.get(variantName)
21
- }
@@ -1,16 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Sury from "sury";
4
- import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
5
-
6
- function getTargetState(commandSchema, variantName) {
7
- let entries = Sury.$Metadata_get(commandSchema, Api$ReventlessInfra.targetStateId);
8
- if (entries !== undefined) {
9
- return entries[variantName];
10
- }
11
- }
12
-
13
- export {
14
- getTargetState,
15
- }
16
- /* sury Not a pure module */