Skip to content

rest-pipeline-js

rest-pipeline-js

Гибкий модульный оркестратор пайплайнов для REST API — последовательные и параллельные этапы, повторные попытки с backoff, кэширование ответов, ограничение частоты запросов, провайдер аутентификации, потоковые этапы (SSE / AsyncIterable), система плагинов и интеграции с Vue / React — и всего одна зависимость (axios).

Возможности

  • createRestClient() — полнофункциональный HTTP-клиент поверх axios: повторные попытки с экспоненциальным backoff и поддержкой Retry-After, кэширование ответов с подключаемым backend CacheStore (включая точечную invalidateCache()), ограничение частоты запросов (конкурентность + запросы/интервал) с подключаемым распределённым RateLimiterStore, circuit breaker с подключаемым распределённым CircuitBreakerStore, провайдер аутентификации с автоматическим обновлением токена по 401 и опциональным кэшированием токена, отмена запроса по ключу, кастомные HTTP-адаптеры
  • Трассировка запросов — генерация заголовка W3C traceparent плюс хук TracingProvider (duck-typing под API Span из OpenTelemetry) для подключения реального backend трассировки
  • Ключи идемпотентности — заголовок Idempotency-Key на изменяющих запросах, вручную или автоматически генерируется на один логический запрос через все попытки повтора
  • Очередь офлайн-запросов — постановка в очередь изменяющих запросов, сделанных в офлайне, и их повтор (один и тот же ключ идемпотентности на каждой попытке) после восстановления связи; подключаемое хранилище, isOnline/onOnlineChange для не-браузерных окружений
  • PipelineOrchestrator — последовательное и параллельное выполнение этапов; у каждого этапа есть хуки condition, before, request, after, validateInput, validateOutput, errorHandler (все получают AbortSignal пайплайна); пул sharedData, общий для всех этапов
  • Восстановление после ошибокerrorHandler может вернуть recoverStep(data), чтобы превратить провалившийся этап в успешный и продолжить пайплайн, а не просто преобразовать ошибку
  • Глобальные middleware — хуки beforeEach / afterEach / onError, применяемые ко всем этапам без изменения конфигурации каждого из них
  • Параллельные группы — несколько этапов выполняются одновременно через Promise.all либо через пул с ограничением через concurrency; при провале одного этапа группа останавливается
  • Пауза / Продолжение / Прерываниеpause() ждёт после завершения текущего этапа; resume() продолжает выполнение; abort() отменяет текущий HTTP-запрос и передаёт свой AbortSignal в каждый хук этапа, чтобы пользовательские функции request/before/after тоже могли прервать свою работу
  • Экспорт / импорт состояния — сериализация stageResults и логов в обычный объект; восстановление при следующей загрузке страницы
  • Потоковые этапыstream: async function* для SSE / любого AsyncIterable; коллбэк onChunk в реальном времени; учитывает прерывание
  • Этапы WebSocket — этап поверх постоянного соединения (onOpen/onMessage/onClose/onError, closeOn); подключаемый createWebSocket (по умолчанию globalThis.WebSocket) для Node <22/edge-окружений
  • Метрики пайплайна и корреляция запусков — коллбэки onPipelineStart, onPipelineEnd, onStepDuration, а также runId (также доступен через getRunId(), в записях логов и событиях шагов), общий для всех коллбэков/событий одного запуска
  • Билдер createPipeline() / pipe() — короткая фабрика и fluent-API для распространённых паттернов; в TypeScript цепочки pipe().step() автоматически выводят тип prev из предыдущего шага
  • validatePipelineConfig() — отлавливает дублирующиеся ключи, пустые ключи, ошибки типов ещё до выполнения
  • Система плагинов — устанавливайте переиспользуемое поведение (логирование, аналитика и т. д.); очистка через destroy()
  • Адаптер сохранения состояния — подключаемый интерфейс save/load; автосохранение после каждого этапа
  • Санитизация логов — маскирование чувствительных заголовков (authorization, x-api-key, cookie, …) в коллбэках метрик, включено по умолчанию
  • Интеграция с VueusePipelineRunVue, usePipelineProgressVue и другие (импорт из rest-pipeline-js/vue)
  • Интеграция с ReactusePipelineRunReact, usePipelineProgressReact и другие (импорт из rest-pipeline-js/react)
  • paginate() / paginateAll() / flattenPages() — обход постраничного API (курсор или offset/limit) как AsyncGenerator<T[]>, отдельно или как источник StreamStageConfig
  • createMockAdapter() (отдельная точка входа rest-pipeline-js/testing) — маршрутизируемый HttpAdapter для тестирования кода, использующего этот пакет, без реального backend, с историей вызовов и последовательными ответами для проверки повторных попыток
  • Tree-shakeablesideEffects: false; точки входа Vue и React разбиты на отдельные чанки

Установка

bash
npm install rest-pipeline-js

Peer-зависимости для интеграций с фреймворками:

bash
# Vue
npm install vue@>=3.3

# React
npm install react@>=19 react-dom@>=19

Использование через CDN

Без бандлера, без Node — один тег <script> подключает базовый модуль (PipelineOrchestrator / createRestClient / всё из базовой точки входа, без Vue/React) со встроенным axios, так что больше ничего подгружать не нужно. Собран как самодостаточный IIFE, который экспонирует глобальную переменную window.RestPipeline — обычный тег <script>, без поддержки загрузчиков CommonJS/AMD:

html
<script src="https://unpkg.com/rest-pipeline-js/dist/umd/rest-pipeline.umd.min.js"></script>
<script>
  const { createRestClient, PipelineOrchestrator } = RestPipeline;

  const client = createRestClient({ baseURL: "https://api.example.com" });

  const pipeline = new PipelineOrchestrator({
    config: {
      stages: [{ key: "user", request: () => client.get("/me") }],
    },
  });

  pipeline.run().then((result) => console.log(result));
</script>

Для продакшена фиксируйте версию (rest-pipeline-js@2.1.0/dist/umd/...) — незафиксированный URL выше всегда указывает на последний релиз. jsDelivr работает так же: https://cdn.jsdelivr.net/npm/rest-pipeline-js/dist/umd/rest-pipeline.umd.min.js.

Также опубликована неминифицированная сборка с source map (rest-pipeline.umd.js) — для отладки.

Быстрый старт

js
import { createRestClient, PipelineOrchestrator } from "rest-pipeline-js";

// 1. Создаём REST-клиент
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 () => {
      /* обновление токена */
    },
  },
});

const res = await client.get("/users/1");

// 2. Запускаем пайплайн
const orchestrator = new PipelineOrchestrator({
  config: {
    stages: [
      {
        key: "fetchUser",
        request: async ({ sharedData }) =>
          client.get(`/users/${sharedData.userId}`),
      },
      {
        key: "processData",
        request: async ({ prev }) => ({ ...prev.data, processed: true }),
      },
    ],
  },
  sharedData: { userId: 42 },
});

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