Catalog npm
PACKAGE EXPLORERView in registry

@0xshariq/voxa

npm

A modern HTTP client library built on native Fetch API with advanced features like caching, retry, and request deduplication.

axioscachefetchhttphttp-clientrequestretrytypescript
Versions collected12
Direct dependencies6From release 2.4.1
Last observed21 Oct, 11:26 UTC

README

Current package documentation

Voxa HTTP Client

Modern, feature-rich HTTP client for Node.js and browsers, built on the native Fetch API. Supports REST and GraphQL, automatic JSON parsing, metadata, caching, deduplication, queueing, and more.

npm version License: MIT

✨ Features

  • 🔄 Automatic Retry (exponential backoff)
  • 💾 Response Caching (memory/redis/custom)
  • 🎯 Request Deduplication
  • ⚡ Priority Queue
  • 🔒 TypeScript First
  • 🔌 Interceptors
  • 📊 Request Tracking & Metadata
  • ⏱️ Timeout Control
  • 🚀 Static Methods
  • 🛑 CancelManager
  • 📡 OfflineQueueManager
  • 🪪 TokenManager
  • 🧬 GraphQL Support
  • 🧪 Automatic JSON Parsing
  • 📹 Streaming Images/Videos (with progress tracking)
  • 🔐 SSRF Protection

📦 Installation

npm install @0xshariq/voxa
# or
pnpm install @0xshariq/voxa
# or
yarn add @0xshariq/voxa

🚀 Usage

🧩 Feature Modularity & Extensibility

Voxa's features (cache, retry, queue, batch, deduplication, interceptors, etc.) are fully modular and can be enabled, disabled, or extended at runtime.

Enabling/Disabling Features at Runtime

You can toggle features on/off by updating the instance configuration:

// Disable cache and queue at runtime
api.updateConfig({
  cache: { enabled: false },
  queue: { enabled: false },
});

// Enable retry and set new retry count
api.updateConfig({
  retry: { enabled: true, count: 10 },
});

Note: Not all features support dynamic reconfiguration in-flight. For critical changes, create a new instance with the desired config.

Extending with Plugins (Custom Features)

You can add your own features or override built-in ones by attaching custom managers or hooks:

// Example: Add a custom logging plugin
api.usePlugin({
  onRequest(config) {
    console.log("Request:", config.url);
    return config;
  },
  onResponse(response) {
    console.log("Response:", response.status);
    return response;
  },
});

Plugin Interface

A plugin is an object with any of these hooks:

  • onRequest(config)
  • onResponse(response)
  • onError(error)
  • onBatch(batch)
  • onCacheEvent(event)

You can register multiple plugins. They are called in the order added.

Disabling a Feature for a Single Request

// Disable cache for a single request
await api.get('/users', { cache: { enabled: false } });

// Set custom queue priority for a single request
await api.post('/orders', { ... }, { priority: 'critical' });

See Advanced Features for more on feature modularity and plugins.

Using Voxa with an Instance

Injecting Custom requestId & Metadata

You can supply your own requestId or custom metadata for distributed tracing or advanced tracking:

// Provide a custom requestId and metadata for tracing
const response = await api.get("/users/1", {
  requestId: "trace-abc-123",
  metadata: {
    traceId: "trace-abc-123",
    userId: "user-42",
    customField: "my-value",
  },
});
console.log(response.metadata); // includes your custom fields

Note: If you provide a requestId, it will be used for all feature tracking (cache, batch, queue, etc.).

Create a client instance to reuse configuration and advanced features:

import voxa from "@0xshariq/voxa";

const api = voxa.create({
  baseURL: "https://api.example.com",
  timeout: 5000,
  // ...other options
});

// Make requests (response is always parsed JSON)
const response = await api.get<User>("/users/1");
console.log(response.data); // { id, name, ... }

// You can also use other HTTP methods:
await api.post("/users", { name: "John" });
await api.put("/users/1", { name: "Jane" });
await api.delete("/users/1");

Using Voxa Without an Instance (Static Methods)

Call static methods directly for one-off requests:

import { Voxa } from "@0xshariq/voxa";

const response = await Voxa.get<User>("https://api.example.com/users/1");
console.log(response.data);

