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

@peassoft/request

v1.0.1

Published

Peassoft HTTP client library for Node.js

Readme

@peassoft/request

Peassoft HTTP client library for Node.js

You may not need it!

This is a custom, highly opinionated solution aimed at code re-use for a few private projects.

Installation

$ npm install @peassoft/request

Usage Example

import {
  createRequestFunction,
  type ApiDescriptor,
  type CustomError,
} from 'mnr-request';

const apis: Map<string, ApiDescriptor> = new Map([
  ['httpbin', {
    baseUrl: 'https://httpbin.org',
    apiOptions: {
      requestTimeoutMs: 5000,
      retries: 5,
      retryTimeoutMs: 500,
      customErrors: new Map<Map<number, CustomError>>([
        [401, { name: 'UnauthorizedError', message: 'request unauthorized' }]
      ])
    }
  }],
  ['example', { baseUrl: 'http://example.com' }],
]);

const globalOptions = {
  requestTimeoutMs: 10000,
  retries: 1,
  retryTimeoutMs: 3000,
  customErrors: new Map<Map<number, CustomError>>([
    [409, { name: 'ConflictError', message: 'request resulted in 409 Conflict response' }],
  ])
};

const request = createRequestFunction(apis, globalOptions);

// Type of data we expect the endpoint to respond with
type ResponseData1 = {
  foo: string;
};

const responseData1: ResponseData1 | null = await request<ResponseData1>({
  apiName: 'httpbin',
  path: '/get',
  method: 'GET',
  headers: {
    authorization: 'Bearer 123foo=',
  },
  qs: {
    foo: 'bar',
  },
});

await request<void>({
  apiName: 'example',
  path: '/',
  method: 'PUT',
  body: {
    foo: 'bar',
  },
  requestOptions: {
    requestTimeoutMs: 0,
    retries: 0,
    retryTimeoutMs: 0,
    customErrors: new Map<Map<number, CustomError>>([
      [500, { name: 'CriticalError', message: 'backend is broken' }],
    ]),
  },
});

API Reference

Options

There are four levels of options:

  1. Default options - applied to all requests if no other options override them.
  2. Custom global options - override default options and are applied to all requests if not overriden by neither custom API options, nor custom request options.
  3. Custom API options - override both default and global options and are applied to all requests to a particular API.
  4. Custom request options - override all other options and are applied to this particular request.

Options object intarface:

type Options = {
  /**
   * Timeout in milliseconds after which a single request attempt/retry fails.
   *
   * 0 disables the setting (OS limit applies).
   */
  requestTimeoutMs?: number;

  /**
   * Number of retries.
   *
   * This number does not include the initial request.
   *
   * Retries happen in case of:
   *
   *  • request fails due to a technical reason;
   *
   *  • response status code is 503, no custom error is configured for this status
   *    code, and response body JSON object DOES NOT contain a field `retry: false`;
   *
   *  • response status code is 504.
   */
  retries?: number;

  /**
   * Amount of time in milliseconds to wait before next retry.
   */
  retryTimeoutMs?: number;

  /**
   * Collection of custom error descriptors a promise has to reject with for defined
   * response status codes.
   *
   * A key of a map is response status code.
   */
  customErrors?: Map<number, CustomError>;
};

All fields in an Options object are optional. If a field is missing in a particular Options object, it just means that this option at a higher level is not overriden.

Default options:

{
  requestTimeoutMs: 0,
  retries: 2,
  retryTimeoutMs: 2000,
  customErrors: new Map<number, CustomError>(), // Empty collection
}

Initializing request function

You should initialize request function once and then use it througout your app.

import {
  createRequestFunction,
  type ApiDescriptor,
  type Options,
} from '@peassoft/request';

const apis: ApiDescriptor = ...
const globalOptions: Options = ...

export const request = createRequestFunction(apis, globalOptions);