/** * Storage Adapters * * @module @bytelyst/sync/storage */ import type { StorageAdapter } from './types.js'; // ───────────────────────────────────────────────────────────────────────────── // LocalStorage Adapter (Web) // ───────────────────────────────────────────────────────────────────────────── export class LocalStorageAdapter implements StorageAdapter { private prefix: string; constructor(prefix = 'bytelyst:sync:') { this.prefix = prefix; } getItem(key: string): T | null { if (typeof localStorage === 'undefined') return null; const value = localStorage.getItem(this.prefix + key); if (!value) return null; try { return JSON.parse(value) as T; } catch { return null; } } setItem(key: string, value: T): void { if (typeof localStorage === 'undefined') return; localStorage.setItem(this.prefix + key, JSON.stringify(value)); } removeItem(key: string): void { if (typeof localStorage === 'undefined') return; localStorage.removeItem(this.prefix + key); } keys(): string[] { if (typeof localStorage === 'undefined') return []; const keys: string[] = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && key.startsWith(this.prefix)) { keys.push(key.slice(this.prefix.length)); } } return keys; } } // ───────────────────────────────────────────────────────────────────────────── // In-Memory Adapter (Testing / SSR) // ───────────────────────────────────────────────────────────────────────────── export class InMemoryAdapter implements StorageAdapter { private store = new Map(); getItem(key: string): T | null { const value = this.store.get(key); return value !== undefined ? (value as T) : null; } setItem(key: string, value: T): void { this.store.set(key, value); } removeItem(key: string): void { this.store.delete(key); } keys(): string[] { return Array.from(this.store.keys()); } clear(): void { this.store.clear(); } } // ───────────────────────────────────────────────────────────────────────────── // MMKV Adapter Interface (React Native) // ───────────────────────────────────────────────────────────────────────────── export interface MMKVInstance { getString(key: string): string | undefined; set(key: string, value: string): void; delete(key: string): void; getAllKeys(): string[]; } export class MMKVAdapter implements StorageAdapter { private mmkv: MMKVInstance; private prefix: string; constructor(mmkv: MMKVInstance, prefix = 'sync:') { this.mmkv = mmkv; this.prefix = prefix; } getItem(key: string): T | null { const value = this.mmkv.getString(this.prefix + key); if (!value) return null; try { return JSON.parse(value) as T; } catch { return null; } } setItem(key: string, value: T): void { this.mmkv.set(this.prefix + key, JSON.stringify(value)); } removeItem(key: string): void { this.mmkv.delete(this.prefix + key); } keys(): string[] { return this.mmkv .getAllKeys() .filter(k => k.startsWith(this.prefix)) .map(k => k.slice(this.prefix.length)); } }