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

@callsy/http-kit

v1.4.0

Published

HTTP client utilities and custom error handling.

Readme

@callsy/http-kit

A powerful and fluent HTTP client toolkit for Node.js, built on top of Axios. It simplifies creating robust and resilient HTTP clients with built-in caching, automatic retries, and intelligent error handling.

Features

  • Fluent Builder: A clean, chainable API for constructing axios instances.
  • Smart Error Handling: Automatically map HTTP error responses to custom, serializable error classes.
  • Automatic Retries: Built-in, configurable retry mechanism for transient network and server errors.
  • Request Caching: Out-of-the-box caching for GET requests to improve performance.
  • TypeScript Ready: Fully typed for a great developer experience.

Installation

npm install @callsy/http-kit

Quick Start

Create a configured client, make a request, and automatically catch a typed, custom error.

import {
  Builder,
  ErrorMap,
  ExternalApiError,
  InvalidInputError,
  CustomError
} from '@callsy/http-kit';

// 1. Define how errors should be mapped
const errorMap = new ErrorMap()
  .withError(InvalidInputError, [400]) // Map 400 status to InvalidInputError
  .withDefault(ExternalApiError); // Use ExternalApiError for all other errors

// 2. Build a new HTTP client instance
const httpClient = new Builder()
  .withDefaults({ baseURL: 'https://api.example.com' })
  .withRetry(3) // Retry failed requests up to 3 times
  .withCache(60) // Cache GET requests for 60 seconds
  .withErrorMapping(errorMap)
  .build();

// 3. Use the client and handle errors
async function getUser(id: string) {
  try {
    const response = await httpClient.get(`/users/${id}`);
    return response.data;
  } catch (error) {
    if (CustomError.isError(error)) {
      // 'error' is now a typed CustomError instance (e.g., InvalidInputError)
      console.error(error.getTitle()); // "Bad Request"
      console.error(error.getMessage()); // "The server cannot process the request..."
      // You can now handle the specific error type
    } else {
      // Handle non-custom errors (e.g., network issues)
      console.error('An unknown error occurred', error);
    }
  }
}

Core Concepts

The Fluent Builder

The Builder provides a clean, chainable API to construct your axios client.

  • .withDefaults({ ... }): Sets default axios request configuration (e.g., baseURL, headers, timeout).
  • .withRetry(retries, delay): Enables automatic retries for failed requests. Retries on network errors, 5xx status codes, 408 (Request Timeout), and 429 (Too Many Requests).
  • .withCache(ttlSeconds): Enables in-memory caching for GET requests with a specified Time-To-Live.
  • .withErrorMapping(errorMap): Attaches an ErrorMap to translate HTTP errors into custom error classes.

Advanced Error Handling with ErrorMap

  • The ErrorMap gives you fine-grained control over how errors are translated.
  • When an HTTP response body contains a serialized custom error, ErrorMap automatically deserializes it to the correct error type before applying any trigger-based mappings.
import { ErrorMap, RateLimitError, UnauthorizedError, ExternalApiError, GenericError } from '@callsy/http-kit';

const errorMap = new ErrorMap()
  // Map by HTTP status code
  .withError(UnauthorizedError, [401, 403])

  // Map by a substring in the response body
  .withError(RateLimitError, ['rate limit', 'too many requests'])

  // Extract a specific error message from a nested path in the JSON response
  .withCustomErrorPath('errors[0].detail')

  // Set a default fallback error for any unhandled cases
  .withDefault(ExternalApiError);

Error Serialization & Deserialization

A key feature of @callsy/http-kit is the ability to serialize custom errors to plain objects and deserialize them back into class instances. This is incredibly useful for passing errors between services or from your backend to your frontend.

Serializing an Error to an Object:

import { ResourceDoesNotExistError } from '@callsy/http-kit';

const error = new ResourceDoesNotExistError({ message: 'User not found' });

// The .toObject() method converts the error into a plain object.
const errorObject = error.toObject();
/*
{
  isCustomError: true,
  name: 'ResourceDoesNotExistError',
  message: 'User not found',
  title: 'Resource does not exist',
  description: 'The requested resource could not be found.',
  httpCode: 404,
  isCritical: false
}
*/

Deserializing an Object back into an Error:

Use the static fromObject method to reconstruct the error.

import { CustomError } from '@callsy/http-kit';

// Assume 'errorObject' is from an API response
const errorInstance = CustomError.fromObject(errorObject);

if (errorInstance) {
  // errorInstance is now a fully-functional ResourceDoesNotExistError instance
  console.log(errorInstance instanceof ResourceDoesNotExistError); // true
  throw errorInstance;
}

You can also safely check and throw the error in one go:

// Throws a fully reconstructed (deserialised) error if the object is a custom error
CustomError.throwIfError(apiResponse);

Available Error Classes

The library includes a set of pre-defined, semantic error classes for common HTTP scenarios:

  • BadRequestError (400)
  • UnauthorizedError (401)
  • PaymentRequiredError (402)
  • ForbiddenError (403)
  • ResourceDoesNotExistError (404)
  • MethodNotAllowedError (405)
  • NotAcceptableError (406)
  • RequestTimeoutError (408)
  • ConflictError (409)
  • GoneError (410)
  • RateLimitError (429)
  • UnprocessableEntityError (422)
  • ExternalApiError (424)
  • GenericError (500)
  • NotImplementedError (501)
  • BadGatewayError (502)
  • GatewayTimeoutError (504)
  • MaintenanceModeError (503)

And utility errors:

  • CustomError (Base class)
  • InvalidInputError
  • RequiredValueError
  • MisconfiguredError
  • NotAllowedError

Custom Error Classes

  • You can create your own custom errors that extend CustomError.
  • Make sure your custom error contains public static readonly NAME = 'YourCustomErrorName'.
  • Make sure your custom error is registered CustomError.register(YourCustomError).

Example:

import { CustomError, CustomErrorProps } from '@callsy/http-kit'

class MyAppError extends CustomError {
  public static readonly NAME = 'MyAppError'

  constructor(props?: CustomErrorProps) {
    super({
      name: MyAppError.NAME,
      message: 'Something app-specific went wrong.',
      httpCode: 422,
      ...props
    })
  }
}

CustomError.register(MyAppError)

License

ISC