@reventlessdev/reventless-spec 3.0.0-alpha.132 → 3.0.0-alpha.134
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 +14 -0
- package/package.json +2 -2
- package/src/AnsiStyle.res +0 -1
- package/src/LogPrefix.res +4 -13
- package/src/components/AutomationSlice.res +1 -5
- package/src/components/CapabilityManifest.res +2 -3
- package/src/components/DcbDecode.res +6 -2
- package/src/components/DcbScopeInference.res +16 -12
- package/src/components/DcbTag.res +74 -46
- package/src/components/DcbValidation.res +114 -89
- package/src/components/DisplayName.res +4 -2
- package/src/components/ExtensionPoint.res +0 -1
- package/src/components/FieldDefault.res +52 -0
- package/src/components/FieldDefault.res.mjs +50 -0
- package/src/components/InboundTranslationSlice.res +0 -2
- package/src/components/OutboundTranslationSlice.res +10 -8
- package/src/components/Owner.res +4 -4
- package/src/components/Plugin.res +10 -4
- package/src/components/ReadModel.res +0 -1
- package/src/components/Reference.res +2 -8
- package/src/components/Sensitive.res +4 -4
- package/src/components/StateAnnotations.res +4 -2
- package/src/components/StateChangeSlice.res +0 -2
- package/src/components/StateViewSlice.res +0 -2
- package/src/components/TaggedUnion.res +1 -2
- package/src/components/Task.res +0 -1
- package/src/components/TraitCertificate.res +2 -2
- package/src/components/TraitManifest.res +1 -1
- package/src/generator/CertifyTrait.res +2 -4
- package/src/generator/Codegen.res +77 -68
- package/src/generator/Discovery.res +29 -12
- package/src/generator/GraftTrait.res +17 -9
- package/src/generator/Pairing.res +39 -13
- package/src/generator/PlatformCodegen.res +13 -11
- package/src/generator/PlatformManifests.res +1 -3
- package/src/generator/PluginGenerator.res +0 -1
- package/src/generator/TraitManifestCli.res +7 -7
- package/src/lifecycle/CheckLifecycleModel.res +173 -145
- package/src/lifecycle/CheckLifecycleModel.res.mjs +17 -2
- package/src/semantic/Bytes.res +0 -1
- package/src/semantic/CalendarDate.res +2 -2
- package/src/semantic/Capabilities.res +4 -6
- package/src/semantic/Capabilities.res.mjs +9 -11
- package/src/semantic/CapabilityNeed.res +4 -5
- package/src/semantic/CaptionedImage.res +0 -1
- package/src/semantic/Color.res +0 -1
- package/src/semantic/Currency.res +189 -170
- package/src/semantic/DateRange.res +3 -4
- package/src/semantic/DateTime.res +5 -5
- package/src/semantic/Duration.res +2 -2
- package/src/semantic/Email.res +0 -1
- package/src/semantic/FileRef.res +2 -2
- package/src/semantic/GeoPoint.res +17 -21
- package/src/semantic/Geocoding.res +8 -9
- package/src/semantic/Geolocation.res +6 -9
- package/src/semantic/ImageRef.res +2 -2
- package/src/semantic/MemberRef.res +0 -1
- package/src/semantic/Messaging.res +141 -21
- package/src/semantic/Messaging.res.mjs +51 -8
- package/src/semantic/Money.res +23 -20
- package/src/semantic/Offload.res +6 -4
- package/src/semantic/Percent.res +3 -3
- package/src/semantic/Phone.res +0 -1
- package/src/semantic/RowImage.res +4 -3
- package/src/semantic/Semantic.res +8 -11
- package/src/semantic/StorageRef.res +17 -17
- package/src/semantic/Template.res +5 -7
- package/src/semantic/UploadableFile.res +0 -1
- package/src/semantic/UploadableImage.res +0 -1
- package/src/semantic/Url.res +3 -3
- package/src/types/Authorization.res +1 -2
- package/src/types/Handler.res +0 -1
- package/src/types/Identity.res +1 -3
- package/src/types/Lifecycle.res +7 -6
- package/src/types/Message.res +6 -4
- package/src/types/OwnerScope.res +1 -3
- package/src/types/Projection.res +9 -2
- package/src/types/StoredEvent.res +2 -4
- package/src/types/Transition.res +8 -4
- package/src/util/Util_Sury.res +1 -4
package/src/semantic/Url.res
CHANGED
|
@@ -24,7 +24,6 @@ they actually hold and render correctly on their own.
|
|
|
24
24
|
})
|
|
25
25
|
```
|
|
26
26
|
*/
|
|
27
|
-
|
|
28
27
|
/** The address's representation. Transparent `string`; see `Email.t`. */
|
|
29
28
|
type t = string
|
|
30
29
|
|
|
@@ -56,8 +55,9 @@ let fromString = (raw: string): result<t, string> =>
|
|
|
56
55
|
Ok(value)
|
|
57
56
|
} else {
|
|
58
57
|
Error(
|
|
59
|
-
`a URL field takes an http:// or https:// address, got ${Semantic.showString(
|
|
60
|
-
|
|
58
|
+
`a URL field takes an http:// or https:// address, got ${Semantic.showString(
|
|
59
|
+
raw,
|
|
60
|
+
)}. ` ++ `Use Email or Phone for mailto:/tel:, and a storage ref for an uploaded object.`,
|
|
61
61
|
)
|
|
62
62
|
}
|
|
63
63
|
| exception _ =>
|
|
@@ -18,6 +18,5 @@ let isAllowed = (rule: permission, identity: Identity.t): bool =>
|
|
|
18
18
|
| DenyAll => false
|
|
19
19
|
| AllowAnonymous => true
|
|
20
20
|
| AllowAuthenticated => identity.userId !== "anonymous"
|
|
21
|
-
| AllowGroups(groups) =>
|
|
22
|
-
groups->Array.some(group => identity.groups->Array.includes(group))
|
|
21
|
+
| AllowGroups(groups) => groups->Array.some(group => identity.groups->Array.includes(group))
|
|
23
22
|
}
|
package/src/types/Handler.res
CHANGED
package/src/types/Identity.res
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
/** Identity provider that authenticated the user. */
|
|
3
2
|
@schema
|
|
4
3
|
type provider = Cognito | InMemory | Custom(string)
|
|
@@ -25,8 +24,7 @@ let anonymous: t = {
|
|
|
25
24
|
provider: InMemory,
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
let hasGroup = (identity: t, group: string): bool =>
|
|
29
|
-
identity.groups->Array.includes(group)
|
|
27
|
+
let hasGroup = (identity: t, group: string): bool => identity.groups->Array.includes(group)
|
|
30
28
|
|
|
31
29
|
let getClaim = (identity: t, key: string): option<string> =>
|
|
32
30
|
switch identity.claims {
|
package/src/types/Lifecycle.res
CHANGED
|
@@ -6,10 +6,9 @@ consumer resolves it here rather than restating it. `Trail` is the one field a
|
|
|
6
6
|
view declares to have each state it reaches recorded with the instant it was
|
|
7
7
|
reached; the projection machinery fills it, not the domain.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
// A wire enum: a union whose non-null members are all string constants. A
|
|
9
|
+
let // A wire enum: a union whose non-null members are all string constants. A
|
|
11
10
|
// tagged union's members are objects, so the same test excludes it.
|
|
12
|
-
|
|
11
|
+
isEnumSchema = (schema: S.t<unknown>): bool =>
|
|
13
12
|
switch schema {
|
|
14
13
|
| AnyOf({anyOf}) =>
|
|
15
14
|
let members = anyOf->Array.filter(v =>
|
|
@@ -80,8 +79,7 @@ module Trail = {
|
|
|
80
79
|
let schema = (stateSchema: S.t<'state>): S.t<t<'state>> =>
|
|
81
80
|
S.array(entrySchema(stateSchema))->Semantic.mark(~id=Semantic.Id.lifecycleTrail)
|
|
82
81
|
|
|
83
|
-
let isTrail = (schema: S.t<unknown>): bool =>
|
|
84
|
-
Semantic.has(schema, ~id=Semantic.Id.lifecycleTrail)
|
|
82
|
+
let isTrail = (schema: S.t<unknown>): bool => Semantic.has(schema, ~id=Semantic.Id.lifecycleTrail)
|
|
85
83
|
|
|
86
84
|
/** The trail field declared on a state record, if it declares one. */
|
|
87
85
|
let fieldName = (stateSchema: S.t<unknown>): option<string> =>
|
|
@@ -101,6 +99,9 @@ module Trail = {
|
|
|
101
99
|
| _ => []
|
|
102
100
|
}
|
|
103
101
|
let entry = Dict.fromArray([("state", state), ("at", JSON.Encode.string(at))])
|
|
104
|
-
stateDict->Dict.set(
|
|
102
|
+
stateDict->Dict.set(
|
|
103
|
+
field,
|
|
104
|
+
entries->Array.concat([entry->JSON.Encode.object])->JSON.Encode.array,
|
|
105
|
+
)
|
|
105
106
|
}
|
|
106
107
|
}
|
package/src/types/Message.res
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
/** Identifies the service that produced or is addressed by a message. */
|
|
3
2
|
@schema
|
|
4
3
|
type service = string
|
|
@@ -179,7 +178,11 @@ type commandJson = {
|
|
|
179
178
|
//
|
|
180
179
|
// `scalarFills` is an out-parameter: the walker pushes `path := value` for each scalar it
|
|
181
180
|
// invented.
|
|
182
|
-
let fillMissingDefaults: (
|
|
181
|
+
let fillMissingDefaults: (
|
|
182
|
+
S.t<'a>,
|
|
183
|
+
JSON.t,
|
|
184
|
+
array<string>,
|
|
185
|
+
) => JSON.t = %raw(`function(schema, json, scalarFills){
|
|
183
186
|
function isSchema(x){ return x && typeof x === "object" && typeof x.type === "string"; }
|
|
184
187
|
function firstConst(anyOf){ var m=(anyOf||[]).find(function(s){return s.const!==undefined;}); return m ? m.const : undefined; }
|
|
185
188
|
// Which object-typed member of an anyOf a plain (untagged) object value belongs to.
|
|
@@ -274,8 +277,7 @@ let parseJsonTolerant = (json, schema) =>
|
|
|
274
277
|
->Array.length
|
|
275
278
|
->Int.toString} missing scalar field(s): ${scalarFills->Array.join(
|
|
276
279
|
", ",
|
|
277
|
-
)}. A required scalar was added to a persisted type after this message was ` ++
|
|
278
|
-
`written; the value above is fabricated, not recovered. Prefer an optional field.`,
|
|
280
|
+
)}. 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.`,
|
|
279
281
|
)
|
|
280
282
|
}
|
|
281
283
|
value
|
package/src/types/OwnerScope.res
CHANGED
|
@@ -20,7 +20,6 @@ fields this module reads are typed non-optional and are, at runtime, sometimes
|
|
|
20
20
|
absent. Every read here goes through a nullable cast for that reason; deleting
|
|
21
21
|
one restores a silent failure rather than a type error.
|
|
22
22
|
*/
|
|
23
|
-
|
|
24
23
|
/** Whether a JS value is a primitive string — `Cognito` and `InMemory` compile to
|
|
25
24
|
bare strings while `Custom(_)` compiles to an object, so this is how a modelled
|
|
26
25
|
provider is told from an unmodelled one that arrived as raw JSON. */
|
|
@@ -135,8 +134,7 @@ let classify = (identity: Identity.t, ~elevated: array<string>): t => {
|
|
|
135
134
|
switch identity.userId->asNullableString->Nullable.toOption {
|
|
136
135
|
| None => Unidentified("identity carries no userId")
|
|
137
136
|
| Some("") => Unidentified("identity carries an empty userId")
|
|
138
|
-
| Some(userId) if userId == Identity.anonymous.userId =>
|
|
139
|
-
Unidentified("caller is anonymous")
|
|
137
|
+
| Some(userId) if userId == Identity.anonymous.userId => Unidentified("caller is anonymous")
|
|
140
138
|
| Some(userId) =>
|
|
141
139
|
let groups = identity.groups->asNullableArray->Nullable.toOption->Option.getOr([])
|
|
142
140
|
groups->Array.some(g => elevated->Array.includes(g))
|
package/src/types/Projection.res
CHANGED
|
@@ -145,8 +145,15 @@ module Mapping = {
|
|
|
145
145
|
module Make = (
|
|
146
146
|
Source: Source,
|
|
147
147
|
Target: Target,
|
|
148
|
-
MappingImpl: MappingImpl
|
|
149
|
-
|
|
148
|
+
MappingImpl: MappingImpl
|
|
149
|
+
with type sourceEvent := Source.event
|
|
150
|
+
and type targetState := Target.state,
|
|
151
|
+
): (
|
|
152
|
+
Mapping
|
|
153
|
+
with type targetState = Target.state
|
|
154
|
+
and type sourceEvent = Source.event
|
|
155
|
+
and module SourceId = Source.Id
|
|
156
|
+
) => {
|
|
150
157
|
module SourceId = Source.Id
|
|
151
158
|
@schema
|
|
152
159
|
type sourceEvent = Source.event
|
|
@@ -38,9 +38,7 @@ let toStoredEventSchema = (idSchema: S.t<'id>): S.t<storedEvent<'id>> =>
|
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
/** Decode a `storedEvent<'id>` from JSON. */
|
|
41
|
-
let decode = (json, idSchema) =>
|
|
42
|
-
json->Util_Sury.fromJson(toStoredEventSchema(idSchema))
|
|
41
|
+
let decode = (json, idSchema) => json->Util_Sury.fromJson(toStoredEventSchema(idSchema))
|
|
43
42
|
|
|
44
43
|
/** Encode a `storedEvent<'id>` to JSON. */
|
|
45
|
-
let encode = (stored, idSchema) =>
|
|
46
|
-
stored->Util_Sury.toJson(toStoredEventSchema(idSchema))
|
|
44
|
+
let encode = (stored, idSchema) => stored->Util_Sury.toJson(toStoredEventSchema(idSchema))
|
package/src/types/Transition.res
CHANGED
|
@@ -69,9 +69,11 @@ let allowedStates = (transition: t<'state>): option<array<'state>> =>
|
|
|
69
69
|
switch transition {
|
|
70
70
|
| Undeclared
|
|
71
71
|
| Unrestricted
|
|
72
|
-
| Creates(_) =>
|
|
72
|
+
| Creates(_) =>
|
|
73
|
+
None
|
|
73
74
|
| Guards(states)
|
|
74
|
-
| Moves(states, _) =>
|
|
75
|
+
| Moves(states, _) =>
|
|
76
|
+
Some(states)
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
/** The state the command's handler writes, or `None` for one that moves nothing. */
|
|
@@ -79,9 +81,11 @@ let targetState = (transition: t<'state>): option<'state> =>
|
|
|
79
81
|
switch transition {
|
|
80
82
|
| Undeclared
|
|
81
83
|
| Unrestricted
|
|
82
|
-
| Guards(_) =>
|
|
84
|
+
| Guards(_) =>
|
|
85
|
+
None
|
|
83
86
|
| Creates(state)
|
|
84
|
-
| Moves(_, state) =>
|
|
87
|
+
| Moves(_, state) =>
|
|
88
|
+
Some(state)
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
/** Whether the command is claimed legal in every state, as opposed to nothing
|
package/src/util/Util_Sury.res
CHANGED
|
@@ -11,10 +11,7 @@ let toJson: ('a, S.t<'a>) => JSON.t = (value, schema) =>
|
|
|
11
11
|
|
|
12
12
|
// `~space` defaults to compact, matching the removed `reverseConvertToJsonStringOrThrow`.
|
|
13
13
|
let toJsonString = (value: 'a, schema: S.t<'a>, ~space: int=0): string =>
|
|
14
|
-
value->S.decodeOrThrow(
|
|
15
|
-
~from=schema,
|
|
16
|
-
~to=space == 0 ? S.jsonString : S.jsonStringWithSpace(space),
|
|
17
|
-
)
|
|
14
|
+
value->S.decodeOrThrow(~from=schema, ~to=space == 0 ? S.jsonString : S.jsonStringWithSpace(space))
|
|
18
15
|
|
|
19
16
|
let fromJson: (JSON.t, S.t<'a>) => 'a = (json, schema) => json->S.parseOrThrow(~to=schema)
|
|
20
17
|
|