@bbn/bbn 2.0.221 → 2.0.222
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/bbn.js +1 -1
- package/dist/bbn.js.map +1 -1
- package/dist/com.js +0 -1
- package/dist/db.d.ts +3 -1
- package/dist/db.js +131 -50
- package/dist/fn/init.js +21 -21
- package/package.json +1 -1
package/dist/com.js
CHANGED
|
@@ -53,7 +53,6 @@ const fetchRequest = (method, url, config = {}, aborter) => {
|
|
|
53
53
|
const hasBody = methodsWithBody.includes(method.toUpperCase());
|
|
54
54
|
if (config.data != null && hasBody) {
|
|
55
55
|
// You can get fancier here (JSON, FormData, etc.)
|
|
56
|
-
bbn.fn.log('DATA', config.data);
|
|
57
56
|
if (typeof config.data === 'object' && !(config.data instanceof FormData)) {
|
|
58
57
|
fetchConfig.headers.set('Content-Type', 'application/json');
|
|
59
58
|
fetchConfig.body = JSON.stringify(config.data);
|
package/dist/db.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ type WhereObject = Record<string, unknown> | null;
|
|
|
16
16
|
type OrderClause = unknown;
|
|
17
17
|
interface IDbApi {
|
|
18
18
|
lastError(): unknown;
|
|
19
|
+
close(): void;
|
|
19
20
|
insert(table: string, data: Record<string, unknown> | Record<string, unknown>[]): Promise<number>;
|
|
20
21
|
update(table: string, data: Record<string, unknown>, where: WhereObject, replace?: boolean): Promise<number>;
|
|
21
22
|
delete(table: string, where: Record<string, unknown>): Promise<number>;
|
|
@@ -32,7 +33,8 @@ interface DbManager {
|
|
|
32
33
|
_stores: Record<string, unknown>;
|
|
33
34
|
ok: boolean;
|
|
34
35
|
open(name: string): Promise<IDbApi>;
|
|
35
|
-
add(database: string, name: string, structure: DbStructure): Promise<
|
|
36
|
+
add(database: string, name: string, structure: DbStructure): Promise<IDBDatabase>;
|
|
37
|
+
openRaw(name: string, version?: number): Promise<IDBDatabase>;
|
|
36
38
|
remove(database: string, name: string): Promise<void>;
|
|
37
39
|
updateStructure(storeName: string, structure: DbStructure, database: IDBDatabase): void;
|
|
38
40
|
reopenWithUpgrade(name: string): Promise<IDBDatabase>;
|
package/dist/db.js
CHANGED
|
@@ -82,12 +82,22 @@ class DbObject {
|
|
|
82
82
|
this.lastErr = null;
|
|
83
83
|
this.dbName = dbName;
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return
|
|
85
|
+
hasMissingStores(database, conn) {
|
|
86
|
+
const structures = db._structures[database] || {};
|
|
87
|
+
return Object.keys(structures).some(storeName => !conn.objectStoreNames.contains(storeName));
|
|
88
|
+
}
|
|
89
|
+
getConnection() {
|
|
90
|
+
return __awaiter(this, arguments, void 0, function* (database = '') {
|
|
91
|
+
let conn = db._connections[database || this.dbName];
|
|
92
|
+
if (!conn) {
|
|
93
|
+
const tmp = yield db.open(database || this.dbName);
|
|
94
|
+
if (!db._connections[database || this.dbName]) {
|
|
95
|
+
throw new Error(_('The database %s is not open', this.dbName));
|
|
96
|
+
}
|
|
97
|
+
conn = db._connections[database || this.dbName];
|
|
98
|
+
}
|
|
99
|
+
return conn;
|
|
100
|
+
});
|
|
91
101
|
}
|
|
92
102
|
get structure() {
|
|
93
103
|
const structure = db._structures[this.dbName];
|
|
@@ -97,27 +107,43 @@ class DbObject {
|
|
|
97
107
|
return structure;
|
|
98
108
|
}
|
|
99
109
|
getStore(table, mode) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
this.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
const connection = yield this.getConnection();
|
|
112
|
+
if (!this.structure[table]) {
|
|
113
|
+
throw new Error(_('Table %s is not defined in database structure %s', table, this.dbName));
|
|
114
|
+
}
|
|
115
|
+
if (!connection.objectStoreNames.contains(table)) {
|
|
116
|
+
throw new Error(_('Table %s does not exist in database %s. Schema upgrade required.', table, this.dbName));
|
|
117
|
+
}
|
|
118
|
+
const tx = connection.transaction([table], mode);
|
|
119
|
+
tx.onabort = () => {
|
|
120
|
+
this.lastErr = tx.error;
|
|
121
|
+
log(tx.error);
|
|
122
|
+
};
|
|
123
|
+
tx.onerror = () => {
|
|
124
|
+
this.lastErr = tx.error;
|
|
125
|
+
log(tx.error);
|
|
126
|
+
};
|
|
127
|
+
return [tx, tx.objectStore(table)];
|
|
128
|
+
});
|
|
110
129
|
}
|
|
111
130
|
lastError() {
|
|
112
131
|
return this.lastErr;
|
|
113
132
|
}
|
|
133
|
+
close() {
|
|
134
|
+
const conn = db._connections[this.dbName];
|
|
135
|
+
if (conn) {
|
|
136
|
+
conn.close();
|
|
137
|
+
delete db._connections[this.dbName];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
114
140
|
insert(table, data) {
|
|
115
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
116
142
|
const rows = Array.isArray(data) ? data : [data];
|
|
117
143
|
if (!rows.length) {
|
|
118
144
|
return 0;
|
|
119
145
|
}
|
|
120
|
-
const [tx, store] = this.getStore(table, 'readwrite');
|
|
146
|
+
const [tx, store] = yield this.getStore(table, 'readwrite');
|
|
121
147
|
let inserted = 0;
|
|
122
148
|
for (const row of rows) {
|
|
123
149
|
const req = store.put(row);
|
|
@@ -144,7 +170,7 @@ class DbObject {
|
|
|
144
170
|
if (Array.isArray(primary)) {
|
|
145
171
|
throw new Error(_('Composite primary keys are not supported by this update implementation'));
|
|
146
172
|
}
|
|
147
|
-
const [tx, store] = this.getStore(table, 'readwrite');
|
|
173
|
+
const [tx, store] = yield this.getStore(table, 'readwrite');
|
|
148
174
|
let updated = 0;
|
|
149
175
|
for (const row of rows) {
|
|
150
176
|
const nextRow = extend({}, replace ? { [primary]: row[primary] } : row, data);
|
|
@@ -174,7 +200,7 @@ class DbObject {
|
|
|
174
200
|
if (!(primary in where)) {
|
|
175
201
|
throw new Error(_('No primary key in the filter'));
|
|
176
202
|
}
|
|
177
|
-
const [tx, store] = this.getStore(table, 'readwrite');
|
|
203
|
+
const [tx, store] = yield this.getStore(table, 'readwrite');
|
|
178
204
|
store.delete(where[primary]);
|
|
179
205
|
yield transactionDone(tx);
|
|
180
206
|
return 1;
|
|
@@ -196,7 +222,7 @@ class DbObject {
|
|
|
196
222
|
selectAll(table_1) {
|
|
197
223
|
return __awaiter(this, arguments, void 0, function* (table, fields = [], where = null, order = null, start = 0, limit = null) {
|
|
198
224
|
void order;
|
|
199
|
-
const [tx, store] = this.getStore(table, 'readonly');
|
|
225
|
+
const [tx, store] = yield this.getStore(table, 'readonly');
|
|
200
226
|
const structure = this.structure[table];
|
|
201
227
|
const primary = getPrimaryKey(structure);
|
|
202
228
|
const results = [];
|
|
@@ -241,7 +267,7 @@ class DbObject {
|
|
|
241
267
|
}
|
|
242
268
|
const matches = !where || !((_b = (_a = globalThis.bbn) === null || _a === void 0 ? void 0 : _a.fn) === null || _b === void 0 ? void 0 : _b.search)
|
|
243
269
|
? true
|
|
244
|
-
:
|
|
270
|
+
: 0 === globalThis.bbn.fn.search([cursor.value], where);
|
|
245
271
|
if (matches) {
|
|
246
272
|
if (i >= start) {
|
|
247
273
|
const transformed = transformResult(cursor.value, fields);
|
|
@@ -277,11 +303,15 @@ class DbObject {
|
|
|
277
303
|
}
|
|
278
304
|
copyTable(target_1, table_1) {
|
|
279
305
|
return __awaiter(this, arguments, void 0, function* (target, table, fields = [], where = null, order = null, start = 0, limit = null) {
|
|
280
|
-
if (!this.
|
|
306
|
+
if (!this.structure[table]) {
|
|
307
|
+
throw new Error(_('Source table %s does not exist in structure', table));
|
|
308
|
+
}
|
|
309
|
+
let connection = yield this.getConnection();
|
|
310
|
+
if (!connection.objectStoreNames.contains(target)) {
|
|
281
311
|
yield db.add(this.dbName, target, this.structure[table]);
|
|
282
|
-
yield
|
|
312
|
+
connection = yield this.getConnection();
|
|
283
313
|
}
|
|
284
|
-
if (!
|
|
314
|
+
if (!connection.objectStoreNames.contains(target)) {
|
|
285
315
|
throw new Error(_('The target table %s does not exist', target));
|
|
286
316
|
}
|
|
287
317
|
const rows = yield this.selectAll(table, fields, where, order, start, limit);
|
|
@@ -348,8 +378,12 @@ const db = {
|
|
|
348
378
|
},
|
|
349
379
|
reopenWithUpgrade(name) {
|
|
350
380
|
return __awaiter(this, void 0, void 0, function* () {
|
|
381
|
+
if (!this._structures[name]) {
|
|
382
|
+
throw new Error(_('Impossible to find a structure for the database %s', name));
|
|
383
|
+
}
|
|
351
384
|
const existingVersion = yield this.getExistingVersion(name);
|
|
352
385
|
const nextVersion = existingVersion + 1;
|
|
386
|
+
log(_('Going from version %s to version %s for database %s', existingVersion, nextVersion, name));
|
|
353
387
|
if (this._connections[name]) {
|
|
354
388
|
this._connections[name].close();
|
|
355
389
|
delete this._connections[name];
|
|
@@ -374,7 +408,10 @@ const db = {
|
|
|
374
408
|
resolve(req.result);
|
|
375
409
|
};
|
|
376
410
|
req.onerror = () => reject(req.error);
|
|
377
|
-
req.onblocked = () =>
|
|
411
|
+
req.onblocked = (event) => {
|
|
412
|
+
log(event);
|
|
413
|
+
reject(_('reopenWithUpgrade: Upgrade blocked for database %s. Please close other connections to proceed.', name));
|
|
414
|
+
};
|
|
378
415
|
});
|
|
379
416
|
});
|
|
380
417
|
},
|
|
@@ -405,6 +442,9 @@ const db = {
|
|
|
405
442
|
resolve(req.result);
|
|
406
443
|
};
|
|
407
444
|
req.onerror = () => reject(req.error);
|
|
445
|
+
req.onblocked = (event) => {
|
|
446
|
+
reject(_('open: Upgrade blocked for database %s. Please close other connections to proceed.', database));
|
|
447
|
+
};
|
|
408
448
|
});
|
|
409
449
|
return new DbObject(database);
|
|
410
450
|
});
|
|
@@ -412,6 +452,7 @@ const db = {
|
|
|
412
452
|
add(database, name, structure) {
|
|
413
453
|
return __awaiter(this, void 0, void 0, function* () {
|
|
414
454
|
var _a;
|
|
455
|
+
log(_('Adding database structure for %s.%s', database, name));
|
|
415
456
|
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
457
|
throw new Error(_('The database structure for %s is not valid (missing keys, fields, or primary key)', name));
|
|
417
458
|
}
|
|
@@ -419,42 +460,82 @@ const db = {
|
|
|
419
460
|
this._structures[database] = {};
|
|
420
461
|
}
|
|
421
462
|
this._structures[database][name] = structure;
|
|
422
|
-
// Only upgrade if the DB already exists/open and the store is missing
|
|
423
463
|
const conn = this._connections[database];
|
|
424
|
-
if (conn
|
|
425
|
-
|
|
464
|
+
if (conn) {
|
|
465
|
+
if (!conn.objectStoreNames.contains(name)) {
|
|
466
|
+
return yield this.reopenWithUpgrade(database);
|
|
467
|
+
}
|
|
468
|
+
return conn;
|
|
469
|
+
}
|
|
470
|
+
// No live connection: inspect current DB and upgrade if needed.
|
|
471
|
+
const existingVersion = yield this.getExistingVersion(database);
|
|
472
|
+
const hasDbAlready = existingVersion > 0;
|
|
473
|
+
if (!hasDbAlready) {
|
|
474
|
+
yield this.open(database);
|
|
475
|
+
return this._connections[database];
|
|
476
|
+
}
|
|
477
|
+
// DB exists already: open temporarily and check if store exists
|
|
478
|
+
const tmp = yield this.openRaw(database);
|
|
479
|
+
const hasStore = tmp.objectStoreNames.contains(name);
|
|
480
|
+
tmp.close();
|
|
481
|
+
if (!hasStore) {
|
|
482
|
+
return yield this.reopenWithUpgrade(database);
|
|
483
|
+
}
|
|
484
|
+
return yield this.openRaw(database);
|
|
485
|
+
});
|
|
486
|
+
},
|
|
487
|
+
openRaw(name, version) {
|
|
488
|
+
return new Promise((resolve, reject) => {
|
|
489
|
+
if (!idb) {
|
|
490
|
+
reject(new Error(_('IndexedDB is not available')));
|
|
491
|
+
return;
|
|
426
492
|
}
|
|
493
|
+
const req = version ? idb.open(name, version) : idb.open(name);
|
|
494
|
+
req.onsuccess = () => resolve(req.result);
|
|
495
|
+
req.onerror = () => reject(req.error);
|
|
496
|
+
req.onblocked = () => reject(new Error(_('IndexedDB open blocked for database %s', name)));
|
|
427
497
|
});
|
|
428
498
|
},
|
|
429
499
|
remove(database, name) {
|
|
430
500
|
return __awaiter(this, void 0, void 0, function* () {
|
|
431
|
-
|
|
432
|
-
(
|
|
433
|
-
const conn = this._connections[database];
|
|
434
|
-
if (!conn) {
|
|
501
|
+
const currentStructure = this._structures[database];
|
|
502
|
+
if (!(currentStructure === null || currentStructure === void 0 ? void 0 : currentStructure[name])) {
|
|
435
503
|
return;
|
|
436
504
|
}
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
if (!
|
|
442
|
-
reject(new Error(_('IndexedDB is not available')));
|
|
505
|
+
const old = currentStructure[name];
|
|
506
|
+
delete currentStructure[name];
|
|
507
|
+
try {
|
|
508
|
+
const conn = this._connections[database];
|
|
509
|
+
if (!conn) {
|
|
443
510
|
return;
|
|
444
511
|
}
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
512
|
+
const nextVersion = conn.version + 1;
|
|
513
|
+
conn.close();
|
|
514
|
+
delete this._connections[database];
|
|
515
|
+
yield new Promise((resolve, reject) => {
|
|
516
|
+
if (!idb) {
|
|
517
|
+
reject(new Error(_('IndexedDB is not available')));
|
|
518
|
+
return;
|
|
450
519
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
520
|
+
const req = idb.open(database, nextVersion);
|
|
521
|
+
req.onupgradeneeded = () => {
|
|
522
|
+
const dbInstance = req.result;
|
|
523
|
+
if (dbInstance.objectStoreNames.contains(name)) {
|
|
524
|
+
dbInstance.deleteObjectStore(name);
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
req.onsuccess = () => {
|
|
528
|
+
this._connections[database] = req.result;
|
|
529
|
+
resolve();
|
|
530
|
+
};
|
|
531
|
+
req.onerror = () => reject(req.error);
|
|
532
|
+
req.onblocked = () => reject(new Error(_('Remove blocked for database %s', database)));
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
catch (e) {
|
|
536
|
+
currentStructure[name] = old;
|
|
537
|
+
throw e;
|
|
538
|
+
}
|
|
458
539
|
});
|
|
459
540
|
}
|
|
460
541
|
};
|
package/dist/fn/init.js
CHANGED
|
@@ -81,7 +81,7 @@ export default function init(cfg, force) {
|
|
|
81
81
|
if (bbn.var.colors) {
|
|
82
82
|
addColors(bbn.var.colors);
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
document.addEventListener("visibilitychange", () => {
|
|
85
85
|
if (document.hidden) {
|
|
86
86
|
bbn.env.isVisible = false;
|
|
87
87
|
}
|
|
@@ -89,7 +89,7 @@ export default function init(cfg, force) {
|
|
|
89
89
|
bbn.env.isVisible = true;
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
|
-
|
|
92
|
+
document.addEventListener("focus", (e) => {
|
|
93
93
|
if (e.target instanceof HTMLElement &&
|
|
94
94
|
!e.target.classList.contains("bbn-no")) {
|
|
95
95
|
bbn.env.focused = e.target;
|
|
@@ -97,7 +97,7 @@ export default function init(cfg, force) {
|
|
|
97
97
|
bbn.env.isFocused = true;
|
|
98
98
|
bbn.env.last_focus = timestamp();
|
|
99
99
|
});
|
|
100
|
-
|
|
100
|
+
document.addEventListener("blur", (e) => {
|
|
101
101
|
if (e.target instanceof HTMLElement &&
|
|
102
102
|
!e.target.classList.contains("bbn-no")) {
|
|
103
103
|
bbn.env.focused = e.target;
|
|
@@ -105,29 +105,29 @@ export default function init(cfg, force) {
|
|
|
105
105
|
bbn.env.isFocused = false;
|
|
106
106
|
bbn.env.last_focus = timestamp();
|
|
107
107
|
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
document.addEventListener("click", onActivity);
|
|
109
|
+
document.addEventListener("keydown", onActivity);
|
|
110
|
+
document.addEventListener("focusin", onFocus);
|
|
111
|
+
document.addEventListener("focusout", onFocus);
|
|
112
|
+
window.addEventListener("hashchange", () => {
|
|
113
113
|
bbn.env.hashChanged = new Date().getTime();
|
|
114
114
|
}, false);
|
|
115
|
-
|
|
115
|
+
window.addEventListener("resize", () => {
|
|
116
116
|
resize();
|
|
117
117
|
});
|
|
118
|
-
|
|
118
|
+
window.addEventListener("orientationchange", () => {
|
|
119
119
|
resize();
|
|
120
120
|
});
|
|
121
121
|
resize();
|
|
122
122
|
if (isMobile()) {
|
|
123
|
-
|
|
123
|
+
document.body.classList.add("bbn-mobile");
|
|
124
124
|
if (isTabletDevice()) {
|
|
125
|
-
|
|
125
|
+
document.body.classList.add("bbn-tablet");
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
let h =
|
|
128
|
+
if (window.history) {
|
|
129
|
+
window.onpopstate = function (e) {
|
|
130
|
+
let h = window.history;
|
|
131
131
|
if (!bbn.env.historyDisabled && h) {
|
|
132
132
|
//e.preventDefault();
|
|
133
133
|
if (bbn.fn.defaultHistoryFunction(h.state)) {
|
|
@@ -143,17 +143,17 @@ export default function init(cfg, force) {
|
|
|
143
143
|
}
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
window.addEventListener('online', () => {
|
|
147
147
|
bbn.env.online = true;
|
|
148
148
|
});
|
|
149
|
-
|
|
149
|
+
window.addEventListener('offline', () => {
|
|
150
150
|
bbn.env.online = false;
|
|
151
151
|
});
|
|
152
152
|
bbn.env.isInit = true;
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
document.dispatchEvent(new Event("bbninit"));
|
|
154
|
+
}
|
|
155
|
+
if (bbn.env.logging) {
|
|
156
|
+
log("Logging in bbn is enabled");
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
}
|