{"_id":"q-api","_rev":"2-9fa64d600f0c4c4ea0b8beebbac9e591","name":"q-api","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"q-api","version":"1.0.0","keywords":["api-client","typescript","fetch","interceptors","retry","abort","lightweight"],"author":{"name":"Raja Dubey"},"license":"MIT","_id":"q-api@1.0.0","maintainers":[{"name":"rajadubey","email":"rajadubey1997@gmail.com"}],"dist":{"shasum":"3aabe3b9329aa8b5ebe57962a935e42c2bb29c02","tarball":"https://registry.npmjs.org/q-api/-/q-api-1.0.0.tgz","fileCount":8,"integrity":"sha512-gB00Wgq/IS1gw/PXGED5ZOiQEm8C7EFb0X0+np0A9X7Dn/TQ5Z/o04NtXrBaHYIU+Tc+BKb5HQu7kQpC9cbcMw==","signatures":[{"sig":"MEQCICAgQMcHrhSyXKQzmxQJnBsx8hONvhmdP3oeSFPheMLdAiBfQw72PZhEzfPaSaZohCN58LuvElrJ1oFB+QNphgjIAQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38764},"main":"dist/index.js","_from":"file:q-api-1.0.0.tgz","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=24"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"dev":"tsup src/index.ts --watch","lint":"biome check .","test":"vitest run","build":"tsup","format":"biome format --write .","lint:fix":"biome check --write .","test:watch":"vitest"},"_npmUser":{"name":"rajadubey","email":"rajadubey1997@gmail.com"},"_resolved":"/private/var/folders/27/w7z0x6pj2pz4vq_vzhjfq8h80000gp/T/3ce6212e63ed95726b7800f4c8ee64b4/q-api-1.0.0.tgz","_integrity":"sha512-gB00Wgq/IS1gw/PXGED5ZOiQEm8C7EFb0X0+np0A9X7Dn/TQ5Z/o04NtXrBaHYIU+Tc+BKb5HQu7kQpC9cbcMw==","_npmVersion":"11.6.2","description":"Lightweight, TypeScript-ready API client with interceptors, retry, token refresh, and abort support","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^7.0.0","vitest":"^4.0.17","happy-dom":"^20.3.1","typescript":"^5.1.6","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/q-api_1.0.0_1768577844352_0.6104351305761306","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"q-api","version":"1.0.1","description":"Lightweight, TypeScript-ready API client with interceptors, retry, token refresh, and abort support","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.js","types":"./dist/index.d.ts"}},"keywords":["api-client","typescript","fetch","interceptors","retry","abort","lightweight"],"author":{"name":"Raja Dubey"},"license":"MIT","devDependencies":{"@biomejs/biome":"^1.9.4","happy-dom":"^20.3.1","tsup":"^7.0.0","typescript":"^5.1.6","vitest":"^4.0.17"},"engines":{"node":">=24"},"scripts":{"build":"tsup","dev":"tsup src/index.ts --watch","lint":"biome check .","lint:fix":"biome check --write .","format":"biome format --write .","test":"vitest run","test:watch":"vitest"},"_id":"q-api@1.0.1","_integrity":"sha512-EaAx5LmwQm/53BoXcX80csH9CNheKXSY7+AdbxUcingzx5q7azcynfHm4cYA3tP7y1VTJGweASOLMgxc6WUudg==","_resolved":"/private/var/folders/27/w7z0x6pj2pz4vq_vzhjfq8h80000gp/T/9fcf223048285bdf8d8e24de9c745594/q-api-1.0.1.tgz","_from":"file:q-api-1.0.1.tgz","_nodeVersion":"22.16.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-EaAx5LmwQm/53BoXcX80csH9CNheKXSY7+AdbxUcingzx5q7azcynfHm4cYA3tP7y1VTJGweASOLMgxc6WUudg==","shasum":"92bade36b0d4282379a236b3f207d0c557555868","tarball":"https://registry.npmjs.org/q-api/-/q-api-1.0.1.tgz","fileCount":8,"unpackedSize":66026,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEMCIDIxqXstv4krUG1Q9nXPdAsmWeM1yhRks+CVw2OAb17EAh8+pZPDNhGh9ARXXvSXOsHtpXgrGwZJOKlHUoYav/vq"}]},"_npmUser":{"name":"rajadubey","email":"rajadubey1997@gmail.com"},"directories":{},"maintainers":[{"name":"rajadubey","email":"rajadubey1997@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/q-api_1.0.1_1768578743270_0.45446990098662976"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-16T15:37:24.351Z","modified":"2026-01-16T15:52:23.505Z","1.0.0":"2026-01-16T15:37:24.505Z","1.0.1":"2026-01-16T15:52:23.401Z"},"author":{"name":"Raja Dubey"},"license":"MIT","keywords":["api-client","typescript","fetch","interceptors","retry","abort","lightweight"],"description":"Lightweight, TypeScript-ready API client with interceptors, retry, token refresh, and abort support","maintainers":[{"name":"rajadubey","email":"rajadubey1997@gmail.com"}],"readme":"# q-api\n\n<div align=\"center\">\n\n```text\n   ___             _    ____  ____\n  / _ \\           / \\  |  _ \\|_  _|\n | | | |  _____  / _ \\ | |_) | | |\n | |_| | |_____|/ ___ \\|  __/  | |\n  \\__\\_\\       /_/   \\_\\_|    |___|\n```\n\n**Lightweight · Type-Safe · Powerful**\n\nA modern, zero-dependency HTTP client for TypeScript & JavaScript applications. Built with `fetch`, designed for developers.\n\n[![npm version](https://img.shields.io/npm/v/q-api.svg?style=flat-square)](https://www.npmjs.com/package/q-api)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg?style=flat-square)](https://www.typescriptlang.org/)\n[![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg?style=flat-square)]()\n\n</div>\n\n---\n\n## 🚀 Why q-api?\n\n`q-api` is designed to be a drop-in replacement for complex fetching libraries while keeping the bundle size tiny. It wraps the standard `fetch` API with powerful features often needed in production apps:\n\n- ✅ **Type-Safe**: First-class TypeScript support with generics.\n- 🔄 **Interceptors**: Middleware for requests, responses, and errors.\n- 🛡️ **Auto-Refresh Auth**: Built-in logic to handle 401s and refresh tokens seamlessy.\n- 🔁 **Automatic Retries**: Configurable retry logic with exponential backoff.\n- 📂 **File Uploads**: Native support for file uploads with progress tracking.\n- ⚡ **Lightweight**: Zero external dependencies.\n\n## 📦 Installation\n\n```bash\n# using pnpm\npnpm add q-api\n\n# using npm\nnpm install q-api\n\n# using yarn\nyarn add q-api\n```\n\n## 🧠 How it Works\n\nHere is a high-level overview of the request lifecycle in `q-api`:\n\n```mermaid\nflowchart TD\n    Start([Start Request]) --> ReqInt[Request Interceptors]\n    ReqInt --> Fetch{Fetch API}\n\n    Fetch -->|Success| CheckAuth{Status 401?}\n\n    %% Auth Flow\n    CheckAuth -- Yes --> HasHandler{Refresh Handler?}\n    HasHandler -- Yes --> Refresh[Refresh Token]\n    Refresh -->|Retry Request| Fetch\n    HasHandler -- No --> ErrInt\n\n    %% Success Flow\n    CheckAuth -- No --> CheckOK{Response OK?}\n    CheckOK -- Yes --> ResInt[Response Interceptors]\n    ResInt --> Finish([Return Data])\n\n    %% Error Flow\n    CheckOK -- No --> ErrInt[Error Interceptors]\n    ErrInt --> Error[Throw Error]\n\n    Error -.-> Retry{Retries Left?}\n    Retry -- Yes --> Backoff[Wait Delay]\n    Backoff -.-> Start\n    Retry -- No --> Final([Throw Final Error])\n```\n\n## 🛠️ Usage\n\n### Basic Request\n\n```typescript\nimport { api } from 'q-api';\n\ninterface User {\n  id: number;\n  name: string;\n}\n\n// Fully typed response\nconst users = await api.get<User[]>('/users');\n\nconst newUser = await api.post<User>('/users', { name: 'Alice' });\n```\n\n### Interceptors\n\nIntercept requests to add necessary headers (like Authorization) or log activity.\n\n```typescript\nimport { addRequestInterceptor, addResponseInterceptor } from 'q-api';\n\n// Add Auth Token to every request\naddRequestInterceptor((url, options) => {\n  const token = localStorage.getItem('token');\n  if (token) {\n    options.headers = {\n      ...options.headers,\n      Authorization: `Bearer ${token}`,\n    };\n  }\n  return [url, options]; // Must return generic tuple [url, options]\n});\n\n// Transform or Log Responses\naddResponseInterceptor(async (response, data) => {\n  console.log(`Received status: ${response.status}`);\n  return data;\n});\n```\n\n### Automatic Token Refresh 🔐\n\nHandle expired access tokens automatically without disrupting the user experience.\n\n```typescript\nimport { setRefreshTokenHandler } from 'q-api';\n\n// Define how to get a new token\nsetRefreshTokenHandler(async () => {\n  const res = await fetch('/auth/refresh-token');\n  const { accessToken } = await res.json();\n\n  // Save new token\n  localStorage.setItem('token', accessToken);\n\n  return accessToken; // Return the new token string\n});\n\n// Now, if any request returns 401, q-api will:\n// 1. Pause the request\n// 2. Call your handler to get a new token\n// 3. Retry the original request automatically\n```\n\n### Automatic Retries 🔁\n\nMake your application resilient to network blips.\n\n```typescript\n// Retry up to 3 times with exponential backoff\nconst data = await api.get('/unstable-endpoint', {\n  retries: 3,\n  retryDelay: 1000, // Start with 1s delay (1s, 2s, 4s)\n});\n```\n\n### File Uploads 📤\n\nUpload files easily with `FormData` handling handled for you.\n\n```typescript\nimport { upload } from 'q-api';\n\nconst fileInput = document.querySelector('#file') as HTMLInputElement;\nconst files = fileInput.files;\n\nif (files) {\n  try {\n    const response = await upload('/api/upload', Array.from(files), {\n      headers: { 'X-Custom-ID': '123' },\n    });\n    console.log('Upload complete!', response);\n  } catch (err) {\n    console.error('Upload failed', err);\n  }\n}\n```\n\n### Cancellation 🛑\n\nCancel requests using the standard `AbortController`.\n\n```typescript\nconst controller = new AbortController();\n\nconst promise = api.get('/long-task', {\n  signal: controller.signal,\n});\n\n// Cancel the request\ncontroller.abort();\n```\n\n## 📚 API Reference\n\n### `api` Object\n\n- `api.get<T>(url, options?)`\n- `api.post<T>(url, body?, options?)`\n- `api.put<T>(url, body?, options?)`\n- `api.patch<T>(url, body?, options?)`\n- `api.delete<T>(url, options?)`\n\n### Utils\n\n- `upload(url, files[], options?)`\n- `addRequestInterceptor(fn)`\n- `addResponseInterceptor(fn)`\n- `addErrorInterceptor(fn)`\n- `setRefreshTokenHandler(fn)`\n\n## 🤝 Contributing\n\nContributions are welcome! Please follow these steps to contribute:\n\n1.  **Fork the repository** on GitHub.\n2.  **Clone your fork**:\n    ```bash\n    git clone https://github.com/your-username/q-api.git\n    cd q-api\n    ```\n3.  **Install dependencies**:\n    ```bash\n    pnpm install\n    ```\n4.  **Create a new branch**:\n    ```bash\n    git checkout -b feature/my-new-feature\n    ```\n5.  **Make your changes** and write tests.\n6.  **Run tests** to ensure everything is working:\n    ```bash\n    pnpm test\n    ```\n7.  **Lint and format** your code:\n    ```bash\n    pnpm run lint\n    pnpm run format\n    ```\n8.  **Commit your changes** and push to your fork.\n9.  **Submit a Pull Request**!\n\nPlease ensure your code follows the project's coding style and includes appropriate tests.\n\n## 📄 License\n\nMIT © [Raja Dubey](https://github.com/rajadubey)\n","readmeFilename":"README.md"}