rest-pipeline-js

Гибкий модульный оркестратор пайплайнов для REST API — последовательные и параллельные этапы, повторные попытки с backoff, кэширование ответов, ограничение частоты запросов, провайдер аутентификации, потоковые этапы (SSE / AsyncIterable), система плагинов и интеграции с Vue / React — и всего одна зависимость (axios).
Возможности
createRestClient()— полнофункциональный HTTP-клиент поверх axios: повторные попытки с экспоненциальным backoff и поддержкойRetry-After, кэширование ответов с подключаемым backendCacheStore(включая точечнуюinvalidateCache()), ограничение частоты запросов (конкурентность + запросы/интервал) с подключаемым распределённымRateLimiterStore, circuit breaker с подключаемым распределённымCircuitBreakerStore, провайдер аутентификации с автоматическим обновлением токена по 401 и опциональным кэшированием токена, отмена запроса по ключу, кастомные HTTP-адаптеры- Трассировка запросов — генерация заголовка W3C
traceparentплюс хукTracingProvider(duck-typing под APISpanиз 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, …) в коллбэках метрик, включено по умолчанию - Интеграция с Vue —
usePipelineRunVue,usePipelineProgressVueи другие (импорт изrest-pipeline-js/vue) - Интеграция с React —
usePipelineRunReact,usePipelineProgressReactи другие (импорт изrest-pipeline-js/react) paginate()/paginateAll()/flattenPages()— обход постраничного API (курсор или offset/limit) какAsyncGenerator<T[]>, отдельно или как источникStreamStageConfigcreateMockAdapter()(отдельная точка входаrest-pipeline-js/testing) — маршрутизируемыйHttpAdapterдля тестирования кода, использующего этот пакет, без реального backend, с историей вызовов и последовательными ответами для проверки повторных попыток- Tree-shakeable —
sideEffects: false; точки входа Vue и React разбиты на отдельные чанки
Установка
npm install rest-pipeline-jsPeer-зависимости для интеграций с фреймворками:
# 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:
<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) — для отладки.
Быстрый старт
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);