// Other static methods:
await Voxa.post("https://api.example.com/users", { name: "John" });
await Voxa.put("https://api.example.com/users/1", { name: "Jane" });
await Voxa.delete("https://api.example.com/users/1");

Use an instance for advanced features (caching, queueing, interceptors, GraphQL, etc.), or static methods for simple requests.

🚀 Quick Start

Complete Instance Example

import voxa from "@0xshariq/voxa";

const api = voxa.create({
  baseURL: "https://api.example.com", // string
  timeout: 5000, // number (ms)
  headers: {
    "Content-Type": "application/json", // string
    Authorization: "Bearer <token>", // string
  },
  priority: "high", // 'critical' | 'high' | 'normal' | 'low'
  retry: {
    enabled: true, // boolean (default: true)
    count: 5, // number (max: 5)
    delay: 1000, // number (ms)
    exponentialBackoff: true, // boolean
    maxRetry: 10000, // number (ms)
    statusCodes: [429, 500, 502, 503, 504], // number[]
  },
  deduplication: {
    enabled: true, // boolean (default: true)
    ttl: 300000, // number (ms)
  },
  cache: {
    enabled: true, // boolean (default: true)
    ttl: 300000, // number (ms, default: 5 min)
    storage: "memory", // 'memory' | 'custom'
    adapter: undefined, // custom cache adapter (optional)
  },
  queue: {
    enabled: true, // boolean
    maxConcurrent: 5, // number
  },
  batch: {
    enabled: true, // boolean
    endpoint: "/batch", // string (optional)
    wait: 100, // number (ms, optional)
    maxBatchSize: 10, // number (optional)
  },
  token: {
    enabled: true, // boolean
    type: "bearer", // 'bearer' | 'oauth2' | 'jwt'
    tokenEndpoint: "/auth/token", // string
    clientId: "client-id", // string
    clientSecret: "client-secret", // string
    refreshEndpoint: "/auth/refresh", // string
    storage: "memory", // 'memory' | 'localStorage'
    getToken: async () => "token", // function
    setToken: (token: string) => {}, // function
    refreshToken: async () => "new-token", // function
  },
  // Token refresh failure hook
  onTokenRefreshFailure: (error, context) => {
    // Custom logic: log, alert, or trigger re-authentication
    console.error("Token refresh failed:", error, context);
    // Optionally, redirect user or clear session
  },

  // Multi-tenant/multi-user support example
  getToken: async (userId) => {
    // Fetch token for a specific user/tenant
    return await fetchTokenForUser(userId);
  },
  setToken: (token, userId) => {
    // Store token for a specific user/tenant
    saveTokenForUser(token, userId);
  },
  refreshToken: async (userId) => {
    // Refresh token for a specific user/tenant
    return await refreshUserToken(userId);
  },

  // Usage:
  // await api.get('/resource', { userId: 'user-42' });
  offline: {
    enabled: true, // boolean (default: true)
    storage: "localStorage", // 'localStorage' | 'indexedDB'
  },
  circuitBreaker: {
    enabled: true, // boolean
    threshold: 5, // number
    timeout: 10000, // number (ms)
    onOpen: () => {}, // function (optional)
  },
  metrics: {
    enabled: true, // boolean
  },
  errors: {
    enabled: true, // boolean (default: true)
  },
  rate: {
    enabled: true, // boolean (default: true)
    maxRequests: 100, // number
    perMilliseconds: 60000, // number (ms)
  },
  schema: {
    enabled: true, // boolean
    requestSchema: undefined, // any (optional)
    responseSchema: undefined, // any (optional)
    library: "zod", // 'zod' | 'yup' (optional)
  },
  cancel: {
    enabled: true, // boolean (default: true)
  },
  graphql: {
    enabled: true, // boolean
    endpoint: "https://graphqlzero.almansi.me/api", // string
    logErrors: true, // boolean
    headers: undefined, // Record<string, string> (optional)
    timeout: undefined, // number (optional)
    cache: undefined, // boolean (optional)
  },
  interceptors: {
    request: [
      (config) => {
        /* modify config */ return config;
      },
    ],
    response: [
      (response) => {
        /* log/modify response */ return response;
      },
    ],
  },
  metadata: {
    enabled: true, // boolean (default: true)
    log: true, // boolean (log metadata events)
    fields: [
      "id",
      "method",
      "endpoint",
      "priority",
      "timestamp",
      "startTime",
      "endTime",
    ], // string[] (fields to track)
    maxEntries: 100, // number (max entries to keep)
    customHandler: (meta) => {}, // function (custom handler)
  },
});

