0.1.24 • Published 3 years ago
flux-machine v0.1.24
Flux machine
Spec compliant finite state machines using JSX and chainable methods.
Installation:
npm install flux-machineExample:
import fsm, { State, Transition } from "flux-machine";
// Define state chart using JSX (finite state)
const humanStateChart = (
<>
<State initial id="sleeping">
<Transition event="walk" target="walking" />
</State>
<State id="walking">
<Transition event="sleep" target="sleeping" />
<Transition event="run" target="running" />
</State>
<State id="running">
<Transition event="walk" target="walking" />
</State>
</>
);
// Define data (infinite state)
const data = {
energy: 10,
speed: 0,
};
// Create a machine
const humanMachine = fsm(humanStateChart, data);
// Add conditions, assignments or invoke side effects with chained syntax
humanMachine
.when({
state: "sleeping",
event: "walk",
})
.assign(() => ({
speed: 1,
}));
humanMachine
.when({
state: "walking",
event: "run",
})
.cond((data) => {
return data.energy > 5;
})
.assign((context) => ({
energy: data.energy--,
speed: 10,
}));
humanMachine
.when({
state: "sleeping",
})
.assign((data) => ({
energy: data.energy++,
speed: 0,
}));
// Start machine
export const service = humanMachine.start();
// Interact with machine
service.send("walk");
console.log(service.state.value); // walking
console.log(service.state.context); // { speed: 1 }Features
| SCXML specification | flux-machine | Supported via |
|---|---|---|
| scxml | ✅ | <SCXML> |
| state | ✅ | <State> |
| parallel | ❌ | |
| transition | ✅ | <Transition> |
| initial | ✅ | <State initial> |
| final | ✅ | <Final> |
| onentry | ✅ | .onEntry() |
| onexit | ✅ | .onExit() |
| history | ❌ | |
| raise | ❌ | |
| if | ❌ | |
| elseif | ❌ | |
| else | ❌ | |
| foreach | ❌ | |
| log | ❌ | |
| datamodel | ✅ | fsm(..., data) |
| data | ✅ | fsm(..., data) |
| assign | ✅ | .assign() |
| donedata | ❌ | |
| content | ❌ | |
| param | ❌ | |
| script | ✅ | .action() |
| send | ✅ | .send() |
| cancel | ❌ | |
| invoke | ❌ | |
| finalize | ❌ |
Additional features
| Feature | flux-machine |
|---|---|
| JSX | ✅ |
| SCXML | ❌ |
| JSON | ❌ |
Additional examples
Set an initial state that is not the first state
By default the first state is the initial state
const sc = (
<>
<State id="sleeping"></State>
<State initial id="awake"></State>
</>
);
const service = fsm(sc).start();
console.log(machine.state.value); // awakeRe-use transitions
const goToStart = <Transition event="start" target="1" />;
const goToEnd = <Transition event="end" target="3" />;
const sc = (
<>
<State id="1">{goToEnd}</State>
<State id="2">{goToEnd}</State>
<State id="3">{goToStart}</State>
</>
);Listen to transitions from any state
machine
.when({
event: "end",
})
.action(() => {
console.log("transitioning to end"); // 'end' event was fired from any state
});Project goals
- Match the SCXML specification as closely as possible
- Allows developers to reference the spec directly
- Allows developers learning efforts to be transferable
- Avoids us having to write extensive documentation
- Improved developer experience
- Separate finite and extended state
- Fluent API should provide intellisense to avoid guessing method or property names
- Small bundle size (
< 5kb)- Allows developers to import it into existing projects to address specific problems
- High code coverage (
>= 95%)- Allows developers to be confident the library works as expected
Bundle size
Code coverage
FAQ
Can I use this in production?
- I do not recommend it until it reaches V1.0.0
Why the name flux?
Credit
This library uses @xstate/fsm for its finite state machine.