npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

next-machine

v0.0.1

Published

A typed state machine implementation with persistence and debugging capabilities

Readme

My Machine Library

A type-safe state machine library for managing complex workflows in TypeScript, React, and Next.js.

Features

  • Type-safe events and transitions: Ensures correctness at compile time.
  • Immutable context updates: Uses immer for safe and efficient state management.
  • Error handling: Built-in error handling with custom error handlers.
  • Entry/Exit Actions: Support for state entry and exit actions.
  • Guards: Conditional transitions based on context state.
  • Testing utilities: createMockMachine for simplified testing.
  • Hierarchical States: Support for nested state configurations.
  • History States: Track and return to previous states.
  • Delayed Transitions: Time-based state transitions.
  • Persistence: Built-in adapters for event sourcing and state persistence
  • Concurrency Control: Optimistic locking for handling concurrent updates

Installation

npm install my-machine-lib

Basic Usage

import { StateMachine, createState } from 'my-machine-lib';
// Define your context
interface MyContext {
id: string;
count: number;
}
// Define your events
type MyEventMap = {
INCREMENT: void;
DECREMENT: void;
};
const config = {
states: {
idle: createState<MyContext, MyEventMap>('idle')
.on('INCREMENT', 'active', [(ctx) => ({ count: ctx.count + 1 })])
.build(),
active: createState<MyContext, MyEventMap>('active')
.on('DECREMENT', 'idle', [(ctx) => ({ count: ctx.count - 1 })])
.build()
},
initial: 'idle',
context: { id: 'counter-1', count: 0 }
};
const machine = new StateMachine(config);

Persistence

Use the built-in MemoryAdapter or create your own:

import { MemoryAdapter } from 'my-machine-lib';
const persistenceAdapter = new MemoryAdapter<MyContext, MyEventMap>({
maxEventsBeforeSnapshot: 100
});
const machine = new StateMachine({
...config,
persistence: persistenceAdapter
});

Concurrency Control

Handle concurrent updates with optimistic locking:

// Send event with version check
try {
await machine.send(
{ type: 'INCREMENT', data: undefined },
{ expectedVersion: currentVersion }
);
} catch (error) {
if (error instanceof ConcurrencyError) {
// Handle concurrent modification
console.error('Concurrent modification detected');
}
}
// Get current version
const version = machine.getVersion();

Testing

Use the testing utilities for simplified testing:

import { createMockMachine } from 'my-machine-lib';
const { machine, sendEvent, getContext } = createMockMachine({
...config,
persistence: new MemoryAdapter()
});
// Test with version control
await sendEvent(
{ type: 'INCREMENT', data: undefined },
{ expectedVersion: 0 }
);
expect(getContext().count).toBe(1);
expect(machine.getVersion()).toBe(1);

/**

  • How to Create a State Machine
    1. Define event types with data payloads:
  • type Events = {
  • 'EVENT.NAME': { data: string }; // With payload
  • 'EVENT.OTHER': void; // No payload
  • };
    1. Define context interface for state data:
  • interface Context {
  • someData: string;
  • otherData: number;
  • }
    1. Create machine with StateMachine.create<Context, Events>({
  • initial: 'startState',
  • context: {...}, // Initial context values
  • persistence: { // Optional local storage
  • prefix: 'unique-id'  
  • },
  • states: {
  • stateName: {
  •   id: 'stateName',
  •   on: {
  •     'EVENT.NAME': {
  •       target: 'nextState',
  •       actions: [(ctx, event, send) => {
  •         // Modify context
  •         Object.assign(ctx, {...});
  •         // Optionally send new events
  •         send({type: 'EVENT.OTHER'});
  •       }]
  •     }
  •   }
  • }
  • }
  • });
  • Key Rules:
    • Context is modified via Object.assign(ctx, {...})
    • Use send() to trigger new events from actions
    • Each state needs unique id matching its key
    • Events can transition between states via target */

License

This library is open-sourced under the MIT License - see the LICENSE file for details.