Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@stone-js/pipeline

stone-foundation349MIT0.1.3TypeScript support: included

An implementation based on the Chain of Responsibility (aka CoR) design pattern.

CoR, Stone.js, Pipeline, Chain of Responsibility

readme

Stone.js - Pipeline

npm npm npm Maintenance Build Status Publish Package to npmjs Quality Gate Status Coverage Security Policy CodeQL Dependabot Status Conventional Commits

An implementation of the Chain of Responsibility (CoR) pattern tailored for modern JavaScript and TypeScript apps using the Continuum Architecture philosophy.


Overview

The Pipeline class is a flexible processor of "passable" values through a series of configurable steps called pipes. Pipes can be functions, factory-generated handlers, or class instances. Pipelines can run synchronously or asynchronously, support custom hook events, and allow pipe resolution via a resolver for advanced dependency injection scenarios.

Installation

npm i @stone-js/pipeline
# or
yarn add @stone-js/pipeline
# or
pnpm add @stone-js/pipeline

[!IMPORTANT] This package is pure ESM. Ensure your package.json includes "type": "module" or configure your bundler appropriately.

import { Pipeline } from '@stone-js/pipeline'

Quick Start

import { Pipeline } from '@stone-js/pipeline'

const addOne = (v, next) => next(v + 1)
const timesTwo = (v, next) => next(v * 2)

const result = Pipeline.create<number>()
  .send(1)
  .through(addOne, timesTwo)
  .sync()
  .thenReturn()

console.log(result) // Output: 4

Features

  • Chain-of-responsibility execution
  • Supports function, factory, and class-based pipes
  • Works in both sync and async mode
  • Custom resolver support
  • Pipe lifecycle hooks via on()
  • Priority-based execution order
  • Type-safe with TypeScript, compatible with JavaScript

Usage Patterns

Synchronous Pipeline

const pipeline = Pipeline.create<number>()
  .send(2)
  .through([
    (v, next) => next(v + 3),
    (v, next) => next(v * 2)
  ])
  .sync()

const result = pipeline.thenReturn()
console.log(result) // Output: 10

Asynchronous Pipeline

const fetch = async (v, next) => next(await mockFetch(v))
const mockFetch = async (v) => new Promise(res => setTimeout(() => res(v * 10), 500))

const result = await Pipeline.create<number>()
  .send(5)
  .through(fetch)
  .thenReturn()

console.log(result) // Output: 50

Using .pipe() Incrementally

const result = Pipeline.create<number>()
  .send(1)
  .pipe(v => v + 1)
  .pipe(v => v * 5)
  .sync()
  .thenReturn()

console.log(result) // Output: 10

Resolver for Dependency Injection

class MyPipe {
  handle(v, next) {
    return next(`Resolved: ${v}`)
  }
}

const resolver = () => new MyPipe()

const result = Pipeline.create<string>({ resolver })
  .send('value')
  .through({ module: MyPipe, isClass: true })
  .sync()
  .thenReturn()

console.log(result) // Output: Resolved: value

Hooking Into Lifecycle

const pipeline = Pipeline.create<number>()
  .on('onProcessingPipe', ({ passable }) => console.log('Processing', passable))
  .on('onPipeProcessed', ({ passable }) => console.log('Processed', passable))
  .send(3)
  .through((v, next) => next(v + 2))
  .sync()

const result = pipeline.thenReturn()
console.log(result) // Output: 5

Factory and Class-Based Pipes

const factoryPipe = () => (v, next) => next(v + 2)

class CustomPipe {
  handle(v, next) {
    return next(v * 3)
  }
}

const result = Pipeline.create<number>()
  .send(1)
  .through(
    { module: CustomPipe, isClass: true },
    { module: factoryPipe, isFactory: true }
  )
  .sync()
  .thenReturn()

console.log(result) // Output: 9

Using .via() to Customize Method Name

class Pipe {
  transform(value, next) {
    return next(value + '!')
  }
}

const result = Pipeline.create<string>()
  .send('Wow')
  .through({ module: Pipe, isClass: true })
  .via('transform')
  .sync()
  .thenReturn()

console.log(result) // Output: Wow!

Priority-based Execution

const p1 = { module: (v, next) => next(v + 1), priority: 10 }
const p2 = { module: (v, next) => next(v * 2), priority: 20 }

const result = Pipeline.create<number>()
  .send(1)
  .through(p1, p2)
  .sync()
  .thenReturn()

console.log(result) // Output: 4 → (1 + 1) * 2

API

All methods are chainable:

  • .send(passable)
  • .through(...pipes)
  • .pipe(...pipes)
  • .sync(true|false)
  • .via(methodName)
  • .on(hookName, listener)
  • .then(fn)
  • .thenReturn()

Pipes can be:

  • Function: (value, next) => next(...)
  • Factory: () => (value, next) => next(...)
  • Class: new MyPipe().handle(...)

Summary

The Pipeline class provides a powerful and flexible way to process values through a series of steps, allowing for both synchronous and asynchronous operations. It supports various types of pipes, including functions, factories, and classes, and offers lifecycle hooks for custom behavior during processing.

Learn More

This package is part of the Stone.js ecosystem, a modern JavaScript framework built around the Continuum Architecture.

Explore the full documentation: https://stonejs.dev

API documentation

Contributing

See Contributing Guide

Credits

Inspired by Laravel's Pipeline

changelog

Change Log

All notable changes to the "Stone.js pipeline" extension will be documented in this file.

Unreleased

0.1.3 (2025-07-01)

Bug Fixes

  • fix type issues by updating type annotations and refactoring parts of the pipe handling logic (#25) (97865f6)

0.1.2 (2025-07-01)

Bug Fixes

  • Add the 'isAlias' flag to clarify pipe handling by marking alias types explicitly (#23) (2c0f031)

0.1.1 (2025-06-12)

Miscellaneous Chores

  • migrate to stone-foundation, integrate sonar cloud and add security policy (#17) (ec2f372)

0.1.0 (2025-05-11)

Features

  • transform pipe to meta pipe and change the license to MIT (14ede7d)

0.0.46 (2024-11-25)

Miscellaneous Chores

  • add custom pipeline error (f7cff0e)

0.0.45 (2024-11-22)

Miscellaneous Chores

  • allow to return undefined (5c1b6a7)

0.0.44 (2024-11-18)

Features

  • replace container by resolver in order to remove the coupling with the container (a70b996)

0.0.43 (2024-11-16)

Bug Fixes

  • import real container from service container and refactor executePipe (ad92185)

0.0.42 (2024-11-15)

Miscellaneous Chores

  • replace jest by vitest and add rollup plugin to bundle types (b0a246c)

0.0.41 (2024-11-11)

Features