UNPKG

react-native-mmkv

Version:

⚡️ The fastest key/value storage for React Native.

145 lines (144 loc) 5.11 kB
import { createTextDecoder } from '../web/createTextDecoder'; import { createTextEncoder } from '../web/createTextEncoder'; import { getLocalStorage, LOCAL_STORAGE_KEY_WILDCARD, } from '../web/getLocalStorage'; export function createMMKV(config = { id: 'mmkv.default' }) { if (config.encryptionKey != null) { throw new Error("MMKV: 'encryptionKey' is not supported on Web!"); } if (config.path != null) { throw new Error("MMKV: 'path' is not supported on Web!"); } const textDecoder = createTextDecoder(); const textEncoder = createTextEncoder(); const listeners = new Set(); if (config.id.includes(LOCAL_STORAGE_KEY_WILDCARD)) { throw new Error('MMKV: `id` cannot contain the backslash character (`\\`)!'); } const keyPrefix = `${config.id}${LOCAL_STORAGE_KEY_WILDCARD}`; // mmkv.default\\ const prefixedKey = (key) => { if (key.includes('\\')) { throw new Error('MMKV: `key` cannot contain the backslash character (`\\`)!'); } return `${keyPrefix}${key}`; }; const callListeners = (key) => { listeners.forEach((l) => l(key)); }; return { id: config.id, get length() { return getLocalStorage().length; }, get size() { return this.byteSize; }, get byteSize() { // estimate - assumes UTF8 return JSON.stringify(getLocalStorage()).length; }, isReadOnly: false, isEncrypted: false, clearAll: () => { const storage = getLocalStorage(); const keys = Object.keys(storage); for (const key of keys) { if (key.startsWith(keyPrefix)) { storage.removeItem(key); callListeners(key); } } }, remove: (key) => { const storage = getLocalStorage(); storage.removeItem(prefixedKey(key)); const wasRemoved = storage.getItem(prefixedKey(key)) === null; if (wasRemoved) callListeners(key); return wasRemoved; }, set: (key, value) => { const storage = getLocalStorage(); if (key === '') throw new Error('Cannot set a value for an empty key!'); if (value instanceof ArrayBuffer) { storage.setItem(prefixedKey(key), textDecoder.decode(value)); } else { storage.setItem(prefixedKey(key), String(value)); } callListeners(key); }, getString: (key) => { const storage = getLocalStorage(); return storage.getItem(prefixedKey(key)) ?? undefined; }, getNumber: (key) => { const storage = getLocalStorage(); const value = storage.getItem(prefixedKey(key)); if (value == null) return undefined; return Number(value); }, getBoolean: (key) => { const storage = getLocalStorage(); const value = storage.getItem(prefixedKey(key)); if (value == null) return undefined; return value === 'true'; }, getBuffer: (key) => { const storage = getLocalStorage(); const value = storage.getItem(prefixedKey(key)); if (value == null) return undefined; return textEncoder.encode(value).buffer; }, getAllKeys: () => { const storage = getLocalStorage(); const keys = Object.keys(storage); return keys .filter((key) => key.startsWith(keyPrefix)) .map((key) => key.slice(keyPrefix.length)); }, contains: (key) => { const storage = getLocalStorage(); return storage.getItem(prefixedKey(key)) != null; }, recrypt: () => { throw new Error('`recrypt(..)` is not supported on Web!'); }, encrypt: () => { throw new Error('`encrypt(..)` is not supported on Web!'); }, decrypt: () => { throw new Error('`decrypt(..)` is not supported on Web!'); }, trim: () => { // no-op }, dispose: () => { }, equals: () => false, name: 'MMKV', addOnValueChangedListener: (listener) => { listeners.add(listener); return { remove: () => { listeners.delete(listener); }, }; }, importAllFrom: (other) => { const storage = getLocalStorage(); const keys = other.getAllKeys(); let imported = 0; for (const key of keys) { const string = other.getString(key); if (string != null) { storage.set(key, string); imported++; } } return imported; }, }; }