{"_id":"nexus-http","_rev":"68-078519d969c13741047f4664dbc1d3bb","name":"nexus-http","dist-tags":{"latest":"1.0.7"},"versions":{"1.0.1":{"name":"nexus-http","version":"1.0.1","keywords":["http","fetch","client","axios-alternative","request","caching","retry","streaming","deduplication"],"author":{"name":"Nitesh Ghosh"},"license":"MIT","_id":"nexus-http@1.0.1","maintainers":[{"name":"nit47","email":"workwithnites@gmail.com"}],"homepage":"https://github.com/NiteshCodes7/nexus-http#readme","bugs":{"url":"https://github.com/NiteshCodes7/nexus-http/issues"},"dist":{"shasum":"0fba04c5fef46322e302f331a2c2fb67f0c67204","tarball":"https://registry.npmjs.org/nexus-http/-/nexus-http-1.0.1.tgz","fileCount":9,"integrity":"sha512-N2lDvqCGUZIEFqDMXv9jxV4WcqcsSD+rbjkN//zFlt3B18uC6DhnN22cirDhvYuZFhFdPEHgDH9hOurScxSiaQ==","signatures":[{"sig":"MEQCIF3uZ69/s0WUKRQP7I9AGYMNj80fRleyyfyrkTXIof+5AiBeyGY6wWdpto7mB2GiSNehfrr5gVy99Wda6UxQNHQOVg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76199},"main":"src/index.js","types":"src/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js","require":"./src/index.js"}},"gitHead":"a56a0b190b0b32cc1aebb4bee924fca5da3dedbc","scripts":{"test":"node tests/index.test.js","build":"tsup src/index.js --format cjs,esm --dts --clean"},"_npmUser":{"name":"nit47","email":"workwithnites@gmail.com"},"repository":{"url":"git+https://github.com/NiteshCodes7/nexus-http.git","type":"git"},"_npmVersion":"11.6.2","description":"A powerful, feature-rich HTTP client with caching, retries, deduplication, streaming, and more.","directories":{},"_nodeVersion":"22.16.0","dependencies":{"typescript":"^6.0.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1"},"_npmOperationalInternal":{"tmp":"tmp/nexus-http_1.0.1_1777063674878_0.694676426471853","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"nexus-http","version":"1.0.4","keywords":["http","fetch","client","axios-alternative","request","caching","retry","streaming","deduplication"],"author":{"name":"Nitesh Ghosh"},"license":"MIT","_id":"nexus-http@1.0.4","maintainers":[{"name":"nit47","email":"workwithnites@gmail.com"}],"homepage":"https://github.com/NiteshCodes7/nexus-http#readme","bugs":{"url":"https://github.com/NiteshCodes7/nexus-http/issues"},"dist":{"shasum":"8d9779a77b9493f3913d8842c71cc2f4ae1d98b1","tarball":"https://registry.npmjs.org/nexus-http/-/nexus-http-1.0.4.tgz","fileCount":9,"integrity":"sha512-dU7NuG77waBcpt+DReeVJIOFBYXAW9+YIRiNX0OJMIFCFGSIUDn29mkyGMOrEX8zPOLT/gQjg8QQwsutwSiEkA==","signatures":[{"sig":"MEUCIDA9qDQxVa1f40Zo4j/SHUc5mFab+wIIo5PTWTcloYAcAiEA0DBcAFEDl3QaYFVxXvapJIFaG6CHCw6E3OWZvHHTU2g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92194},"main":"src/index.js","types":"src/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js","require":"./src/index.js"}},"gitHead":"20b7710f60b1bdbd189a9f19d72dd138a1fb05ea","scripts":{"test":"node tests/index.test.js","build":"tsup src/index.js --format cjs,esm --dts --clean"},"_npmUser":{"name":"nit47","email":"workwithnites@gmail.com"},"repository":{"url":"git+https://github.com/NiteshCodes7/nexus-http.git","type":"git"},"_npmVersion":"11.6.2","description":"A powerful, feature-rich HTTP client with caching, retries, deduplication, streaming, and more.","directories":{},"_nodeVersion":"22.16.0","dependencies":{"typescript":"^6.0.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1"},"_npmOperationalInternal":{"tmp":"tmp/nexus-http_1.0.4_1777147545136_0.7276059065113383","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"nexus-http","version":"1.0.5","keywords":["http","fetch","client","axios-alternative","request","caching","retry","streaming","deduplication"],"author":{"name":"Nitesh Ghosh"},"license":"MIT","_id":"nexus-http@1.0.5","maintainers":[{"name":"nit47","email":"workwithnites@gmail.com"}],"homepage":"https://github.com/NiteshCodes7/nexus-http#readme","bugs":{"url":"https://github.com/NiteshCodes7/nexus-http/issues"},"dist":{"shasum":"552f15fe5a0807c753b05487b441a8ce961cba87","tarball":"https://registry.npmjs.org/nexus-http/-/nexus-http-1.0.5.tgz","fileCount":9,"integrity":"sha512-cmUEhtBBWQ7W291cc9tq4qFEasDLUyuwGQhJFgvkCjkydq1Nrt+BLhxV2wBz3hDa7X9FsPxgettjT/k04B+tvQ==","signatures":[{"sig":"MEUCIH4b8xSVzDMiKNu22wH+xfb/EyAnP3yU0YoX/fpIge5mAiEAgjsGp66c9BV6Iehp9x7QAu3GQbQ6B8C7rsWPWvc0y7E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92170},"main":"src/index.js","types":"src/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js","require":"./src/index.js"}},"gitHead":"7b30e4a84ae0656e2f0dd1c9786ef4a91c1f96c7","scripts":{"test":"node tests/index.test.js","build":"tsup src/index.js --format cjs,esm --dts --clean"},"_npmUser":{"name":"nit47","email":"workwithnites@gmail.com"},"repository":{"url":"git+https://github.com/NiteshCodes7/nexus-http.git","type":"git"},"_npmVersion":"11.6.2","description":"A powerful, feature-rich HTTP client with caching, retries, deduplication, streaming, and more.","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/nexus-http_1.0.5_1777148404211_0.05140701518631707","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"nexus-http","version":"1.0.6","keywords":["http","fetch","client","axios-alternative","request","caching","retry","streaming","deduplication"],"author":{"name":"Nitesh Ghosh"},"license":"MIT","_id":"nexus-http@1.0.6","maintainers":[{"name":"nit47","email":"workwithnites@gmail.com"}],"homepage":"https://github.com/NiteshCodes7/nexus-http#readme","bugs":{"url":"https://github.com/NiteshCodes7/nexus-http/issues"},"dist":{"shasum":"52fe9b5c17a2dbd8b459c07c76662880a17f66b5","tarball":"https://registry.npmjs.org/nexus-http/-/nexus-http-1.0.6.tgz","fileCount":6,"integrity":"sha512-80sreg440vlR9iDOc0UbDz9y6ZMHSOHbYEDJYyBphX1L2iGgmtRZJTq/7oJBck0Wr4Mjoyvz5A4Ydubvp2ncoQ==","signatures":[{"sig":"MEUCICNUn82d1whGMKyCTDy4ViddPIKmorqgnFFZJJCG122KAiEAmabHwD2eyIzZQgnN/x4cNnJ8UsUqqJNxKPNDcnmvync=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61125},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"bb598092fb08b23f5a361c4a646fd0692059408e","scripts":{"test":"node tests/index.test.js","build":"tsup src/index.js --format cjs,esm --dts --clean"},"_npmUser":{"name":"nit47","email":"workwithnites@gmail.com"},"repository":{"url":"git+https://github.com/NiteshCodes7/nexus-http.git","type":"git"},"_npmVersion":"11.6.2","description":"A powerful, feature-rich HTTP client with caching, retries, deduplication, streaming, and more.","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/nexus-http_1.0.6_1777150692703_0.3807717062757323","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"nexus-http","version":"1.0.7","description":"A powerful, feature-rich HTTP client with caching, retries, deduplication, streaming, and more.","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"tsup src/index.js --format cjs,esm --dts --clean","test":"node tests/index.test.js"},"keywords":["http","fetch","client","axios-alternative","request","caching","retry","streaming","deduplication"],"author":{"name":"Nitesh Ghosh"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/NiteshCodes7/nexus-http.git"},"engines":{"node":">=18.0.0"},"devDependencies":{"tsup":"^8.5.1","typescript":"^6.0.3"},"gitHead":"dddf02e7323d35a824d4e09bedd79f91c3642baf","_id":"nexus-http@1.0.7","bugs":{"url":"https://github.com/NiteshCodes7/nexus-http/issues"},"homepage":"https://github.com/NiteshCodes7/nexus-http#readme","_nodeVersion":"22.16.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-Ag6vQdGSkTG/ESNcosd7Dl/Q95dZLtix8E0oO8nzoaSTQ7n0mhnKw7og1HOSY3jdTl+VwgxfkBViBSEThVQKBw==","shasum":"c592ace5d61df52ebad9e591561f608857f4c83d","tarball":"https://registry.npmjs.org/nexus-http/-/nexus-http-1.0.7.tgz","fileCount":6,"unpackedSize":60286,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC17/z4wghQ/OrIMnSsM67SqE1fkNrkPji2cKHVcB4/bwIhAOdKl3lFj643eElVHnqs2ohJmf/ci515U/GRcNRZaf1L"}]},"_npmUser":{"name":"nit47","email":"workwithnites@gmail.com"},"directories":{},"maintainers":[{"name":"nit47","email":"workwithnites@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nexus-http_1.0.7_1777152067684_0.15660012196422857"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-24T20:47:54.772Z","modified":"2026-04-25T21:21:07.972Z","1.0.0-pre1":"2021-08-30T17:00:56.830Z","1.0.0-pre2":"2021-08-30T17:29:49.311Z","1.0.0-pre3":"2021-08-30T17:37:56.433Z","1.0.0":"2021-09-05T10:31:45.297Z","1.1.0-pre1":"2021-09-05T16:22:19.557Z","1.1.0-pre2":"2021-09-05T16:59:23.802Z","1.1.0-pre3":"2021-09-05T17:10:31.433Z","1.1.0-pre4":"2021-09-05T17:23:44.659Z","1.1.0-rc1":"2021-09-05T17:39:40.491Z","1.1.0-rc2":"2021-09-08T21:25:27.863Z","1.1.0":"2021-09-09T11:17:50.992Z","1.1.1":"2021-09-09T11:31:32.493Z","1.1.2":"2021-09-09T15:01:04.747Z","1.1.3":"2021-09-09T16:12:44.054Z","1.2.0":"2021-09-09T19:47:13.911Z","1.3.0":"2021-09-11T08:23:56.638Z","1.3.1":"2021-11-01T15:45:44.694Z","2.0.0":"2021-12-12T18:39:09.266Z","2.0.1":"2021-12-20T14:47:21.482Z","2.0.2":"2021-12-20T15:29:45.373Z","2.0.3":"2021-12-20T19:21:03.700Z","2.1.0":"2021-12-22T14:14:55.599Z","2.1.1":"2021-12-22T14:41:31.403Z","2.1.2":"2021-12-23T17:50:59.867Z","2.1.3":"2021-12-29T21:38:57.164Z","2.2.0":"2022-01-01T22:09:10.987Z","2.2.1":"2022-01-02T13:34:57.077Z","2.2.2":"2022-01-23T20:17:41.469Z","2.3.0":"2022-02-04T23:17:14.078Z","2.4.0":"2022-06-06T12:02:33.332Z","2.4.1":"2022-06-19T18:34:43.965Z","1.0.1":"2026-04-24T20:47:55.064Z","1.0.4":"2026-04-25T20:05:45.266Z","1.0.5":"2026-04-25T20:20:04.338Z","1.0.6":"2026-04-25T20:58:12.840Z","1.0.7":"2026-04-25T21:21:07.862Z"},"bugs":{"url":"https://github.com/NiteshCodes7/nexus-http/issues"},"author":{"name":"Nitesh Ghosh"},"license":"MIT","homepage":"https://github.com/NiteshCodes7/nexus-http#readme","keywords":["http","fetch","client","axios-alternative","request","caching","retry","streaming","deduplication"],"repository":{"type":"git","url":"git+https://github.com/NiteshCodes7/nexus-http.git"},"description":"A powerful, feature-rich HTTP client with caching, retries, deduplication, streaming, and more.","maintainers":[{"name":"nit47","email":"workwithnites@gmail.com"}],"readme":"# nexus-http\r\n\r\n[![npm version](https://img.shields.io/npm/v/nexus-http.svg)](https://www.npmjs.com/package/nexus-http)\r\n[![npm downloads](https://img.shields.io/npm/dm/nexus-http.svg)](https://www.npmjs.com/package/nexus-http)\r\n[![bundle size](https://img.shields.io/bundlephobia/minzip/nexus-http)](https://bundlephobia.com/package/nexus-http)\r\n[![license](https://img.shields.io/npm/l/nexus-http.svg)](https://github.com/yourusername/nexus-http/blob/main/LICENSE)\r\n\r\n> A powerful, zero-dependency HTTP client with built-in caching, retries, deduplication, streaming, upload progress, offline support, metrics, middleware, and plugins — for both Node.js and the browser.\r\n\r\n---\r\n\r\n## Table of contents\r\n\r\n- [Installation](#installation)\r\n- [Quick start](#quick-start)\r\n- [CommonJS vs ESM](#commonjs-vs-esm)\r\n- [Creating an instance](#creating-an-instance)\r\n- [HTTP methods](#http-methods)\r\n- [Request config](#request-config)\r\n- [Response object](#response-object)\r\n- [Caching](#caching)\r\n- [Auto retry](#auto-retry)\r\n- [Request deduplication](#request-deduplication)\r\n- [Concurrency control](#concurrency-control)\r\n- [Offline support](#offline-support)\r\n- [Streaming](#streaming)\r\n- [File upload with progress](#file-upload-with-progress)\r\n- [Interceptors](#interceptors)\r\n- [Middleware](#middleware)\r\n- [Plugins](#plugins)\r\n- [Metrics](#metrics)\r\n- [Parallel requests](#parallel-requests)\r\n- [TypeScript](#typescript)\r\n- [vs Axios](#vs-axios)\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\n# npm\r\nnpm install nexus-http\r\n\r\n# yarn\r\nyarn add nexus-http\r\n\r\n# pnpm\r\npnpm add nexus-http\r\n```\r\n\r\n**Requirements:** Node.js 18+ or any modern browser. Zero dependencies.\r\n\r\n---\r\n\r\n## Quick start\r\n\r\n### CommonJS\r\n\r\n```js\r\nconst nexus = require('nexus-http');\r\n\r\nconst { data } = await nexus.get('https://api.example.com/users');\r\nconsole.log(data);\r\n```\r\n\r\n### ESM\r\n\r\n```js\r\nimport nexus from 'nexus-http';\r\n\r\nconst { data } = await nexus.get('https://api.example.com/users');\r\nconsole.log(data);\r\n```\r\n\r\n---\r\n\r\n## CommonJS vs ESM\r\n\r\nnexus-http supports both module systems out of the box.\r\n\r\n### CommonJS (Node.js require)\r\n\r\n```js\r\n// default instance\r\nconst nexus = require('nexus-http');\r\n\r\n// named exports\r\nconst { NexusHTTP, NexusError, create, LoggerPlugin, AuthPlugin, CachePlugin } = require('nexus-http');\r\n```\r\n\r\n### ESM (import)\r\n\r\n```js\r\n// default instance\r\nimport nexus from 'nexus-http';\r\n\r\n// named exports\r\nimport { NexusHTTP, NexusError, create, LoggerPlugin, AuthPlugin, CachePlugin } from 'nexus-http';\r\n\r\n// mix default and named\r\nimport nexus, { create, NexusError } from 'nexus-http';\r\n```\r\n\r\n### ESM in the browser via CDN\r\n\r\n```html\r\n<script type=\"module\">\r\n  import nexus from 'https://cdn.jsdelivr.net/npm/nexus-http/dist/index.mjs';\r\n\r\n  const { data } = await nexus.get('https://api.example.com/users');\r\n  console.log(data);\r\n</script>\r\n```\r\n\r\n---\r\n\r\n## Creating an instance\r\n\r\nThe default export is a ready-to-use instance. For most apps, create your own instance with `create()` so you can set a base URL, default headers, and other options once.\r\n\r\n### CommonJS\r\n\r\n```js\r\nconst { create } = require('nexus-http');\r\n\r\nconst api = create({\r\n  baseURL: 'https://api.example.com',\r\n  timeout: 5000,\r\n  headers: { 'X-App-Version': '1.0.0' },\r\n  maxRetries: 3,\r\n  maxConcurrent: 10,\r\n  cache: false,\r\n  cacheTTL: 60000\r\n});\r\n```\r\n\r\n### ESM\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({\r\n  baseURL: 'https://api.example.com',\r\n  timeout: 5000,\r\n  headers: { 'X-App-Version': '1.0.0' },\r\n  maxRetries: 3,\r\n  maxConcurrent: 10,\r\n  cache: false,\r\n  cacheTTL: 60000\r\n});\r\n```\r\n\r\n### Config options\r\n\r\n| Option | Type | Default | Description |\r\n|---|---|---|---|\r\n| `baseURL` | `string` | `''` | Root URL prepended to every request |\r\n| `timeout` | `number` | `10000` | Request timeout in milliseconds |\r\n| `headers` | `object` | `{ 'Content-Type': 'application/json' }` | Default headers sent with every request |\r\n| `maxRetries` | `number` | `3` | Max retry attempts on failure |\r\n| `maxConcurrent` | `number` | `10` | Max simultaneous requests |\r\n| `cache` | `boolean` | `false` | Enable response caching globally |\r\n| `cacheTTL` | `number` | `60000` | Cache time-to-live in milliseconds |\r\n\r\n---\r\n\r\n## HTTP methods\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nconst { data } = await api.get('/users');\r\nconst { data } = await api.post('/users', { name: 'Alice' });\r\nconst { data } = await api.put('/users/1', { name: 'Alice Updated' });\r\nconst { data } = await api.patch('/users/1', { active: false });\r\nconst { data } = await api.delete('/users/1');\r\nconst { headers } = await api.head('/users');\r\nconst { data } = await api.options('/users');\r\n```\r\n\r\n---\r\n\r\n## Request config\r\n\r\nEvery method accepts an optional config object as the last argument.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nconst { data } = await api.get('/users', {\r\n  // query string — appended to URL as ?page=1&limit=10\r\n  params: { page: 1, limit: 10 },\r\n\r\n  // per-request headers — merged with instance headers\r\n  headers: { 'X-Request-Source': 'dashboard' },\r\n\r\n  // override instance timeout for this request only\r\n  timeout: 3000,\r\n\r\n  // override retry count for this request only\r\n  retries: 1,\r\n\r\n  // which status codes to retry on\r\n  retryOn: [429, 503],\r\n\r\n  // cache this request for 30 seconds\r\n  cache: true,\r\n  cacheTTL: 30000,\r\n\r\n  // disable deduplication for this request\r\n  dedupe: false\r\n});\r\n```\r\n\r\n---\r\n\r\n## Response object\r\n\r\nEvery request resolves to a consistent response object.\r\n\r\n```js\r\nimport nexus from 'nexus-http';\r\n\r\nconst response = await nexus.get('https://api.example.com/users');\r\n\r\nresponse.data        // parsed body — JS object, string, or Blob\r\nresponse.status      // HTTP status code — 200, 201, 404 etc\r\nresponse.statusText  // status text — 'OK', 'Not Found' etc\r\nresponse.headers     // response headers as a plain object\r\nresponse.duration    // how long the request took in ms\r\nresponse.url         // full URL that was requested\r\nresponse.fromCache   // true if this came from cache, false if from network\r\n```\r\n\r\n---\r\n\r\n## Caching\r\n\r\nCache GET responses so repeated calls return instantly without hitting the network.\r\n\r\n### Enable globally\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({\r\n  baseURL: 'https://api.example.com',\r\n  cache: true,\r\n  cacheTTL: 30000  // 30 seconds\r\n});\r\n\r\nawait api.get('/products');  // network request\r\nawait api.get('/products');  // instant cache hit ✅\r\n```\r\n\r\n### Enable per request\r\n\r\n```js\r\nconst { data } = await api.get('/products', {\r\n  cache: true,\r\n  cacheTTL: 10000  // only cache this one for 10 seconds\r\n});\r\n```\r\n\r\n### Clear cache\r\n\r\n```js\r\n// clear only /products entries\r\napi.clearCache('/products');\r\n\r\n// clear everything\r\napi.clearCache();\r\n```\r\n\r\n### Via plugin\r\n\r\n```js\r\nimport { create, CachePlugin } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\napi.use(CachePlugin({ ttl: 30000 }));\r\n```\r\n\r\n---\r\n\r\n## Auto retry\r\n\r\nAutomatically retries failed requests with exponential backoff — 1s → 2s → 4s.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({\r\n  baseURL: 'https://api.example.com',\r\n  maxRetries: 3\r\n});\r\n\r\n// retries automatically on 429 and 503 by default\r\nawait api.get('/unstable-endpoint');\r\n```\r\n\r\n### Custom status codes\r\n\r\n```js\r\nconst { data } = await api.get('/users', {\r\n  retries: 5,\r\n  retryOn: [500, 502, 503]\r\n});\r\n```\r\n\r\nNetwork errors (DNS failure, connection reset, no internet) are also retried automatically.\r\n\r\n### Disable retries\r\n\r\n```js\r\n// no retries for this request\r\nawait api.get('/users', { retries: 0 });\r\n```\r\n\r\n---\r\n\r\n## Request deduplication\r\n\r\nWhen the same request fires multiple times simultaneously, only one network call is made. All callers receive the same response.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\n// three components all fetch users at the same time\r\nconst [r1, r2, r3] = await Promise.all([\r\n  api.get('/users'),\r\n  api.get('/users'),\r\n  api.get('/users')\r\n]);\r\n\r\n// only ONE network request was made\r\n// all three got the same result ✅\r\n```\r\n\r\nDisable per request:\r\n\r\n```js\r\nawait api.get('/users', { dedupe: false });\r\n```\r\n\r\n---\r\n\r\n## Concurrency control\r\n\r\nLimits simultaneous requests. Extras wait in a queue and run as slots free up.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({\r\n  baseURL: 'https://api.example.com',\r\n  maxConcurrent: 3  // max 3 at once\r\n});\r\n\r\n// fire 10 at once — first 3 run, rest queue\r\nconst results = await api.all(\r\n  Array.from({ length: 10 }, (_, i) => api.get(`/items/${i}`))\r\n);\r\n```\r\n\r\n---\r\n\r\n## Offline support\r\n\r\nRequests made while offline are queued and automatically sent when the connection restores. Browser only.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\n// device goes offline here\r\nconst { data } = await api.get('/users');\r\n// ← caller is frozen here, not dropped\r\n\r\n// device comes back online\r\n// request fires automatically\r\n// caller gets the response ✅\r\nconsole.log(data);\r\n```\r\n\r\n---\r\n\r\n## Streaming\r\n\r\nRead response data chunk by chunk as it arrives. Perfect for AI text generation, live logs, and large file downloads.\r\n\r\n### ESM\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\n// stream a GET endpoint\r\nawait api.stream('/logs', (chunk) => {\r\n  process.stdout.write(chunk);\r\n});\r\n\r\n// stream a POST — AI generation example\r\nawait api.stream('/ai/generate', (chunk) => {\r\n  document.getElementById('output').innerHTML += chunk;\r\n}, {\r\n  method: 'POST',\r\n  data: { prompt: 'explain javascript closures' }\r\n});\r\n```\r\n\r\n### CommonJS\r\n\r\n```js\r\nconst { create } = require('nexus-http');\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nawait api.stream('/ai/chat', (chunk) => {\r\n  process.stdout.write(chunk);\r\n}, {\r\n  method: 'POST',\r\n  data: { message: 'hello' }\r\n});\r\n```\r\n\r\n---\r\n\r\n## File upload with progress\r\n\r\nUpload files with real-time percentage progress.\r\n\r\n### ESM\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nconst formData = new FormData();\r\nformData.append('avatar', fileInput.files[0]);\r\n\r\nconst { data } = await api.upload(\r\n  '/upload/avatar',\r\n  formData,\r\n  (percent) => {\r\n    progressBar.style.width = `${percent}%`;\r\n    console.log(`${percent}% uploaded`);\r\n  }\r\n);\r\n\r\nconsole.log(data.url);  // URL of uploaded file\r\n```\r\n\r\n### CommonJS\r\n\r\n```js\r\nconst { create } = require('nexus-http');\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nconst formData = new FormData();\r\nformData.append('file', fileBuffer, 'report.pdf');\r\n\r\nawait api.upload('/files', formData, (percent) => {\r\n  console.log(percent + '%');\r\n});\r\n```\r\n\r\nThe progress callback is optional:\r\n\r\n```js\r\n// upload without tracking progress\r\nawait api.upload('/upload', formData);\r\n```\r\n\r\n---\r\n\r\n## Interceptors\r\n\r\nModify every request before it goes out and every response before it comes back.\r\n\r\n### Request interceptor\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\n// add auth header to every request\r\napi.addRequestInterceptor((config) => {\r\n  config.headers['Authorization'] = `Bearer ${getToken()}`;\r\n  return config;\r\n});\r\n\r\n// async interceptor — fetch a fresh token each time\r\napi.addRequestInterceptor(async (config) => {\r\n  const token = await refreshTokenIfExpired();\r\n  config.headers['Authorization'] = `Bearer ${token}`;\r\n  return config;\r\n});\r\n```\r\n\r\n### Response interceptor\r\n\r\n```js\r\n// unwrap nested API response\r\napi.addResponseInterceptor((response) => {\r\n  response.data = response.data.result;\r\n  return response;\r\n});\r\n\r\n// redirect on unauthorized\r\napi.addResponseInterceptor((response) => {\r\n  if (response.status === 401) window.location = '/login';\r\n  return response;\r\n});\r\n```\r\n\r\n### Chaining\r\n\r\n```js\r\napi\r\n  .addRequestInterceptor(addAuth)\r\n  .addRequestInterceptor(addCorrelationId)\r\n  .addResponseInterceptor(logResponse)\r\n  .addResponseInterceptor(unwrapData);\r\n```\r\n\r\n---\r\n\r\n## Middleware\r\n\r\nMiddleware wraps the entire request lifecycle — you get access to both the request config AND the response in a single function. More powerful than interceptors for complex logic.\r\n\r\n### Basic\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\napi.use(async (ctx, next) => {\r\n  // before — ctx.config is the request\r\n  console.log(`→ ${ctx.config.method} ${ctx.config.url}`);\r\n\r\n  await next();  // ← HTTP request happens here\r\n\r\n  // after — ctx.response is the response\r\n  console.log(`← ${ctx.response.status} in ${ctx.response.duration}ms`);\r\n});\r\n```\r\n\r\n### Timing middleware\r\n\r\n```js\r\napi.use(async (ctx, next) => {\r\n  const start = Date.now();\r\n  await next();\r\n  ctx.response.totalTime = Date.now() - start;\r\n});\r\n```\r\n\r\n### Auth retry middleware\r\n\r\n```js\r\n// detect 401, refresh token, retry automatically\r\napi.use(async (ctx, next) => {\r\n  await next();\r\n\r\n  if (ctx.response.status === 401) {\r\n    const newToken = await refreshToken();\r\n    ctx.config.headers['Authorization'] = `Bearer ${newToken}`;\r\n    await next();  // retry with fresh token\r\n  }\r\n});\r\n```\r\n\r\n### Request blocker\r\n\r\n```js\r\n// block requests before they hit the network\r\napi.use(async (ctx, next) => {\r\n  if (!isLoggedIn()) {\r\n    // set response manually — no network call made\r\n    ctx.response = { status: 401, data: { error: 'Unauthorized' } };\r\n    return;\r\n  }\r\n  await next();\r\n});\r\n```\r\n\r\n### Middleware vs interceptors\r\n\r\n| | Interceptor | Middleware |\r\n|---|---|---|\r\n| Sees request config | ✅ | ✅ |\r\n| Sees response | ✅ (separate function) | ✅ (same function) |\r\n| Can compare request + response | ❌ | ✅ |\r\n| Can block request | ❌ | ✅ |\r\n| Can retry request | ❌ | ✅ |\r\n| Best for | header injection, data transform | logging, auth retry, blocking |\r\n\r\n---\r\n\r\n## Plugins\r\n\r\nPlugins bundle related functionality into a single installable unit.\r\n\r\n### Built-in plugins\r\n\r\n#### LoggerPlugin\r\n\r\nLogs every request and response automatically.\r\n\r\n```js\r\nimport { create, LoggerPlugin } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\napi.use(LoggerPlugin);\r\n\r\n// [NexusHTTP] → GET /users\r\n// [NexusHTTP] ← 200 https://api.example.com/users (143ms)\r\n```\r\n\r\n#### AuthPlugin\r\n\r\nInjects a Bearer token into every request. Accepts a string or an async function.\r\n\r\n```js\r\nimport { create, AuthPlugin } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\n// static token\r\napi.use(AuthPlugin('my-token'));\r\n\r\n// dynamic — called before every request\r\napi.use(AuthPlugin(() => localStorage.getItem('token')));\r\n\r\n// async — await is supported\r\napi.use(AuthPlugin(async () => {\r\n  const { token } = await getSession();\r\n  return token;\r\n}));\r\n```\r\n\r\n#### CachePlugin\r\n\r\nEnables caching for all GET requests with a configurable TTL.\r\n\r\n```js\r\nimport { create, CachePlugin } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\napi.use(CachePlugin({ ttl: 60000 }));  // cache for 1 minute\r\n```\r\n\r\n### Combining plugins\r\n\r\n```js\r\nimport { create, LoggerPlugin, AuthPlugin, CachePlugin } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\napi\r\n  .use(LoggerPlugin)\r\n  .use(AuthPlugin(() => getToken()))\r\n  .use(CachePlugin({ ttl: 30000 }));\r\n```\r\n\r\n### Writing your own plugin\r\n\r\nA plugin is any object with an `install(client)` method.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst ErrorReportingPlugin = {\r\n  install(client) {\r\n    client.addResponseInterceptor((response) => {\r\n      if (response.status >= 500) {\r\n        sendToErrorTracker({\r\n          url: response.url,\r\n          status: response.status,\r\n          duration: response.duration\r\n        });\r\n      }\r\n      return response;\r\n    });\r\n  }\r\n};\r\n\r\n// factory plugin — accepts configuration\r\nconst RateLimitPlugin = (requestsPerSecond = 10) => ({\r\n  install(client) {\r\n    let count = 0;\r\n    setInterval(() => { count = 0; }, 1000);\r\n\r\n    client.use(async (ctx, next) => {\r\n      if (count >= requestsPerSecond) {\r\n        ctx.response = { status: 429, data: { error: 'Rate limit exceeded' } };\r\n        return;\r\n      }\r\n      count++;\r\n      await next();\r\n    });\r\n  }\r\n});\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\napi.use(ErrorReportingPlugin);\r\napi.use(RateLimitPlugin(5));  // max 5 requests per second\r\n```\r\n\r\n---\r\n\r\n## Metrics\r\n\r\nTrack every request — response times, status codes, and full history.\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nawait api.get('/users');\r\nawait api.get('/posts');\r\nawait api.post('/users', { name: 'Alice' });\r\nawait api.get('/notfound');\r\n\r\nconst report = api.getMetrics();\r\n\r\nconsole.log(report.total);      // 4\r\nconsole.log(report.avgTime);    // 143  (ms)\r\nconsole.log(report.byStatus);   // { 200: 2, 201: 1, 404: 1 }\r\nconsole.log(report.history);    // full array of all 4 requests\r\n\r\n// reset\r\napi.clearMetrics();\r\n```\r\n\r\n### History entry\r\n\r\n```js\r\nreport.history[0] = {\r\n  url: 'https://api.example.com/users',\r\n  method: 'GET',\r\n  status: 200,\r\n  duration: 143\r\n}\r\n```\r\n\r\n---\r\n\r\n## Parallel requests\r\n\r\n### all() — run simultaneously, wait for all\r\n\r\n```js\r\nimport { create } from 'nexus-http';\r\n\r\nconst api = create({ baseURL: 'https://api.example.com' });\r\n\r\nconst [users, posts, comments] = await api.all([\r\n  api.get('/users'),\r\n  api.get('/posts'),\r\n  api.get('/comments')\r\n]);\r\n// all three ran at the same time\r\n// resolves when the LAST one finishes\r\n```\r\n\r\n### race() — run simultaneously, take the fastest\r\n\r\n```js\r\nconst { data } = await api.race([\r\n  api.get('/users?source=primary'),\r\n  api.get('/users?source=replica')\r\n]);\r\n// resolves when the FIRST one finishes\r\n```\r\n\r\n---\r\n\r\n## TypeScript\r\n\r\nFull TypeScript support is built in. No `@types` package needed.\r\n\r\n```ts\r\nimport { create, NexusResponse, NexusError, NexusConfig } from 'nexus-http';\r\n\r\n// typed config\r\nconst config: NexusConfig = {\r\n  baseURL: 'https://api.example.com',\r\n  timeout: 5000\r\n};\r\n\r\nconst api = create(config);\r\n\r\n// typed response\r\ninterface User {\r\n  id: number;\r\n  name: string;\r\n  email: string;\r\n}\r\n\r\nconst { data } = await api.get<User>('/users/1');\r\ndata.name;   // ✅ string\r\ndata.email;  // ✅ string\r\n\r\n// typed arrays\r\nconst { data: users } = await api.get<User[]>('/users');\r\nusers[0].name;  // ✅ string\r\n\r\n// typed error handling\r\ntry {\r\n  await api.delete('/users/999');\r\n} catch (e) {\r\n  if (e instanceof NexusError) {\r\n    e.status;    // number | null\r\n    e.response;  // NexusResponse | null\r\n    e.config;    // RequestConfig | null\r\n    e.message;   // string\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n## vs Axios\r\n\r\n| Feature | nexus-http | axios |\r\n|---|---|---|\r\n| Built-in caching | ✅ | ❌ |\r\n| Auto retry + backoff | ✅ built-in | ❌ plugin needed |\r\n| Request deduplication | ✅ | ❌ |\r\n| Concurrency limiting | ✅ | ❌ |\r\n| Offline request queue | ✅ | ❌ |\r\n| SSE / Streaming | ✅ | ⚠️ limited |\r\n| Upload with progress | ✅ | ✅ |\r\n| Middleware pipeline | ✅ | ⚠️ interceptors only |\r\n| Request metrics | ✅ | ❌ |\r\n| Plugin system | ✅ | ⚠️ basic |\r\n| ESM support | ✅ | ✅ |\r\n| TypeScript | ✅ built-in | ✅ via @types |\r\n| Bundle size | ~3kb | ~14kb |\r\n| Zero dependencies | ✅ | ✅ |\r\n| Node.js 18+ | ✅ | ✅ |\r\n| Browser | ✅ | ✅ |\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT © [Your Name](https://github.com/yourusername)\r\n\r\n---\r\n\r\n## Contributing\r\n\r\nPull requests are welcome. For major changes please open an issue first.\r\n\r\n```bash\r\ngit clone https://github.com/NiteshCodes7/nexus-http\r\ncd nexus-http\r\n\r\n# no install needed — zero dependencies\r\n\r\n# run tests\r\nnode tests/index.test.js\r\n```","readmeFilename":"Readme.md"}