// All options above are shown with possible values in comments. // You can use only the options you need.


### TypeScript Generics

```typescript
interface User {
  id: number;
  name: string;
  email: string;
}

// Type-safe responses
const response = await api.get<User>("/users/1");
const user: User = await response.json();
```

### Streaming Upload/Download

```typescript
import { StreamingImageManager, StreamingVideoManager } from '@0xshariq/voxa';

// Upload image with progress tracking
const streamingImages = new StreamingImageManager({});

const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];

await streamingImages.upload(
  'https://api.example.com/images/upload',
  file,
  { 'Content-Type': 'image/jpeg' },
  (sentBytes, totalBytes) => {
    const percentage = (sentBytes / totalBytes) * 100;
    console.log(`Upload progress: ${percentage.toFixed(2)}%`);
  }
);

// Download video with progress
const streamingVideos = new StreamingVideoManager({});

const response = await streamingVideos.download(
  'https://api.example.com/videos/12345',
  {},
  (receivedBytes, totalBytes) => {
    console.log(`Downloaded: ${receivedBytes}/${totalBytes} bytes`);
  }
);

const blob = await response.blob();
const videoUrl = URL.createObjectURL(blob);
```

See [Streaming Guide](./docs/STREAMING.md) for complete examples and advanced usage.

## 📖 Documentation

### Core Documentation

**Documentation:**

- [Configuration Guide](./docs/CONFIGURATION.md) — All config options
- [Advanced Features](./docs/ADVANCED.md) — Caching, deduplication, queueing, interceptors, GraphQL, etc.
- [Streaming Guide](./docs/STREAMING.md) — Image/video upload/download with progress tracking
- [Developer Experience](./docs/DEVELOPER_EXPERIENCE.md) — Debug mode, logging, public getters, type safety
- [Troubleshooting](./docs/TROUBLESHOOTING.md) — Common issues and solutions
- [Custom Cache](./docs/CUSTOM_CACHE.md) — Custom cache implementation
- [Batch Usage](./docs/BATCH_USAGE.md) — Batch request patterns
- [Examples](./docs/EXAMPLES.md) — Usage patterns and code samples

See docs/ for full details and up-to-date usage.

## 🎯 Key Features

### Automatic Retry with Exponential Backoff

```typescript
const api = voxa.create({
  baseURL: "https://api.example.com",
  retry: {
    count: 3, // Max 3 retries
    delay: 1000, // Initial delay: 1s
    exponentialBackoff: true, // 1s → 2s → 4s
    maxRetry: 10000, // Max delay: 10s
  },
});
```

### Response Structure

```typescript
{
  response: Response, // Http Response object
  data: {}, // Api Data will store here
  metadata: {
    id: "string", // requestId used everywhere
    method: "'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'",
    endpoint: "string",
    priority: "'critical' | 'high' | 'normal' | 'low'",
    timestamp: 2000,
    startTime: 2000,
    endTime: 2000
  },
  requestId: string, // Unique requestId, used in all features (queue, batch, cache, metrics, etc.)
  status: 200,
  statusText: "Ok"
}
```

See [Response Structure](./src/lib/types/client-types.ts) for detailed info.

### Response Caching

```typescript
// Memory cache (default)
const api = voxa.create({
  cache: {
    enabled: true,
    type: "memory",
    ttl: 300000, // 5 minutes
  },
});

// Redis cache
const api = voxa.create({
  cache: {
    enabled: true,
    type: "redis",
    ttl: 300000,
  },
});
```

### Request Prioritization

```typescript
// High priority request
await api.get("/critical-data", { priority: "critical" });

// Normal priority (default)
await api.get("/regular-data");

// Low priority
await api.get("/background-data", { priority: "low" });
```

### Request Interceptors

