JSPM

smart-api-throttle

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q12292F
  • License MIT

A lightweight, flexible, frontend-friendly API rate limiter with multiple strategies

Package Exports

  • smart-api-throttle
  • smart-api-throttle/react

Readme

Smart API Throttle

A lightweight, flexible, frontend-friendly API rate limiter with multiple strategies, universal async wrapper, and React hooks.

Features

  • Multiple Rate Limiting Strategies: Fixed Window, Token Bucket, and Debounce
  • Universal Async Wrapper: Wrap any async function with rate limiting
  • Ready-to-use Adapters: Built-in support for fetch and axios
  • React Hooks: Easy integration with React applications
  • Smart Features: Retry on failure, exponential backoff, request queuing
  • Lightweight: Zero dependencies (except axios for axios adapter)

Installation

npm install smart-api-throttle

Quick Start

Basic Usage

import { SmartThrottle, presets } from 'smart-api-throttle';

// Create a limiter with fixed window strategy
const limiter = new SmartThrottle({
  strategy: 'fixed-window',
  maxRequests: 10,
  windowMs: 60000, // 1 minute
  queue: true,
  retryOnFail: true,
});

// Wrap any async function
const limitedFetch = limiter.wrap(fetch);
const response = await limitedFetch('https://api.example.com/data');

Using Presets

import { SmartThrottle, presets } from 'smart-api-throttle';

// Use predefined configurations
const conservativeLimiter = new SmartThrottle(presets.conservative); // 10 req/min
const moderateLimiter = new SmartThrottle(presets.moderate); // 100 req/min
const tokenBucketLimiter = new SmartThrottle(presets.tokenBucket); // 10 tokens, 1/sec

Rate Limiting Strategies

Fixed Window

Limits requests to X calls per Y milliseconds window.

const limiter = new SmartThrottle({
  strategy: 'fixed-window',
  maxRequests: 100,
  windowMs: 60000, // 100 requests per minute
});

Token Bucket

Implements a token bucket algorithm with configurable capacity and refill rate.

const limiter = new SmartThrottle({
  strategy: 'token-bucket',
  capacity: 10, // Maximum tokens
  refillRate: 1, // 1 token per second
});

Debounce

Waits for a specified delay after the last trigger before allowing execution.

const limiter = new SmartThrottle({
  strategy: 'debounce',
  debounceMs: 500, // 500ms delay
});

Adapters

Fetch Adapter

import { createSmartFetch } from 'smart-api-throttle';

const smartFetch = createSmartFetch({
  strategy: 'fixed-window',
  maxRequests: 10,
  windowMs: 60000,
});

// Use like regular fetch
const response = await smartFetch.fetch('https://api.example.com/data');

// Or use convenience methods
const data = await smartFetch.get('https://api.example.com/users');
const newUser = await smartFetch.post('https://api.example.com/users', {
  name: 'John Doe',
  email: 'john@example.com'
});

Axios Adapter

import { createSmartAxios } from 'smart-api-throttle';

const smartAxios = createSmartAxios({
  strategy: 'token-bucket',
  capacity: 10,
  refillRate: 1,
});

// Use like regular axios
const response = await smartAxios.get('https://api.example.com/data');
const newData = await smartAxios.post('https://api.example.com/data', {
  title: 'New Post',
  content: 'Hello World'
});

React Hooks

useSmartFetch

import { useSmartFetch } from 'smart-api-throttle/react';

function MyComponent() {
  const { fetchData, isThrottled, isLoading, error } = useSmartFetch({
    strategy: 'fixed-window',
    maxRequests: 10,
    windowMs: 60000,
  }, {
    onThrottle: (request) => console.log('Request throttled:', request),
    onError: (error) => console.error('Request failed:', error),
  });

  const handleClick = async () => {
    try {
      const response = await fetchData('https://api.example.com/data');
      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <div>
      <button onClick={handleClick} disabled={isThrottled || isLoading}>
        {isLoading ? 'Loading...' : 'Fetch Data'}
      </button>
      {isThrottled && <p>Rate limited. Please wait...</p>}
      {error && <p>Error: {error.message}</p>}
    </div>
  );
}

useSmartFetchInstance

import { useSmartFetchInstance } from 'smart-api-throttle/react';

function MyComponent() {
  const { fetch, isThrottled, getUsage } = useSmartFetchInstance({
    strategy: 'token-bucket',
    capacity: 10,
    refillRate: 1,
  });

  const handleClick = async () => {
    const response = await fetch('https://api.example.com/data');
    const usage = getUsage();
    console.log('Token bucket usage:', usage);
  };

  return (
    <div>
      <button onClick={handleClick} disabled={isThrottled}>
        Fetch Data
      </button>
      <p>Throttled: {isThrottled ? 'Yes' : 'No'}</p>
    </div>
  );
}

Advanced Features

Request Queuing

const limiter = new SmartThrottle({
  strategy: 'fixed-window',
  maxRequests: 5,
  windowMs: 60000,
  queue: true, // Enable queuing
});

// Requests will be queued when rate limit is exceeded
const promises = Array.from({ length: 10 }, (_, i) =>
  limiter.wrap(fetch)(`https://api.example.com/data/${i}`)
);

// All requests will be processed in order
const responses = await Promise.all(promises);

Retry with Exponential Backoff

const limiter = new SmartThrottle({
  strategy: 'fixed-window',
  maxRequests: 10,
  windowMs: 60000,
  retryOnFail: true,
  maxRetries: 3,
  backoffOn: [429, 503], // Retry on rate limit and service unavailable
});

Custom Callbacks

const limiter = new SmartThrottle({
  strategy: 'fixed-window',
  maxRequests: 10,
  windowMs: 60000,
  onLimitReached: (request) => {
    console.log('Rate limit reached for request:', request);
    // Show user notification, update UI, etc.
  },
  onThrottle: (request) => {
    console.log('Request throttled:', request);
    // Handle throttled request
  },
});

API Reference

SmartThrottle

Constructor

new SmartThrottle(config: RateLimitConfig)

Methods

  • wrap<T, R>(fn: (...args: T) => Promise<R>, ...args: T): Promise<R> - Wrap an async function with rate limiting
  • canExecute(): boolean - Check if a request can be executed
  • getQueueLength(): number - Get the number of queued requests
  • clearQueue(): void - Clear the request queue
  • getUsage(): any - Get current usage statistics (strategy-specific)
  • updateConfig(config: RateLimitConfig): void - Update the limiter configuration

Configuration Options

interface RateLimitConfig {
  strategy: 'fixed-window' | 'token-bucket' | 'debounce';
  maxRequests?: number;        // For fixed-window
  windowMs?: number;           // For fixed-window
  capacity?: number;           // For token-bucket
  refillRate?: number;         // For token-bucket
  debounceMs?: number;         // For debounce
  queue?: boolean;             // Enable request queuing
  retryOnFail?: boolean;       // Enable retry on failure
  maxRetries?: number;         // Maximum retry attempts
  backoffOn?: number[];        // HTTP status codes to trigger backoff
  onLimitReached?: (request: any) => void; // Callback when limit is reached
  onThrottle?: (request: any) => void;     // Callback when request is throttled
}

Testing

# Run tests
npm test

# Run examples
npm run example

# Build package
npm run build

License

MIT