@gitkraken/api-tools
v0.2.0
Published
Validation-agnostic HTTP/auth transport for GitKraken client SDKs (token-per-request, envelope unwrapping).
Downloads
184
Readme
@gitkraken/api-tools
Validation-agnostic HTTP/auth transport for GitKraken client SDKs.
Transport wraps a host-injected request function (or a default globalThis.fetch
requester), attaches a fresh bearer token per request, unwraps the identity-service
{ data, error } envelope, and surfaces non-2xx (and 3xx redirects) as a typed
HttpError. Callers narrow the unwrapped data by passing an optional parse hook;
the transport itself owns no schema library.
Install
pnpm add @gitkraken/api-toolsUsage
import { Transport, HttpError } from '@gitkraken/api-tools';
const transport = new Transport({
baseUrl: 'https://id.gitkraken.com',
getToken: async () => authStore.accessToken, // awaited per request
});
// `parse` runs on the unwrapped envelope data; bring your own validator (zod, etc.).
const { data, status, headers } = await transport.request({
method: 'GET',
path: '/v1/demographic',
parse: (raw) => demographicSchema.parse(raw),
});request<T> takes { method, path, body?, headers?, signal?, parse? } and resolves
{ data: T | undefined, status, headers }. data is undefined for a 204 or an
empty JSON body (an empty body with a non-JSON content-type resolves ''); caller headers are merged over the defaults (Authorization,
Content-Type: application/json).
Injecting your own request function
The host owns the network. Omit request to use the default fetch adapter, or pass
one (same { body, status, headers } shape as GitKraken's other SDKs) for proxies,
on-prem hosts, or custom TLS:
const transport = new Transport({
baseUrl,
getToken,
request: async ({ method, url, headers, body, signal }) => {
const res = await myHttp(method, url, { headers, body, signal });
return { body: res.text, status: res.status, headers: res.headers };
},
logger: { debug: log.debug, warn: log.warn, error: log.error }, // optional
});Errors
A non-2xx response, a 3xx redirect (not followed), a 2xx { data, error } envelope
with a non-null error, or malformed JSON all reject with an HttpError:
try {
await transport.request({ method: 'POST', path: '/v1/milestones', body });
} catch (err) {
if (err instanceof HttpError) {
// err.status, err.body (parsed when JSON), err.headers
}
}Responses
204/ empty body (no or JSON content-type) →data: undefined.- Empty body typed non-JSON (e.g.
text/plain) →''. - JSON
{ data, error }→ unwrappeddata; an object withoutdata/errorkeys is returned as-is; a non-JSON body is handed back untouched. parse, when provided, runs last on the unwrapped value.
