@reventlessdev/reventless-spec 3.0.0-alpha.124 → 3.0.0-alpha.125

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 (37) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/package.json +5 -2
  3. package/run-certify-trait.mjs +2 -0
  4. package/run-graft-trait.mjs +2 -0
  5. package/run-trait-manifest.mjs +2 -0
  6. package/schema/platform-api.graphql +17 -3
  7. package/src/components/Aggregate.res +22 -0
  8. package/src/components/AutomationSlice.res +29 -3
  9. package/src/components/CapabilityManifest.res +52 -24
  10. package/src/components/CapabilityManifest.res.mjs +35 -11
  11. package/src/components/InboundTranslationSlice.res +14 -0
  12. package/src/components/OutboundTranslationSlice.res +24 -0
  13. package/src/components/Plugin.res +53 -0
  14. package/src/components/Plugin.res.mjs +23 -1
  15. package/src/components/StateChangeSlice.res +22 -0
  16. package/src/components/TraitCertificate.res +105 -0
  17. package/src/components/TraitCertificate.res.mjs +65 -0
  18. package/src/components/TraitManifest.res +90 -0
  19. package/src/components/TraitManifest.res.mjs +48 -0
  20. package/src/generator/CertifyTrait.res +190 -0
  21. package/src/generator/CertifyTrait.res.mjs +154 -0
  22. package/src/generator/GraftTrait.res +230 -0
  23. package/src/generator/GraftTrait.res.mjs +193 -0
  24. package/src/generator/PlatformCodegen.res +44 -30
  25. package/src/generator/PlatformCodegen.res.mjs +36 -17
  26. package/src/generator/TraitManifestCli.res +138 -0
  27. package/src/generator/TraitManifestCli.res.mjs +105 -0
  28. package/src/semantic/Capabilities.res +19 -3
  29. package/src/semantic/Capabilities.res.mjs +18 -2
  30. package/src/semantic/CapabilityNeed.res +81 -0
  31. package/src/semantic/CapabilityNeed.res.mjs +46 -0
  32. package/src/semantic/Messaging.res +127 -0
  33. package/src/semantic/Messaging.res.mjs +57 -0
  34. package/src/types/Trait.res +62 -0
  35. package/src/types/Trait.res.mjs +18 -0
  36. package/src/types/Transition.res +71 -0
  37. package/src/types/Transition.res.mjs +36 -0
