@typeonce/effect-machine 0.14.0 → 0.15.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 +68 -45
- package/dist/Machine.d.ts +178 -68
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +81 -24
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/machine.d.ts +9 -4
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +27 -10
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/stateDefinition.d.ts +3 -1
- package/dist/internal/machine/stateDefinition.d.ts.map +1 -1
- package/dist/internal/machine/stateDefinition.js +35 -0
- package/dist/internal/machine/stateDefinition.js.map +1 -1
- package/dist/internal/testing/machine/finiteModel.js +1 -1
- package/dist/internal/testing/machine/finiteModel.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +7 -7
- package/dist/testing/MachineTest.js +7 -7
- package/dist/unstable/cluster/ClusterMachine.d.ts +1 -1
- package/dist/unstable/cluster/ClusterMachine.js +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +3 -3
- package/dist/unstable/reactivity/AtomMachine.js +3 -3
- package/docs/agent-guide.md +144 -51
- package/package.json +1 -1
- package/src/Machine.ts +279 -97
- package/src/internal/machine/machine.ts +42 -22
- package/src/internal/machine/stateDefinition.ts +41 -1
- package/src/internal/testing/machine/finiteModel.ts +1 -1
- package/src/testing/MachineTest.ts +7 -7
- package/src/unstable/cluster/ClusterMachine.ts +1 -1
- package/src/unstable/reactivity/AtomMachine.ts +3 -3
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
ChildAddress,
|
|
12
12
|
ChildMachine,
|
|
13
13
|
Command,
|
|
14
|
+
Definition,
|
|
14
15
|
ExecutionServices,
|
|
15
16
|
InitialEvent as InitialEventModel,
|
|
16
17
|
Logic,
|
|
@@ -79,7 +80,14 @@ type ValidateDefinedStates<States extends Machine.StateSchemas> = [States] exten
|
|
|
79
80
|
type InvalidDefinedStateTreeInput<States extends Machine.StateSchemas> = [States] extends
|
|
80
81
|
[Machine.ValidateStateSchemas<States>] ? never
|
|
81
82
|
: States & Machine.ValidateStateSchemas<States>
|
|
82
|
-
|
|
83
|
+
type ReusableStateNodeConfig =
|
|
84
|
+
| Machine.AtomicStateNodeConfig
|
|
85
|
+
| Machine.CompoundStateNodeConfig
|
|
86
|
+
| Machine.ParallelStateNodeConfig
|
|
87
|
+
interface StateConstructor {
|
|
88
|
+
<const Node extends ReusableStateNodeConfig>(node: Node): Node
|
|
89
|
+
}
|
|
90
|
+
interface StatesConstructor {
|
|
83
91
|
<const States extends Machine.StateSchemas>(
|
|
84
92
|
states: States,
|
|
85
93
|
..._validation: ValidateDefinedStates<NoInfer<States>>
|
|
@@ -106,8 +114,8 @@ const Proto = {
|
|
|
106
114
|
|
|
107
115
|
const makeBoundInvoke = (config: unknown): unknown => config
|
|
108
116
|
|
|
109
|
-
const
|
|
110
|
-
self:
|
|
117
|
+
const makeWithHandlers = (
|
|
118
|
+
self: Definition.Any,
|
|
111
119
|
handlers: Machine.StateConfigs<any, any, any, any, any, any, any>
|
|
112
120
|
): Machine.Any => {
|
|
113
121
|
const machine = Object.create(Proto)
|
|
@@ -123,7 +131,6 @@ const cloneWithHandlers = (
|
|
|
123
131
|
machine.stateNodes = self.stateNodes
|
|
124
132
|
machine.makeTargetBuilder = self.makeTargetBuilder
|
|
125
133
|
machine.handlers = handlers
|
|
126
|
-
machine.handle = makeHandle(machine)
|
|
127
134
|
machine.invoke = makeBoundInvoke
|
|
128
135
|
Protocol.copyProtocol(self, machine)
|
|
129
136
|
return machine
|
|
@@ -220,7 +227,13 @@ const makeTargetSelector = (
|
|
|
220
227
|
branch[root.key] = makeSelectionNode(stateNodes, root.path, "branch")
|
|
221
228
|
const local: Record<string, unknown> = {}
|
|
222
229
|
const localScope = getLocalTargetScope(stateNodes, source)
|
|
223
|
-
if (localScope !== undefined)
|
|
230
|
+
if (localScope !== undefined) {
|
|
231
|
+
const localScopeNode = getTargetBuilderNode(stateNodes, localScope)
|
|
232
|
+
if (localScopeNode.schema !== undefined) {
|
|
233
|
+
local.with = makeSelectionMethod("state", localScope, "local")
|
|
234
|
+
}
|
|
235
|
+
addSelectionChildren(local, stateNodes, localScope, "local")
|
|
236
|
+
}
|
|
224
237
|
return {
|
|
225
238
|
none: makeSelectionMethod("none", undefined, "local"),
|
|
226
239
|
local,
|
|
@@ -263,7 +276,14 @@ const getSelectionBuilder = (
|
|
|
263
276
|
} else if (selection.scope === "local") {
|
|
264
277
|
builder = target.local
|
|
265
278
|
const scope = getLocalTargetScope(stateNodes, source)
|
|
266
|
-
if (scope !== undefined)
|
|
279
|
+
if (scope !== undefined) {
|
|
280
|
+
if (selection.path === scope) {
|
|
281
|
+
builder = builder.with
|
|
282
|
+
parts = []
|
|
283
|
+
} else {
|
|
284
|
+
parts = selection.path!.slice(scope.length + 1).split(".")
|
|
285
|
+
}
|
|
286
|
+
}
|
|
267
287
|
} else if (selection.scope === "branch") {
|
|
268
288
|
builder = target.branch
|
|
269
289
|
} else {
|
|
@@ -512,15 +532,12 @@ const flattenHandlers = (
|
|
|
512
532
|
}
|
|
513
533
|
}
|
|
514
534
|
|
|
515
|
-
const makeHandle = (self:
|
|
535
|
+
const makeHandle = (self: Definition.Any): Definition.Any["handle"] =>
|
|
516
536
|
((config: Record<string, unknown>) => {
|
|
517
|
-
const handlers: Record<PropertyKey, Machine.AnyStateConfig> = Object.
|
|
518
|
-
Object.create(null),
|
|
519
|
-
self.handlers
|
|
520
|
-
)
|
|
537
|
+
const handlers: Record<PropertyKey, Machine.AnyStateConfig> = Object.create(null)
|
|
521
538
|
flattenHandlers(handlers, self.stateNodes, self.states, "", config)
|
|
522
|
-
return
|
|
523
|
-
}) as
|
|
539
|
+
return makeWithHandlers(self, handlers)
|
|
540
|
+
}) as Definition.Any["handle"]
|
|
524
541
|
|
|
525
542
|
export const isMachine = (
|
|
526
543
|
u: unknown
|
|
@@ -1128,12 +1145,19 @@ const compileInitial = (
|
|
|
1128
1145
|
}
|
|
1129
1146
|
}
|
|
1130
1147
|
|
|
1131
|
-
export const
|
|
1148
|
+
export const state: StateConstructor = (<const Node extends ReusableStateNodeConfig>(node: Node): Node => {
|
|
1149
|
+
StateDefinition.validateStateDefinitions({ state: node }, "Machine.state")
|
|
1150
|
+
return StateDefinition.captureStateDefinitions({ state: node }).state
|
|
1151
|
+
}) as StateConstructor
|
|
1152
|
+
|
|
1153
|
+
export const states: StatesConstructor = (<const States extends Machine.StateSchemas>(
|
|
1132
1154
|
states: States
|
|
1133
1155
|
): Machine.DefinedStates<States> => {
|
|
1134
|
-
StateDefinition.validateStateDefinitions(states, "Machine.
|
|
1156
|
+
StateDefinition.validateStateDefinitions(states, "Machine.states")
|
|
1157
|
+
const captured = StateDefinition.captureStateDefinitions(states)
|
|
1135
1158
|
return {
|
|
1136
|
-
states,
|
|
1159
|
+
states: captured,
|
|
1160
|
+
path: ((path: string) => path) as Machine.DefinedStates<States>["path"],
|
|
1137
1161
|
get:
|
|
1138
1162
|
((snapshot: Machine.AtomicSnapshot<string, unknown>, path: string) =>
|
|
1139
1163
|
Topology.getSnapshotByPath(snapshot, path).pipe(
|
|
@@ -1150,7 +1174,7 @@ export const defineStates: DefineStates = (<const States extends Machine.StateSc
|
|
|
1150
1174
|
((snapshot: Machine.AtomicSnapshot<string, unknown>, path: string) =>
|
|
1151
1175
|
Option.isSome(Topology.getSnapshotByPath(snapshot, path))) as Machine.DefinedStates<States>["matches"]
|
|
1152
1176
|
}
|
|
1153
|
-
}) as
|
|
1177
|
+
}) as StatesConstructor
|
|
1154
1178
|
|
|
1155
1179
|
type MakeConfig<
|
|
1156
1180
|
States extends Machine.StateSchemas,
|
|
@@ -1188,19 +1212,15 @@ type MakeResult<
|
|
|
1188
1212
|
InitialR,
|
|
1189
1213
|
InternalEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1190
1214
|
ParentEvents extends ReadonlyArray<Machine.TaggedSchema>
|
|
1191
|
-
> =
|
|
1215
|
+
> = Definition<
|
|
1192
1216
|
States,
|
|
1193
1217
|
readonly [...InputEvents, ...InternalEvents],
|
|
1194
1218
|
Input,
|
|
1195
|
-
Machine.StateIdentifier<States>,
|
|
1196
|
-
never,
|
|
1197
|
-
never,
|
|
1198
1219
|
InitialE,
|
|
1199
1220
|
InitialR,
|
|
1200
1221
|
Machine.FinalStateFromDefinition<States>,
|
|
1201
1222
|
Machine.TerminalOutput<States>,
|
|
1202
1223
|
Emits,
|
|
1203
|
-
never,
|
|
1204
1224
|
InputEvents,
|
|
1205
1225
|
ParentEvents
|
|
1206
1226
|
>
|
|
@@ -18,7 +18,7 @@ export type AllowedStateNodeProperty<Kind extends StateNodeKind> = (typeof State
|
|
|
18
18
|
|
|
19
19
|
export type AllowedPseudoStateAnnotationProperty = (typeof PseudoStateAnnotationProperties)[number]
|
|
20
20
|
|
|
21
|
-
export type StateDefinitionBoundary = "Machine.
|
|
21
|
+
export type StateDefinitionBoundary = "Machine.state" | "Machine.states" | "Machine.make"
|
|
22
22
|
|
|
23
23
|
const hasOwn = (value: object, key: PropertyKey): boolean => Object.prototype.hasOwnProperty.call(value, key)
|
|
24
24
|
|
|
@@ -279,3 +279,43 @@ export const validateStateDefinitions = (
|
|
|
279
279
|
states: unknown,
|
|
280
280
|
boundary: StateDefinitionBoundary
|
|
281
281
|
): void => validateStateTree(boundary, states, "", false)
|
|
282
|
+
|
|
283
|
+
const captureAnnotations = (annotations: unknown): unknown =>
|
|
284
|
+
typeof annotations === "object" && annotations !== null
|
|
285
|
+
? Object.freeze({ ...annotations })
|
|
286
|
+
: annotations
|
|
287
|
+
|
|
288
|
+
const captureStateTree = (states: Readonly<Record<string, unknown>>): Readonly<Record<string, unknown>> => {
|
|
289
|
+
const captured: Record<string, unknown> = {}
|
|
290
|
+
for (const key of Object.keys(states)) {
|
|
291
|
+
const node = states[key]
|
|
292
|
+
if (Schema.isSchema(node)) {
|
|
293
|
+
Object.defineProperty(captured, key, {
|
|
294
|
+
value: node,
|
|
295
|
+
enumerable: true,
|
|
296
|
+
configurable: false,
|
|
297
|
+
writable: false
|
|
298
|
+
})
|
|
299
|
+
continue
|
|
300
|
+
}
|
|
301
|
+
const config = node as Readonly<Record<string, unknown>>
|
|
302
|
+
const copy: Record<string, unknown> = { ...config }
|
|
303
|
+
if ("states" in config) {
|
|
304
|
+
copy.states = captureStateTree(config.states as Readonly<Record<string, unknown>>)
|
|
305
|
+
}
|
|
306
|
+
if ("annotations" in config) {
|
|
307
|
+
copy.annotations = captureAnnotations(config.annotations)
|
|
308
|
+
}
|
|
309
|
+
Object.defineProperty(captured, key, {
|
|
310
|
+
value: Object.freeze(copy),
|
|
311
|
+
enumerable: true,
|
|
312
|
+
configurable: false,
|
|
313
|
+
writable: false
|
|
314
|
+
})
|
|
315
|
+
}
|
|
316
|
+
return Object.freeze(captured)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** Captures caller-owned structural containers while preserving schema identity. */
|
|
320
|
+
export const captureStateDefinitions = <States>(states: States): States =>
|
|
321
|
+
captureStateTree(states as Readonly<Record<string, unknown>>) as States
|
|
@@ -1509,7 +1509,7 @@ export const compileModel = (model: FiniteModel): Machine.Machine.Any => {
|
|
|
1509
1509
|
const flattened = validateModel(model)
|
|
1510
1510
|
const byPath = new Map(flattened.map((state) => [state.path, state]))
|
|
1511
1511
|
const stateTree = makeStateTree(model.roots, undefined)
|
|
1512
|
-
const defined = Machine.
|
|
1512
|
+
const defined = Machine.states(stateTree as any)
|
|
1513
1513
|
const eventSchemas = model.events.map((event) => Schema.TaggedStruct(event, {}))
|
|
1514
1514
|
const initial = byPath.get(model.initial)!
|
|
1515
1515
|
const machine = Machine.make({
|
|
@@ -227,7 +227,7 @@ export interface Scenarios<M extends AnyMachine> {
|
|
|
227
227
|
*
|
|
228
228
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
229
229
|
* class Reset extends Schema.TaggedClass<Reset>("Reset")("Reset", {}) {}
|
|
230
|
-
* const States = Machine.
|
|
230
|
+
* const States = Machine.states({ Idle })
|
|
231
231
|
* const machine = Machine.make({
|
|
232
232
|
* states: States.states,
|
|
233
233
|
* events: Machine.events(Reset),
|
|
@@ -488,7 +488,7 @@ export { ProbeUnavailableError } from "../internal/testing/machine/verification.
|
|
|
488
488
|
* import { MachineTest } from "@typeonce/effect-machine/testing"
|
|
489
489
|
*
|
|
490
490
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
491
|
-
* const States = Machine.
|
|
491
|
+
* const States = Machine.states({ Idle })
|
|
492
492
|
* const machine = Machine.make({
|
|
493
493
|
* states: States.states,
|
|
494
494
|
* events: Machine.events(),
|
|
@@ -1101,7 +1101,7 @@ export const Invariant: {
|
|
|
1101
1101
|
* class Count extends Schema.TaggedClass<Count>("Count")("Count", {
|
|
1102
1102
|
* value: Schema.Number
|
|
1103
1103
|
* }) {}
|
|
1104
|
-
* const States = Machine.
|
|
1104
|
+
* const States = Machine.states({ Count })
|
|
1105
1105
|
* const machine = Machine.make({
|
|
1106
1106
|
* states: States.states,
|
|
1107
1107
|
* events: Machine.events(),
|
|
@@ -1436,7 +1436,7 @@ export type ExploreOptions<M extends AnyMachine, Key extends ExplorationKey = Ex
|
|
|
1436
1436
|
* value: Schema.Number
|
|
1437
1437
|
* }) {}
|
|
1438
1438
|
* class Increment extends Schema.TaggedClass<Increment>("Increment")("Increment", {}) {}
|
|
1439
|
-
* const States = Machine.
|
|
1439
|
+
* const States = Machine.states({ Count })
|
|
1440
1440
|
* const machine = Machine.make({
|
|
1441
1441
|
* states: States.states,
|
|
1442
1442
|
* events: Machine.events(Increment),
|
|
@@ -1629,7 +1629,7 @@ export type RunServices<M extends AnyMachine> = IsAny<
|
|
|
1629
1629
|
* import { MachineTest } from "@typeonce/effect-machine/testing"
|
|
1630
1630
|
*
|
|
1631
1631
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
1632
|
-
* const States = Machine.
|
|
1632
|
+
* const States = Machine.states({ Idle })
|
|
1633
1633
|
* const machine = Machine.make({
|
|
1634
1634
|
* states: States.states,
|
|
1635
1635
|
* events: Machine.events(),
|
|
@@ -1893,7 +1893,7 @@ export interface Coverage<M extends AnyMachine> {
|
|
|
1893
1893
|
* import { MachineTest } from "@typeonce/effect-machine/testing"
|
|
1894
1894
|
*
|
|
1895
1895
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
1896
|
-
* const States = Machine.
|
|
1896
|
+
* const States = Machine.states({ Idle })
|
|
1897
1897
|
* const machine = Machine.make({
|
|
1898
1898
|
* states: States.states,
|
|
1899
1899
|
* events: Machine.events(),
|
|
@@ -2118,7 +2118,7 @@ export interface VerifyOptions {
|
|
|
2118
2118
|
* import { MachineTest } from "@typeonce/effect-machine/testing"
|
|
2119
2119
|
*
|
|
2120
2120
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
2121
|
-
* const States = Machine.
|
|
2121
|
+
* const States = Machine.states({ Idle })
|
|
2122
2122
|
* const machine = Machine.make({
|
|
2123
2123
|
* states: States.states,
|
|
2124
2124
|
* events: Machine.events(),
|
|
@@ -312,7 +312,7 @@ export const layerMemory: Layer.Layer<Storage> = internal.layerMemory
|
|
|
312
312
|
* import { ClusterMachine } from "@typeonce/effect-machine/cluster"
|
|
313
313
|
*
|
|
314
314
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
315
|
-
* const States = Machine.
|
|
315
|
+
* const States = Machine.states({ Idle })
|
|
316
316
|
* const machine = Machine.make({
|
|
317
317
|
* states: States.states,
|
|
318
318
|
* events: Machine.events(),
|
|
@@ -366,7 +366,7 @@ type ChildState<Child extends Machine.ChildMachine.Any> = RefState<Machine.Child
|
|
|
366
366
|
* class Count extends Schema.TaggedClass<Count>("Count")("Count", {
|
|
367
367
|
* value: Schema.Number
|
|
368
368
|
* }) {}
|
|
369
|
-
* const States = Machine.
|
|
369
|
+
* const States = Machine.states({ Count })
|
|
370
370
|
* const machine = Machine.make({
|
|
371
371
|
* states: States.states,
|
|
372
372
|
* events: Machine.events(),
|
|
@@ -480,7 +480,7 @@ export const selectSnapshotChild: <
|
|
|
480
480
|
* import { AtomMachine } from "@typeonce/effect-machine/reactivity"
|
|
481
481
|
*
|
|
482
482
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
483
|
-
* const States = Machine.
|
|
483
|
+
* const States = Machine.states({ Idle })
|
|
484
484
|
* const machine = Machine.make({
|
|
485
485
|
* states: States.states,
|
|
486
486
|
* events: Machine.events(),
|
|
@@ -653,7 +653,7 @@ export interface Bound<Services, RuntimeError = never> {
|
|
|
653
653
|
* import { AtomMachine } from "@typeonce/effect-machine/reactivity"
|
|
654
654
|
*
|
|
655
655
|
* class Idle extends Schema.TaggedClass<Idle>("Idle")("Idle", {}) {}
|
|
656
|
-
* const States = Machine.
|
|
656
|
+
* const States = Machine.states({ Idle })
|
|
657
657
|
* const machine = Machine.make({
|
|
658
658
|
* states: States.states,
|
|
659
659
|
* events: Machine.events(),
|