Skip to main content

@54vie/storage - Persistent Storage

High-performance persistent storage using MMKV.

Installation

pnpm add @54vie/storage

Quick Start

import { StorageManager } from '@54vie/storage';

const storage = new StorageManager({ namespace: 'myapp' });

// Set value
await storage.set('user', { name: 'John', age: 25 });

// Get value
const user = await storage.get('user');

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

StorageManager

Constructor

const storage = new StorageManager({
namespace: 'myapp', // Isolated namespace
encryption: true, // Enable encryption (optional)
encryptionKey: 'secret', // Encryption key (if encryption enabled)
});

Methods

// Get value (returns undefined if not exists)
const value = await storage.get<T>('key');

// Get with default
const value = await storage.get('key', defaultValue);

// Set value (supports any serializable value)
await storage.set('key', value);

// Check if key exists
const exists = await storage.has('key');

// Remove key
await storage.remove('key');

// Clear all keys in namespace
await storage.clear();

// Get all keys
const keys = await storage.getAllKeys();

// Get multiple values
const values = await storage.getMultiple(['key1', 'key2']);

// Set multiple values
await storage.setMultiple({
key1: value1,
key2: value2,
});

Hooks

useStorage

import { useStorage } from '@54vie/storage';

function Settings() {
const [theme, setTheme] = useStorage('theme', 'light');

return (
<Switch
value={theme === 'dark'}
onValueChange={(dark) => setTheme(dark ? 'dark' : 'light')}
/>
);
}

useStorageItem

import { useStorageItem } from '@54vie/storage';

function Profile() {
const {
value: user,
setValue: setUser,
removeValue,
isLoading,
} = useStorageItem('user');

if (isLoading) return <Loading />;

return (
<View>
<Text>{user?.name}</Text>
<Button onPress={() => setUser({ ...user, name: 'New Name' })}>
Update
</Button>
<Button onPress={removeValue}>Logout</Button>
</View>
);
}

Typed Storage

interface UserSettings {
theme: 'light' | 'dark';
notifications: boolean;
language: string;
}

const settingsStorage = new StorageManager<UserSettings>({
namespace: 'settings',
});

// Type-safe get/set
const theme = await settingsStorage.get('theme'); // 'light' | 'dark' | undefined
await settingsStorage.set('theme', 'dark'); // Type checked

Encryption

const secureStorage = new StorageManager({
namespace: 'secure',
encryption: true,
});

// Values are encrypted at rest
await secureStorage.set('token', 'sensitive-data');
caution

Encryption adds overhead. Only use for sensitive data.

Migration

import { StorageManager, migrateStorage } from '@54vie/storage';

// Migrate from old storage
await migrateStorage({
from: new StorageManager({ namespace: 'v1' }),
to: new StorageManager({ namespace: 'v2' }),
transform: (key, value) => {
// Transform data if needed
return value;
},
});

Best Practices

1. Use namespaces

// ✅ Good - Separate concerns
const authStorage = new StorageManager({ namespace: 'auth' });
const cacheStorage = new StorageManager({ namespace: 'cache' });

// ❌ Bad - Everything in one place
const storage = new StorageManager({ namespace: 'app' });

2. Type your data

// ✅ Good
interface CartItem {
id: string;
quantity: number;
}
const cart = await storage.get<CartItem[]>('cart');

// ❌ Bad
const cart = await storage.get('cart'); // any