npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@vivtel/web-storage

v1.0.4

Published

Full-featured browser storage solution supporting localStorage, sessionStorage, and IndexedDB with React integration

Downloads

409

Readme

@vivtel/web-storage

A comprehensive, type-safe browser storage solution for modern web applications. Supports localStorage, sessionStorage, and IndexedDB with React integration, TypeScript support, TTL, and cross-tab synchronization.

Features

  • 🗄️ Multiple Storage Types: localStorage, sessionStorage, and IndexedDB
  • ⚛️ React Integration: Hooks and context provider for seamless React integration
  • 🔒 Type-Safe: Full TypeScript support with generic types
  • ⏱️ TTL Support: Automatic expiration for stored data
  • 🔄 Cross-Tab Sync: Automatic synchronization across browser tabs (localStorage)
  • 🎯 Simple API: Intuitive and consistent API across all storage types
  • 🔌 SSR-Safe: Server-side rendering compatible
  • 🎨 Flexible: Use with or without React

Installation

pnpm add @vivtel/web-storage

Quick Start

Vanilla JavaScript/TypeScript

import { StorageManager } from '@vivtel/web-storage';

// Create a storage manager
const storage = new StorageManager({
  driver: 'local_storage',
  prefix: 'myapp_',
  ttl: 3600, // Default 1 hour TTL
});

// Store data
await storage.set('user', { id: 1, name: 'John Doe' });

// Retrieve data
const user = await storage.get<User>('user');

// Remove data
await storage.remove('user');

React

import { StorageProvider, useLocalStorage } from '@vivtel/web-storage/react';

// 1. Wrap your app with StorageProvider
function App() {
  return (
    <StorageProvider
      config={{
        driver: 'local_storage',
        prefix: 'myapp_',
        ttl: 3600,
      }}
    >
      <YourApp />
    </StorageProvider>
  );
}

// 2. Use storage hooks in your components
function ThemeSelector() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');

  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
      Current theme: {theme}
    </button>
  );
}

Storage Types

LocalStorage

Best for: User preferences, settings, and persistent data across sessions.

const storage = new StorageManager({
  driver: 'local_storage',
  prefix: 'myapp_',
});

React Hook:

const [value, setValue, removeValue, loading, error] = useLocalStorage(
  'key',
  defaultValue
);

Features:

  • Persists across browser sessions
  • Cross-tab synchronization (React hook)
  • ~5-10MB storage limit

SessionStorage

Best for: Temporary session data, wizard forms, shopping carts.

const storage = new StorageManager({
  driver: 'session_storage',
  prefix: 'session_',
});

React Hook:

const [value, setValue, removeValue, loading, error] = useSessionStorage(
  'key',
  defaultValue
);

Features:

  • Clears when tab/window closes
  • Isolated per tab
  • ~5-10MB storage limit

IndexedDB

Best for: Large datasets, files, blobs, offline-first applications.

const storage = new StorageManager({
  driver: 'indexed_db',
  dbName: 'MyAppDB',
  storeName: 'cache',
});

React Hook:

const [value, setValue, removeValue, loading, error] = useIndexedDB(
  'key',
  defaultValue
);

Features:

  • Persists across browser sessions
  • High storage limits (hundreds of MB to GB)
  • Asynchronous API
  • Can store complex data types

API Reference

StorageManager

Main class for interacting with storage.

Constructor

new StorageManager(config: IStorageConfig)

Config Options:

interface IStorageConfig {
  driver: 'local_storage' | 'session_storage' | 'indexed_db';
  prefix?: string; // Key prefix (default: '')
  ttl?: number; // Default TTL in seconds

  // IndexedDB-specific options
  dbName?: string; // Database name (default: 'WebStorage')
  storeName?: string; // Object store name (default: 'storage')
  version?: number; // Database version (default: 1)

  // Custom serialization (optional)
  serializer?: (value: any) => string;
  deserializer?: (value: string) => any;
}

Methods

// Get value
async get<T>(key: string): Promise<T | null>

// Set value (with optional TTL)
async set<T>(key: string, value: T, ttl?: number): Promise<void>

// Remove value
async remove(key: string): Promise<void>

// Clear all values
async clear(): Promise<void>

// Check if key exists
async has(key: string): Promise<boolean>

// Get all keys
async keys(): Promise<string[]>

// Get storage size
async size(): Promise<number>

// Get or set (cache pattern)
async getOrSet<T>(
  key: string,
  defaultValue: () => T | Promise<T>,
  ttl?: number
): Promise<T>

