Universal HTTP fetch library with intelligent parsing, error handling, retry logic, and cross-environment compatibility
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Create customized fetch instances with default options, base URLs, platform-specific settings, and advanced configuration for different environments and use cases.
Create customized fetch instances with default options that apply to all requests made with that instance.
/**
* Create a customized fetch instance with default options
* @param defaults - Default fetch options to merge with each request
* @param globalOptions - Global configuration for fetch implementation
* @returns New $Fetch instance with configured defaults
*/
function create(
defaults?: FetchOptions,
globalOptions?: CreateFetchOptions
): $Fetch;
interface CreateFetchOptions {
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}Usage Examples:
import { ofetch } from "ofetch";
// Basic API client with base URL
const api = ofetch.create({
baseURL: "https://api.example.com"
});
// Full configuration with authentication and timeouts
const authenticatedApi = ofetch.create({
baseURL: "https://api.example.com",
headers: {
"Authorization": "Bearer token123",
"Content-Type": "application/json",
"User-Agent": "MyApp/1.0"
},
timeout: 10000,
retry: 3,
retryDelay: 1000
});
// Environment-specific configuration
const api = ofetch.create({
baseURL: process.env.API_BASE_URL,
headers: {
"X-API-Key": process.env.API_KEY
}
});Lower-level factory function for creating fetch instances with custom fetch implementations and global options.
/**
* Factory function to create fetch instances with custom implementations
* @param globalOptions - Global configuration including custom fetch implementation
* @returns New $Fetch instance with specified configuration
*/
function createFetch(globalOptions?: CreateFetchOptions): $Fetch;Usage Examples:
import { createFetch } from "ofetch";
// Custom fetch instance with specific global options
const customFetch = createFetch({
defaults: {
baseURL: "https://internal.api.com",
timeout: 5000
},
fetch: globalThis.fetch,
Headers: globalThis.Headers,
AbortController: globalThis.AbortController
});
// Use with custom fetch implementation
const proxyFetch = createFetch({
fetch: (input, init) => {
console.log("Proxying request:", input);
return globalThis.fetch(input, init);
}
});Node.js optimized fetch creation with keep-alive support and HTTP agent configuration. The main ofetch package automatically detects Node.js environment and uses optimizations, but explicit Node.js configuration is available.
/**
* Creates Node.js-specific fetch with conditional keep-alive support
* Reads FETCH_KEEP_ALIVE environment variable to enable persistent connections
* @returns Fetch function with Node.js optimizations and optional keep-alive
*/
function createNodeFetch(): typeof globalThis.fetch;Keep-Alive Support:
When FETCH_KEEP_ALIVE environment variable is set to "true", Node.js HTTP and HTTPS agents are created with keepAlive: true to reuse connections across requests.
Usage Examples:
import { createNodeFetch } from "ofetch/node";
// Enable keep-alive via environment variable
process.env.FETCH_KEEP_ALIVE = "true";
const fetch = createNodeFetch();
// Without keep-alive (default behavior)
process.env.FETCH_KEEP_ALIVE = "false";
const standardFetch = createNodeFetch();
// Use in custom instance
import { createFetch } from "ofetch";
const nodeFetch = createFetch({
fetch: createNodeFetch(),
defaults: { timeout: 10000 }
});
// Automatic Node.js detection (recommended)
import { ofetch } from "ofetch"; // Uses Node.js optimizations automatically in Node.js
const data = await ofetch("https://api.example.com/data");Comprehensive options for configuring individual requests and default behaviors.
interface FetchOptions<R extends ResponseType = ResponseType, T = any>
extends Omit<RequestInit, "body">, FetchHooks<T, R> {
// URL Configuration
baseURL?: string;
query?: Record<string, any>;
params?: Record<string, any>; // Alias for query
// Request Body
body?: RequestInit["body"] | Record<string, any>;
// Response Handling
responseType?: R;
parseResponse?: (responseText: string) => any;
ignoreResponseError?: boolean;
// Timeout and Retry
timeout?: number;
retry?: number | false;
retryDelay?: number | ((context: FetchContext<T, R>) => number);
retryStatusCodes?: number[];
// Streaming
duplex?: "half" | undefined;
// Node.js Specific (>= 18)
dispatcher?: InstanceType<typeof import("undici").Dispatcher>;
// Node.js Specific (< 18)
agent?: unknown;
}Usage Examples:
import { ofetch } from "ofetch";
// URL and query configuration
const data = await ofetch("https://api.example.com/search", {
baseURL: "https://api.example.com", // Would result in https://api.example.com/search
query: { q: "typescript", limit: 10 }
});
// Response configuration
const text = await ofetch("https://api.example.com/document", {
responseType: "text",
parseResponse: (text) => text.toUpperCase()
});
// Timeout and retry configuration
const data = await ofetch("https://unreliable-api.com/data", {
timeout: 5000,
retry: 3,
retryDelay: (context) => Math.min(1000 * Math.pow(2, context.options.retry || 0), 10000),
retryStatusCodes: [408, 429, 500, 502, 503, 504]
});
// Error handling configuration
const response = await ofetch("https://api.example.com/might-fail", {
ignoreResponseError: true // Won't throw on 4xx/5xx status codes
});Configure request headers with proper merging and override behavior.
interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any>
extends FetchOptions<R, T> {
headers: Headers;
}Usage Examples:
import { ofetch } from "ofetch";
// Static headers
const api = ofetch.create({
headers: {
"Authorization": "Bearer token",
"Content-Type": "application/json"
}
});
// Dynamic headers
const api = ofetch.create({
async onRequest({ options }) {
const token = await getAuthToken();
options.headers.set("Authorization", `Bearer ${token}`);
}
});
// Per-request header override
const data = await api("/admin/users", {
headers: {
"X-Admin": "true" // Adds to existing headers
}
});ofetch uses conditional exports to automatically provide the best implementation for each environment:
globalThis.fetch with polyfill fallbacknode-fetch-native with conditional keep-alive supportglobalThis.fetchPackage Exports Structure:
{
"exports": {
".": {
"node": "./dist/node.mjs",
"import": "./dist/index.mjs",
"require": "./dist/node.cjs"
},
"./node": {
"import": "./dist/node.mjs",
"require": "./dist/node.cjs"
}
}
}Advanced Node.js specific configuration including HTTP agents, proxies, and custom dispatchers.
Usage Examples:
// HTTP Agent configuration (Node.js < 18)
import { HttpsProxyAgent } from "https-proxy-agent";
import { ofetch } from "ofetch";
const data = await ofetch("https://api.example.com/data", {
agent: new HttpsProxyAgent("http://proxy.example.com:8080")
});
// Undici Dispatcher (Node.js >= 18)
import { ProxyAgent } from "undici";
import { ofetch } from "ofetch";
const proxyAgent = new ProxyAgent("http://proxy.example.com:8080");
const data = await ofetch("https://api.example.com/data", {
dispatcher: proxyAgent
});
// Keep-alive configuration
process.env.FETCH_KEEP_ALIVE = "true";
import { ofetch } from "ofetch/node";
// All requests will use keep-alive connectionsinterface CreateFetchOptions {
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}
type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">;Install with Tessl CLI
npx tessl i tessl/npm-ofetch