idb-ts 3.2.0 → 3.7.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/lib/index.esm.js CHANGED
@@ -1,60 +1,298 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.DataClass = exports.KeyPath = exports.Database = void 0;
2
+ exports.KeyGenerators = exports.Index = exports.DataClass = exports.CompositeKeyPath = exports.KeyPath = exports.Database = void 0;
3
3
  const tslib_1 = require("tslib");
4
4
  require("reflect-metadata");
5
- function KeyPath() {
5
+ class QueryBuilder {
6
+ constructor(db, storeName) {
7
+ this.conditions = [];
8
+ this.orderDirection = 'asc';
9
+ this.db = db;
10
+ this.storeName = storeName;
11
+ }
12
+ where(field) {
13
+ this.currentField = field;
14
+ return this;
15
+ }
16
+ and(field) {
17
+ this.currentField = field;
18
+ return this;
19
+ }
20
+ equals(value) {
21
+ if (!this.currentField)
22
+ throw new Error('No field specified for equals');
23
+ this.conditions.push({ field: this.currentField, op: 'equals', value });
24
+ this.currentField = undefined;
25
+ return this;
26
+ }
27
+ gt(value) {
28
+ if (!this.currentField)
29
+ throw new Error('No field specified for gt');
30
+ this.conditions.push({ field: this.currentField, op: 'gt', value });
31
+ this.currentField = undefined;
32
+ return this;
33
+ }
34
+ gte(value) {
35
+ if (!this.currentField)
36
+ throw new Error('No field specified for gte');
37
+ this.conditions.push({ field: this.currentField, op: 'gte', value });
38
+ this.currentField = undefined;
39
+ return this;
40
+ }
41
+ lt(value) {
42
+ if (!this.currentField)
43
+ throw new Error('No field specified for lt');
44
+ this.conditions.push({ field: this.currentField, op: 'lt', value });
45
+ this.currentField = undefined;
46
+ return this;
47
+ }
48
+ lte(value) {
49
+ if (!this.currentField)
50
+ throw new Error('No field specified for lte');
51
+ this.conditions.push({ field: this.currentField, op: 'lte', value });
52
+ this.currentField = undefined;
53
+ return this;
54
+ }
55
+ orderBy(field, direction = 'asc') {
56
+ this.orderField = field;
57
+ this.orderDirection = direction;
58
+ return this;
59
+ }
60
+ limit(n) {
61
+ this.limitCount = n;
62
+ return this;
63
+ }
64
+ offset(n) {
65
+ this.offsetCount = n;
66
+ return this;
67
+ }
68
+ useIndex(indexName) {
69
+ this.indexName = indexName;
70
+ return this;
71
+ }
72
+ range(start, end) {
73
+ this.rangeStart = start;
74
+ this.rangeEnd = end;
75
+ return this;
76
+ }
77
+ execute() {
78
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
79
+ return new Promise((resolve, reject) => {
80
+ const tx = this.db.transaction(this.storeName, 'readonly');
81
+ let store = tx.objectStore(this.storeName);
82
+ let request;
83
+ let results = [];
84
+ if (this.indexName) {
85
+ if (!store.indexNames.contains(this.indexName)) {
86
+ reject(new Error(`Index '${this.indexName}' does not exist on ${this.storeName}`));
87
+ return;
88
+ }
89
+ const index = store.index(this.indexName);
90
+ let keyRange;
91
+ if (this.rangeStart !== undefined && this.rangeEnd !== undefined) {
92
+ keyRange = IDBKeyRange.bound(this.rangeStart, this.rangeEnd);
93
+ }
94
+ else if (this.rangeStart !== undefined) {
95
+ keyRange = IDBKeyRange.lowerBound(this.rangeStart);
96
+ }
97
+ else if (this.rangeEnd !== undefined) {
98
+ keyRange = IDBKeyRange.upperBound(this.rangeEnd);
99
+ }
100
+ request = index.openCursor(keyRange);
101
+ }
102
+ else {
103
+ request = store.openCursor();
104
+ }
105
+ request.onsuccess = () => {
106
+ const cursor = request.result;
107
+ if (cursor) {
108
+ let match = true;
109
+ const value = cursor.value;
110
+ for (const cond of this.conditions) {
111
+ const val = value[cond.field];
112
+ switch (cond.op) {
113
+ case 'equals':
114
+ match = match && val === cond.value;
115
+ break;
116
+ case 'gt':
117
+ match = match && val > cond.value;
118
+ break;
119
+ case 'gte':
120
+ match = match && val >= cond.value;
121
+ break;
122
+ case 'lt':
123
+ match = match && val < cond.value;
124
+ break;
125
+ case 'lte':
126
+ match = match && val <= cond.value;
127
+ break;
128
+ }
129
+ }
130
+ if (match)
131
+ results.push(value);
132
+ cursor.continue();
133
+ }
134
+ else {
135
+ if (this.orderField) {
136
+ results.sort((a, b) => {
137
+ const va = a[this.orderField];
138
+ const vb = b[this.orderField];
139
+ if (va < vb)
140
+ return this.orderDirection === 'asc' ? -1 : 1;
141
+ if (va > vb)
142
+ return this.orderDirection === 'asc' ? 1 : -1;
143
+ return 0;
144
+ });
145
+ }
146
+ if (this.offsetCount !== undefined)
147
+ results = results.slice(this.offsetCount);
148
+ if (this.limitCount !== undefined)
149
+ results = results.slice(0, this.limitCount);
150
+ resolve(results);
151
+ }
152
+ };
153
+ request.onerror = () => reject(request.error);
154
+ });
155
+ });
156
+ }
157
+ }
158
+ class KeyGenerators {
159
+ static uuid() {
160
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
161
+ const r = Math.random() * 16 | 0;
162
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
163
+ return v.toString(16);
164
+ });
165
+ }
166
+ static timestamp() {
167
+ return Date.now();
168
+ }
169
+ static random() {
170
+ return Math.random().toString(36).substring(2, 15);
171
+ }
172
+ }
173
+ exports.KeyGenerators = KeyGenerators;
174
+ function KeyPath(options) {
6
175
  return (target, propertyKey) => {
7
176
  const constructor = target.constructor;
8
- Reflect.defineMetadata("keypath", [propertyKey], constructor);
177
+ const existingKeypaths = Reflect.getMetadata("individual_keypaths", constructor) || [];
178
+ existingKeypaths.push(propertyKey);
179
+ Reflect.defineMetadata("individual_keypaths", existingKeypaths, constructor);
180
+ const metadata = {
181
+ fields: propertyKey,
182
+ options: options
183
+ };
184
+ Reflect.defineMetadata("keypath", metadata, constructor);
9
185
  };
10
186
  }
