pianometer/lib.js

38 lines
1 KiB
JavaScript
Raw Normal View History

/**
* @template {Record<string, any>} T
* @param {string} keyPrefix
* @param {T} defaultState
* @returns {T}
*/
function State(keyPrefix, defaultState) {
/** @param {string} key */
function getFromRegistry(key) {
try {
// TODO validate type
const rawValue = localStorage.getItem(keyPrefix+key);
if (rawValue == null) return null;
return JSON.parse(rawValue);
} catch {
return null;
}
}
return new Proxy(/**@type T*/(Object.fromEntries(
Object.entries(defaultState)
.map(([k, v]) => [k, getFromRegistry(k) ?? v]),
)), {
get(cache, key) {
if (typeof key === 'symbol') return undefined;
// cache hit
if (key in cache) return cache[key];
// cache miss => get from localStorage
return /**@type{any}*/(cache)[key] = getFromRegistry(key);
},
set(cache, key, value) {
if (typeof key === 'symbol') return false;
/**@type{any}*/(cache)[key] = value;
localStorage.setItem(keyPrefix+key, JSON.stringify(value));
return true;
},
});
};