@bekaert-dev/rqst
v1.0.4
Published
A small axios + zod based request client with built in data validation and builders for headers, body, and query string handling.
Readme
@bekaert-dev/rqst
A small axios + zod based request client with built in data validation and builders for headers, body, and query string handling.
Install
pnpm add @bekaert-dev/rqstPeer dependency (required):
pnpm add zodDocs:
- axios: https://axios-http.com
- zod: https://zod.dev
Quick start
import { rqst } from '@bekaert-dev/rqst'
import { z } from 'zod'
const api = rqst({ baseURL: 'https://api.example.com' })
const User = z.object({ id: z.string(), name: z.string() })
const user = await api.get('/users/1', User).execute()API
rqst(options?, instanceOptions?)
Creates a new client instance.
options(AxiosRequestConfig, optional): Base axios config applied to all requests.instanceOptions(InstanceOptions, optional): Extra rqst options.
Returns an object with HTTP methods and interceptor helpers:
get,post,put,patch,deleteaddRequestInterceptor,clearRequestInterceptoraddResponseInterceptor,clearResponseInterceptor
Request builder
Each HTTP method returns a request builder:
api.get('/users', schema)The builder supports chaining:
withOptions(options)withHeaders(headers)withBody(body)withQS(qs)execute(params?)
execute(params?)
type ExecuteParams<RequestResponse> = {
debug?: boolean
fallback?: RequestResponse
rethrowOnError?: boolean
}Behavior:
RequestResponse: the inferred output type from the zod schema you pass to the request (i.e.z.output<typeof schema>). It represents the successful return type of.execute()and also the type of anyfallbackyou provide.debug: logs the full axios response withconsole.log.fallback: returned if response decoding fails (zod validation error). When used, no error is thrown.rethrowOnError: whentrue, request errors are rethrown. Defaults totrue.
fallback and rethrowOnError can be used together. When both are set and decoding fails, the fallback is returned (and the decoding error is still logged) but the error is not rethrown. Request errors will still be rethrown when rethrowOnError is true.
Interceptors
The instance exposes helpers to register and clear interceptors. These map directly to axios interceptors.
const api = rqst()
const requestId = api.addRequestInterceptor(config => {
return config
})
const responseId = api.addResponseInterceptor(response => {
return response
})
api.clearRequestInterceptor(requestId)
api.clearResponseInterceptor(responseId)Error logging
Errors are normalized into a small set of types, and passed to a custom logger if provided. The customErrorLogger receives:
type customErrorLogger = (
url: string,
errorType: RqstErrorType,
err: unknown,
) => voidRqstErrorType values:
HTTP_ERRORNO_RESPONSEREQUEST_SETUP_INVALIDDECODING_FAILEDUNKNOWN
Example handling with a switch:
const api = rqst(undefined, {
customErrorLogger: (_url, errorType, err) => {
switch (errorType) {
case 'HTTP_ERROR':
console.error('Server returned an error response', err)
break
case 'NO_RESPONSE':
console.error('No response received', err)
break
case 'REQUEST_SETUP_INVALID':
console.error('Request setup failed', err)
break
case 'DECODING_FAILED':
console.error('Response validation failed', err)
break
case 'UNKNOWN':
default:
console.error('Unknown error', err)
}
},
})To provide a custom logger:
const api = rqst(
{ baseURL: 'https://api.example.com' },
{
customErrorLogger: (url, type, err) => {
console.error(url, type, err)
},
},
)Examples
With headers and query string
const schema = z.object({ ok: z.boolean() })
const result = await api
.get('/health', schema)
.withHeaders({ 'x-trace-id': 'abc' })
.withQS({ verbose: true })
.execute()With body and fallback
const schema = z.object({ id: z.string() })
const result = await api
.post('/users', schema)
.withBody({ name: 'Ada' })
.execute({ fallback: { id: 'unknown' } })Swallowing request errors
const schema = z.object({ ok: z.boolean() })
const result = await api
.get('/maybe-down', schema)
.execute({ rethrowOnError: false })
if (result === undefined) {
// request failed and was swallowed
}Type exports
import type { RqstAPI, RqstErrorType } from '@bekaert-dev/rqst'RqstAPI
type RqstAPI = ReturnType<typeof rqst>TypeScript & module format
This package is written in TypeScript and built with tsup. It publishes ESM and CJS builds.
- Module format: ESM (
dist/index.js) and CJS (dist/index.cjs). - TypeScript: developed against TypeScript 5.9.x. Other versions may work, but 5.9.x is the supported baseline.
