Skip to content

Rest Pipeline JS

v2.1.5NetworkingVanilla JSVueReact

Flexible, modular pipeline orchestrator for REST APIs — retry with backoff, caching, rate limiting, streaming, plugin system, and Vue/React integrations.

Rest Pipeline JS
Get started →
npm install rest-pipeline-js@latest
01 — Purpose

When you'd reach for this

A plain fetch call with error handling works fine until your project needs retries, caching, rate limits, and token refresh all at once — rest-pipeline-js pulls all of that into one configurable pipeline instead of scattered ad-hoc code for every case.

A checkout shouldn't double-charge

A shopper taps "Pay" twice because the network stalls — idempotency keys guarantee the retry doesn't create a second order, and an offline queue delivers the operation once the connection comes back if it drops entirely.

A dashboard is assembled from dependent requests

One request returns a list of objects, the next pulls metrics for each one, a third compares them to the previous period, and each step's result shapes the parameters of the next. The whole chain is described as a single pipeline, where each step automatically receives what it needs from the one before it, instead of requests nested inside each other and data passed around by hand.

Booking a service means several linked checks

Confirming a reservation means checking slot availability, pricing in a discount, reserving the spot, and sending a notification — if one step fails, you need to know exactly what already happened and retry just the stuck step instead of starting the whole flow over.

A server response fails validation

A validation schema (Zod, Yup, or Valibot) catches a malformed response before it reaches the rest of your code, and the process itself gets a chance to fall back to a default value instead of aborting entirely.

02 — Features

At a glance

Powerful HTTP client with advanced features

Powerful HTTP client with advanced features

Create clients with retries (exponential backoff, Retry‑After, jitter), caching (TTL, stale‑while‑revalidate, invalidation), rate limiting (local and distributed), automatic authentication with token refresh, circuit breaker, request cancellation by key, idempotency, and an offline queue for mutating operations.

Pipeline orchestrator with sequential and parallel stages

Pipeline orchestrator with sequential and parallel stages

Build flexible pipelines from sequential and parallel stage groups with conditions, before/after/errorHandler hooks, shared context (sharedData), pause/resume, state export/import, rerunning individual steps, and nested sub‑pipelines. Control execution with AbortSignal and collect metrics.

Stream stages and WebSocket

Stream stages and WebSocket

Use stream stages for SSE and any AsyncIterable with real‑time chunk handling (onChunk) and cancellation support. WebSocket stages provide persistent connections with onOpen/onMessage/onClose/onError callbacks, automatic closing by condition, timeouts, and integration with the abort signal.

Ready‑to‑use integration with Vue 3 and React 19+

Ready‑to‑use integration with Vue 3 and React 19+

Vue composables and React hooks (usePipelineRun, usePipelineProgress) let you run pipelines and track progress in components. All hooks are SSR‑safe. Plugins, global middleware, metrics, and tracing (W3C traceparent, OpenTelemetry) are easily attached without changing stage logic.

Resilience, testing, and adaptability

Resilience, testing, and adaptability

Offline queue, idempotency keys, and step recovery via recoverStep ensure reliability. Schema validation (Zod, Yup, Valibot) and custom HTTP adapters (fetch, edge) adapt the library to any environment. A built‑in mock adapter simplifies testing without a real backend.

Pagination helpers and a fluent pipeline builder

Pagination helpers and a fluent pipeline builder

Ready‑made paginate, paginateAll, and flattenPages helpers save you from hand‑writing pagination loops — cursor‑based or offset‑based, including automatic stopping on a condition. Pipelines can also be built with a fluent createPipeline().pipe().step() API, with types inferred automatically.

03 — Quick example

See how it works

A client with retries, caching, and auth

Set up the REST client once — from there it handles retries, caching, and token refresh on its own.

client.ts
import { createRestClient } from 'rest-pipeline-js'

const client = createRestClient({
  baseURL: 'https://api.example.com',
  retry: { attempts: 2, delayMs: 500, backoffMultiplier: 2 },
  cache: { enabled: true, ttlMs: 60000 },
  auth: {
    getToken: async () => localStorage.getItem('token') ?? '',
    onUnauthorized: async () => {
      // refresh the token here
    },
  },
})

const user = await client.get('/users/1')

A pipeline on top of it

Chain steps into a pipeline — each one gets the previous result through sharedData.

pipeline.ts
import { PipelineOrchestrator } from 'rest-pipeline-js'

const orchestrator = new PipelineOrchestrator({
  config: {
    stages: [
      {
        key: 'fetchUser',
        request: ({ sharedData }) => client.get(`/users/${sharedData.userId}`),
      },
      {
        key: 'processData',
        request: ({ prev }) => ({ ...prev.data, processed: true }),
      },
    ],
  },
  sharedData: { userId: 42 },
})

const result = await orchestrator.run()
console.log(result.success, result.stageResults)

A circuit breaker for a failing backend

After a run of consecutive failures, the client stops hitting the dead API and rejects requests locally right away — then probes on its own to see if it's back.

circuit-breaker.ts
import { createRestClient, CircuitOpenError } from 'rest-pipeline-js'

const client = createRestClient({
  baseURL: 'https://api.example.com',
  circuitBreaker: {
    failureThreshold: 5, // open after 5 consecutive failures
    openMs: 30_000, // stay open for 30s before probing again
    isFailure: (error) => error.status === undefined || error.status >= 500, // ignore 4xx
  },
})

try {
  await client.get('/flaky-endpoint')
} catch (err) {
  if (err instanceof CircuitOpenError) {
    // rejected locally — no network call was made
  }
}