diff --git a/web/database/utils/constants.js b/web/database/utils/constants.js new file mode 100644 index 000000000..6bd6f014f --- /dev/null +++ b/web/database/utils/constants.js @@ -0,0 +1,3 @@ +// @flow + +export const SQLITE_CONTENT = 'sqliteFileContent'; diff --git a/web/database/worker/db-worker.js b/web/database/worker/db-worker.js index cc2e209c5..98c6776e4 100644 --- a/web/database/worker/db-worker.js +++ b/web/database/worker/db-worker.js @@ -1,68 +1,102 @@ // @flow import localforage from 'localforage'; +import initSqlJs from 'sql.js'; import { type SharedWorkerMessageEvent, type WorkerRequestMessage, type WorkerResponseMessage, workerRequestMessageTypes, workerResponseMessageTypes, type WorkerRequestProxyMessage, } from '../../types/worker-types.js'; +import { SQLITE_CONTENT } from '../utils/constants.js'; const localforageConfig: PartialConfig = { driver: localforage.INDEXEDDB, name: 'comm', storeName: 'commStorage', description: 'Comm encrypted database storage', version: '1.0', }; localforage.config(localforageConfig); -function processAppRequest( +let sqliteDb = null; + +async function initDatabase(sqljsFilePath: string, sqljsFilename: ?string) { + const content = await localforage.getItem(SQLITE_CONTENT); + + const locateFile = defaultFilename => { + if (sqljsFilename) { + return `${sqljsFilePath}/${sqljsFilename}`; + } + return `${sqljsFilePath}/${defaultFilename}`; + }; + const SQL = await initSqlJs({ + locateFile, + }); + + if (content) { + sqliteDb = new SQL.Database(new Uint8Array(content)); + } else { + sqliteDb = new SQL.Database(); + } + + const versionData = sqliteDb.exec('PRAGMA user_version;'); + if (versionData.length && versionData[0].values.length) { + console.info(`Db version: ${versionData[0].values[0]}`); + } else { + throw new Error('Error while retrieving database version'); + } +} + +async function processAppRequest( message: WorkerRequestMessage, -): ?WorkerResponseMessage { +): Promise { if (message.type === workerRequestMessageTypes.PING) { return { type: workerResponseMessageTypes.PONG, text: 'PONG', }; + } else if (message.type === workerRequestMessageTypes.INIT) { + await initDatabase(message.sqljsFilePath, message.sqljsFilename); + return; } throw new Error('Request type not supported'); } function connectHandler(event: SharedWorkerMessageEvent) { if (!event.ports.length) { return; } const port: MessagePort = event.ports[0]; console.log('Web database worker alive!'); port.onmessage = async function (messageEvent: MessageEvent) { const data: WorkerRequestProxyMessage = (messageEvent.data: any); const { id, message } = data; if (!id) { port.postMessage({ error: new Error('Request without identifier'), }); } try { - const result = processAppRequest(message); + const result = await processAppRequest(message); port.postMessage({ id, message: result, }); } catch (e) { port.postMessage({ id, error: e, }); } }; } self.addEventListener('connect', connectHandler); diff --git a/web/types/worker-types.js b/web/types/worker-types.js index efd269c2e..bd1fd706f 100644 --- a/web/types/worker-types.js +++ b/web/types/worker-types.js @@ -1,42 +1,51 @@ // @flow // The types of messages sent from app to worker export const workerRequestMessageTypes = Object.freeze({ PING: 0, + INIT: 1, }); export type PingWorkerRequestMessage = { +type: 0, +text: string, }; -export type WorkerRequestMessage = PingWorkerRequestMessage; +export type InitWorkerRequestMessage = { + +type: 1, + +sqljsFilePath: string, + +sqljsFilename: ?string, +}; + +export type WorkerRequestMessage = + | PingWorkerRequestMessage + | InitWorkerRequestMessage; export type WorkerRequestProxyMessage = { +id: number, +message: WorkerRequestMessage, }; // The types of messages sent from worker to app export const workerResponseMessageTypes = Object.freeze({ PONG: 0, }); export type PongWorkerResponseMessage = { +type: 0, +text: string, }; export type WorkerResponseMessage = PongWorkerResponseMessage; export type WorkerResponseProxyMessage = { +id?: number, +message?: WorkerResponseMessage, +error?: Error, }; // SharedWorker types export type SharedWorkerMessageEvent = MessageEvent & { +ports: $ReadOnlyArray, ... };