-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcreate-indexeddatabase.ts
78 lines (70 loc) · 2.97 KB
/
create-indexeddatabase.ts
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
// @ts-nocheck
type CreateObjectStores =
| Record<string, IDBObjectStoreParameters>
| Map<string, IDBObjectStoreParameters>;
function makePromise<T>() {
let resolve!: (value: T) => void;
let reject!: (reason?: any) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return {resolve, reject, promise};
}
/**
* Creates objectStores in database called dbname using single transaction
* @param {string} dbname
* @param {CreateObjectStores} objectStores
* @return The db version right now.
* @returns number
*
* In IndexedDB, if you don't specify a key path or auto-increment option when creating an object store, the object store will use the following defaults:
*
* - The key path will be null. This means that objects in the store will not have a key path, and you will need to provide a key explicitly when adding or updating objects.
* - The auto-increment option will be false. This means that objects in the store will not have an auto-incrementing key. If you provide a key when adding an object to the store, that key will be used as the key for the object.
*/
async function createIndexeddatabase(
dbname: string,
objectStores: CreateObjectStores
): Promise<number> {
/* First find out if we need to update by opening the database without a version to get the current version and datastores */
const {resolve, promise, reject} = makePromise<IDBDatabase>();
const request = indexedDB.open(dbname);
request.onsuccess = (event) => resolve(event.target!.result);
request.onerror = reject;
const db = await promise;
db.onversionchange = db.close;
let version = db.version;
let to_create: { name: string; options: IDBObjectStoreParameters }[] = [];
if (objectStores instanceof Map) {
for (const [name, options] of objectStores)
if (!db.objectStoreNames.contains(name)) to_create.push({name, options});
} else if (!(objectStores instanceof Map)) {
for (const name in objectStores)
if (!db.objectStoreNames.contains(name))
to_create.push({name, options: objectStores[name]});
}
/* Create the new database if needed */
{
const {promise, reject, resolve} = makePromise<number>();
if (to_create.length) {
// true if we need to update
const request = indexedDB.open(dbname, ++version); // closes other db
request.onupgradeneeded = (event) => {
const db = event.target!.result;
for (const {name, options} of to_create) db.createObjectStore(name, options);
};
request.onerror = reject;
request.onsuccess = (event) => {
const db = event.target!.result;
resolve(db.version);
db.close();
};
return promise;
}
resolve(db.version);
db.close();
return promise;
}
}
export default createIndexeddatabase;