@discoveryjs/discovery
Version:
Frontend framework for rapid data (JSON) analysis, shareable serverless reports and dashboards
109 lines (108 loc) • 3.1 kB
JavaScript
import { Observer } from "../observer.js";
export const getSessionStorageEntry = /* @__PURE__ */ createStorageEntryFactory("sessionStorage");
export const getSessionStorageValue = /* @__PURE__ */ createStorageReader("sessionStorage");
export const getLocalStorageEntry = /* @__PURE__ */ createStorageEntryFactory("localStorage");
export const getLocalStorageValue = /* @__PURE__ */ createStorageReader("localStorage");
const storageMaps = /* @__PURE__ */ new Map();
function createStorageEntryFactory(type) {
const storage = getStorage(type);
const map = /* @__PURE__ */ new Map();
return function getOrCreateStorageEntry(key) {
let persistentKey = map.get(key);
if (persistentKey === void 0) {
persistentKey = new PersistentStorageEntry(storage, key);
map.set(key, persistentKey);
registerStorageMap(storage, map);
}
return persistentKey;
};
}
function createStorageReader(type) {
const storage = getStorage(type);
return function getStorageValue(key) {
return storage?.getItem(key) ?? null;
};
}
function getStorage(type) {
const key = "__storage_test__" + Math.random();
let storage;
try {
storage = window[type];
} catch {
return null;
}
try {
storage.setItem(key, key);
storage.removeItem(key);
} catch (e) {
const ok = e instanceof DOMException && // everything except Firefox
(e.code === 22 || // Firefox
e.code === 1014 || // test name field too, because code might not be present
// everything except Firefox
e.name === "QuotaExceededError" || // Firefox
e.name === "NS_ERROR_DOM_QUOTA_REACHED") && // acknowledge QuotaExceededError only if there's something already stored
storage.length !== 0;
if (!ok) {
return null;
}
}
return storage;
}
function registerStorageMap(storage, map) {
if (storage !== null && !storageMaps.has(storage)) {
storageMaps.set(storage, map);
if (storageMaps.size === 1) {
addEventListener("storage", (e) => {
const map2 = storageMaps.get(e.storageArea);
if (map2 !== void 0) {
const persistentKey = map2.get(e.key);
if (persistentKey) {
persistentKey.forceSync();
}
}
});
}
}
}
export class PersistentStorageEntry extends Observer {
#storage;
#key;
constructor(storage, key) {
super(storage?.getItem(key) ?? null);
this.#storage = storage;
this.#key = key;
}
#readStorageValue() {
return this.#storage?.getItem(this.#key) ?? null;
}
get storage() {
return this.#storage;
}
get key() {
return this.#key;
}
get() {
return this.value;
}
set(value) {
if (this.#storage) {
const storageValue = this.#readStorageValue();
if (value !== storageValue) {
this.#storage.setItem(this.#key, value);
return super.set(value);
}
}
return false;
}
delete() {
if (this.#storage) {
this.#storage.removeItem(this.#key);
}
}
forceSync() {
if (this.#storage) {
return super.set(this.#readStorageValue());
}
return false;
}
}