179 lines
6.1 KiB
TypeScript
179 lines
6.1 KiB
TypeScript
class Database {
|
|
private static instance: Database;
|
|
private db: IDBDatabase | null = null;
|
|
private dbName: string = '4nk';
|
|
private dbVersion: number = 1;
|
|
private storeDefinitions = {
|
|
AnkUser: {
|
|
name: "user",
|
|
options: {'keyPath': 'pre_id'},
|
|
indices: []
|
|
},
|
|
AnkSession: {
|
|
name: "session",
|
|
options: {},
|
|
indices: []
|
|
},
|
|
AnkProcess: {
|
|
name: "process",
|
|
options: {'keyPath': 'id'},
|
|
indices: [{
|
|
name: 'by_name',
|
|
keyPath: 'name',
|
|
options: {
|
|
'unique': true
|
|
}
|
|
}]
|
|
},
|
|
AnkMessages: {
|
|
name: "messages",
|
|
options: {'keyPath': 'id'},
|
|
indices: []
|
|
}
|
|
}
|
|
|
|
// Private constructor to prevent direct instantiation from outside
|
|
private constructor() {}
|
|
|
|
// Method to access the singleton instance of Database
|
|
public static async getInstance(): Promise<Database> {
|
|
if (!Database.instance) {
|
|
Database.instance = new Database();
|
|
await Database.instance.init();
|
|
}
|
|
return Database.instance;
|
|
}
|
|
|
|
// Initialize the database
|
|
private async init(): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
|
|
request.onupgradeneeded = () => {
|
|
const db = request.result;
|
|
|
|
Object.values(this.storeDefinitions).forEach(({name, options, indices}) => {
|
|
if (!db.objectStoreNames.contains(name)) {
|
|
let store = db.createObjectStore(name, options);
|
|
|
|
indices.forEach(({name, keyPath, options}) => {
|
|
store.createIndex(name, keyPath, options);
|
|
})
|
|
}
|
|
});
|
|
};
|
|
|
|
request.onsuccess = () => {
|
|
this.db = request.result;
|
|
resolve();
|
|
};
|
|
|
|
request.onerror = () => {
|
|
console.error("Database error:", request.error);
|
|
reject(request.error);
|
|
};
|
|
});
|
|
}
|
|
|
|
public async getDb(): Promise<IDBDatabase> {
|
|
if (!this.db) {
|
|
await this.init();
|
|
}
|
|
return this.db!;
|
|
}
|
|
|
|
public getStoreList(): {[key: string]: string} {
|
|
const objectList: {[key: string]: string} = {};
|
|
Object.keys(this.storeDefinitions).forEach(key => {
|
|
objectList[key] = this.storeDefinitions[key as keyof typeof this.storeDefinitions].name;
|
|
});
|
|
return objectList;
|
|
}
|
|
|
|
public writeObject(db: IDBDatabase, storeName: string, obj: any, key: IDBValidKey | null): Promise<IDBRequest> {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(storeName, 'readwrite');
|
|
const store = transaction.objectStore(storeName);
|
|
let request: IDBRequest<any>;
|
|
if (key) {
|
|
request = store.add(obj, key);
|
|
} else {
|
|
request = store.add(obj);
|
|
}
|
|
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => resolve(request.result);
|
|
});
|
|
}
|
|
|
|
public getObject<T>(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise<T> {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(storeName, 'readonly');
|
|
const store = transaction.objectStore(storeName);
|
|
const request = store.get(key);
|
|
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => resolve(request.result);
|
|
});
|
|
}
|
|
|
|
public rmObject(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(storeName, 'readwrite');
|
|
const store = transaction.objectStore(storeName);
|
|
const request = store.delete(key);
|
|
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => resolve(request.result);
|
|
});
|
|
}
|
|
|
|
public getFirstMatchWithIndex<T>(db: IDBDatabase, storeName: string, indexName: string, lookup: string): Promise<T | null> {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(storeName, 'readonly');
|
|
const store = transaction.objectStore(storeName);
|
|
const index = store.index(indexName);
|
|
const request = index.openCursor(IDBKeyRange.only(lookup));
|
|
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => {
|
|
const cursor = request.result;
|
|
if (cursor) {
|
|
resolve(cursor.value);
|
|
} else {
|
|
resolve(null)
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public setObject(db: IDBDatabase, storeName: string, obj: any, key: string | null): Promise<IDBRequest> {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(storeName, 'readwrite');
|
|
const store = transaction.objectStore(storeName);
|
|
let request: IDBRequest<any>;
|
|
if (key) {
|
|
request = store.put(obj, key);
|
|
} else {
|
|
request = store.put(obj);
|
|
}
|
|
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => resolve(request.result);
|
|
});
|
|
}
|
|
|
|
public getAll<T>(db: IDBDatabase, storeName: string): Promise<T[]> {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(storeName, 'readonly');
|
|
const store = transaction.objectStore(storeName);
|
|
const request = store.getAll();
|
|
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => resolve(request.result);
|
|
});
|
|
}
|
|
}
|
|
|
|
export default Database;
|