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

@molecule/app-http-axios

v1.1.0

Published

Axios HTTP client provider for @molecule/app-http

Readme

@molecule/app-http-axios

Axios HTTP client provider for @molecule/app-http.

This package provides an Axios-based implementation of the molecule HttpClient interface, allowing you to use molecule's HTTP abstractions with Axios.

The body is the SECOND argument: post(url, data, config?) — likewise put and patch. data IS the request body, so post(url, { data: body }) sends the JSON body {"data":body}, not body, and the API finds none of its fields at the top level (it answers 422 {"errors":{"username":["can't be blank"],…}}). Write post('/users', { user }), never post('/users', { data: { user } }); a config (headers, params) is the THIRD argument.

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Quick Start

import { createAxiosClient } from '@molecule/app-http-axios'
import { setClient } from '@molecule/app-http'

const client = createAxiosClient({
  baseURL: 'https://api.example.com',
  timeout: 10000,
})

setClient(client)

// Now use via `@molecule/app-http`
import { get, post } from '@molecule/app-http'
const users = await get('/users')
const newUser = await post('/users', { name: 'John' })

Type

provider

Installation

npm install @molecule/app-http-axios @molecule/app-http axios

API

Interfaces

AxiosHttpClientConfig

Axios-specific configuration.

interface AxiosHttpClientConfig {
  /**
   * Base URL for all requests.
   */
  baseURL?: string

  /**
   * Default headers for all requests.
   */
  defaultHeaders?: Record<string, string>

  /**
   * Default timeout in milliseconds.
   */
  timeout?: number

  /**
   * Whether to include credentials by default.
   */
  withCredentials?: boolean

  /**
   * The scheme of the `Authorization` header the auth token is sent with:
   * `Bearer` (default), or what your API expects, e.g. `Token` for an API that
   * reads `Authorization: Token <jwt>`. Pass it to this config, at construction —
   * `setClient(createAxiosClient({ baseURL, authScheme: 'Token' }))` — never as a
   * property of the client it returns. Same option as `@molecule/app-http`'s
   * `HttpClientConfig.authScheme`, so the config reads the same whichever
   * transport is bonded.
   */
  authScheme?: string

  /**
   * Existing Axios instance to wrap (optional).
   */
  instance?: AxiosInstance

  /**
   * Additional Axios-specific config.
   */
  axiosConfig?: AxiosRequestConfig

  /**
   * Default retry policy for every request this client makes, or `false` to
   * disable retries. A request's own `retry` overrides it. The policy is the
   * same one `@molecule/app-http`'s fetch client uses: idempotent requests
   * only, on 502/503/504 or a reset/refused connection, with backoff and
   * jitter, honoring `Retry-After`.
   */
  retry?: RetryOptions | false
}

HttpClient

HTTP client interface.

All HTTP providers must implement this interface.

interface HttpClient {
  /**
   * Base URL for all requests.
   */
  baseURL: string
  /**
   * Default headers for all requests.
   */
  defaultHeaders: Record<string, string>
  /**
   * Makes a generic HTTP request. `data` is a field of THIS config object — the same body
   * `post(url, data, config)` takes as its second argument.
   */
  request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a GET request.
   */
  get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a POST request. `data` is the request BODY, not a config object: the wire body is
   * `data` itself, so `post(url, { data: body })` sends `{"data":body}` — pass `body` directly.
   * A config (headers, params) is the THIRD argument.
   */
  post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a PUT request. `data` is the request BODY (second argument) — never `{ data: body }`,
   * which sends `{"data":body}`; a config is the THIRD argument.
   */
  put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a PATCH request. `data` is the request BODY (second argument) — never `{ data: body }`,
   * which sends `{"data":body}`; a config is the THIRD argument.
   */
  patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a DELETE request.
   */
  delete<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Adds a request interceptor.
   * Returns a function to remove the interceptor.
   */
  addRequestInterceptor(interceptor: RequestInterceptor): () => void
  /**
   * Adds a response interceptor.
   * Returns a function to remove the interceptor.
   */
  addResponseInterceptor(interceptor: ResponseInterceptor): () => void
  /**
   * Adds an error interceptor.
   * Returns a function to remove the interceptor.
   */
  addErrorInterceptor(interceptor: ErrorInterceptor): () => void
  /**
   * Sets the authorization token.
   */
  setAuthToken(token: string | null): void
  /**
   * Returns the current authorization token, or `null` if not set.
   */
  getAuthToken(): string | null
  /**
   * Registers a handler for authentication errors (401).
   *
   * @returns An unsubscribe function.
   */
  onAuthError(handler: () => void): () => void
}

HttpClientConfig

