undici-extra wraps undici.fetch to provide an elegant and familiar API while maintaining the high-performance core of Undici.
- Elegant API: Method shortcuts (
.post(),.put()) and direct response parsing (.json(),.text()). - Smart Dispatcher: Automatic handling and caching for Proxies and Unix Sockets.
- Robust Retries: Built-in retry logic with exponential backoff and customizable status codes.
- Request Lifecycle: Flexible hooks for
beforeRequest,afterResponse, andbeforeRetry. - Advanced Features: Native support for Throttling, Request Deduping, Pagination, and Node.js Streams (including NDJSON).
- Developer Friendly: Zero-config cURL command logging for easier debugging.
npm install undici-extraInstall using your favorite package manager
pnpm
pnpm install undici-extrayarn
yarn add undici-extraimport undici from 'undici-extra';
const data = await undici('https://api.example.com/data').json();Simplified JSON sending with automatic headers.
await undici.post('https://api.example.com/users', {
json: { name: 'John Doe' },
});Prepend a base URL to all requests.
const client = undici.extend({ prefixUrl: 'https://api.example.com/v1' });
const user = await client.get('users/1').json();Lifecycle hooks for modifying requests and responses.
const client = undici.extend({
hooks: {
beforeRequest: [
(request) => {
request.headers.set('X-Request-Id', crypto.randomUUID());
},
],
afterResponse: [
(request, options, response) => {
if (response.status === 401) {
// Handle unauthorized
}
},
],
},
});Robust retry logic with exponential backoff.
await undici('https://api.example.com/retry', {
retry: {
limit: 5,
statusCodes: [408, 429, 500, 502, 503, 504],
},
});Smart dispatcher resolution for proxies and sockets.
// Proxy
await undici('https://api.example.com', { proxy: 'http://my-proxy:8080' });
// Unix Socket
await undici('http://localhost/info', { unixSocket: '/var/run/docker.sock' });Easily iterate through paginated APIs.
const items = undici.paginate('https://api.example.com/events', {
pagination: {
transform: (res) => res.json().then((data) => data.items),
paginate: (res) => res.json().then((data) => data.next_page_url),
},
});
for await (const item of items) {
console.log(item);
}Seamlessly bridge Web Streams to Node.js streams with automatic error propagation and cleanup.
import fs from 'node:fs';
// One-liner for piping to disk
await undici('https://api.example.com/file.zip').pipe(
fs.createWriteStream('file.zip')
);
// Or get a Node.js Readable stream
const stream = await undici('https://api.example.com/data').stream();
stream.on('data', (chunk) => console.log(chunk.toString()));Native support for streaming newline-delimited JSON.
for await (const log of undici('https://api.example.com/logs').ndjson()) {
console.log(log.level, log.message);
}Automatically coalesces concurrent requests to the same endpoint.
// Only one network request is made
const [r1, r2] = await Promise.all([
undici('https://api.com/data', { dedup: true }),
undici('https://api.com/data', { dedup: true }),
]);Built-in rate limiting with support for shared buckets across extended clients.
const client = undici.extend({
throttle: { limit: 10, interval: 1000 }, // 10 requests per second
});
// These will be queued and executed at the specified rate
await Promise.all([client('https://api.com/1'), client('https://api.com/2')]);
// Monitor the queue
console.log(client.queueSize);Log equivalent curl commands for easier debugging.
await undici('https://api.example.com', { debug: true });
// Output: curl -X GET "https://api.example.com"For all configuration options, please see the API docs.
Want to contribute? Awesome! To show your support is to star the project, or to raise issues on GitHub.
Thanks again for your support, it is much appreciated! π
MIT Β© Shahrad Elahi and contributors.