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

@dsherwin/react-api-interface

v0.1.1

Published

REST API interface hook for React

Readme

A tiny, typed API interface for React apps and plain TS/JS, with consistent errors, timeouts, and hooks or singleton usage.

Table of Contents

  • Install
  • Description
  • Quick Start
  • Usage
    • Global singleton helpers
    • React hook factory
  • API Reference
    • Configuration
    • Requests
    • Error handling
    • Processors (request/response)
    • Logging
  • Examples
  • Author

Install

npm install @dsherwin/react-api-interface

Description

This library simplifies calling REST APIs with ergonomic methods (GET/POST/PUT/PATCH/DELETE). Success responses always return parsed JSON. All failures throw a typed APIError with normalized errorData — no more "unknown" error shapes.

  • Built-in base URL management, headers, and Authorization.
  • Optional request timeout and abort handling.
  • Optional debug logging of requests/responses.
  • Extensible request/response processors.
  • Form-data POST helper.

Quick Start

import {
  useAPIInterface,
  setAPIBaseURL,
  setAuthorizationHeader,
  apiGet
} from "@dsherwin/react-api-interface";
import { useEffect } from "react";

const App = () => {
  // Use shared singleton helpers in global app setup
  useEffect(() => {
    setAPIBaseURL("http://localhost:3500");
    setAuthorizationHeader("Bearer " + token);
  }, []);

  const handleClick = async () => {
    try {
      const data = await apiGet("/mystuff");
      console.log("DATA", data);
    } catch (e) {
      console.log("ERROR", e);
    }
  };

  return <button onClick={handleClick}>Click me!</button>;
};

Usage

1) Global singleton helpers

For simple apps, configure once and call from anywhere:

import {
  setAPIBaseURL,
  setAuthorizationHeader,
  setAPITimeout,
  enableAPILog,
  apiGet, apiPost, apiPut, apiPatch, apiDelete, apiPostForm
} from "@dsherwin/react-api-interface";

setAPIBaseURL("https://api.example.com");
setAuthorizationHeader("Bearer <token>");
setAPITimeout(8000); // 8s
enableAPILog(true);

const data = await apiGet("/users", { role: "admin" });

2) React hook factory (isolated instances)

If you need different configs per component or scope, create an instance:

import { useAPIInterface } from "@dsherwin/react-api-interface";

const { apiGet, setAPITimeout } = useAPIInterface(
  "https://api.example.com",
  "Bearer <token>",
  true,   // enable logging
  5000    // timeout (ms)
);

setAPITimeout(10000); // override later if needed

API Reference

Configuration (singleton helpers)

  • setAPIBaseURL(url: string): void
  • setAuthorizationHeader(authStr: string | null | undefined): void
  • enableAPILog(log: boolean): void
  • setAPITimeout(ms: number): void
  • setHeader(key: string, value: string): void
  • rmHeader(key: string): void
  • clearHeaders(): void
  • setRequestPreProcessor((req) => req): void
  • setResponsePostProcessor((res) => res): void
  • setErrorResponsePostProcessor((err: APIError) => APIError): void

Requests

  • apiGet(path: string, queryParams?): Promise
  • apiDelete(path: string, queryParams?): Promise
  • apiPost(path: string, data?: any, queryParams?): Promise
  • apiPut(path: string, data?: any, queryParams?): Promise
  • apiPatch(path: string, data?: any, queryParams?): Promise
  • apiPostForm(path: string, data?: Array<Record<string, string | Blob>>, queryParams?): Promise

Notes:

  • path can be absolute or relative to the configured base URL.
  • For JSON requests, Content-Type is set automatically.
  • apiPostForm sends FormData and will not set JSON Content-Type.

Error handling

All failures throw APIError. Access normalized error data via error.errorData:

import { APIError } from "@dsherwin/react-api-interface";

try {
  await apiGet("/restricted");
} catch (e) {
  if (e instanceof APIError) {
    const { code, status, message, description, details, requestPath } = e.errorData;
    // Handle
  }
}

Processors

  • setRequestPreProcessor((req) => req): mutate/inspect a request before sending.
  • setResponsePostProcessor((res) => res): transform successful JSON responses.
  • setErrorResponsePostProcessor((err: APIError) => APIError): map/augment errors before they bubble up.

Logging

  • enableAPILog(true) to log requests and responses to console for debugging.

Examples

  • Add a global header
setHeader("X-Trace-Id", crypto.randomUUID());
  • Retry wrapper (simple)
async function apiGetWithRetry(path: string, retries = 2) {
  for (let i = 0; i <= retries; i++) {
    try { return await apiGet(path); } catch (e) { if (i === retries) throw e; }
  }
}
  • Form upload
await apiPostForm("/upload", [{ file: myBlob, name: "avatar.png" }]);

Author

👤 dsherwin