JSPM

  • Created
  • Published
  • Downloads 85
  • Score
    100M100P100Q93813F
  • License MIT

A high-performance, universal HTTP client for Node.js, Bun, Deno and Browser with caching, retries, queueing, rate limiting, cookies and logging.

Package Exports

  • hyperttp

Readme

Hyperttp ⚡

English | Русский

npm version npm downloads license typescript


🌐 Language



Hyperttp is a batteries-included, high-performance HTTP client for Node.js, Bun, Deno, and Browser environments. It is a feature-rich, production-ready extension over the optimized @hyperttp/core engine, shipping with caching, rate limiting, request queuing, inflight deduplication, performance metrics, and a fluent chainable API — all pre-wired and ready to use.


🔥 Key Features

  • 🎯 Smart Response Parsing: Automatically parses responses based on responseType (json, text, xml, html, buffer, blob, stream).
  • 🔀 Concurrency Management: Built-in queue plugin (withQueue) to strictly enforce concurrent request limits.
  • 💾 Smart LRU Caching: Dedicated caching layer (withCache) with TTL support to prevent redundant network drift.
  • 🚦 Rate Limiting: Built-in Token Bucket algorithm to protect against external API blocks and rate limits.
  • 🛡️ Inflight Deduplication: Prevents duplicate simultaneous requests to the same endpoint if the first is pending.
  • 📈 Real-Time Metrics: Out-of-the-box telemetry tracking latencies, RPS, cache hits, and overall client health.
  • 🔌 Modular Architecture: Clean pipeline approach allowing custom plugins, serialization layers, and interceptors.
  • 💎 Fluent Request Builder API: Clean, chainable API syntax to compose and configure requests with ease.
  • 🗜️ Transparent Decompression: Automatic handling of gzip, deflate, and br (Brotli) out of the box.

📦 Ecosystem Packages

Package Description Repository
hyperttp (you are here) High-level client with all plugins pre-wired GitHub
@hyperttp/core Low-level core with transport pipeline GitHub
@hyperttp/types Shared TypeScript type definitions GitHub
@hyperttp/transport-bun Native Bun transport GitHub
@hyperttp/transport-undici Undici transport for Node.js GitHub
@hyperttp/parser Response body parser (JSON/XML/HTML) GitHub
@hyperttp/serializer Request body serializer GitHub
@hyperttp/cache HTTP response caching GitHub
@hyperttp/queue Request queueing GitHub
@hyperttp/ratelimit Rate limiting GitHub
@hyperttp/inflight In-flight request deduplication GitHub
@hyperttp/interceptors Request/response interceptors GitHub
@hyperttp/metrics Performance metrics GitHub

Which package should I use?

  • Just need HTTP requests with caching, retries, and parsing? → Use hyperttp (this package)
  • Need full control over the pipeline? → Use @hyperttp/core
  • Building a custom transport or plugin? → Use @hyperttp/types

🚀 Installation

npm install hyperttp

# Optional: install a specific transport
npm install @hyperttp/transport-bun    # for Bun
npm install @hyperttp/transport-undici # for Node.js

📦 Quick Start

Simply import HyperClient and start dispatching requests. Core features like caching, queue management, and rate limiting are instantly preconfigured and active out of the box.

import { HyperClient } from "hyperttp";

const client = new HyperClient();

// Simple GET request (instantly resolves to the pre-parsed type-safe body)
const data = await client.get<MyDataType>("https://api.example.com/data");

// POST request specifying expected response type alongside body payload
const newItem = await client.post<Item>("https://api.example.com/items", "json", {
  name: "New Item Structure",
});

// Explicit response type
const html = await client.get<string>("https://example.com", "text");
const xml = await client.get<XmlDoc>("https://api.example.com/feed.xml", "xml");

// Streaming responses (e.g., LLM completions)
const chatStream = await client.stream("https://api.openai.com/v1/chat/completions");
const reader = chatStream.body.getReader();

💎 Fluent Builder API

Invoke the .request(url) chain to programmatically craft highly specific request structures on the fly:

const user = await client
  .request("https://api.example.com/users")
  .post() // Specify HTTP Method (Defaults to GET)
  .query({ include: "profile" }) // Safely append and encode Query Parameters
  .headers({ "X-Request-ID": crypto.randomUUID() })
  .jsonBody({ name: "John", email: "john@example.com" }) // Automatically serializes and sets Content-Type header
  .json<User>() // Asserts expected response format (.text(), .buffer(), .stream())
  .timeout(5000) // Instantiates a contextual, request-scoped AbortSignal timeout
  .send();

⚙️ Advanced Configuration

Fine-tune every infrastructure layer by supplying a configuration object directly to the HyperClient constructor:

import { HyperClient } from "hyperttp";

