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

@ksv90/fsm

v0.3.12

Published

Finite State Machine (FSM)

Downloads

49

Readme

Finite State Machine (FSM)

A library for creating Finite State Machines (FSM) with event-driven support. This tool enables state management and event handling in applications, offering flexibility and ease in configuring transitions and actions when state changes.

Table of Contents

  1. Installation
  2. Quick Start
  3. Detailed Functionality
  4. Configuration and Options
  5. Error Handling
  6. License
  7. Acknowledgments and Inspiration
  8. Contribution
  9. Examples

Installation

To install the library, use your preferred package manager:

npm install @ksv90/fsm

This command will add the library to your project's dependencies, allowing you to use the FSM in your code.

FSM requires the @ksv90/decorators package, which is listed as peerDependencies. This means that for npm versions higher than 7, the package will be added automatically if it is not in the core dependencies. Otherwise, you need to add it manually.

Quick Start

Below is a quick example of using a Finite State Machine (FSM). This example demonstrates how to create a simple FSM, add event listeners, and manage transitions between states.

import { StateMachine } from './fsm';

// Creating a new FSM with initial states
const fsm = new StateMachine({
  initState: 'idle',
  context: {},
  states: {
    idle: {
      on: { START: [{ target: 'running' }] },
    },
    running: {
      on: { STOP: [{ target: 'idle' }] },
    },
  },
});

// Subscribing to FSM events using EventEmitter
fsm.on('transition', ({ stateName, nextStateName }) => {
  console.log(`Переход: ${stateName} -> ${nextStateName}`);
});

// Starting the FSM and state transitions
fsm.start(); // Transitions to the 'idle' state
fsm.transition('START'); // Transitions to the 'running' state
fsm.transition('STOP'); // Transitions back to the 'idle' state

This example shows how easy it is to create a finite state machine, start it, add listeners, and manage states using an event-driven model.

Detailed Functionality

States and Transitions

Finite State Machine (FSM) manages transitions between states based on events. Each state defines transitions to other states in response to specific events.

Example state structure:

const fsm = new StateMachine({
  initState: 'idle',
  context: { count: 0 },
  states: {
    idle: {
      entry: [(context) => (context.count += 1)],
      job: async () => {
        console.log('Асинхронная задача');
        await new Promise((resolve) => setTimeout(resolve, 100));
      },
      exit: [(context) => (context.count -= 1)],
      on: {
        START: [
          { target: 'running', cond: (context) => context.count > 0, actions: [(context) => (context.count *= 2)] },
        ],
      },
    },
    running: {
      on: { STOP: [{ target: 'idle' }] },
    },
  },
});

initState: The initial state of the FSM, in this example — idle. states: An object containing the state definitions and possible transitions.

External State Transitions

FSM reacts to events that trigger state transitions. Events are sent using the transition method.

Example of event usage:

fsm.transition('START'); // Transition from 'idle' to 'running'
fsm.transition('STOP');  // Transition from 'running' to 'idle'
  • transition(eventType): Sends an event to the FSM, initiating a corresponding transition if one exists for the current state.

Transition Object

The Transition Object describes possible state transitions and actions that are executed during these transitions. Each transition can include the following properties:

  • target: The state to transition to.
  • actions: Actions executed during the transition.
  • cond: A condition determining whether the transition should occur.
idle: {
  on: { 
    START: [{ target: 'running', cond: (context) => context.count > 0, actions: [(context) => (context.count *= 2)] }] 
  },
}

FSM Context

The context is used to store data between state transitions. It is accessible within all actions and conditions.

context: { count: 0 }

Actions

FSM supports several types of actions:

  • entry: Executed upon entering a state.
  • exit: Executed upon exiting a state.
  • actions: Executed during a transition between states.
idle: {
  entry: [(context) => (context.count += 1)],
  exit: [(context) => (context.count -= 1)],
}

Job

job is an asynchronous or synchronous task executed upon entering a state after the entry actions.

idle: {
  job: async () => {
    await new Promise((resolve) => setTimeout(resolve, 100));
  },
}
idle: {
  job: (_ctx, complete) => {
    setTimeout(complete, 200);
  },
}

If the second argument complete is not specified, the function terminates after all instructions have been executed.

Emit Object

emit is used to automatically trigger events after the completion of state actions and tasks.

idle: {
  emit: [
    { eventType: 'START', cond: (context) => context.count > 10 },
  ],
}

EventEmitter Support

FSM uses EventEmitter to handle events such as the start and end of transitions, state entry, and state exit.

fsm.on('entry', (context) => {
  console.log(`Entering state with context:`, context);
});

Available events:

  • start: FSM started.
  • entry: Entering a state.
  • job: Executing a task within a state.
  • pending: Waiting for a state transition (idle).
  • transition: Transitioning between states.
  • exit: Exiting a state.
  • finish: FSM process completed.
  • stop: FSM stopped.

Each of these events passes specific data to the handler, allowing you to react to changes in the machine's state.

Configuration and Options

Finite State Machine (FSM) supports various configuration options that allow you to customize the behavior of the state machine. These options are defined using StateMachineOptions types.

Example of StateMachineOptions:

export type StateMachineOptions = {
  maxJobTime?: number;
  stopOnError?: boolean;
  jobTimer?: () => Promise<void>;
};
  • maxJobTime: The time in milliseconds allowed for tasks in the state to execute before timing out. If the task does not complete in the allotted time, an error message will be raised. Usage: This parameter is useful for limiting the time asynchronous tasks execute in the state and preventing potential memory leaks. If jobTimer is specified, this parameter will be ignored. A zero or negative value does not start the timer.
const options: StateMachineOptions = {
  maxJobTime: 5000, // 5 seconds to complete the task
};
  • stopOnError: Whether to stop the FSM when an internal error occurs. Defaults to true. This does not apply to runtime errors, only errors that are sent to the error event.
const options: StateMachineOptions = {
  stopOnError: false
};
  • jobTimer: An asynchronous function that will be called together with the job function. If the timer completes before job, the FSM will emit an error event. If timer is not specified, setTimeout will be used.
const options: StateMachineOptions = {
  jobTimer: async () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 1000);
  });
}
};

Error Handling

FSM uses exception handling mechanisms to manage unexpected situations, ensuring the application continues to run smoothly.

Example of error handling using the error event:

fsm.on('error', (error) => {
  console.error('An error occurred in the FSM:', error.message);
  // Error handling logic
});

License

This library is distributed under the MIT license, which means that it can be used by anyone without exception. The MIT license grants users the following rights:

Freedom of use: You can use the library for any purpose, including commercial and non-commercial projects. Freedom of distribution: You are free to copy, modify, and distribute the library or its derivative works. Ease of integration: The license allows you to integrate the library into other projects without having to disclose the source code of your project.

Acknowledgments and Inspiration

This library was inspired by the @xstate/fsm package. I am grateful to the developers of @xstate/fsm for their contribution to the community and creating a powerful tool for managing finite state machines.

I used ideas and concepts from @xstate/fsm to create my own solution tailored to my needs, and added features that I think make state machines even more convenient and powerful for use in real projects.

Contribution

Anyone is welcome to contribute to the development of this library.

Examples