```typescript
// Add authentication header
api.interceptors.request.use((config) => {
  config.headers = {
    ...config.headers,
    Authorization: `Bearer ${getToken()}`,
  };
  return config;
});

// Log responses
api.interceptors.response.use((response) => {
  console.log("Response:", response.status);
  return response;
});
```

## 🔧 Configuration

### Environment Variables

Create a `.env` file in your project root:

```env
# Cache Configuration (Generic - works with any cache backend)
CACHE_URL=redis://localhost:6379
CACHE_PASSWORD=your-password
CACHE_HOST=localhost
CACHE_PORT=6379
CACHE_DB=0

# HTTP Configuration
HTTP_TIMEOUT=5000
HTTP_BASE_URL=https://api.example.com
```

See [Configuration Guide](./docs/CONFIGURATION.md) for detailed options.

## 📊 Monitoring & Statistics

```typescript
// Get cache statistics
const cacheStats = api.getCacheStats();
console.log(cacheStats); // { storage: 'memory', size: 10, entries: [...] }

// Get queue statistics
const queueStats = api.getQueueStats();
console.log(queueStats); // { queueSize: 2, activeRequests: 3, maxConcurrent: 5 }

// Get request metadata
const metadata = api.getRequestMetadata("request-id-123");
console.log(metadata); // { id, method, endpoint, duration, ... }
```

## Request ID Format and Expiry

Each request is assigned a unique `requestId` for tracking and feature management. The format is:

```
<timestamp>-<expiry>-<random>
```

- `timestamp`: When the request was created
- `expiry`: When the requestId expires (used for cache/batch conflict avoidance)
- `random`: Random string for uniqueness

- **Cache feature** uses a 5 minute expiry (default).
- **Batch feature** uses a 15 minute expiry.

This prevents conflicts when the same request is sent at different times. Always use the generated requestId for all features (cache, batch, queue, etc.).

---

## Error Classification & Debugging

Voxa now provides detailed error classification and debugging messages for every request. Use `api.classifyError(error)` to get both the error category and a helpful message for easier troubleshooting.

---

### Feature Manager Access

All feature managers (cache, queue, deduplication, metadata, circuit breaker, batch, rate limiter, metrics, schema, error classifier) are accessible via public methods or stats getters:

- `api.getCacheStats()`
- `api.getQueueStats()`
- `api.getDeduplicationStats()`
- `api.getMetadataStats()`
- `api.circuitBreaker()`
- `api.batch()`
- `api.rate()`
- `api.metrics()`
- `api.schema()`
- `api.classifyError(error)`

---

## 🧪 Testing

```bash
# Run test file directly
pnpm test

# Or using development mode
pnpm dev
```

## 📝 HTTP Methods

Voxa supports all standard HTTP methods:

```typescript
await api.get("/users");
await api.post("/users", { name: "John" });
await api.put("/users/1", { name: "Jane" });
await api.patch("/users/1", { email: "new@example.com" });
await api.delete("/users/1");
await api.head("/users");
await api.options("/users");
```

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## 📄 License

MIT © [Sharique Chaudhary](https://github.com/0xshariq)

## 🔗 Links

- [GitHub Repository](https://github.com/0xshariq/voxa)
- [npm Package](https://www.npmjs.com/package/@0xshariq/voxa)
- [Issue Tracker](https://github.com/0xshariq/voxa/issues)

## 🌟 Credits

Built with inspiration from Axios and modern web standards.

---

**Note:** This project is built on the native Fetch API and requires Node.js 18+ or a modern browser environment.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 12

Collected releases
VersionPublishedDirect dependenciesOpen version
2.4.1Registry latest4 Dec 20256
2.4.04 Dec 20256
2.3.02 Dec 20256
2.2.52 Dec 20256
2.2.41 Dec 20256
2.2.31 Dec 20256
2.2.21 Dec 20256
2.2.11 Dec 20256
2.2.030 Nov 20256
2.1.029 Nov 20256
2.0.026 Nov 20256
1.0.024 Nov 20251

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
0xshariq/voxa

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 21 Oct, 11:26 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:b9eee995c10915f1f85c5219b1c05ab9c8d6c4556fe56e72072a11be751c41da