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

typed-sdk-builder

v1.0.5

Published

A lightweight, zero-dependency TypeScript library for creating a fully-typed, configuration-based REST API client that handles authentication failures automatically.

Readme

npm version GitHub License Bundle Size Dependencies

Typed SDK Builder

A lightweight, zero-dependency TypeScript library for creating a fully-typed, configuration-based REST API client that handles authentication failures automatically, so you don't have to.

Motivation: The "Why"

In modern web applications, interacting with a REST API often involves repetitive and error-prone boilerplate. For every API call, you might find yourself:

  1. Wrapping your fetch call in a try...catch block.
  2. Checking the response status and parsing the body.
  3. Most importantly, checking for authentication errors (like a 401 Unauthorized status) when an access token expires.

This forces you to scatter the same authentication logic throughout your application: "Is the token invalid? Should I refresh it? Should I redirect to the login page?" This becomes tedious to maintain and violates the DRY (Don't Repeat Yourself) principle.

This SDK Builder was created to solve that exact problem.

The core idea is to provide a centralized, "set-it-and-forget-it" solution for API integration. You define your API endpoints once, and you define your authentication failure logic once. The builder then generates a fully-typed client. When you use this client to make a request, it will automatically trigger your custom handler if it detects an invalid credential response.

This means you can call any API endpoint directly without worrying about the token's validity on each call. The SDK handles the interception, letting you seamlessly redirect to a restricted page or attempt a silent token refresh, all from one place.

Features

  • Centralized Auth Failure Logic: Automatically intercepts 401 Unauthorized responses and triggers your global onInvalidCredential handler.
  • Zero-Boilerplate API Calls: Stop writing repetitive fetch and try...catch blocks. Just call the generated methods directly.
  • Configuration-Driven: Define all your API endpoints in a single, easy-to-read configuration object.
  • Fully-Typed Client: Generates a typed fetch client that mirrors your endpoint configuration, providing excellent autocompletion and type-safety.
  • Automatic Payload Handling: Intelligently handles JSON bodies, FormData for file uploads, and URL query parameters.
  • Zero Dependencies: Clean, modern TypeScript code with no external packages.
  • Simple Authorization: Built-in support for adding authorization headers to requests with minimal configuration.

Installation

npm install typed-sdk-builder
# or
yarn add typed-sdk-builder

Core Usage

1. Define Your Endpoints

Create a configuration object that lists all your API endpoints. It is crucial to use as const to allow TypeScript to infer the exact shape of your API for precise typing.

// src/api/config.ts

export const endpointsConfig = {
  auth: {
    signin: { path: "/auth/signin", method: "POST" as const },
    logout: { path: "/auth/logout", method: "POST" as const },
  },
  order: {
    getDetail: { path: "/guest/order/:id", method: "GET" as const },
    create: { path: "/guest/order", method: "POST" as const },
  },
  account: {
    get: { path: "/guest/account", method: "GET" as const },
    updateProfile: { path: "/guest/account/profile", method: "POST" as const }
  }
} as const; // <-- This "as const" is the magic!

2. Instantiate the SDK Builder

Create a new SDKBuilder instance. This is where you provide your base URL and, most importantly, the onInvalidCredential handler.

// src/api/index.ts

import { SDKBuilder } from 'typed-sdk-builder';
import { endpointsConfig } from './config';

const PUBLIC_API_URL = "https://your-api-domain.com/api";

export const api = new SDKBuilder({
  base: PUBLIC_API_URL,
  endpoints: endpointsConfig,

  /**
   * This is the core of the automatic auth handling.
   * This function will be called automatically on any 401 response.
   */
  onInvalidCredential: (response) => {
    console.warn("Invalid credentials detected. Redirecting to login page...");
    
    // Clear any stale session data
    api.clearAllPersistentData();

    // Redirect to a restricted or login page
    if (typeof window !== 'undefined') {
      window.location.href = '/login?session_expired=true';
    }
  },
});

3. Use the Generated Client Directly

Now you can import and use your api object anywhere in your application without worrying about auth checks.

import { api } from './api';

async function fetchAccountDetails() {
  // You can call this directly. If the token is invalid,
  // the `onInvalidCredential` handler will fire automatically and
  // the user will be redirected. No extra checks needed here.
  const accountResponse = await api.fetch.account.get();

  if (accountResponse.success) {
    console.log("Welcome back!", accountResponse.response);
  } else {
    // This part will likely not be reached on a 401 error
    // because the page will redirect first.
    console.error("Failed to fetch account:", accountResponse.response.message);
  }
}

async function login() {
    const signInResponse = await api.fetch.auth.signin({
        email: '[email protected]',
        password: 'password123'
    });

    if (signInResponse.success) {
        // Assuming the token is in the response, store it
        api.store({ token: signInResponse.response.token });
        window.location.href = '/dashboard';
    }
}

4. Authorization with Token

After successful login, the authentication token can be stored using the api.store() method by passing an object with token or access_token as the key. However, it is highly recommended to implement server-side cookies with HttpOnly enabled, as this approach provides enhanced security and is managed automatically by the browser.

// Example of using token for authentication
const token = 'your-jwt-token-here';
api.store({ token });

// Or using access_token
const accessToken = 'your-access-token-here';
api.store({ access_token: accessToken });

// After storing the token, all requests will automatically include the Authorization header
const userProfile = await api.fetch.user.profile.get();
// Request will be sent with header: Authorization: Bearer your-jwt-token-here

// To logout, remove token from storage
api.store({ token: null });
// or clear all persistent data
api.clearAllPersistentData();

5. Storing Objects and Complex Data

The api.store() method can handle various data types including objects, arrays, and primitive values. Objects are automatically serialized to JSON when stored and deserialized when retrieved.

API Reference

SDKBuilder Configuration

The constructor accepts a configuration object with the following properties:

| Property | Type | Required | Description | | --------------------- | ----------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- | | base | string | Yes | The base URL for all API requests (e.g., https://api.example.com/v1). | | endpoints | EndpointsInput | Yes | The endpoint configuration object, asserted with as const. | | onInvalidCredential | (response?) => Promise<void> \| void | No | Key Feature: A global callback triggered on any 401 Unauthorized response. Use this to handle session expiry and redirects. | | defaultHeaders | Record<string, string> | No | A dictionary of headers to be sent with every request. | | requestTimeout | number | No | The request timeout in milliseconds. Defaults to 30000 (30 seconds). |

The Response Object (CustomApiResponse)

Every fetch call returns a Promise that resolves to a CustomApiResponse object:

| Property | Type | Description | | ---------- | --------- | --------------------------------------------------------------------------- | | success | boolean | true if the HTTP response status was in the 200-299 range. Same as ok. | | ok | boolean | true if the HTTP response status was in the 200-299 range. | | response | any | The parsed response body (JSON or text). | | status | number | The HTTP status code (e.g., 200, 401, 404). 0 for client-side/network errors. |

License

This project is licensed under GPL-3.0 license.