Skip to main content

NestJS Workflow & State Machine

Overview​

A powerful, intuitive workflow management tool built specifically for NestJS and Node.js applications. This library allows you to define, manage, and execute workflows using a straightforward, declarative syntax, transforming complex state transitions into structured, maintainable code.

Instead of writing intricate conditional logic scattered across your application, NestJS Workflow provides a centralized approach to workflow management, leading to clearer code, better governance, and improved maintainability.

Installation​

npm install @jescrich/nestjs-workflow

or using Yarn:

yarn add @jescrich/nestjs-workflow

Usage​

Module Registration​

import { Module } from '@nestjs/common';
import { WorkflowModule } from '@jescrich/nestjs-workflow';

@Module({
imports: [
WorkflowModule.register({
name: 'orderWorkflow',
definition: orderWorkflowDefinition,
}),
WorkflowModule.forRoot({ storage: { type: 'memory' } }),
],
})
export class AppModule {}

app.module.ts

Define a Workflow​

import { WorkflowDefinition } from '@jescrich/nestjs-workflow';
import { Order, OrderEvent, OrderStatus } from '../orders/types';

const orderWorkflowDefinition: WorkflowDefinition<Order, any, OrderEvent, OrderStatus> = {
FinalStates: [OrderStatus.Completed, OrderStatus.Failed],
Transitions: [
{
from: OrderStatus.Pending,
to: OrderStatus.Processing,
event: OrderEvent.Submit,
conditions: [(entity) => entity.price > 10],
},
{
from: OrderStatus.Pending,
to: OrderStatus.Pending,
event: OrderEvent.Update,
actions: [(entity, payload) => {
entity.price = payload.price;
entity.items = payload.items;
return Promise.resolve(entity);
}],
},
{
from: OrderStatus.Processing,
to: OrderStatus.Completed,
event: OrderEvent.Complete,
},
{
from: OrderStatus.Processing,
to: OrderStatus.Failed,
event: OrderEvent.Fail,
},
],
};

export default orderWorkflowDefinition;

order.workflow.ts

Using Workflows in Services​

import { Injectable, Inject } from '@nestjs/common';
import { Workflow } from '@jescrich/nestjs-workflow';
import { Order, OrderEvent } from './types';

@Injectable()
export class OrderService {
constructor(
@Inject('orderWorkflow') private readonly workflow: Workflow<Order, OrderEvent>,
) {}

async submitOrder(urn: string) {
return await this.workflow.emit({ urn, event: OrderEvent.Submit });
}

async updateOrder(urn: string, price: number, items: string[]) {
return await this.workflow.emit({
urn,
event: OrderEvent.Update,
payload: { price, items },
});
}
}

orders.service.ts

Class-based Actions with Decorators​

import { Injectable } from '@nestjs/common';
import { WorkflowAction, OnEvent, OnStatusChanged } from '@jescrich/nestjs-workflow';
import { Order, OrderEvent, OrderStatus } from '../orders/types';

@Injectable()
@WorkflowAction()
export class OrderActions {
@OnEvent({ event: OrderEvent.Submit })
execute({ entity, payload }: { entity: Order; payload: any }) {
entity.price *= 100;
return Promise.resolve(entity);
}

@OnStatusChanged({ from: OrderStatus.Pending, to: OrderStatus.Processing })
onProcessing({ entity }: { entity: Order }) {
entity.name = 'Processing Order';
return Promise.resolve(entity);
}
}

order.actions.ts

Benefits​

Maintainability​

Workflow definitions centralize state logic, making it easy to update or extend. This reduces the cognitive load on developers and simplifies debugging.

Architecture Governance​

NestJS Workflow enforces clear and consistent state management practices. Developers adhere to a structured approach, aligning code with enterprise architecture standards.

Scalability & Extensibility​

The workflow engine integrates seamlessly into NestJS applications, enabling easy extension through custom actions, conditions, and event handlers.

Event-Driven & Declarative​

Built on NestJS's event system, the workflow module enables clear and robust event-driven architectures that are easier to reason about and document.

API Reference​

WorkflowModule​

// Register a specific workflow
WorkflowModule.register({
name: string,
definition: WorkflowDefinition<Entity, Payload, Event, Status>
})

// Configure the workflow module globally
WorkflowModule.forRoot({
storage: { type: 'memory' | 'database' }
})

WorkflowDefinition​

interface WorkflowDefinition<Entity, Payload, Event, Status> {
FinalStates: Status[];
Transitions: Array<{
from: Status;
to: Status;
event: Event;
conditions?: Array<(entity: Entity) => boolean>;
actions?: Array<(entity: Entity, payload?: Payload) => Promise<Entity>>;
}>;
}

Workflow Service​

// Emit an event to trigger a workflow transition
workflow.emit({
urn: string,
event: Event,
payload?: any
}): Promise<Entity>

Decorators​

  • @WorkflowAction() - Mark a class as containing workflow action handlers
  • @OnEvent({ event }) - Define an event handler method
  • @OnStatusChanged({ from, to }) - Define a status transition handler method

From Chaos to Clarity​

By adopting NestJS Workflow, you transform complex, error-prone state transitions into structured, clear, and maintainable workflows. This architectural clarity improves team efficiency, reduces bugs, and makes scaling enterprise applications much smoother.

Repository​

Explore NestJS Workflow & State Machine: https://github.com/jescrich/nestjs-workflow

License​

This project is licensed under the MIT License.