{"_id":"@ahriknow/afetch","_rev":"6-ee2f0ef4f89bc6547198edffa64fe9e0","name":"@ahriknow/afetch","dist-tags":{"latest":"0.0.6"},"versions":{"0.0.1":{"name":"@ahriknow/afetch","version":"0.0.1","keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout"],"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","_id":"@ahriknow/afetch@0.0.1","maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"homepage":"https://github.com/ahriknow/afetch#readme","bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"dist":{"shasum":"6083c16ec73c92b1be762c94a42329fdac6aa52d","tarball":"https://registry.npmjs.org/@ahriknow/afetch/-/afetch-0.0.1.tgz","fileCount":44,"integrity":"sha512-ipdL/uM6xERIsQYZIJN1Y+fDKvTPHtPEZGYj3KI/gywTNQiy1CwPNox2KTOe2NIfa9Uk6/hFil0OOqSpfGUk6A==","signatures":[{"sig":"MEUCIQDDfDdu5TUnGCVjdYBn8YueoEgWs2wqpqRnJRUNakJMPgIgPmhCDCRoda/ETVWuweMe/STZ9geTojrmNe4AyHLi3/o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahriknow%2fafetch@0.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":121893},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"d68ddee31795fc5e28689665837c8f7e453c2cc3","scripts":{"lint":"eslint src/ --ext .ts","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","build":"tsc","format":"prettier --write \"src/**/*.ts\"","test:coverage":"node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"repository":{"url":"git+https://github.com/ahriknow/afetch.git","type":"git"},"_npmVersion":"10.8.2","description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.0","ts-node":"^10.9.2","prettier":"^3.2.0","@types/jest":"^29.5.0","@typescript-eslint/parser":"^7.0.0","@typescript/native-preview":"beta","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/afetch_0.0.1_1781588155171_0.2474517879432756","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@ahriknow/afetch","version":"0.0.2","keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout"],"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","_id":"@ahriknow/afetch@0.0.2","maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"homepage":"https://github.com/ahriknow/afetch#readme","bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"dist":{"shasum":"337466b6c62cebbf911ae2dcaaf4d5771dfebdd0","tarball":"https://registry.npmjs.org/@ahriknow/afetch/-/afetch-0.0.2.tgz","fileCount":52,"integrity":"sha512-kzjB0fI2DgawIhes2WtbfD+bwNsIEYrP46mBgzarX2dhR+u+klRw2LQ3YThsrYglj8ExOo7IV84XqKEKg2yTpw==","signatures":[{"sig":"MEUCIQCrfR2Jw2zDHgy4P7LR6SZz9cjIv+0JB83sUDeKeqMLSgIgUgQSbfIu9FG0E36ZVNwxG5oP6A4MZcP94SvZAojFHQs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahriknow%2fafetch@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":128153},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"b02007c261a5d7d9d1941a428c2f74ff4beac331","scripts":{"lint":"eslint src/ --ext .ts","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","build":"tsc","format":"prettier --write \"src/**/*.ts\"","test:coverage":"node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"repository":{"url":"git+https://github.com/ahriknow/afetch.git","type":"git"},"_npmVersion":"10.8.2","description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.0","ts-node":"^10.9.2","prettier":"^3.2.0","@types/jest":"^29.5.0","@typescript-eslint/parser":"^7.0.0","@typescript/native-preview":"beta","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/afetch_0.0.2_1781608039616_0.0857282838525455","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@ahriknow/afetch","version":"0.0.3","keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout"],"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","_id":"@ahriknow/afetch@0.0.3","maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"homepage":"https://github.com/ahriknow/afetch#readme","bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"dist":{"shasum":"b3795296f101113941be0964bb632c5f646c5eec","tarball":"https://registry.npmjs.org/@ahriknow/afetch/-/afetch-0.0.3.tgz","fileCount":52,"integrity":"sha512-EI9TavU37JXXnQRDmaVkFpYfMCUhgTes6J9eJCu5dwpuucxtgKbvnFcaUDzW8Z7en5o9GSSVz/EXoo0/zsSFyA==","signatures":[{"sig":"MEUCIQCqCSzfx5G/tLskcE7uOFqR0LRmQsvH6JXJsk/laqkj9wIgRnBZP9mUxR1ZCUTn4+DOCmaaN/LNQ/BaQ2RMUIxNfbQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahriknow%2fafetch@0.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":130555},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"5c1152e7e874c6ab497650d4cad18fb7f9bdc268","scripts":{"lint":"eslint src/ --ext .ts","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","build":"tsc","format":"prettier --write \"src/**/*.ts\"","test:coverage":"node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"repository":{"url":"git+https://github.com/ahriknow/afetch.git","type":"git"},"_npmVersion":"10.8.2","description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.0","ts-node":"^10.9.2","prettier":"^3.2.0","@types/jest":"^29.5.0","typescript-eslint":"^8.61.1","@typescript-eslint/parser":"^7.0.0","@typescript/native-preview":"beta","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/afetch_0.0.3_1781751214491_0.7926526268670087","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@ahriknow/afetch","version":"0.0.4","keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout"],"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","_id":"@ahriknow/afetch@0.0.4","maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"homepage":"https://github.com/ahriknow/afetch#readme","bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"dist":{"shasum":"7a2aa88b293d687e71a152b605bddce3da22b825","tarball":"https://registry.npmjs.org/@ahriknow/afetch/-/afetch-0.0.4.tgz","fileCount":52,"integrity":"sha512-Qt0GD1akK5esDdTgxDBMzXWvlOUSZjrEKxd2z8ETF0sDhFi7OfjadH+bqhvb+BaLZWDVaoz+37SRRYboJXr9Cw==","signatures":[{"sig":"MEQCICP1almCj2syUEjsziXFCc2EZNRGpDw7/3ZegnjBntwAAiBPXo82K0AVuz8C0iDfTFtNuq8LLhLDx835LuLVyY46gA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahriknow%2fafetch@0.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":134487},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"8c1dd614833d3975b368608ea4e7a0f06236d33f","scripts":{"lint":"eslint src/ --ext .ts","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","build":"tsc","format":"prettier --write \"src/**/*.ts\"","test:coverage":"node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"repository":{"url":"git+https://github.com/ahriknow/afetch.git","type":"git"},"_npmVersion":"10.8.2","description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.0","ts-node":"^10.9.2","prettier":"^3.2.0","@types/jest":"^29.5.0","typescript-eslint":"^8.61.1","@typescript-eslint/parser":"^7.0.0","@typescript/native-preview":"beta","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/afetch_0.0.4_1782114944069_0.9207993632799198","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"@ahriknow/afetch","version":"0.0.5","keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout","sse","server-sent-events","eventsource","ws","websocket","socket"],"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","_id":"@ahriknow/afetch@0.0.5","maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"homepage":"https://github.com/ahriknow/afetch#readme","bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"dist":{"shasum":"e860acd547ba5aa252b16e8e1adea02dd6340165","tarball":"https://registry.npmjs.org/@ahriknow/afetch/-/afetch-0.0.5.tgz","fileCount":120,"integrity":"sha512-EflC6ZxsuzUkSRqV93mWGjlhMoguipBBM8s4qTQ22KaFKvXeXuL4w9MzbP9X2tjdaUsG8uAfLDse3cIG7/JYzA==","signatures":[{"sig":"MEYCIQC2ZG3erqsLKcazfIKjAYA7feIQsl6s0ODlh+IfLZtvLQIhAKzfxFr1kMusNjh509EDGmmWOdq3l1iGYqClzM+tep9l","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahriknow%2fafetch@0.0.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":258970},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./ws":{"types":"./dist/ws/index.d.ts","import":"./dist/ws/index.js","default":"./dist/ws/index.js"},"./sse":{"types":"./dist/sse/index.d.ts","import":"./dist/sse/index.js","default":"./dist/sse/index.js"}},"gitHead":"2e6e9f993dd705776b01f09410dec26c532d8ba0","scripts":{"lint":"eslint src/","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","build":"tsc","format":"prettier --write \"src/**/*.ts\"","test:coverage":"node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"repository":{"url":"git+https://github.com/ahriknow/afetch.git","type":"git"},"_npmVersion":"11.13.0","description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.0","ts-node":"^10.9.2","prettier":"^3.2.0","@types/jest":"^29.5.0","typescript-eslint":"^8.61.1","@typescript-eslint/parser":"^7.0.0","@typescript/native-preview":"beta","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/afetch_0.0.5_1782262124934_0.927896769640784","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"name":"@ahriknow/afetch","version":"0.0.6","description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./sse":{"types":"./dist/sse/index.d.ts","import":"./dist/sse/index.js","default":"./dist/sse/index.js"},"./ws":{"types":"./dist/ws/index.d.ts","import":"./dist/ws/index.js","default":"./dist/ws/index.js"}},"scripts":{"build":"tsc","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","test:coverage":"node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage","lint":"eslint src/","format":"prettier --write \"src/**/*.ts\"","prepublishOnly":"npm run build"},"keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout","sse","server-sent-events","eventsource","ws","websocket","socket"],"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ahriknow/afetch.git"},"bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"homepage":"https://github.com/ahriknow/afetch#readme","sideEffects":false,"devDependencies":{"@types/jest":"^29.5.0","@typescript-eslint/eslint-plugin":"^7.0.0","@typescript-eslint/parser":"^7.0.0","@typescript/native-preview":"beta","eslint":"^8.57.0","jest":"^29.7.0","prettier":"^3.2.0","ts-jest":"^29.1.0","ts-node":"^10.9.2","typescript-eslint":"^8.61.1"},"engines":{"node":">=18.0.0"},"gitHead":"d0fb78bdb611b463e7171a79b394b5e276f94275","_id":"@ahriknow/afetch@0.0.6","_nodeVersion":"24.17.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-yc/RESRQwcKvVj8XrxKvzFUsvGLj0UYQC2rWDPfKuANjh/vvZ6J5NaVR/jWT9oBP5gymAAF1Zi+HaG964QrvhQ==","shasum":"fe86bc2c9e54d5b38123d13198c3de16278ae573","tarball":"https://registry.npmjs.org/@ahriknow/afetch/-/afetch-0.0.6.tgz","fileCount":120,"unpackedSize":259219,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahriknow%2fafetch@0.0.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICoWh2Ns8dhEq6+gMc3cfIErrGD1e5wh/2jbJky5p29rAiAafI03Vv9Wi7QxW6BpNr8tSMf4AjuiC8qROjaAzTu60A=="}]},"_npmUser":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"directories":{},"maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/afetch_0.0.6_1782893253484_0.7928576199918267"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-16T05:35:54.935Z","modified":"2026-07-01T08:07:33.923Z","0.0.1":"2026-06-16T05:35:55.336Z","0.0.2":"2026-06-16T11:07:19.732Z","0.0.3":"2026-06-18T02:53:34.653Z","0.0.4":"2026-06-22T07:55:44.212Z","0.0.5":"2026-06-24T00:48:45.080Z","0.0.6":"2026-07-01T08:07:33.633Z"},"bugs":{"url":"https://github.com/ahriknow/afetch/issues"},"author":{"name":"ahriknow","email":"ahriknow@ahriknow.com"},"license":"MIT","homepage":"https://github.com/ahriknow/afetch#readme","keywords":["fetch","http","request","client","api","typescript","async","await","plugin","retry","abort","timeout","sse","server-sent-events","eventsource","ws","websocket","socket"],"repository":{"type":"git","url":"git+https://github.com/ahriknow/afetch.git"},"description":"A lightweight, type-safe fetch API wrapper for modern JavaScript/TypeScript","maintainers":[{"name":"ahriknow","email":"ahriknow@ahriknow.com"}],"readme":"<div align=\"center\">\n\n# afetch\n\n**English** | [中文](./README_zh-CN.md)\n\nA lightweight, type-safe, plugin-based fetch API wrapper for modern JavaScript/TypeScript.\n\n[![npm version](https://img.shields.io/npm/v/@ahriknow/afetch.svg)](https://www.npmjs.com/package/@ahriknow/afetch)\n[![license](https://img.shields.io/npm/l/@ahriknow/afetch.svg)](./LICENSE)\n[![codecov](https://codecov.io/gh/ahriknow/afetch/branch/develop/graph/badge.svg?token=NDSDK60RUM)](https://codecov.io/gh/ahriknow/afetch)\n[![typescript](https://img.shields.io/badge/TypeScript-7.0-blue.svg)](https://www.typescriptlang.org/)\n\n</div>\n\n---\n\n## Features\n\n- 🚀 **Lightweight** — Zero dependencies, minimal bundle size\n- 🔒 **Type-safe** — Full TypeScript support with strict types\n- 🧩 **Plugin System** — Extensible via `beforeRequest`, `afterResponse`, `onError` hooks\n- 🔁 **Retry Plugin** — Automatic retry with exponential backoff, status matching, and custom hooks\n- 📡 **Event Bus Plugin** — Observe request lifecycle via events\n- 📨 **SSE Support** — Server-Sent Events client with plugin system and auto-reconnect (`@ahriknow/afetch/sse`)\n- 🔌 **WebSocket Support** — WebSocket client with plugin system, auto-reconnect, and request-sync (`@ahriknow/afetch/ws`)\n- ⏱️ **Timeout** — Request timeout with automatic abort\n- ❌ **Cancellation** — AbortController support + Task API for fine-grained control\n- 📊 **Progress** — Upload and download progress tracking\n- 🏗️ **Instances** — Create pre-configured instances for different APIs\n- 🔧 **Transforms** — Request and response data transformation\n- 🌐 **Universal** — Works in browsers (Chrome 42+, Firefox 39+, Safari 10.1+) and Node.js 18+\n\n## Installation\n\n```bash\nnpm install @ahriknow/afetch\n```\n\n## Quick Start\n\n```typescript\nimport { afetch } from '@ahriknow/afetch';\n\n// GET request\nconst { data } = await afetch.get<User[]>('/api/users');\n\n// POST request\nconst { data: user } = await afetch.post<User>('/api/users', {\n    name: 'John Doe',\n    email: 'john@example.com',\n});\n\n// With options\nconst { data: item } = await afetch.get<Item>('/api/items/1', {\n    headers: { Authorization: 'Bearer token' },\n    timeout: 5000,\n    params: { fields: 'name,email' },\n});\n```\n\n## Creating Instances\n\n```typescript\nimport { createInstance } from '@ahriknow/afetch';\n\nconst api = createInstance({\n    baseURL: 'https://api.example.com',\n    timeout: 10000,\n    headers: { 'Content-Type': 'application/json' },\n});\n\nconst { data: users } = await api.get<User[]>('/users');\nconst { data: user } = await api.post<User>('/users', { name: 'John' });\n```\n\n## Built-in Plugins\n\n### Retry Plugin\n\n```typescript\nimport { createRetryPlugin } from '@ahriknow/afetch';\n\nconst api = createInstance({ baseURL: 'https://api.example.com' });\n\n// Plugin-level defaults — all requests inherit these\napi.use(createRetryPlugin({\n    maxRetries: 3,\n    delay: 1000,\n    retryOn: [500, 502, 503, 504],\n}));\n\n// Uses plugin defaults (retries 3 times on 5xx errors)\nawait api.get('/api/data');\n\n// Override per-request\nawait api.get('/api/critical', {\n    meta: { retry: { maxRetries: 5, delay: 2000 } },\n});\n\n// Exponential backoff\napi.use(createRetryPlugin({\n    maxRetries: 5,\n    delay: (attempt) => Math.pow(2, attempt) * 1000,\n}));\n\n// Advanced: hook + call for token refresh on 401\napi.use(createRetryPlugin({\n    maxRetries: 3,\n    delay: 1000,\n    retryOn: [\n        500,\n        {\n            hook: async (error) => error.status === 401,\n            retryDelay: 0,\n            call: async () => {\n                const token = await refreshToken();\n                api.defaults.headers!['Authorization'] = `Bearer ${token}`;\n            },\n        },\n    ],\n}));\n\n// Custom condition function per-request\nawait api.get('/api/data', {\n    meta: {\n        retry: {\n            condition: (attempt, error) => error.status === 503 && attempt < 2,\n        },\n    },\n});\n```\n\n### Event Bus Plugin\n\n```typescript\nimport { createEventBusPlugin } from '@ahriknow/afetch';\n\nconst api = createInstance({ baseURL: 'https://api.example.com' });\nconst eventBus = createEventBusPlugin();\napi.use(eventBus);\n\n// Listen to lifecycle events\nconst unsub = eventBus.on('request', ({ config }) => {\n    console.log(`→ ${config.method} ${config.url}`);\n});\n\neventBus.on('response', ({ config, response }) => {\n    console.log(`← ${response.status} ${config.url}`);\n});\n\neventBus.on('error', ({ config, error }) => {\n    console.error(`✗ ${error.code} ${config.url}`);\n});\n\n// Unsubscribe\nunsub();\n\n// Remove all listeners for an event\neventBus.off('response');\n```\n\n### Queue Plugin\n\nControls concurrent request execution automatically. Just install the plugin and all requests are concurrency-limited:\n\n```typescript\nimport { createQueuePlugin } from '@ahriknow/afetch';\n\nconst queue = createQueuePlugin({ maxConcurrent: 3 });\napi.use(queue);\n\n// All requests are automatically queued — max 3 run at a time\nconst results = await Promise.all(\n    urls.map(url => api.get(url))\n);\n\nconsole.log('Running:', queue.pending);\nconsole.log('Waiting:', queue.queued);\nqueue.clear(); // reject all waiting\n```\n\n### Cache Plugin\n\nCaches GET responses automatically:\n\n```typescript\nimport { createCachePlugin } from '@ahriknow/afetch';\n\napi.use(createCachePlugin({\n    maxAge: 30_000,\n    maxSize: 50,\n    // Optional: per-request cache decision\n    shouldCache: (config, response) => {\n        if (response.status >= 400) return false;\n        if (config.url.startsWith('/users')) return { maxAge: 60_000 };\n        return true; // use default maxAge\n    },\n}));\n\n// First call — network request\nconst users1 = await api.get('/users');\n\n// Second call — served from cache (no network)\nconst users2 = await api.get('/users');\n\n// POST requests are never cached\nawait api.post('/users', { name: 'John' });\n```\n\n### Writing Custom Plugins\n\n```typescript\nimport type { AFetchPlugin } from '@ahriknow/afetch';\n\nconst loggerPlugin: AFetchPlugin = {\n    name: 'logger',\n    install(api) {\n        api.addHook('beforeRequest', ({ config }) => {\n            console.log(`[REQ] ${config.method} ${config.baseURL}${config.url}`);\n        });\n\n        api.addHook('afterResponse', ({ response }) => {\n            console.log(`[RES] ${response.status} ${response.statusText}`);\n        });\n\n        api.addHook('onError', ({ error }) => {\n            console.error(`[ERR] ${error.code}: ${error.message}`);\n        });\n    },\n};\n\napi.use(loggerPlugin);\n```\n\n### Plugin Lifecycle Hooks\n\n| Hook | When | Return |\n|------|------|--------|\n| `beforeRequest` | Before sending request | `AResponse` (cache hit) or `void` |\n| `afterResponse` | After receiving response | `AResponse` (replace) or `void` |\n| `onError` | On request error | `AResponse` (retry/replace) or `void` (propagate) |\n\nPlugins are installed once per instance — calling `use()` with the same plugin name is a no-op.\n\n## Documentation\n\n| Topic | Description |\n|-------|-------------|\n| [Error Handling](./docs/en/error-handling.md) | AFetchError, error types, and error handling patterns |\n| [Request Cancellation](./docs/en/cancellation.md) | Task API and AbortController |\n| [Transforms](./docs/en/transforms.md) | Request and response data transformation |\n| [TypeScript Support](./docs/en/typescript.md) | Type definitions and generic support |\n| [Configuration](./docs/en/configuration.md) | Instance and per-request configuration options |\n| [API Reference](./docs/en/api-reference.md) | Complete API reference |\n| [SSE (Server-Sent Events)](./docs/en/sse.md) | SSE client with plugin system and auto-reconnect |\n| [WebSocket](./docs/en/ws.md) | WebSocket client with plugin system, auto-reconnect, and request-sync |\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}