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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
import { Stores } from "./types/dbTypes";
import { openDatabase, Database, Store, Index } from "./util/query";
import {
IDBFactory,
IDBDatabase,
IDBObjectStore,
IDBTransaction,
} from "idb-bridge";
import { Logger } from "./util/logging";
/**
* Name of the Taler database. This is effectively the major
* version of the DB schema. Whenever it changes, custom import logic
* for all previous versions must be written, which should be
* avoided.
*/
const TALER_DB_NAME = "taler-wallet-prod-v1";
/**
* Current database minor version, should be incremented
* each time we do minor schema changes on the database.
* A change is considered minor when fields are added in a
* backwards-compatible way or object stores and indices
* are added.
*/
export const WALLET_DB_MINOR_VERSION = 3;
const logger = new Logger("db.ts");
/**
* Return a promise that resolves
* to the taler wallet db.
*/
export function openTalerDatabase(
idbFactory: IDBFactory,
onVersionChange: () => void,
): Promise<IDBDatabase> {
const onUpgradeNeeded = (
db: IDBDatabase,
oldVersion: number,
newVersion: number,
upgradeTransaction: IDBTransaction,
): void => {
if (oldVersion === 0) {
for (const n in Stores) {
if ((Stores as any)[n] instanceof Store) {
const si: Store<string, any> = (Stores as any)[n];
const s = db.createObjectStore(si.name, si.storeParams);
for (const indexName in si as any) {
if ((si as any)[indexName] instanceof Index) {
const ii: Index<string, string, any, any> = (si as any)[
indexName
];
s.createIndex(ii.indexName, ii.keyPath, ii.options);
}
}
}
}
return;
}
if (oldVersion === newVersion) {
return;
}
logger.info(`upgrading database from ${oldVersion} to ${newVersion}`);
for (const n in Stores) {
if ((Stores as any)[n] instanceof Store) {
const si: Store<string, any> = (Stores as any)[n];
let s: IDBObjectStore;
const storeVersionAdded = si.storeParams?.versionAdded ?? 1;
if (storeVersionAdded > oldVersion) {
s = db.createObjectStore(si.name, si.storeParams);
} else {
s = upgradeTransaction.objectStore(si.name);
}
for (const indexName in si as any) {
if ((si as any)[indexName] instanceof Index) {
const ii: Index<string, string, any, any> = (si as any)[indexName];
const indexVersionAdded = ii.options?.versionAdded ?? 0;
if (indexVersionAdded > oldVersion || storeVersionAdded > oldVersion) {
s.createIndex(ii.indexName, ii.keyPath, ii.options);
}
}
}
}
}
};
return openDatabase(
idbFactory,
TALER_DB_NAME,
WALLET_DB_MINOR_VERSION,
onVersionChange,
onUpgradeNeeded,
);
}
export function deleteTalerDatabase(idbFactory: IDBFactory): void {
Database.deleteDatabase(idbFactory, TALER_DB_NAME);
}
|