11
187
  exports.KeyPath = KeyPath;
12
- function DataClass() {
188
+ function CompositeKeyPath(fields, options) {
189
+ return (target) => {
190
+ const metadata = {
191
+ fields: fields,
192
+ options: options
193
+ };
194
+ Reflect.defineMetadata("keypath", metadata, target);
195
+ };
196
+ }
197
+ exports.CompositeKeyPath = CompositeKeyPath;
198
+ function Index() {
199
+ return (target, propertyKey) => {
200
+ const constructor = target.constructor;
201
+ const existing = Reflect.getMetadata("indexes", constructor) || [];
202
+ Reflect.defineMetadata("indexes", [...existing, propertyKey], constructor);
203
+ };
204
+ }
205
+ exports.Index = Index;
206
+ function DataClass(options = {}) {
13
207
  return (target) => {
14
- if (!Reflect.getMetadata("keypath", target)) {
208
+ const keyPathMetadata = Reflect.getMetadata("keypath", target);
209
+ if (!keyPathMetadata) {
15
210
  throw new Error(`No keypath field defined for the class ${target.name}.`);
16
211
  }
17
- const keyPathFields = Reflect.getMetadata("keypath", target) || [];
18
- if (keyPathFields.length > 1) {
212
+ const individualKeypaths = Reflect.getMetadata("individual_keypaths", target) || [];
213
+ if (individualKeypaths.length > 1) {
19
214
  throw new Error(`Only one keypath field can be defined for the class ${target.name}.`);
20
215
  }
216
+ const version = options.version || 1;
21
217
  Reflect.defineMetadata("dataclass", true, target);
218
+ Reflect.defineMetadata("version", version, target);
22
219
  };
23
220
  }
24
221
  exports.DataClass = DataClass;
25
222
  class Database {
26
223
  constructor(dbName, classes) {
27
224
  this.db = null;
225
+ this.entityRepositories = new Map();
28
226
  this.dbName = dbName;
29
227
  if (!classes.every(cls => Reflect.getMetadata("dataclass", cls))) {
30
228
  throw new Error("All classes should be decorated with @DataClass.");
31
229
  }
32
230
  this.classes = classes;
231
+ this.dbVersion = this.calculateDatabaseVersion();
232
+ }
233
+ calculateDatabaseVersion() {
234
+ const versions = this.classes.map(cls => Reflect.getMetadata("version", cls) || 1);
235
+ return Math.max(...versions);
33
236
  }
34
237
  static build(dbName, classes) {
35
238
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
36
239
  const instance = new Database(dbName, classes);
37
240
  yield instance.initDB();
241
+ instance.generateEntityRepositories();
38
242
  return instance;
39
243
  });
40
244
  }
41
245
  initDB() {
42
246
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
43
247
  return new Promise((resolve, reject) => {
44
- const request = indexedDB.open(this.dbName, 1);
45
- request.onupgradeneeded = () => {
248
+ const request = indexedDB.open(this.dbName, this.dbVersion);
249
+ request.onupgradeneeded = (event) => {
46
250
  const db = request.result;
251
+ const oldVersion = event.oldVersion;
252
+ const newVersion = event.newVersion || this.dbVersion;
253
+ console.debug(`Database upgrade from version ${oldVersion} to ${newVersion}`);
47
254
  this.classes.forEach((cls) => {
48
- const keyPathFields = Reflect.getMetadata("keypath", cls) || [];
49
- const storeName = cls.name.toLowerCase() + "s";
50
- if (!db.objectStoreNames.contains(storeName)) {
51
- db.createObjectStore(storeName, { keyPath: keyPathFields[0] });
255
+ var _a;
256
+ const keyPathMetadata = Reflect.getMetadata("keypath", cls);
257
+ const indexFields = Reflect.getMetadata("indexes", cls) || [];
258
+ const classVersion = Reflect.getMetadata("version", cls) || 1;
259
+ const storeName = cls.name.toLowerCase();
260
+ if (classVersion > oldVersion) {
261
+ if (!db.objectStoreNames.contains(storeName)) {
262
+ console.debug(`Creating object store: ${storeName} (version ${classVersion})`);
263
+ const storeOptions = {};
264
+ if (keyPathMetadata) {
265
+ storeOptions.keyPath = keyPathMetadata.fields;
266
+ if ((_a = keyPathMetadata.options) === null || _a === void 0 ? void 0 : _a.autoIncrement) {
267
+ storeOptions.autoIncrement = true;
268
+ }
269
+ }
270
+ const store = db.createObjectStore(storeName, storeOptions);
271
+ indexFields.forEach((indexField) => {
272
+ if (!store.indexNames.contains(indexField)) {
273
+ store.createIndex(indexField, indexField, { unique: false });
274
+ }
275
+ });
276
+ }
277
+ else {
278
+ console.debug(`Updating object store: ${storeName} (version ${classVersion})`);
279
+ const transaction = request.transaction;
280
+ if (transaction) {
281
+ const store = transaction.objectStore(storeName);
282
+ indexFields.forEach((indexField) => {
283
+ if (!store.indexNames.contains(indexField)) {
284
+ console.debug(`Adding index: ${indexField} to ${storeName}`);
285
+ store.createIndex(indexField, indexField, { unique: false });
286
+ }
287
+ });
288
+ }
289
+ }
52
290
  }
53
291
  });
54
292
  };
55
293
  request.onsuccess = () => {
56
294
  this.db = request.result;
57
- console.log(`Database initialized with object stores for: ${this.classes.map(cls => cls.name).join(", ")}`);
295
+ console.debug(`Database initialized (version ${this.dbVersion}) with object stores for: ${this.classes.map(cls => `${cls.name}(v${Reflect.getMetadata("version", cls) || 1})`).join(", ")}`);
58
296
  resolve();
59
297
  };
60
298
  request.onerror = () => {
@@ -64,118 +302,253 @@ class Database {
64
302
  });
65
303
  });
66
304
  }
67
- getObjectStore(className, mode) {
68
- if (!this.db) {
69
- throw new Error("Database not initialized.");
70
- }
71
- const storeName = className.toLowerCase() + "s";
72
- const transaction = this.db.transaction(storeName, mode);
73
- return transaction.objectStore(storeName);
74
- }
75
- create(cls, item) {
76
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
77
- return new Promise((resolve, reject) => {
78
- try {
79
- const store = this.getObjectStore(cls.name, "readwrite");
80
- const request = store.add(item);
81
- request.onsuccess = () => {
82
- console.log(`Item added to ${cls.name}:`, item);
83
- resolve();
84
- };
85
- request.onerror = () => {
86
- console.error(`Error adding item to ${cls.name}:`, request.error);
87
- reject(request.error);
88
- };
89
- }
90
- catch (error) {
91
- reject(error);
92
- }
305
+ generateEntityRepositories() {
306
+ this.classes.forEach(cls => {
307
+ const entityName = cls.name;
308
+ const repository = this.createEntityRepository(cls);
309
+ this.entityRepositories.set(entityName, repository);
310
+ Object.defineProperty(this, entityName, {
311
+ value: repository,
312
+ writable: false,
313
+ enumerable: true,
314
+ configurable: false
93
315
  });
94
316
  });
95
317
  }
96
- read(cls, key) {
97
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
98
- return new Promise((resolve, reject) => {
99
- try {
100
- const store = this.getObjectStore(cls.name, "readonly");
101
- const request = store.get(key);
102
- request.onsuccess = () => {
103
- console.log(`Item read from ${cls.name}:`, request.result);
104
- resolve(request.result);
105
- };
106
- request.onerror = () => {
107
- console.error(`Error reading item from ${cls.name}:`, request.error);
108
- reject(request.error);
109
- };
110
- }
111
- catch (error) {
112
- reject(error);
318
+ createEntityRepository(cls) {
319
+ const self = this;
320
+ const generateKey = (item) => {
321
+ var _a;
322
+ const keyPathMetadata = Reflect.getMetadata("keypath", cls);
323
+ if (!((_a = keyPathMetadata === null || keyPathMetadata === void 0 ? void 0 : keyPathMetadata.options) === null || _a === void 0 ? void 0 : _a.generator))
324
+ return undefined;
325
+ const generator = keyPathMetadata.options.generator;
326
+ if (typeof generator === 'function') {
327
+ return generator(item);
328
+ }
329
+ switch (generator) {
330
+ case 'uuid':
331
+ return KeyGenerators.uuid();
332
+ case 'timestamp':
333
+ return KeyGenerators.timestamp();
334
+ case 'random':
335
+ return KeyGenerators.random();
336
+ default:
337
+ return undefined;
338
+ }
339
+ };
340
+ const extractKey = (item) => {
341
+ const keyPathMetadata = Reflect.getMetadata("keypath", cls);
342
+ if (!keyPathMetadata)
343
+ return undefined;
344
+ const fields = keyPathMetadata.fields;
345
+ if (Array.isArray(fields)) {
346
+ return fields.map(field => item[field]);
347
+ }
348
+ else {
349
+ return item[fields];
350
+ }
351
+ };
352
+ const setKey = (item, key) => {
353
+ const keyPathMetadata = Reflect.getMetadata("keypath", cls);
354
+ if (!keyPathMetadata)
355
+ return;
356
+ const fields = keyPathMetadata.fields;
357
+ if (typeof fields === 'string') {
358
+ item[fields] = key;
359
+ }
360
+ };
361
+ return {
362
+ query() {
363
+ if (!self.db)
364
+ throw new Error('Database not initialized.');
365
+ const storeName = cls.name.toLowerCase();
366
+ return new QueryBuilder(self.db, storeName);
367
+ },
368
+ create: (item) => tslib_1.__awaiter(this, void 0, void 0, function* () {
369
+ var _a;
370
+ const keyPathMetadata = Reflect.getMetadata("keypath", cls);
371
+ if (((_a = keyPathMetadata === null || keyPathMetadata === void 0 ? void 0 : keyPathMetadata.options) === null || _a === void 0 ? void 0 : _a.generator) && !keyPathMetadata.options.autoIncrement) {
372
+ const currentKey = extractKey(item);
373
+ if (currentKey === undefined || currentKey === null || currentKey === '') {
374
+ const generatedKey = generateKey(item);
375
+ if (generatedKey !== undefined) {
376
+ setKey(item, generatedKey);
377
+ }
378
+ }
113
379
  }
114
- });
115
- });
116
- }
117
- update(cls, item) {
118
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
119
- return new Promise((resolve, reject) => {
120
- try {
121
- const store = this.getObjectStore(cls.name, "readwrite");
380
+ return this.performOperation(cls.name, 'readwrite', (store) => {
381
+ const request = store.add(item);
382
+ return new Promise((resolve, reject) => {
383
+ request.onsuccess = () => {
384
+ console.debug(`Item added to ${cls.name}:`, item);
385
+ resolve();
386
+ };
387
+ request.onerror = () => reject(request.error);
388
+ });
389
+ });
390
+ }),
391
+ read: (key) => tslib_1.__awaiter(this, void 0, void 0, function* () {
392
+ return this.performOperation(cls.name, 'readonly', (store) => {
393
+ const request = store.get(key);
394
+ return new Promise((resolve, reject) => {
395
+ request.onsuccess = () => {
396
+ console.debug(`Item read from ${cls.name}:`, request.result);
397
+ resolve(request.result);
398
+ };
399
+ request.onerror = () => reject(request.error);
400
+ });
401
+ });
402
+ }),
403
+ update: (item) => tslib_1.__awaiter(this, void 0, void 0, function* () {
404
+ return this.performOperation(cls.name, 'readwrite', (store) => {
122
405
  const request = store.put(item);
123
- request.onsuccess = () => {
124
- console.log(`Item updated in ${cls.name}:`, item);
125
- resolve();
126
- };
127
- request.onerror = () => {
128
- console.error(`Error updating item in ${cls.name}:`, request.error);
129
- reject(request.error);
130
- };
131
- }
132
- catch (error) {
133
- reject(error);
134
- }
135
- });
136
- });
406
+ return new Promise((resolve, reject) => {
407
+ request.onsuccess = () => {
408
+ console.debug(`Item updated in ${cls.name}:`, item);
409
+ resolve();
410
+ };
411
+ request.onerror = () => reject(request.error);
412
+ });
413
+ });
414
+ }),
415
+ delete: (key) => tslib_1.__awaiter(this, void 0, void 0, function* () {
416
+ return this.performOperation(cls.name, 'readwrite', (store) => {
417
+ const request = store.delete(key);
418
+ return new Promise((resolve, reject) => {
419
+ request.onsuccess = () => {
420
+ console.debug(`Item deleted from ${cls.name}:`, key);
421
+ resolve();
422
+ };
423
+ request.onerror = () => reject(request.error);
424
+ });
425
+ });
426
+ }),
427
+ list: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
428
+ return this.performOperation(cls.name, 'readonly', (store) => {
429
+ const request = store.getAll();
430
+ return new Promise((resolve, reject) => {
431
+ request.onsuccess = () => {
432
+ console.debug(`All items from ${cls.name}:`, request.result);
433
+ resolve(request.result);
434
+ };
435
+ request.onerror = () => reject(request.error);
436
+ });
437
+ });
438
+ }),
439
+ listPaginated: (page, pageSize) => tslib_1.__awaiter(this, void 0, void 0, function* () {
440
+ return this.performOperation(cls.name, 'readonly', (store) => {
441
+ const request = store.getAll();
442
+ return new Promise((resolve, reject) => {
443
+ request.onsuccess = () => {
444
+ const items = request.result;
445
+ const paginatedItems = items.slice((page - 1) * pageSize, page * pageSize);
446
+ console.debug(`Paginated items from ${cls.name}:`, paginatedItems);
447
+ resolve(paginatedItems);
448
+ };
449
+ request.onerror = () => reject(request.error);
450
+ });
451
+ });
452
+ }),
453
+ findByIndex: (indexName, value) => tslib_1.__awaiter(this, void 0, void 0, function* () {
454
+ return this.performOperation(cls.name, 'readonly', (store) => {
455
+ if (!store.indexNames.contains(indexName)) {
456
+ throw new Error(`Index '${indexName}' does not exist on ${cls.name}`);
457
+ }
458
+ const index = store.index(indexName);
459
+ const request = index.getAll(value);
460
+ return new Promise((resolve, reject) => {
461
+ request.onsuccess = () => {
462
+ console.debug(`Items found by index ${indexName} with value ${value}:`, request.result);
463
+ resolve(request.result);
464
+ };
465
+ request.onerror = () => reject(request.error);
466
+ });
467
+ });
468
+ }),
469
+ findOneByIndex: (indexName, value) => tslib_1.__awaiter(this, void 0, void 0, function* () {
470
+ return this.performOperation(cls.name, 'readonly', (store) => {
471
+ if (!store.indexNames.contains(indexName)) {
472
+ throw new Error(`Index '${indexName}' does not exist on ${cls.name}`);
473
+ }
474
+ const index = store.index(indexName);
475
+ const request = index.get(value);
476
+ return new Promise((resolve, reject) => {
477
+ request.onsuccess = () => {
478
+ console.debug(`Item found by index ${indexName} with value ${value}:`, request.result);
479
+ resolve(request.result);
480
+ };
481
+ request.onerror = () => reject(request.error);
482
+ });
483
+ });
484
+ }),
485
+ count: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
486
+ return this.performOperation(cls.name, 'readonly', (store) => {
487
+ const request = store.count();
488
+ return new Promise((resolve, reject) => {
489
+ request.onsuccess = () => {
490
+ console.debug(`Count for ${cls.name}:`, request.result);
491
+ resolve(request.result);
492
+ };
493
+ request.onerror = () => reject(request.error);
494
+ });
495
+ });
496
+ }),
497
+ exists: (key) => tslib_1.__awaiter(this, void 0, void 0, function* () {
498
+ return this.performOperation(cls.name, 'readonly', (store) => {
499
+ const request = store.count(key);
500
+ return new Promise((resolve, reject) => {
501
+ request.onsuccess = () => {
502
+ const exists = request.result > 0;
503
+ console.debug(`Exists check for ${cls.name} with key ${key}:`, exists);
504
+ resolve(exists);
505
+ };
506
+ request.onerror = () => reject(request.error);
507
+ });
508
+ });
509
+ }),
510
+ clear: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
511
+ return this.performOperation(cls.name, 'readwrite', (store) => {
512
+ const request = store.clear();
513
+ return new Promise((resolve, reject) => {
514
+ request.onsuccess = () => {
515
+ console.debug(`Cleared all items from ${cls.name}`);
516
+ resolve();
517
+ };
518
+ request.onerror = () => reject(request.error);
519
+ });
520
+ });
521
+ })
522
+ };
137
523
  }
