npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@eric8810/catcher-napi-http

v0.3.10

Published

catcher HTTP native addon for Node.js via napi-rs

Readme

@eric8810/catcher-napi-http

npm version License: MIT

Rust-powered HTTP + SSE client for Node.js via napi-rs. Part of the catcher toolkit.

Wraps catcher-http's HttpTransport — reqwest + retry + circuit breaker, compiled to a native addon. Includes typed TypeScript wrappers with auto-generated .d.ts.

⚠️ Breaking Changes (0.3.0+)

Migrate from 0.2.x → 0.3.x — see napi API docs for full details.

v0.3.2: HttpResponse, RequestOptions, Metrics types now correctly use camelCase (auto-generated by NAPI-RS). JSON config types (HttpClientConfig, etc.) remain snake_case.

| Change | Before | After | |--------|--------|-------| | Entry point | client.js / client.d.ts | dist/client.js / dist/client.d.ts | | Config format | JSON.stringify(config) only | Typed object or JSON string | | Class names | JsHttpClient, JsSseStream, JsSseClient | HttpClient, SseStream, SseClient | | Callback events | Raw JSON strings, need JSON.parse() | Typed objects, auto-parsed | | Default backoff | Exponential | Fixed | | Default connect_timeout_ms | 5000 | 10000 | | Default min_backoff_ms | 500 | 100 | | Default max_backoff_ms | 30000 | 10000 | | camelCase fields | Not supported | #[serde(alias)] — both snake_case and camelCase accepted |

- const client = require('@eric8810/catcher-napi-http').HttpClient
- const c = new HttpClient(JSON.stringify({ base_url: '...' }))
+ import { HttpClient } from '@eric8810/catcher-napi-http'
+ const c = new HttpClient({ base_url: '...' })

Install

npm install @eric8810/catcher-napi-http

Pre-built binaries available for Linux (x64/arm64 gnu/musl), macOS (x64/arm64), and Windows (x64/arm64). Installed automatically via platform-specific optionalDependencies.

Usage

import { HttpClient } from '@eric8810/catcher-napi-http'
import type { HttpClientConfig, SseEvent } from '@eric8810/catcher-napi-http/types'

// Config as typed object (recommended) or JSON string
const client = new HttpClient({
  base_url: 'https://api.example.com',
  connect_timeout_ms: 10000,
  retry: { max_attempts: 3, backoff: 'Fixed' },
  circuit_breaker: { failure_threshold: 5, reset_timeout_ms: 30000 },
  dns: {
    cache_size: 512,
    cache_ttl_secs: 300,
    negative_ttl_secs: 60,
    stale_ttl_secs: 3600,
    stale_on_error: true,
    host_mapping: { 'api.internal': '10.0.0.10' },
  },
  msgpack: true,
})

// GET
const resp = await client.get('/users/1')
console.log(resp.status, resp.body.toString())

// POST
await client.post('/messages', Buffer.from(JSON.stringify({ text: 'hello' })), {
  contentType: 'application/json',
})

// Circuit breaker state
console.log(client.circuitBreakerState()) // 'closed' | 'open' | 'half-open'

// SSE (one-shot stream)
import { SseStream } from '@eric8810/catcher-napi-http/sse'

const stream = new SseStream(
  { url: 'https://stream.example.com/events' },
  (event: SseEvent) => {
    if (event.type === 'Line') console.log(event.data)
  },
)
// later: stream.close()

// SSE (auto-reconnect client)
import { SseClient } from '@eric8810/catcher-napi-http/sse'

const sse = new SseClient(
  {
    url: 'https://stream.example.com/events',
    reconnect: { max_retries: 10, initial_delay_ms: 1000 },
  },
  (event: SseEvent) => {
    if (event.type === 'Line') console.log(event.data)
  },
)

API

new HttpClient(config: HttpClientConfig | string)

Create a client from a typed config object or JSON string. All fields are optional with sensible defaults. Supports both snake_case and camelCase field names.

