Skip to content

Repository files navigation

hapic

hapic

The tiny, fetch-based HTTP API client.
Request & response hooks, transformers, authorization helpers and proxy support —
plus a family of typed service clients built on the same core.

CInpm versionKnown VulnerabilitiesConventional CommitsLicense

Documentation · Getting Started · Guide · Packages


Why hapic?

Most HTTP libraries sit at one of two extremes: a bare fetch wrapper where you re-solve auth, JSON handling and error throwing on every project — or a heavyweight SDK locked to a single backend. hapic splits the difference. A tiny base Client owns the transport — and typed service clients extend it for specific backends.

// the base client — fetch with batteriesimporthapicfrom'hapic';const{ data }=awaithapic.post('https://api.example.com/users',{name: 'Max'});// a typed service client built on that same coreimport{HarborClient}from'@hapic/harbor';constharbor=newHarborClient({connectionString: 'admin:pw@https://registry.example.com/api/v2.0/'});constproject=awaitharbor.project.getOne(1);// typed call → no URL building, no manual decoding

That split serves two audiences:

  • App developers get fetch with batteries included — baseURL, authorization headers, JSON in/out, errors that throw on non-2xx, proxy support, and hooks for retry/refresh-token flows — in a package small enough to drop into the browser, Node.js or a worker.
  • Service-client authors get a transport contract: extend Client, declare a few domain *API classes, and inherit the entire request lifecycle — hooks, transformers, error handling and cross-environment fetch — instead of re-implementing it per backend. The @hapic/* clients in this repo are exactly that pattern, shipped.

Features

  • Simple APIget / post / put / patch / delete / head shortcuts over a single request().
  • 🛑 Hooks to intercept and mutate requests, responses and errors — error hooks can even recover a failed request (retry / refresh token).
  • 🔄 Transformers for request payloads & headers.
  • 🔐 Authorization helpersBasic, Bearer and api-key headers from a typed config.
  • Throws on non-2xx — every 400–599 response becomes a typed HttpResponseError; network failures become a NetworkError.
  • 🎭 Proxy support out of the box.
  • 🌐 Runs everywhere — Node.js, the browser and worker environments, through one cross-env fetch layer.
  • 🧩 Typed service clients for Harbor, Loki, OAuth2, Vault and VictoriaLogs — all on the same core.

Getting Started

npm install hapic
importhapic,{createClient}from'hapic';// use the default singleton instance...constresponse=awaithapic.post('https://api.example.com/users',{firstName: 'Max',lastName: 'Mustermann',});console.log(response);// { data: …, headers: …, status: …, statusText: … }// ...or create a configured clientconstclient=createClient({baseURL: 'https://api.example.com/',});const{ data }=awaitclient.get('users/1');

Follow the full walkthrough at hapic.tada5hi.net/getting-started.

The request lifecycle

Every request(config) runs through the same pipeline. Hooks and transformers slot into it, so cross-cutting concerns live in one place instead of at every call site:

request(config)
1. merge headers over the client defaults
2. resolve URL baseURL + params/query
3. request hooks ← intercept / mutate the outgoing request
4. transformers ← reshape the body
5. dispatch fetch(url, init) (with optional proxy)
6. decode by responseType, or detected from Content-Type
7. throw on 4xx–5xx ← error hooks may recover: return a Response, or retry
8. response hooks ← inspect / transform the result
import{createClient,HookName}from'hapic';constclient=createClient({baseURL: 'https://api.example.com/'});// attach a bearer token on every requestclient.on(HookName.REQUEST,(request)=>({
...request,headers: { ...request.headers,authorization: `Bearer ${token}`},}));// recover from a 401 by refreshing the token and retryingclient.on(HookName.REQUEST_ERROR,async(error)=>{if(error.response?.status===401){token=awaitrefreshToken();returnerror.request;// returning RequestOptions retries the request}});

→ Deep dive: The Client · Hooks · Transformers · Error Handling · Building a Service Client

Packages

Base

PackageVersionDescription
hapicnpmBase fetch-based HTTP client — request methods, hooks, transformers, headers, authorization, proxy and auto-throwing errors. The foundation every other package builds on.

Service Clients

PackageVersionDescription
@hapic/harbornpmTyped client for the Harbor container registry — projects, repositories, artifacts, robots, webhooks and more.
@hapic/lokinpmClient for Grafana Loki — push, query and analyze logs through the querier, distributor and compactor endpoints.
@hapic/oauth2npmOAuth2 / OpenID Connect client — authorization flows, token issuance, userinfo and provider metadata.
@hapic/vaultnpmClient for HashiCorp Vault — key-value engines (v1/v2), mounts and secrets management.
@hapic/victorialogsnpmClient for VictoriaLogs — ingest and query logs via its HTTP API.

Every service client follows the same shape — a <Service>Client extends Client composing domain *API classes — so once you know one, you know them all. See Building a Service Client to publish your own.

Contributing

npm ci # install
npm run build # build all packages (Nx, cached)
npm run test# run tests
npm run lint # ESLint — must pass with zero errors

Commits follow Conventional Commits; releases and changelogs are automated via release-please.

License

Made with 💚

Published under MIT License.

About

A tiny & simple fetch based http client with a collection of different presets.

Topics

Resources

Security policy

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages