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

@icib.dev/api-client

v1.3.2

Published

Generator for strictly-typed TypeScript API clients from OpenAPI specs

Readme

@icib.dev/api-client

Generator for strictly-typed TypeScript API clients from OpenAPI specs. The client is generated in your project—nothing is published to npm.

Install

npm install @icib.dev/api-client axios

Quick Start

  1. Generate the client in your project:
npx api-client-generate
  1. Import from your generated client:
import { setAuthToken, apiClient } from "./api";  // or your --out path

setAuthToken(process.env.API_TOKEN);
const res = await apiClient.allegati.list({ page: 1, size: 10 });

For JWT + localStorage, generate with --auth jwt (see Authentication).

  1. Add verify to your build (ensures version alignment for production; fails if docs changed or client was modified):
{
  "scripts": {
    "build": "api-client-verify && tsc"
  }
}

API Client Generator

From consuming apps (npx)

If you use this library in your app, run the generator from your project root:

npx api-client-generate

With options:

# Custom URL
npx api-client-generate --url https://api.example.com/docs/openapi --out api

# Using BASE_URL env (default: $BASE_URL/docs/openapi)
BASE_URL=https://api.example.com npx api-client-generate --out api

# Custom base path (default empty; when set, included in axios baseURL)
npx api-client-generate --base-path /v1/api
BASE_PATH=/v2 npx api-client-generate

# Custom client base URL (default: from spec URL, BASE_URL, or spec host)
npx api-client-generate --base-url https://api.mycompany.com
BASE_URL=https://api.mycompany.com npx api-client-generate

# Override client.ts (by default, existing client is preserved if you customized it)
npx api-client-generate --override-client   # prompts for confirmation
npx api-client-generate --override-client --yes   # skip confirmation (e.g. CI)

# client.ts includes only the auth mode you choose (see table below)
npx api-client-generate --auth jwt --jwt-init lazy --override-client --yes
npx api-client-generate --auth jwt --jwt-init eager --jwt-access-key myAccess --jwt-refresh-key myRefresh --override-client --yes
npx api-client-generate --auth cookie --override-client --yes
npx api-client-generate --auth custom --override-client --yes

# CLI reference
npx api-client-generate --help
npx api-client-verify --help

The client is generated in your project directory (e.g. ./api/). If client.ts already exists, it is not overwritten unless you pass --override-client (which prompts for confirmation; use --yes to skip the prompt).

Auth mode (--auth)

client.ts is generated with only the matching implementation (no configureAuth, setDefaultAuthProfile, or unused profiles).

| Flag | Generated behavior | |------|-------------------| | --auth none (default) | Bearer from setAuthToken in memory; optional object form for access + refresh; no localStorage. | | --auth jwt | Same Bearer + persist access/refresh in localStorage. --jwt-init lazy (default): read storage on the first HTTP request. --jwt-init eager: read when the module loads. Keys: --jwt-access-key, --jwt-refresh-key (defaults accessToken / refreshToken). | | --auth cookie | withCredentials: true; no Bearer header; token helpers are no-ops for headers. | | --auth custom | Bearer + empty applyRequestAuth in client.ts — edit it for API keys, etc. |

Aliases: --default-auth--auth; --default-auth-timing immediate--jwt-init eager; lazy--jwt-init lazy.

You still register setAuthRefreshHandler in your app (refresh URLs are not in the OpenAPI spec). Use --override-client when regenerating so client.ts matches your chosen --auth.

From the library repo (maintainers)

npm run generate

By default, the spec URL is $BASE_URL/docs/openapi when the BASE_URL env variable is set. If unset, it falls back to the ICIB default.

Output

The generator creates an api/ folder and a local manifest (api-client.manifest.json, gitignored):

api/
├── client.ts          # Axios instance + single auth mode + optional token refresh
├── types/index.ts     # TypeScript interfaces from schema definitions
├── contexts/          # One file per API context (tag)
│   ├── allegati.ts
│   ├── articolo.ts
│   └── ...
└── index.ts           # Re-exports all contexts and types

Hash verification

Add api-client-verify before your build to ensure the generated client matches the current OpenAPI docs. You can insert it in the build step of your utilization library (the app or library that consumes the API client) to verify version alignment before production builds—if the API docs changed or the client was modified, the build fails and you must regenerate.

