Last active
May 9, 2024 15:24
-
-
Save bureyburey/2345dfa88a31e00a514479be37848d42 to your computer and use it in GitHub Desktop.
SplitAsyncStorage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* custom wrapper for AsyncStorage that splits the data of a given storageKey to smaller chunks | |
* a large object with multiple keys will be spreaded to all the keys in the first level of the main object | |
* { data: { key1: value1, key2: value2, ...} } | |
* will be saved as key1 => value1, key2 => value2, ... | |
* this approach is intended to prevent the limitation of 2MB per value of AsyncStorage by spreading the values across the storage | |
* | |
* basic usage: | |
* | |
* import AsyncStorage from '@react-native-community/async-storage'; | |
* const storage = SplitAsyncStorage(AsyncStorage); | |
* | |
* @param storageProvider - a storage provider instance such as AsyncStorage | |
* @param options - optional options object, passing "storageKey" will control which key should be splitted, defaults to "apollo-cache-persist" | |
* @returns {{removeItem: removeItem, getItem: getItem, setItem: setItem}} | |
* @constructor | |
*/ | |
export default function SplitAsyncStorage(storageProvider, options = {}) { | |
if (!storageProvider) { | |
throw new Error('storageProvider is required!'); | |
} | |
// the STORAGE_KEY fallback to the default key used by apollo-cache-persist | |
// if that key is changed manually, then this key should be changed as well by passing {storageKey: 'your-storage-key'} as options | |
const STORAGE_KEY = options.storageKey || 'apollo-cache-persist'; | |
const STORAGE_KEY_KEYS = `${options.storageKey || STORAGE_KEY}-keys`; | |
return { | |
// spread all storageProvider methods | |
...storageProvider, | |
getItem: async (key) => { | |
// override getItem | |
let data; | |
if (key === STORAGE_KEY) { | |
// get all keys that needs to be extracted from the storage | |
const keys = await storageProvider.getItem(STORAGE_KEY_KEYS); | |
// get all the pieces of data | |
const splitData = await storageProvider.multiGet(JSON.parse(keys)); | |
data = {}; | |
// build the merged data object | |
for (let entry of splitData) { | |
if (typeof entry[1] === 'string') { | |
data[entry[0]] = JSON.parse(entry[1]); | |
} else { | |
data[entry[0]] = entry[1]; | |
} | |
} | |
// return the data | |
return data; | |
} | |
// default behaviour | |
data = await storageProvider.getItem(key); | |
if (typeof data === 'string') { | |
return JSON.parse(data); | |
} | |
return data; | |
}, | |
setItem: async (key, value) => { | |
// override setItem | |
let valueStr = value; | |
if (key === STORAGE_KEY) { | |
// parse the value if it isn't an object | |
let valueParsed = typeof value === 'object' ? value : JSON.parse(value); | |
// create an array of entries [[key1, value1], [key2, value2], ...] | |
const splitData = Object.entries(valueParsed); | |
// prepare the array of entries to be saved in the store | |
for (let entry of splitData) { | |
// stringify each value that is an object | |
if (typeof entry[1] === 'object') { | |
entry[1] = JSON.stringify(entry[1]); | |
} | |
} | |
// create an array of all the keys in the first level of the parsed value object and save it | |
const keys = Object.keys(valueParsed); | |
// store the values + the keys | |
return storageProvider.multiSet([...splitData, [STORAGE_KEY_KEYS, JSON.stringify(keys)]]); | |
} | |
// default behaviour | |
if (typeof valueStr === 'object') { | |
valueStr = JSON.stringify(value); | |
} | |
return storageProvider.setItem(key, valueStr); | |
}, | |
removeItem: async (key) => { | |
// override removeItem | |
if (key === STORAGE_KEY) { | |
// get all keys that needs to be removed from the storage | |
const keys = await storageProvider.getItem(STORAGE_KEY_KEYS); | |
// remove all data + the keys | |
return storageProvider.multiRemove([...JSON.parse(keys), STORAGE_KEY_KEYS]); | |
} | |
// default behaviour | |
return storageProvider.removeItem(key); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment