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 🙏

© 2026 – Pkg Stats / Ryan Hefner

expo-storage-universal

v0.3.8

Published

A universal storage implementation for Expo that works across all platforms. Features type-safe storage wrappers for strings and binary data.

Downloads

58

Readme

expo-storage-universal

A universal storage implementation for Expo that works across all platforms. This package provides a consistent interface for storage operations with type-safe wrappers for different data types.

Features

  • 🌐 Universal storage API that works across all platforms
  • 📦 Type-safe storage wrappers for different data types
  • 🔐 Base64 encoding support for binary data
  • 📱 Consistent interface across platforms
  • ⚡ Efficient storage format for each data type
  • 🔄 Array manipulation utilities for JSON collections

Installation

npm install expo-storage-universal

For platform-specific implementations, install the corresponding package:

# For native platforms (iOS/Android)
npm install expo-storage-universal-native

# For web platform
npm install expo-storage-universal-web

Usage

Getting Storage Instances

Platform-Specific Imports

import { Platform } from 'react-native';
import {
  WebRegularStorage,
  WebSecureStorage,
} from 'expo-storage-universal-web';
import {
  NativeRegularStorage,
  NativeSecureStorage,
} from 'expo-storage-universal-native';

// Conditionally create storage instances based on platform
const regularStorage =
  Platform.OS === 'web' ? new WebRegularStorage() : new NativeRegularStorage();
const secureStorage =
  Platform.OS === 'web' ? new WebSecureStorage() : new NativeSecureStorage();

Web Platform

import {
  WebRegularStorage,
  WebSecureStorage,
} from 'expo-storage-universal-web';

// For regular storage (non-secure)
const regularStorage = new WebRegularStorage();

// For secure storage
const secureStorage = new WebSecureStorage();

Native Platform (iOS/Android)

import {
  NativeRegularStorage,
  NativeSecureStorage,
} from 'expo-storage-universal-native';

// For regular storage (non-secure)
const regularStorage = new NativeRegularStorage();

// For secure storage
const secureStorage = new NativeSecureStorage();

Type-Safe Storage Wrappers

import {
  StringValueStorageWrapper,
  NumberValueStorageWrapper,
  BooleanValueStorageWrapper,
  DateValueStorageWrapper,
  JsonValueStorageWrapper,
  JsonValuesStorageWrapper,
  Uint8ArrayValueStorageWrapper,
} from 'expo-storage-universal';

// String value storage
const tokenStorage = new StringValueStorageWrapper(storage, 'auth-token');
await tokenStorage.save('abc123');
const token = await tokenStorage.retrieve(); // Throws if not found
const maybeToken = await tokenStorage.find(); // Returns undefined if not found

// String value storage with generic type
type UserRole = 'admin' | 'user' | 'guest';
const roleStorage = new StringValueStorageWrapper<UserRole>(
  storage,
  'user-role',
);
await roleStorage.save('admin'); // Type-safe: only 'admin', 'user', or 'guest' allowed
const role = await roleStorage.retrieve(); // Type is UserRole

// Number value storage
const countStorage = new NumberValueStorageWrapper(storage, 'counter');
await countStorage.save(42);
const count = await countStorage.retrieve();

// Boolean value storage (uses '1'/'0' for efficient storage)
const flagStorage = new BooleanValueStorageWrapper(storage, 'feature-flag');
await flagStorage.save(true);
const isEnabled = await flagStorage.retrieve();

// Date value storage (uses timestamp for efficient storage)
const lastLoginStorage = new DateValueStorageWrapper(storage, 'last-login');
await lastLoginStorage.save(new Date());
const lastLogin = await lastLoginStorage.retrieve();

// JSON value storage
const userStorage = new JsonValueStorageWrapper<User>(storage, 'user-data');
await userStorage.save({ id: 1, name: 'John' });
const user = await userStorage.retrieve();

// JSON array storage with collection utilities
interface User {
  id: number;
  name: string;
  active: boolean;
}

const compareById = (a: User, b: User) => a.id - b.id;
const usersStorage = new JsonValuesStorageWrapper<User>(
  storage,
  'users',
  compareById,
);

