Delete store definition
This commit is contained in:
parent
71d0d14095
commit
f74fcabec7
@ -1,467 +1,429 @@
|
|||||||
import Services from './service';
|
import Services from './service';
|
||||||
|
|
||||||
export class Database {
|
export class Database {
|
||||||
private static instance: Database;
|
private static instance: Database;
|
||||||
private db: IDBDatabase | null = null;
|
private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;
|
||||||
private dbName: string = '4nk';
|
private serviceWorkerCheckIntervalId: number | null = null;
|
||||||
private dbVersion: number = 1;
|
private indexedDBWorker: Worker | null = null;
|
||||||
private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;
|
private messageIdCounter: number = 0;
|
||||||
private messageChannel: MessageChannel | null = null;
|
private pendingMessages: Map<number, { resolve: (value: any) => void; reject: (error: any) => void }> = new Map();
|
||||||
private messageChannelForGet: MessageChannel | null = null;
|
|
||||||
private serviceWorkerCheckIntervalId: number | null = null;
|
// ============================================
|
||||||
private storeDefinitions = {
|
// INITIALIZATION & SINGLETON
|
||||||
AnkLabels: {
|
// ============================================
|
||||||
name: 'labels',
|
|
||||||
options: { keyPath: 'emoji' },
|
private constructor() {
|
||||||
indices: [],
|
this.initIndexedDBWorker();
|
||||||
},
|
this.initServiceWorker();
|
||||||
AnkWallet: {
|
}
|
||||||
name: 'wallet',
|
|
||||||
options: { keyPath: 'pre_id' },
|
public static async getInstance(): Promise<Database> {
|
||||||
indices: [],
|
if (!Database.instance) {
|
||||||
},
|
Database.instance = new Database();
|
||||||
AnkProcess: {
|
await Database.instance.init();
|
||||||
name: 'processes',
|
}
|
||||||
options: {},
|
return Database.instance;
|
||||||
indices: [],
|
}
|
||||||
},
|
|
||||||
AnkSharedSecrets: {
|
// Initialize the database
|
||||||
name: 'shared_secrets',
|
private async init(): Promise<void> {
|
||||||
options: {},
|
return new Promise((resolve, reject) => {
|
||||||
indices: [],
|
const request = indexedDB.open(this.dbName, this.dbVersion);
|
||||||
},
|
|
||||||
AnkUnconfirmedSecrets: {
|
request.onupgradeneeded = () => {
|
||||||
name: 'unconfirmed_secrets',
|
const db = request.result;
|
||||||
options: { autoIncrement: true },
|
|
||||||
indices: [],
|
Object.values(this.storeDefinitions).forEach(({ name, options, indices }) => {
|
||||||
},
|
if (!db.objectStoreNames.contains(name)) {
|
||||||
AnkPendingDiffs: {
|
let store = db.createObjectStore(name, options as IDBObjectStoreParameters);
|
||||||
name: 'diffs',
|
|
||||||
options: { keyPath: 'value_commitment' },
|
indices.forEach(({ name, keyPath, options }) => {
|
||||||
indices: [
|
store.createIndex(name, keyPath, options);
|
||||||
{ name: 'byStateId', keyPath: 'state_id', options: { unique: false } },
|
});
|
||||||
{ name: 'byNeedValidation', keyPath: 'need_validation', options: { unique: false } },
|
}
|
||||||
{ name: 'byStatus', keyPath: 'validation_status', options: { unique: false } },
|
});
|
||||||
],
|
};
|
||||||
},
|
|
||||||
AnkData: {
|
request.onsuccess = async () => {
|
||||||
name: 'data',
|
this.db = request.result;
|
||||||
options: {},
|
resolve();
|
||||||
indices: [],
|
};
|
||||||
},
|
|
||||||
};
|
request.onerror = () => {
|
||||||
|
console.error('Database error:', request.error);
|
||||||
// Private constructor to prevent direct instantiation from outside
|
reject(request.error);
|
||||||
private constructor() {}
|
};
|
||||||
|
});
|
||||||
// Method to access the singleton instance of Database
|
}
|
||||||
public static async getInstance(): Promise<Database> {
|
|
||||||
if (!Database.instance) {
|
public async getDb(): Promise<IDBDatabase> {
|
||||||
Database.instance = new Database();
|
if (!this.db) {
|
||||||
await Database.instance.init();
|
await this.init();
|
||||||
}
|
}
|
||||||
return Database.instance;
|
return this.db!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the database
|
public getStoreList(): { [key: string]: string } {
|
||||||
private async init(): Promise<void> {
|
const objectList: { [key: string]: string } = {};
|
||||||
return new Promise((resolve, reject) => {
|
Object.keys(this.storeDefinitions).forEach((key) => {
|
||||||
const request = indexedDB.open(this.dbName, this.dbVersion);
|
objectList[key] = this.storeDefinitions[key as keyof typeof this.storeDefinitions].name;
|
||||||
|
});
|
||||||
request.onupgradeneeded = () => {
|
return objectList;
|
||||||
const db = request.result;
|
}
|
||||||
|
|
||||||
Object.values(this.storeDefinitions).forEach(({ name, options, indices }) => {
|
public async registerServiceWorker(path: string) {
|
||||||
if (!db.objectStoreNames.contains(name)) {
|
if (!('serviceWorker' in navigator)) return;
|
||||||
let store = db.createObjectStore(name, options as IDBObjectStoreParameters);
|
console.log('[Database] Initialisation du Service Worker sur :', path);
|
||||||
|
|
||||||
indices.forEach(({ name, keyPath, options }) => {
|
try {
|
||||||
store.createIndex(name, keyPath, options);
|
// 1. NETTOYAGE DES ANCIENS WORKERS (ZOMBIES)
|
||||||
});
|
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||||
}
|
|
||||||
});
|
for (const registration of registrations) {
|
||||||
};
|
const scriptURL = registration.active?.scriptURL || registration.installing?.scriptURL || registration.waiting?.scriptURL;
|
||||||
|
const scope = registration.scope;
|
||||||
request.onsuccess = async () => {
|
|
||||||
this.db = request.result;
|
// On détecte spécifiquement l'ancien dossier qui pose problème
|
||||||
resolve();
|
// L'erreur mentionne : scope ('.../src/service-workers/')
|
||||||
};
|
if (scope.includes('/src/service-workers/') || (scriptURL && scriptURL.includes('/src/service-workers/'))) {
|
||||||
|
console.warn(`[Database] 🚨 ANCIEN Service Worker détecté (${scope}). Suppression immédiate...`);
|
||||||
request.onerror = () => {
|
await registration.unregister();
|
||||||
console.error('Database error:', request.error);
|
// On continue la boucle, ne pas retourner ici, il faut installer le nouveau après
|
||||||
reject(request.error);
|
}
|
||||||
};
|
}
|
||||||
});
|
|
||||||
}
|
// 2. INSTALLATION DU NOUVEAU WORKER (PROPRE)
|
||||||
|
// On vérifie s'il est déjà installé à la BONNE adresse
|
||||||
public async getDb(): Promise<IDBDatabase> {
|
const existingValidWorker = registrations.find((r) => {
|
||||||
if (!this.db) {
|
const url = r.active?.scriptURL || r.installing?.scriptURL || r.waiting?.scriptURL;
|
||||||
await this.init();
|
// On compare la fin de l'URL pour éviter les soucis http/https/localhost
|
||||||
}
|
return url && url.endsWith(path.replace(/^\//, ''));
|
||||||
return this.db!;
|
});
|
||||||
}
|
|
||||||
|
if (!existingValidWorker) {
|
||||||
public getStoreList(): { [key: string]: string } {
|
console.log('[Database] Enregistrement du nouveau Service Worker...');
|
||||||
const objectList: { [key: string]: string } = {};
|
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module', scope: '/' });
|
||||||
Object.keys(this.storeDefinitions).forEach((key) => {
|
} else {
|
||||||
objectList[key] = this.storeDefinitions[key as keyof typeof this.storeDefinitions].name;
|
console.log('[Database] Service Worker déjà actif et valide.');
|
||||||
});
|
this.serviceWorkerRegistration = existingValidWorker;
|
||||||
return objectList;
|
await this.serviceWorkerRegistration.update();
|
||||||
}
|
}
|
||||||
|
// Set up listeners
|
||||||
public async registerServiceWorker(path: string) {
|
navigator.serviceWorker.addEventListener('message', async (event) => {
|
||||||
if (!('serviceWorker' in navigator)) return;
|
// console.log('Received message from service worker:', event.data);
|
||||||
console.log('[Database] Initialisation du Service Worker sur :', path);
|
await this.handleServiceWorkerMessage(event.data);
|
||||||
|
});
|
||||||
try {
|
|
||||||
// 1. NETTOYAGE DES ANCIENS WORKERS (ZOMBIES)
|
// Periodic check
|
||||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
if (this.serviceWorkerCheckIntervalId) clearInterval(this.serviceWorkerCheckIntervalId);
|
||||||
|
this.serviceWorkerCheckIntervalId = window.setInterval(async () => {
|
||||||
for (const registration of registrations) {
|
const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!));
|
||||||
const scriptURL = registration.active?.scriptURL || registration.installing?.scriptURL || registration.waiting?.scriptURL;
|
const service = await Services.getInstance();
|
||||||
const scope = registration.scope;
|
const payload = await service.getMyProcesses();
|
||||||
|
if (payload && payload.length != 0) {
|
||||||
// On détecte spécifiquement l'ancien dossier qui pose problème
|
activeWorker?.postMessage({ type: 'SCAN', payload });
|
||||||
// L'erreur mentionne : scope ('.../src/service-workers/')
|
}
|
||||||
if (scope.includes('/src/service-workers/') || (scriptURL && scriptURL.includes('/src/service-workers/'))) {
|
}, 5000);
|
||||||
console.warn(`[Database] 🚨 ANCIEN Service Worker détecté (${scope}). Suppression immédiate...`);
|
} catch (error) {
|
||||||
await registration.unregister();
|
console.error('[Database] 💥 Erreur critique Service Worker:', error);
|
||||||
// On continue la boucle, ne pas retourner ici, il faut installer le nouveau après
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Helper function to wait for service worker activation
|
||||||
// 2. INSTALLATION DU NOUVEAU WORKER (PROPRE)
|
private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise<ServiceWorker | null> {
|
||||||
// On vérifie s'il est déjà installé à la BONNE adresse
|
return new Promise((resolve) => {
|
||||||
const existingValidWorker = registrations.find((r) => {
|
if (registration.active) {
|
||||||
const url = r.active?.scriptURL || r.installing?.scriptURL || r.waiting?.scriptURL;
|
resolve(registration.active);
|
||||||
// On compare la fin de l'URL pour éviter les soucis http/https/localhost
|
} else {
|
||||||
return url && url.endsWith(path.replace(/^\//, ''));
|
const listener = () => {
|
||||||
});
|
if (registration.active) {
|
||||||
|
navigator.serviceWorker.removeEventListener('controllerchange', listener);
|
||||||
if (!existingValidWorker) {
|
resolve(registration.active);
|
||||||
console.log('[Database] Enregistrement du nouveau Service Worker...');
|
}
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module', scope: '/' });
|
};
|
||||||
} else {
|
navigator.serviceWorker.addEventListener('controllerchange', listener);
|
||||||
console.log('[Database] Service Worker déjà actif et valide.');
|
}
|
||||||
this.serviceWorkerRegistration = existingValidWorker;
|
});
|
||||||
await this.serviceWorkerRegistration.update();
|
}
|
||||||
}
|
|
||||||
// Set up listeners
|
private async checkForUpdates() {
|
||||||
navigator.serviceWorker.addEventListener('message', async (event) => {
|
if (this.serviceWorkerRegistration) {
|
||||||
// console.log('Received message from service worker:', event.data);
|
// Check for updates to the service worker
|
||||||
await this.handleServiceWorkerMessage(event.data);
|
try {
|
||||||
});
|
await this.serviceWorkerRegistration.update();
|
||||||
|
|
||||||
// Periodic check
|
// If there's a new worker waiting, activate it immediately
|
||||||
if (this.serviceWorkerCheckIntervalId) clearInterval(this.serviceWorkerCheckIntervalId);
|
if (this.serviceWorkerRegistration.waiting) {
|
||||||
this.serviceWorkerCheckIntervalId = window.setInterval(async () => {
|
this.serviceWorkerRegistration.waiting.postMessage({ type: 'SKIP_WAITING' });
|
||||||
const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!));
|
}
|
||||||
const service = await Services.getInstance();
|
} catch (error) {
|
||||||
const payload = await service.getMyProcesses();
|
console.error('Error checking for service worker updates:', error);
|
||||||
if (payload && payload.length != 0) {
|
}
|
||||||
activeWorker?.postMessage({ type: 'SCAN', payload });
|
}
|
||||||
}
|
}
|
||||||
}, 5000);
|
|
||||||
} catch (error) {
|
private async handleServiceWorkerMessage(message: any) {
|
||||||
console.error('[Database] 💥 Erreur critique Service Worker:', error);
|
switch (message.type) {
|
||||||
}
|
case 'TO_DOWNLOAD':
|
||||||
}
|
await this.handleDownloadList(message.data);
|
||||||
|
break;
|
||||||
// Helper function to wait for service worker activation
|
default:
|
||||||
private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise<ServiceWorker | null> {
|
console.warn('Unknown message type received from service worker:', message);
|
||||||
return new Promise((resolve) => {
|
}
|
||||||
if (registration.active) {
|
}
|
||||||
resolve(registration.active);
|
|
||||||
} else {
|
private async handleDownloadList(downloadList: string[]): Promise<void> {
|
||||||
const listener = () => {
|
// Download the missing data
|
||||||
if (registration.active) {
|
let requestedStateId: string[] = [];
|
||||||
navigator.serviceWorker.removeEventListener('controllerchange', listener);
|
const service = await Services.getInstance();
|
||||||
resolve(registration.active);
|
for (const hash of downloadList) {
|
||||||
}
|
const diff = await service.getDiffByValue(hash);
|
||||||
};
|
if (!diff) {
|
||||||
navigator.serviceWorker.addEventListener('controllerchange', listener);
|
// This should never happen
|
||||||
}
|
console.warn(`Missing a diff for hash ${hash}`);
|
||||||
});
|
continue;
|
||||||
}
|
}
|
||||||
|
const processId = diff.process_id;
|
||||||
private async checkForUpdates() {
|
const stateId = diff.state_id;
|
||||||
if (this.serviceWorkerRegistration) {
|
const roles = diff.roles;
|
||||||
// Check for updates to the service worker
|
try {
|
||||||
try {
|
const valueBytes = await service.fetchValueFromStorage(hash);
|
||||||
await this.serviceWorkerRegistration.update();
|
if (valueBytes) {
|
||||||
|
// Save data to db
|
||||||
// If there's a new worker waiting, activate it immediately
|
const blob = new Blob([valueBytes], { type: 'application/octet-stream' });
|
||||||
if (this.serviceWorkerRegistration.waiting) {
|
await service.saveBlobToDb(hash, blob);
|
||||||
this.serviceWorkerRegistration.waiting.postMessage({ type: 'SKIP_WAITING' });
|
document.dispatchEvent(
|
||||||
}
|
new CustomEvent('newDataReceived', {
|
||||||
} catch (error) {
|
detail: {
|
||||||
console.error('Error checking for service worker updates:', error);
|
processId,
|
||||||
}
|
stateId,
|
||||||
}
|
hash,
|
||||||
}
|
},
|
||||||
|
}),
|
||||||
private async handleServiceWorkerMessage(message: any) {
|
);
|
||||||
switch (message.type) {
|
} else {
|
||||||
case 'TO_DOWNLOAD':
|
// We first request the data from managers
|
||||||
await this.handleDownloadList(message.data);
|
console.log('Request data from managers of the process');
|
||||||
break;
|
// get the diff from db
|
||||||
default:
|
if (!requestedStateId.includes(stateId)) {
|
||||||
console.warn('Unknown message type received from service worker:', message);
|
await service.requestDataFromPeers(processId, [stateId], [roles]);
|
||||||
}
|
requestedStateId.push(stateId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private async handleDownloadList(downloadList: string[]): Promise<void> {
|
} catch (e) {
|
||||||
// Download the missing data
|
console.error(e);
|
||||||
let requestedStateId: string[] = [];
|
}
|
||||||
const service = await Services.getInstance();
|
}
|
||||||
for (const hash of downloadList) {
|
}
|
||||||
const diff = await service.getDiffByValue(hash);
|
|
||||||
if (!diff) {
|
private handleAddObjectResponse = async (event: MessageEvent) => {
|
||||||
// This should never happen
|
const data = event.data;
|
||||||
console.warn(`Missing a diff for hash ${hash}`);
|
console.log('Received response from service worker (ADD_OBJECT):', data);
|
||||||
continue;
|
const service = await Services.getInstance();
|
||||||
}
|
if (data.type === 'NOTIFICATIONS') {
|
||||||
const processId = diff.process_id;
|
service.setNotifications(data.data);
|
||||||
const stateId = diff.state_id;
|
} else if (data.type === 'TO_DOWNLOAD') {
|
||||||
const roles = diff.roles;
|
console.log(`Received missing data ${data}`);
|
||||||
try {
|
// Download the missing data
|
||||||
const valueBytes = await service.fetchValueFromStorage(hash);
|
let requestedStateId: string[] = [];
|
||||||
if (valueBytes) {
|
for (const hash of data.data) {
|
||||||
// Save data to db
|
try {
|
||||||
const blob = new Blob([valueBytes], { type: 'application/octet-stream' });
|
const valueBytes = await service.fetchValueFromStorage(hash);
|
||||||
await service.saveBlobToDb(hash, blob);
|
if (valueBytes) {
|
||||||
document.dispatchEvent(
|
// Save data to db
|
||||||
new CustomEvent('newDataReceived', {
|
const blob = new Blob([valueBytes], { type: 'application/octet-stream' });
|
||||||
detail: {
|
await service.saveBlobToDb(hash, blob);
|
||||||
processId,
|
} else {
|
||||||
stateId,
|
// We first request the data from managers
|
||||||
hash,
|
console.log('Request data from managers of the process');
|
||||||
},
|
// get the diff from db
|
||||||
}),
|
const diff = await service.getDiffByValue(hash);
|
||||||
);
|
if (diff === null) {
|
||||||
} else {
|
continue;
|
||||||
// We first request the data from managers
|
}
|
||||||
console.log('Request data from managers of the process');
|
const processId = diff!.process_id;
|
||||||
// get the diff from db
|
const stateId = diff!.state_id;
|
||||||
if (!requestedStateId.includes(stateId)) {
|
const roles = diff!.roles;
|
||||||
await service.requestDataFromPeers(processId, [stateId], [roles]);
|
if (!requestedStateId.includes(stateId)) {
|
||||||
requestedStateId.push(stateId);
|
await service.requestDataFromPeers(processId, [stateId], [roles]);
|
||||||
}
|
requestedStateId.push(stateId);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
}
|
||||||
console.error(e);
|
} catch (e) {
|
||||||
}
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private handleAddObjectResponse = async (event: MessageEvent) => {
|
};
|
||||||
const data = event.data;
|
|
||||||
console.log('Received response from service worker (ADD_OBJECT):', data);
|
private handleGetObjectResponse = (event: MessageEvent) => {
|
||||||
const service = await Services.getInstance();
|
console.log('Received response from service worker (GET_OBJECT):', event.data);
|
||||||
if (data.type === 'NOTIFICATIONS') {
|
};
|
||||||
service.setNotifications(data.data);
|
|
||||||
} else if (data.type === 'TO_DOWNLOAD') {
|
public addObject(payload: { storeName: string; object: any; key: any }): Promise<void> {
|
||||||
console.log(`Received missing data ${data}`);
|
return new Promise(async (resolve, reject) => {
|
||||||
// Download the missing data
|
// Check if the service worker is active
|
||||||
let requestedStateId: string[] = [];
|
if (!this.serviceWorkerRegistration) {
|
||||||
for (const hash of data.data) {
|
// console.warn('Service worker registration is not ready. Waiting...');
|
||||||
try {
|
this.serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
||||||
const valueBytes = await service.fetchValueFromStorage(hash);
|
}
|
||||||
if (valueBytes) {
|
|
||||||
// Save data to db
|
const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration);
|
||||||
const blob = new Blob([valueBytes], { type: 'application/octet-stream' });
|
|
||||||
await service.saveBlobToDb(hash, blob);
|
// Create a message channel for communication
|
||||||
} else {
|
const messageChannel = new MessageChannel();
|
||||||
// We first request the data from managers
|
|
||||||
console.log('Request data from managers of the process');
|
// Handle the response from the service worker
|
||||||
// get the diff from db
|
messageChannel.port1.onmessage = (event) => {
|
||||||
const diff = await service.getDiffByValue(hash);
|
if (event.data.status === 'success') {
|
||||||
if (diff === null) {
|
resolve();
|
||||||
continue;
|
} else {
|
||||||
}
|
const error = event.data.message;
|
||||||
const processId = diff!.process_id;
|
reject(new Error(error || 'Unknown error occurred while adding object'));
|
||||||
const stateId = diff!.state_id;
|
}
|
||||||
const roles = diff!.roles;
|
};
|
||||||
if (!requestedStateId.includes(stateId)) {
|
|
||||||
await service.requestDataFromPeers(processId, [stateId], [roles]);
|
// Send the add object request to the service worker
|
||||||
requestedStateId.push(stateId);
|
try {
|
||||||
}
|
activeWorker?.postMessage(
|
||||||
}
|
{
|
||||||
} catch (e) {
|
type: 'ADD_OBJECT',
|
||||||
console.error(e);
|
payload,
|
||||||
}
|
},
|
||||||
}
|
[messageChannel.port2],
|
||||||
}
|
);
|
||||||
};
|
} catch (error) {
|
||||||
|
reject(new Error(`Failed to send message to service worker: ${error}`));
|
||||||
private handleGetObjectResponse = (event: MessageEvent) => {
|
}
|
||||||
console.log('Received response from service worker (GET_OBJECT):', event.data);
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
public addObject(payload: { storeName: string; object: any; key: any }): Promise<void> {
|
public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
// Check if the service worker is active
|
if (!this.serviceWorkerRegistration) {
|
||||||
if (!this.serviceWorkerRegistration) {
|
this.serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
||||||
// console.warn('Service worker registration is not ready. Waiting...');
|
}
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
|
||||||
}
|
const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration);
|
||||||
|
const messageChannel = new MessageChannel();
|
||||||
const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration);
|
|
||||||
|
messageChannel.port1.onmessage = (event) => {
|
||||||
// Create a message channel for communication
|
if (event.data.status === 'success') {
|
||||||
const messageChannel = new MessageChannel();
|
resolve();
|
||||||
|
} else {
|
||||||
// Handle the response from the service worker
|
const error = event.data.message;
|
||||||
messageChannel.port1.onmessage = (event) => {
|
reject(new Error(error || 'Unknown error occurred while adding objects'));
|
||||||
if (event.data.status === 'success') {
|
}
|
||||||
resolve();
|
};
|
||||||
} else {
|
|
||||||
const error = event.data.message;
|
try {
|
||||||
reject(new Error(error || 'Unknown error occurred while adding object'));
|
activeWorker?.postMessage(
|
||||||
}
|
{
|
||||||
};
|
type: 'BATCH_WRITING',
|
||||||
|
payload,
|
||||||
// Send the add object request to the service worker
|
},
|
||||||
try {
|
[messageChannel.port2],
|
||||||
activeWorker?.postMessage(
|
);
|
||||||
{
|
} catch (error) {
|
||||||
type: 'ADD_OBJECT',
|
reject(new Error(`Failed to send message to service worker: ${error}`));
|
||||||
payload,
|
}
|
||||||
},
|
});
|
||||||
[messageChannel.port2],
|
}
|
||||||
);
|
|
||||||
} catch (error) {
|
public async getObject(storeName: string, key: string): Promise<any | null> {
|
||||||
reject(new Error(`Failed to send message to service worker: ${error}`));
|
const db = await this.getDb();
|
||||||
}
|
const tx = db.transaction(storeName, 'readonly');
|
||||||
});
|
const store = tx.objectStore(storeName);
|
||||||
}
|
const result = await new Promise((resolve, reject) => {
|
||||||
|
const getRequest = store.get(key);
|
||||||
public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise<void> {
|
getRequest.onsuccess = () => resolve(getRequest.result);
|
||||||
return new Promise(async (resolve, reject) => {
|
getRequest.onerror = () => reject(getRequest.error);
|
||||||
if (!this.serviceWorkerRegistration) {
|
});
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
return result ?? null; // Convert undefined to null
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration);
|
public async dumpStore(storeName: string): Promise<Record<string, any>> {
|
||||||
const messageChannel = new MessageChannel();
|
const db = await this.getDb();
|
||||||
|
const tx = db.transaction(storeName, 'readonly');
|
||||||
messageChannel.port1.onmessage = (event) => {
|
const store = tx.objectStore(storeName);
|
||||||
if (event.data.status === 'success') {
|
|
||||||
resolve();
|
try {
|
||||||
} else {
|
return new Promise((resolve, reject) => {
|
||||||
const error = event.data.message;
|
const result: Record<string, any> = {};
|
||||||
reject(new Error(error || 'Unknown error occurred while adding objects'));
|
const cursor = store.openCursor();
|
||||||
}
|
|
||||||
};
|
cursor.onsuccess = (event) => {
|
||||||
|
const request = event.target as IDBRequest<IDBCursorWithValue | null>;
|
||||||
try {
|
const cursor = request.result;
|
||||||
activeWorker?.postMessage(
|
if (cursor) {
|
||||||
{
|
result[cursor.key as string] = cursor.value;
|
||||||
type: 'BATCH_WRITING',
|
cursor.continue();
|
||||||
payload,
|
} else {
|
||||||
},
|
resolve(result);
|
||||||
[messageChannel.port2],
|
}
|
||||||
);
|
};
|
||||||
} catch (error) {
|
|
||||||
reject(new Error(`Failed to send message to service worker: ${error}`));
|
cursor.onerror = () => {
|
||||||
}
|
reject(cursor.error);
|
||||||
});
|
};
|
||||||
}
|
});
|
||||||
|
} catch (error) {
|
||||||
public async getObject(storeName: string, key: string): Promise<any | null> {
|
console.error('Error fetching data from IndexedDB:', error);
|
||||||
const db = await this.getDb();
|
throw error;
|
||||||
const tx = db.transaction(storeName, 'readonly');
|
}
|
||||||
const store = tx.objectStore(storeName);
|
}
|
||||||
const result = await new Promise((resolve, reject) => {
|
|
||||||
const getRequest = store.get(key);
|
public async deleteObject(storeName: string, key: string): Promise<void> {
|
||||||
getRequest.onsuccess = () => resolve(getRequest.result);
|
const db = await this.getDb();
|
||||||
getRequest.onerror = () => reject(getRequest.error);
|
const tx = db.transaction(storeName, 'readwrite');
|
||||||
});
|
const store = tx.objectStore(storeName);
|
||||||
return result ?? null; // Convert undefined to null
|
try {
|
||||||
}
|
await new Promise((resolve, reject) => {
|
||||||
|
const getRequest = store.delete(key);
|
||||||
public async dumpStore(storeName: string): Promise<Record<string, any>> {
|
getRequest.onsuccess = () => resolve(getRequest.result);
|
||||||
const db = await this.getDb();
|
getRequest.onerror = () => reject(getRequest.error);
|
||||||
const tx = db.transaction(storeName, 'readonly');
|
});
|
||||||
const store = tx.objectStore(storeName);
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
try {
|
}
|
||||||
return new Promise((resolve, reject) => {
|
}
|
||||||
const result: Record<string, any> = {};
|
|
||||||
const cursor = store.openCursor();
|
public async clearStore(storeName: string): Promise<void> {
|
||||||
|
const db = await this.getDb();
|
||||||
cursor.onsuccess = (event) => {
|
const tx = db.transaction(storeName, 'readwrite');
|
||||||
const request = event.target as IDBRequest<IDBCursorWithValue | null>;
|
const store = tx.objectStore(storeName);
|
||||||
const cursor = request.result;
|
try {
|
||||||
if (cursor) {
|
await new Promise((resolve, reject) => {
|
||||||
result[cursor.key as string] = cursor.value;
|
const clearRequest = store.clear();
|
||||||
cursor.continue();
|
clearRequest.onsuccess = () => resolve(clearRequest.result);
|
||||||
} else {
|
clearRequest.onerror = () => reject(clearRequest.error);
|
||||||
resolve(result);
|
});
|
||||||
}
|
} catch (e) {
|
||||||
};
|
throw e;
|
||||||
|
}
|
||||||
cursor.onerror = () => {
|
}
|
||||||
reject(cursor.error);
|
|
||||||
};
|
// Request a store by index
|
||||||
});
|
public async requestStoreByIndex(storeName: string, indexName: string, request: string): Promise<any[]> {
|
||||||
} catch (error) {
|
const db = await this.getDb();
|
||||||
console.error('Error fetching data from IndexedDB:', error);
|
const tx = db.transaction(storeName, 'readonly');
|
||||||
throw error;
|
const store = tx.objectStore(storeName);
|
||||||
}
|
const index = store.index(indexName);
|
||||||
}
|
|
||||||
|
try {
|
||||||
public async deleteObject(storeName: string, key: string): Promise<void> {
|
return new Promise((resolve, reject) => {
|
||||||
const db = await this.getDb();
|
const getAllRequest = index.getAll(request);
|
||||||
const tx = db.transaction(storeName, 'readwrite');
|
getAllRequest.onsuccess = () => {
|
||||||
const store = tx.objectStore(storeName);
|
const allItems = getAllRequest.result;
|
||||||
try {
|
const filtered = allItems.filter((item) => item.state_id === request);
|
||||||
await new Promise((resolve, reject) => {
|
resolve(filtered);
|
||||||
const getRequest = store.delete(key);
|
};
|
||||||
getRequest.onsuccess = () => resolve(getRequest.result);
|
getAllRequest.onerror = () => reject(getAllRequest.error);
|
||||||
getRequest.onerror = () => reject(getRequest.error);
|
});
|
||||||
});
|
} catch (e) {
|
||||||
} catch (e) {
|
throw e;
|
||||||
throw e;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async clearStore(storeName: string): Promise<void> {
|
export default Database;
|
||||||
const db = await this.getDb();
|
|
||||||
const tx = db.transaction(storeName, 'readwrite');
|
|
||||||
const store = tx.objectStore(storeName);
|
|
||||||
try {
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
const clearRequest = store.clear();
|
|
||||||
clearRequest.onsuccess = () => resolve(clearRequest.result);
|
|
||||||
clearRequest.onerror = () => reject(clearRequest.error);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request a store by index
|
|
||||||
public async requestStoreByIndex(storeName: string, indexName: string, request: string): Promise<any[]> {
|
|
||||||
const db = await this.getDb();
|
|
||||||
const tx = db.transaction(storeName, 'readonly');
|
|
||||||
const store = tx.objectStore(storeName);
|
|
||||||
const index = store.index(indexName);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const getAllRequest = index.getAll(request);
|
|
||||||
getAllRequest.onsuccess = () => {
|
|
||||||
const allItems = getAllRequest.result;
|
|
||||||
const filtered = allItems.filter((item) => item.state_id === request);
|
|
||||||
resolve(filtered);
|
|
||||||
};
|
|
||||||
getAllRequest.onerror = () => reject(getAllRequest.error);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Database;
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user