When you run your build, it:

  1. Reads the manifest (created by generate)
  2. Fetches the current docs and compares their hash
  3. Hashes the generated client files and compares with the manifest

If docs changed: Build fails with:

API docs have changed. Run npm run generate to regenerate the client, then update your application.

If client was manually edited: Build fails with:

Generated client files were modified. Run npm run generate to regenerate.

If manifest is missing: Run npm run generate first (e.g. after a fresh clone).

Authentication (client.ts)

Choose --auth when you generate so client.ts only contains that flow. There is no runtime configureAuth / setDefaultAuthProfile — switching modes means regenerating with --override-client.

Exports (typical): client, setAuthToken (string or { accessToken, refreshToken? }), setRefreshToken, getAuthToken, getRefreshToken, clearAuthToken, setAuthRefreshHandler, blob helpers.

Successful calls on client resolve to a full AxiosResponse (use .data for the parsed body, .headers / .status for debugging).

  • setAuthRefreshHandler — on 401/403, runs your refresh, then saveToken like setAuthToken. Mark the refresh HTTP call with skipAuthRefresh: true (see client.ts JSDoc).
  • --auth jwt + lazy: first request loads tokens from localStorage if memory is still empty (then keeps using memory). Eager loads storage when the module loads.
  • --auth custom: edit applyRequestAuth inside client.ts for API keys, etc.

Example (JWT client + refresh) — generate with npx api-client-generate --auth jwt --jwt-init lazy …:

import { apiClient, client, setAuthToken, setAuthRefreshHandler, getRefreshToken } from "./api";

setAuthRefreshHandler(async (saveToken) => {
  const refreshToken = getRefreshToken();
  if (!refreshToken) throw new Error("Not logged in");
  const res = await client.post<{
    accessToken: string;
    refreshToken: string;
  }>("/auth/refresh", { refreshToken }, { skipAuthRefresh: true });
  saveToken({
    accessToken: res.data.accessToken,
    refreshToken: res.data.refreshToken,
  });
});

setAuthToken({
  accessToken: loginResponse.accessToken,
  refreshToken: loginResponse.refreshToken,
});

await apiClient.someContext.list({ page: 1, size: 10 });

Nuxt 3: use a .client plugin for setAuthRefreshHandler (and any login that calls setAuthToken). With --auth jwt, you do not configure a separate “profile” in Nuxt—client.ts is already JWT-only.

JSDoc documentation

The generated client includes JSDoc comments from the OpenAPI spec:

  • Context/controller: Description from tag or "API client for X endpoints"
  • Methods: Operation summary and description
  • Params: @param with descriptions for path params, query params, and body
  • Types: Interface and property descriptions when present in the schema

File uploads (multipart/form-data)

OpenAPI 3 operations whose requestBody uses multipart/form-data with a flat object schema are generated to accept a typed data object and build FormData inside the method (so axios sends the correct multipart body and boundary). Properties with format: binary are typed as Blob | File; other scalar parts are appended as strings. Arrays of binary parts (array of string + format: binary) are supported as repeated append calls.

If the same operation lists application/json and multipart, the generator prefers JSON for the body schema (unchanged behavior). Multipart-only (or multipart when JSON is absent) triggers automatic FormData.

If the multipart schema is not a plain object with supported fields (e.g. nested objects, allOf, or unsupported array shapes), the method expects data: FormData and passes it through unchanged.

OpenAPI 2 in: formData / type: file parameters are not handled by this path; use OpenAPI 3 requestBody + multipart/form-data for uploads.

Blob / file download endpoints

Endpoints that return files (CSV, PDF, etc.) are detected from the spec (description, path patterns like /download/, x-response-type: blob). They return Blob and support download: true to trigger a browser download:

import { apiClient } from "./api";

// Get blob in response.data
const res = await apiClient.QR_Code.downloadUnassigned({ page: 1, size: 100 });
const csvBlob = res.data; // Blob

// Auto-download in browser
await apiClient.QR_Code.downloadUnassigned({}, { download: true });
await apiClient.QR_Code.generateCsv(
  { n: 10 },
  { download: true, filename: "qrcodes.csv" },
);