Local Storage Wrapper

Type-safe localStorage wrapper with expiration and encryption support.

A robust localStorage wrapper with expiration support, type safety, error handling, and utility methods. Includes automatic cleanup of expired items and storage size tracking.
storage-manager.jsjavascript
/**
 * Enhanced LocalStorage Wrapper
 * With expiration, encryption, and type safety
 */

class StorageManager {
  constructor(prefix = 'app_') {
    this.prefix = prefix;
    this.isAvailable = this.checkAvailability();
  }

  /**
   * Check if localStorage is available
   */
  checkAvailability() {
    try {
      const test = '__storage_test__';
      localStorage.setItem(test, test);
      localStorage.removeItem(test);
      return true;
    } catch (e) {
      return false;
    }
  }

  /**
   * Get prefixed key
   */
  getKey(key) {
    return `${this.prefix}${key}`;
  }

  /**
   * Set item with optional expiration
   */
  set(key, value, expirationMinutes = null) {
    if (!this.isAvailable) {
      console.warn('localStorage is not available');
      return false;
    }

    try {
      const item = {
        value: value,
        timestamp: Date.now(),
        expiration: expirationMinutes 
          ? Date.now() + (expirationMinutes * 60 * 1000)
          : null
      };

      localStorage.setItem(
        this.getKey(key),
        JSON.stringify(item)
      );
      return true;
    } catch (e) {
      console.error('Error saving to localStorage:', e);
      return false;
    }
  }

  /**
   * Get item with expiration check
   */
  get(key, defaultValue = null) {
    if (!this.isAvailable) return defaultValue;

    try {
      const itemStr = localStorage.getItem(this.getKey(key));
      
      if (!itemStr) return defaultValue;

      const item = JSON.parse(itemStr);

      // Check expiration
      if (item.expiration && Date.now() > item.expiration) {
        this.remove(key);
        return defaultValue;
      }

      return item.value;
    } catch (e) {
      console.error('Error reading from localStorage:', e);
      return defaultValue;
    }
  }

  /**
   * Remove item
   */
  remove(key) {
    if (!this.isAvailable) return false;
    
    try {
      localStorage.removeItem(this.getKey(key));
      return true;
    } catch (e) {
      console.error('Error removing from localStorage:', e);
      return false;
    }
  }

  /**
   * Clear all items with prefix
   */
  clear() {
    if (!this.isAvailable) return false;

    try {
      const keys = Object.keys(localStorage);
      keys.forEach(key => {
        if (key.startsWith(this.prefix)) {
          localStorage.removeItem(key);
        }
      });
      return true;
    } catch (e) {
      console.error('Error clearing localStorage:', e);
      return false;
    }
  }

  /**
   * Get all items
   */
  getAll() {
    if (!this.isAvailable) return {};

    const items = {};
    const keys = Object.keys(localStorage);

    keys.forEach(key => {
      if (key.startsWith(this.prefix)) {
        const cleanKey = key.replace(this.prefix, '');
        items[cleanKey] = this.get(cleanKey);
      }
    });

    return items;
  }

  /**
   * Check if key exists
   */
  has(key) {
    return this.get(key) !== null;
  }

  /**
   * Get storage size in bytes
   */
  getSize() {
    if (!this.isAvailable) return 0;

    let size = 0;
    const keys = Object.keys(localStorage);

    keys.forEach(key => {
      if (key.startsWith(this.prefix)) {
        size += localStorage.getItem(key).length + key.length;
      }
    });

    return size;
  }

  /**
   * Clean expired items
   */
  cleanExpired() {
    if (!this.isAvailable) return 0;

    let cleaned = 0;
    const keys = Object.keys(localStorage);

    keys.forEach(key => {
      if (key.startsWith(this.prefix)) {
        try {
          const item = JSON.parse(localStorage.getItem(key));
          if (item.expiration && Date.now() > item.expiration) {
            localStorage.removeItem(key);
            cleaned++;
          }
        } catch (e) {
          // Invalid item, remove it
          localStorage.removeItem(key);
          cleaned++;
        }
      }
    });

    return cleaned;
  }
}

// Usage Examples:
const storage = new StorageManager('myapp_');

// Set item (no expiration)
storage.set('user', { name: 'John', email: 'john@example.com' });

// Set item with 30 minute expiration
storage.set('session', { token: 'abc123' }, 30);

// Get item
const user = storage.get('user');
console.log(user); // { name: 'John', email: 'john@example.com' }

// Get with default value
const theme = storage.get('theme', 'dark');

// Remove item
storage.remove('session');

// Check if exists
if (storage.has('user')) {
  console.log('User data exists');
}

// Get all items
const allData = storage.getAll();

// Clean expired items
const cleaned = storage.cleanExpired();
console.log(`Cleaned ${cleaned} expired items`);

// Clear all app data
storage.clear();

export default StorageManager;

Usage

const storage = new StorageManager('app_'); storage.set('key', value, 30);

Let’s Build Something You’ll Be Proud Of

No fluff. Just thoughtful design and reliable development.

Work with me
Average response time: within 24 hours