webext-storage
Version:
A more usable typed storage API for Web Extensions
71 lines (70 loc) • 3.03 kB
JavaScript
import chromeP from 'webext-polyfill-kinda';
export class StorageItemMap {
prefix;
areaName;
defaultValue;
constructor(key, { area = 'local', defaultValue, } = {}) {
this.prefix = `${key}:::`;
this.areaName = area;
this.defaultValue = defaultValue;
}
has = async (secondaryKey) => {
const rawStorageKey = this.getRawStorageKey(secondaryKey);
const result = await chromeP.storage[this.areaName].get(rawStorageKey);
// Do not use Object.hasOwn() due to https://github.com/RickyMarou/jest-webextension-mock/issues/20
return result[rawStorageKey] !== undefined;
};
get = async (secondaryKey) => {
const rawStorageKey = this.getRawStorageKey(secondaryKey);
const result = await chromeP.storage[this.areaName].get(rawStorageKey);
// Do not use Object.hasOwn() due to https://github.com/RickyMarou/jest-webextension-mock/issues/20
if (result[rawStorageKey] === undefined) {
return this.defaultValue;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return -- Assumes the user never uses the Storage API directly for this key
return result[rawStorageKey];
};
set = async (secondaryKey, value) => {
const rawStorageKey = this.getRawStorageKey(secondaryKey);
// eslint-disable-next-line unicorn/prefer-ternary -- ur rong
if (value === undefined) {
await chromeP.storage[this.areaName].remove(rawStorageKey);
}
else {
await chromeP.storage[this.areaName].set({ [rawStorageKey]: value });
}
};
remove = async (secondaryKey) => {
const rawStorageKey = this.getRawStorageKey(secondaryKey);
await chromeP.storage[this.areaName].remove(rawStorageKey);
};
/** @deprecated Only here to match the Map API; use `remove` instead */
// eslint-disable-next-line @typescript-eslint/member-ordering -- invalid
delete = this.remove;
onChanged(callback, signal) {
const changeHandler = (changes, area) => {
if (area !== this.areaName) {
return;
}
for (const rawKey of Object.keys(changes)) {
const secondaryKey = this.getSecondaryStorageKey(rawKey);
if (secondaryKey) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- Assumes the user never uses the Storage API directly
callback(secondaryKey, changes[rawKey].newValue);
}
}
};
chrome.storage.onChanged.addListener(changeHandler);
signal?.addEventListener('abort', () => {
chrome.storage.onChanged.removeListener(changeHandler);
}, {
once: true,
});
}
getRawStorageKey(secondaryKey) {
return this.prefix + secondaryKey;
}
getSecondaryStorageKey(rawKey) {
return rawKey.startsWith(this.prefix) && rawKey.slice(this.prefix.length);
}
}