@bbn/bbn 2.0.213 → 2.0.214

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/db.js CHANGED
@@ -1,16 +1,31 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import _ from './_.js';
2
- import each from './fn/loop/each.js';
3
11
  import iterate from './fn/loop/iterate.js';
4
12
  import log from './fn/browser/log.js';
5
13
  import isObject from './fn/type/isObject.js';
6
14
  import isArray from './fn/type/isArray.js';
7
15
  import extend from './fn/object/extend.js';
8
- const idb = window['indexedDB'] || window['webkitIndexedDB'] || window['mozIndexedDB'] || window['OIndexedDB'] || window['msIndexedDB'];
16
+ const idb = window.indexedDB ||
17
+ window.webkitIndexedDB ||
18
+ window.mozIndexedDB ||
19
+ window.OIndexedDB ||
20
+ window.msIndexedDB;
9
21
  const transformResult = (obj, fields) => {
22
+ if (!obj) {
23
+ return undefined;
24
+ }
10
25
  if (fields === null || fields === void 0 ? void 0 : fields.length) {
11
- let res = {};
26
+ const res = {};
12
27
  iterate(obj, (v, n) => {
13
- if (fields.indexOf(n) > -1) {
28
+ if (fields.includes(n)) {
14
29
  res[n] = v;
15
30
  }
16
31
  });
@@ -21,7 +36,7 @@ const transformResult = (obj, fields) => {
21
36
  const fieldsFromFilter = (filter, fields = []) => {
22
37
  var _a;
23
38
  if ((_a = filter === null || filter === void 0 ? void 0 : filter.conditions) === null || _a === void 0 ? void 0 : _a.length) {
24
- filter.conditions.forEach(cond => {
39
+ filter.conditions.forEach((cond) => {
25
40
  if (cond.field && !fields.includes(cond.field)) {
26
41
  fields.push(cond.field);
27
42
  }
@@ -31,14 +46,14 @@ const fieldsFromFilter = (filter, fields = []) => {
31
46
  });
32
47
  }
33
48
  else if (isObject(filter)) {
34
- iterate(filter, (v, n) => {
49
+ iterate(filter, (_v, n) => {
35
50
  if (!fields.includes(n)) {
36
51
  fields.push(n);
37
52
  }
38
53
  });
39
54
  }
40
55
  else if (isArray(filter)) {
41
- filter.forEach(cond => {
56
+ filter.forEach((cond) => {
42
57
  if (cond.field && !fields.includes(cond.field)) {
43
58
  fields.push(cond.field);
44
59
  }
@@ -49,259 +64,398 @@ const fieldsFromFilter = (filter, fields = []) => {
49
64
  }
50
65
  return fields;
51
66
  };
52
- const dbObject = function (dbName) {
53
- const conn = db._connections[dbName];
54
- const structure = db._structures[dbName];
55
- let lastError = null;
56
- const onError = (req, resolve) => {
57
- req.onerror = () => {
58
- lastError = req.error;
59
- log(req.error);
60
- resolve(req.error);
61
- };
62
- };
63
- const getStore = (table, mode) => {
64
- const tx = conn.transaction([table], mode.toLowerCase().indexOf('r') === 0 ? "readonly" : "readwrite");
67
+ const getPrimaryKey = (structure) => {
68
+ const cols = structure.keys.PRIMARY.columns;
69
+ return cols.length > 1 ? cols : cols[0];
70
+ };
71
+ const requestToPromise = (req) => new Promise((resolve, reject) => {
72
+ req.onsuccess = () => resolve(req.result);
73
+ req.onerror = () => reject(req.error);
74
+ });
75
+ const transactionDone = (tx) => new Promise((resolve, reject) => {
76
+ tx.oncomplete = () => resolve();
77
+ tx.onabort = () => reject(tx.error);
78
+ tx.onerror = () => reject(tx.error);
79
+ });
80
+ class DbObject {
81
+ constructor(dbName) {
82
+ this.lastErr = null;
83
+ this.dbName = dbName;
84
+ }
85
+ get connection() {
86
+ const conn = db._connections[this.dbName];
87
+ if (!conn) {
88
+ throw new Error(_('The database %s is not open', this.dbName));
89
+ }
90
+ return conn;
91
+ }
92
+ get structure() {
93
+ const structure = db._structures[this.dbName];
94
+ if (!structure) {
95
+ throw new Error(_('No structure defined for database %s', this.dbName));
96
+ }
97
+ return structure;
98
+ }
99
+ getStore(table, mode) {
100
+ const tx = this.connection.transaction([table], mode);
65
101
  tx.onabort = () => {
66
- lastError = tx.error;
67
- throw new Error(tx.error);
102
+ this.lastErr = tx.error;
103
+ log(tx.error);
104
+ };
105
+ tx.onerror = () => {
106
+ this.lastErr = tx.error;
107
+ log(tx.error);
68
108
  };
69
109
  return [tx, tx.objectStore(table)];
70
- };
71
- this.lastError = () => lastError;
72
- this.insert = (table, data) => {
73
- if (!Array.isArray(data)) {
74
- data = [data];
75
- }
76
- return new Promise(resolve => {
77
- const [tx, store] = getStore(table, 'w');
78
- let res = data.length;
79
- each(data, a => {
80
- const request = store.put(a);
81
- request.onerror = () => {
82
- log(request.error);
83
- res--;
110
+ }
111
+ lastError() {
112
+ return this.lastErr;
113
+ }
114
+ insert(table, data) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ const rows = Array.isArray(data) ? data : [data];
117
+ if (!rows.length) {
118
+ return 0;
119
+ }
120
+ const [tx, store] = this.getStore(table, 'readwrite');
121
+ let inserted = 0;
122
+ for (const row of rows) {
123
+ const req = store.put(row);
124
+ req.onsuccess = () => {
125
+ inserted++;
84
126
  };
85
- });
86
- tx.oncomplete = () => {
87
- resolve(res);
88
- };
127
+ req.onerror = () => {
128
+ this.lastErr = req.error;
129
+ log(req.error);
130
+ };
131
+ }
132
+ yield transactionDone(tx);
133
+ return inserted;
89
134
  });
90
- };
91
- this.update = (table, data, where, replace) => {
92
- return new Promise(resolve => {
93
- this.selectAll(table, [], where).then(rows => {
94
- if (!rows.length) {
95
- resolve(0);
96
- return;
97
- }
98
- const [tx, store] = getStore(table, 'w');
99
- const arch = structure[table];
100
- const primary = arch.keys.PRIMARY.columns.length > 1 ? arch.keys.PRIMARY.columns : arch.keys.PRIMARY.columns[0];
101
- let res = 0;
102
- for (let i = 0; i < rows.length; i++) {
103
- const newData = extend({}, replace ? { [primary]: rows[i][primary] } : rows[i], data);
104
- if (!newData[primary]) {
105
- throw new Error(_("No primary key in the data"));
106
- }
107
- const req = store.put(newData);
108
- onError(req, resolve);
109
- req.onsuccess = () => {
110
- res++;
111
- };
135
+ }
136
+ update(table_1, data_1, where_1) {
137
+ return __awaiter(this, arguments, void 0, function* (table, data, where, replace = false) {
138
+ const rows = yield this.selectAll(table, [], where);
139
+ if (!rows.length) {
140
+ return 0;
141
+ }
142
+ const structure = this.structure[table];
143
+ const primary = getPrimaryKey(structure);
144
+ if (Array.isArray(primary)) {
145
+ throw new Error(_('Composite primary keys are not supported by this update implementation'));
146
+ }
147
+ const [tx, store] = this.getStore(table, 'readwrite');
148
+ let updated = 0;
149
+ for (const row of rows) {
150
+ const nextRow = extend({}, replace ? { [primary]: row[primary] } : row, data);
151
+ if (!(primary in nextRow)) {
152
+ throw new Error(_('No primary key in the data'));
112
153
  }
113
- tx.oncomplete = () => {
114
- resolve(res);
154
+ const req = store.put(nextRow);
155
+ req.onsuccess = () => {
156
+ updated++;
115
157
  };
116
- });
158
+ req.onerror = () => {
159
+ this.lastErr = req.error;
160
+ log(req.error);
161
+ };
162
+ }
163
+ yield transactionDone(tx);
164
+ return updated;
117
165
  });
118
- };
119
- this.delete = (table, where) => {
120
- return new Promise(resolve => {
121
- const [tx, store] = getStore(table, 'w');
122
- const arch = structure[table];
123
- const primary = arch.keys.PRIMARY.columns.length > 1 ? arch.keys.PRIMARY.columns : arch.keys.PRIMARY.columns[0];
124
- if (!where[primary]) {
125
- throw new Error(_("No "));
166
+ }
167
+ delete(table, where) {
168
+ return __awaiter(this, void 0, void 0, function* () {
169
+ const structure = this.structure[table];
170
+ const primary = getPrimaryKey(structure);
171
+ if (Array.isArray(primary)) {
172
+ throw new Error(_('Composite primary keys are not supported by this delete implementation'));
173
+ }
174
+ if (!(primary in where)) {
175
+ throw new Error(_('No primary key in the filter'));
126
176
  }
127
- let res = 1;
128
- const req = store.delete(where[primary]);
129
- onError(req, resolve);
130
- tx.oncomplete = () => {
131
- resolve(res);
132
- };
177
+ const [tx, store] = this.getStore(table, 'readwrite');
178
+ store.delete(where[primary]);
179
+ yield transactionDone(tx);
180
+ return 1;
133
181
  });
134
- };
135
- this.selectOne = (table, field, where, order, start, limit) => {
136
- return new Promise(resolve => {
137
- this.selectAll(table, [field], where, order, start, 1).then(d => {
138
- var _a, _b;
139
- resolve((_b = (_a = d === null || d === void 0 ? void 0 : d[0]) === null || _a === void 0 ? void 0 : _a[field]) !== null && _b !== void 0 ? _b : undefined);
140
- });
182
+ }
183
+ selectOne(table_1, field_1) {
184
+ return __awaiter(this, arguments, void 0, function* (table, field, where = null, order = null, start = 0, limit = 1) {
185
+ var _a;
186
+ const rows = yield this.selectAll(table, [field], where, order, start, limit);
187
+ return (_a = rows === null || rows === void 0 ? void 0 : rows[0]) === null || _a === void 0 ? void 0 : _a[field];
141
188
  });
142
- };
143
- this.select = (table, fields, where, order, start) => {
144
- return new Promise(resolve => {
145
- this.selectAll(table, fields, where, order, start, 1).then(d => {
146
- resolve(d.length ? d[0] : null);
147
- });
189
+ }
190
+ select(table_1) {
191
+ return __awaiter(this, arguments, void 0, function* (table, fields = [], where = null, order = null, start = 0) {
192
+ const rows = yield this.selectAll(table, fields, where, order, start, 1);
193
+ return rows.length ? rows[0] : null;
148
194
  });
149
- };
150
- this.selectAll = (table, fields = [], where = null, order = null, start = 0, limit = null) => {
151
- return new Promise(resolve => {
152
- const [tx, store] = getStore(table, 'r');
153
- const arch = structure[table];
154
- const primary = arch.keys.PRIMARY.columns.length > 1 ? arch.keys.PRIMARY.columns : arch.keys.PRIMARY.columns[0];
155
- const search = isObject(where) ? Object.keys(where)[0] : (!where || isArray(where) ? null : primary);
195
+ }
196
+ selectAll(table_1) {
197
+ return __awaiter(this, arguments, void 0, function* (table, fields = [], where = null, order = null, start = 0, limit = null) {
198
+ void order;
199
+ const [tx, store] = this.getStore(table, 'readonly');
200
+ const structure = this.structure[table];
201
+ const primary = getPrimaryKey(structure);
156
202
  const results = [];
157
- if (search === primary) {
158
- if (bbn.fn.isArray(where === null || where === void 0 ? void 0 : where[primary])) {
159
- let req = [];
160
- const max = Math.min(where[primary].length, limit || 9999999);
161
- for (let i = start || 0; i < max; i++) {
162
- let getter = store.get(where[primary][i]);
163
- getter.onsuccess = () => {
164
- let obj = getter.result;
165
- results.push(transformResult(obj, fields));
166
- if (results.length === max) {
167
- resolve(results);
168
- }
169
- };
170
- onError(getter, resolve);
171
- req.push(getter);
203
+ const searchField = isObject(where)
204
+ ? Object.keys(where)[0]
205
+ : (!where || isArray(where) ? null : primary);
206
+ if (!Array.isArray(primary) && searchField === primary) {
207
+ if (Array.isArray(where === null || where === void 0 ? void 0 : where[primary])) {
208
+ const ids = where[primary];
209
+ const max = Math.min(ids.length - start, limit !== null && limit !== void 0 ? limit : ids.length);
210
+ const slice = ids.slice(start, start + max);
211
+ for (const id of slice) {
212
+ const row = yield requestToPromise(store.get(id));
213
+ const transformed = transformResult(row, fields);
214
+ if (transformed) {
215
+ results.push(transformed);
216
+ }
172
217
  }
218
+ yield transactionDone(tx);
219
+ return results;
173
220
  }
174
- else {
175
- let req = store.get((where === null || where === void 0 ? void 0 : where[primary]) || where);
176
- req.onsuccess = () => {
177
- let obj = req.result;
178
- results.push(transformResult(obj, fields));
179
- resolve(results);
180
- };
181
- onError(req, resolve);
221
+ const key = isObject(where)
222
+ ? where[primary]
223
+ : where;
224
+ const row = yield requestToPromise(store.get(key));
225
+ const transformed = transformResult(row, fields);
226
+ if (transformed) {
227
+ results.push(transformed);
182
228
  }
229
+ yield transactionDone(tx);
230
+ return results;
183
231
  }
184
- else {
232
+ yield new Promise((resolve, reject) => {
185
233
  const req = store.openCursor();
186
234
  let i = 0;
187
235
  req.onsuccess = (e) => {
236
+ var _a, _b;
188
237
  const cursor = e.target.result;
189
- if (cursor) {
190
- if (!where || !bbn.fn.search([cursor.value], where)) {
191
- if (i >= start) {
192
- results.push(transformResult(cursor.value, fields));
193
- if (results.length === limit) {
194
- resolve(results);
195
- }
238
+ if (!cursor) {
239
+ resolve();
240
+ return;
241
+ }
242
+ const matches = !where || !((_b = (_a = window.bbn) === null || _a === void 0 ? void 0 : _a.fn) === null || _b === void 0 ? void 0 : _b.search)
243
+ ? true
244
+ : !window.bbn.fn.search([cursor.value], where);
245
+ if (matches) {
246
+ if (i >= start) {
247
+ const transformed = transformResult(cursor.value, fields);
248
+ if (transformed) {
249
+ results.push(transformed);
250
+ }
251
+ if (limit !== null && results.length >= limit) {
252
+ resolve();
253
+ return;
196
254
  }
197
- i++;
198
255
  }
199
- cursor.continue();
200
- }
201
- else {
202
- resolve(results);
256
+ i++;
203
257
  }
258
+ cursor.continue();
204
259
  };
205
- onError(req, resolve);
206
- }
260
+ req.onerror = () => {
261
+ this.lastErr = req.error;
262
+ log(req.error);
263
+ reject(req.error);
264
+ };
265
+ });
266
+ yield transactionDone(tx);
267
+ return results;
207
268
  });
208
- };
209
- this.getColumnValues = (table, field, where, order, start, limit) => {
210
- return new Promise(resolve => {
211
- const tx = conn.transaction([table], "read");
212
- const store = tx.objectStore(table);
269
+ }
270
+ getColumnValues(table_1, field_1) {
271
+ return __awaiter(this, arguments, void 0, function* (table, field, where = null, order = null, start = 0, limit = null) {
272
+ const rows = yield this.selectAll(table, fieldsFromFilter(where, [field]), where, order, start, limit);
273
+ return rows
274
+ .map(row => row[field])
275
+ .filter(v => v !== undefined);
213
276
  });
214
- };
215
- this.copyTable = (target, table, fields = [], where = null, order = null, start = 0, limit = null) => {
216
- return new Promise(resolve => {
217
- if (!conn.objectStoreNames.contains(target)) {
218
- db.add(dbName, target, structure[table]);
277
+ }
278
+ copyTable(target_1, table_1) {
279
+ return __awaiter(this, arguments, void 0, function* (target, table, fields = [], where = null, order = null, start = 0, limit = null) {
280
+ if (!this.connection.objectStoreNames.contains(target)) {
281
+ yield db.add(this.dbName, target, this.structure[table]);
282
+ yield db.open(this.dbName);
219
283
  }
220
- if (!conn.objectStoreNames.contains(target)) {
221
- resolve(0);
222
- throw new Error(_("The target table %s does not exist", target));
284
+ if (!this.connection.objectStoreNames.contains(target)) {
285
+ throw new Error(_('The target table %s does not exist', target));
223
286
  }
224
- this.selectAll(table, fields, where, order, start, limit).then(d => {
225
- if (d.length) {
226
- this.insert(target, d).then(res => {
227
- resolve(res);
228
- });
229
- }
230
- else {
231
- resolve(0);
232
- }
233
- });
287
+ const rows = yield this.selectAll(table, fields, where, order, start, limit);
288
+ if (!rows.length) {
289
+ return 0;
290
+ }
291
+ return this.insert(target, rows);
234
292
  });
235
- };
236
- this.deleteTable = table => {
237
- return new Promise(resolve => {
238
- conn.deleteObjectStore(table);
239
- resolve(true);
293
+ }
294
+ deleteTable(table) {
295
+ return __awaiter(this, void 0, void 0, function* () {
296
+ yield db.remove(this.dbName, table);
297
+ return true;
240
298
  });
241
- };
242
- };
299
+ }
300
+ }
243
301
  const db = {
244
302
  _structures: {},
245
- /* This variable should be set to true in debugging mode only */
246
303
  _connections: {},
247
- /* Address of the CDN (where this file should be hosted) */
248
304
  _stores: {},
249
305
  ok: idb !== undefined,
250
- updateStructure(storeName, structure, req) {
251
- const primary = structure.keys.PRIMARY.columns.length > 1 ? structure.keys.PRIMARY.columns : structure.keys.PRIMARY.columns[0];
252
- const stores = req.objectStoreNames;
253
- if (!stores.contains(storeName)) {
254
- const store = req.createObjectStore(storeName, { keyPath: primary });
306
+ updateStructure(storeName, structure, database) {
307
+ const primary = getPrimaryKey(structure);
308
+ if (!database.objectStoreNames.contains(storeName)) {
309
+ const store = database.createObjectStore(storeName, {
310
+ keyPath: primary
311
+ });
255
312
  iterate(structure.keys, (a, n) => {
256
313
  if (n !== 'PRIMARY') {
257
- store.createIndex(n, a.columns.length > 1 ? a.columns : a.columns[0], {
258
- unique: !!a.unique
259
- });
314
+ store.createIndex(n, a.columns.length > 1 ? a.columns : a.columns[0], { unique: !!a.unique });
260
315
  }
261
316
  });
262
317
  }
263
- else {
264
- }
265
318
  },
266
- open(name) {
267
- return new Promise((resolve) => {
268
- if (!db._connections[name]) {
269
- if (!db._structures[name]) {
270
- throw new Error(_("Impossible to find a structure for the database %s", name));
319
+ getExistingVersion(name) {
320
+ return __awaiter(this, void 0, void 0, function* () {
321
+ const live = this._connections[name];
322
+ if (live) {
323
+ return live.version;
324
+ }
325
+ return new Promise((resolve, reject) => {
326
+ if (!idb) {
327
+ reject(new Error(_('IndexedDB is not available')));
328
+ return;
271
329
  }
272
- let num = Math.max.apply(this, [1].concat(Object.keys(db._structures[name]).map(a => db._structures[name][a].num || 1)));
273
- const conn = idb.open(name, num);
274
- conn.onupgradeneeded = () => {
275
- const req = conn.result;
276
- iterate(db._structures[name], (structure, storeName) => {
277
- this.updateStructure(storeName, structure, req);
330
+ const req = idb.open(name);
331
+ req.onsuccess = () => {
332
+ const database = req.result;
333
+ const version = database.version;
334
+ database.close();
335
+ resolve(version);
336
+ };
337
+ req.onupgradeneeded = () => {
338
+ // Database did not exist before; this open created it temporarily.
339
+ // Version is therefore effectively 1.
340
+ const database = req.result;
341
+ const version = database.version;
342
+ database.close();
343
+ resolve(version);
344
+ };
345
+ req.onerror = () => reject(req.error);
346
+ });
347
+ });
348
+ },
349
+ reopenWithUpgrade(name) {
350
+ return __awaiter(this, void 0, void 0, function* () {
351
+ const existingVersion = yield this.getExistingVersion(name);
352
+ const nextVersion = existingVersion + 1;
353
+ if (this._connections[name]) {
354
+ this._connections[name].close();
355
+ delete this._connections[name];
356
+ }
357
+ return new Promise((resolve, reject) => {
358
+ if (!idb) {
359
+ reject(new Error(_('IndexedDB is not available')));
360
+ return;
361
+ }
362
+ const req = idb.open(name, nextVersion);
363
+ req.onupgradeneeded = () => {
364
+ const database = req.result;
365
+ const dbStructure = this._structures[name] || {};
366
+ iterate(dbStructure, (structure, storeName) => {
367
+ if (!database.objectStoreNames.contains(storeName)) {
368
+ this.updateStructure(storeName, structure, database);
369
+ }
278
370
  });
279
371
  };
280
- conn.onsuccess = () => {
281
- db._connections[name] = conn.result;
282
- let obj = new dbObject(name);
283
- resolve(obj);
372
+ req.onsuccess = () => {
373
+ this._connections[name] = req.result;
374
+ resolve(req.result);
284
375
  };
376
+ req.onerror = () => reject(req.error);
377
+ req.onblocked = () => reject(req.error || new Error(_('IndexedDB upgrade blocked')));
378
+ });
379
+ });
380
+ },
381
+ open(name) {
382
+ return __awaiter(this, void 0, void 0, function* () {
383
+ if (!idb) {
384
+ throw new Error(_('IndexedDB is not available'));
285
385
  }
286
- else {
287
- resolve(new dbObject(name));
386
+ if (!this._structures[name]) {
387
+ throw new Error(_('Impossible to find a structure for the database %s', name));
288
388
  }
389
+ if (this._connections[name]) {
390
+ return new DbObject(name);
391
+ }
392
+ yield new Promise((resolve, reject) => {
393
+ const req = idb.open(name);
394
+ req.onupgradeneeded = () => {
395
+ const database = req.result;
396
+ const dbStructure = this._structures[name] || {};
397
+ iterate(dbStructure, (structure, storeName) => {
398
+ if (!database.objectStoreNames.contains(storeName)) {
399
+ this.updateStructure(storeName, structure, database);
400
+ }
401
+ });
402
+ };
403
+ req.onsuccess = () => {
404
+ this._connections[name] = req.result;
405
+ resolve(req.result);
406
+ };
407
+ req.onerror = () => reject(req.error);
408
+ });
409
+ return new DbObject(name);
289
410
  });
290
411
  },
291
412
  add(database, name, structure) {
292
- var _a;
293
- if (((_a = structure === null || structure === void 0 ? void 0 : structure.keys) === null || _a === void 0 ? void 0 : _a.PRIMARY) && (structure === null || structure === void 0 ? void 0 : structure.fields)) {
294
- if (!db._structures[database]) {
295
- db._structures[database] = {};
413
+ return __awaiter(this, void 0, void 0, function* () {
414
+ var _a;
415
+ if (!((_a = structure === null || structure === void 0 ? void 0 : structure.keys) === null || _a === void 0 ? void 0 : _a.PRIMARY) || !(structure === null || structure === void 0 ? void 0 : structure.fields)) {
416
+ throw new Error(_('The database structure for %s is not valid (missing keys, fields, or primary key)', name));
296
417
  }
297
- db._structures[database][name] = structure;
298
- if (db._connections[database]) {
299
- this.updateStructure(name, structure, db._connections[database]);
418
+ if (!this._structures[database]) {
419
+ this._structures[database] = {};
300
420
  }
301
- }
302
- else {
303
- throw new Error(_("The database structure for %s is not valid (are there keys and field? Is there a primary?", name));
304
- }
421
+ this._structures[database][name] = structure;
422
+ // Only upgrade if the DB already exists/open and the store is missing
423
+ const conn = this._connections[database];
424
+ if (conn && !conn.objectStoreNames.contains(name)) {
425
+ yield this.reopenWithUpgrade(database);
426
+ }
427
+ });
428
+ },
429
+ remove(database, name) {
430
+ return __awaiter(this, void 0, void 0, function* () {
431
+ var _a;
432
+ (_a = this._structures[database]) === null || _a === void 0 ? true : delete _a[name];
433
+ const conn = this._connections[database];
434
+ if (!conn) {
435
+ return;
436
+ }
437
+ const nextVersion = conn.version + 1;
438
+ conn.close();
439
+ delete this._connections[database];
440
+ yield new Promise((resolve, reject) => {
441
+ if (!idb) {
442
+ reject(new Error(_('IndexedDB is not available')));
443
+ return;
444
+ }
445
+ const req = idb.open(database, nextVersion);
446
+ req.onupgradeneeded = () => {
447
+ const dbInstance = req.result;
448
+ if (dbInstance.objectStoreNames.contains(name)) {
449
+ dbInstance.deleteObjectStore(name);
450
+ }
451
+ };
452
+ req.onsuccess = () => {
453
+ this._connections[database] = req.result;
454
+ resolve();
455
+ };
456
+ req.onerror = () => reject(req.error);
457
+ });
458
+ });
305
459
  }
306
460
  };
307
461
  export default db;