// Add a new user
await usersStorage.addItem({ id: 1, name: 'John', active: true });

// Update a user
await usersStorage.updateItem({ id: 1, name: 'Johnny', active: true });

// Update multiple users
await usersStorage.updateItems([
  { id: 1, name: 'Johnny', active: true },
  { id: 2, name: 'Jane', active: false },
]);

// Remove a user
await usersStorage.removeItem({ id: 1, name: 'Johnny', active: true });

// Remove multiple users
await usersStorage.removeItems([
  { id: 1, name: 'Johnny', active: true },
  { id: 2, name: 'Jane', active: false },
]);

// Filter active users
const activeUsers = await usersStorage.getItemsByFilter((user) => user.active);

// Sort users by name (using default comparison from constructor)
const sortedUsers = await usersStorage.sortItems();

// Sort users by name (using custom comparison)
const sortedByName = await usersStorage.sortItems((a, b) =>
  a.name.localeCompare(b.name),
);

// Binary data storage (automatically handles base64 encoding/decoding)
const binaryStorage = new Uint8ArrayValueStorageWrapper(storage, 'binary-data');
const data = new Uint8Array([1, 2, 3, 4, 5]);
await binaryStorage.save(data);
const retrievedData = await binaryStorage.retrieve();

API

Core Storage Interface

interface Storage {
  find(key: string): Promise<string | undefined>;
  save(key: string, value: string): Promise<void>;
  remove(key: string): Promise<void>;
}

StorageWrapper Interface

interface StorageWrapper<T> {
  find(): Promise<T | undefined>; // Returns undefined if not found
  retrieve(): Promise<T>; // Throws error if not found
  save(value: T): Promise<void>;
  remove(): Promise<void>;
}

Available Storage Wrappers

  • StringValueStorageWrapper: For storing string values
  • NumberValueStorageWrapper: For storing number values
  • BooleanValueStorageWrapper: For storing boolean values (uses '1'/'0' for efficient storage)
  • DateValueStorageWrapper: For storing Date values (uses timestamp for efficient storage)
  • JsonValueStorageWrapper<T>: For storing JSON data with type safety
  • JsonValuesStorageWrapper<T>: For storing and manipulating arrays of JSON data with type safety
  • Uint8ArrayValueStorageWrapper: For storing binary data (automatically handles base64 encoding/decoding)

JsonValuesStorageWrapper Methods

class JsonValuesStorageWrapper<T> extends JsonValueStorageWrapper<T[]> {
  constructor(
    storage: Storage,
    key: string,
    compareItem: (a: T, b: T) => number,
  );

  // Add a single item to the array
  addItem(item: T): Promise<void>;

  // Update a single item in the array
  updateItem(item: T): Promise<void>;

  // Update multiple items in the array
  updateItems(items: T[]): Promise<void>;

  // Remove a single item from the array
  removeItem(item: T): Promise<void>;

  // Remove multiple items from the array
  removeItems(items: T[]): Promise<void>;

  // Filter items in the array
  getItemsByFilter(filterItem: (item: T) => boolean): Promise<T[]>;

  // Sort items in the array (returns new array, doesn't modify storage)
  // If no comparison function is provided, uses the one from constructor
  sortItems(compareItem?: (a: T, b: T) => number): Promise<T[]>;
}

Storage Format Details

Each wrapper uses an optimized storage format:

  • String: Stored as-is
  • Number: Stored as string representation
  • Boolean: Stored as '1'/'0' for minimal storage usage
  • Date: Stored as timestamp (number) for efficient storage and parsing
  • JSON: Stored as stringified JSON
  • Binary: Stored as base64-encoded string

Platform-Specific Implementations

Native Platform (iOS/Android)

The expo-storage-universal-native package provides:

  • NativeRegularStorage: Non-secure storage using @react-native-async-storage/async-storage
  • NativeSecureStorage: Secure storage using expo-secure-store

Web Platform

The expo-storage-universal-web package provides:

  • WebRegularStorage: Storage using sessionStorage
  • WebSecureStorage: Storage using sessionStorage (Note: For truly secure storage, use NativeSecureStorage on native platforms)

License

MIT