138
- delete(cls, key) {
524
+ performOperation(className, mode, operation) {
139
525
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
140
- return new Promise((resolve, reject) => {
141
- try {
142
- const store = this.getObjectStore(cls.name, "readwrite");
143
- const request = store.delete(key);
144
- request.onsuccess = () => {
145
- console.log(`Item deleted from ${cls.name}:`, key);
146
- resolve();
147
- };
148
- request.onerror = () => {
149
- console.error(`Error deleting item from ${cls.name}:`, request.error);
150
- reject(request.error);
151
- };
152
- }
153
- catch (error) {
154
- reject(error);
155
- }
156
- });
526
+ if (!this.db) {
527
+ throw new Error("Database not initialized.");
528
+ }
529
+ const storeName = className.toLowerCase();
530
+ const transaction = this.db.transaction(storeName, mode);
531
+ const store = transaction.objectStore(storeName);
532
+ return operation(store);
157
533
  });
158
534
  }
159
- list(cls) {
160
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
161
- return new Promise((resolve, reject) => {
162
- try {
163
- const store = this.getObjectStore(cls.name, "readonly");
164
- const request = store.getAll();
165
- request.onsuccess = () => {
166
- console.log(`All items from ${cls.name}:`, request.result);
167
- resolve(request.result);
168
- };
169
- request.onerror = () => {
170
- console.error(`Error listing items from ${cls.name}:`, request.error);
171
- reject(request.error);
172
- };
173
- }
174
- catch (error) {
175
- reject(error);
176
- }
177
- });
535
+ getAvailableEntities() {
536
+ return Array.from(this.entityRepositories.keys());
537
+ }
538
+ getDatabaseVersion() {
539
+ return this.dbVersion;
540
+ }
541
+ getEntityVersions() {
542
+ const versions = new Map();
543
+ this.classes.forEach(cls => {
544
+ const version = Reflect.getMetadata("version", cls) || 1;
545
+ versions.set(cls.name, version);
178
546
  });
547
+ return versions;
548
+ }
549
+ getEntityVersion(entityName) {
550
+ const cls = this.classes.find(c => c.name === entityName);
551
+ return cls ? (Reflect.getMetadata("version", cls) || 1) : undefined;
179
552
  }
180
553
  }
181
554
  exports.Database = Database;