// Batch operations
async setMany<T>(items: Record<string, T>, ttl?: number): Promise<void>
async getMany<T>(keys: string[]): Promise<Record<string, T | null>>
async removeMany(keys: string[]): Promise<void>

React Hooks

useLocalStorage

const [value, setValue, removeValue, loading, error] = useLocalStorage<T>(
  key: string,
  defaultValue: T
);

Features:

  • Automatic cross-tab synchronization
  • Component re-renders on storage changes

useSessionStorage

const [value, setValue, removeValue, loading, error] = useSessionStorage<T>(
  key: string,
  defaultValue: T
);

Features:

  • Session-scoped storage
  • Isolated per browser tab

useIndexedDB

const [value, setValue, removeValue, loading, error] = useIndexedDB<T>(
  key: string,
  defaultValue: T
);

Features:

  • High storage capacity
  • Efficient for large data

useStorage (Generic)

const [value, setValue, removeValue, loading, error] = useStorage<T>(
  key: string,
  defaultValue: T,
  storageManager?: StorageManager
);

Use case: When you need to dynamically choose storage type or use custom storage configuration.

StorageProvider

Provides storage context to React components.

<StorageProvider
  config={{
    driver: 'local_storage',
    prefix: 'app_',
  }}
  localStorageConfig={{ ttl: 86400 }}
  sessionStorageConfig={{ prefix: 'session_' }}
  indexedDBConfig={{ dbName: 'MyDB' }}
>
  {children}
</StorageProvider>

Examples

TTL (Time To Live)

// Set data with 1 hour TTL
await storage.set('session_token', token, 3600);

// Data expires automatically after 1 hour
const token = await storage.get('session_token'); // null after expiration

Cache Pattern

// Fetch from storage or compute if missing
const userData = await storage.getOrSet(
  'user_profile',
  async () => {
    const response = await fetch('/api/user');
    return response.json();
  },
  3600
); // Cache for 1 hour

Batch Operations

// Store multiple values at once
await storage.setMany({
  user_id: 123,
  username: 'john',
  email: '[email protected]',
});

// Get multiple values at once
const data = await storage.getMany(['user_id', 'username', 'email']);
console.log(data.username); // 'john'

Cross-Tab Synchronization (React)

// Component A in Tab 1
function ComponentA() {
  const [count, setCount] = useLocalStorage('counter', 0);

  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

// Component B in Tab 2 - automatically syncs!
function ComponentB() {
  const [count] = useLocalStorage('counter', 0);

  return <div>Current count: {count}</div>; // Updates when Tab 1 changes
}

Custom Storage Manager with React

function DataTable() {
  const { indexedDB } = useStorageContext();
  const [data, setData] = useStorage('api_cache', null, indexedDB);

  useEffect(() => {
    async function loadData() {
      if (!data) {
        const response = await fetch('/api/data');
        const result = await response.json();
        await setData(result, 3600); // Cache in IndexedDB for 1 hour
      }
    }
    loadData();
  }, []);

  return data ? <Table data={data} /> : 'Loading...';
}

Fallback Strategy

import { StorageFactory } from '@vivtel/web-storage';

// Try IndexedDB, fallback to localStorage if unavailable
const storage = StorageFactory.createWithFallback(
  { driver: 'indexed_db', dbName: 'MyDB' },
  { driver: 'local_storage', prefix: 'fallback_' }
);

SSR-Safe Usage

// Automatically handles server-side rendering
const storage = new StorageManager({
  driver: 'local_storage',
  prefix: 'app_',
});

// Safe to call on server - returns null gracefully
const value = await storage.get('key'); // null on server

TypeScript Support

Full TypeScript support with generic types:

interface User {
  id: number;
  name: string;
  email: string;
}

// Type-safe storage
const storage = new StorageManager({ driver: 'local_storage' });
await storage.set<User>('user', {
  id: 1,
  name: 'John',
  email: '[email protected]',
});
const user = await storage.get<User>('user'); // user is User | null

// Type-safe React hook
const [user, setUser] = useLocalStorage<User>('user', null);

Browser Support

  • localStorage/sessionStorage: All modern browsers
  • IndexedDB: Chrome 24+, Firefox 16+, Safari 10+, Edge 12+

The package automatically detects browser support and gracefully handles unsupported environments.

License

MIT

Contributing

Contributions are welcome! Please see the main repository for contribution guidelines.