@philiprehberger/http-client
v0.4.3
Published
Type-safe fetch wrapper with interceptors, retries, and base URL support
Readme
@philiprehberger/http-client
Type-safe fetch wrapper with interceptors, retries, and base URL support.
Installation
npm install @philiprehberger/http-clientUsage
Basic
import { createClient } from '@philiprehberger/http-client';
const api = createClient({
baseURL: 'https://api.example.com',
timeout: 5000,
});
const user = await api.get<User>('/users/1');
const created = await api.post<User>('/users', { body: { name: 'Alice' } });
await api.put<User>('/users/1', { body: { name: 'Bob' } });
await api.patch<User>('/users/1', { body: { name: 'Bob' } });
await api.delete('/users/1');
await api.head('/users/1');
await api.options('/users');Query Parameters
const users = await api.get<User[]>('/users', {
params: { page: 2, limit: 10, active: true },
});
// GET /users?page=2&limit=10&active=trueAuth
const api = createClient({
baseURL: 'https://api.example.com',
auth: { type: 'bearer', token: 'my-token' },
});
// Or basic auth:
const api = createClient({
baseURL: 'https://api.example.com',
auth: { type: 'basic', username: 'user', password: 'pass' },
});Retry
const api = createClient({
baseURL: 'https://api.example.com',
retry: {
maxAttempts: 3,
retryOn: [500, 502, 503],
backoff: 1000,
backoffStrategy: 'exponential', // default, or 'linear'
jitter: true, // add randomized variation
maxBackoff: 30000, // cap maximum wait
},
});Interceptors
// Request interceptor
api.onRequest((req) => {
req.headers.set('X-Request-Id', crypto.randomUUID());
return req;
});
// Response interceptor
api.onResponse((res) => {
console.log(`${res.url} → ${res.status} (${res.duration}ms)`);
return res;
});Timeout
// Default timeout for all requests
const api = createClient({ timeout: 5000 });
// Per-request override
await api.get('/slow-endpoint', { timeout: 30000 });Response Type
// Force response parsing regardless of Content-Type header
const html = await api.get<string>('/page', { responseType: 'text' });
const data = await api.get<Blob>('/file', { responseType: 'blob' });
const buf = await api.get<ArrayBuffer>('/binary', { responseType: 'arrayBuffer' });
const json = await api.get<MyType>('/data', { responseType: 'json' });Abort Signal
const controller = new AbortController();
await api.get('/data', { signal: controller.signal });
controller.abort();Error Handling
import { HttpError } from '@philiprehberger/http-client';
try {
await api.get('/not-found');
} catch (error) {
if (error instanceof HttpError) {
error.status; // 404
error.statusText; // 'Not Found'
error.url; // full URL
error.body; // parsed response body
}
}API Reference
createClient(options?: ClientOptions)
Returns an HTTP client with the following methods:
| Method | Signature | Description |
|--------|-----------|-------------|
| get | <T>(path, opts?) => Promise<T> | GET request. |
| post | <T>(path, opts?) => Promise<T> | POST request. |
| put | <T>(path, opts?) => Promise<T> | PUT request. |
| patch | <T>(path, opts?) => Promise<T> | PATCH request. |
| delete | <T>(path, opts?) => Promise<T> | DELETE request. |
| head | <T>(path, opts?) => Promise<T> | HEAD request. |
| options | <T>(path, opts?) => Promise<T> | OPTIONS request. |
| onRequest | (interceptor) => void | Add a request interceptor. |
| onResponse | (interceptor) => void | Add a response interceptor. |
ClientOptions
| Property | Type | Description |
|----------|------|-------------|
| baseURL | string | Prepended to all request paths. |
| headers | Record<string, string> | Default headers for all requests. |
| timeout | number | Default timeout in ms. |
| retry | RetryConfig | Retry configuration. |
| auth | AuthConfig | Auth configuration (bearer or basic). |
RetryConfig
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| maxAttempts | number | 1 | Total attempts (1 = no retry). |
| retryOn | number[] \| (status) => boolean | None | HTTP status codes to retry on. |
| backoff | number | 1000 | Base backoff in ms. |
| backoffStrategy | 'linear' \| 'exponential' | 'exponential' | Backoff growth strategy. |
| jitter | boolean | false | Add random variation to backoff. |
| maxBackoff | number | 30000 | Maximum backoff cap in ms. |
RequestOptions
| Property | Type | Description |
|----------|------|-------------|
| headers | Record<string, string> | Per-request headers (merged with defaults). |
| params | Record<string, string \| number \| boolean> | Query parameters. |
| body | unknown | Request body (auto-serialized to JSON). |
| timeout | number | Per-request timeout override. |
| signal | AbortSignal | Abort signal for cancellation. |
| responseType | 'json' \| 'text' \| 'blob' \| 'arrayBuffer' | Force response parsing method (overrides Content-Type auto-detect). |
HttpError
| Property | Type | Description |
|----------|------|-------------|
| status | number | HTTP status code. |
| statusText | string | HTTP status text. |
| url | string | Request URL. |
| body | unknown | Parsed response body. |
Development
npm install
npm run build
npm testLicense
MIT
