add db and call it in a service worker
This commit is contained in:
parent
896de5aca4
commit
81bab0b469
@ -1,5 +1,6 @@
|
|||||||
import '../public/style/4nk.css';
|
import '../public/style/4nk.css';
|
||||||
import { initHeader } from './components/header/header';
|
import { initHeader } from './components/header/header';
|
||||||
|
import Database from './services/database.service';
|
||||||
import Services from './services/service';
|
import Services from './services/service';
|
||||||
import { cleanSubscriptions } from './utils/subscription.utils';
|
import { cleanSubscriptions } from './utils/subscription.utils';
|
||||||
|
|
||||||
@ -67,6 +68,7 @@ window.onpopstate = async () => {
|
|||||||
async function init(): Promise<void> {
|
async function init(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const services = await Services.getInstance();
|
const services = await Services.getInstance();
|
||||||
|
await Database.getInstance();
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
let device = await services.getDevice();
|
let device = await services.getDevice();
|
||||||
console.log('🚀 ~ setTimeout ~ device:', device);
|
console.log('🚀 ~ setTimeout ~ device:', device);
|
||||||
|
58
src/service-workers/database.worker.js
Normal file
58
src/service-workers/database.worker.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import Database from '../services/database.service';
|
||||||
|
|
||||||
|
self.addEventListener('install', (event) => {
|
||||||
|
event.waitUntil(self.skipWaiting()); // Activate worker immediately
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', (event) => {
|
||||||
|
event.waitUntil(self.clients.claim()); // Become available to all pages
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event listener for messages from clients
|
||||||
|
self.addEventListener('message', async (event) => {
|
||||||
|
const data = event.data;
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
|
||||||
|
if (data.type === 'ADD_OBJECT') {
|
||||||
|
try {
|
||||||
|
const { storeName, object, key } = data.payload;
|
||||||
|
const db = await openDatabase();
|
||||||
|
const tx = db.transaction(storeName, 'readwrite');
|
||||||
|
const store = tx.objectStore(storeName);
|
||||||
|
console.log("🚀 ~ self.addEventListener ~ store:", store, storeName, key, object)
|
||||||
|
await store.put(object);
|
||||||
|
event.ports[0].postMessage({ status: 'success', message: 'Object added or replaced successfully' });
|
||||||
|
} catch(error) {
|
||||||
|
event.ports[0].postMessage({ status: 'error', message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.type === 'GET_OBJECT') {
|
||||||
|
const { storeName, key } = data.payload;
|
||||||
|
const db = await openDatabase();
|
||||||
|
const tx = db.transaction(storeName, 'readonly');
|
||||||
|
const store = tx.objectStore(storeName);
|
||||||
|
const result = await store.get(key);
|
||||||
|
|
||||||
|
event.ports[0].postMessage({ type: 'GET_OBJECT_RESULT', payload: result });
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
async function openDatabase() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const request = indexedDB.open('4nk', 1);
|
||||||
|
request.onerror = (event) => {
|
||||||
|
reject(request.error);
|
||||||
|
};
|
||||||
|
request.onsuccess = (event) => {
|
||||||
|
resolve(request.result);
|
||||||
|
};
|
||||||
|
request.onupgradeneeded = (event) => {
|
||||||
|
const db = event.target.result;
|
||||||
|
if (!db.objectStoreNames.contains('wallet')) {
|
||||||
|
db.createObjectStore('wallet', { keyPath: 'pre_id' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
154
src/services/database.service.ts
Normal file
154
src/services/database.service.ts
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
class Database {
|
||||||
|
private static instance: Database;
|
||||||
|
private db: IDBDatabase | null = null;
|
||||||
|
private dbName: string = '4nk';
|
||||||
|
private dbVersion: number = 1;
|
||||||
|
private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;
|
||||||
|
private messageChannel: MessageChannel = new MessageChannel();
|
||||||
|
private messageChannelForGet: MessageChannel = new MessageChannel();
|
||||||
|
private storeDefinitions = {
|
||||||
|
AnkWallet: {
|
||||||
|
name: 'wallet',
|
||||||
|
options: { keyPath: 'pre_id' },
|
||||||
|
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;
|
||||||
|
this.initServiceWorker();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private createMessageChannel(responseHandler: (event: MessageEvent) => void): MessageChannel {
|
||||||
|
const messageChannel = new MessageChannel();
|
||||||
|
messageChannel.port1.onmessage = responseHandler;
|
||||||
|
return messageChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initServiceWorker() {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
try {
|
||||||
|
const registration = await navigator.serviceWorker.register('/src/service-workers/database.worker.js', { type: 'module' });
|
||||||
|
console.log('Service Worker registered with scope:', registration.scope);
|
||||||
|
|
||||||
|
this.serviceWorkerRegistration = registration;
|
||||||
|
|
||||||
|
// Set up the message channels
|
||||||
|
this.messageChannel.port1.onmessage = this.handleAddObjectResponse;
|
||||||
|
this.messageChannelForGet.port1.onmessage = this.handleGetObjectResponse;
|
||||||
|
|
||||||
|
// Optionally, initialize service worker with some data
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Service Worker registration failed:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private handleAddObjectResponse = (event: MessageEvent) => {
|
||||||
|
console.log('Received response from service worker (ADD_OBJECT):', event.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleGetObjectResponse = (event: MessageEvent) => {
|
||||||
|
console.log('Received response from service worker (GET_OBJECT):', event.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
public addObject(payload: { storeName: string; object: any; key: any }) {
|
||||||
|
if (this.serviceWorkerRegistration?.active) {
|
||||||
|
const messageChannel = this.createMessageChannel(this.handleAddObjectResponse);
|
||||||
|
this.serviceWorkerRegistration.active.postMessage(
|
||||||
|
{
|
||||||
|
type: 'ADD_OBJECT',
|
||||||
|
payload,
|
||||||
|
},
|
||||||
|
[messageChannel.port2],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getObject(storeName: string, key: string) {
|
||||||
|
if (this.serviceWorkerRegistration?.active) {
|
||||||
|
const messageChannel = this.createMessageChannel(this.handleGetObjectResponse);
|
||||||
|
|
||||||
|
this.serviceWorkerRegistration.active.postMessage(
|
||||||
|
{
|
||||||
|
type: 'GET_OBJECT',
|
||||||
|
payload: { storeName, key },
|
||||||
|
},
|
||||||
|
[messageChannel.port2],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Database;
|
@ -6,6 +6,7 @@ import { initWebsocket, sendMessage } from '../websockets';
|
|||||||
import { ApiReturn, Member } from '../../dist/pkg/sdk_client';
|
import { ApiReturn, Member } from '../../dist/pkg/sdk_client';
|
||||||
import ModalService from './modal.service';
|
import ModalService from './modal.service';
|
||||||
import { navigate } from '../router';
|
import { navigate } from '../router';
|
||||||
|
import Database from './database.service';
|
||||||
|
|
||||||
type ProcessesCache = {
|
type ProcessesCache = {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
@ -199,6 +200,12 @@ export default class Services {
|
|||||||
|
|
||||||
// Save process to storage
|
// Save process to storage
|
||||||
localStorage.setItem(processCommitment, JSON.stringify(process));
|
localStorage.setItem(processCommitment, JSON.stringify(process));
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
db.addObject({
|
||||||
|
storeName: 'process',
|
||||||
|
object: { id: processCommitment, process },
|
||||||
|
key: processCommitment,
|
||||||
|
});
|
||||||
// Check if the newly updated process reveals some new information
|
// Check if the newly updated process reveals some new information
|
||||||
try {
|
try {
|
||||||
const proposals: string[] = this.sdkClient.get_update_proposals(processCommitment);
|
const proposals: string[] = this.sdkClient.get_update_proposals(processCommitment);
|
||||||
@ -213,10 +220,16 @@ export default class Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (apiReturn.updated_cached_msg && apiReturn.updated_cached_msg.length) {
|
if (apiReturn.updated_cached_msg && apiReturn.updated_cached_msg.length) {
|
||||||
apiReturn.updated_cached_msg.forEach((msg, index) => {
|
apiReturn.updated_cached_msg.forEach(async (msg, index) => {
|
||||||
// console.debug(`CachedMessage ${index}:`, msg);
|
// console.debug(`CachedMessage ${index}:`, msg);
|
||||||
// Save the message to local storage
|
// Save the message to local storage
|
||||||
localStorage.setItem(msg.id.toString(), JSON.stringify(msg));
|
localStorage.setItem(msg.id.toString(), JSON.stringify(msg));
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
db.addObject({
|
||||||
|
storeName: 'process',
|
||||||
|
object: { id: msg.id.toString(), msg },
|
||||||
|
key: msg.id.toString(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,10 +325,18 @@ export default class Services {
|
|||||||
|
|
||||||
async saveDevice(device: any): Promise<any> {
|
async saveDevice(device: any): Promise<any> {
|
||||||
// console.log("🚀 ~ Services ~ saveDevice ~ device:", device)
|
// console.log("🚀 ~ Services ~ saveDevice ~ device:", device)
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
db.addObject({
|
||||||
|
storeName: 'wallet',
|
||||||
|
object: { pre_id: '1', device },
|
||||||
|
key: '1',
|
||||||
|
});
|
||||||
localStorage.setItem('wallet', device);
|
localStorage.setItem('wallet', device);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDevice(): Promise<string | null> {
|
async getDevice(): Promise<string | null> {
|
||||||
|
const db = await Database.getInstance();
|
||||||
|
db.getObject('wallet', '1');
|
||||||
return localStorage.getItem('wallet');
|
return localStorage.getItem('wallet');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"declaration": true,
|
"declaration": true,
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
"lib": ["DOM", "DOM.Iterable", "ESNext", "webworker"],
|
||||||
"types": ["vite/client", "node"],
|
"types": ["vite/client", "node"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
@ -22,6 +22,6 @@
|
|||||||
"~/*": ["src/*"]
|
"~/*": ["src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src", "src/**/*", "./vite.config.ts", "src/index.d.ts", "src/router.ts"],
|
"include": ["src", "src/**/*", "./vite.config.ts", "src/*.d.ts", "src/router.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user