63 lines
2.5 KiB
JavaScript
63 lines
2.5 KiB
JavaScript
(function (root, factory) {
|
|
if (typeof module !== 'undefined' && module.exports) module.exports = factory;
|
|
else root.stackchainPrivateDeviceData = factory({
|
|
localStorage: root.localStorage,
|
|
sessionStorage: root.sessionStorage,
|
|
indexedDB: root.indexedDB,
|
|
caches: root.caches,
|
|
serviceWorker: root.navigator?.serviceWorker,
|
|
MessageChannel: root.MessageChannel,
|
|
});
|
|
})(typeof window !== 'undefined' ? window : this, function createPrivateDeviceDataPurger({
|
|
localStorage, sessionStorage, indexedDB, caches, serviceWorker, MessageChannel,
|
|
}) {
|
|
function removeOwnedStorage(storage) {
|
|
if (!storage) return;
|
|
const keys = [];
|
|
for (let index = 0; index < storage.length; index += 1) {
|
|
const key = storage.key(index);
|
|
if (key?.startsWith('stackchain.')) keys.push(key);
|
|
}
|
|
keys.forEach(key => storage.removeItem(key));
|
|
}
|
|
|
|
async function stopWorkerOutbox() {
|
|
const registration = await serviceWorker?.ready;
|
|
if (!registration?.active || !MessageChannel) return;
|
|
await new Promise((resolve, reject) => {
|
|
const channel = new MessageChannel();
|
|
const timeout = setTimeout(() => reject(new Error('Background outbox purge timed out.')), 3000);
|
|
channel.port1.onmessage = event => {
|
|
clearTimeout(timeout);
|
|
if (event.data?.ok) resolve();
|
|
else reject(new Error(event.data?.error || 'Background outbox purge failed.'));
|
|
};
|
|
registration.active.postMessage({ type: 'stackchain-purge-outbox' }, [channel.port2]);
|
|
});
|
|
}
|
|
|
|
function deletePrivateDatabase(name) {
|
|
if (!indexedDB) return Promise.resolve();
|
|
return new Promise((resolve, reject) => {
|
|
let request;
|
|
try { request = indexedDB.deleteDatabase(name); }
|
|
catch (error) { reject(error); return; }
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error || new Error('IndexedDB deletion failed.'));
|
|
request.onblocked = () => reject(new Error('IndexedDB deletion was blocked.'));
|
|
});
|
|
}
|
|
|
|
return async function clearPrivateDeviceData() {
|
|
removeOwnedStorage(localStorage);
|
|
if (sessionStorage !== localStorage) removeOwnedStorage(sessionStorage);
|
|
await stopWorkerOutbox();
|
|
await deletePrivateDatabase('stackchain-background-outbox-v1');
|
|
await deletePrivateDatabase('stackchain-offline-work-v2');
|
|
const keys = await caches?.keys?.() || [];
|
|
await Promise.all(
|
|
keys.filter(key => key.startsWith('stackchain-dashboard-')).map(key => caches.delete(key))
|
|
);
|
|
};
|
|
});
|