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

Простой fetch с обработкой ошибок работает, пока в проекте не понадобились retry, кэш, лимиты запросов и обновление токена одновременно — rest-pipeline-js собирает всё это в один настраиваемый пайплайн вместо россыпи разрозненного кода на каждый случай.
Покупатель дважды нажимает «Оплатить» из-за медленной сети — идемпотентные ключи гарантируют, что повторный запрос не создаст второй заказ, а офлайн-очередь довозит операцию, если соединение обрывается совсем.
Первый запрос отдаёт список объектов, второй — метрики по каждому, третий — сравнение с прошлым периодом, и результат каждого шага определяет параметры следующего. Вся эта цепочка описывается одним пайплайном, где каждый шаг сам получает нужные данные от предыдущего — вместо запросов, вложенных друг в друга, и ручной передачи результатов между ними.
Перед подтверждением брони нужно проверить доступность слота, рассчитать цену со скидками, зарезервировать место и отправить уведомление — если один из шагов падает, важно понимать, что уже случилось, и повторить именно застрявший шаг, а не весь процесс заново.
Схема валидации (Zod, Yup или Valibot) ловит некорректный ответ до того, как он попадёт в остальной код, а сам процесс получает шанс подставить значение по умолчанию вместо аварийного завершения целиком.

Создавайте клиенты с повторными попытками (экспоненциальная задержка, Retry‑After, jitter), кэшированием (TTL, stale‑while‑revalidate, инвалидация), ограничением частоты (локальным и распределённым), автоматической аутентификацией с обновлением токена, защитой от сбоев (circuit breaker), отменой запросов по ключу, идемпотентностью и офлайн‑очередью мутирующих операций.

Стройте гибкие пайплайны из последовательных и параллельных групп этапов с условиями, хуками before/after/errorHandler, общим контекстом (sharedData), паузой и возобновлением, экспортом/импортом состояния, перезапуском отдельных шагов и вложенными подпайплайнами. Управляйте выполнением с помощью AbortSignal и метрик.

Используйте stream-этапы для обработки SSE и любых AsyncIterable с получением чанков в реальном времени (onChunk) и поддержкой отмены. WebSocket-этапы обеспечивают постоянное соединение с колбэками onOpen/onMessage/onClose/onError, автоматическим закрытием по условию, таймаутами и интеграцией с сигналом отмены.

Vue-композаблы и React-хуки (usePipelineRun, usePipelineProgress) позволяют запускать пайплайны и отслеживать прогресс в компонентах. Все хуки SSR-безопасны. Плагины, глобальные middleware, метрики и трассировка (W3C traceparent, OpenTelemetry) легко подключаются без изменения логики этапов.

Офлайн‑очередь, идемпотентные ключи и восстановление шагов через recoverStep обеспечивают надёжность. Валидация схем (Zod, Yup, Valibot) и кастомные HTTP-адаптеры (fetch, edge) адаптируют библиотеку под любую среду. Встроенный mock-адаптер упрощает тестирование без реального бекенда.

Готовые хелперы paginate, paginateAll и flattenPages избавляют от ручного написания циклов пагинации — от курсорной до offset, включая автоматическую остановку по условию. Пайплайны можно строить и через fluent-API createPipeline().pipe().step(), где TypeScript выводит тип данных автоматически.
Один раз настраиваем REST-клиент — дальше он сам обрабатывает повторные попытки, кэш и обновление токена.
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') Собираем шаги в пайплайн — каждый получает результат предыдущего через sharedData.
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)После нескольких неудач подряд клиент перестаёт бить по упавшему API и сразу отклоняет запросы локально — а затем сам пробует восстановиться пробным запросом.
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
}
}