npm package: @lionrapid/storage
Description: Persistent storage adapters for LionRapid localization library
Author: Janrau B
Latest version: 0.1.0

# @lionrapid/storage

Persistent storage adapters for LionRapid localization library.

## Installation

```bash
npm install @lionrapid/storage
```

## Usage

```typescript
import {
  LionRapidBuilder,
  MemoryRepository,
  NetworkRepository,
} from '@lionrapid/core';
import {
  LocalStorageRepository,
  CacheStorageRepository,
} from '@lionrapid/storage';

// Handlers are used in the order they're added (no priority needed)
const i18n = await LionRapidBuilder.init({
  defaultLocale: 'en',
  namespace: 'app',
})
  .use(new MemoryRepository({ enabled: true })) // Layer 1: fastest (sync)
  .use(
    new LocalStorageRepository({
      // Layer 2: persistent (sync)
      enabled: true,
      options: {
        ttl: 24 * 60 * 60 * 1000, // 24 hours
        maxSize: 500,
      },
    })
  )
  .use(
    new CacheStorageRepository({
      // Layer 3: larger capacity (async)
      enabled: true,
      options: {
        ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
      },
    })
  )
  .use(
    new NetworkRepository({
      // Layer 4: source of truth (async)
      enabled: true,
      options: { baseUrl: 'https://api.example.com' },
    })
  )
  .build();
```

## Handler Chain Flow

```
t('key') called
    ↓
[SYNC PHASE - Immediate]
    ↓
1. MemoryRepository.get(key)         → ~0ms, session-only
2. LocalStorageRepository.get(key)   → ~1-5ms, persists across loads
    ↓
If hit: Return immediately ✅
    ↓
[ASYNC PHASE - Background]
    ↓
3. CacheStorageRepository.get(key)   → ~5-20ms, larger capacity
4. NetworkRepository.fetch(key)      → ~50-200ms, source of truth
    ↓
Save to: CacheStorage → localStorage → memory
```

## LocalStorageRepository

A synchronous localStorage-based repository for persistent translation caching.

### Features

- **Synchronous access** - localStorage is sync, so translations display instantly
- **TTL-based expiration** - Automatic cache invalidation
- **Graceful fallback** - Works in SSR and private browsing mode
- **Quota handling** - Automatic eviction when storage is full
- **Version migration** - Clears cache on version changes

### Configuration

```typescript
interface LocalStorageRepositoryConfig {
  enabled?: boolean; // Enable/disable (default: true)
  priority?: number; // Handler priority (default: 0, uses build sequence)
  options?: {
    prefix?: string; // Storage key prefix (default: 'lionrapid:')
    ttl?: number; // TTL in milliseconds (default: 24 hours)
    maxSize?: number; // Max entries before eviction (default: 500)
  };
}
```

## CacheStorageRepository

An asynchronous Cache API-based repository for larger persistent storage.

### Features

- **Asynchronous access** - Cache API is async, runs in background
- **Larger storage capacity** - Not limited by localStorage 5MB quota
- **TTL-based expiration** - Automatic cache invalidation
- **Graceful fallback** - Works when Cache API unavailable (SSR, old browsers)
- **Service Worker ready** - Works alongside Service Workers for offline support

### Configuration

```typescript
interface CacheStorageRepositoryConfig {
  enabled?: boolean; // Enable/disable (default: true)
  priority?: number; // Handler priority (default: 0, uses build sequence)
  options?: {
    cacheName?: string; // Cache name (default: 'lionrapid-v1')
    ttl?: number; // TTL in milliseconds (default: 7 days)
  };
}
```

### When to Use

| Feature           | LocalStorage        | CacheStorage               |
| ----------------- | ------------------- | -------------------------- |
| **Access Type**   | Synchronous         | Asynchronous               |
| **Storage Limit** | ~5MB                | Larger (browser-dependent) |
| **Speed**         | ~1-5ms              | ~5-20ms                    |
| **Best For**      | Small, fast lookups | Large translation sets     |
| **SSR Support**   | Graceful fallback   | Graceful fallback          |

## Optional: Service Worker for Offline Support

For full offline support, you can add a Service Worker. The package includes an optional Service Worker file.

### Service Worker Features

| Feature                    | Cache API Only | + Service Worker |
| -------------------------- | -------------- | ---------------- |
| Persistent cache           | ✅             | ✅               |
| Offline translations (GET) | ❌             | ✅               |
| Background sync (POST/PUT) | ❌             | ✅               |
| Cache invalidation         | Manual         | ✅ Via message   |
| Version management         | Manual         | ✅ Automatic     |
| Request interception       | ❌             | ✅               |

### Setup

The package ships a pre-built `sw.js` file. Copy it to your public folder:

```bash
# Copy to your app's public folder
cp node_modules/@lionrapid/storage/dist/sw.js public/

# Or with npx (coming soon)
# npx lionrapid sw init
```

### Service Worker Registration

```typescript
// In your app's entry point
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}
```

### Service Worker Communication

```typescript
// Invalidate specific pattern
navigator.serviceWorker.controller?.postMessage({
  type: 'INVALIDATE_CACHE',
  payload: { pattern: 'en:app' },
});

// Clear all cache
navigator.serviceWorker.controller?.postMessage({ type: 'CLEAR_ALL' });

// Get cache stats
const channel = new MessageChannel();
channel.port1.onmessage = e => console.log('Stats:', e.data);
navigator.serviceWorker.controller?.postMessage({ type: 'GET_CACHE_STATS' }, [
  channel.port2,
]);
```

> **Note:** Handlers are processed in the order they're added via `.use()`. Priority is only needed if you want to override this default sequence.

## License

MIT