const client = new HyperClient({
  // 🌐 Core Network Level Settings (NetworkOptions)
  network: {
    timeout: 10000, // Request timeout in milliseconds
    maxConcurrent: 50, // Maximum simultaneous active sockets (0 = unlimited)
    pipelining: 1, // Pipelined requests per connection limit
    keepAliveTimeout: 30000, // Keep-alive socket preservation time in ms
    rejectUnauthorized: true, // Reject untrusted or self-signed SSL certificates
    followRedirects: true, // Automatically follow HTTP redirects
    maxRedirects: 5, // Maximum follow threshold for redirects
    maxResponseBytes: 10 * 1024 * 1024, // Prevents OOM by capping response body size (10 MB)
    userAgent: "HyperClient/2.0", // Global fallback User-Agent header
    headers: {
      // Default baseline headers appended to every request
      "X-App-Client": "Backend",
    },
    validateStatus: (status) => status >= 200 && status < 300, // Status success validation rules
  },

  // 🔄 Automated Retry Logic (RetryOptions)
  retry: {
    maxRetries: 3, // Number of recovery attempts before failing
    baseDelay: 1000, // Initial delay baseline between retries (ms)
    maxDelay: 10000, // Maximum cap for retry delay intervals (ms)
    retryStatusCodes: [408, 429, 502, 503, 504], // Target status codes that trigger a retry
    jitter: true, // Randomized delay variations to avoid thundering herd crashes
  },

  // 📈 Telemetry and Engine Logging
  trackMetrics: true, // Enables global system performance collection
  verbose: false, // Toggles internal micro-logs output
  logger: (level, message, meta) => {
    // Custom logging implementation sink
    console.log(`[${level}] ${message}`, meta ?? "");
  },

  // 💾 Extended Plugin Configurations (Injected via HyperttpPluginsExtension)
  cache: {
    enabled: true,
    ttl: 300000, // 5 minutes cache lifespan
    maxSize: 500, // Max item limit for local LRU storage
  },
  rateLimit: {
    enabled: true,
    maxRequests: 100,
    windowMs: 60000,
  },
  inflight: {
    enabled: true,
  },
});

🔌 Pre-Wired Plugins

When using HyperClient, the following plugins are automatically registered:

Plugin Purpose
withSerializer Serializes request bodies (JSON, FormData, URLSearchParams)
withParser Parses response bodies based on responseType
withQueue Queues requests when concurrency limit is reached
withRateLimit Enforces rate limits
withInflight Deduplicates in-flight requests
withCache Caches responses based on HTTP headers
withInterceptors Request/response interceptors
withMetrics Collects performance metrics

Custom Plugins

Extend the client with your own hooks:

client.use({
  name: "performance-logger",
  priority: 100, // Sorted execution priority (higher runs first)
  mode: "background", // Forces onResponse to run as a non-blocking side-effect

  setup: (ctx) => {
    ctx.config.logger?.info?.("Plugin active");
  },

  onRequest: async (req, ctx) => {
    req.meta.startTime = performance.now();
  },

  onResponse: async (res, req, ctx) => {
    const duration = performance.now() - (req.meta.startTime as number);
    console.log(`[${req.method}] ${req.url} -> ${res.status} (${duration.toFixed(2)}ms)`);
  },

  onError: async (error, req, ctx) => {
    console.error(`Request failed to ${req.url}: ${error.message}`);
    // Return a response object here to bypass/recover from the failure
  },
});

Plugin Phases

Phase Hook Description
REQUEST onRequest Intercepts before execution. Supports short-circuiting.
DATA onResponseData Transforms raw transport responses before mapping.
FORMAT onResponse Modifies client-facing responses.
ERROR onError Catches and recovers from errors.

🏗️ Architecture Pipeline

HyperClient structures outbound and inbound requests across a sequential pipeline composed of granular plugins:

┌─────────────────────────────────────────────────────────────────┐
│                        HyperClient                              │
│   (Auto-wires: Serializer → Parser → Queue → RateLimit →        │
│    Inflight → Cache → Interceptors → Metrics)                   │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                         HyperCore                               │
│                                                                 │
│  1. Request Pipeline (onRequest) ─── short-circuit capable      │
│                     │                                           │
│  2. Transport Execution (HyperTransport)                        │
│     ├─ BunTransport (native Bun fetch)                          │
│     ├─ UndiciTransport (Node.js)                                │
│     └─ NodeTransport (global fetch)                             │
│                     │                                           │
│  3. Response Data Pipeline (onResponseData)                     │
│                     │                                           │
│  4. Internal Processing (decompression, mapping)                │
│                     │                                           │
│  5. Response Pipeline (onResponse)                              │
│     ├─ Mutators (sync/async modification)                       │
│     └─ Side Effects (background, non-blocking)                  │
│                     │                                           │
│  6. Error Pipeline (onError) ─── recovery capable               │
└─────────────────────────────────────────────────────────────────┘

🛠️ Advanced Features

Statistics, Cache, and Metrics Engine

// Inspect pipeline internals (active connections, active queue payloads)
const stats = client.getStats();
console.log(stats);

// Retrieve aggregated historical latency and performance metrics
const allMetrics = client.getAllMetrics();
console.log(allMetrics);

// Flush the entire local response cache programmatically
await client.clearCache();

// Identify the execution context's current driving transport layout
const transportName = await client.getTransportName();
console.log(`Current Active Transport Driver: ${transportName}`);

// Gracefully teardown the client instance, draining keep-alive pools and sockets
await client.destroy();

Stream Handlers

// Returns an HttpResponse interface carrying a custom ReadableStream with clone() support
const streamResponse = await client.stream("https://stream.example.com/audio.mp3");
const reader = streamResponse.body.getReader();

Extending Configuration

Create derived clients with merged configuration:

const authenticatedClient = client.extend({
  network: { headers: { Authorization: "Bearer token_abc" } },
});

🔄 Migration from axios

If you're migrating from axios, Hyperttp provides a familiar API:

// axios
import axios from "axios";
const { data } = await axios.get("/users/123");

// hyperttp (drop-in replacement)
import { HyperClient } from "hyperttp";
const client = new HyperClient();
const data = await client.get("/users/123");

📊 Benchmarks

For detailed benchmarks across Bun and Node.js runtimes with various transports, see the @hyperttp/core benchmarks.

Key takeaways:

  • Bun + BunTransport: ~15.22K RPS with all plugins enabled
  • Node.js + UndiciTransport: ~10.82K RPS with all plugins enabled
  • Plugin Overhead: Only ~9-14% compared to the bare @hyperttp/core
  • Zero Error Rate: 0% errors across all benchmark scenarios

📄 License

MIT


dirold2