Real-World Examples

July 13, 2026 ยท View on GitHub

Comprehensive examples demonstrating plugin usage in production scenarios.

Table of Contents


E-commerce Shopping Cart

Persistent cart with TTL expiration:

import localspace, { ttlPlugin } from 'localspace';

// Create cart storage with expiration
const cartStore = localspace.createInstance({
  name: 'ecommerce',
  storeName: 'cart',
  plugins: [
    // Cart items expire after 7 days
    ttlPlugin({
      defaultTTL: 7 * 24 * 60 * 60 * 1000, // 7 days
      cleanupInterval: 60 * 60 * 1000, // Hourly cleanup
      onExpire: (key, value) => {
        analytics.track('cart_expired', {
          key,
          itemCount: value?.items?.length,
        });
      },
    }),
  ],
  pluginErrorPolicy: 'strict',
});

// Cart operations
class CartService {
  async addItem(productId: string, quantity: number) {
    const cart = (await cartStore.getItem<Cart>('cart')) ?? { items: [] };
    const existing = cart.items.find((i) => i.productId === productId);

    if (existing) {
      existing.quantity += quantity;
    } else {
      cart.items.push({ productId, quantity, addedAt: Date.now() });
    }

    cart.updatedAt = Date.now();
    await cartStore.setItem('cart', cart);
    return cart;
  }

  async removeItem(productId: string) {
    const cart = await cartStore.getItem<Cart>('cart');
    if (!cart) return null;

    cart.items = cart.items.filter((i) => i.productId !== productId);
    cart.updatedAt = Date.now();
    await cartStore.setItem('cart', cart);
    return cart;
  }

  async getCart(): Promise<Cart | null> {
    return cartStore.getItem('cart');
  }

  async clearCart() {
    await cartStore.removeItem('cart');
  }
}

interface Cart {
  items: CartItem[];
  updatedAt: number;
}

interface CartItem {
  productId: string;
  quantity: number;
  addedAt: number;
}

Secure User Credentials Storage

Encrypted storage for sensitive user data with key derivation:

import localspace, { encryptionPlugin, ttlPlugin } from 'localspace';

// Create secure credentials store
async function createSecureStore(userPassword: string, userId: string) {
  const store = localspace.createInstance({
    name: 'secure-vault',
    storeName: 'credentials',
    plugins: [
      // Short TTL for security-sensitive data
      ttlPlugin({
        defaultTTL: 30 * 60 * 1000, // 30 minutes default
        keyTTL: {
          'session-token': 4 * 60 * 60 * 1000, // 4 hours for session
          'refresh-token': 7 * 24 * 60 * 60 * 1000, // 7 days for refresh
          'biometric-key': 24 * 60 * 60 * 1000, // 24 hours for biometrics
        },
        onExpire: async (key) => {
          if (key === 'session-token') {
            // Trigger re-authentication
            window.dispatchEvent(new CustomEvent('session-expired'));
          }
        },
      }),

      // Encrypt with password-derived key
      encryptionPlugin({
        keyDerivation: {
          passphrase: userPassword,
          salt: `vault-salt-${userId}`, // User-specific salt
          iterations: 200000, // High iteration count for security
          hash: 'SHA-256',
          length: 256,
        },
      }),
    ],
    pluginErrorPolicy: 'strict', // Also fail fast for TTL and custom plugin errors
  });

  await store.ready();
  return store;
}

// Usage example
class CredentialManager {
  private store: Awaited<ReturnType<typeof createSecureStore>> | null = null;

  async initialize(password: string, userId: string) {
    this.store = await createSecureStore(password, userId);
  }

  async storeCredentials(credentials: {
    accessToken: string;
    refreshToken: string;
    apiKeys?: Record<string, string>;
  }) {
    if (!this.store) throw new Error('Store not initialized');

    await this.store.setItems([
      { key: 'session-token', value: credentials.accessToken },
      { key: 'refresh-token', value: credentials.refreshToken },
      ...(credentials.apiKeys
        ? Object.entries(credentials.apiKeys).map(([name, key]) => ({
            key: `api-key:${name}`,
            value: key,
          }))
        : []),
    ]);
  }

  async getAccessToken(): Promise<string | null> {
    return this.store?.getItem('session-token') ?? null;
  }

  async getApiKey(name: string): Promise<string | null> {
    return this.store?.getItem(`api-key:${name}`) ?? null;
  }

  async logout() {
    if (this.store) {
      await this.store.clear();
      await this.store.close();
      this.store = null;
    }
  }
}

Offline-First Application Cache

Compressed API cache with intelligent expiration:

import localspace, { ttlPlugin, compressionPlugin } from 'localspace';

const apiCache = localspace.createInstance({
  name: 'offline-app',
  storeName: 'api-cache',
  plugins: [
    // Different TTLs for different data types
    ttlPlugin({
      defaultTTL: 5 * 60 * 1000, // 5 minutes for general API data
      keyTTL: {
        'api:/api/app-manifest': 24 * 60 * 60 * 1000, // 24 hours
        'api:/api/user/profile': 30 * 60 * 1000, // 30 minutes
        'api:/api/feed/home': 2 * 60 * 1000, // 2 minutes
      },
      cleanupInterval: 5 * 60 * 1000, // Cleanup every 5 minutes
      cleanupBatchSize: 200,
    }),

    // Compress large responses
    compressionPlugin({
      threshold: 2048, // Compress responses > 2KB
      algorithm: 'lz-string',
    }),
  ],
});

// Cache-aware fetch wrapper
async function cachedFetch<T>(
  url: string,
  options?: {
    cacheKey?: string;
    ttl?: number;
    skipCache?: boolean;
  }
): Promise<T> {
  const cacheKey = options?.cacheKey ?? `api:${url}`;

  // Check cache first
  if (!options?.skipCache) {
    const cached = await apiCache.getItem<CachedResponse<T>>(cacheKey);
    if (cached) {
      // Return cached data, optionally revalidate in background
      if (cached.staleAt && Date.now() > cached.staleAt) {
        // Stale-while-revalidate pattern
        revalidateInBackground(url, cacheKey);
      }
      return cached.data;
    }
  }

  // Fetch fresh data
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  const data = (await response.json()) as T;

  // Cache the response
  await apiCache.setItem(cacheKey, {
    data,
    fetchedAt: Date.now(),
    staleAt: Date.now() + (options?.ttl ?? 60_000), // Stale after 1 minute
  });

  return data;
}

async function revalidateInBackground(url: string, cacheKey: string) {
  try {
    const response = await fetch(url);
    if (response.ok) {
      const data = await response.json();
      await apiCache.setItem(cacheKey, {
        data,
        fetchedAt: Date.now(),
        staleAt: Date.now() + 60_000,
      });
    }
  } catch {
    // Silent failure for background revalidation
  }
}

interface CachedResponse<T> {
  data: T;
  fetchedAt: number;
  staleAt?: number;
}

// Prefetch common data
async function prefetchAppData() {
  const prefetchUrls = [
    '/api/user/profile',
    '/api/settings',
    '/api/notifications/count',
  ];

  await Promise.all(
    prefetchUrls.map((url) => cachedFetch(url).catch(() => null))
  );
}

// Clear cache on logout
async function clearCacheOnLogout() {
  await apiCache.clear();
}