HTTP client configuration.

interface HttpClientConfig {
  /**
   * Base URL for all requests.
   */
  baseURL?: string
  /**
   * Default headers for all requests.
   */
  defaultHeaders?: Record<string, string>
  /**
   * Default timeout in milliseconds.
   */
  timeout?: number
  /**
   * Whether to include credentials by default.
   */
  withCredentials?: boolean
  /**
   * The scheme of the `Authorization` header the auth token is sent with:
   * `Bearer` (default), or what your API expects, e.g. `Token` for an API that
   * reads `Authorization: Token <jwt>`. It is an option of the client's
   * CONSTRUCTOR (`createFetchClient({ baseURL, authScheme: 'Token' })`, or the
   * bonded provider's `createAxiosClient({ … })`), never a property of the client
   * it returns.
   */
  authScheme?: string
  /**
   * Default retry policy for every request this client makes, or `false` to
   * disable retries. A request's own `retry` overrides it.
   */
  retry?: RetryOptions | false
}

RequestConfig

HTTP request options (headers, query params, timeout, credentials, response type, abort signal).

interface RequestConfig {
  /**
   * Request headers.
   */
  headers?: Record<string, string>
  /**
   * Query parameters.
   */
  params?: Record<string, string | number | boolean | undefined>
  /**
   * Request timeout in milliseconds.
   */
  timeout?: number
  /**
   * Whether to include credentials (cookies).
   */
  withCredentials?: boolean
  /**
   * Send this request WITHOUT waiting for the session restore (the auth gate).
   *
   * A request the gate's restore issues from a LATER continuation must set this. The gate
   * recognizes a request the settle function issues while it runs and never holds it — this
   * package's client awaits the gate before anything else, so a `restoreSession()` that calls
   * it directly does not deadlock. But a restore that awaits something else first
   * (`await storage.get()`), then calls the client, reaches `awaitAuthGate` after that window:
   * the gate then waits on itself, and every request on the page stalls until the gate times
   * out (3 s) — so pass `skipAuthGate: true` on that request. A provider that awaits the gate
   * inside a scheduled interceptor (the Axios bond) also reaches it after the window, so its
   * restore's request needs the opt-out.
   *
   * ```typescript
   * // the request the gate's restore makes, through the same client the gate holds back
   * await http.get(currentUserEndpoint, { skipAuthGate: true })
   * ```
   *
   * `@molecule/app-auth`'s own restore does not need it — it sends its request with
   * `fetch`, not through this client. An app with its own session store that registers a
   * gate with `setAuthGate` does not need it either when its restore calls the client
   * directly.
   */
  skipAuthGate?: boolean
  /**
   * Response type.
   */
  responseType?: 'json' | 'text' | 'blob' | 'arraybuffer'
  /**
   * Abort signal for cancellation.
   */
  signal?: AbortSignal
  /**
   * Request body data, as a field of THIS config object — the `request({ method, url, data })`
   * form. The verb methods take the body as their SECOND argument: `post(url, data, config)`,
   * `put(url, data, config)`, `patch(url, data, config)`. Never wrap it there as
   * `{ data: body }`: that object is the body, so the wire sends `{"data":body}` and the API
   * sees none of the fields at its top level.
   */
  data?: unknown
  /**
   * Custom request options (implementation-specific).
   */
  options?: Record<string, unknown>
  /**
   * Retry policy for this request, or `false` to disable retries.
   *
   * The default policy retries only IDEMPOTENT requests (`GET`/`HEAD`/`PUT`/
   * `DELETE`/`OPTIONS`, and `POST`/`PATCH` carrying an `Idempotency-Key`) on
   * `502`/`503`/`504` or a reset/refused connection, twice, with exponential
   * backoff and jitter, honoring `Retry-After`. See `@molecule/app-http`'s
   * `shouldRetryRequest`.
   */
  retry?: RetryOptions | false
}

FullRequestConfig

Full request configuration including method and URL.

interface FullRequestConfig extends RequestConfig {
  /**
   * HTTP method.
   */
  method: HttpMethod
  /**
   * Request URL (can be relative or absolute).
   */
  url: string
  /**
   * Request body data — a field of this config object, never a second argument here.
   */
  data?: unknown
}

HttpResponse

Parsed HTTP response with status code, headers, and typed body data.

interface HttpResponse<T = unknown> {
  /**
   * Response data.
   */
  data: T
  /**
   * HTTP status code.
   */
  status: number
  /**
   * HTTP status text.
   */
  statusText: string
  /**
   * Response headers.
   */
  headers: Record<string, string>
  /**
   * Original request config.
   */
  config: FullRequestConfig
}

Types

RequestInterceptor

