Skip to content

Commit 1e79161

Browse files
committed
fix: update README.md
1 parent c0d53eb commit 1e79161

File tree

6 files changed

+408
-245
lines changed

6 files changed

+408
-245
lines changed

README.md

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,122 @@
1-
# typescript-library-starter
1+
# @escapace/fsm
2+
3+
Type-safe finite state machine library for TypeScript.
4+
5+
## Features
6+
7+
- Type-safe state machine definition and execution
8+
- Conditional transitions with predicates
9+
- Context management with reducers
10+
- State change subscriptions
11+
- High-frequency transition performance (8x faster than @xstate/fsm)
12+
13+
## Installation
14+
15+
```bash
16+
npm install @escapace/fsm
17+
```
18+
19+
## Example
20+
21+
```typescript
22+
import { stateMachine, interpret } from '@escapace/fsm'
23+
24+
// Define coin values and state types
25+
type Coin = 5 | 10 | 25 | 50
26+
enum State {
27+
Locked = 'LOCKED',
28+
Unlocked = 'UNLOCKED',
29+
}
30+
enum Action {
31+
Coin = 'COIN',
32+
Push = 'PUSH',
33+
}
34+
35+
// Create a turnstile that requires 50 cents to unlock
36+
const machine = stateMachine()
37+
.state(State.Locked) // Define possible states
38+
.state(State.Unlocked)
39+
.initial(State.Locked) // Set starting state
40+
.action<Action.Coin, { coin: Coin }>(Action.Coin) // Define action with payload type
41+
.action(Action.Push) // Define action without payload
42+
.context<{ total: number }>({ total: 0 }) // Set context type and initial value
43+
.transition(
44+
State.Locked, // From locked state
45+
[
46+
Action.Coin,
47+
(
48+
context,
49+
action, // On coin insert, with predicate
50+
) => context.total + action.payload.coin >= 50,
51+
],
52+
State.Unlocked, // Go to unlocked state
53+
(context, action) => {
54+
// Run this reducer
55+
context.total += action.payload.coin
56+
return context
57+
},
58+
)
59+
.transition(
60+
State.Locked, // Fallback transition when not enough coins
61+
Action.Coin,
62+
State.Locked,
63+
(context, action) => {
64+
// Add coin to total
65+
context.total += action.payload.coin
66+
return context
67+
},
68+
)
69+
.transition(State.Unlocked, Action.Coin, State.Unlocked) // Stay unlocked on coin insert
70+
.transition(
71+
[State.Locked, State.Unlocked], // Push always locks
72+
Action.Push,
73+
State.Locked,
74+
(context) => {
75+
// Reset total on push
76+
context.total = 0
77+
return context
78+
},
79+
)
80+
81+
// Create and use the state machine
82+
const turnstile = interpret(machine)
83+
84+
console.log(turnstile.state) // 'LOCKED'
85+
86+
turnstile.do(Action.Coin, { coin: 25 }) // Insert 25 cents
87+
console.log(turnstile.state) // 'LOCKED'
88+
89+
turnstile.do(Action.Coin, { coin: 25 }) // Insert another 25 cents (total 50)
90+
console.log(turnstile.state) // 'UNLOCKED'
91+
92+
turnstile.do(Action.Push) // Push through turnstile
93+
console.log(turnstile.state) // 'LOCKED'
94+
```
95+
96+
## API
97+
98+
### `stateMachine()`
99+
100+
Creates a new state machine builder.
101+
102+
#### Methods
103+
104+
- `.state(name)` - Define a state
105+
- `.initial(state)` - Set initial state
106+
- `.action<Type, Payload>(name)` - Define an action type
107+
- `.context<Type>(initialValue)` - Set context type and initial value
108+
- `.transition(source, action, target, reducer?)` - Define state transition
109+
110+
### `interpret(machine)`
111+
112+
Creates an executable state machine instance.
113+
114+
#### Properties
115+
116+
- `.state` - Current state (readonly)
117+
- `.context` - Current context (readonly)
118+
119+
#### Methods
120+
121+
- `.do(action, payload?)` - Dispatch an action
122+
- `.subscribe(callback)` - Subscribe to state changes

knip.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
{
22
"$schema": "https://unpkg.com/knip@5/schema.json",
33
"entry": [
4-
"{scripts,perf}/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}",
54
"**/*.{test,spec}.?(c|m)[jt]s?(x)",
65
"**/test/**/*.?(c|m)[jt]s?(x)",
76
"eslint.config.mjs",
87
"src/**/example*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,vue}",
98
"src/cli.ts!",
109
"src/index.ts!",
11-
"src/types.ts"
10+
"src/types.ts",
11+
"vitest.config.*.ts",
12+
"vitest.config.ts",
13+
"{scripts,perf}/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}"
1214
],
1315
"ignore": ["**/*.d.+([a-zA-Z0-9]).ts", "**/*.d.ts", "lib/**"],
1416
"ignoreBinaries": ["ncu"],

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
"@commitlint/cli": "19.8.1",
1212
"@commitlint/config-conventional": "19.8.1",
1313
"@escapace/pnpm-pack": "0.6.0",
14-
"@ls-lint/ls-lint": "2.3.0",
14+
"@ls-lint/ls-lint": "2.3.1",
1515
"@types/lodash-es": "4.17.12",
16-
"@vitest/coverage-v8": "3.1.4",
16+
"@vitest/coverage-v8": "3.2.2",
1717
"@xstate/fsm": "2.1.0",
18-
"eslint": "9.27.0",
18+
"eslint": "9.28.0",
1919
"eslint-config-escapace": "5.7.1",
2020
"esroll": "0.4.5",
21-
"knip": "5.57.2",
21+
"knip": "5.60.2",
2222
"lefthook": "1.11.13",
2323
"lodash-es": "4.17.21",
2424
"prettier": "3.5.3",
@@ -27,7 +27,7 @@
2727
"syncpack": "13.0.4",
2828
"tsx": "4.19.4",
2929
"typescript": "5.8.3",
30-
"vitest": "3.1.4"
30+
"vitest": "3.2.2"
3131
},
3232
"engines": {
3333
"pnpm": ">=10.4.1"

0 commit comments

Comments
 (0)