@reventlessdev/reventless-spec 3.0.0-alpha.169 → 3.0.0-alpha.170
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/README.md +17 -3
- package/package.json +5 -4
- package/run-rename-to-decision.mjs +3 -0
- package/src/AnsiStyle.res +3 -3
- package/src/CliArgs.res +1 -1
- package/src/LogPrefix.res +1 -1
- package/src/codemod/RenameToDecision.res +207 -0
- package/src/codemod/RenameToDecision.res.mjs +334 -0
- package/src/components/Aggregate.res +1 -1
- package/src/components/CapabilityManifest.res +1 -1
- package/src/components/ComponentKind.res +2 -2
- package/src/components/ComponentKind.res.mjs +1 -1
- package/src/components/DcbScopeInference.res +2 -2
- package/src/components/DcbTag.res +5 -5
- package/src/components/OutboundTranslationSlice.res +2 -2
- package/src/components/Plugin.res +2 -2
- package/src/components/Sensitive.res +1 -1
- package/src/components/Snapshot.res +5 -5
- package/src/components/StateChangeSlice.res +6 -5
- package/src/components/TaggedUnion.res +1 -1
- package/src/generator/Codegen.res +5 -5
- package/src/generator/Codegen.res.mjs +1 -1
- package/src/generator/Discovery.res +3 -3
- package/src/generator/Pairing.res +47 -18
- package/src/generator/Pairing.res.mjs +41 -10
- package/src/lifecycle/CheckLifecycleModel.res +3 -3
- package/src/semantic/Capabilities.res +2 -2
- package/src/semantic/CapabilityNeed.res +3 -3
- package/src/semantic/Color.res +8 -8
- package/src/semantic/IdentityProvider.res +1 -1
- package/src/semantic/Messaging.res +2 -2
- package/src/types/{Behavior.res → Decision.res} +10 -6
- package/src/types/Message.res +1 -1
- package/src/types/OwnerScope.res +5 -5
- package/src/types/Trait.res +1 -1
- /package/src/types/{Behavior.res.mjs → Decision.res.mjs} +0 -0
package/src/semantic/Color.res
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Marks a `string` field as a
|
|
2
|
+
Marks a `string` field as a color, written as a hex triplet.
|
|
3
3
|
|
|
4
4
|
## Why hex only
|
|
5
5
|
|
|
6
6
|
A field carrying this semantic is rendered as a swatch by setting the value as a
|
|
7
|
-
CSS `background`. CSS accepts far more than a
|
|
8
|
-
`var(…)` — so "any CSS colour" would make a
|
|
7
|
+
CSS `background`. CSS accepts far more than a color there — `url(…)`, gradients,
|
|
8
|
+
`var(…)` — so "any CSS colour" would make a color field a way to write arbitrary
|
|
9
9
|
CSS into a log that cannot be edited afterwards. Hex is the form that is a
|
|
10
|
-
|
|
10
|
+
color and nothing else, and it is what a color picker emits anyway.
|
|
11
11
|
|
|
12
|
-
Named
|
|
12
|
+
Named colors (`rebeccapurple`) and functional forms (`rgb(…)`, `oklch(…)`) are
|
|
13
13
|
rejected for the same reason, not because they are worse notation.
|
|
14
14
|
|
|
15
15
|
## The grammar
|
|
@@ -26,7 +26,7 @@ full triplet, and the triplet with alpha. Case is not significant.
|
|
|
26
26
|
})
|
|
27
27
|
```
|
|
28
28
|
*/
|
|
29
|
-
/** The
|
|
29
|
+
/** The color's representation. Transparent `string`; see `Email.t`. */
|
|
30
30
|
type t = string
|
|
31
31
|
|
|
32
32
|
external unsafe: string => t = "%identity"
|
|
@@ -34,7 +34,7 @@ external toString: t => string = "%identity"
|
|
|
34
34
|
|
|
35
35
|
let hex = /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/
|
|
36
36
|
|
|
37
|
-
/** Validate a raw string as a hex
|
|
37
|
+
/** Validate a raw string as a hex color, saying why when it is not one. */
|
|
38
38
|
let fromString = (raw: string): result<t, string> =>
|
|
39
39
|
if hex->RegExp.test(raw) {
|
|
40
40
|
Ok(raw)
|
|
@@ -46,5 +46,5 @@ let fromString = (raw: string): result<t, string> =>
|
|
|
46
46
|
)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
/** The sury schema for a
|
|
49
|
+
/** The sury schema for a color field. Use with `@s.matches(Reventless.Color.schema)`. */
|
|
50
50
|
let schema: S.t<t> = S.string->Semantic.refined(~id=Semantic.Id.color, ~check=fromString)
|
|
@@ -38,7 +38,7 @@ surface. Collapsing them either loses accounts to a transient blip or retries
|
|
|
38
38
|
forever against a password policy.
|
|
39
39
|
*/
|
|
40
40
|
type failure =
|
|
41
|
-
/** The contact is already a principal. A
|
|
41
|
+
/** The contact is already a principal. A modeled answer, not an exception —
|
|
42
42
|
which is what a silent idempotent sign-up throws away. */
|
|
43
43
|
| Conflict
|
|
44
44
|
/** The provider is down or unreachable. The domain fact stands; retry. */
|
|
@@ -142,7 +142,7 @@ type message = {subject?: string, body: string}
|
|
|
142
142
|
|
|
143
143
|
/** The provider accepted the message. `ref` is its own id for it — what a
|
|
144
144
|
support conversation about a missing message is conducted with, and the only
|
|
145
|
-
thing a caller can record that the provider will
|
|
145
|
+
thing a caller can record that the provider will recognize. */
|
|
146
146
|
type receipt = {ref: string}
|
|
147
147
|
|
|
148
148
|
/**
|
|
@@ -203,7 +203,7 @@ type send = (~recipient: recipient, ~message: message) => promise<result<receipt
|
|
|
203
203
|
The capability as a slice receives it: what can be attempted, and how.
|
|
204
204
|
|
|
205
205
|
`channels` is here because a recipient cannot be offered a choice the deployment
|
|
206
|
-
cannot
|
|
206
|
+
cannot honor. A platform provisions email only, or email and SMS; a preference
|
|
207
207
|
centre that listed all three would collect a subscription every send then answers
|
|
208
208
|
`UnsupportedChannel` for. Published rather than inferred from a failed send,
|
|
209
209
|
because discovering a channel by failing on it costs a real message.
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Lives in reventless-spec so application domain code can define
|
|
1
|
+
// Decision module type for an aggregate's write-side logic.
|
|
2
|
+
// Lives in reventless-spec so application domain code can define decisions
|
|
3
3
|
// without importing the reventless implementation package.
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
Module type that application code must implement to define aggregate
|
|
6
|
+
Module type that application code must implement to define an aggregate's
|
|
7
|
+
write-side logic: whether a command goes through, and what it emits.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
It implements the *decider* pattern: `initialState`, `evolve` and `decide`.
|
|
10
|
+
The file is `<Entity>_Decision.res`, annotated `@@reventless.decision`.
|
|
11
|
+
|
|
12
|
+
A `Decision.T` module contains the `Spec` (command / event / error types), the
|
|
9
13
|
aggregate `state`, and two pure functions plus an initial state value:
|
|
10
14
|
|
|
11
15
|
- `initialState` — the starting state before any events (represents "not yet created")
|
|
@@ -14,7 +18,7 @@ aggregate `state`, and two pure functions plus an initial state value:
|
|
|
14
18
|
|
|
15
19
|
@example
|
|
16
20
|
```rescript
|
|
17
|
-
//
|
|
21
|
+
// Category_Decision.res
|
|
18
22
|
module Spec = Category
|
|
19
23
|
|
|
20
24
|
@schema
|
|
@@ -73,7 +77,7 @@ module type T = {
|
|
|
73
77
|
let decide: (state, Spec.command) => result<array<Spec.event>, Spec.error>
|
|
74
78
|
|
|
75
79
|
/** Persisted-snapshot configuration (docs/plans/done/aggregate-snapshotting.md).
|
|
76
|
-
`None` — the default, auto-injected by `@@reventless.
|
|
80
|
+
`None` — the default, auto-injected by `@@reventless.decision` — keeps
|
|
77
81
|
full replay; `Some({interval, stateSchema})` writes a keep-one snapshot
|
|
78
82
|
every `interval` events and seeds cold replays from the latest one.
|
|
79
83
|
Enable with `@@reventless.snapshots(<interval>)` (requires
|
package/src/types/Message.res
CHANGED
|
@@ -76,7 +76,7 @@ type meta = {
|
|
|
76
76
|
/**
|
|
77
77
|
Context passed into command handlers, carrying the aggregate ID and envelope metadata.
|
|
78
78
|
|
|
79
|
-
Passed as the second argument to `
|
|
79
|
+
Passed as the second argument to `Decision.T.create` and `Decision.T.execute`
|
|
80
80
|
so business logic can read the caller identity or propagate correlation IDs.
|
|
81
81
|
*/
|
|
82
82
|
@schema
|
package/src/types/OwnerScope.res
CHANGED
|
@@ -21,8 +21,8 @@ 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
23
|
/** Whether a JS value is a primitive string — `Cognito` and `InMemory` compile to
|
|
24
|
-
bare strings while `Custom(_)` compiles to an object, so this is how a
|
|
25
|
-
provider is told from an
|
|
24
|
+
bare strings while `Custom(_)` compiles to an object, so this is how a modeled
|
|
25
|
+
provider is told from an unmodeled one that arrived as raw JSON. */
|
|
26
26
|
let isJsString: 'a => bool = %raw(`v => typeof v === "string"`)
|
|
27
27
|
|
|
28
28
|
external asNullableString: string => Nullable.t<string> = "%identity"
|
|
@@ -213,8 +213,8 @@ let classify = (identity: Identity.t, ~elevated: array<string>): t => {
|
|
|
213
213
|
|
|
214
214
|
switch providerName {
|
|
215
215
|
| Some(name) if systemProviders->Array.includes(name) => System
|
|
216
|
-
// A
|
|
217
|
-
// None) — either way a caller claiming to be a person.
|
|
216
|
+
// A modeled string provider, or `Custom(_)` (an object, so `providerName` is
|
|
217
|
+
// None) — either way a caller claiming to be a person. Unmodeled strings fall
|
|
218
218
|
// through to the refusal below.
|
|
219
219
|
| Some("Cognito") | Some("InMemory") | None =>
|
|
220
220
|
switch identity.userId->asNullableString->Nullable.toOption {
|
|
@@ -415,7 +415,7 @@ type retiredDecision =
|
|
|
415
415
|
/**
|
|
416
416
|
Combine a view's declared retirement flag with the caller behind the request.
|
|
417
417
|
|
|
418
|
-
`~asked` is the caller's `includeRetired` request,
|
|
418
|
+
`~asked` is the caller's `includeRetired` request, honored only where the
|
|
419
419
|
caller was going to see those rows anyway. Reading it before classifying would
|
|
420
420
|
make the argument the decision rather than a request.
|
|
421
421
|
|
package/src/types/Trait.res
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// annotation — an attribute's fields would all be strings the compiler never
|
|
20
20
|
// checks, which is the failure this program exists to remove.
|
|
21
21
|
//
|
|
22
|
-
// **A declaration is a claim about origin, never about
|
|
22
|
+
// **A declaration is a claim about origin, never about behavior.** After a graft
|
|
23
23
|
// the developer owns the files and may edit them freely. So this says "grafted
|
|
24
24
|
// from trait X", and it does NOT say "still behaves like trait X" — the thing that
|
|
25
25
|
// answers the second question is the trait's conformance suite, which runs in the
|
|
File without changes
|