Skip to content

Commit 9c5c9c3

Browse files
authored
Use idb 7 for products using shared idb library (#6154)
1 parent 5c92d9c commit 9c5c9c3

File tree

16 files changed

+112
-290
lines changed

16 files changed

+112
-290
lines changed

.changeset/four-steaks-relate.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@firebase/util': minor
3+
'@firebase/app': patch
4+
'@firebase/installations': patch
5+
'@firebase/messaging': patch
6+
---
7+
8+
Replace stopgap firebase/util IndexedDB methods with `idb` library.

common/api-review/util.api.md

-29
Original file line numberDiff line numberDiff line change
@@ -87,25 +87,6 @@ export function createMockUserToken(token: EmulatorMockTokenOptions, projectId?:
8787
// @public
8888
export function createSubscribe<T>(executor: Executor<T>, onNoObservers?: Executor<T>): Subscribe<T>;
8989

90-
// Warning: (ae-internal-missing-underscore) The name "DBWrapper" should be prefixed with an underscore because the declaration is marked as @internal
91-
//
92-
// @internal (undocumented)
93-
export class DBWrapper {
94-
constructor(_db: IDBDatabase);
95-
// (undocumented)
96-
close(): void;
97-
// Warning: (ae-forgotten-export) The symbol "ObjectStoreWrapper" needs to be exported by the entry point index.d.ts
98-
//
99-
// (undocumented)
100-
createObjectStore(storeName: string, options?: IDBObjectStoreParameters): ObjectStoreWrapper;
101-
// (undocumented)
102-
objectStoreNames: DOMStringList;
103-
// Warning: (ae-forgotten-export) The symbol "TransactionWrapper" needs to be exported by the entry point index.d.ts
104-
//
105-
// (undocumented)
106-
transaction(storeNames: string[] | string, mode?: IDBTransactionMode): TransactionWrapper;
107-
}
108-
10990
// Warning: (ae-forgotten-export) The symbol "DecodedToken" needs to be exported by the entry point index.d.ts
11091
// Warning: (ae-missing-release-tag) "decode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
11192
//
@@ -141,11 +122,6 @@ export class Deferred<R> {
141122
wrapCallback(callback?: (error?: unknown, value?: unknown) => void): (error: unknown, value?: unknown) => void;
142123
}
143124

144-
// Warning: (ae-internal-missing-underscore) The name "deleteDB" should be prefixed with an underscore because the declaration is marked as @internal
145-
//
146-
// @internal (undocumented)
147-
export function deleteDB(dbName: string): Promise<void>;
148-
149125
// Warning: (ae-forgotten-export) The symbol "FirebaseIdToken" needs to be exported by the entry point index.d.ts
150126
// Warning: (ae-missing-release-tag) "EmulatorMockTokenOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
151127
//
@@ -360,11 +336,6 @@ export interface Observer<T> {
360336
next: NextFn<T>;
361337
}
362338

363-
// Warning: (ae-internal-missing-underscore) The name "openDB" should be prefixed with an underscore because the declaration is marked as @internal
364-
//
365-
// @internal (undocumented)
366-
export function openDB(dbName: string, dbVersion: number, upgradeCallback: (db: DBWrapper, oldVersion: number, newVersion: number | null, transaction: TransactionWrapper) => void): Promise<DBWrapper>;
367-
368339
// Warning: (ae-missing-release-tag) "ordinal" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
369340
//
370341
// @public

packages/app/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@
4040
"@firebase/util": "1.5.2",
4141
"@firebase/logger": "0.3.2",
4242
"@firebase/component": "0.5.13",
43+
"idb": "7.0.1",
4344
"tslib": "^2.1.0"
4445
},
4546
"license": "Apache-2.0",
4647
"devDependencies": {
47-
"rollup": "2.57.0",
4848
"@rollup/plugin-json": "4.1.0",
49+
"rollup": "2.57.0",
4950
"rollup-plugin-replace": "2.2.0",
5051
"rollup-plugin-typescript2": "0.30.0",
5152
"typescript": "4.2.2"
@@ -65,4 +66,4 @@
6566
],
6667
"reportDir": "./coverage/node"
6768
}
68-
}
69+
}

