diff --git a/.vscode/settings.json b/.vscode/settings.json index 52de813..c1c5ee8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,26 +1,6 @@ { - "workbench.colorCustomizations": { - "activityBar.activeBackground": "#66b2f4", - "activityBar.background": "#66b2f4", - "activityBar.foreground": "#15202b", - "activityBar.inactiveForeground": "#15202b99", - "activityBarBadge.background": "#d00f76", - "activityBarBadge.foreground": "#e7e7e7", - "commandCenter.border": "#15202b99", - "sash.hoverBorder": "#66b2f4", - "statusBar.background": "#369af1", - "statusBar.foreground": "#15202b", - "statusBarItem.hoverBackground": "#1081e4", - "statusBarItem.remoteBackground": "#369af1", - "statusBarItem.remoteForeground": "#15202b", - "titleBar.activeBackground": "#369af1", - "titleBar.activeForeground": "#15202b", - "titleBar.inactiveBackground": "#369af199", - "titleBar.inactiveForeground": "#15202b99" - }, - "peacock.remoteColor": "#369af1", "deno.enable": true, "deno.unstable": true, "deno.config": "./deno.jsonc", - "svg.preview.background": "black" + "svg.preview.background": "white" } \ No newline at end of file diff --git a/project-warstone/src/utils/indexeddb.ts b/project-warstone/src/utils/indexeddb.ts new file mode 100644 index 0000000..419023c --- /dev/null +++ b/project-warstone/src/utils/indexeddb.ts @@ -0,0 +1,168 @@ +class IndexedDBService { + private dbName: string; + private dbVersion: number; + private storeNames: string[]; + private db: IDBDatabase | null = null; + + constructor(dbName: string, dbVersion: number, storeNames: string[]) { + this.dbName = dbName; + this.dbVersion = dbVersion; + this.storeNames = storeNames; + } + + private async openDB(): Promise { + if (this.db) return this.db; + + return new Promise((resolve, reject) => { + const request = indexedDB.open(this.dbName, this.dbVersion); + + request.onerror = () => { + reject(new Error('Failed to open the database.')); + }; + + request.onsuccess = () => { + this.db = request.result; + resolve(this.db); + }; + + request.onupgradeneeded = (event) => { + const db = (event.target as IDBOpenDBRequest).result; + + // Create all the required object stores during the upgrade + for (const storeName of this.storeNames) { + if (!db.objectStoreNames.contains(storeName)) { + db.createObjectStore(storeName, { keyPath: 'uuid' }); + } + } + }; + + request.onblocked = () => { + reject(new Error('Database is blocked and cannot be accessed.')); + }; + }); + } + + private generateUUID(): string { + return crypto.randomUUID(); + } + + public async create(data: any): Promise { + const db = await this.openDB(); + const uuid = this.generateUUID(); + return new Promise((resolve, reject) => { + const transaction = db.transaction(data.storeName, 'readwrite'); + const objectStore = transaction.objectStore(data.storeName); + + const request = objectStore.add({ ...data, uuid }); + + request.onsuccess = () => { + resolve(uuid); + }; + + request.onerror = () => { + reject(new Error('Failed to add data to IndexedDB.')); + }; + }); + } + + public async read(storeName: string, uuid: string): Promise { + const db = await this.openDB(); + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readonly'); + const objectStore = transaction.objectStore(storeName); + + const request = objectStore.get(uuid); + + request.onsuccess = () => { + resolve(request.result); + }; + + request.onerror = () => { + reject(new Error('Failed to read data from IndexedDB.')); + }; + }); + } + + public async update(storeName: string, uuid: string, newData: any): Promise { + const db = await this.openDB(); + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readwrite'); + const objectStore = transaction.objectStore(storeName); + + const request = objectStore.put({ ...newData, uuid }, uuid); + + request.onsuccess = () => { + resolve(); + }; + + request.onerror = () => { + reject(new Error('Failed to update data in IndexedDB.')); + }; + }); + } + + public async delete(storeName: string, uuid: string): Promise { + const db = await this.openDB(); + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readwrite'); + const objectStore = transaction.objectStore(storeName); + + const request = objectStore.delete(uuid); + + request.onsuccess = () => { + resolve(); + }; + + request.onerror = () => { + reject(new Error('Failed to delete data from IndexedDB.')); + }; + }); + } + + public async listAll(storeName: string, fieldName: string): Promise<[string, any][]> { + const db = await this.openDB(); + + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readonly'); + const objectStore = transaction.objectStore(storeName); + const request = objectStore.openCursor(); + + const results: [string, any][] = []; + + request.onsuccess = (event) => { + const cursor: IDBCursorWithValue = (event.target as IDBRequest).result; + if (cursor) { + const data = cursor.value; + if (fieldName in data) { + results.push([data.uuid, data[fieldName]]); + } + cursor.continue(); + } else { + resolve(results); + } + }; + + request.onerror = () => { + reject(new Error('Failed to list data from IndexedDB.')); + }; + }); + } + + public async createOrUpdate(data: any): Promise { + const db = await this.openDB(); + + // If the provided data already has a UUID, check if it exists in the database + if (data.uuid) { + const existingData = await this.read(data.storeName, data.uuid); + if (existingData) { + await this.update(data.storeName, data.uuid, data); + return data.uuid; + } + } + + // Generate a new UUID for the data and use the create method + const uuid = this.generateUUID(); + await this.create({ ...data, uuid, storeName: data.storeName }); + return uuid; + } +}