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.