jekyll-pwa-plugin 1.0.2 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jekyll-pwa-plugin.rb +18 -36
- data/lib/vendor/workbox-v3.3.1/workbox-background-sync.dev.js +593 -0
- data/lib/vendor/workbox-v3.3.1/workbox-background-sync.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-background-sync.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-background-sync.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-broadcast-cache-update.dev.js +395 -0
- data/lib/vendor/workbox-v3.3.1/workbox-broadcast-cache-update.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-broadcast-cache-update.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-broadcast-cache-update.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cache-expiration.dev.js +740 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cache-expiration.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cache-expiration.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cache-expiration.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cacheable-response.dev.js +236 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cacheable-response.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cacheable-response.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-cacheable-response.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-core.dev.js +1690 -0
- data/lib/vendor/workbox-v3.3.1/workbox-core.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-core.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-core.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-google-analytics.dev.js +255 -0
- data/lib/vendor/workbox-v3.3.1/workbox-google-analytics.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-google-analytics.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-google-analytics.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-precaching.dev.js +1149 -0
- data/lib/vendor/workbox-v3.3.1/workbox-precaching.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-precaching.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-precaching.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-range-requests.dev.js +299 -0
- data/lib/vendor/workbox-v3.3.1/workbox-range-requests.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-range-requests.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-range-requests.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-routing.dev.js +863 -0
- data/lib/vendor/workbox-v3.3.1/workbox-routing.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-routing.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-routing.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-strategies.dev.js +1091 -0
- data/lib/vendor/workbox-v3.3.1/workbox-strategies.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-strategies.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-strategies.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-streams.dev.js +390 -0
- data/lib/vendor/workbox-v3.3.1/workbox-streams.dev.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-streams.prod.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-streams.prod.js.map +1 -0
- data/lib/vendor/workbox-v3.3.1/workbox-sw.js +3 -0
- data/lib/vendor/workbox-v3.3.1/workbox-sw.js.map +1 -0
- metadata +48 -3
- data/lib/vendor/workbox-sw.prod.v2.1.1.js +0 -186
@@ -0,0 +1,740 @@
|
|
1
|
+
this.workbox = this.workbox || {};
|
2
|
+
this.workbox.expiration = (function (exports,DBWrapper_mjs,WorkboxError_mjs,assert_mjs,logger_mjs,cacheNames_mjs,quota_mjs) {
|
3
|
+
'use strict';
|
4
|
+
|
5
|
+
try {
|
6
|
+
self.workbox.v['workbox:cache-expiration:3.3.1'] = 1;
|
7
|
+
} catch (e) {} // eslint-disable-line
|
8
|
+
|
9
|
+
/*
|
10
|
+
Copyright 2017 Google Inc.
|
11
|
+
|
12
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
13
|
+
you may not use this file except in compliance with the License.
|
14
|
+
You may obtain a copy of the License at
|
15
|
+
|
16
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
|
18
|
+
Unless required by applicable law or agreed to in writing, software
|
19
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
20
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21
|
+
See the License for the specific language governing permissions and
|
22
|
+
limitations under the License.
|
23
|
+
*/
|
24
|
+
|
25
|
+
const URL_KEY = 'url';
|
26
|
+
const TIMESTAMP_KEY = 'timestamp';
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Returns the timestamp model.
|
30
|
+
*
|
31
|
+
* @private
|
32
|
+
*/
|
33
|
+
class CacheTimestampsModel {
|
34
|
+
/**
|
35
|
+
*
|
36
|
+
* @param {string} cacheName
|
37
|
+
*
|
38
|
+
* @private
|
39
|
+
*/
|
40
|
+
constructor(cacheName) {
|
41
|
+
// TODO Check cacheName
|
42
|
+
|
43
|
+
this._cacheName = cacheName;
|
44
|
+
this._storeName = cacheName;
|
45
|
+
|
46
|
+
this._db = new DBWrapper_mjs.DBWrapper(this._cacheName, 2, {
|
47
|
+
onupgradeneeded: evt => this._handleUpgrade(evt)
|
48
|
+
});
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Should perform an upgrade of indexedDB.
|
53
|
+
*
|
54
|
+
* @param {Event} evt
|
55
|
+
*
|
56
|
+
* @private
|
57
|
+
*/
|
58
|
+
_handleUpgrade(evt) {
|
59
|
+
const db = evt.target.result;
|
60
|
+
if (evt.oldVersion < 2) {
|
61
|
+
// Remove old databases.
|
62
|
+
if (db.objectStoreNames.contains('workbox-cache-expiration')) {
|
63
|
+
db.deleteObjectStore('workbox-cache-expiration');
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
db.createObjectStore(this._storeName, { keyPath: URL_KEY }).createIndex(TIMESTAMP_KEY, TIMESTAMP_KEY, { unique: false });
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* @param {string} url
|
72
|
+
* @param {number} timestamp
|
73
|
+
*
|
74
|
+
* @private
|
75
|
+
*/
|
76
|
+
setTimestamp(url, timestamp) {
|
77
|
+
var _this = this;
|
78
|
+
|
79
|
+
return babelHelpers.asyncToGenerator(function* () {
|
80
|
+
yield _this._db.put(_this._storeName, {
|
81
|
+
[URL_KEY]: new URL(url, location).href,
|
82
|
+
[TIMESTAMP_KEY]: timestamp
|
83
|
+
});
|
84
|
+
})();
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Get all of the timestamps in the indexedDB.
|
89
|
+
*
|
90
|
+
* @return {Array<Objects>}
|
91
|
+
*
|
92
|
+
* @private
|
93
|
+
*/
|
94
|
+
getAllTimestamps() {
|
95
|
+
var _this2 = this;
|
96
|
+
|
97
|
+
return babelHelpers.asyncToGenerator(function* () {
|
98
|
+
return yield _this2._db.getAllMatching(_this2._storeName, {
|
99
|
+
index: TIMESTAMP_KEY
|
100
|
+
});
|
101
|
+
})();
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* Returns the timestamp stored for a given URL.
|
106
|
+
*
|
107
|
+
* @param {string} url
|
108
|
+
* @return {number}
|
109
|
+
*
|
110
|
+
* @private
|
111
|
+
*/
|
112
|
+
getTimestamp(url) {
|
113
|
+
var _this3 = this;
|
114
|
+
|
115
|
+
return babelHelpers.asyncToGenerator(function* () {
|
116
|
+
const timestampObject = yield _this3._db.get(_this3._storeName, url);
|
117
|
+
return timestampObject.timestamp;
|
118
|
+
})();
|
119
|
+
}
|
120
|
+
|
121
|
+
/**
|
122
|
+
* @param {string} url
|
123
|
+
*
|
124
|
+
* @private
|
125
|
+
*/
|
126
|
+
deleteUrl(url) {
|
127
|
+
var _this4 = this;
|
128
|
+
|
129
|
+
return babelHelpers.asyncToGenerator(function* () {
|
130
|
+
yield _this4._db.delete(_this4._storeName, new URL(url, location).href);
|
131
|
+
})();
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
* Removes the underlying IndexedDB object store entirely.
|
136
|
+
*/
|
137
|
+
delete() {
|
138
|
+
var _this5 = this;
|
139
|
+
|
140
|
+
return babelHelpers.asyncToGenerator(function* () {
|
141
|
+
yield _this5._db.deleteDatabase();
|
142
|
+
_this5._db = null;
|
143
|
+
})();
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
/*
|
148
|
+
Copyright 2017 Google Inc.
|
149
|
+
|
150
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
151
|
+
you may not use this file except in compliance with the License.
|
152
|
+
You may obtain a copy of the License at
|
153
|
+
|
154
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
155
|
+
|
156
|
+
Unless required by applicable law or agreed to in writing, software
|
157
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
158
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
159
|
+
See the License for the specific language governing permissions and
|
160
|
+
limitations under the License.
|
161
|
+
*/
|
162
|
+
|
163
|
+
/**
|
164
|
+
* The `CacheExpiration` class allows you define an expiration and / or
|
165
|
+
* limit on the number of responses stored in a
|
166
|
+
* [`Cache`](https://developer.mozilla.org/en-US/docs/Web/API/Cache).
|
167
|
+
*
|
168
|
+
* @memberof workbox.expiration
|
169
|
+
*/
|
170
|
+
class CacheExpiration {
|
171
|
+
/**
|
172
|
+
* To construct a new CacheExpiration instance you must provide at least
|
173
|
+
* one of the `config` properties.
|
174
|
+
*
|
175
|
+
* @param {string} cacheName Name of the cache to apply restrictions to.
|
176
|
+
* @param {Object} config
|
177
|
+
* @param {number} [config.maxEntries] The maximum number of entries to cache.
|
178
|
+
* Entries used the least will be removed as the maximum is reached.
|
179
|
+
* @param {number} [config.maxAgeSeconds] The maximum age of an entry before
|
180
|
+
* it's treated as stale and removed.
|
181
|
+
*/
|
182
|
+
constructor(cacheName, config = {}) {
|
183
|
+
{
|
184
|
+
assert_mjs.assert.isType(cacheName, 'string', {
|
185
|
+
moduleName: 'workbox-cache-expiration',
|
186
|
+
className: 'CacheExpiration',
|
187
|
+
funcName: 'constructor',
|
188
|
+
paramName: 'cacheName'
|
189
|
+
});
|
190
|
+
|
191
|
+
if (!(config.maxEntries || config.maxAgeSeconds)) {
|
192
|
+
throw new WorkboxError_mjs.WorkboxError('max-entries-or-age-required', {
|
193
|
+
moduleName: 'workbox-cache-expiration',
|
194
|
+
className: 'CacheExpiration',
|
195
|
+
funcName: 'constructor'
|
196
|
+
});
|
197
|
+
}
|
198
|
+
|
199
|
+
if (config.maxEntries) {
|
200
|
+
assert_mjs.assert.isType(config.maxEntries, 'number', {
|
201
|
+
moduleName: 'workbox-cache-expiration',
|
202
|
+
className: 'CacheExpiration',
|
203
|
+
funcName: 'constructor',
|
204
|
+
paramName: 'config.maxEntries'
|
205
|
+
});
|
206
|
+
|
207
|
+
// TODO: Assert is positive
|
208
|
+
}
|
209
|
+
|
210
|
+
if (config.maxAgeSeconds) {
|
211
|
+
assert_mjs.assert.isType(config.maxAgeSeconds, 'number', {
|
212
|
+
moduleName: 'workbox-cache-expiration',
|
213
|
+
className: 'CacheExpiration',
|
214
|
+
funcName: 'constructor',
|
215
|
+
paramName: 'config.maxAgeSeconds'
|
216
|
+
});
|
217
|
+
|
218
|
+
// TODO: Assert is positive
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
this._isRunning = false;
|
223
|
+
this._rerunRequested = false;
|
224
|
+
this._maxEntries = config.maxEntries;
|
225
|
+
this._maxAgeSeconds = config.maxAgeSeconds;
|
226
|
+
this._cacheName = cacheName;
|
227
|
+
this._timestampModel = new CacheTimestampsModel(cacheName);
|
228
|
+
}
|
229
|
+
|
230
|
+
/**
|
231
|
+
* Expires entries for the given cache and given criteria.
|
232
|
+
*/
|
233
|
+
expireEntries() {
|
234
|
+
var _this = this;
|
235
|
+
|
236
|
+
return babelHelpers.asyncToGenerator(function* () {
|
237
|
+
if (_this._isRunning) {
|
238
|
+
_this._rerunRequested = true;
|
239
|
+
return;
|
240
|
+
}
|
241
|
+
_this._isRunning = true;
|
242
|
+
|
243
|
+
const now = Date.now();
|
244
|
+
|
245
|
+
// First, expire old entries, if maxAgeSeconds is set.
|
246
|
+
const oldEntries = yield _this._findOldEntries(now);
|
247
|
+
|
248
|
+
// Once that's done, check for the maximum size.
|
249
|
+
const extraEntries = yield _this._findExtraEntries();
|
250
|
+
|
251
|
+
// Use a Set to remove any duplicates following the concatenation, then
|
252
|
+
// convert back into an array.
|
253
|
+
const allUrls = [...new Set(oldEntries.concat(extraEntries))];
|
254
|
+
|
255
|
+
yield Promise.all([_this._deleteFromCache(allUrls), _this._deleteFromIDB(allUrls)]);
|
256
|
+
|
257
|
+
{
|
258
|
+
// TODO: break apart entries deleted due to expiration vs size restraints
|
259
|
+
if (allUrls.length > 0) {
|
260
|
+
logger_mjs.logger.groupCollapsed(`Expired ${allUrls.length} ` + `${allUrls.length === 1 ? 'entry' : 'entries'} and removed ` + `${allUrls.length === 1 ? 'it' : 'them'} from the ` + `'${_this._cacheName}' cache.`);
|
261
|
+
logger_mjs.logger.log(`Expired the following ${allUrls.length === 1 ? 'URL' : 'URLs'}:`);
|
262
|
+
allUrls.forEach(function (url) {
|
263
|
+
return logger_mjs.logger.log(` ${url}`);
|
264
|
+
});
|
265
|
+
logger_mjs.logger.groupEnd();
|
266
|
+
} else {
|
267
|
+
logger_mjs.logger.debug(`Cache expiration ran and found no entries to remove.`);
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
_this._isRunning = false;
|
272
|
+
if (_this._rerunRequested) {
|
273
|
+
_this._rerunRequested = false;
|
274
|
+
_this.expireEntries();
|
275
|
+
}
|
276
|
+
})();
|
277
|
+
}
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Expires entries based on the maximum age.
|
281
|
+
*
|
282
|
+
* @param {number} expireFromTimestamp A timestamp.
|
283
|
+
* @return {Promise<Array<string>>} A list of the URLs that were expired.
|
284
|
+
*
|
285
|
+
* @private
|
286
|
+
*/
|
287
|
+
_findOldEntries(expireFromTimestamp) {
|
288
|
+
var _this2 = this;
|
289
|
+
|
290
|
+
return babelHelpers.asyncToGenerator(function* () {
|
291
|
+
{
|
292
|
+
assert_mjs.assert.isType(expireFromTimestamp, 'number', {
|
293
|
+
moduleName: 'workbox-cache-expiration',
|
294
|
+
className: 'CacheExpiration',
|
295
|
+
funcName: '_findOldEntries',
|
296
|
+
paramName: 'expireFromTimestamp'
|
297
|
+
});
|
298
|
+
}
|
299
|
+
|
300
|
+
if (!_this2._maxAgeSeconds) {
|
301
|
+
return [];
|
302
|
+
}
|
303
|
+
|
304
|
+
const expireOlderThan = expireFromTimestamp - _this2._maxAgeSeconds * 1000;
|
305
|
+
const timestamps = yield _this2._timestampModel.getAllTimestamps();
|
306
|
+
const expiredUrls = [];
|
307
|
+
timestamps.forEach(function (timestampDetails) {
|
308
|
+
if (timestampDetails.timestamp < expireOlderThan) {
|
309
|
+
expiredUrls.push(timestampDetails.url);
|
310
|
+
}
|
311
|
+
});
|
312
|
+
|
313
|
+
return expiredUrls;
|
314
|
+
})();
|
315
|
+
}
|
316
|
+
|
317
|
+
/**
|
318
|
+
* @return {Promise<Array>}
|
319
|
+
*
|
320
|
+
* @private
|
321
|
+
*/
|
322
|
+
_findExtraEntries() {
|
323
|
+
var _this3 = this;
|
324
|
+
|
325
|
+
return babelHelpers.asyncToGenerator(function* () {
|
326
|
+
const extraUrls = [];
|
327
|
+
|
328
|
+
if (!_this3._maxEntries) {
|
329
|
+
return [];
|
330
|
+
}
|
331
|
+
|
332
|
+
const timestamps = yield _this3._timestampModel.getAllTimestamps();
|
333
|
+
while (timestamps.length > _this3._maxEntries) {
|
334
|
+
const lastUsed = timestamps.shift();
|
335
|
+
extraUrls.push(lastUsed.url);
|
336
|
+
}
|
337
|
+
|
338
|
+
return extraUrls;
|
339
|
+
})();
|
340
|
+
}
|
341
|
+
|
342
|
+
/**
|
343
|
+
* @param {Array<string>} urls Array of URLs to delete from cache.
|
344
|
+
*
|
345
|
+
* @private
|
346
|
+
*/
|
347
|
+
_deleteFromCache(urls) {
|
348
|
+
var _this4 = this;
|
349
|
+
|
350
|
+
return babelHelpers.asyncToGenerator(function* () {
|
351
|
+
const cache = yield caches.open(_this4._cacheName);
|
352
|
+
for (const url of urls) {
|
353
|
+
yield cache.delete(url);
|
354
|
+
}
|
355
|
+
})();
|
356
|
+
}
|
357
|
+
|
358
|
+
/**
|
359
|
+
* @param {Array<string>} urls Array of URLs to delete from IDB
|
360
|
+
*
|
361
|
+
* @private
|
362
|
+
*/
|
363
|
+
_deleteFromIDB(urls) {
|
364
|
+
var _this5 = this;
|
365
|
+
|
366
|
+
return babelHelpers.asyncToGenerator(function* () {
|
367
|
+
for (const url of urls) {
|
368
|
+
yield _this5._timestampModel.deleteUrl(url);
|
369
|
+
}
|
370
|
+
})();
|
371
|
+
}
|
372
|
+
|
373
|
+
/**
|
374
|
+
* Update the timestamp for the given URL. This ensures the when
|
375
|
+
* removing entries based on maximum entries, most recently used
|
376
|
+
* is accurate or when expiring, the timestamp is up-to-date.
|
377
|
+
*
|
378
|
+
* @param {string} url
|
379
|
+
*/
|
380
|
+
updateTimestamp(url) {
|
381
|
+
var _this6 = this;
|
382
|
+
|
383
|
+
return babelHelpers.asyncToGenerator(function* () {
|
384
|
+
{
|
385
|
+
assert_mjs.assert.isType(url, 'string', {
|
386
|
+
moduleName: 'workbox-cache-expiration',
|
387
|
+
className: 'CacheExpiration',
|
388
|
+
funcName: 'updateTimestamp',
|
389
|
+
paramName: 'url'
|
390
|
+
});
|
391
|
+
}
|
392
|
+
|
393
|
+
const urlObject = new URL(url, location);
|
394
|
+
urlObject.hash = '';
|
395
|
+
|
396
|
+
yield _this6._timestampModel.setTimestamp(urlObject.href, Date.now());
|
397
|
+
})();
|
398
|
+
}
|
399
|
+
|
400
|
+
/**
|
401
|
+
* Can be used to check if a URL has expired or not before it's used.
|
402
|
+
*
|
403
|
+
* This requires a look up from IndexedDB, so can be slow.
|
404
|
+
*
|
405
|
+
* Note: This method will not remove the cached entry, call
|
406
|
+
* `expireEntries()` to remove indexedDB and Cache entries.
|
407
|
+
*
|
408
|
+
* @param {string} url
|
409
|
+
* @return {boolean}
|
410
|
+
*/
|
411
|
+
isURLExpired(url) {
|
412
|
+
var _this7 = this;
|
413
|
+
|
414
|
+
return babelHelpers.asyncToGenerator(function* () {
|
415
|
+
if (!_this7._maxAgeSeconds) {
|
416
|
+
throw new WorkboxError_mjs.WorkboxError(`expired-test-without-max-age`, {
|
417
|
+
methodName: 'isURLExpired',
|
418
|
+
paramName: 'maxAgeSeconds'
|
419
|
+
});
|
420
|
+
}
|
421
|
+
const urlObject = new URL(url, location);
|
422
|
+
urlObject.hash = '';
|
423
|
+
|
424
|
+
const timestamp = yield _this7._timestampModel.getTimestamp(urlObject.href);
|
425
|
+
const expireOlderThan = Date.now() - _this7._maxAgeSeconds * 1000;
|
426
|
+
return timestamp < expireOlderThan;
|
427
|
+
})();
|
428
|
+
}
|
429
|
+
|
430
|
+
/**
|
431
|
+
* Removes the IndexedDB object store used to keep track of cache expiration
|
432
|
+
* metadata.
|
433
|
+
*/
|
434
|
+
delete() {
|
435
|
+
var _this8 = this;
|
436
|
+
|
437
|
+
return babelHelpers.asyncToGenerator(function* () {
|
438
|
+
// Make sure we don't attempt another rerun if we're called in the middle of
|
439
|
+
// a cache expiration.
|
440
|
+
_this8._rerunRequested = false;
|
441
|
+
yield _this8._timestampModel.delete();
|
442
|
+
})();
|
443
|
+
}
|
444
|
+
}
|
445
|
+
|
446
|
+
/*
|
447
|
+
Copyright 2016 Google Inc. All Rights Reserved.
|
448
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
449
|
+
you may not use this file except in compliance with the License.
|
450
|
+
You may obtain a copy of the License at
|
451
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
452
|
+
Unless required by applicable law or agreed to in writing, software
|
453
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
454
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
455
|
+
See the License for the specific language governing permissions and
|
456
|
+
limitations under the License.
|
457
|
+
*/
|
458
|
+
|
459
|
+
/**
|
460
|
+
* This plugin can be used in the Workbox APIs to regularly enforce a
|
461
|
+
* limit on the age and / or the number of cached requests.
|
462
|
+
*
|
463
|
+
* Whenever a cached request is used or updated, this plugin will look
|
464
|
+
* at the used Cache and remove any old or extra requests.
|
465
|
+
*
|
466
|
+
* When using `maxAgeSeconds`, requests may be used *once* after expiring
|
467
|
+
* because the expiration clean up will not have occurred until *after* the
|
468
|
+
* cached request has been used. If the request has a "Date" header, then
|
469
|
+
* a light weight expiration check is performed and the request will not be
|
470
|
+
* used immediately.
|
471
|
+
*
|
472
|
+
* When using `maxEntries`, the last request to be used will be the request
|
473
|
+
* that is removed from the Cache.
|
474
|
+
*
|
475
|
+
* @memberof workbox.expiration
|
476
|
+
*/
|
477
|
+
class Plugin {
|
478
|
+
/**
|
479
|
+
* @param {Object} config
|
480
|
+
* @param {number} [config.maxEntries] The maximum number of entries to cache.
|
481
|
+
* Entries used the least will be removed as the maximum is reached.
|
482
|
+
* @param {number} [config.maxAgeSeconds] The maximum age of an entry before
|
483
|
+
* it's treated as stale and removed.
|
484
|
+
* @param {boolean} [config.purgeOnQuotaError] Whether to opt this cache in to
|
485
|
+
* automatic deletion if the available storage quota has been exceeded.
|
486
|
+
*/
|
487
|
+
constructor(config = {}) {
|
488
|
+
{
|
489
|
+
if (!(config.maxEntries || config.maxAgeSeconds)) {
|
490
|
+
throw new WorkboxError_mjs.WorkboxError('max-entries-or-age-required', {
|
491
|
+
moduleName: 'workbox-cache-expiration',
|
492
|
+
className: 'Plugin',
|
493
|
+
funcName: 'constructor'
|
494
|
+
});
|
495
|
+
}
|
496
|
+
|
497
|
+
if (config.maxEntries) {
|
498
|
+
assert_mjs.assert.isType(config.maxEntries, 'number', {
|
499
|
+
moduleName: 'workbox-cache-expiration',
|
500
|
+
className: 'Plugin',
|
501
|
+
funcName: 'constructor',
|
502
|
+
paramName: 'config.maxEntries'
|
503
|
+
});
|
504
|
+
}
|
505
|
+
|
506
|
+
if (config.maxAgeSeconds) {
|
507
|
+
assert_mjs.assert.isType(config.maxAgeSeconds, 'number', {
|
508
|
+
moduleName: 'workbox-cache-expiration',
|
509
|
+
className: 'Plugin',
|
510
|
+
funcName: 'constructor',
|
511
|
+
paramName: 'config.maxAgeSeconds'
|
512
|
+
});
|
513
|
+
}
|
514
|
+
}
|
515
|
+
|
516
|
+
this._config = config;
|
517
|
+
this._maxAgeSeconds = config.maxAgeSeconds;
|
518
|
+
this._cacheExpirations = new Map();
|
519
|
+
|
520
|
+
if (config.purgeOnQuotaError) {
|
521
|
+
quota_mjs.registerQuotaErrorCallback(() => this.deleteCacheAndMetadata());
|
522
|
+
}
|
523
|
+
}
|
524
|
+
|
525
|
+
/**
|
526
|
+
* A simple helper method to return a CacheExpiration instance for a given
|
527
|
+
* cache name.
|
528
|
+
*
|
529
|
+
* @param {string} cacheName
|
530
|
+
* @return {CacheExpiration}
|
531
|
+
*
|
532
|
+
* @private
|
533
|
+
*/
|
534
|
+
_getCacheExpiration(cacheName) {
|
535
|
+
if (cacheName === cacheNames_mjs.cacheNames.getRuntimeName()) {
|
536
|
+
throw new WorkboxError_mjs.WorkboxError('expire-custom-caches-only');
|
537
|
+
}
|
538
|
+
|
539
|
+
let cacheExpiration = this._cacheExpirations.get(cacheName);
|
540
|
+
if (!cacheExpiration) {
|
541
|
+
cacheExpiration = new CacheExpiration(cacheName, this._config);
|
542
|
+
this._cacheExpirations.set(cacheName, cacheExpiration);
|
543
|
+
}
|
544
|
+
return cacheExpiration;
|
545
|
+
}
|
546
|
+
|
547
|
+
/**
|
548
|
+
* A "lifecycle" callback that will be triggered automatically by the
|
549
|
+
* `workbox.runtimeCaching` handlers when a `Response` is about to be returned
|
550
|
+
* from a [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) to
|
551
|
+
* the handler. It allows the `Response` to be inspected for freshness and
|
552
|
+
* prevents it from being used if the `Response`'s `Date` header value is
|
553
|
+
* older than the configured `maxAgeSeconds`.
|
554
|
+
*
|
555
|
+
* @param {Object} input
|
556
|
+
* @param {string} input.cacheName Name of the cache the responses belong to.
|
557
|
+
* @param {Response} input.cachedResponse The `Response` object that's been
|
558
|
+
* read from a cache and whose freshness should be checked.
|
559
|
+
* @return {Response} Either the `cachedResponse`, if it's
|
560
|
+
* fresh, or `null` if the `Response` is older than `maxAgeSeconds`.
|
561
|
+
*
|
562
|
+
* @private
|
563
|
+
*/
|
564
|
+
cachedResponseWillBeUsed({ cacheName, cachedResponse }) {
|
565
|
+
if (!cachedResponse) {
|
566
|
+
return null;
|
567
|
+
}
|
568
|
+
|
569
|
+
let isFresh = this._isResponseDateFresh(cachedResponse);
|
570
|
+
|
571
|
+
// Expire entries to ensure that even if the expiration date has
|
572
|
+
// expired, it'll only be used once.
|
573
|
+
const cacheExpiration = this._getCacheExpiration(cacheName);
|
574
|
+
cacheExpiration.expireEntries();
|
575
|
+
|
576
|
+
return isFresh ? cachedResponse : null;
|
577
|
+
}
|
578
|
+
|
579
|
+
/**
|
580
|
+
* @param {Response} cachedResponse
|
581
|
+
* @return {boolean}
|
582
|
+
*
|
583
|
+
* @private
|
584
|
+
*/
|
585
|
+
_isResponseDateFresh(cachedResponse) {
|
586
|
+
if (!this._maxAgeSeconds) {
|
587
|
+
// We aren't expiring by age, so return true, it's fresh
|
588
|
+
return true;
|
589
|
+
}
|
590
|
+
|
591
|
+
// Check if the 'date' header will suffice a quick expiration check.
|
592
|
+
// See https://github.com/GoogleChromeLabs/sw-toolbox/issues/164 for
|
593
|
+
// discussion.
|
594
|
+
const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);
|
595
|
+
if (dateHeaderTimestamp === null) {
|
596
|
+
// Unable to parse date, so assume it's fresh.
|
597
|
+
return true;
|
598
|
+
}
|
599
|
+
|
600
|
+
// If we have a valid headerTime, then our response is fresh iff the
|
601
|
+
// headerTime plus maxAgeSeconds is greater than the current time.
|
602
|
+
const now = Date.now();
|
603
|
+
return dateHeaderTimestamp >= now - this._maxAgeSeconds * 1000;
|
604
|
+
}
|
605
|
+
|
606
|
+
/**
|
607
|
+
* This method will extract the data header and parse it into a useful
|
608
|
+
* value.
|
609
|
+
*
|
610
|
+
* @param {Response} cachedResponse
|
611
|
+
* @return {number}
|
612
|
+
*
|
613
|
+
* @private
|
614
|
+
*/
|
615
|
+
_getDateHeaderTimestamp(cachedResponse) {
|
616
|
+
if (!cachedResponse.headers.has('date')) {
|
617
|
+
return null;
|
618
|
+
}
|
619
|
+
|
620
|
+
const dateHeader = cachedResponse.headers.get('date');
|
621
|
+
const parsedDate = new Date(dateHeader);
|
622
|
+
const headerTime = parsedDate.getTime();
|
623
|
+
|
624
|
+
// If the Date header was invalid for some reason, parsedDate.getTime()
|
625
|
+
// will return NaN.
|
626
|
+
if (isNaN(headerTime)) {
|
627
|
+
return null;
|
628
|
+
}
|
629
|
+
|
630
|
+
return headerTime;
|
631
|
+
}
|
632
|
+
|
633
|
+
/**
|
634
|
+
* A "lifecycle" callback that will be triggered automatically by the
|
635
|
+
* `workbox.runtimeCaching` handlers when an entry is added to a cache.
|
636
|
+
*
|
637
|
+
* @param {Object} input
|
638
|
+
* @param {string} input.cacheName Name of the cache the responses belong to.
|
639
|
+
* @param {string} input.request The Request for the cached entry.
|
640
|
+
*
|
641
|
+
* @private
|
642
|
+
*/
|
643
|
+
cacheDidUpdate({ cacheName, request }) {
|
644
|
+
var _this = this;
|
645
|
+
|
646
|
+
return babelHelpers.asyncToGenerator(function* () {
|
647
|
+
{
|
648
|
+
assert_mjs.assert.isType(cacheName, 'string', {
|
649
|
+
moduleName: 'workbox-cache-expiration',
|
650
|
+
className: 'Plugin',
|
651
|
+
funcName: 'cacheDidUpdate',
|
652
|
+
paramName: 'cacheName'
|
653
|
+
});
|
654
|
+
assert_mjs.assert.isInstance(request, Request, {
|
655
|
+
moduleName: 'workbox-cache-expiration',
|
656
|
+
className: 'Plugin',
|
657
|
+
funcName: 'cacheDidUpdate',
|
658
|
+
paramName: 'request'
|
659
|
+
});
|
660
|
+
}
|
661
|
+
|
662
|
+
const cacheExpiration = _this._getCacheExpiration(cacheName);
|
663
|
+
yield cacheExpiration.updateTimestamp(request.url);
|
664
|
+
yield cacheExpiration.expireEntries();
|
665
|
+
})();
|
666
|
+
}
|
667
|
+
|
668
|
+
/**
|
669
|
+
* This is a helper method that performs two operations:
|
670
|
+
*
|
671
|
+
* - Deletes *all* the underlying Cache instances associated with this plugin
|
672
|
+
* instance, by calling caches.delete() on you behalf.
|
673
|
+
* - Deletes the metadata from IndexedDB used to keep track of expiration
|
674
|
+
* details for each Cache instance.
|
675
|
+
*
|
676
|
+
* When using cache expiration, calling this method is preferable to calling
|
677
|
+
* `caches.delete()` directly, since this will ensure that the IndexedDB
|
678
|
+
* metadata is also cleanly removed and open IndexedDB instances are deleted.
|
679
|
+
*
|
680
|
+
* Note that if you're *not* using cache expiration for a given cache, calling
|
681
|
+
* `caches.delete()` and passing in the cache's name should be sufficient.
|
682
|
+
* There is no Workbox-specific method needed for cleanup in that case.
|
683
|
+
*/
|
684
|
+
deleteCacheAndMetadata() {
|
685
|
+
var _this2 = this;
|
686
|
+
|
687
|
+
return babelHelpers.asyncToGenerator(function* () {
|
688
|
+
// Do this one at a time instead of all at once via `Promise.all()` to
|
689
|
+
// reduce the chance of inconsistency if a promise rejects.
|
690
|
+
for (const [cacheName, cacheExpiration] of _this2._cacheExpirations) {
|
691
|
+
yield caches.delete(cacheName);
|
692
|
+
yield cacheExpiration.delete();
|
693
|
+
}
|
694
|
+
|
695
|
+
// Reset this._cacheExpirations to its initial state.
|
696
|
+
_this2._cacheExpirations = new Map();
|
697
|
+
})();
|
698
|
+
}
|
699
|
+
}
|
700
|
+
|
701
|
+
/*
|
702
|
+
Copyright 2017 Google Inc.
|
703
|
+
|
704
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
705
|
+
you may not use this file except in compliance with the License.
|
706
|
+
You may obtain a copy of the License at
|
707
|
+
|
708
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
709
|
+
|
710
|
+
Unless required by applicable law or agreed to in writing, software
|
711
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
712
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
713
|
+
See the License for the specific language governing permissions and
|
714
|
+
limitations under the License.
|
715
|
+
*/
|
716
|
+
|
717
|
+
/*
|
718
|
+
Copyright 2017 Google Inc.
|
719
|
+
|
720
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
721
|
+
you may not use this file except in compliance with the License.
|
722
|
+
You may obtain a copy of the License at
|
723
|
+
|
724
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
725
|
+
|
726
|
+
Unless required by applicable law or agreed to in writing, software
|
727
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
728
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
729
|
+
See the License for the specific language governing permissions and
|
730
|
+
limitations under the License.
|
731
|
+
*/
|
732
|
+
|
733
|
+
exports.CacheExpiration = CacheExpiration;
|
734
|
+
exports.Plugin = Plugin;
|
735
|
+
|
736
|
+
return exports;
|
737
|
+
|
738
|
+
}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private));
|
739
|
+
|
740
|
+
//# sourceMappingURL=workbox-cache-expiration.dev.js.map
|