packages/app/src/indexeddb.ts

+23-13
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,36 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { DBWrapper, openDB } from '@firebase/util';
18+
import { DBSchema, openDB, IDBPDatabase } from 'idb';
1919
import { AppError, ERROR_FACTORY } from './errors';
2020
import { FirebaseApp } from './public-types';
2121
import { HeartbeatsInIndexedDB } from './types';
22+
2223
const DB_NAME = 'firebase-heartbeat-database';
2324
const DB_VERSION = 1;
2425
const STORE_NAME = 'firebase-heartbeat-store';
2526

26-
let dbPromise: Promise<DBWrapper> | null = null;
27-
function getDbPromise(): Promise<DBWrapper> {
27+
interface AppDB extends DBSchema {
28+
'firebase-heartbeat-store': {
29+
key: string;
30+
value: HeartbeatsInIndexedDB;
31+
};
32+
}
33+
34+
let dbPromise: Promise<IDBPDatabase<AppDB>> | null = null;
35+
function getDbPromise(): Promise<IDBPDatabase<AppDB>> {
2836
if (!dbPromise) {
29-
dbPromise = openDB(DB_NAME, DB_VERSION, (db, oldVersion) => {
30-
// We don't use 'break' in this switch statement, the fall-through
31-
// behavior is what we want, because if there are multiple versions between
32-
// the old version and the current version, we want ALL the migrations
33-
// that correspond to those versions to run, not only the last one.
34-
// eslint-disable-next-line default-case
35-
switch (oldVersion) {
36-
case 0:
37-
db.createObjectStore(STORE_NAME);
37+
dbPromise = openDB<AppDB>(DB_NAME, DB_VERSION, {
38+
upgrade: (db, oldVersion) => {
39+
// We don't use 'break' in this switch statement, the fall-through
40+
// behavior is what we want, because if there are multiple versions between
41+
// the old version and the current version, we want ALL the migrations
42+
// that correspond to those versions to run, not only the last one.
43+
// eslint-disable-next-line default-case
44+
switch (oldVersion) {
45+
case 0:
46+
db.createObjectStore(STORE_NAME);
47+
}
3848
}
3949
}).catch(e => {
4050
throw ERROR_FACTORY.create(AppError.STORAGE_OPEN, {
@@ -70,7 +80,7 @@ export async function writeHeartbeatsToIndexedDB(
7080
const tx = db.transaction(STORE_NAME, 'readwrite');
7181
const objectStore = tx.objectStore(STORE_NAME);
7282
await objectStore.put(heartbeatObject, computeKey(app));
73-
return tx.complete;
83+
return tx.done;
7484
} catch (e) {
7585
throw ERROR_FACTORY.create(AppError.STORAGE_WRITE, {
7686
originalErrorMessage: e.message

packages/installations/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"dependencies": {
6565
"@firebase/util": "1.5.2",
6666
"@firebase/component": "0.5.13",
67+
"idb": "7.0.1",
6768
"tslib": "^2.1.0"
6869
}
6970
}

packages/installations/src/helpers/idb-manager.ts

+25-16
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { DBWrapper, openDB } from '@firebase/util';
18+
import { DBSchema, IDBPDatabase, openDB } from 'idb';
1919
import { AppConfig } from '../interfaces/installation-impl';
2020
import { InstallationEntry } from '../interfaces/installation-entry';
2121
import { getKey } from '../util/get-key';
@@ -25,18 +25,27 @@ const DATABASE_NAME = 'firebase-installations-database';
2525
const DATABASE_VERSION = 1;
2626
const OBJECT_STORE_NAME = 'firebase-installations-store';
2727

28-
let dbPromise: Promise<DBWrapper> | null = null;
29-
function getDbPromise(): Promise<DBWrapper> {
28+
interface InstallationsDB extends DBSchema {
29+
'firebase-installations-store': {
30+
key: string;
31+
value: InstallationEntry | undefined;
32+
};
33+
}
34+
35+
let dbPromise: Promise<IDBPDatabase<InstallationsDB>> | null = null;
36+
function getDbPromise(): Promise<IDBPDatabase<InstallationsDB>> {
3037
if (!dbPromise) {
31-
dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, (db, oldVersion) => {
32-
// We don't use 'break' in this switch statement, the fall-through
33-
// behavior is what we want, because if there are multiple versions between
34-
// the old version and the current version, we want ALL the migrations
35-
// that correspond to those versions to run, not only the last one.
36-
// eslint-disable-next-line default-case
37-
switch (oldVersion) {
38-
case 0:
39-
db.createObjectStore(OBJECT_STORE_NAME);
38+
dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {
39+
upgrade: (db, oldVersion) => {
40+
// We don't use 'break' in this switch statement, the fall-through
41+
// behavior is what we want, because if there are multiple versions between
42+
// the old version and the current version, we want ALL the migrations
43+
// that correspond to those versions to run, not only the last one.
44+
// eslint-disable-next-line default-case
45+
switch (oldVersion) {
46+
case 0:
47+
db.createObjectStore(OBJECT_STORE_NAME);
48+
}
4049
}
4150
});
4251
}
@@ -66,7 +75,7 @@ export async function set<ValueType extends InstallationEntry>(
6675
const objectStore = tx.objectStore(OBJECT_STORE_NAME);
6776
const oldValue = (await objectStore.get(key)) as InstallationEntry;
6877
await objectStore.put(value, key);
69-
await tx.complete;
78+
await tx.done;
7079

7180
if (!oldValue || oldValue.fid !== value.fid) {
7281
fidChanged(appConfig, value.fid);
@@ -81,7 +90,7 @@ export async function remove(appConfig: AppConfig): Promise<void> {
8190
const db = await getDbPromise();
8291
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
8392
await tx.objectStore(OBJECT_STORE_NAME).delete(key);
84-
await tx.complete;
93+
await tx.done;
8594
}
8695

8796
/**
@@ -108,7 +117,7 @@ export async function update<ValueType extends InstallationEntry | undefined>(
108117
} else {
109118
await store.put(newValue, key);
110119
}
111-
await tx.complete;
120+
await tx.done;
112121

113122
if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
114123
fidChanged(appConfig, newValue.fid);
@@ -121,5 +130,5 @@ export async function clear(): Promise<void> {
121130
const db = await getDbPromise();
122131
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
123132
await tx.objectStore(OBJECT_STORE_NAME).clear();
124-
await tx.complete;
133+
await tx.done;
125134
}

packages/messaging/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"@firebase/messaging-interop-types": "0.1.0",
5757
"@firebase/util": "1.5.2",
5858
"@firebase/component": "0.5.13",
59+
"idb": "7.0.1",
5960
"tslib": "^2.1.0"
6061
},
6162
"devDependencies": {

packages/messaging/src/helpers/migrate-old-database.test.ts

+13-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { FakePushSubscription } from '../testing/fakes/service-worker';
2828
import { base64ToArray } from './array-base64-translator';
2929
import { expect } from 'chai';
3030
import { getFakeTokenDetails } from '../testing/fakes/token-details';
31-
import { openDB } from '@firebase/util';
31+
import { openDB } from 'idb';
3232

3333
describe('migrateOldDb', () => {
3434
it("does nothing if old DB didn't exist", async () => {
@@ -179,22 +179,24 @@ describe('migrateOldDb', () => {
179179
});
180180

181181
async function put(version: number, value: object): Promise<void> {
182-
const db = await openDB('fcm_token_details_db', version, (db, oldVersion) => {
183-
if (oldVersion === 0) {
184-
const objectStore = db.createObjectStore('fcm_token_object_Store', {
185-
keyPath: 'swScope'
186-
});
187-
objectStore.createIndex('fcmSenderId', 'fcmSenderId', {
188-
unique: false
189-
});
190-
objectStore.createIndex('fcmToken', 'fcmToken', { unique: true });
182+
const db = await openDB('fcm_token_details_db', version, {
183+
upgrade: (db, oldVersion) => {
184+
if (oldVersion === 0) {
185+
const objectStore = db.createObjectStore('fcm_token_object_Store', {
186+
keyPath: 'swScope'
187+
});
188+
objectStore.createIndex('fcmSenderId', 'fcmSenderId', {
189+
unique: false
190+
});
191+
objectStore.createIndex('fcmToken', 'fcmToken', { unique: true });
192+
}
191193
}
192194
});
193195

194196
try {
195197
const tx = db.transaction('fcm_token_object_Store', 'readwrite');
196198
await tx.objectStore('fcm_token_object_Store').put(value);
197-
await tx.complete;
199+
await tx.done;
198200
} finally {
199201
db.close();
200202
}

packages/messaging/src/helpers/migrate-old-database.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { deleteDB, openDB } from '@firebase/util';
18+
import { deleteDB, openDB } from 'idb';
1919

2020
import { TokenDetails } from '../interfaces/token-details';
2121
import { arrayToBase64 } from './array-base64-translator';
@@ -88,10 +88,8 @@ export async function migrateOldDatabase(
8888

8989
let tokenDetails: TokenDetails | null = null;
9090

91-
const db = await openDB(
92-
OLD_DB_NAME,
93-
OLD_DB_VERSION,
94-
async (db, oldVersion, newVersion, upgradeTransaction) => {
91+
const db = await openDB(OLD_DB_NAME, OLD_DB_VERSION, {
92+
upgrade: async (db, oldVersion, newVersion, upgradeTransaction) => {
9593
if (oldVersion < 2) {
9694
// Database too old, skip migration.
9795
return;
@@ -162,7 +160,7 @@ export async function migrateOldDatabase(
162160
};
163161
}
164162
}
165-
);
163+
});
166164
db.close();
167165

168166
// Delete all old databases.

packages/messaging/src/internals/idb-manager.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { DBWrapper, deleteDB, openDB } from '@firebase/util';
18+
import { DBSchema, IDBPDatabase, deleteDB, openDB } from 'idb';
1919

2020
import { FirebaseInternalDependencies } from '../interfaces/internal-dependencies';
2121
import { TokenDetails } from '../interfaces/token-details';
@@ -26,13 +26,18 @@ export const DATABASE_NAME = 'firebase-messaging-database';
2626
const DATABASE_VERSION = 1;
2727
const OBJECT_STORE_NAME = 'firebase-messaging-store';
2828

29-
let dbPromise: Promise<DBWrapper> | null = null;
30-
function getDbPromise(): Promise<DBWrapper> {
29+
interface MessagingDB extends DBSchema {
30+
'firebase-messaging-store': {
31+
key: string;
32+
value: TokenDetails;
33+
};
34+
}
35+
36+
let dbPromise: Promise<IDBPDatabase<MessagingDB>> | null = null;
37+
function getDbPromise(): Promise<IDBPDatabase<MessagingDB>> {
3138
if (!dbPromise) {
32-
dbPromise = openDB(
33-
DATABASE_NAME,
34-
DATABASE_VERSION,
35-
(upgradeDb, oldVersion) => {
39+
dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {
40+
upgrade: (upgradeDb, oldVersion) => {
3641
// We don't use 'break' in this switch statement, the fall-through behavior is what we want,
3742
// because if there are multiple versions between the old version and the current version, we
3843
// want ALL the migrations that correspond to those versions to run, not only the last one.
@@ -42,7 +47,7 @@ function getDbPromise(): Promise<DBWrapper> {
4247
upgradeDb.createObjectStore(OBJECT_STORE_NAME);
4348
}
4449
}
45-
);
50+
});
4651
}
4752
return dbPromise;
4853
}
@@ -81,7 +86,7 @@ export async function dbSet(
8186
const db = await getDbPromise();
8287
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
8388
await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);
84-
await tx.complete;
89+
await tx.done;
8590
return tokenDetails;
8691
}
8792

@@ -93,7 +98,7 @@ export async function dbRemove(
9398
const db = await getDbPromise();
9499
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
95100
await tx.objectStore(OBJECT_STORE_NAME).delete(key);
96-
await tx.complete;
101+
await tx.done;
97102
}
98103

99104
/** Deletes the DB. Useful for tests. */

0 commit comments

Comments
 (0)