idb-ts 3.13.0 → 3.15.0
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/README.md +198 -74
- package/lib/index.cjs +1169 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.esm.js +73 -69
- package/lib/index.js +39 -44
- package/package.json +8 -5
- package/lib/jest.setup.d.ts +0 -1
- package/lib/jest.setup.js +0 -6
package/lib/index.js
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.KeyGenerators = exports.Database = void 0;
|
|
13
|
-
exports.KeyPath = KeyPath;
|
|
14
|
-
exports.CompositeKeyPath = CompositeKeyPath;
|
|
15
|
-
exports.DataClass = DataClass;
|
|
16
|
-
exports.Index = Index;
|
|
17
|
-
exports.Validate = Validate;
|
|
18
|
-
exports.RetentionPolicy = RetentionPolicy;
|
|
19
|
-
require("reflect-metadata");
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import 'reflect-metadata';
|
|
3
|
+
|
|
20
4
|
class FieldQueryBuilder {
|
|
21
5
|
constructor(parent, field) {
|
|
22
6
|
this.parent = parent;
|
|
@@ -459,7 +443,6 @@ class KeyGenerators {
|
|
|
459
443
|
return Math.random().toString(36).substring(2, 15);
|
|
460
444
|
}
|
|
461
445
|
}
|
|
462
|
-
exports.KeyGenerators = KeyGenerators;
|
|
463
446
|
function KeyPath(options) {
|
|
464
447
|
return (target, propertyKey) => {
|
|
465
448
|
const constructor = target.constructor;
|
|
@@ -534,12 +517,23 @@ function DataClass(options = {}) {
|
|
|
534
517
|
};
|
|
535
518
|
}
|
|
536
519
|
class Database {
|
|
537
|
-
constructor(dbName, classes) {
|
|
520
|
+
constructor(dbName, classes, printEnabled = false) {
|
|
538
521
|
this.db = null;
|
|
539
522
|
this.entityRepositories = new Map();
|
|
540
523
|
this.retentionTimer = null;
|
|
541
524
|
this.retentionCleanupRunning = false;
|
|
525
|
+
this.printDebug = (...data) => {
|
|
526
|
+
if (!this.printEnabled)
|
|
527
|
+
return;
|
|
528
|
+
console.debug('[idb-ts]:DEBUG:', ...data);
|
|
529
|
+
};
|
|
530
|
+
this.printError = (...error) => {
|
|
531
|
+
if (!this.printEnabled)
|
|
532
|
+
return;
|
|
533
|
+
console.error('[idb-ts]:ERROR:', ...error);
|
|
534
|
+
};
|
|
542
535
|
this.dbName = dbName;
|
|
536
|
+
this.printEnabled = printEnabled;
|
|
543
537
|
if (!classes.every((cls) => Reflect.getMetadata('dataclass', cls))) {
|
|
544
538
|
throw new Error('All classes should be decorated with @DataClass.');
|
|
545
539
|
}
|
|
@@ -579,7 +573,7 @@ class Database {
|
|
|
579
573
|
const db = request.result;
|
|
580
574
|
const oldVersion = event.oldVersion;
|
|
581
575
|
const newVersion = event.newVersion || this.dbVersion;
|
|
582
|
-
|
|
576
|
+
this.printDebug(`Database upgrade from version ${oldVersion} to ${newVersion}`);
|
|
583
577
|
this.classes.forEach((cls) => {
|
|
584
578
|
var _a;
|
|
585
579
|
const keyPathMetadata = Reflect.getMetadata('keypath', cls);
|
|
@@ -588,7 +582,7 @@ class Database {
|
|
|
588
582
|
const storeName = cls.name.toLowerCase();
|
|
589
583
|
if (classVersion > oldVersion) {
|
|
590
584
|
if (!db.objectStoreNames.contains(storeName)) {
|
|
591
|
-
|
|
585
|
+
this.printDebug(`Creating object store: ${storeName} (version ${classVersion})`);
|
|
592
586
|
const storeOptions = {};
|
|
593
587
|
if (keyPathMetadata) {
|
|
594
588
|
storeOptions.keyPath = keyPathMetadata.fields;
|
|
@@ -611,7 +605,7 @@ class Database {
|
|
|
611
605
|
});
|
|
612
606
|
}
|
|
613
607
|
else {
|
|
614
|
-
|
|
608
|
+
this.printDebug(`Updating object store: ${storeName} (version ${classVersion})`);
|
|
615
609
|
const transaction = request.transaction;
|
|
616
610
|
if (transaction) {
|
|
617
611
|
const store = transaction.objectStore(storeName);
|
|
@@ -624,7 +618,7 @@ class Database {
|
|
|
624
618
|
? { unique: false }
|
|
625
619
|
: ((_a = indexField.options) !== null && _a !== void 0 ? _a : { unique: false });
|
|
626
620
|
if (!store.indexNames.contains(indexName)) {
|
|
627
|
-
|
|
621
|
+
this.printDebug(`Adding index: ${indexName} to ${storeName}`);
|
|
628
622
|
store.createIndex(indexName, indexName, indexOptions);
|
|
629
623
|
}
|
|
630
624
|
});
|
|
@@ -635,12 +629,12 @@ class Database {
|
|
|
635
629
|
};
|
|
636
630
|
request.onsuccess = () => {
|
|
637
631
|
this.db = request.result;
|
|
638
|
-
|
|
632
|
+
this.printDebug(`Database initialized (version ${this.dbVersion}) with object stores for: ${this.classes.map((cls) => `${cls.name}(v${Reflect.getMetadata('version', cls) || 1})`).join(', ')}`);
|
|
639
633
|
this.startRetentionCleanup();
|
|
640
634
|
resolve();
|
|
641
635
|
};
|
|
642
636
|
request.onerror = () => {
|
|
643
|
-
|
|
637
|
+
this.printError('Error initializing database:', request.error);
|
|
644
638
|
reject(request.error);
|
|
645
639
|
};
|
|
646
640
|
});
|
|
@@ -681,7 +675,7 @@ class Database {
|
|
|
681
675
|
if (!cleanupIntervalMs || !this.db || this.retentionTimer) {
|
|
682
676
|
return;
|
|
683
677
|
}
|
|
684
|
-
|
|
678
|
+
this.printDebug(`Retention cleanup enabled for ${this.retentionPolicies.length} entities every ${cleanupIntervalMs}ms`);
|
|
685
679
|
void this.runRetentionCleanup();
|
|
686
680
|
this.retentionTimer = setInterval(() => {
|
|
687
681
|
void this.runRetentionCleanup();
|
|
@@ -696,11 +690,11 @@ class Database {
|
|
|
696
690
|
}
|
|
697
691
|
this.retentionCleanupRunning = true;
|
|
698
692
|
try {
|
|
699
|
-
|
|
693
|
+
this.printDebug('Retention cleanup tick started');
|
|
700
694
|
for (const { storeName, className, policy } of this.retentionPolicies) {
|
|
701
695
|
yield this.cleanupExpiredRecords(storeName, className, policy);
|
|
702
696
|
}
|
|
703
|
-
|
|
697
|
+
this.printDebug('Retention cleanup tick finished');
|
|
704
698
|
}
|
|
705
699
|
finally {
|
|
706
700
|
this.retentionCleanupRunning = false;
|
|
@@ -724,11 +718,11 @@ class Database {
|
|
|
724
718
|
}
|
|
725
719
|
const value = cursor.value;
|
|
726
720
|
const timestamp = value === null || value === void 0 ? void 0 : value[policy.field];
|
|
727
|
-
|
|
721
|
+
this.printDebug(`Retention cleanup inspecting ${className}.${policy.field}:`, timestamp, 'cutoff:', cutoff);
|
|
728
722
|
if (typeof timestamp === 'number' && timestamp <= cutoff) {
|
|
729
723
|
const deleteRequest = cursor.delete();
|
|
730
724
|
deleteRequest.onsuccess = () => {
|
|
731
|
-
|
|
725
|
+
this.printDebug(`Retention cleanup removed expired record from ${className}`);
|
|
732
726
|
cursor.continue();
|
|
733
727
|
};
|
|
734
728
|
deleteRequest.onerror = () => {
|
|
@@ -889,7 +883,7 @@ class Database {
|
|
|
889
883
|
applyTimestampFields(item);
|
|
890
884
|
return this.performOperation(cls.name, 'readwrite', (store) => {
|
|
891
885
|
return createStoredItem(store, item).then(() => {
|
|
892
|
-
|
|
886
|
+
this.printDebug(`Item added to ${cls.name}:`, item);
|
|
893
887
|
});
|
|
894
888
|
}, transaction);
|
|
895
889
|
}),
|
|
@@ -904,7 +898,7 @@ class Database {
|
|
|
904
898
|
const request = store.get(key);
|
|
905
899
|
return new Promise((resolve, reject) => {
|
|
906
900
|
request.onsuccess = () => {
|
|
907
|
-
|
|
901
|
+
this.printDebug(`Item read from ${cls.name}:`, request.result);
|
|
908
902
|
resolve(request.result);
|
|
909
903
|
};
|
|
910
904
|
request.onerror = () => reject(request.error);
|
|
@@ -915,7 +909,7 @@ class Database {
|
|
|
915
909
|
validateItem(item);
|
|
916
910
|
return this.performOperation(cls.name, 'readwrite', (store) => {
|
|
917
911
|
return updateStoredItem(store, item).then(() => {
|
|
918
|
-
|
|
912
|
+
this.printDebug(`Item updated in ${cls.name}:`, item);
|
|
919
913
|
});
|
|
920
914
|
}, transaction);
|
|
921
915
|
}),
|
|
@@ -928,7 +922,7 @@ class Database {
|
|
|
928
922
|
delete: (key) => __awaiter(this, void 0, void 0, function* () {
|
|
929
923
|
return this.performOperation(cls.name, 'readwrite', (store) => {
|
|
930
924
|
return deleteStoredItem(store, key).then(() => {
|
|
931
|
-
|
|
925
|
+
this.printDebug(`Item deleted from ${cls.name}:`, key);
|
|
932
926
|
});
|
|
933
927
|
}, transaction);
|
|
934
928
|
}),
|
|
@@ -954,7 +948,7 @@ class Database {
|
|
|
954
948
|
const request = store.getAll();
|
|
955
949
|
return new Promise((resolve, reject) => {
|
|
956
950
|
request.onsuccess = () => {
|
|
957
|
-
|
|
951
|
+
this.printDebug(`All items from ${cls.name}:`, request.result);
|
|
958
952
|
resolve(request.result);
|
|
959
953
|
};
|
|
960
954
|
request.onerror = () => reject(request.error);
|
|
@@ -968,7 +962,7 @@ class Database {
|
|
|
968
962
|
request.onsuccess = () => {
|
|
969
963
|
const items = request.result;
|
|
970
964
|
const paginatedItems = items.slice((page - 1) * pageSize, page * pageSize);
|
|
971
|
-
|
|
965
|
+
this.printDebug(`Paginated items from ${cls.name}:`, paginatedItems);
|
|
972
966
|
resolve(paginatedItems);
|
|
973
967
|
};
|
|
974
968
|
request.onerror = () => reject(request.error);
|
|
@@ -984,7 +978,7 @@ class Database {
|
|
|
984
978
|
const request = index.getAll(value);
|
|
985
979
|
return new Promise((resolve, reject) => {
|
|
986
980
|
request.onsuccess = () => {
|
|
987
|
-
|
|
981
|
+
this.printDebug(`Items found by index ${indexName} with value ${value}:`, request.result);
|
|
988
982
|
resolve(request.result);
|
|
989
983
|
};
|
|
990
984
|
request.onerror = () => reject(request.error);
|
|
@@ -1000,7 +994,7 @@ class Database {
|
|
|
1000
994
|
const request = index.get(value);
|
|
1001
995
|
return new Promise((resolve, reject) => {
|
|
1002
996
|
request.onsuccess = () => {
|
|
1003
|
-
|
|
997
|
+
this.printDebug(`Item found by index ${indexName} with value ${value}:`, request.result);
|
|
1004
998
|
resolve(request.result);
|
|
1005
999
|
};
|
|
1006
1000
|
request.onerror = () => reject(request.error);
|
|
@@ -1012,7 +1006,7 @@ class Database {
|
|
|
1012
1006
|
const request = store.count();
|
|
1013
1007
|
return new Promise((resolve, reject) => {
|
|
1014
1008
|
request.onsuccess = () => {
|
|
1015
|
-
|
|
1009
|
+
this.printDebug(`Count for ${cls.name}:`, request.result);
|
|
1016
1010
|
resolve(request.result);
|
|
1017
1011
|
};
|
|
1018
1012
|
request.onerror = () => reject(request.error);
|
|
@@ -1025,7 +1019,7 @@ class Database {
|
|
|
1025
1019
|
return new Promise((resolve, reject) => {
|
|
1026
1020
|
request.onsuccess = () => {
|
|
1027
1021
|
const exists = request.result > 0;
|
|
1028
|
-
|
|
1022
|
+
this.printDebug(`Exists check for ${cls.name} with key ${key}:`, exists);
|
|
1029
1023
|
resolve(exists);
|
|
1030
1024
|
};
|
|
1031
1025
|
request.onerror = () => reject(request.error);
|
|
@@ -1037,7 +1031,7 @@ class Database {
|
|
|
1037
1031
|
const request = store.clear();
|
|
1038
1032
|
return new Promise((resolve, reject) => {
|
|
1039
1033
|
request.onsuccess = () => {
|
|
1040
|
-
|
|
1034
|
+
this.printDebug(`Cleared all items from ${cls.name}`);
|
|
1041
1035
|
resolve();
|
|
1042
1036
|
};
|
|
1043
1037
|
request.onerror = () => reject(request.error);
|
|
@@ -1162,4 +1156,5 @@ class Database {
|
|
|
1162
1156
|
return cls ? Reflect.getMetadata('version', cls) || 1 : undefined;
|
|
1163
1157
|
}
|
|
1164
1158
|
}
|
|
1165
|
-
|
|
1159
|
+
|
|
1160
|
+
export { CompositeKeyPath, DataClass, Database, Index, KeyGenerators, KeyPath, RetentionPolicy, Validate };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "idb-ts",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "Easy CRUD for indexed-db, written in TypeScript",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.esm.js",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"prepare": "pnpm run build",
|
|
18
|
-
"build": "pnpm run build:tsc && pnpm run build:rollup",
|
|
19
|
-
"build:tsc": "tsc",
|
|
18
|
+
"build": "rm -rf lib && pnpm run build:tsc && pnpm run build:rollup",
|
|
19
|
+
"build:tsc": "tsc -p tsconfig.build.json",
|
|
20
20
|
"build:rollup": "rollup -c",
|
|
21
21
|
"lint": "eslint .",
|
|
22
22
|
"lint:fix": "prettier --write . && eslint . --fix",
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"test:types": "tsc -p tsconfig.test.json --noEmit",
|
|
26
26
|
"test:watch": "jest --watchAll --runInBand --detectOpenHandles",
|
|
27
27
|
"test:coverage": "jest --coverage --runInBand --detectOpenHandles",
|
|
28
|
-
"test:coverage:watch": "jest --coverage --watchAll --runInBand --detectOpenHandles"
|
|
28
|
+
"test:coverage:watch": "jest --coverage --watchAll --runInBand --detectOpenHandles",
|
|
29
|
+
"test:performance": "npx tsx performance.ts",
|
|
30
|
+
"docs:generate": "typedoc"
|
|
29
31
|
},
|
|
30
32
|
"repository": {
|
|
31
33
|
"type": "git",
|
|
@@ -70,6 +72,7 @@
|
|
|
70
72
|
"prettier": "^3.8.3",
|
|
71
73
|
"rollup": "^4.60.1",
|
|
72
74
|
"ts-jest": "^29.4.9",
|
|
75
|
+
"typedoc": "^0.28.19",
|
|
73
76
|
"typescript": "^6.0.3"
|
|
74
77
|
}
|
|
75
|
-
}
|
|
78
|
+
}
|
package/lib/jest.setup.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import 'fake-indexeddb/auto';
|
package/lib/jest.setup.js
DELETED