Skip to content

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

typescript
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:

typescript
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.

typescript
// 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:

typescript
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):

typescript
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:

typescript
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.

Released under the MIT License.