# mfsm

> my finite state machine. not yours. don't use it.

Latest version **3.1.0** (published 2026-08-30) · MIT license · 0 weekly downloads

## Install

```sh
npm install mfsm
pnpm add mfsm
yarn add mfsm
bun add mfsm
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 3.1.0 |
| Published | 2026-08-30 |
| First published | 2021-01-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 3 |
| Unpacked size | 25.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 0 |
| Author | Alex Robson |
| Maintainers | arobson |
| Keywords | fsm, finite state machine, typescript |

## Links

- npm: https://www.npmjs.com/package/mfsm
- Repository: https://github.com/distsys-labs/mfsm
- Homepage: https://github.com/distsys-labs/mfsm#readme
- Issues: https://github.com/distsys-labs/mfsm/issues
- npm.io page: https://npm.io/package/mfsm

## Dependencies (3)

- [logging](https://npm.io/package/logging.md) ^4.2.0
- [fauxdash](https://npm.io/package/fauxdash.md) ^1.9.1
- [topic-dispatch](https://npm.io/package/topic-dispatch.md) ^4.0.0

## Alternatives

- [@openai/codex-sdk](https://npm.io/package/@openai/codex-sdk.md) — 731.4K weekly downloads
- [babel-plugin-transform-react-jsx](https://npm.io/package/babel-plugin-transform-react-jsx.md) — 565.0K weekly downloads
- [babel-helper-remove-or-void](https://npm.io/package/babel-helper-remove-or-void.md) — 508.5K weekly downloads
- [@pnpm/store-controller-types](https://npm.io/package/@pnpm/store-controller-types.md) — 186.9K weekly downloads
- [react-native-signature-canvas](https://npm.io/package/react-native-signature-canvas.md) — 155.6K weekly downloads

## Recent versions

- 3.1.0 (latest) — 2026-08-30
- 3.0.0 — 2026-02-07
- 2.0.0 — 2021-04-22
- 1.6.0 — 2021-04-06
- 1.5.0 — 2021-03-12
- 1.4.0 — 2021-02-27
- 1.3.3 — 2021-02-24
- 1.3.2 — 2021-02-22
- 1.3.1 — 2021-02-22
- 1.3.0 — 2021-02-22
- 1.2.0 — 2021-01-27
- 1.1.2 — 2021-01-24
- 1.1.1 — 2021-01-24
- 1.1.0 — 2021-01-22
- 1.0.0 — 2021-01-22

## README

## My Finite State Machine

No really, this is probably not for you.

## Installation

```bash
npm install mfsm
```

**Requirements:**
- Node.js 22 or higher
- ESM only (no CommonJS support)

## Usage

### TypeScript

```typescript
import fsm from 'mfsm'
import type { FSMDefinition, FSMInstance } from 'mfsm'
import client from 'something'

const clientFsm: FSMInstance = fsm({
    api: {
        connect: function () {
            this.handle('connect')
            return this.after('connected')
        },
        disconnect: function () {
            this.handle('disconnect')
            return this.after('disconnected')
        }
    },
    init: {
        url: process.env.HOST_URL,
        client: client,
        default: 'disconnected'
    },
    states: {
        connected: {
            disconnect: function () {
                this.client.disconnect()
                    .then(
                        () => {
                            this.handle('disconnect')
                        }
                    )
            }
        },
        connecting: {
            disconnect: { deferUntil: 'connected' }
        },
        disconnecting: {
            connect: { deferUntil: 'disconnected' }
        },
        disconnected: {
            onEntry: { emit: 'ready', wait: 50 },
            connect: function () {
                this.client.connect(this.url)
                    .then(
                        () => {
                            this.next('connected')
                        }
                    )
                this.next('connecting')
                this.once('closed', () => {
                    this.next('disconnected')
                })
            }
        }
    }
}
})

clientFsm.connect()
    .then(() => { console.log("connection established") })
```

### JavaScript (ESM)

```javascript
import fsm from 'mfsm'

const clientFsm = fsm({
    api: {
        connect() {
            this.handle('connect')
            return this.after('connected')
        },
        disconnect() {
            this.handle('disconnect')
            return this.after('disconnected')
        }
    },
    init: {
        url: process.env.HOST_URL,
        client: client,
        default: 'disconnected'
    },
    states: {
        connected: {
            disconnect() {
                this.client.disconnect()
                    .then(() => {
                        this.handle('disconnect')
                    })
            }
        },
        connecting: {
            disconnect: { deferUntil: 'connected' }
        },
        disconnecting: {
            connect: { deferUntil: 'disconnected' }
        },
        disconnected: {
            onEntry: { emit: 'ready', wait: 50 },
            connect() {
                this.client.connect(this.url)
                    .then(() => {
                        this.next('connected')
                    })
                this.next('connecting')
                this.once('closed', () => {
                    this.next('disconnected')
                })
            }
        }
    }
})

clientFsm.connect()
    .then(() => { console.log("connection established") })
```

## Declarative Handle Properties

 * `emit` - emits an event from the FSM
 * `next` - transitions FSM to a new state
 * `after` - shorthand for deferUntil
 * `deferUntil` - delays handling the event until after a specific state has occurred
 * `forward` - forwards the event to a new state (after + next)
 * `wait` - amount of time (in ms) to wait before emitting events or transitioning

## Event Patterns

The FSM uses [topic-dispatch](https://github.com/arobson/topic-dispatch) for event handling, which supports AMQP-style wildcard patterns:

```typescript
// Listen to all events
machine.on('*', (event, topic) => {
  console.log(`Event on ${topic}:`, event)
})

// Pattern matching (see topic-dispatch docs for more patterns)
machine.on('state.*', handler)  // Match state.connected, state.idle, etc.
```

## Version 3.0.0 Changes

This is a major rewrite with breaking changes:

- **ESM-only**: No CommonJS support. Use ESM imports (`import`) only.
- **TypeScript**: Full TypeScript support with complete type definitions.
- **Node.js 22+**: Minimum Node.js version is now 22.
- **Modern dependencies**: Updated to latest versions with ESM and TypeScript support.
  - `fauxdash` ^1.8.6 (ESM + TypeScript)
  - `topic-dispatch` ^3.0.0 (ESM + TypeScript)
  - `logging` ^4.2.0 (ESM)
- **Modern tooling**: Built with TypeScript, tested with Vitest.

---
_Source: https://npm.io/package/mfsm · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
