jacobinathanialpeterson's picture
Upload 1035 files
1e40c2a
raw
history blame
5.11 kB
'use strict';
const OFFLINE_DATA_FILE = 'offline.json',
CACHE_NAME_PREFIX = 'c3offline',
BROADCASTCHANNEL_NAME = 'offline',
CONSOLE_PREFIX = '[SW] ',
LAZYLOAD_KEYNAME = '',
broadcastChannel =
'undefined' == typeof BroadcastChannel ? null : new BroadcastChannel('offline');
function PostBroadcastMessage(a) {
broadcastChannel && setTimeout(() => broadcastChannel.postMessage(a), 3e3);
}
function Broadcast(a) {
PostBroadcastMessage({ type: a });
}
function BroadcastDownloadingUpdate(a) {
PostBroadcastMessage({ type: 'downloading-update', version: a });
}
function BroadcastUpdateReady(a) {
PostBroadcastMessage({ type: 'update-ready', version: a });
}
function IsUrlInLazyLoadList(a, b) {
if (!b) return !1;
try {
for (const c of b) if (new RegExp(c).test(a)) return !0;
} catch (a) {
console.error('[SW] Error matching in lazy-load list: ', a);
}
return !1;
}
function WriteLazyLoadListToStorage(a) {
return 'undefined' == typeof localforage
? Promise.resolve()
: localforage.setItem(LAZYLOAD_KEYNAME, a);
}
function ReadLazyLoadListFromStorage() {
return 'undefined' == typeof localforage
? Promise.resolve([])
: localforage.getItem(LAZYLOAD_KEYNAME);
}
function GetCacheBaseName() {
return 'c3offline-' + self.registration.scope;
}
function GetCacheVersionName(a) {
return GetCacheBaseName() + '-v' + a;
}
async function GetAvailableCacheNames() {
const a = await caches.keys(),
b = GetCacheBaseName();
return a.filter((a) => a.startsWith(b));
}
async function IsUpdatePending() {
const a = await GetAvailableCacheNames();
return 2 <= a.length;
}
async function GetMainPageUrl() {
const a = await clients.matchAll({ includeUncontrolled: !0, type: 'window' });
for (const b of a) {
let a = b.url;
if (
(a.startsWith(self.registration.scope) && (a = a.substring(self.registration.scope.length)),
a && '/' !== a)
)
return a.startsWith('?') && (a = '/' + a), a;
}
return '';
}
function fetchWithBypass(a, b) {
return (
'string' == typeof a && (a = new Request(a)),
b
? fetch(a.url, {
headers: a.headers,
mode: a.mode,
credentials: a.credentials,
redirect: a.redirect,
cache: 'no-store'
})
: fetch(a)
);
}
async function CreateCacheFromFileList(a, b, c) {
const d = await Promise.all(b.map((a) => fetchWithBypass(a, c)));
let e = !0;
for (const f of d)
f.ok ||
((e = !1),
console.error("[SW] Error fetching '" + f.url + "' (" + f.status + ' ' + f.statusText + ')'));
if (!e) throw new Error('not all resources were fetched successfully');
const f = await caches.open(a);
try {
return await Promise.all(d.map((a, c) => f.put(b[c], a)));
} catch (b) {
throw (console.error('[SW] Error writing cache entries: ', b), caches.delete(a), b);
}
}
async function UpdateCheck(a) {
try {
const b = await fetchWithBypass(OFFLINE_DATA_FILE, !0);
if (!b.ok) throw new Error('offline.json responded with ' + b.status + ' ' + b.statusText);
const c = await b.json(),
d = c.version,
e = c.fileList,
f = c.lazyLoad,
g = GetCacheVersionName(d),
h = await caches.has(g);
if (h) {
const a = await IsUpdatePending();
return void (a
? (console.log('[SW] Update pending'), Broadcast('update-pending'))
: (console.log('[SW] Up to date'), Broadcast('up-to-date')));
}
const i = await GetMainPageUrl();
e.unshift('./'),
i && -1 === e.indexOf(i) && e.unshift(i),
console.log('[SW] Caching ' + e.length + ' files for offline use'),
a ? Broadcast('downloading') : BroadcastDownloadingUpdate(d),
f && (await WriteLazyLoadListToStorage(f)),
await CreateCacheFromFileList(g, e, !a);
const j = await IsUpdatePending();
j
? (console.log('[SW] All resources saved, update ready'), BroadcastUpdateReady(d))
: (console.log('[SW] All resources saved, offline support ready'),
Broadcast('offline-ready'));
} catch (a) {
console.warn('[SW] Update check failed: ', a);
}
}
self.addEventListener('install', (a) => {
a.waitUntil(UpdateCheck(!0).catch(() => null));
});
async function GetCacheNameToUse(a, b) {
if (1 === a.length || !b) return a[0];
const c = await clients.matchAll();
if (1 < c.length) return a[0];
const d = a[a.length - 1];
return (
console.log('[SW] Updating to new version'),
await Promise.all(a.slice(0, -1).map((a) => caches.delete(a))),
d
);
}
async function HandleFetch(a, b) {
const c = await GetAvailableCacheNames();
if (!c.length) return fetch(a.request);
const d = await GetCacheNameToUse(c, b),
e = await caches.open(d),
f = await e.match(a.request);
if (f) return f;
const g = await Promise.all([fetch(a.request), ReadLazyLoadListFromStorage()]),
h = g[0],
i = g[1];
if (IsUrlInLazyLoadList(a.request.url, i))
try {
await e.put(a.request, h.clone());
} catch (b) {
console.warn("[SW] Error caching '" + a.request.url + "': ", b);
}
return h;
}
self.addEventListener('fetch', (a) => {
if (new URL(a.request.url).origin === location.origin) {
const b = 'navigate' === a.request.mode,
c = HandleFetch(a, b);
b && a.waitUntil(c.then(() => UpdateCheck(!1))), a.respondWith(c);
}
});