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-universalFor 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-webUsage
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 valuesNumberValueStorageWrapper: For storing number valuesBooleanValueStorageWrapper: 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 safetyJsonValuesStorageWrapper<T>: For storing and manipulating arrays of JSON data with type safetyUint8ArrayValueStorageWrapper: 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-storageNativeSecureStorage: Secure storage usingexpo-secure-store
Web Platform
The expo-storage-universal-web package provides:
WebRegularStorage: Storage usingsessionStorageWebSecureStorage: Storage usingsessionStorage(Note: For truly secure storage, useNativeSecureStorageon native platforms)
License
MIT
