Quick Start
A Client holds a set of defaults (a baseURL, headers, transformers, proxy settings) and exposes method shortcuts — get, post, put, patch, delete, head — that resolve a URL, run the request lifecycle, decode the body, and either return a typed Response or throw a ClientError.
Create a client
import { createClient } from 'hapic';
const client = createClient({
baseURL: 'https://jsonplaceholder.typicode.com/',
});createClient(options) is a thin wrapper around new Client(options). If you don't need a baseURL you can import the default instance instead:
import client from 'hapic';
const { data } = await client.get('https://jsonplaceholder.typicode.com/users/1');Make requests
Every method returns a Response whose data property holds the decoded body. JSON responses are parsed automatically.
// GET — read a resource
const { data: user } = await client.get<User>('users/1');
// POST — create a resource (body is serialized, Content-Type set)
const { data: created } = await client.post('users', { name: 'Peter' });
// PATCH — partial update
await client.patch(`users/${created.id}`, { name: 'Peter P.' });
// DELETE
await client.delete(`users/${created.id}`);Pass a generic to type the decoded data:
interface User {
id: number;
name: string;
}
const { data } = await client.get<User[]>('users');
// ^? Response<User[]>Handle errors
hapic throws a ClientError for any response in the 400–599 range, and for network/dispatch failures. Use the duck-typed guards rather than instanceof — they work across realm boundaries (e.g. multiple bundled copies of the package):
import { isClientError, isClientErrorWithStatusCode } from 'hapic';
try {
await client.get('users/99999');
} catch (error) {
if (isClientErrorWithStatusCode(error, 404)) {
console.warn('user not found');
} else if (isClientError(error)) {
console.error(error.status, error.message);
} else {
throw error;
}
}The ClientError carries the originating request, the response (when there is one), and the status. See Error Handling for the full surface.
Add authorization
Set an authorization header once, and it applies to every subsequent request:
client.setAuthorizationHeader({ type: 'Bearer', token: '<access-token>' });
// Basic auth
client.setAuthorizationHeader({ type: 'Basic', username: 'admin', password: 'secret' });
// API key
client.setAuthorizationHeader({ type: 'X-API-Key', key: '<api-key>' });See Headers & Authorization for details.
Going further
- The Client — every configuration option.
- Hooks — intercept and recover from requests, responses, and errors.
- Instance Registry — share one configured client across your app.
- Packages — typed clients for Harbor, Vault, Loki, VictoriaLogs, and OAuth2.