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

@axiomify/sdk-runtime

v6.3.2

Published

Runtime library for Axiomify-generated TypeScript SDKs — HTTP client, auth injection, retry engine, interceptors, caching, typed errors.

Readme

@axiomify/sdk-runtime

npm version codecov OpenSSF Scorecard License: MIT

The @axiomify/sdk-runtime is the foundational HTTP networking library that powers all TypeScript clients generated by the axiomify sdk generate command.

Rather than bloating every single generated SDK file with complex logic for retries, interceptors, and authentication injection, the generated code outsources those responsibilities to this zero-dependency library.

Philosophy

  • Zero Dependencies: Uses the native fetch API. It does not wrap or bundle Axios, Got, or Node-Fetch. This keeps your client bundle size incredibly small.
  • Pluggable: Exposes an InterceptorManager to tap into the request lifecycle.
  • Resilient: Features an advanced withRetry engine with exponential backoff and jitter designed specifically for server-to-server and high-latency edge environments.

Installation

Normally, you don't need to install this manually. If you used axiomify sdk generate -t typescript, this package is included as a dependency of the generated SDK.

However, if you generated only the types, you can install the runtime manually:

npm install @axiomify/sdk-runtime

Basic Usage

The runtime is initialized via the BaseClient. Your generated SDK will extend this class, but you will configure it using ClientConfig.

import { MyGeneratedSDK } from './generated-sdks';

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  timeoutMs: 10000, // default is 5000ms
});

const users = await client.getUsers({ limit: 100 });

Interceptors

Interceptors allow you to mutate requests before they are sent, or intercept responses before they are returned to the caller.

// 1. Add a Request Interceptor
client.interceptors.request.use(async (req) => {
  req.headers.set('X-Request-Start', Date.now().toString());
  return req;
});

// 2. Add a Response Interceptor
client.interceptors.response.use(async (res) => {
  if (res.status === 401) {
    console.error('Unauthorized! Redirecting to login...');
  }
  return res;
});

Retry Engine

Network requests fail. @axiomify/sdk-runtime handles retries automatically using exponential backoff and full jitter.

By default, the client retries 3 times on 429 Too Many Requests and 5xx server errors.

You can override the retry config at initialization:

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  retries: {
    maxAttempts: 5, // Retry up to 5 times
    initialDelayMs: 200, // Start with a 200ms delay
    maxDelayMs: 5000, // Cap the delay at 5000ms
    retryableStatuses: [429, 500, 502, 503, 504],
  },
});

Authentication

Injecting tokens into every request is tedious. Use the integrated AuthProvider to automatically manage tokens.

OAuth2 / Bearer Tokens

import { OAuth2BearerProvider } from '@axiomify/sdk-runtime';

const authProvider = new OAuth2BearerProvider({
  getToken: async () => {
    // Fetch from memory, local storage, or a secure credential store
    return localStorage.getItem('access_token');
  },
});

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  authProvider,
});

The OAuth2BearerProvider automatically intercepts requests and attaches the Authorization: Bearer <token> header before the request hits the network.

Advanced: Raw Fetch Configuration

Because the runtime uses the native fetch API, you can pass arbitrary native fetch initialization options into the client.

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  fetchOptions: {
    cache: 'no-store',
    keepalive: true,
  },
});

Circuit Breaker

To prevent cascading failures in high-volume microservices or distributed systems, the SDK client wraps all outgoing requests in a circuit breaker. By default, it operates with standard thresholds, but you can configure the behavior to suit your system:

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  circuitBreakerConfig: {
    failureThreshold: 5, // Number of failures before tripping the circuit
    cooldownPeriodMs: 10000, // Time to wait (in ms) before attempting probe requests in HALF_OPEN state
    halfOpenMaxProbeRequests: 3, // Max probe requests allowed in HALF_OPEN to check system health
  },
});

If the breaker trips, the client throws a CircuitBreakerError directly, shielding downstream dependencies until the cooldown period expires.

LRU TTL Caching

