Overview
This guide covers the base hapic package — the Client class and everything around it. If you're using a service client like @hapic/harbor, everything here applies too: those clients are a Client, extended with typed domain APIs.
The request lifecycle
The heart of hapic is Client.request(config). Every method shortcut (get, post, …) funnels into it. A single call walks these steps in order:
- Build headers — merge the per-request headers over the client's default headers.
- Resolve the URL — apply
baseURL, then appendparams/query(withbigintvalues stringified). - Request hooks — run every
requesthook; each may rewrite the options. - Transformers — apply the
transformfunction(s) to the body (and headers). - Dispatch — call
fetch, with or without a proxy. - Decode — pick a decoder by
responseType, or detect it from theContent-Typeheader:stream·blob·arrayBuffer·text·json. - Error check — a status of 400–599 builds a
ClientErrorand runs the error hooks. - Response hooks — run every
responsehook; each may rewrite the response.
The decoded body is exposed lazily as response.data.
A map of the guide
Concepts
- The Client — construct and configure a client; every option explained.
- Instance Registry — create / use / set named singleton clients.
Making Requests
- Request Methods —
get/post/put/patch/delete/headand the genericrequest. - Responses — the
Responseobject,responseType, and body decoding. - Headers & Authorization — default headers and the Basic / Bearer / API-key helpers.
The Pipeline
- Hooks — intercept and recover from requests, responses, and errors.
- Transformers — shape outgoing bodies and incoming data.
- Error Handling —
ClientError, error codes, and the guard helpers.
Advanced
- Proxy & Environments — proxy support and the cross-environment
fetchresolution. - Building a Service Client — extend
Clientwith your own domain APIs, the way the@hapic/*packages do.
A quick mental model
typescript
import { createClient } from 'hapic';
const client = createClient({
baseURL: 'https://api.example.com/',
headers: { accept: 'application/json' },
});
// defaults + per-request options are merged for every call
const { data } = await client.get('users', {
query: { page: 1, page_size: 25 },
});A Client is just defaults + headers + a hook manager, wrapped around fetch. Keep that in mind and the rest of the API falls into place.