mirror of
https://github.com/frappe/books.git
synced 2025-02-02 03:58:26 +00:00
incr: improve db call error handling
This commit is contained in:
parent
969ec5d7cd
commit
ca5514417e
111
fyo/demux/db.ts
111
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<DatabaseResponse>): Promise<unknown> {
|
||||
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<SchemaMap> {
|
||||
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<string> {
|
||||
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<string> {
|
||||
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<unknown> {
|
||||
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<unknown> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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<unknown>) {
|
||||
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;
|
||||
}
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export interface DatabaseResponse {
|
||||
error: string;
|
||||
data?: unknown;
|
||||
error?: { message: string; name: string; stack?: string };
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user