undici-extra
v1.2.0
Published
Extra features for Undici with an elegant API, smart dispatcher, robust retries, and more.
Maintainers
Readme
undici-extra wraps undici.fetch to provide an elegant and familiar API while maintaining the high-performance core of Undici.
Benefits
- 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.
📦 Installation
npm install undici-extrapnpm
pnpm install undici-extrayarn
yarn add undici-extra📖 Usage
Basic Usage
import undici from 'undici-extra';
const data = await undici('https://api.example.com/data').json();JSON
Simplified JSON sending with automatic headers.
await undici.post('https://api.example.com/users', {
json: { name: 'John Doe' },
});Prefix URL
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();Hooks
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
}
},
],
},
});Automatic Retries
Robust retry logic with exponential backoff.
await undici('https://api.example.com/retry', {
retry: {
limit: 5,
statusCodes: [408, 429, 500, 502, 503, 504],
},
});Proxy & Unix Sockets
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' });Pagination
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);
}Streaming
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()));NDJSON
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);
}Request Deduping
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 }),
]);Throttling
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);Debugging
Log equivalent curl commands for easier debugging.
await undici('https://api.example.com', { debug: true });
// Output: curl -X GET "https://api.example.com"📚 Documentation
For all configuration options, please see the API docs.
🤝 Contributing
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! 🙏
License
MIT © Shahrad Elahi and contributors.
