Configuration
Configuration is merged from client defaults and per-call options via mergeConfig (see merge rules below).
OpenFetchConfig (request)
URL and query
url— Absolute or relative (withbaseURL).baseURL— Prepended to non-absolute paths (see URL helpers in the package:buildURL,combineURLs,isAbsoluteURL).params— Plain object serialized to a query string (default serializer; override withparamsSerializer).paramsSerializer—(params: Record<string, unknown>) => string. When set, it replaces the built-in serialization for that request (merged config). Use for repeated keys, bracket notation, or custom encoding.
Method and body
method— HTTP method; helpers set this automatically.data— Logical payload: aftertransformRequesthooks, objects (exceptFormData,URLSearchParams,Blob,ArrayBuffer, typed arrays) are JSON-stringified;content-typedefaults toapplication/jsonif missing.body— Rawfetchbody when you do not usedatathe same way; dispatch usesdataif defined, elsebody.
Headers and auth
headers—Record<string, string>(normalized to lowercase keys internally for the outgoing request).auth—{ username, password }→Authorization: Basic ….withCredentials: true— Setscredentials: 'include'unlesscredentialsis set explicitly.
Timeouts and cancellation
timeout— Milliseconds; uses an internalAbortControllermerged withsignalviamergeAbortSignals. When the internal timeout fires first (user signal not aborted), the error code isERR_TIMEOUT. Pure user abort →ERR_CANCELED.signal— ExternalAbortSignal; combined with timeout abort.
Response handling
responseType—"json"|"text"|"arraybuffer"|"blob"|"stream".
If omitted, dispatch infers JSON fromContent-Type: application/json, otherwise reads as text. WhenresponseTypeis set andacceptis missing, dispatch sets a suggestedAcceptheader (e.g.application/jsonforjson).rawResponse— Whentrue,dispatchreturns anOpenFetchResponsewhosedatais the nativeResponsewith an unread body. Body parsing and thetransformResponsechain are skipped. Request interceptors still ran earlier; response interceptors still run and seedataas thatResponse. Middleware that expects parsed JSON inctx.response.datawill not see transforms until you callresponse.json()/text()yourself. Pair withcloneResponse(package export) if you need two independent reads of the sameResponse.validateStatus—(status: number) => boolean. Default: 200–299 inclusive. If false, throwsOpenFetchErrorwith codeERR_BAD_RESPONSEand attaches the response.throwHttpErrors— Used only whenvalidateStatusis omitted. Ky-style control:falsemeans never throw on HTTP status (same asvalidateStatus: () => true). A function(status) => booleanmeans throw when it returnstruefor that status. IfvalidateStatusis provided,throwHttpErrorsis ignored.jsonSchema— Optional Standard Schema (e.g. Zod 3.24+) applied to parsed JSON after a successfulvalidateStatus. On failure throwsSchemaValidationError(notOpenFetchError). Runs before thetransformResponsechain.init— Array of synchronous(config) => voidcallbacks on the merged config, aftermergeConfigand before request interceptors. Use to attach headers, tweak options, etc.
Request input
- Besides
string | URLand a config object,client.request(nativeRequest, overrides?)accepts aRequest. URL, method, headers, body,signal, and supportedRequestInitfields are copied from theRequest, then shallow-overridden by merged defaults +overrides.
Transforms
transformRequest— Array of(data, headers) => unknown. Run in order before building the fetch body.transformResponse— Array of(data) => T. Run on successful responses after parsing.
Middleware, retry, cache hints
middlewares— Array of middleware functions (concatenated with defaults).retry— Shallow-merged retry options forcreateRetryMiddleware(defaults + per request).memoryCache— Per-request overrides for cache middleware:ttlMs,staleWhileRevalidateMs,skip.
Ergonomics
unwrapResponse— Whentrue,get/post/… returndataonly instead of fullOpenFetchResponse. Useful for RSC and minimal call sites.
Debugging (observability)
debug—true,"verbose","basic", or omit /falsefor off. When enabled, emits structuredOpenFetchDebugEventrecords for the HTTP lifecycle (merge, fetch per attempt, parse, schema, retries, final response, errors)."basic"limits events torequest,response, anderror.logger—(event) => voidsink whendebugis enabled; omit to log viaconsole.debug. See Debugging & observability for stages, privacy defaults, and how this differs from thedebug()plugin.
RequestInit passthrough
These RequestInit fields are typed on OpenFetchConfig and passed to fetch:
cache, credentials, integrity, keepalive, mode, redirect, referrer, referrerPolicy.
Node.js: dispatcher and HTTP/2 (allowH2)
On Node (and any runtime whose fetch accepts a Undici-style dispatcher option), you can pass:
dispatcher— Your own agent or pool (for examplenew Agent({ allowH2: true })from theundicipackage you install). OpenFetch forwards it tofetchwhen the runtime supports it.allowH2: true— Shorthand: OpenFetch dynamically loadsundici, builds anAgentwithallowH2: true, and passes it asdispatcher.
undici is not an npm dependency of @hamdymohamedak/openfetch. The published package has no dependencies, no peerDependencies, and does not bundle undici. Install it only when you need this path: npm install undici. If allowH2 is true and import("undici") fails, OpenFetch throws OpenFetchError with code ERR_UNDICI_REQUIRED.
In browsers and on edges where fetch ignores dispatcher, these options have no effect or are ignored by the runtime.
OpenFetchResponse
type OpenFetchResponse<T = unknown> = {
data: T;
status: number;
statusText: string;
headers: Record<string, string>;
config: OpenFetchConfig;
};Other exports (main package)
Useful when building tooling, logs, or custom middleware:
| Export | Role |
|---|---|
assertSafeHttpUrl(url) | Optional guard for untrusted URLs (see Errors & security). |
maskHeaderValues(headers, options?) | Redact sensitive header values (partial / hash strategies). |
cloneResponse(res) | Clone a native Response so the body can be read more than once. |
generateIdempotencyKey, hasIdempotencyKeyHeader, ensureIdempotencyKeyHeader | Helpers for POST retry idempotency (see Retry & cache). |
InterceptorManager | Low-level stack; normally you use client.interceptors. |
SchemaValidationError, isSchemaValidationError | Standard Schema failures on jsonSchema / fluent .json(schema). |
OpenFetchForceRetry, isOpenFetchForceRetry | Throw from retry.onAfterResponse to force another attempt. |
isHTTPError, isTimeoutError | Narrow OpenFetchError by code / semantics. |
| Standard Schema types | StandardSchemaV1, StandardSchemaV1InferOutput, … (types only). |
| Types | OpenFetchConfig, OpenFetchResponse, Middleware, OpenFetchContext, … |
Plugins and fluent client live under @hamdymohamedak/openfetch/plugins and /sugar — see Plugins & fluent API.
Merge behavior (mergeConfig)
- Top-level keys: later config wins.
headers: shallow merge; per-call headers override defaults.middlewares,transformRequest,transformResponse,init: concatenated (defaults first, then call-specific).retry,memoryCache: shallow merge of scalar fields;retry.onBeforeRetryandretry.onAfterResponseare composed (defaults run first, then per-call).- Prototype-pollution keys (
__proto__,constructor,prototype) are stripped from merged objects and nestedheaders/retry/memoryCache.
Quick checklist (common options)
| Goal | Config / approach |
|---|---|
| JSON API base URL | baseURL + relative url; get/post helpers |
| Query string | params or custom paramsSerializer |
| Bearer token | headers: { authorization: "Bearer …" } |
| Timeout | timeout (ms) or timeout(ms) plugin |
| Cancel | signal from AbortController |
| Only body value | unwrapResponse: true |
| Binary / file | responseType: "blob" or "arraybuffer" |
| Streaming | responseType: "stream" |
Raw fetch Response | rawResponse: true or fluent .raw() |
| Retries | createRetryMiddleware or retry() plugin |
| GET caching | createCacheMiddleware + MemoryCacheStore |
| Structured lifecycle logs | debug + optional logger on defaults (see Debugging) |
| Node HTTP/2 or custom agent | User-installed undici + dispatcher or allowH2: true (dispatcher / allowH2) |
Next
- Debugging & observability — client debug pipeline,
debug()plugin, safe logging - Features & request pipeline — full feature list and diagrams
- Plugins & fluent API
- Interceptors & middleware