Intercepts outgoing requests to modify headers, URL, or body before the request is sent.

type RequestInterceptor = (
  config: FullRequestConfig,
) => FullRequestConfig | Promise<FullRequestConfig>
  • config — The full request configuration to transform.

ResponseInterceptor

Intercepts incoming responses to transform data, check status, or perform side effects before the response reaches the caller.

type ResponseInterceptor<T = unknown> = (
  response: HttpResponse<T>,
) => HttpResponse<T> | Promise<HttpResponse<T>>

ErrorInterceptor

Intercepts HTTP errors to transform, retry, or rethrow them. Throwing from this interceptor propagates the error to the caller.

type ErrorInterceptor = (error: HttpError) => HttpError | Promise<HttpError> | never

HttpMethod

HTTP request method.

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'

Classes

HttpError

HTTP error with response details.

status is an HTTP status when the server answered, and 0 when it did not. A 0 means NO response exists: the request was aborted (an AbortController, a component's effect cleanup, a route change tearing the request down) or the network failed before anything came back. It is not an HTTP status at all, so it says nothing about the session — an app must never treat status < 500 as "signed out", because every aborted request on a route change would clear the session. The correct check is {@link isAuthFailure} (status === 401 || status === 403); isNoResponse (status === 0) identifies this case.

declare class HttpError extends Error {
  status: number
  response?: HttpResponse | undefined
  config?: FullRequestConfig | undefined
  errorKey?: string | undefined
  aborted: boolean
  /**
   * Builds a failed-request error.
   *
   * @param message - Human-readable message (already translated where a key exists).
   * @param status - HTTP status, or `0` when no response was received (aborted / network failure).
   * @param response - Parsed response when the server answered, otherwise undefined.
   * @param config - The request config that failed.
   * @param errorKey - Translation key for the failure (`http.error.aborted` for an
   *   aborted request, `http.error.networkError` for a real network failure).
   * @param aborted - Whether the request was aborted before a response: an
   *   `AbortController` signal (component cleanup, a cancelled request) or the
   *   browser tearing the fetch down during a navigation. Distinguishes an abort
   *   from a network outage on the same `status === 0`, without parsing the message.
   */
  constructor(
    message: string,
    status: number,
    response?: HttpResponse | undefined,
    config?: FullRequestConfig | undefined,
    errorKey?: string | undefined,
    aborted?: boolean,
  )
}

Functions

createAxiosClient(config)

Creates an Axios-based HTTP client implementing the molecule HttpClient interface. Supports request/response/error interceptors, auth token management, and 401 error handlers.

function createAxiosClient(config?: AxiosHttpClientConfig): HttpClient
  • config — Axios client configuration (base URL, headers, timeout, credentials, auth scheme, or an existing Axios instance).

Returns: An HttpClient backed by Axios with interceptor and auth token support.

Constants

provider

Default Axios-based HTTP client created with default options (no base URL, 30s timeout).

const provider: HttpClient

Core Interface

Implements @molecule/app-http interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setClient } from '@molecule/app-http'
import { provider } from '@molecule/app-http-axios'

export function setupHttpAxios(): void {
  setClient(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-http ^1.0.1
  • axios ^1.6.0

Runtime Dependencies

  • @molecule/app-http

  • axios

  • Call setClient(...) at startup, BEFORE any get/post from @molecule/app-http runs. The core's getClient() lazily bonds its own fetch-based fallback on first use — requests issued before setClient() silently bypass the Axios client (no interceptors, no auth token).

  • get()/post()/… resolve to HttpResponse<T> — read .data for the body (const { data: users } = await get('/users')).

  • The exported provider constant is a pre-built default client (no baseURL, 30 s timeout); prefer createAxiosClient({...}) so baseURL/credentials are explicit.

  • A bonded baseURL applies to every relative path, and a path that already starts with it is not prefixed twice: with baseURL: '/api', both get('/articles') and get('/api/articles') request /api/articles. Leave the base URL off and both ask the PAGE origin, which answers its own index.html with a 200.

  • An API whose scheme is not Bearer (Authorization: Token <jwt>) passes authScheme: 'Token' to THIS package's constructor — setClient(createAxiosClient({ baseURL, authScheme: 'Token' })) — and the auth token is then sent with that scheme. It is NOT a property of the client setClient()/getClient() hands around: that is a built HttpClient, and client.authScheme = 'Token' is a type error that changes no header. The option name is the same one @molecule/app-http's HttpClientConfig declares, so the config reads the same whichever transport is bonded.

  • instance/axiosConfig accept raw Axios options — anything the app sets there couples it to Axios; keep app code on the @molecule/app-http interface so the bond stays swappable.