@lamstack/http-client
A framework-agnostic HTTP client core built around a pluggable, Koa/onion-style
middleware pipeline. The core has zero runtime dependency on axios or fetch — you
choose a transport adapter (fetch or axios, both included) and layer behavior
(credential attachment, failure recovery, error mapping, or anything you write yourself)
on top via a single .use() API. No plugin shipped with this package — not auth, not
recover — has any capability you don’t also have.
Unlike the rest of @lamstack, this package has no React dependency at all — it works
identically in a Node service, a React Native app, or a browser SPA.
Pre-1.0 (0.x): the API may still change between minor versions. retryPlugin, upload/download
progress, and a session-layer helper are architected for but not implemented yet — see
Roadmap below.
pnpm
pnpm add @lamstack/http-clientaxios is an optional peer dependency — only needed if you use
@lamstack/http-client/adapters/axios. Sticking to the fetch adapter, you never
install it.
Quickstart
import { HttpClient } from '@lamstack/http-client';
import { fetchAdapter } from '@lamstack/http-client/adapters/fetch';
const client = new HttpClient({
adapter: fetchAdapter(),
baseURL: 'https://api.example.com',
});
interface User {
id: string;
name: string;
}
const user = await client.get<User>('/users/me');
await client.post('/users', { name: 'Ada' });
await client.put(`/users/${user.id}`, { name: 'Ada Lovelace' });
await client.delete(`/users/${user.id}`);get/post/put/patch/delete all return the parsed response body directly —
not a wrapper object. Use client.request() (see
API reference) when you need the status code,
headers, or other response metadata.
Attaching credentials and recovering from an expired one is two more .use() calls:
import { auth, bearer, recover, onStatus } from '@lamstack/http-client';
const refreshClient = client.extend({}); // no plugins yet — safe for the refresh call itself
client.use(
recover({
recover: () => session.renew(), // your own object — see Concepts below
shouldRecover: onStatus(401),
}),
);
client.use(auth(bearer(session)));- Concepts — the request lifecycle, the middleware pipeline and
its re-entrant
next(),metaflags, and howauth/recoverfit together around a token store. - API reference —
HttpClient, both adapters, every built-in plugin,HttpError,EventBus, and the serializers. - Testing — scripted adapters for integration-style tests, and
resolve()for unit-testing a plugin directly.
Why this exists
Most HTTP client wrappers pick a transport (axios, or fetch) and bolt auth/recovery
logic onto it via that transport’s own interceptor system. That logic then can’t move to
a different transport, and typically can’t be unit-tested without mocking the transport
itself. This package inverts that: the pipeline (auth, recovery, error mapping, retry
policy, anything else) is transport-agnostic middleware; adapters are a thin,
interchangeable translation layer between that pipeline and a real transport. The same
auth/recover setup works identically whether the underlying adapter is fetch or an
existing axios instance — proven by a shared contract test suite that runs both
adapters through identical scenarios (200/404/500/timeout/abort/…) and asserts
identical results.
Roadmap
Not yet implemented:
retryPlugin— backoff/jitter,Retry-Aftersupport, method-safety rules.PluginOrder.retryis already reserved for it.- Upload/download progress — both adapters currently report every
AdapterCapabilitiesfieldfalse, honestly. - An SSE plugin — the plugin system is already extensible enough for one; it just doesn’t ship yet.
- A session-layer helper — a built-in primitive tying a stored token to both
auth()andrecover(), so the hand-written session object in Concepts isn’t the only option. An earlier version of this shipped briefly during0.1.0development and was pulled before release to be redesigned rather than carried forward as-is.