An open API service indexing awesome lists of open source software.

https://github.com/shahradelahi/undici-extra

🌊 Elegant HTTP client for Node.js based on Undici with extra features
https://github.com/shahradelahi/undici-extra

dedup fetch hooks http-client ndjson nodejs pagination proxy retry undici

Last synced: 4 months ago
JSON representation

🌊 Elegant HTTP client for Node.js based on Undici with extra features

Awesome Lists containing this project

README

          


undici-extra


CI
NPM Version
MIT License
npm bundle size
Install Size

_undici-extra_ wraps `undici.fetch` to provide an elegant and familiar API while maintaining the high-performance core of [Undici](https://github.com/nodejs/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`, and `beforeRetry`.
- **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.

---

- [Benefits](#benefits)
- [Installation](#-installation)
- [Usage](#-usage)
- [Documentation](#-documentation)
- [Contributing](#-contributing)
- [License](#license)

## 📦 Installation

```bash
npm install undici-extra
```

Install using your favorite package manager

**pnpm**

```bash
pnpm install undici-extra
```

**yarn**

```bash
yarn add undici-extra
```

## 📖 Usage

### Basic Usage

```ts
import undici from 'undici-extra';

const data = await undici('https://api.example.com/data').json();
```

### JSON

Simplified JSON sending with automatic headers.

```ts
await undici.post('https://api.example.com/users', {
json: { name: 'John Doe' },
});
```

### Prefix URL

Prepend a base URL to all requests.

```ts
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.

```ts
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.

```ts
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.

```ts
// 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.

```ts
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.

```ts
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.

```ts
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.

```ts
// 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.

```ts
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.

```ts
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](https://www.jsdocs.io/package/undici-extra).

## 🤝 Contributing

Want to contribute? Awesome! To show your support is to star the project, or to raise issues on [GitHub](https://github.com/shahradelahi/undici-extra).

Thanks again for your support, it is much appreciated! 🙏

## License

[MIT](/LICENSE) © [Shahrad Elahi](https://github.com/shahradelahi) and [contributors](https://github.com/shahradelahi/undici-extra/graphs/contributors).