Fixed using numbers as database table name
All checks were successful
Build / Build NPM Project (push) Successful in 1m16s
Build / Tag Version (push) Successful in 15s
Build / Publish Documentation (push) Successful in 53s

This commit is contained in:
Zakary Timson 2025-05-27 14:51:04 -04:00
parent 6d706d4c15
commit e19768688d
3 changed files with 16 additions and 36 deletions

View File

@ -3,27 +3,7 @@
<script type="module"> <script type="module">
import {Cache, Database} from './dist/index.mjs'; import {Cache, Database} from './dist/index.mjs';
const db = new Database('test', ['test', 'test2', 'test3']); const db = new Database('test', []);
const cache = new Cache('id', {
ttl: 60,
storage: db.table('test'),
expiryPolicy: 'delete'
});
const cache2 = new Cache('id', {
ttl: 60,
storage: db.table('test2'),
expiryPolicy: 'delete'
});
const cache3 = new Cache('id', {
ttl: 60,
storage: db.table('test3'),
expiryPolicy: 'delete'
});
console.log(cache3.all());
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,6 +1,6 @@
{ {
"name": "@ztimson/utils", "name": "@ztimson/utils",
"version": "0.25.3", "version": "0.25.4",
"description": "Utility library", "description": "Utility library",
"author": "Zak Timson", "author": "Zak Timson",
"license": "MIT", "license": "MIT",

View File

@ -1,3 +1,5 @@
import {ASet} from './aset.ts';
export type TableOptions = { export type TableOptions = {
name: string; name: string;
key?: string; key?: string;
@ -9,12 +11,13 @@ export class Database {
constructor(public readonly database: string, public readonly tables: (string | TableOptions)[], public version?: number) { constructor(public readonly database: string, public readonly tables: (string | TableOptions)[], public version?: number) {
this.connection = new Promise((resolve, reject) => { this.connection = new Promise((resolve, reject) => {
const req = indexedDB.open(this.database, this.version); const req = indexedDB.open(this.database, this.version);
const tableNames = new ASet(tables.map(t => (typeof t == 'object' ? t.name : t).toString()));
req.onerror = () => reject(req.error); req.onerror = () => reject(req.error);
req.onsuccess = () => { req.onsuccess = () => {
const db = req.result; const db = req.result;
if(tables.find(s => !db.objectStoreNames.contains(typeof s === 'string' ? s : s.name))) { if(tableNames.symmetricDifference(new ASet(Array.from(db.objectStoreNames))).length) {
db.close(); db.close();
Object.assign(this, new Database(this.database, this.tables, db.version + 1)); Object.assign(this, new Database(this.database, this.tables, db.version + 1));
} else { } else {
@ -25,14 +28,11 @@ export class Database {
req.onupgradeneeded = () => { req.onupgradeneeded = () => {
const db = req.result; const db = req.result;
Array.from(db.objectStoreNames) const existingTables = new ASet(Array.from(db.objectStoreNames));
.filter(s => !this.tables.find(t => typeof t === 'string' ? t : t.name == s)) console.log('delete', existingTables.difference(tableNames));
.forEach(name => db.deleteObjectStore(name)); existingTables.difference(tableNames).forEach(name => db.deleteObjectStore(name));
tables.filter(t => !db.objectStoreNames.contains(typeof t === 'string' ? t : t.name)) console.log('create', tableNames.difference(existingTables));
.forEach(t => {db.createObjectStore(typeof t === 'string' ? t : t.name, { tableNames.difference(existingTables).forEach(name => db.createObjectStore(name));
keyPath: typeof t === 'string' ? undefined : t.key
});
});
}; };
}); });
} }
@ -41,18 +41,18 @@ export class Database {
return this.tables.some(t => (typeof t === 'string' ? name === t : name === t.name)); return this.tables.some(t => (typeof t === 'string' ? name === t : name === t.name));
} }
table<K extends IDBValidKey = any, T = any>(name: string): Table<K, T> { table<K extends IDBValidKey = any, T = any>(name: any): Table<K, T> {
return new Table<K, T>(this, name); return new Table<K, T>(this, name.toString());
} }
} }
export class Table<K extends IDBValidKey = any, T = any> { export class Table<K extends IDBValidKey = any, T = any> {
constructor(private readonly database: Database, public readonly name: string) {} constructor(private readonly database: Database, public readonly name: string) {}
async tx<R>(schema: string, fn: (store: IDBObjectStore) => IDBRequest, readonly = false): Promise<R> { async tx<R>(table: string, fn: (store: IDBObjectStore) => IDBRequest, readonly = false): Promise<R> {
const db = await this.database.connection; const db = await this.database.connection;
const tx = db.transaction(schema, readonly ? 'readonly' : 'readwrite'); const tx = db.transaction(table, readonly ? 'readonly' : 'readwrite');
const store = tx.objectStore(schema); const store = tx.objectStore(table);
return new Promise<R>((resolve, reject) => { return new Promise<R>((resolve, reject) => {
const request = fn(store); const request = fn(store);
request.onsuccess = () => resolve(request.result as R); // ✅ explicit cast request.onsuccess = () => resolve(request.result as R); // ✅ explicit cast