New:Socket for Asana Is Now Available.Learn more
Get Started

@eric8810/catcher-http

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eric8810/catcher-http

Catcher HTTP client — resilient transport with retry, circuit breaker, priority scheduling

npmnpm
Version
0.3.9
Version published
Weekly downloads
17
-63.83%
Maintainers
1
Weekly downloads
 
Created
Source

@eric8810/catcher-http

npm version License: MIT

Resilient HTTP client for Node.js — retry, circuit breaker, priority queue, interceptors, SSE streaming. Part of the catcher toolkit.

Built on axios (optional peer dep) + cockatiel (circuit breaker) + p-retry + p-queue.

💡 For maximum performance, consider @eric8810/catcher-napi-http — Rust native via napi-rs, with typed TypeScript wrappers and the same config schema. Recommended for production Node.js workloads.

Install

npm install @eric8810/catcher-http
# axios is an optional peer dependency
npm install axios

Quick Start

import { createHttpClient } from '@eric8810/catcher-http'

const client = createHttpClient({
  baseURL: 'https://api.example.com',
  keepAlive: true,
  retry: { attempts: 3, backoff: 'exponential', minTimeout: 500 },
  concurrency: 10,
  circuitBreaker: { failureThreshold: 5, resetTimeout: 30_000 },
})

// Basic requests
const user = await client.get('/users/1')
const created = await client.post('/messages', { text: 'hello' })

// Per-request overrides
await client.get('/analytics', { retry: false, timeout: 5000 })

// Dynamic interceptors
client.interceptors.request.use(config => {
  config.headers['Authorization'] = `Bearer ${token}`
  return config
})

SSE Streaming

One-shot stream (e.g. OpenAI)

import { createSSEStream } from '@eric8810/catcher-http'

const stream = createSSEStream({
  url: 'https://api.openai.com/v1/chat/completions',
  method: 'POST',
  headers: { Authorization: `Bearer ${apiKey}` },
  body: { model: 'gpt-4', messages: [{ role: 'user', content: 'Hello' }], stream: true },
})

for await (const line of stream) {
  if (!line.startsWith('data:')) continue
  const payload = line.startsWith('data: ') ? line.slice(6) : line.slice(5)
  if (payload === '[DONE]') break
  process.stdout.write(JSON.parse(payload).choices[0]?.delta?.content ?? '')
}

Long-lived push with auto-reconnect

import { createSSEClient } from '@eric8810/catcher-http'

const sse = createSSEClient({
  url: 'https://api.example.com/events',
  reconnect: { initialDelay: 1000, maxDelay: 30_000 },
})

for await (const line of sse) {
  if (line.startsWith('data: ')) console.log(line.slice(6))
}

API

createHttpClient(config)

Resilience layers (inside → out): axios → retry → circuit breaker → concurrency queue

interface HttpClientConfig {
  baseURL?: string
  timeout?: number
  keepAlive?: boolean
  retry?: RetryOptions | false
  concurrency?: number
  circuitBreaker?: { failureThreshold: number; resetTimeout: number }
  interceptors?: { request?: Function[]; response?: [Function?, Function?] }
  auth?: { username: string; password: string }
  bearerToken?: string | (() => Promise<string>)
  // ... more options
}

Client Methods

MethodPriority
client.get(url, config?)3 (low)
client.put(url, body?, config?)2
client.patch(url, body?, config?)2
client.post(url, body?, config?)1 (high)
client.delete(url, config?)3
client.circuitBreakerState()'closed' | 'open' | 'half-open'
client.queueDepth()Current queue size
client.on(event, listener)Subscribe to events
client.updateConfig(updates)Hot-update retry/timeout at runtime

Additional Exports

ExportDescription
createRetryWrapper(fn, retryOpts)Wrap any async function with retry
createInterceptorManager()Standalone interceptor chain
createSharedAgent(opts)TCP keep-alive + DNS cache agent
clearDnsCache()Clear the shared DNS cache
createPriorityQueue(opts)Priority-based concurrency queue
createSSEStream(opts)One-shot SSE async iterable
createSSEClient(opts)Long-lived SSE with auto-reconnect

License

MIT

FAQs

Package last updated on 20 May 2026

Related posts