@xmachines/play-actor 2.0.0-alpha.1 → 2.1.0
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/README.md +90 -41
- package/dist/abstract-actor.d.ts +108 -85
- package/dist/abstract-actor.d.ts.map +1 -1
- package/dist/abstract-actor.js +45 -33
- package/dist/abstract-actor.js.map +1 -1
- package/dist/context-projection.d.ts +116 -0
- package/dist/context-projection.d.ts.map +1 -0
- package/dist/context-projection.js +236 -0
- package/dist/context-projection.js.map +1 -0
- package/dist/index.d.ts +14 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -9
- package/dist/index.js.map +1 -1
- package/dist/provider-guards.d.ts +37 -33
- package/dist/provider-guards.d.ts.map +1 -1
- package/dist/provider-guards.js +34 -30
- package/dist/provider-guards.js.map +1 -1
- package/dist/view-store-lifecycle.d.ts +82 -0
- package/dist/view-store-lifecycle.d.ts.map +1 -0
- package/dist/view-store-lifecycle.js +97 -0
- package/dist/view-store-lifecycle.js.map +1 -0
- package/package.json +23 -21
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
<!-- generated-by: gsd-doc-writer -->
|
|
2
|
-
|
|
3
1
|
# @xmachines/play-actor
|
|
4
2
|
|
|
5
3
|
Abstract Actor base class for XMachines Play Architecture.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
[](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@xmachines/play-actor)
|
|
8
6
|
|
|
9
7
|
## Installation
|
|
10
8
|
|
|
@@ -12,90 +10,101 @@ Part of the [xmachines-js monorepo](../../README.md).
|
|
|
12
10
|
pnpm add @xmachines/play-actor
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
**Peer dependencies
|
|
13
|
+
**Peer dependencies.** Install them with the package:
|
|
16
14
|
|
|
17
15
|
```bash
|
|
18
|
-
pnpm add xstate @xmachines/play @xmachines/play-signals
|
|
16
|
+
pnpm add xstate @xmachines/play @xmachines/play-signals @xmachines/json-render-core
|
|
19
17
|
```
|
|
20
18
|
|
|
21
19
|
## Overview
|
|
22
20
|
|
|
23
|
-
`@xmachines/play-actor`
|
|
21
|
+
`@xmachines/play-actor` gives you `AbstractActor`, a minimal base class. The class extends the XState `Actor` class, and it enforces the **signal protocol** of the Play Architecture (RFC section 5.3). It exposes reactive TC39 Signals for the infrastructure layer. It also keeps the complete compatibility with the XState ecosystem, which includes the devtools and the inspection.
|
|
24
22
|
|
|
25
|
-
The core protocol is
|
|
23
|
+
The core protocol is small on purpose:
|
|
26
24
|
|
|
27
25
|
| Property | Type | Description |
|
|
28
26
|
| -------- | ------------------------- | ---------------------------------------- |
|
|
29
27
|
| `state` | `Signal.State<unknown>` | Reactive snapshot of current actor state |
|
|
30
28
|
| `send` | `(event: TEvent) => void` | Event dispatch method |
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
Separate interfaces declare the optional capabilities. A concrete actor implements only the interfaces that it needs:
|
|
33
31
|
|
|
34
32
|
| Interface | Property | Description |
|
|
35
33
|
| ---------- | ----------------------------------------------- | ------------------------------------- |
|
|
36
34
|
| `Routable` | `currentRoute: Signal.Computed<string \| null>` | Current route path derived from state |
|
|
37
|
-
| `Routable` | `initialRoute: string \| null` |
|
|
35
|
+
| `Routable` | `initialRoute: string \| null` | The route where the actor starts |
|
|
38
36
|
| `Viewable` | `currentView: Signal.State<PlaySpec \| null>` | Current JSON-render view spec |
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
An adapter, such as [`@xmachines/play-xstate`](../play-xstate/README.md), makes the concrete implementations.
|
|
41
39
|
|
|
42
40
|
## API Summary
|
|
43
41
|
|
|
44
42
|
### `AbstractActor<TLogic, TEvent>`
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
The abstract base class extends the XState `Actor<TLogic>` class.
|
|
45
|
+
|
|
46
|
+
A subclass **is** the actor. Give the logic and its options to `super()`, so that one
|
|
47
|
+
instance holds the running machine. Reach the `send` method of XState through the
|
|
48
|
+
prototype. This class declares `send` as abstract for one reason only: to narrow the
|
|
49
|
+
event type. TypeScript forbids a `super` call to an abstract member.
|
|
47
50
|
|
|
48
51
|
```ts
|
|
49
52
|
import { AbstractActor } from "@xmachines/play-actor";
|
|
50
53
|
import { Signal } from "@xmachines/play-signals";
|
|
51
|
-
import type
|
|
54
|
+
import { Actor, type ActorOptions, type AnyActorLogic } from "xstate";
|
|
52
55
|
|
|
53
56
|
class MyActor extends AbstractActor<AnyActorLogic> {
|
|
54
57
|
// Required: reactive state signal
|
|
55
|
-
state
|
|
58
|
+
state: Signal.State<unknown>;
|
|
59
|
+
|
|
60
|
+
constructor(logic: AnyActorLogic, options?: ActorOptions<AnyActorLogic>) {
|
|
61
|
+
super(logic, options);
|
|
62
|
+
this.state = new Signal.State(this.getSnapshot());
|
|
63
|
+
super.subscribe((snapshot) => this.state.set(snapshot));
|
|
64
|
+
}
|
|
56
65
|
|
|
57
66
|
// Required: typed event dispatch
|
|
58
|
-
send
|
|
59
|
-
|
|
60
|
-
}
|
|
67
|
+
override send(event: { type: string }): void {
|
|
68
|
+
Actor.prototype.send.call(this, event);
|
|
69
|
+
}
|
|
61
70
|
}
|
|
62
71
|
```
|
|
63
72
|
|
|
64
73
|
With a typed event union:
|
|
65
74
|
|
|
66
75
|
```ts
|
|
76
|
+
// imports as in the previous example
|
|
67
77
|
type AuthEvent = { type: "auth.login"; username: string } | { type: "auth.logout" };
|
|
68
78
|
|
|
69
79
|
class AuthActor extends AbstractActor<AnyActorLogic, AuthEvent> {
|
|
70
80
|
state = new Signal.State({ isAuthenticated: false, username: null });
|
|
71
81
|
|
|
72
|
-
send
|
|
73
|
-
|
|
74
|
-
}
|
|
82
|
+
override send(event: AuthEvent): void {
|
|
83
|
+
Actor.prototype.send.call(this, event);
|
|
84
|
+
}
|
|
75
85
|
}
|
|
76
86
|
```
|
|
77
87
|
|
|
78
|
-
### `typedSpec
|
|
88
|
+
### `typedSpec(spec)`
|
|
79
89
|
|
|
80
|
-
|
|
90
|
+
This identity helper gives a view-spec literal the type `PlaySpec` at the definition site. The
|
|
91
|
+
XState `meta` field has the type `Record<string, unknown>`. Therefore this helper is the place
|
|
92
|
+
where the spec shape receives the compile-time check and the IDE autocomplete. The helper has no
|
|
93
|
+
cost at run time.
|
|
81
94
|
|
|
82
95
|
```ts
|
|
83
96
|
import { typedSpec } from "@xmachines/play-actor";
|
|
84
97
|
|
|
85
|
-
interface DashboardCtx {
|
|
86
|
-
username: string;
|
|
87
|
-
params: Record<string, string>;
|
|
88
|
-
query: Record<string, string>;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
98
|
// In an XState machine meta block:
|
|
92
99
|
meta: {
|
|
93
|
-
view: typedSpec
|
|
100
|
+
view: typedSpec({
|
|
94
101
|
root: "root",
|
|
95
|
-
contextProps: ["username"], // ✓ key of DashboardCtx
|
|
96
|
-
// contextProps: ["usernaem"], // ✗ compile error
|
|
97
102
|
elements: {
|
|
98
|
-
root: {
|
|
103
|
+
root: {
|
|
104
|
+
type: "Dashboard",
|
|
105
|
+
props: { username: { $state: "/context/username" } },
|
|
106
|
+
children: [],
|
|
107
|
+
},
|
|
99
108
|
},
|
|
100
109
|
}),
|
|
101
110
|
}
|
|
@@ -103,36 +112,76 @@ meta: {
|
|
|
103
112
|
|
|
104
113
|
### `PlaySpec`
|
|
105
114
|
|
|
106
|
-
|
|
115
|
+
This type extends the `Spec` type of `@xmachines/json-render-core`. Each derived view receives
|
|
116
|
+
the complete machine context in its state store, under the read-only **`/context` subtree**. A
|
|
117
|
+
spec therefore reads the context through the ordinary `{ $state: "/context/…" }` grammar: in a
|
|
118
|
+
prop, in a `visible` condition, and in `repeat.statePath`.
|
|
119
|
+
|
|
120
|
+
`/context` is read-only by design. Nothing can write to it. The machine context changes through
|
|
121
|
+
an event only. A `$bindState` write or a `setState` write under `/context` throws an error, and
|
|
122
|
+
the error names the event to send. This is the model: the bindable ephemeral state is at the
|
|
123
|
+
root of the store, from `spec.state`; the domain state is in the machine, and it changes through
|
|
124
|
+
events that are meaningful and easy to inspect.
|
|
125
|
+
|
|
126
|
+
The path shows the origin of each value. `/context/params/username` comes from the URL.
|
|
127
|
+
`/context/username` belongs to the machine. One value can never hide the other.
|
|
128
|
+
|
|
129
|
+
The model projects everything, and this has two consequences. The first consequence is
|
|
130
|
+
**exposure**. The complete context is visible to the client in the view store, which includes a
|
|
131
|
+
debug panel, an inspector, and a validator. The context is a client-side value in each case, so
|
|
132
|
+
keep a secret out of it.
|
|
133
|
+
|
|
134
|
+
The second consequence is **emission granularity**. The emit gate compares the context field by
|
|
135
|
+
field, at the top level only. Therefore an event that changes any field emits the view again
|
|
136
|
+
with the same `viewKey`. A provider refreshes `/context` in the live store, and it does not seed
|
|
137
|
+
the store again. The component does not remount, and the ephemeral view state and the focus
|
|
138
|
+
stay. However, a new emission is still a render pass in the framework layer. Keep
|
|
139
|
+
high-frequency ephemeral data, such as a draft for each keystroke or a timer, in the view store
|
|
140
|
+
(`spec.state` with `$bindState`) or in a child actor. The domain state belongs in the context. A
|
|
141
|
+
keystroke does not.
|
|
107
142
|
|
|
108
143
|
```ts
|
|
109
144
|
import type { PlaySpec } from "@xmachines/play-actor";
|
|
110
145
|
|
|
111
146
|
const spec: PlaySpec = {
|
|
112
147
|
root: "root",
|
|
113
|
-
contextProps: ["username"], // only these keys are exposed to components
|
|
114
148
|
elements: {
|
|
115
|
-
root: {
|
|
149
|
+
root: {
|
|
150
|
+
type: "Profile",
|
|
151
|
+
props: { username: { $state: "/context/username" } },
|
|
152
|
+
children: [],
|
|
153
|
+
},
|
|
116
154
|
},
|
|
117
155
|
};
|
|
118
156
|
```
|
|
119
157
|
|
|
158
|
+
> Historical note: an earlier version had a `contextProps` field. At first the field drove an
|
|
159
|
+
> implicit prop-enrichment pass. That pass merged the allowlisted context fields and the URL
|
|
160
|
+
> params into the props of every element. We removed it, because it put values into components
|
|
161
|
+
> that never asked for them, and it let URL data from the user hide machine-owned state. The
|
|
162
|
+
> field was then a projection filter for a short time. We removed that filter too, because a
|
|
163
|
+
> limit on what a view can read added machinery without a real problem to solve. Always
|
|
164
|
+
> validate the **derived** view (`actor.currentView.get()`), not the raw `meta.view`. The
|
|
165
|
+
> `state` of the derived spec carries the projection, so a tool such as `validateSpec` sees a
|
|
166
|
+
> spec that is consistent with itself.
|
|
167
|
+
|
|
120
168
|
### `Routable`
|
|
121
169
|
|
|
122
170
|
Interface for actors that support routing.
|
|
123
171
|
|
|
124
172
|
```ts
|
|
125
|
-
import type
|
|
173
|
+
import { AbstractActor, type Routable } from "@xmachines/play-actor";
|
|
126
174
|
import { Signal } from "@xmachines/play-signals";
|
|
175
|
+
import type { AnyActorLogic, EventObject } from "xstate";
|
|
127
176
|
|
|
128
177
|
// Implement in a concrete actor (note: RoutableActor interface is exported from @xmachines/play-router):
|
|
129
178
|
class MyRoutableActor extends AbstractActor<AnyActorLogic> implements Routable {
|
|
130
|
-
state = new Signal.State({});
|
|
131
|
-
currentRoute = new Signal.Computed(() => this.state.get().path ?? null);
|
|
179
|
+
state = new Signal.State<{ path?: string }>({});
|
|
180
|
+
currentRoute = new Signal.Computed<string | null>(() => this.state.get().path ?? null);
|
|
132
181
|
initialRoute = "/";
|
|
133
|
-
send
|
|
182
|
+
override send(event: EventObject): void {
|
|
134
183
|
/* dispatch */
|
|
135
|
-
}
|
|
184
|
+
}
|
|
136
185
|
}
|
|
137
186
|
```
|
|
138
187
|
|
|
@@ -152,7 +201,7 @@ const viewable: Viewable = { currentView: signal };
|
|
|
152
201
|
|
|
153
202
|
### `BaseActorProviderProps<TRegistry>`
|
|
154
203
|
|
|
155
|
-
|
|
204
|
+
The framework-agnostic base props. Every `ActorProvider` implementation shares them: React, Vue, Solid, and Svelte. Each framework renderer package extends this interface.
|
|
156
205
|
|
|
157
206
|
```ts
|
|
158
207
|
import type { BaseActorProviderProps } from "@xmachines/play-actor";
|
|
@@ -166,7 +215,7 @@ interface ActorProviderProps extends BaseActorProviderProps<DefineRegistryResult
|
|
|
166
215
|
|
|
167
216
|
### `BaseViewContextValue<TRegistry>`
|
|
168
217
|
|
|
169
|
-
|
|
218
|
+
The framework-agnostic base of the `ViewContextValue` type in each framework. It holds the `spec`, `handlers`, `registry`, and `store` fields. These fields are identical in React, Vue, Solid, and Svelte.
|
|
170
219
|
|
|
171
220
|
## Testing
|
|
172
221
|
|
package/dist/abstract-actor.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AbstractActor base class
|
|
2
|
+
* The AbstractActor base class of the Play Architecture
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* It extends the XState Actor class, which keeps the compatibility with the
|
|
5
|
+
* ecosystem, such as the inspection and the devtools. It also enforces the signal
|
|
6
|
+
* protocol of the communication between the Actor and the infrastructure.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
* - state:
|
|
9
|
-
* - send:
|
|
8
|
+
* RFC section 5.3 gives the minimal protocol of the Actor:
|
|
9
|
+
* - state: the snapshot of the current machine state
|
|
10
|
+
* - send: the method that sends an event
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
* - Routable:
|
|
13
|
-
* - Viewable:
|
|
12
|
+
* Two interfaces give the optional capabilities:
|
|
13
|
+
* - Routable: for an actor with a routing support
|
|
14
|
+
* - Viewable: for an actor with a view rendering
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
+
* An adapter, such as @xmachines/play-xstate, makes the concrete implementations.
|
|
16
17
|
*
|
|
17
18
|
* @packageDocumentation
|
|
18
19
|
*/
|
|
@@ -20,110 +21,115 @@ import { Actor, type AnyActorLogic, type EventObject } from "xstate";
|
|
|
20
21
|
import type { Signal } from "@xmachines/play-signals";
|
|
21
22
|
import type { Spec, StateStore, RenderErrorHandler, ActionHandler } from "@xmachines/json-render-core";
|
|
22
23
|
/**
|
|
23
|
-
*
|
|
24
|
+
* An optional capability: the routing support
|
|
24
25
|
*/
|
|
25
26
|
export interface Routable {
|
|
26
27
|
readonly currentRoute: Signal.Computed<string | null>;
|
|
27
28
|
readonly initialRoute: string | null;
|
|
28
29
|
}
|
|
29
30
|
/**
|
|
30
|
-
* XMachines extension of `@xmachines/json-render-core
|
|
31
|
+
* The XMachines extension of the `Spec` type of `@xmachines/json-render-core`.
|
|
31
32
|
*
|
|
32
|
-
*
|
|
33
|
-
* `
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* Use `typedSpec<TContext>(...)` at the definition site to validate `contextProps`
|
|
38
|
-
* entries against your machine's context type at compile time.
|
|
33
|
+
* Each derived view receives the machine context in its state store, under the
|
|
34
|
+
* read-only `/context` subtree. A spec therefore reads the context through the
|
|
35
|
+
* ordinary `{ $state: "/context/…" }` grammar: in a prop, in a `visible` condition,
|
|
36
|
+
* and in `repeat.statePath`. The store always holds the complete context, and a
|
|
37
|
+
* spec reads only the paths that it needs.
|
|
39
38
|
*/
|
|
40
39
|
export interface PlaySpec extends Spec {
|
|
41
40
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
41
|
+
* The identity of the view of this derived spec. `deriveCurrentView` sets it from
|
|
42
|
+
* the meta entry that the derivation selected. A provider uses it as the key of its
|
|
43
|
+
* store lifecycle: a new `viewKey` seeds the store again, and the same `viewKey`
|
|
44
|
+
* refreshes `/context` in place, which keeps the ephemeral view state. Never write
|
|
45
|
+
* this field in `meta.view`.
|
|
47
46
|
*/
|
|
48
|
-
readonly
|
|
47
|
+
readonly viewKey?: string;
|
|
49
48
|
}
|
|
50
49
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* The identity helper gives a view spec literal the type `PlaySpec` at the
|
|
51
|
+
* definition site. The compiler therefore checks the spec, and the IDE completes it.
|
|
52
|
+
*
|
|
53
|
+
* The XState `meta` field has the type `Record<string, unknown>`. TypeScript
|
|
54
|
+
* therefore infers no spec shape from the context. `typedSpec(...)` is the
|
|
55
|
+
* mechanism that starts the check where you write the spec. The parameter holds no
|
|
56
|
+
* `viewKey`: the derivation stamps that field, and it overwrites a value from an
|
|
57
|
+
* author without a notice. Therefore the compiler refuses a `viewKey` here.
|
|
54
58
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
59
|
+
* The check of an excess property works on an inline object literal only. For a
|
|
60
|
+
* spec in a variable, or for a spec from a spread, write `satisfies PlaySpec` at
|
|
61
|
+
* the literal instead.
|
|
58
62
|
*
|
|
59
|
-
* At
|
|
63
|
+
* At run time this function does nothing: it returns the spec object without a
|
|
64
|
+
* change.
|
|
60
65
|
*
|
|
61
66
|
* @example
|
|
62
67
|
* ```ts
|
|
63
|
-
* interface DashboardCtx {
|
|
64
|
-
* username: string;
|
|
65
|
-
* params: Record<string, string>;
|
|
66
|
-
* query: Record<string, string>;
|
|
67
|
-
* }
|
|
68
|
-
*
|
|
69
68
|
* meta: {
|
|
70
|
-
* view: typedSpec
|
|
69
|
+
* view: typedSpec({
|
|
71
70
|
* root: "root",
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
71
|
+
* elements: {
|
|
72
|
+
* root: {
|
|
73
|
+
* type: "Dashboard",
|
|
74
|
+
* props: { username: { $state: "/context/username" } },
|
|
75
|
+
* children: [],
|
|
76
|
+
* },
|
|
77
|
+
* },
|
|
75
78
|
* }),
|
|
76
79
|
* }
|
|
77
80
|
* ```
|
|
78
81
|
*/
|
|
79
|
-
export declare function typedSpec
|
|
80
|
-
readonly contextProps?: readonly (keyof TContext & string)[];
|
|
81
|
-
}): PlaySpec;
|
|
82
|
+
export declare function typedSpec(spec: Omit<PlaySpec, "viewKey">): PlaySpec;
|
|
82
83
|
/**
|
|
83
|
-
*
|
|
84
|
+
* The actor capability that exposes a renderable view state.
|
|
84
85
|
*
|
|
85
|
-
* `Viewable` marks
|
|
86
|
-
*
|
|
87
|
-
* current view
|
|
88
|
-
*
|
|
86
|
+
* `Viewable` marks an actor that publishes a `currentView` signal.
|
|
87
|
+
* A renderer, such as `PlayRenderer`, reads this contract. It converts the
|
|
88
|
+
* description of the current view into a concrete UI, and the framework adapter
|
|
89
|
+
* therefore holds no view logic.
|
|
89
90
|
*/
|
|
90
91
|
export interface Viewable {
|
|
91
92
|
/**
|
|
92
|
-
*
|
|
93
|
-
* state, or null when no view is active.
|
|
93
|
+
* The signal of the current view. It holds the json-render PlaySpec of the current
|
|
94
|
+
* machine state, or null when no view is active.
|
|
94
95
|
*
|
|
95
|
-
*
|
|
96
|
+
* The infrastructure renders the view. This is the Logic-Driven UI invariant.
|
|
96
97
|
*/
|
|
97
98
|
readonly currentView: Signal.State<PlaySpec | null>;
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
100
|
-
*
|
|
101
|
+
* The framework-agnostic base of the `ViewContextValue` type in each framework.
|
|
101
102
|
*
|
|
102
|
-
*
|
|
103
|
-
* `registry`
|
|
104
|
-
* type
|
|
103
|
+
* It holds the three fields that are identical in React, Vue, Solid, and Svelte.
|
|
104
|
+
* The `registry` field belongs to one framework, because each framework has its own
|
|
105
|
+
* `ComponentRegistry` type. Therefore `TRegistry` gives its type, and this is the
|
|
106
|
+
* same generic parameter as in `BaseActorProviderProps`.
|
|
105
107
|
*
|
|
106
|
-
* @typeParam TRegistry - The
|
|
108
|
+
* @typeParam TRegistry - The registry type of the component of the framework, for example `ComponentRegistry` from `@xmachines/json-render-react`.
|
|
107
109
|
*/
|
|
108
110
|
export interface BaseViewContextValue<TRegistry extends object> {
|
|
109
111
|
/** The current PlaySpec to render. */
|
|
110
112
|
spec: PlaySpec;
|
|
111
|
-
/**
|
|
113
|
+
/** The action handlers, resolved against the live StateStore. */
|
|
112
114
|
handlers: Record<string, ActionHandler>;
|
|
113
|
-
/**
|
|
115
|
+
/** The component registry, from registryResult.registry. */
|
|
114
116
|
registry: TRegistry;
|
|
115
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* The active StateStore. Give it to JSONUIProvider or JsonUIProvider as `store`, and the providers then share the state.
|
|
119
|
+
*/
|
|
116
120
|
store: StateStore;
|
|
117
121
|
}
|
|
118
122
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* `DefineRegistryResult` type
|
|
122
|
-
* `@xmachines/json-render-core
|
|
123
|
+
* The framework-agnostic base props. Every `ActorProvider` implementation shares
|
|
124
|
+
* them: React, Vue, Solid, and Svelte. `TRegistry` holds the
|
|
125
|
+
* `DefineRegistryResult` type of the framework. `RenderErrorHandler` comes from
|
|
126
|
+
* `@xmachines/json-render-core`, and a second generic parameter is therefore not
|
|
127
|
+
* necessary.
|
|
123
128
|
*
|
|
124
|
-
*
|
|
129
|
+
* Each framework package extends this interface with its `fallback` field, its
|
|
130
|
+
* `onError` field, and its `children` field.
|
|
125
131
|
*
|
|
126
|
-
* @typeParam TRegistry - The
|
|
132
|
+
* @typeParam TRegistry - The `DefineRegistryResult` type of the framework.
|
|
127
133
|
*
|
|
128
134
|
* @example
|
|
129
135
|
* ```ts
|
|
@@ -140,44 +146,61 @@ export interface BaseActorProviderProps<TRegistry extends {
|
|
|
140
146
|
registry: object;
|
|
141
147
|
handlers: (...args: never[]) => unknown;
|
|
142
148
|
}> {
|
|
143
|
-
/**
|
|
149
|
+
/** The actor instance with the currentView signal. It requires the Viewable capability. */
|
|
144
150
|
actor: AbstractActor<AnyActorLogic> & Viewable;
|
|
145
|
-
/**
|
|
151
|
+
/** The complete result of defineRegistry(). It holds the component registry and the factory of the action handlers. */
|
|
146
152
|
registryResult: TRegistry;
|
|
147
153
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
154
|
+
* The optional external StateStore, which is the controlled mode.
|
|
155
|
+
* With this option, the provider ignores spec.state, and this store is the single
|
|
156
|
+
* source of truth. Without it, the provider makes a new @xstate/store atom for each
|
|
157
|
+
* view transition, with the values of spec.state.
|
|
151
158
|
*/
|
|
152
159
|
store?: StateStore;
|
|
153
160
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
161
|
+
* The provider calls it when one catalog component throws during a render.
|
|
162
|
+
* This handler replaces every onRenderError of defineRegistry.
|
|
156
163
|
*/
|
|
157
164
|
onRenderError?: RenderErrorHandler;
|
|
158
165
|
}
|
|
159
166
|
/**
|
|
160
|
-
*
|
|
167
|
+
* The abstract base class of an actor of the Play Architecture.
|
|
161
168
|
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
169
|
+
* It observes the state through the signals, and it works with the tools of the
|
|
170
|
+
* XState ecosystem, such as the devtools and the inspection. It also exposes the
|
|
171
|
+
* reactive signals of the communication with the infrastructure layer.
|
|
165
172
|
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
173
|
+
* **A subclass IS the actor.** Give the logic *and* its options to
|
|
174
|
+
* `super(logic, options)`, then observe `this`. A separate actor beside this
|
|
175
|
+
* instance leaves this instance as an empty second actor. Every inherited member
|
|
176
|
+
* then answers from that empty actor, until you forward each one: `system`,
|
|
177
|
+
* `sessionId`, `clock`, the internal `_send` that receives the traffic of
|
|
178
|
+
* `sendTo()`, and each member that a later XState version adds.
|
|
179
|
+
*
|
|
180
|
+
* @typeParam TLogic - The type of the XState actor logic
|
|
181
|
+
* @typeParam TEvent - The constraint of the event type. The default is EventObject
|
|
168
182
|
*/
|
|
169
183
|
export declare abstract class AbstractActor<TLogic extends AnyActorLogic, TEvent extends EventObject = EventObject> extends Actor<TLogic> {
|
|
170
184
|
/**
|
|
171
|
-
*
|
|
185
|
+
* The reactive snapshot of the current actor state.
|
|
172
186
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
187
|
+
* The infrastructure observes this signal, and it reacts to each state change. It
|
|
188
|
+
* therefore holds no coupling to the internal state machine of the actor.
|
|
175
189
|
*/
|
|
176
190
|
abstract state: Signal.State<unknown>;
|
|
177
191
|
/**
|
|
178
|
-
*
|
|
192
|
+
* Sends an event to the Actor.
|
|
193
|
+
*
|
|
194
|
+
* The constraint is TEvent, which gives the type safety of a concrete
|
|
195
|
+
* implementation.
|
|
179
196
|
*
|
|
180
|
-
*
|
|
197
|
+
* A note for an implementation that wraps `send`, to check the event or to notify a
|
|
198
|
+
* hook around it: this declaration is abstract for one reason only, to narrow the
|
|
199
|
+
* event type, and TypeScript forbids a `super` call to an abstract member. Reach
|
|
200
|
+
* the implementation of XState with `Actor.prototype.send.call(this, event)`
|
|
201
|
+
* instead. A concrete declaration permits `super.send()`, but it also forces an
|
|
202
|
+
* `override` modifier in every subclass that exists now, and that is a breaking
|
|
203
|
+
* change for an adapter outside this repository.
|
|
181
204
|
*/
|
|
182
205
|
abstract send(event: TEvent): void;
|
|
183
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-actor.d.ts","sourceRoot":"","sources":["../src/abstract-actor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"abstract-actor.d.ts","sourceRoot":"","sources":["../src/abstract-actor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EACX,IAAI,EACJ,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,MAAM,6BAA6B,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAS,SAAQ,IAAI;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,QAAQ,CAEnE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CACpD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB,CAAC,SAAS,SAAS,MAAM;IAC7D,sCAAsC;IACtC,IAAI,EAAE,QAAQ,CAAC;IACf,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACxC,4DAA4D;IAC5D,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,UAAU,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,sBAAsB,CACtC,SAAS,SAAS;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAA;CAAE;IAE/E,2FAA2F;IAC3F,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC;IAC/C,uHAAuH;IACvH,cAAc,EAAE,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,8BAAsB,aAAa,CAClC,MAAM,SAAS,aAAa,EAC5B,MAAM,SAAS,WAAW,GAAG,WAAW,CACvC,SAAQ,KAAK,CAAC,MAAM,CAAC;IACtB;;;;;OAKG;IACH,SAAgB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE7C;;;;;;;;;;;;;OAaG;aACsB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAClD"}
|