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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@loke/http-client

v2.0.0

Published

## Usage

Downloads

1,037

Readme

LOKE HTTP Client

Usage

import { HTTPClient, HTTPResponseError } from "@loke/http-client";

class MyClient extends HTTPClient {
  constructor() {
    super({ baseUrl: "https://example.com/" });
  }

  getThing(id) {
    return this.request("GET", "/thing/{id}", { id });
  }

  async _handlerResponse(res: Response) {
    // This is the default implementation. It will parse the response body as
    // JSON if the content type is application/json and return the body as an
    // object. If the content type is not application/json, it will return the
    // response as a string.
    //
    // You may want to override this if you want to do something with headers
    // or if you want to handle different content types
    let body = undefined;
    const contentType = res.headers.get("content-type");
    if (contentType?.includes("application/json")) {
      body = await res.json();
    }

    return { body };
  }

  async _handlerError(err: unknown): Promise<void> {
    // HTTPResponseError is thrown when there was a successful response but the
    // status code is not in the 2xx range
    //
    // Other errors are thrown when there was a network error or the request
    // was aborted.
    //
    // Usually you only want to map HTTPResponseError errors in in the 4xx range
    if (!(err instanceof HTTPResponseError)) {
      throw err;
    }

    let body = undefined;
    const contentType = res.headers.get("content-type");
    if (contentType?.includes("application/json")) {
      body = await res.json();
    }

    switch (err.status) {
      case 404:
        throw new ThingNotFoundError(body.message);
      default:
        console.error("Unexpected status code", err.status, body.message);
        throw err;
    }
  }
}

Error Handling

If fetch throws an error, it will be passed to _handlerError. This is usually a network error or an abort error.

If the response is not in the 2xx range, a HTTPResponseError will be thrown. This is a subclass of Error and has the following properties:

  • message: The status text of the response
  • status: The status code of the response
  • response: The original response object

Metrics

import { HTTPClient, registerMetrics } from "@loke/http-client";
import promClient from "prom-client";

registerMetrics(promClient.register);

Breaking Changes in v2

The main breaking change is the we switched from got to native node fetch for the underlying HTTP client. This means that the API is now more aligned with the native fetch API.

  • The Response object is now from native fetch and not got
  • Options are now native fetch options not got options
  • Errors are now either native fetch errors or HTTPResponseError, not got errors. Notably got errors have statusCode as a property, but the HTTPResponseError has status as a property. All other properties are now found under response
  • default _handlerResponse now returns the parsed body of the response
  • Timeout is no longer an option, pass a signal on the fetch options instead
  • No longer supports the retry option, wrap your call to request in a retry loop instead
  • No longer supports the http_client_request_stage_duration_seconds metric

Any project upgrading will have to to a fair bit of work, but it'll mostly be in the _handlerResponse and _handlerError functions