interface HttpClientConfig {
  base_url?: string
  connect_timeout_ms?: number      // default: 10000
  response_timeout_ms?: number     // default: 30000
  pool?: PoolConfig
  tls?: TlsConfig
  dns?: DnsConfig
  retry?: RetryConfig
  circuit_breaker?: CircuitBreakerConfig
  max_concurrency?: number         // default: 50
  default_headers?: Record<string, string>
  hostname_override?: string
  proxy?: ProxyConfig
  redirect?: RedirectConfig
  auth?: { username: string; password: string }
  bearer_token?: string
  msgpack?: boolean                  // default: false
}

interface DnsConfig {
  cache_size?: number                // default: 512
  cache_ttl_secs?: number            // default: 300
  negative_ttl_secs?: number         // default: 60
  stale_ttl_secs?: number            // default: 3600
  stale_on_error?: boolean           // default: true
  nameservers?: string[]
  host_mapping?: Record<string, string>
}

When msgpack is enabled, JSON request bodies are encoded as MessagePack and MessagePack responses are decoded back to JSON bytes when the response content type contains msgpack.

Methods

| Method | Signature | |--------|-----------| | get(url, options?) | async (url: string, options?: RequestOptions) => HttpResponse | | post(url, body?, options?) | async (url: string, body?: Buffer, options?: RequestOptions) => HttpResponse | | put(url, body?, options?) | async (url: string, body?: Buffer, options?: RequestOptions) => HttpResponse | | delete(url, options?) | async (url: string, options?: RequestOptions) => HttpResponse | | patch(url, body?, options?) | async (url: string, body?: Buffer, options?: RequestOptions) => HttpResponse | | circuitBreakerState() | () => 'closed' \| 'open' \| 'half-open' | | metrics() | () => Metrics | | executeStream(method, url, body?, options?, onChunk?) | (method: string, url: string, body?: Buffer, options?: RequestOptions, onChunk?: (event: StreamEvent) => void) => void | | setAdaptiveTimeout(min, max, mult, win) | (min: number, max: number, mult: number, win: number) => void | | cancelAll() | () => void | | cancelRequest(requestId) | (requestId: number) => boolean | | nextRequestId() | () => number |

RequestOptions

Per-request options (NAPI-RS auto-generated, camelCase fields):

interface RequestOptions {
  headers?: Record<string, string>
  timeoutMs?: number
  contentType?: string
}

HttpResponse

NAPI-RS auto-generated (camelCase fields):

interface HttpResponse {
  status: number
  headers: Record<string, string>
  body: Buffer
  elapsedMs: number
}

Metrics

Runtime metrics snapshot (NAPI-RS auto-generated, camelCase fields):

interface Metrics {
  httpRequests: number
  httpSuccessRate: number
  httpAvgLatencyUs: number
  httpRetries: number
  wsConnectSuccessRate: number
  wsDisconnects: number
  wsMessagesSent: number
  wsMessagesReceived: number
  cbOpenCount: number
  queueTimeouts: number
}

Note: HttpResponse, RequestOptions, and Metrics are auto-generated by NAPI-RS (camelCase fields). JSON config types like HttpClientConfig use snake_case (serde-based).

SSE

| Class | Description | |-------|-------------| | SseStream | One-shot SSE stream (no auto-reconnect) | | SseClient | Long-lived SSE client with auto-reconnect |

new SseStream(config: SseClientConfig | string, onEvent: (event: SseEvent) => void)
new SseClient(config: SseClientConfig | string, onEvent: (event: SseEvent) => void)

type SseEvent =
  | { type: 'Line'; data: string }
  | { type: 'Error'; message: string }
  | { type: 'End' }

StreamEvent

type StreamEvent =
  | { type: 'Headers'; status: number; headers: Record<string, string> }
  | { type: 'Chunk'; data: string }  // base64 encoded
  | { type: 'Done' }
  | { type: 'Error'; message: string }

Build from Source

Requires Rust toolchain.

npm run build       # napi build + tsup compile
npm run build:ts    # tsup only (no Rust rebuild)

License

MIT