@reventlessdev/reventless-spec 3.0.0-alpha.128 → 3.0.0-alpha.130
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 +56 -0
- package/package.json +2 -2
- package/schema/platform-api.graphql +1 -0
- package/src/AnsiStyle.res +31 -7
- package/src/AnsiStyle.res.mjs +16 -2
- package/src/components/DcbTag.res +229 -32
- package/src/components/DcbTag.res.mjs +232 -41
- package/src/components/Plugin.res +106 -89
- package/src/components/Plugin.res.mjs +47 -82
- package/src/components/Reference.res +48 -0
- package/src/components/Reference.res.mjs +28 -0
- package/src/generator/Codegen.res +14 -1
- package/src/generator/Codegen.res.mjs +9 -5
- package/src/generator/GraftTrait.res +5 -4
- package/src/generator/GraftTrait.res.mjs +4 -4
- package/src/generator/PluginGenerator.res +4 -1
- package/src/generator/PluginGenerator.res.mjs +2 -1
- package/src/types/Message.res +14 -12
- package/src/types/Message.res.mjs +2 -1
- package/src/types/Transition.res +30 -3
- package/src/types/Transition.res.mjs +13 -4
package/src/types/Message.res
CHANGED
|
@@ -141,22 +141,23 @@ type commandJson = {
|
|
|
141
141
|
|
|
142
142
|
// ── Schema-migration-on-read ──────────────────────────────────────────────────
|
|
143
143
|
// Nested `@schema` types (notably `pluginDefinition`/`pluginStructure`) gain fields
|
|
144
|
-
// over time — `kind`, `chapter`, `events`, `extensionPoints`, `apiExposed`, …
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
// an aggregate that rehydrates from its own event log (the Plugin lifecycle aggregate),
|
|
151
|
-
// that single event then freezes EVERY later heartbeat/redetect/connect on that instance
|
|
152
|
-
// — a silent lifecycle freeze with no error surfaced near the operator.
|
|
144
|
+
// over time — `kind`, `chapter`, `events`, `extensionPoints`, `apiExposed`, … A field
|
|
145
|
+
// that is not optional is *present-required on decode*, so ONE message persisted before
|
|
146
|
+
// it was added SuryError-bricks decode. For an aggregate that rehydrates from its own
|
|
147
|
+
// event log (the Plugin lifecycle aggregate), that single event then freezes EVERY later
|
|
148
|
+
// heartbeat/redetect/connect on that instance — a silent lifecycle freeze with no error
|
|
149
|
+
// surfaced near the operator.
|
|
153
150
|
//
|
|
154
151
|
// We heal on read. Strict decode stays the fast path (unchanged for every current
|
|
155
152
|
// message); only when it throws do we schema-guide the raw JSON and retry once. The fill
|
|
156
153
|
// walks the target sury schema and inserts, for any absent field, the value that field's
|
|
157
|
-
// schema expects: `null` for a `T | null` union (→ `None`),
|
|
154
|
+
// schema expects: `null` for a `T | null` union (→ `None`), nothing at all for an
|
|
155
|
+
// `option` (a union admitting `undefined` — also `None`), `[]` for a missing array, the
|
|
158
156
|
// first variant of a mandatory enum (`kind` → `Domain`), a filled `{}` for a missing
|
|
159
|
-
// nested object, and a zero value for a missing scalar.
|
|
157
|
+
// nested object, and a zero value for a missing scalar. The `undefined` arm mirrors the
|
|
158
|
+
// `null` one and must precede the enum/object guesses below it: an absent `option<enum>`
|
|
159
|
+
// would otherwise heal to that enum's first variant and an absent `option<record>` to a
|
|
160
|
+
// filled `{}`, turning `None` into a `Some` of an invented value. It descends only into values
|
|
160
161
|
// actually present, matches tagged-union members by their `TAG` const, is purely additive
|
|
161
162
|
// (clones via a JSON round-trip; never re-encodes through the schema), is idempotent on
|
|
162
163
|
// valid data, and falls back to the ORIGINAL error when the fill doesn't resolve the
|
|
@@ -229,6 +230,7 @@ let fillMissingDefaults: (S.t<'a>, JSON.t, array<string>) => JSON.t = %raw(`func
|
|
|
229
230
|
var has=schema.has||{};
|
|
230
231
|
if(value===undefined){
|
|
231
232
|
if(has.null) return null;
|
|
233
|
+
if(has.undefined) return undefined;
|
|
232
234
|
var c=firstConst(schema.anyOf); if(c!==undefined) return c;
|
|
233
235
|
var obj=(schema.anyOf||[]).find(function(s){return s.type==="object";}); if(obj) return fill(obj,{},path);
|
|
234
236
|
return undefined;
|
|
@@ -273,7 +275,7 @@ let parseJsonTolerant = (json, schema) =>
|
|
|
273
275
|
->Int.toString} missing scalar field(s): ${scalarFills->Array.join(
|
|
274
276
|
", ",
|
|
275
277
|
)}. A required scalar was added to a persisted type after this message was ` ++
|
|
276
|
-
`written; the value above is fabricated, not recovered. Prefer
|
|
278
|
+
`written; the value above is fabricated, not recovered. Prefer an optional field.`,
|
|
277
279
|
)
|
|
278
280
|
}
|
|
279
281
|
value
|
|
@@ -87,6 +87,7 @@ let fillMissingDefaults = (function(schema, json, scalarFills){
|
|
|
87
87
|
var has=schema.has||{};
|
|
88
88
|
if(value===undefined){
|
|
89
89
|
if(has.null) return null;
|
|
90
|
+
if(has.undefined) return undefined;
|
|
90
91
|
var c=firstConst(schema.anyOf); if(c!==undefined) return c;
|
|
91
92
|
var obj=(schema.anyOf||[]).find(function(s){return s.type==="object";}); if(obj) return fill(obj,{},path);
|
|
92
93
|
return undefined;
|
|
@@ -126,7 +127,7 @@ function parseJsonTolerant(json, schema) {
|
|
|
126
127
|
throw firstErr;
|
|
127
128
|
}
|
|
128
129
|
if (scalarFills.length !== 0) {
|
|
129
|
-
console.warn(`[reventless] decoded a stored message by inventing ` + scalarFills.length.toString() + ` missing scalar field(s): ` + scalarFills.join(", ") + `. A required scalar was added to a persisted type after this message was written; the value above is fabricated, not recovered. Prefer
|
|
130
|
+
console.warn(`[reventless] decoded a stored message by inventing ` + scalarFills.length.toString() + ` missing scalar field(s): ` + scalarFills.join(", ") + `. A required scalar was added to a persisted type after this message was written; the value above is fabricated, not recovered. Prefer an optional field.`);
|
|
130
131
|
}
|
|
131
132
|
return value;
|
|
132
133
|
}
|
package/src/types/Transition.res
CHANGED
|
@@ -36,10 +36,23 @@
|
|
|
36
36
|
// plugin structure is assembled, and what leaves is the pair of names the
|
|
37
37
|
// structure already carried.
|
|
38
38
|
type t<'state> =
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
/** Legal in every state, and moves the row nowhere. The honest answer for a
|
|
40
|
+
report a slice publishes, which must not be refused because the row moved
|
|
41
|
+
on while the report was in flight. A claim, not an omission — see
|
|
42
|
+
`Undeclared`, which is the omission. */
|
|
42
43
|
| Unrestricted
|
|
44
|
+
/** The spec wrote no switch, and the ppx injected this. Never write it: say
|
|
45
|
+
`Unrestricted` if you mean the command is legal everywhere.
|
|
46
|
+
|
|
47
|
+
It reads exactly like `Unrestricted` — no from-set, no target — everywhere
|
|
48
|
+
but one place, and that place is why it exists. The harvested lifecycle
|
|
49
|
+
model may answer for silence; it may not narrow a claim. A corpus only
|
|
50
|
+
covers the states somebody wrote a scenario for, so letting it answer for
|
|
51
|
+
`Unrestricted` would shrink "legal in every state" down to an accident of
|
|
52
|
+
coverage, and the command would quietly stop being offered on the rows
|
|
53
|
+
nobody tested. With the two spelled apart, that shrinkage cannot happen and
|
|
54
|
+
a scenario that genuinely refutes the claim is a contradiction instead. */
|
|
55
|
+
| Undeclared
|
|
43
56
|
/** Brings the row into existence, so there is no state it could come from.
|
|
44
57
|
Distinct from `Unrestricted`, which draws no edge at all. */
|
|
45
58
|
| Creates('state)
|
|
@@ -54,6 +67,7 @@ type t<'state> =
|
|
|
54
67
|
tells apart. */
|
|
55
68
|
let allowedStates = (transition: t<'state>): option<array<'state>> =>
|
|
56
69
|
switch transition {
|
|
70
|
+
| Undeclared
|
|
57
71
|
| Unrestricted
|
|
58
72
|
| Creates(_) => None
|
|
59
73
|
| Guards(states)
|
|
@@ -63,8 +77,21 @@ let allowedStates = (transition: t<'state>): option<array<'state>> =>
|
|
|
63
77
|
/** The state the command's handler writes, or `None` for one that moves nothing. */
|
|
64
78
|
let targetState = (transition: t<'state>): option<'state> =>
|
|
65
79
|
switch transition {
|
|
80
|
+
| Undeclared
|
|
66
81
|
| Unrestricted
|
|
67
82
|
| Guards(_) => None
|
|
68
83
|
| Creates(state)
|
|
69
84
|
| Moves(_, state) => Some(state)
|
|
70
85
|
}
|
|
86
|
+
|
|
87
|
+
/** Whether the command is claimed legal in every state, as opposed to nothing
|
|
88
|
+
being claimed at all. The two erase to the same pair of `None`s above, so this
|
|
89
|
+
is the only thing that can tell a reader of the erased form which it holds. */
|
|
90
|
+
let isUnrestricted = (transition: t<'state>): bool =>
|
|
91
|
+
switch transition {
|
|
92
|
+
| Unrestricted => true
|
|
93
|
+
| Undeclared
|
|
94
|
+
| Creates(_)
|
|
95
|
+
| Guards(_)
|
|
96
|
+
| Moves(_, _) => false
|
|
97
|
+
}
|
|
@@ -7,11 +7,11 @@ function allowedStates(transition) {
|
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
9
|
switch (transition.TAG) {
|
|
10
|
-
case "Creates" :
|
|
11
|
-
return;
|
|
12
10
|
case "Guards" :
|
|
13
11
|
case "Moves" :
|
|
14
12
|
return transition._0;
|
|
13
|
+
default:
|
|
14
|
+
return;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -22,15 +22,24 @@ function targetState(transition) {
|
|
|
22
22
|
switch (transition.TAG) {
|
|
23
23
|
case "Creates" :
|
|
24
24
|
return Primitive_option.some(transition._0);
|
|
25
|
-
case "Guards" :
|
|
26
|
-
return;
|
|
27
25
|
case "Moves" :
|
|
28
26
|
return Primitive_option.some(transition._1);
|
|
27
|
+
default:
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isUnrestricted(transition) {
|
|
33
|
+
if (typeof transition !== "object") {
|
|
34
|
+
return transition === "Unrestricted";
|
|
35
|
+
} else {
|
|
36
|
+
return false;
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
export {
|
|
33
41
|
allowedStates,
|
|
34
42
|
targetState,
|
|
43
|
+
isUnrestricted,
|
|
35
44
|
}
|
|
36
45
|
/* No side effect */
|