source: frontend/node_modules/workbox-background-sync/src/lib/QueueDb.ts

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

Fix frontend appearance

  • Property mode set to 100644
File size: 5.1 KB
RevLine 
[9af201e]1/*
2 Copyright 2021 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*/
8
9import {openDB, DBSchema, IDBPDatabase} from 'idb';
10import {RequestData} from './StorableRequest.js';
11import '../_version.js';
12
13interface QueueDBSchema extends DBSchema {
14 requests: {
15 key: number;
16 value: QueueStoreEntry;
17 indexes: {queueName: string};
18 };
19}
20
21const DB_VERSION = 3;
22const DB_NAME = 'workbox-background-sync';
23const REQUEST_OBJECT_STORE_NAME = 'requests';
24const QUEUE_NAME_INDEX = 'queueName';
25
26export interface UnidentifiedQueueStoreEntry {
27 requestData: RequestData;
28 timestamp: number;
29 id?: number;
30 queueName?: string;
31 // We could use Record<string, unknown> as a type but that would be a breaking
32 // change, better do it in next major release.
33 // eslint-disable-next-line @typescript-eslint/ban-types
34 metadata?: object;
35}
36
37export interface QueueStoreEntry extends UnidentifiedQueueStoreEntry {
38 id: number;
39}
40
41/**
42 * A class to interact directly an IndexedDB created specifically to save and
43 * retrieve QueueStoreEntries. This class encapsulates all the schema details
44 * to store the representation of a Queue.
45 *
46 * @private
47 */
48
49export class QueueDb {
50 private _db: IDBPDatabase<QueueDBSchema> | null = null;
51
52 /**
53 * Add QueueStoreEntry to underlying db.
54 *
55 * @param {UnidentifiedQueueStoreEntry} entry
56 */
57 async addEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {
58 const db = await this.getDb();
59 const tx = db.transaction(REQUEST_OBJECT_STORE_NAME, 'readwrite', {
60 durability: 'relaxed',
61 });
62 await tx.store.add(entry as QueueStoreEntry);
63 await tx.done;
64 }
65
66 /**
67 * Returns the first entry id in the ObjectStore.
68 *
69 * @return {number | undefined}
70 */
71 async getFirstEntryId(): Promise<number | undefined> {
72 const db = await this.getDb();
73 const cursor = await db
74 .transaction(REQUEST_OBJECT_STORE_NAME)
75 .store.openCursor();
76 return cursor?.value.id;
77 }
78
79 /**
80 * Get all the entries filtered by index
81 *
82 * @param queueName
83 * @return {Promise<QueueStoreEntry[]>}
84 */
85 async getAllEntriesByQueueName(
86 queueName: string,
87 ): Promise<QueueStoreEntry[]> {
88 const db = await this.getDb();
89 const results = await db.getAllFromIndex(
90 REQUEST_OBJECT_STORE_NAME,
91 QUEUE_NAME_INDEX,
92 IDBKeyRange.only(queueName),
93 );
94 return results ? results : new Array<QueueStoreEntry>();
95 }
96
97 /**
98 * Returns the number of entries filtered by index
99 *
100 * @param queueName
101 * @return {Promise<number>}
102 */
103 async getEntryCountByQueueName(queueName: string): Promise<number> {
104 const db = await this.getDb();
105 return db.countFromIndex(
106 REQUEST_OBJECT_STORE_NAME,
107 QUEUE_NAME_INDEX,
108 IDBKeyRange.only(queueName),
109 );
110 }
111
112 /**
113 * Deletes a single entry by id.
114 *
115 * @param {number} id the id of the entry to be deleted
116 */
117 async deleteEntry(id: number): Promise<void> {
118 const db = await this.getDb();
119 await db.delete(REQUEST_OBJECT_STORE_NAME, id);
120 }
121
122 /**
123 *
124 * @param queueName
125 * @returns {Promise<QueueStoreEntry | undefined>}
126 */
127 async getFirstEntryByQueueName(
128 queueName: string,
129 ): Promise<QueueStoreEntry | undefined> {
130 return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), 'next');
131 }
132
133 /**
134 *
135 * @param queueName
136 * @returns {Promise<QueueStoreEntry | undefined>}
137 */
138 async getLastEntryByQueueName(
139 queueName: string,
140 ): Promise<QueueStoreEntry | undefined> {
141 return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), 'prev');
142 }
143
144 /**
145 * Returns either the first or the last entries, depending on direction.
146 * Filtered by index.
147 *
148 * @param {IDBCursorDirection} direction
149 * @param {IDBKeyRange} query
150 * @return {Promise<QueueStoreEntry | undefined>}
151 * @private
152 */
153 async getEndEntryFromIndex(
154 query: IDBKeyRange,
155 direction: IDBCursorDirection,
156 ): Promise<QueueStoreEntry | undefined> {
157 const db = await this.getDb();
158
159 const cursor = await db
160 .transaction(REQUEST_OBJECT_STORE_NAME)
161 .store.index(QUEUE_NAME_INDEX)
162 .openCursor(query, direction);
163 return cursor?.value;
164 }
165
166 /**
167 * Returns an open connection to the database.
168 *
169 * @private
170 */
171 private async getDb() {
172 if (!this._db) {
173 this._db = await openDB(DB_NAME, DB_VERSION, {
174 upgrade: this._upgradeDb,
175 });
176 }
177 return this._db;
178 }
179
180 /**
181 * Upgrades QueueDB
182 *
183 * @param {IDBPDatabase<QueueDBSchema>} db
184 * @param {number} oldVersion
185 * @private
186 */
187 private _upgradeDb(db: IDBPDatabase<QueueDBSchema>, oldVersion: number) {
188 if (oldVersion > 0 && oldVersion < DB_VERSION) {
189 if (db.objectStoreNames.contains(REQUEST_OBJECT_STORE_NAME)) {
190 db.deleteObjectStore(REQUEST_OBJECT_STORE_NAME);
191 }
192 }
193
194 const objStore = db.createObjectStore(REQUEST_OBJECT_STORE_NAME, {
195 autoIncrement: true,
196 keyPath: 'id',
197 });
198 objStore.createIndex(QUEUE_NAME_INDEX, QUEUE_NAME_INDEX, {unique: false});
199 }
200}
Note: See TracBrowser for help on using the repository browser.