diff --git a/fyo/demux/db.ts b/fyo/demux/db.ts index d583c9ca..bad7d31c 100644 --- a/fyo/demux/db.ts +++ b/fyo/demux/db.ts @@ -1,5 +1,5 @@ import { ipcRenderer } from 'electron'; -import { DEFAULT_COUNTRY_CODE } from 'fyo/utils/consts'; +import { DatabaseError, NotImplemented } from 'fyo/utils/errors'; import { SchemaMap } from 'schemas/types'; import { DatabaseDemuxBase, DatabaseMethod } from 'utils/db/types'; import { DatabaseResponse } from 'utils/ipc/types'; @@ -12,101 +12,86 @@ export class DatabaseDemux extends DatabaseDemuxBase { this.#isElectron = isElectron; } + async #handleDBCall(func: () => Promise): Promise { + const response = await func(); + + if (response.error?.name) { + const { name, message, stack } = response.error; + const dberror = new DatabaseError(message); + dberror.name = name; + dberror.stack = stack; + + throw dberror; + } + + return response.data; + } + async getSchemaMap(): Promise { - let response: DatabaseResponse; if (this.#isElectron) { - response = await ipcRenderer.invoke(IPC_ACTIONS.DB_SCHEMA); - } else { - // TODO: API Call - response = { error: '', data: undefined }; + return (await this.#handleDBCall(async function dbFunc() { + return await ipcRenderer.invoke(IPC_ACTIONS.DB_SCHEMA); + })) as SchemaMap; } - if (response.error) { - throw new Error(response.error); - } - - return response.data as SchemaMap; + throw new NotImplemented(); } async createNewDatabase( dbPath: string, countryCode?: string ): Promise { - let response: DatabaseResponse; if (this.#isElectron) { - response = await ipcRenderer.invoke( - IPC_ACTIONS.DB_CREATE, - dbPath, - countryCode - ); - } else { - // TODO: API Call - response = { error: '', data: undefined }; + return (await this.#handleDBCall(async function dbFunc() { + return await ipcRenderer.invoke( + IPC_ACTIONS.DB_CREATE, + dbPath, + countryCode + ); + })) as string; } - if (response.error) { - throw new Error(response.error); - } - - return (response.data ?? DEFAULT_COUNTRY_CODE) as string; + throw new NotImplemented(); } async connectToDatabase( dbPath: string, countryCode?: string ): Promise { - let response: DatabaseResponse; if (this.#isElectron) { - response = await ipcRenderer.invoke( - IPC_ACTIONS.DB_CONNECT, - dbPath, - countryCode - ); - } else { - // TODO: API Call - response = { error: '', data: undefined }; + return (await this.#handleDBCall(async function dbFunc() { + return await ipcRenderer.invoke( + IPC_ACTIONS.DB_CONNECT, + dbPath, + countryCode + ); + })) as string; } - if (response.error) { - throw new Error(response.error); - } - - return (response.data ?? DEFAULT_COUNTRY_CODE) as string; + throw new NotImplemented(); } async call(method: DatabaseMethod, ...args: unknown[]): Promise { - let response: DatabaseResponse; if (this.#isElectron) { - response = await ipcRenderer.invoke(IPC_ACTIONS.DB_CALL, method, ...args); - } else { - // TODO: API Call - response = { error: '', data: undefined }; + return (await this.#handleDBCall(async function dbFunc() { + return await ipcRenderer.invoke(IPC_ACTIONS.DB_CALL, method, ...args); + })) as unknown; } - if (response.error) { - throw new Error(response.error); - } - - return response.data; + throw new NotImplemented(); } async callBespoke(method: string, ...args: unknown[]): Promise { - let response: DatabaseResponse; if (this.#isElectron) { - response = await ipcRenderer.invoke( - IPC_ACTIONS.DB_BESPOKE, - method, - ...args - ); - } else { - // TODO: API Call - response = { error: '', data: undefined }; + return (await this.#handleDBCall(async function dbFunc() { + return await ipcRenderer.invoke( + IPC_ACTIONS.DB_BESPOKE, + method, + ...args + ); + })) as unknown; } - if (response.error) { - throw new Error(response.error); - } - - return response.data; + throw new NotImplemented(); } } diff --git a/fyo/utils/errors.ts b/fyo/utils/errors.ts index 9ca6cdad..f323b644 100644 --- a/fyo/utils/errors.ts +++ b/fyo/utils/errors.ts @@ -78,6 +78,14 @@ export class CannotCommitError extends DatabaseError { } } +export class NotImplemented extends BaseError { + constructor() { + super(501, ''); + this.label = t`Not Implemented`; + this.name = 'NotImplemented'; + } +} + export class ValueError extends ValidationError {} export class ConflictError extends ValidationError {} export class InvalidFieldError extends ValidationError {} diff --git a/main/helpers.ts b/main/helpers.ts index 6e674b17..34dda83b 100644 --- a/main/helpers.ts +++ b/main/helpers.ts @@ -2,6 +2,7 @@ import { constants } from 'fs'; import fs from 'fs/promises'; import { ConfigFile, ConfigKeys } from 'fyo/core/types'; import config from 'utils/config'; +import { DatabaseResponse } from 'utils/ipc/types'; interface ConfigFilesWithModified extends ConfigFile { modified: string; @@ -44,3 +45,19 @@ export async function getConfigFilesWithModified(files: ConfigFile[]) { return filesWithModified; } + +export async function getErrorHandledReponse(func: () => Promise) { + const response: DatabaseResponse = {}; + + try { + response.data = await func(); + } catch (err) { + response.error = { + name: (err as Error).name, + message: (err as Error).message, + stack: (err as Error).stack, + }; + } + + return response; +} diff --git a/main/registerIpcMainActionListeners.ts b/main/registerIpcMainActionListeners.ts index ecc11d76..ea6438b5 100644 --- a/main/registerIpcMainActionListeners.ts +++ b/main/registerIpcMainActionListeners.ts @@ -5,12 +5,12 @@ import path from 'path'; import databaseManager from '../backend/database/manager'; import { Main } from '../main'; import { DatabaseMethod } from '../utils/db/types'; -import { DatabaseResponse } from '../utils/ipc/types'; import { IPC_ACTIONS } from '../utils/messages'; import { getUrlAndTokenString, sendError } from './contactMothership'; import { getLanguageMap } from './getLanguageMap'; import { getConfigFilesWithModified, + getErrorHandledReponse, setAndGetCleanedConfigFiles, } from './helpers'; import { saveHtmlAsPdf } from './saveHtmlAsPdf'; @@ -136,68 +136,42 @@ export default function registerIpcMainActionListeners(main: Main) { ipcMain.handle( IPC_ACTIONS.DB_CREATE, async (_, dbPath: string, countryCode: string) => { - const response: DatabaseResponse = { error: '', data: undefined }; - try { - response.data = await databaseManager.createNewDatabase( - dbPath, - countryCode - ); - } catch (error) { - response.error = (error as Error).toString(); - } - - return response; + return await getErrorHandledReponse(async function dbFunc() { + return await databaseManager.createNewDatabase(dbPath, countryCode); + }); } ); ipcMain.handle( IPC_ACTIONS.DB_CONNECT, async (_, dbPath: string, countryCode?: string) => { - const response: DatabaseResponse = { error: '', data: undefined }; - try { - response.data = await databaseManager.connectToDatabase( - dbPath, - countryCode - ); - } catch (error) { - response.error = (error as Error).toString(); - } - - return response; + return await getErrorHandledReponse(async function dbFunc() { + return await databaseManager.connectToDatabase(dbPath, countryCode); + }); } ); ipcMain.handle( IPC_ACTIONS.DB_CALL, async (_, method: DatabaseMethod, ...args: unknown[]) => { - const response: DatabaseResponse = { error: '', data: undefined }; - try { - response.data = await databaseManager.call(method, ...args); - } catch (error) { - response.error = (error as Error).toString(); - } - - return response; + return await getErrorHandledReponse(async function dbFunc() { + return await databaseManager.call(method, ...args); + }); } ); ipcMain.handle( IPC_ACTIONS.DB_BESPOKE, async (_, method: string, ...args: unknown[]) => { - const response: DatabaseResponse = { error: '', data: undefined }; - try { - response.data = await databaseManager.callBespoke(method, ...args); - } catch (error) { - response.error = (error as Error).toString(); - } - - return response; + return await getErrorHandledReponse(async function dbFunc() { + return await databaseManager.callBespoke(method, ...args); + }); } ); ipcMain.handle(IPC_ACTIONS.DB_SCHEMA, async (_) => { - const response: DatabaseResponse = { error: '', data: undefined }; - response.data = await databaseManager.getSchemaMap(); - return response; + return await getErrorHandledReponse(async function dbFunc() { + return await databaseManager.getSchemaMap(); + }); }); } diff --git a/utils/ipc/types.ts b/utils/ipc/types.ts index c86fc084..964ff796 100644 --- a/utils/ipc/types.ts +++ b/utils/ipc/types.ts @@ -1,4 +1,4 @@ export interface DatabaseResponse { - error: string; data?: unknown; + error?: { message: string; name: string; stack?: string }; }