forked from ficohra/hra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsw.js
156 lines (146 loc) · 5.36 KB
/
sw.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"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)
}
});