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

@camcima/finita

v2.2.0

Published

A full-featured finite state machine library for TypeScript

Readme

CI CodeQL codecov npm version License: MIT TypeScript Node.js

A full-featured finite state machine (FSM) library for TypeScript.

This library is a TypeScript port of metabor/statemachine, the PHP state machine library created by Oliver Tischlinger. The original library was the engine behind Bob -- the backend component of the Alice & Bob retail system that Rocket Internet used to power its e-commerce ventures worldwide. The author of this TypeScript port and Oliver worked together at Rocket Internet, where the state machine proved itself at scale across multiple global operations.

Features

  • Type-Safe Subjects -- generic TSubject parameter gives you typed access to the domain object, with unknown default for backward compatibility
  • Async-First -- all conditions, observers, and mutexes support async operations via MaybePromise<T> return types
  • States, Transitions, Events -- define complex workflows declaratively
  • Conditions (Guards) -- control when transitions are allowed, with composable AND/OR/NOT logic
  • Observers (Commands) -- execute side effects when events fire or states change
  • Automatic Transitions -- transitions that fire when a condition becomes true, without an explicit event
  • Transition Selectors -- pluggable strategies for resolving ambiguous transitions (score-based, weight-based)
  • Mutex/Locking -- concurrency control with pluggable lock adapters
  • Factory Pattern -- create pre-configured state machines from subject objects
  • Process Merging -- combine state collections with optional name prefixing
  • Graph Visualization -- build graph data structures for rendering with GraphViz or other tools
  • Setup Helper -- fluent API for building state machines from configuration
  • Zero Dependencies -- no runtime dependencies

Installation

npm install @camcima/finita

Quick Start

stateDiagram-v2
    [*] --> draft
    draft --> published : publish
    published --> archived : archive
    archived --> draft : reopen
import { State, Transition, Process, Statemachine } from "@camcima/finita";

// Define states
const draft = new State("draft");
const published = new State("published");
const archived = new State("archived");

// Define transitions
draft.addTransition(new Transition(published, "publish"));
published.addTransition(new Transition(archived, "archive"));
archived.addTransition(new Transition(draft, "reopen"));

// Create process and state machine
const process = new Process("article-workflow", draft);
const article = { title: "Hello World" };
const sm = new Statemachine(article, process);

console.log(sm.getCurrentState().getName()); // 'draft'

await sm.triggerEvent("publish");
console.log(sm.getCurrentState().getName()); // 'published'

await sm.triggerEvent("archive");
console.log(sm.getCurrentState().getName()); // 'archived'

// Note: use top-level await (supported in ES modules) or wrap in an async function.

Typed Usage

Use the TSubject generic parameter for type-safe access to your domain object -- no more casts:

import {
  State,
  Transition,
  Process,
  Statemachine,
  CallbackCondition,
} from "@camcima/finita";

interface Order {
  id: number;
  total: number;
}

const pending = new State("pending");
const approved = new State("approved");

// subject is typed as Order -- no cast needed
const canApprove = new CallbackCondition<Order>(
  "canApprove",
  (order) => order.total <= 1000,
);
pending.addTransition(new Transition(approved, "review", canApprove));

const process = new Process("order", pending);
const sm = new Statemachine<Order>({ id: 1, total: 500 }, process);

const order = sm.getSubject(); // typed as Order
console.log(order.total); // 500

Concepts

A state machine consists of:

| Concept | Description | | ---------------- | -------------------------------------------------------------------------------------------------------------------- | | State | A named node in the workflow graph. Holds transitions, events, and metadata. | | Transition | A directed edge from one state to another, optionally guarded by a condition and triggered by an event. | | Event | A named trigger attached to a state. When invoked, it fires observers (commands) and initiates transitions. | | Condition | A guard that determines whether a transition is active. | | Process | A named collection of states that defines a complete workflow, starting from an initial state. | | Statemachine | The runtime orchestrator that manages the current state, triggers events, checks conditions, and notifies observers. | | Observer | A callback that reacts to events or state changes. |

classDiagram
    direction LR
    Process *-- State : contains
    State *-- Transition : has outgoing
    State *-- Event : has named
    Transition --> State : targets
    Transition --> Condition : guarded by
    Event --> Observer : notifies
    Statemachine --> Process : uses
    Statemachine --> State : tracks current
    Statemachine --> Observer : notifies on change

Documentation

Detailed documentation for every component:

  • Core -- State, Transition, Event, Process, Statemachine, Dispatcher, StateCollection
  • Conditions -- Tautology, Contradiction, CallbackCondition, Timeout, AndComposite, OrComposite, Not
  • Observers -- CallbackObserver, StatefulStatusChanger, OnEnterObserver, TransitionLogger
  • Filters -- ActiveTransitionFilter, FilterStateByEvent, FilterStateByTransition, FilterStateByFinalState, FilterTransitionByEvent
  • Selectors -- OneOrNoneActiveTransition, ScoreTransition, WeightTransition
  • Mutex -- NullMutex, LockAdapterMutex, MutexFactory
  • Factory -- Factory, SingleProcessDetector, AbstractNamedProcessDetector, StatefulStateNameDetector
  • Utilities -- SetupHelper, StateCollectionMerger
  • Graph -- GraphBuilder
  • Errors -- WrongEventForStateError, LockCanNotBeAcquiredError, DuplicateStateError
  • Interfaces -- All TypeScript interfaces

Examples

A complete working example (order processing with prepayment and postpayment workflows) is available in the finita-example repository.

Architecture

src/
  index.ts                 # Barrel export
  MaybePromise.ts          # MaybePromise<T> = T | Promise<T> utility type
  Event.ts                 # Event implementation
  State.ts                 # State implementation
  Transition.ts            # Transition implementation
  StateCollection.ts       # Named collection of states
  Process.ts               # Process (workflow definition)
  Statemachine.ts          # Runtime state machine
  Dispatcher.ts            # Deferred event dispatcher
  interfaces/              # All TypeScript interfaces
  condition/               # Condition (guard) implementations
  observer/                # Observer implementations
  filter/                  # State and transition filters
  selector/                # Transition selection strategies
  mutex/                   # Locking implementations
  factory/                 # State machine factory pattern
  util/                    # SetupHelper, StateCollectionMerger
  graph/                   # Graph visualization builder
  error/                   # Custom error classes

Security

CI

  • CodeQL -- static analysis for security vulnerabilities (push, PR, weekly)
  • OSV-Scanner -- dependency vulnerability scanning against the OSV database (push, PR, weekly)
  • Dependabot -- automated PRs for dependency and GitHub Actions updates (weekly)

Local (via Lefthook)

  • Gitleaks -- scans staged files for secrets on every commit (auto-skipped if not installed)

Manual checks

npm run security:audit    # npm dependency audit
npm run security:secrets  # Scan full repo for secrets (requires gitleaks)

Install Gitleaks: https://github.com/gitleaks/gitleaks#installing

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Type check
npm run lint

# Build
npm run build

License

MIT