This repository was archived by the owner on Nov 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBrowserCache.ts
More file actions
127 lines (114 loc) · 5.02 KB
/
BrowserCache.ts
File metadata and controls
127 lines (114 loc) · 5.02 KB
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
namespace AdvancedServiceWorker {
export class BrowserCache {
private readonly storageName: string;
constructor(name: string, version?: number) {
if (version) {
name += `-v${version}`;
}
this.storageName = name;
}
private open(): Promise<Cache> {
return caches.open(this.storageName);
}
remove(condition?: RegExp | String | string | string[]): Promise<boolean> {
if (!condition) {
// if there is no condition, delete the whole cache
return caches.delete(this.storageName);
} else if (
// ReSharper disable once SuspiciousInstanceofCheck
typeof condition === "string" ||
condition instanceof String ||
condition instanceof RegExp) {
// if there is a wildcard or regex condition, match and delete based on url
// first make sure that we have a regex condition
if (!(condition instanceof RegExp)) {
condition = Condition.wildCardToRegEx((condition) as string);
}
// now delete all matched requests
return this.open().then(cache => cache.keys().then(keys => {
const promises: Promise<boolean>[] = [];
keys.forEach(request => {
if (request.url && (condition as RegExp).test(request.url)) {
promises.push(cache.delete(request));
}
});
// return false if no request matched
if (!promises.length) {
return Promise.resolve(false);
}
// return true even if one request removed
return Promise.all(promises).then(results => {
for (let i: number = 0; i < results.length; i++) {
if (results[i]) {
return true;
}
}
return false;
},
() => false);
}));
} else if (condition instanceof Array && condition.length) {
// if there is a list of urls, request one by one
return this.open().then(cache => {
const promises: Promise<boolean>[] = [];
for (let i: number = 0; i < (condition as string[]).length; i++) {
promises.push(cache.delete((condition[i]) as string));
}
// return true even if one request removed
return Promise.all(promises).then(results => {
for (let j: number = 0; j < results.length; j++) {
if (results[j]) {
return true;
}
}
return false;
},
() => false);
});
} else {
// otherwise, return false
return Promise.resolve(false);
}
}
preloadUrls(urls: string[], version?: number): Promise<boolean> {
if (!urls) {
return Promise.resolve(false);
}
return this.open().then(
(cache: Cache) => cache.addAll(urls).then(
() => true,
() => {
console.error("Failed to add preload pages to cache.");
return false;
}),
() => {
console.error("Failed to open cache.");
return false;
});
}
putResponse(request: Request, response: Response): Promise<void> {
if (!response) {
throw new Error("Can not add an empty response to cache.");
}
// reject uncachable responses but dont throw an error
if (response.status !== 200 && // oK
response.status !== 204 && // no Content
response.status !== 300 && // multiple Choice
response.status !== 301 && // moved Permanently
response.status !== 303 && // see Other
response.status !== 308) { // permanent Redirect
return Promise.resolve();
}
return this.open().then(cache => cache.put(request, response));
}
getResponse(request: string | Request): Promise<Response> {
return this.open().then(
cache => cache.match(request).then((response: Response) => {
if (response) {
return response;
}
throw new Error("Cache contains empty response.");
}));
}
}
}