@cocalc/local-storage-lru
v2.5.0
Published
Simple LRU cache for a browser's localStorage
Downloads
597
Readme
LRU Cache for Browser's Local Storage
Problem
Saving an increasing number of key/value pairs in localStorage
causes it to fill up at some point.
From that point on, adding/modifying throws an exception.
Solution
Keep track of last n
recently accessed/modified keys.
If an exception occurs,
randomly remove a few keys which aren't in that list and also – optionally – only whitelisted ones.
Then try again storing the new value.
Benefits
- The entire overhead is one additional key/value pair storing the pointers to these LRU keys.
- The keys and values you try to store are not modified.
Design Goals
- robust: no exceptions are thrown (only if there is a problematic key)
- universal: also supports storing objects,
Date
,BigInt
, arrays etc.. - backwards compatible: if you already store string values, they're not modified. You can even tell it to attempt parsing existing JSON values.
Usage
This is how to instantiate the wrapper class.
Options:
recentKey
(optional): the string of the key, under which the list of recently accessed keys is stored.maxSize
(optional): the maximum number of keys to keep in the list of recently used keys. A larger list reduces the chances of deleting an "important" key, but at the same time, overall more storage is used.isCandidate
(optional): a function that takes a key and returnstrue
if the key is a candidate for deletion. By default, any key except for therecentKey
is a candidate. Optional second argument is the array of all recent keys.fallback
(optional, defaultfalse
): iftrue
,localStorage
is checked if it works. If not, data is stored in a mockup storage with limited space.serializer
(optional): by defaultJSON.stringify
, but you can use your own.deserializer
(optional): counterpart to the above, by defaultJSON.parse
.parseExistingJSON
(optional): iftrue
, it tries to deserialize already existing JSON values.typePrefixes
(optional): prefixes to serialized values if they're not stored a strings – somehow, we have to mark values if they are a complex object...typePrefixDelimiter
(optional): string appended to eachtypePrefix
to separate from the serialized value – default:\0
// simple:
const storage = new LocalStorageLRU();
// with options:
function candidate(key: string): boolean {
if (key.startsWith('preserved-')) {
return false;
}
return true;
}
const storage = new LocalStorageLRU({
recentKey: RECENTLY_KEY,
maxSize: RECENTLY_KEEP,
isCandidate: candidate,
fallback: true,
});
// set/get/delete
storage.set('foo', 'bar');
storage.get('foo') == 'bar'; // true
storage.delete('foo');
// iterate
storage.set('key1', '1');
storage.set('key2', '2');
storage.set('key3', '3');
const entries: [string, any][] = [];
for (const [k, v] of storage) {
entries.push([k, v]);
}
entries; // equals: [[ 'key1', '1' ], [ 'key2', '2' ], [ 'key3', '3' ]]
For more, check out the documentation or the tests.
Development
The setup follows this step-by-step guide.
Release
There are some hooks registered, see link above, to check for clean git tree, all tests passing and linting.
npm version patch
npm publish