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

@codefied-codepix/api

v1.0.1

Published

Shared HTTP transport layer for Next.js apps — Axios setup, interceptors, error normalization, token refresh, and retry logic.

Readme

@codefied-codepix/api

Shared HTTP transport layer for Next.js and Node.js applications. Handles Axios setup, interceptors, error normalization, token refresh, and retry logic.

This package is transport only — it does not define business endpoints. Each application owns its own API modules, routes, and domain types.

Requirements

  • Node.js 18+
  • Works with Next.js (App Router, Pages Router), React, or any TypeScript/JavaScript project

Installation

Published on the npm registry.

npm install @codefied-codepix/api@latest
pnpm add @codefied-codepix/api@latest
yarn add @codefied-codepix/api@latest

Or add to package.json:

{
  "dependencies": {
    "@codefied-codepix/api": "^1.0.0"
  }
}

Monorepo (workspace)

If you vendor this package inside a monorepo:

{
  "dependencies": {
    "@codefied-codepix/api": "workspace:*"
  }
}

Quick start

1. Create a client

Create a single API client per runtime context (browser singleton, or per-request on the server). The package does not read environment variables — you inject configuration.

// lib/api/client.ts
import { initializeApi } from "@codefied-codepix/api";

export const api = initializeApi({
  baseURL: process.env.NEXT_PUBLIC_API_URL ?? "",
  authMode: "none",
  retry: { retries: 1 },
});

2. Define feature modules in your app

Keep endpoint paths and response types in your application, not in this package.

// lib/api/features/users.ts
import { api } from "../client";

export type User = {
  id: string;
  name: string;
  email: string;
};

export async function getUser(id: string): Promise<User> {
  return api.get<User>(`/users/${id}`);
}

export async function updateUser(id: string, data: Partial<User>): Promise<User> {
  return api.patch<User>(`/users/${id}`, data);
}

3. Use anywhere in your app

import { getUser } from "@/lib/api/features/users";

const user = await getUser("123");

Recommended project structure

lib/api/
├── client.ts          # initializeApi() — browser singleton
├── server.ts          # optional: per-request client for RSC / Server Actions
├── types.ts           # app-owned DTOs
└── features/
    ├── users.ts       # domain endpoints
    └── products.ts

Configuration

initializeApi({
  baseURL: string;                    // required
  authMode?: "bearer" | "cookie" | "none";  // default: "bearer"
  getAccessToken?: () => string | null | Promise<string | null>;
  setAccessToken?: (token: string) => void | Promise<void>;
  refreshToken?: () => Promise<string | void>;
  onAuthFailure?: () => void | Promise<void>;
  timeout?: number;                   // default: 30000
  withCredentials?: boolean;          // auto true when authMode is "cookie"
  retry?: RetryOptions | false;       // default: 2 retries on network / 408 / 429 / 5xx
  headers?: Record<string, string>;
  unwrapEnvelope?: boolean;           // default: true
});

Auth modes

| Mode | Behavior | You provide | | -------- | ----------------------------------------- | ------------------------------------------- | | bearer | Sets Authorization: Bearer <token> | getAccessToken, optional setAccessToken | | cookie | Sends cookies via withCredentials: true | refreshToken for cookie-based refresh | | none | No auth headers | — |

Usage examples

Public API (no authentication)

import { initializeApi } from "@codefied-codepix/api";

export const api = initializeApi({
  baseURL: process.env.NEXT_PUBLIC_API_URL ?? "",
  authMode: "none",
  retry: { retries: 1 },
});

Bearer token with refresh

import { initializeApi } from "@codefied-codepix/api";

let accessToken: string | null = null;

export const api = initializeApi({
  baseURL: process.env.NEXT_PUBLIC_API_URL ?? "",
  authMode: "bearer",
  getAccessToken: () => accessToken,
  setAccessToken: (token) => {
    accessToken = token;
  },
  refreshToken: async () => {
    const response = await fetch("/api/auth/refresh", {
      method: "POST",
      credentials: "include",
    });

    if (!response.ok) {
      throw new Error("Failed to refresh token");
    }

    const { accessToken: token } = await response.json();
    return token;
  },
  onAuthFailure: () => {
    window.location.href = "/login";
  },
});

Cookie-based authentication

When refreshToken must call the same client instance, use a ref to avoid a circular dependency:

import { initializeApi, type ApiClient } from "@codefied-codepix/api";

const apiRef: { current: ApiClient | null } = { current: null };

const api = initializeApi({
  baseURL: process.env.NEXT_PUBLIC_API_URL ?? "",
  authMode: "cookie",
  withCredentials: true,
  refreshToken: async () => {
    await apiRef.current!.post("/auth/refresh", undefined, {
      _skipAuthRefresh: true,
    });
  },
  onAuthFailure: () => {
    window.location.href = "/login";
  },
});

apiRef.current = api;

export { api };

Next.js Server Components / Server Actions

This package does not import next/headers. Create a per-request client in your app:

import { cookies } from "next/headers";
import { initializeApi } from "@codefied-codepix/api";

export function createServerApi() {
  const cookieStore = cookies();

  return initializeApi({
    baseURL: process.env.API_URL!,
    authMode: "cookie",
    headers: { Cookie: cookieStore.toString() },
    refreshToken: async () => {
      // your server-side refresh logic
    },
  });
}

ApiClient methods

const api = initializeApi({ baseURL: "https://api.example.com" });

await api.get<T>(url, config?);
await api.post<T>(url, body?, config?);
await api.put<T>(url, body?, config?);
await api.patch<T>(url, body?, config?);
await api.delete<T>(url, config?);
await api.request<T>(config);

api.getRawAdapter(); // escape hatch for testing or custom transport

Per-request options

await api.get("/reports/export", {
  unwrapEnvelope: false,
  _skipAuthRefresh: true,
  params: { page: 1 },
  signal: abortController.signal,
});

Backend response contract

The client expects these shapes from your API when unwrapEnvelope is enabled (default).

Success:

{
  "success": true,
  "data": {}
}

Error:

{
  "statusCode": 400,
  "message": "Validation failed",
  "code": "VALIDATION_ERROR"
}

Errors are normalized into ApiError with statusCode, message, code, and helpers (isAuthError, isNetworkError, isRetryable).

Error handling

import { ApiError } from "@codefied-codepix/api";
// or: import { ApiError } from "@codefied-codepix/api/errors";

try {
  await api.get("/resource/123");
} catch (error) {
  if (error instanceof ApiError) {
    if (error.isAuthError) {
      // handle unauthorized
    }
    if (error.code === "VALIDATION_ERROR") {
      // handle domain error
    }
    console.error(error.statusCode, error.message);
  }
}

Token refresh

On a 401 response:

  1. If refreshToken is configured and the request has not been retried, one refresh runs.
  2. Concurrent 401s share the same in-flight refresh (single-flight).
  3. On success, the original request is retried once.
  4. On failure, onAuthFailure runs and the error is thrown.

Use _skipAuthRefresh: true on the refresh endpoint to prevent infinite loops.

Retry behavior

By default, requests retry up to 2 times with exponential backoff on:

  • Network errors and timeouts
  • HTTP 408, 429, and 5xx

Retries are skipped for auth errors and most 4xx responses. Disable with retry: false.

initializeApi({
  baseURL: "https://api.example.com",
  retry: {
    retries: 3,
    baseDelay: 500,
    retryOn: [408, 429, 502, 503],
  },
});

Exports

| Import path | Exports | | ------------------------------ | --------------------------------------------------------------------- | | @codefied-codepix/api | initializeApi, ApiClient, ApiError, normalizeError, types | | @codefied-codepix/api/errors | ApiError | | @codefied-codepix/api/types | ApiSuccess, ApiErrorBody, RequestConfig, InitializeApiOptions |

What belongs in this package vs. your app

In this package (transport):

  • HTTP client and Axios adapter
  • Request / response interceptors
  • Error normalization and ApiError
  • Token refresh orchestration
  • Retry policy

In your application (domain):

  • baseURL and environment variables
  • Auth token storage and refresh implementation
  • Endpoint paths and API routes
  • Domain types and DTOs
  • Feature modules and React hooks

Do not add to this package:

  • Business endpoint definitions
  • Domain-specific types
  • UI hooks (useUsers, etc.)