npm package: @pingpong-js/plugin-cache
Description: Smart caching plugin for @pingpong-js/fetch with memory, localStorage, and IndexedDB support
Author: Devendra Pratap
Latest version: 1.0.1

# @pingpong-js/plugin-cache

Smart caching plugin for [@pingpong-js/fetch](https://www.npmjs.com/package/@pingpong-js/fetch) with multiple storage backends.

## Installation

```bash
npm install @pingpong-js/plugin-cache
# peer dependency
npm install @pingpong-js/fetch
```

## Features

- 🗄️ **Multiple Storage Backends**: Memory, localStorage, IndexedDB
- ⏰ **Configurable TTL**: Time-to-live for cache entries
- 🎯 **URL Pattern Matching**: Include/exclude specific URLs
- 🔄 **Stale-While-Revalidate**: Serve stale data while refreshing
- 📊 **Cache Statistics**: Track hits, misses, and hit rate
- 🚫 **Request Deduplication**: Prevent duplicate concurrent requests

## Usage

### Basic Usage

```typescript
import pingpong from '@pingpong-js/fetch';
import { createCache } from '@pingpong-js/plugin-cache';

const cache = createCache({
  storage: 'memory',
  ttl: 60000, // 1 minute
});

// Register cache listeners
pingpong.onRequest(cache.request);
pingpong.onResponse(cache.response);

// First request - cache miss
await pingpong.get('/api/users'); // 200ms

// Second request - cache hit
await pingpong.get('/api/users'); // <1ms
```

### Quick Setup

```typescript
import pingpong from '@pingpong-js/fetch';
import { withCachePlugin } from '@pingpong-js/plugin-cache';

const { request, response, cache } = withCachePlugin({ ttl: 60000 });

pingpong.onRequest(request);
pingpong.onResponse(response);

// Invalidate cache manually
cache.invalidate('/api/users');
cache.clear();
```

### Storage Options

```typescript
// Memory cache (default)
const memoryCache = createCache({ storage: 'memory' });

// localStorage (persists across sessions)
const localCache = createCache({ storage: 'localStorage' });

// IndexedDB (large data, persists)
const idbCache = createCache({ storage: 'indexeddb' });
```

### Advanced Options

```typescript
const cache = createCache({
  storage: 'memory',
  ttl: 5 * 60 * 1000, // 5 minutes
  maxEntries: 100,
  methods: ['GET'], // Only cache GET requests
  include: [/\/api\/users/], // Only cache matching URLs
  exclude: [/\/api\/auth/], // Exclude from caching
  staleWhileRevalidate: true, // Serve stale while refreshing
  respectCacheControl: true, // Honor server Cache-Control headers
});
```

### Request Deduplication

Prevent duplicate concurrent requests:

```typescript
import pingpong from '@pingpong-js/fetch';
import { withDedupe } from '@pingpong-js/plugin-cache';

pingpong.onRequest(withDedupe());

// These will only make ONE actual request
const [user1, user2, user3] = await Promise.all([
  pingpong.get('/api/users/1'),
  pingpong.get('/api/users/1'),
  pingpong.get('/api/users/1'),
]);
```

### Cache Statistics

```typescript
const cache = createCache();

// ... make some requests ...

console.log(cache.getStats());
// { hits: 42, misses: 10, size: 52, entries: 25 }

console.log(cache.getHitRate());
// 0.807 (80.7% hit rate)
```

## API Reference

### `createCache(options?)`

Creates a new cache instance.

**Options:**
- `storage`: `'memory'` | `'localStorage'` | `'indexeddb'` (default: `'memory'`)
- `ttl`: Time to live in ms (default: `300000` - 5 minutes)
- `maxEntries`: Maximum cache entries (default: `100`)
- `methods`: HTTP methods to cache (default: `['GET']`)
- `include`: URL patterns to cache (RegExp[])
- `exclude`: URL patterns to exclude (RegExp[])
- `staleWhileRevalidate`: Serve stale while refreshing (default: `false`)
- `respectCacheControl`: Honor server Cache-Control headers (default: `false`)

### `withCachePlugin(options?)`

Quick setup helper that returns request/response listeners and cache instance.

### `withDedupe(options?)`

Request deduplication listener.

## License

MIT