source: frontend/node_modules/workbox-expiration/models/CacheTimestampsModel.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 Copyright 2018 Google LLC
3
4 Use of this source code is governed by an MIT-style
5 license that can be found in the LICENSE file or at
6 https://opensource.org/licenses/MIT.
7*/
8import { openDB, deleteDB } from 'idb';
9import '../_version.js';
10const DB_NAME = 'workbox-expiration';
11const CACHE_OBJECT_STORE = 'cache-entries';
12const normalizeURL = (unNormalizedUrl) => {
13 const url = new URL(unNormalizedUrl, location.href);
14 url.hash = '';
15 return url.href;
16};
17/**
18 * Returns the timestamp model.
19 *
20 * @private
21 */
22class CacheTimestampsModel {
23 /**
24 *
25 * @param {string} cacheName
26 *
27 * @private
28 */
29 constructor(cacheName) {
30 this._db = null;
31 this._cacheName = cacheName;
32 }
33 /**
34 * Performs an upgrade of indexedDB.
35 *
36 * @param {IDBPDatabase<CacheDbSchema>} db
37 *
38 * @private
39 */
40 _upgradeDb(db) {
41 // TODO(philipwalton): EdgeHTML doesn't support arrays as a keyPath, so we
42 // have to use the `id` keyPath here and create our own values (a
43 // concatenation of `url + cacheName`) instead of simply using
44 // `keyPath: ['url', 'cacheName']`, which is supported in other browsers.
45 const objStore = db.createObjectStore(CACHE_OBJECT_STORE, { keyPath: 'id' });
46 // TODO(philipwalton): once we don't have to support EdgeHTML, we can
47 // create a single index with the keyPath `['cacheName', 'timestamp']`
48 // instead of doing both these indexes.
49 objStore.createIndex('cacheName', 'cacheName', { unique: false });
50 objStore.createIndex('timestamp', 'timestamp', { unique: false });
51 }
52 /**
53 * Performs an upgrade of indexedDB and deletes deprecated DBs.
54 *
55 * @param {IDBPDatabase<CacheDbSchema>} db
56 *
57 * @private
58 */
59 _upgradeDbAndDeleteOldDbs(db) {
60 this._upgradeDb(db);
61 if (this._cacheName) {
62 void deleteDB(this._cacheName);
63 }
64 }
65 /**
66 * @param {string} url
67 * @param {number} timestamp
68 *
69 * @private
70 */
71 async setTimestamp(url, timestamp) {
72 url = normalizeURL(url);
73 const entry = {
74 url,
75 timestamp,
76 cacheName: this._cacheName,
77 // Creating an ID from the URL and cache name won't be necessary once
78 // Edge switches to Chromium and all browsers we support work with
79 // array keyPaths.
80 id: this._getId(url),
81 };
82 const db = await this.getDb();
83 const tx = db.transaction(CACHE_OBJECT_STORE, 'readwrite', {
84 durability: 'relaxed',
85 });
86 await tx.store.put(entry);
87 await tx.done;
88 }
89 /**
90 * Returns the timestamp stored for a given URL.
91 *
92 * @param {string} url
93 * @return {number | undefined}
94 *
95 * @private
96 */
97 async getTimestamp(url) {
98 const db = await this.getDb();
99 const entry = await db.get(CACHE_OBJECT_STORE, this._getId(url));
100 return entry === null || entry === void 0 ? void 0 : entry.timestamp;
101 }
102 /**
103 * Iterates through all the entries in the object store (from newest to
104 * oldest) and removes entries once either `maxCount` is reached or the
105 * entry's timestamp is less than `minTimestamp`.
106 *
107 * @param {number} minTimestamp
108 * @param {number} maxCount
109 * @return {Array<string>}
110 *
111 * @private
112 */
113 async expireEntries(minTimestamp, maxCount) {
114 const db = await this.getDb();
115 let cursor = await db
116 .transaction(CACHE_OBJECT_STORE)
117 .store.index('timestamp')
118 .openCursor(null, 'prev');
119 const entriesToDelete = [];
120 let entriesNotDeletedCount = 0;
121 while (cursor) {
122 const result = cursor.value;
123 // TODO(philipwalton): once we can use a multi-key index, we
124 // won't have to check `cacheName` here.
125 if (result.cacheName === this._cacheName) {
126 // Delete an entry if it's older than the max age or
127 // if we already have the max number allowed.
128 if ((minTimestamp && result.timestamp < minTimestamp) ||
129 (maxCount && entriesNotDeletedCount >= maxCount)) {
130 // TODO(philipwalton): we should be able to delete the
131 // entry right here, but doing so causes an iteration
132 // bug in Safari stable (fixed in TP). Instead we can
133 // store the keys of the entries to delete, and then
134 // delete the separate transactions.
135 // https://github.com/GoogleChrome/workbox/issues/1978
136 // cursor.delete();
137 // We only need to return the URL, not the whole entry.
138 entriesToDelete.push(cursor.value);
139 }
140 else {
141 entriesNotDeletedCount++;
142 }
143 }
144 cursor = await cursor.continue();
145 }
146 // TODO(philipwalton): once the Safari bug in the following issue is fixed,
147 // we should be able to remove this loop and do the entry deletion in the
148 // cursor loop above:
149 // https://github.com/GoogleChrome/workbox/issues/1978
150 const urlsDeleted = [];
151 for (const entry of entriesToDelete) {
152 await db.delete(CACHE_OBJECT_STORE, entry.id);
153 urlsDeleted.push(entry.url);
154 }
155 return urlsDeleted;
156 }
157 /**
158 * Takes a URL and returns an ID that will be unique in the object store.
159 *
160 * @param {string} url
161 * @return {string}
162 *
163 * @private
164 */
165 _getId(url) {
166 // Creating an ID from the URL and cache name won't be necessary once
167 // Edge switches to Chromium and all browsers we support work with
168 // array keyPaths.
169 return this._cacheName + '|' + normalizeURL(url);
170 }
171 /**
172 * Returns an open connection to the database.
173 *
174 * @private
175 */
176 async getDb() {
177 if (!this._db) {
178 this._db = await openDB(DB_NAME, 1, {
179 upgrade: this._upgradeDbAndDeleteOldDbs.bind(this),
180 });
181 }
182 return this._db;
183 }
184}
185export { CacheTimestampsModel };
Note: See TracBrowser for help on using the repository browser.