@molecule/app-http-axios
Provider bond · http · App (browser) · v1.0.5 · Apache-2.0
Axios HTTP client provider for @molecule/app-http
npm install @molecule/app-http-axiosnpm · Source on GitHub · Implements @molecule/app-http
How it works
@molecule/app-http-axios is a provider bond on the app (browser) side: it implements the http core interface (@molecule/app-http) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
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' })Works with: @molecule/app-http
Reference
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.tsJSDoc, 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
}
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
}
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 itself depends on must set this. A gate registered with
* `setAuthGate` that waits for a session restore whose own request goes through this
* client otherwise waits on itself: the gate holds the restore's request, the restore's
* promise never settles, and every request on the page stalls until the gate times out —
* so pass `skipAuthGate: true` on the restore's own request:
*
* ```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.
*/
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>
}
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.
declare class HttpError extends Error {
status: number
response?: HttpResponse | undefined
config?: FullRequestConfig | undefined
errorKey?: string | undefined
constructor(
message: string,
status: number,
response?: HttpResponse | undefined,
config?: FullRequestConfig | undefined,
errorKey?: string | undefined,
)
}
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.1axios^1.6.0
Runtime Dependencies
-
@molecule/app-http -
axios -
Call
setClient(...)at startup, BEFORE anyget/postfrom@molecule/app-httpruns. The core'sgetClient()lazily bonds its own fetch-based fallback on first use — requests issued beforesetClient()silently bypass the Axios client (no interceptors, no auth token). -
get()/post()/… resolve toHttpResponse<T>— read.datafor the body (const { data: users } = await get('/users')). -
The exported
providerconstant is a pre-built default client (no baseURL, 30 s timeout); prefercreateAxiosClient({...})so baseURL/credentials are explicit. -
An API whose scheme is not
Bearer(Authorization: Token <jwt>) passesauthScheme: '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 clientsetClient()/getClient()hands around: that is a builtHttpClient, andclient.authScheme = 'Token'is a type error that changes no header. The option name is the same one@molecule/app-http'sHttpClientConfigdeclares, so the config reads the same whichever transport is bonded. -
instance/axiosConfigaccept raw Axios options — anything the app sets there couples it to Axios; keep app code on the@molecule/app-httpinterface so the bond stays swappable.