idb-ts 3.3.0 → 3.8.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.debug(`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,141 +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.debug(`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.debug(`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.debug(`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
- });
137
- }
138
- delete(cls, key) {
139
- 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");
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) => {
143
417
  const request = store.delete(key);
144
- request.onsuccess = () => {
145
- console.debug(`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
- });
157
- });
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
+ };
158
523
  }
159
- list(cls) {
524
+ performOperation(className, mode, operation) {
160
525
  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.debug(`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
- });
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);
178
533
  });
179
534
  }
180
- listPaginated(cls, page, pageSize) {
181
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
182
- return new Promise((resolve, reject) => {
183
- try {
184
- const store = this.getObjectStore(cls.name, "readonly");
185
- const request = store.getAll();
186
- request.onsuccess = () => {
187
- const items = request.result;
188
- const paginatedItems = items.slice((page - 1) * pageSize, page * pageSize);
189
- console.debug(`Paginated items from ${cls.name}:`, paginatedItems);
190
- resolve(paginatedItems);
191
- };
192
- request.onerror = () => {
193
- console.error(`Error listing items from ${cls.name}:`, request.error);
194
- reject(request.error);
195
- };
196
- }
197
- catch (error) {
198
- reject(error);
199
- }
200
- });
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);
201
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;
202
552
  }
203
553
  }
204
554
  exports.Database = Database;