@toolsbee/machine
v0.1.0
Published
Tiny, type-safe finite state machine for managing complex logic.
Maintainers
Readme
Machine
Machine is a tiny, type-safe finite state machine for managing complex logic.
It focuses on:
- Zero Dependencies: Lightweight and tree-shakeable (< 1KB).
- Modern APIs: ESM first with CJS fallback.
- Strictness: Built with high strictness TypeScript settings (ES2020 target).
- Features: Guards, Context, Entry/Exit Actions, and Wildcards.
Early development. API stable for v0.1.0.
Maintained by toolsbee.com · https://www.toolsbee.com
Install
npm install @toolsbee/machineQuick Start
import { createMachine } from '@toolsbee/machine';
const toggle = createMachine({
initial: 'inactive',
states: {
inactive: { on: { TOGGLE: 'active' } },
active: { on: { TOGGLE: 'inactive' } }
}
});
toggle.subscribe((state) => console.log(state));
toggle.send('TOGGLE');
// "active"Core API
1. createMachine(config)
Creates a new state machine instance with the given configuration.
const machine = createMachine({
initial: 'idle',
states: {
idle: { on: { START: 'running' } },
running: { on: { STOP: 'idle' } }
}
});2. .send(event)
Sends an event to the machine to trigger a transition.
machine.send('START');
// State transitions to 'running'3. .subscribe(callback)
Listen for state changes. Returns an unsubscribe function.
const unsubscribe = machine.subscribe((state, context) => {
console.log(`Current state: ${state}`);
});4. .can(event)
Check if an event is valid for the current state (respecting guards).
if (machine.can('START')) {
// Safe to send 'START'
}5. .context
Access the current extended state (context) of the machine.
console.log(machine.context);
// { count: 0 }6. .inspect(callback)
Debug all events sent to the machine, even those not handled.
machine.inspect((event, state, context) => {
console.log(`Event: ${event}`, state);
});Advanced Usage
Context and Actions
Store data (context) and execute side-effects (actions) during transitions.
const counter = createMachine({
initial: 'counting',
context: { count: 0 },
states: {
counting: {
on: {
INC: {
target: 'counting',
actions: (ctx) => { ctx.count++ }
}
}
}
}
});Guards (Conditions)
Prevent transitions based on logic using cond.
const form = createMachine({
initial: 'editing',
context: { isValid: false },
states: {
editing: {
on: {
SUBMIT: {
target: 'submitting',
cond: (ctx) => ctx.isValid
}
}
},
submitting: {}
}
});Entry & Exit Actions
Run logic automatically when entering or leaving a state.
const modal = createMachine({
initial: 'closed',
states: {
closed: { on: { OPEN: 'open' } },
open: {
entry: [() => console.log('Opening...')],
exit: [() => console.log('Closing...')]
}
}
});Wildcard Transitions (*)
Handle any unknown event from a state.
const machine = createMachine({
initial: 'idle',
states: {
idle: {
on: {
START: 'running',
'*': 'error' // Catches generic events
}
},
running: {},
error: {}
}
});Browser Usage
<!doctype html>
<html>
<body>
<button id="btn">Toggle</button>
<div id="status">Status: inactive</div>
<script type="module">
import { createMachine } from 'https://cdn.jsdelivr.net/npm/@toolsbee/machine/dist/index.js';
const toggle = createMachine({
initial: 'inactive',
states: {
inactive: { on: { TOGGLE: 'active' } },
active: { on: { TOGGLE: 'inactive' } }
}
});
const status = document.getElementById('status');
// Subscribe to state changes
toggle.subscribe(state => {
status.textContent = `Status: ${state}`;
});
// Send event on click
document.getElementById('btn').onclick = () => {
toggle.send('TOGGLE');
};
</script>
</body>
</html>Design Goals
- Tiny: Minimal footprint, tree-shakeable.
- Modern: Uses modern ESM architecture.
- Zero-Deps: No external dependencies.
- Strict: Built with strict TypeScript settings.
License
MIT
