{"id":43978424,"url":"https://github.com/shahradelahi/undici-extra","last_synced_at":"2026-02-15T09:17:44.030Z","repository":{"id":336361891,"uuid":"1149312696","full_name":"shahradelahi/undici-extra","owner":"shahradelahi","description":"🌊 Elegant HTTP client for Node.js based on Undici with extra features","archived":false,"fork":false,"pushed_at":"2026-02-04T04:11:56.000Z","size":113,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-04T14:45:41.435Z","etag":null,"topics":["dedup","fetch","hooks","http-client","ndjson","nodejs","pagination","proxy","retry","undici"],"latest_commit_sha":null,"homepage":"https://npmjs.com/undici-extra","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shahradelahi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-04T01:05:36.000Z","updated_at":"2026-02-04T10:03:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shahradelahi/undici-extra","commit_stats":null,"previous_names":["shahradelahi/undici-extra"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/shahradelahi/undici-extra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fundici-extra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fundici-extra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fundici-extra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fundici-extra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shahradelahi","download_url":"https://codeload.github.com/shahradelahi/undici-extra/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shahradelahi%2Fundici-extra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29190287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T07:37:03.739Z","status":"ssl_error","status_checked_at":"2026-02-07T07:37:03.029Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dedup","fetch","hooks","http-client","ndjson","nodejs","pagination","proxy","retry","undici"],"created_at":"2026-02-07T08:34:46.957Z","updated_at":"2026-02-15T09:17:43.999Z","avatar_url":"https://github.com/shahradelahi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003csup\u003eundici-extra\u003c/sup\u003e\n  \u003cbr\u003e\n  \u003ca href=\"https://github.com/shahradelahi/undici-extra/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/shahradelahi/undici-extra/actions/workflows/ci.yml/badge.svg?branch=main\u0026event=push\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/undici-extra\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/undici-extra.svg\" alt=\"NPM Version\"\u003e\u003c/a\u003e\n  \u003ca href=\"/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg?style=flat\" alt=\"MIT License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/package/undici-extra\"\u003e\u003cimg src=\"https://img.shields.io/bundlephobia/minzip/undici-extra\" alt=\"npm bundle size\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://packagephobia.com/result?p=undici-extra\"\u003e\u003cimg src=\"https://packagephobia.com/badge?p=undici-extra\" alt=\"Install Size\"\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n_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).\n\n## Benefits\n\n- **Elegant API:** Method shortcuts (`.post()`, `.put()`) and direct response parsing (`.json()`, `.text()`).\n- **Smart Dispatcher:** Automatic handling and caching for Proxies and Unix Sockets.\n- **Robust Retries:** Built-in retry logic with exponential backoff and customizable status codes.\n- **Request Lifecycle:** Flexible hooks for `beforeRequest`, `afterResponse`, and `beforeRetry`.\n- **Advanced Features:** Native support for Throttling, Request Deduping, Pagination, and Node.js Streams (including NDJSON).\n- **Developer Friendly:** Zero-config cURL command logging for easier debugging.\n\n---\n\n- [Benefits](#benefits)\n- [Installation](#-installation)\n- [Usage](#-usage)\n- [Documentation](#-documentation)\n- [Contributing](#-contributing)\n- [License](#license)\n\n## 📦 Installation\n\n```bash\nnpm install undici-extra\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eInstall using your favorite package manager\u003c/summary\u003e\n\n**pnpm**\n\n```bash\npnpm install undici-extra\n```\n\n**yarn**\n\n```bash\nyarn add undici-extra\n```\n\n\u003c/details\u003e\n\n## 📖 Usage\n\n### Basic Usage\n\n```ts\nimport undici from 'undici-extra';\n\nconst data = await undici('https://api.example.com/data').json();\n```\n\n### JSON\n\nSimplified JSON sending with automatic headers.\n\n```ts\nawait undici.post('https://api.example.com/users', {\n  json: { name: 'John Doe' },\n});\n```\n\n### Prefix URL\n\nPrepend a base URL to all requests.\n\n```ts\nconst client = undici.extend({ prefixUrl: 'https://api.example.com/v1' });\nconst user = await client.get('users/1').json();\n```\n\n### Hooks\n\nLifecycle hooks for modifying requests and responses.\n\n```ts\nconst client = undici.extend({\n  hooks: {\n    beforeRequest: [\n      (request) =\u003e {\n        request.headers.set('X-Request-Id', crypto.randomUUID());\n      },\n    ],\n    afterResponse: [\n      (request, options, response) =\u003e {\n        if (response.status === 401) {\n          // Handle unauthorized\n        }\n      },\n    ],\n  },\n});\n```\n\n### Automatic Retries\n\nRobust retry logic with exponential backoff.\n\n```ts\nawait undici('https://api.example.com/retry', {\n  retry: {\n    limit: 5,\n    statusCodes: [408, 429, 500, 502, 503, 504],\n  },\n});\n```\n\n### Proxy \u0026 Unix Sockets\n\nSmart dispatcher resolution for proxies and sockets.\n\n```ts\n// Proxy\nawait undici('https://api.example.com', { proxy: 'http://my-proxy:8080' });\n\n// Unix Socket\nawait undici('http://localhost/info', { unixSocket: '/var/run/docker.sock' });\n```\n\n### Pagination\n\nEasily iterate through paginated APIs.\n\n```ts\nconst items = undici.paginate('https://api.example.com/events', {\n  pagination: {\n    transform: (res) =\u003e res.json().then((data) =\u003e data.items),\n    paginate: (res) =\u003e res.json().then((data) =\u003e data.next_page_url),\n  },\n});\n\nfor await (const item of items) {\n  console.log(item);\n}\n```\n\n### Streaming\n\nSeamlessly bridge Web Streams to Node.js streams with automatic error propagation and cleanup.\n\n```ts\nimport fs from 'node:fs';\n\n// One-liner for piping to disk\nawait undici('https://api.example.com/file.zip').pipe(\n  fs.createWriteStream('file.zip')\n);\n\n// Or get a Node.js Readable stream\nconst stream = await undici('https://api.example.com/data').stream();\nstream.on('data', (chunk) =\u003e console.log(chunk.toString()));\n```\n\n### NDJSON\n\nNative support for streaming newline-delimited JSON.\n\n```ts\nfor await (const log of undici('https://api.example.com/logs').ndjson()) {\n  console.log(log.level, log.message);\n}\n```\n\n### Request Deduping\n\nAutomatically coalesces concurrent requests to the same endpoint.\n\n```ts\n// Only one network request is made\nconst [r1, r2] = await Promise.all([\n  undici('https://api.com/data', { dedup: true }),\n  undici('https://api.com/data', { dedup: true }),\n]);\n```\n\n### Throttling\n\nBuilt-in rate limiting with support for shared buckets across extended clients.\n\n```ts\nconst client = undici.extend({\n  throttle: { limit: 10, interval: 1000 }, // 10 requests per second\n});\n\n// These will be queued and executed at the specified rate\nawait Promise.all([client('https://api.com/1'), client('https://api.com/2')]);\n\n// Monitor the queue\nconsole.log(client.queueSize);\n```\n\n### Debugging\n\nLog equivalent `curl` commands for easier debugging.\n\n```ts\nawait undici('https://api.example.com', { debug: true });\n// Output: curl -X GET \"https://api.example.com\"\n```\n\n## 📚 Documentation\n\nFor all configuration options, please see [the API docs](https://www.jsdocs.io/package/undici-extra).\n\n## 🤝 Contributing\n\nWant to contribute? Awesome! To show your support is to star the project, or to raise issues on [GitHub](https://github.com/shahradelahi/undici-extra).\n\nThanks again for your support, it is much appreciated! 🙏\n\n## License\n\n[MIT](/LICENSE) © [Shahrad Elahi](https://github.com/shahradelahi) and [contributors](https://github.com/shahradelahi/undici-extra/graphs/contributors).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshahradelahi%2Fundici-extra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshahradelahi%2Fundici-extra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshahradelahi%2Fundici-extra/lists"}