The runtime provides an in-memory Least Recently Used (LRU) cache with Time-To-Live (TTL) expiration. If enabled, it automatically caches incoming GET responses and returns them for matching paths and query configurations:

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  enableCache: true,
  cacheTtlMs: 60000, // Cache GET responses for 60 seconds
});

Additionally, the runtime performs Request Deduplication for identical in-flight GET requests, resolving multiple concurrent requests to the same endpoint with a single network round-trip.

Telemetry Hooks

Provide hooks to intercept and log request metadata, responses, or failures for auditing and APM integration:

const client = new MyGeneratedSDK({
  baseUrl: 'https://api.example.com/v1',
  telemetry: {
    onBeforeRequest: (req) => {
      console.log(`Sending ${req.method} request to ${req.path}`);
    },
    onAfterResponse: (res) => {
      console.log(`Received status ${res.status} from ${res.request.path}`);
    },
    onError: (err) => {
      console.error(`Request failed: ${err.message}`);
    },
  },
});

Server-Sent Events (SSE) Client

The client runtime provides a dedicated SseClient to consume Server-Sent Events. It implements automatic reconnection logic with exponential backoff:

import { SseClient } from '@axiomify/sdk-runtime';

const sse = new SseClient('https://api.example.com/v1/live-feed', {
  headers: {
    Authorization: 'Bearer token123',
  },
  maxRetries: 5,
  baseDelayMs: 1000,
  onOpen: () => console.log('SSE connection opened'),
  onMessage: (event, data) => console.log(`Received event: ${event}`, data),
  onError: (err) => console.error('SSE Error:', err),
});

// Start listening
sse.connect();

// Stop listening
sse.disconnect();

WebSocket Client

For full-duplex communication, use the WebSocketClient class. It manages standard browser/node WebSockets with customizable ping-pong heartbeats and auto-reconnection:

import { WebSocketClient } from '@axiomify/sdk-runtime';

const ws = new WebSocketClient('wss://api.example.com/v1/chat', {
  heartbeatIntervalMs: 30000, // Send ping every 30 seconds
  maxRetries: 10,
  onOpen: () => {
    console.log('WS connection active');
    ws.send(JSON.stringify({ event: 'join', channel: 'general' }));
  },
  onMessage: (data) => console.log('WS Message:', data),
  onClose: () => console.log('WS closed'),
});

ws.connect();

Paginators

The Paginator handles cursor-based paginated endpoints seamlessly:

import { Paginator } from '@axiomify/sdk-runtime';

const paginator = new Paginator<User, { cursor?: string }>({
  fetchPage: async (params) => {
    const response = await client.listUsers(params.cursor);
    return {
      items: response.users,
      nextCursor: response.nextCursor,
      hasMore: !!response.nextCursor,
    };
  },
  initialParams: {},
  cursorParamName: 'cursor',
});

// Fetch pages sequentially
if (paginator.hasNext()) {
  const users = await paginator.nextPage();
  console.log('Fetched users:', users);
}

Client Offline Queuing

For mobile or edge clients, the OfflineQueue caches requests during offline periods and flushes them automatically when the connection returns:

import { OfflineQueue } from '@axiomify/sdk-runtime';

const offlineQueue = new OfflineQueue();

// In offline state, queue operations
offlineQueue.enqueue({
  path: '/users',
  method: 'POST',
  body: { name: 'Jane Doe', email: '[email protected]' },
});

// Flush automatically on navigator/window online event
// or call manually with a custom processor:
await offlineQueue.flush(async (queuedRequest) => {
  await client.request({
    path: queuedRequest.path,
    method: queuedRequest.method as any,
    body: queuedRequest.body,
  });
});

Environment Switcher

Manage target environments programmatically using the EnvironmentSwitcher:

import { EnvironmentSwitcher } from '@axiomify/sdk-runtime';

const environments = {
  production: 'https://api.example.com/v1',
  staging: 'https://api-staging.example.com/v1',
  development: 'http://localhost:3000',
};

const switcher = new EnvironmentSwitcher(environments, 'development');
console.log(switcher.getUrl()); // http://localhost:3000

switcher.setEnvironment('production');
console.log(switcher.getUrl()); // https://api.example.com/v1