@@ -0,0 +1,62 @@
1
+ // What a domain trait says about itself, so that a graft leaves a trace.
2
+ //
3
+ // A graft becomes ordinary host source — that is the design, and it is why every
4
+ // other signal a trait leaves is source-side: the package dependency, the variant
5
+ // spread, the `module X = Trait_Rules` alias, the conformance binding under
6
+ // `tests/`. None of them survives into a deployed plugin, so a running estate
7
+ // cannot answer "which of my components came from a trait" at all.
8
+ //
9
+ // This is the one fact that does survive, because it travels the way
10
+ // `capabilityNeeds` does: a value the trait exports and the host names, collected
11
+ // into `pluginStructure` while it is assembled and re-emitted whole on every
12
+ // registration.
13
+ //
14
+ // **Nothing here is typed by a human.** The trait exports its own identity, so a
15
+ // renamed or removed trait is a build error rather than a stale row; the version
16
+ // is read from the trait's own package rather than restated; and the component is
17
+ // filled in by the structure, which is the only party that knows which component
18
+ // declared it. That is the whole reason this is a value rather than an
19
+ // annotation — an attribute's fields would all be strings the compiler never
20
+ // checks, which is the failure this program exists to remove.
21
+ //
22
+ // **A declaration is a claim about origin, never about behaviour.** After a graft
23
+ // the developer owns the files and may edit them freely. So this says "grafted
24
+ // from trait X", and it does NOT say "still behaves like trait X" — the thing that
25
+ // answers the second question is the trait's conformance suite, which runs in the
26
+ // consumer's build and reports separately. A reader that paints a declared graft
27
+ // as verified is drawing a conclusion this field cannot support.
28
+
29
+ /** Whether the graft reports back into the host it is grafted onto.
30
+
31
+ `WritesBack` publishes commands to its host — the geocoding shape, where the
32
+ slice reports its answer back onto the aggregate. `Observes` reads host events
33
+ and writes nothing back. `SelfContained` brings its own components and grafts
34
+ only by reading — the notification shape, which is what broke the
35
+ write-back assumption the first two specimens shared. */
36
+ type posture =
37
+ | WritesBack
38
+ | Observes
39
+ | SelfContained
40
+
41
+ let postureToString = (p: posture): string =>
42
+ switch p {
43
+ | WritesBack => "WritesBack"
44
+ | Observes => "Observes"
45
+ | SelfContained => "SelfContained"
46
+ }
47
+
48
+ /**
49
+ One trait's own account of itself, exported by the trait package.
50
+
51
+ `version` is read from the trait's package at load time rather than restated in
52
+ source — see `PackageVersion.fromModuleUrl`, which the certification CLI already
53
+ resolves trait versions with. A trait whose package.json cannot be found reports
54
+ `"0.0.0"`, which is visibly wrong rather than quietly stale.
55
+ */
56
+ type t = {
57
+ /** The package, as it is depended on: `"@reventlessdev/trait-attachments"`. */
58
+ trait: string,
59
+ /** Resolved from the trait's own package, never written by hand. */
60
+ version: string,
61
+ posture: posture,
62
+ }
@@ -0,0 +1,18 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function postureToString(p) {
5
+ switch (p) {
6
+ case "WritesBack" :
7
+ return "WritesBack";
8
+ case "Observes" :
9
+ return "Observes";
10
+ case "SelfContained" :
11
+ return "SelfContained";
12
+ }
13
+ }
14
+
15
+ export {
16
+ postureToString,
17
+ }
18
+ /* No side effect */
@@ -0,0 +1,71 @@
1
+ // The lifecycle edge a command owns, declared as a value rather than as an
2
+ // attribute on the constructor.
3
+ //
4
+ // `@transition([Orders.Placed] => Orders.Shipped)` says the same thing and is
5
+ // still the shorter spelling for a command a host declares itself. It cannot say
6
+ // it for a command a host did NOT declare: a variant spread splices members,
7
+ // while the annotation lowers to a dict on the parent union, so a spliced
8
+ // command arrives carrying no edge at all. Nor can the annotation be checked —
9
+ // the PPX extracts leaf identifiers as strings, and the states belong to another
10
+ // component's enum, so a misspelling survives to the plugin structure.
11
+ //
12
+ // A `command => t<'state>` switch answers both. It is exhaustive, so a spliced
13
+ // constructor is a compile error until the host says what it does; and `'state`
14
+ // is the view's own lifecycle enum, so `Customers.Active` is a constructor the
15
+ // compiler resolves rather than a string nobody reads.
16
+ //
17
+ // `'state` is one type across the whole switch, which is a third thing the
18
+ // annotation cannot do: every arm of one component's edges must name the same
19
+ // lifecycle, and a from-set drawn from one enum with a target from another does
20
+ // not compile.
21
+ //
22
+ // The type stays parameterised all the way down rather than storing names,
23
+ // because erasing a constructor to its own name means asserting its runtime
24
+ // representation — and this is the module that exists so nothing has to be
25
+ // asserted. The erasure happens once, at the framework's type-erasure boundary
26
+ // (`Plugin_Structure`), which already reads every spec member that way.
27
+ //
28
+ // The reference costs nothing at run time. A lifecycle enum's arms are
29
+ // payload-less, so `[Customers.Active]` compiles to `["Active"]` and the
30
+ // generated module imports nothing from the view — which is also why it cannot
31
+ // cycle: a view spec holds no reference back to the aggregate it projects.
32
+ //
33
+ // Read the same way `commandAuthorization` is: `Plugin_Structure.toCommandDef`
34
+ // evaluates it against a synthetic value per constructor.
35
+ //
36
+ // No `@schema`: nothing serialises a transition. It is read once, while the
37
+ // plugin structure is assembled, and what leaves is the pair of names the
38
+ // structure already carried.
39
+ type t<'state> =
40
+ /** No edge declared: legal in every state, moves the row nowhere. The honest
41
+ answer for a report a slice publishes, which must not be refused because
42
+ the row moved on while the report was in flight. */
43
+ | Unrestricted
44
+ /** Brings the row into existence, so there is no state it could come from.
45
+ Distinct from `Unrestricted`, which draws no edge at all. */
46
+ | Creates('state)
47
+ /** Legal in these states, and moves the row nowhere. A positive claim rather
48
+ than an omission. */
49
+ | Guards(array<'state>)
50
+ /** Legal in these states, and lands the row in that one. */
51
+ | Moves(array<'state>, 'state)
52
+
53
+ /** The from-set, or `None` for a command that names no states to come from —
54
+ which `Creates` and `Unrestricted` both do, for different reasons the target
55
+ tells apart. */
56
+ let allowedStates = (transition: t<'state>): option<array<'state>> =>
57
+ switch transition {
58
+ | Unrestricted
59
+ | Creates(_) => None
60
+ | Guards(states)
61
+ | Moves(states, _) => Some(states)
62
+ }
63
+
64
+ /** The state the command's handler writes, or `None` for one that moves nothing. */
65
+ let targetState = (transition: t<'state>): option<'state> =>
66
+ switch transition {
67
+ | Unrestricted
68
+ | Guards(_) => None
69
+ | Creates(state)
70
+ | Moves(_, state) => Some(state)
71
+ }
@@ -0,0 +1,36 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
4
+
5
+ function allowedStates(transition) {
6
+ if (typeof transition !== "object") {
7
+ return;
8
+ }
9
+ switch (transition.TAG) {
10
+ case "Creates" :
11
+ return;
12
+ case "Guards" :
13
+ case "Moves" :
14
+ return transition._0;
15
+ }
16
+ }
17
+
18
+ function targetState(transition) {
19
+ if (typeof transition !== "object") {
20
+ return;
21
+ }
22
+ switch (transition.TAG) {
23
+ case "Creates" :
24
+ return Primitive_option.some(transition._0);
25
+ case "Guards" :
26
+ return;
27
+ case "Moves" :
28
+ return Primitive_option.some(transition._1);
29
+ }
30
+ }
31
+
32
+ export {
33
+ allowedStates,
34
+ targetState,
35
+ }
36
+ /* No side effect */