Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error reporting for import with opossum-file #2771

Merged
merged 3 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions src/ElectronBackend/errorHandling/errorHandling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { getGlobalBackendState } from '../main/globalBackendState';
import logger from '../main/logger';
import { getLoadedFilePath } from '../utils/getLoadedFile';

async function reportListenerError(
async function reportListenerErrorInBackend(
mainWindow: BrowserWindow,
error: unknown,
): Promise<void> {
Expand All @@ -40,6 +40,19 @@ async function reportListenerError(
}
}

function reportListenerErrorInFrontend(_: BrowserWindow, error: unknown): void {
if (error instanceof Error) {
logger.error(error.message);
} else {
logger.error('Unexpected internal error');
}
}

export const ListenerErrorReporter = {
Backend: reportListenerErrorInBackend,
Frontend: reportListenerErrorInFrontend,
};

type FuncType<T> = T extends (...args: infer P) => infer R
? (...args: P) => R
: never;
Expand All @@ -52,28 +65,37 @@ type FTParameters<A> = A extends FuncType<A> ? Parameters<A> : never;
export function createVoidListenerCallbackWithErrorHandling<F>(
mainWindow: BrowserWindow,
func: F & FuncType<F>,
reportError: (
mainWindow: BrowserWindow,
error: unknown,
) => Promise<void> | void = reportListenerErrorInBackend,
): (...args: FTParameters<F>) => Promise<void> {
return async (...args: FTParameters<F>): Promise<void> => {
try {
await func(...args);
} catch (error: unknown) {
await reportListenerError(mainWindow, error);
await reportError(mainWindow, error);
}
};
}

export function createListenerCallbackWithErrorHandling<F>(
mainWindow: BrowserWindow,
returnValueOnError: ReturnTypeWithoutPromise<F>,
func: F & FuncType<F>,
): (...args: FTParameters<F>) => Promise<ReturnTypeWithoutPromise<F> | null> {
reportError: (
mainWindow: BrowserWindow,
error: unknown,
) => Promise<void> | void = reportListenerErrorInBackend,
): (...args: FTParameters<F>) => Promise<ReturnTypeWithoutPromise<F>> {
return async (
...args: FTParameters<F>
): Promise<ReturnTypeWithoutPromise<F> | null> => {
): Promise<ReturnTypeWithoutPromise<F>> => {
try {
return (await func(...args)) as ReturnTypeWithoutPromise<F>;
} catch (error: unknown) {
await reportListenerError(mainWindow, error);
return Promise.resolve(null);
await reportError(mainWindow, error);
return Promise.resolve(returnValueOnError);
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/ElectronBackend/main/__tests__/listeners.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ describe('getImportFileSelectSaveLocationListener', () => {
'',
);

expect(returnedFilePath).toBeNull();
expect(returnedFilePath).toBe('');
});
});

Expand Down
28 changes: 13 additions & 15 deletions src/ElectronBackend/main/listeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { LoadedFileFormat } from '../enums/enums';
import {
createListenerCallbackWithErrorHandling,
createVoidListenerCallbackWithErrorHandling,
ListenerErrorReporter,
} from '../errorHandling/errorHandling';
import { loadInputAndOutputFromFilePath } from '../input/importFromFile';
import { serializeAttributions } from '../input/parseInputData';
Expand Down Expand Up @@ -146,9 +147,10 @@ export function getImportFileSelectInputListener(
): (
_: Electron.IpcMainInvokeEvent,
fileFormat: FileFormatInfo,
) => Promise<string | null> {
) => Promise<string> {
return createListenerCallbackWithErrorHandling(
mainWindow,
'',
(_: Electron.IpcMainInvokeEvent, fileFormat: FileFormatInfo) => {
const filePaths = openNonOpossumFileDialog(fileFormat);

Expand All @@ -163,15 +165,13 @@ export function getImportFileSelectInputListener(

export function getImportFileSelectSaveLocationListener(
mainWindow: BrowserWindow,
): (
_: Electron.IpcMainInvokeEvent,
defaultPath: string,
) => Promise<string | null> {
): (_: Electron.IpcMainInvokeEvent, defaultPath: string) => Promise<string> {
return createListenerCallbackWithErrorHandling(
mainWindow,
'',
(_: Electron.IpcMainInvokeEvent, defaultPath: string) => {
const filePath = saveFileDialog(defaultPath);
return filePath ?? null;
return filePath ?? '';
},
);
}
Expand All @@ -184,33 +184,30 @@ export function getImportFileConvertAndLoadListener(
resourceFilePath: string,
fileType: FileType,
opossumFilePath: string,
) => Promise<boolean | null> {
) => Promise<boolean> {
return createListenerCallbackWithErrorHandling(
mainWindow,
false,
async (
_: Electron.IpcMainInvokeEvent,
resourceFilePath: string,
fileType: FileType,
opossumFilePath: string,
) => {
if (!resourceFilePath.trim() || !fs.existsSync(resourceFilePath)) {
logger.error('Input file does not exist');
return false;
throw new Error('Input file does not exists');
}

if (!opossumFilePath.trim()) {
logger.error('No .opossum save location selected');
return false;
throw new Error('No .opossum save location selected');
}

if (!opossumFilePath.endsWith('.opossum')) {
logger.error('Output file name must have .opossum extension');
return false;
throw new Error('Output file name must have .opossum extension');
}

if (!fs.existsSync(path.dirname(opossumFilePath))) {
logger.error('Output directory does not exist');
return false;
throw new Error('Output directory does not exist');
}

logger.info('Converting .json to .opossum format');
Expand Down Expand Up @@ -239,6 +236,7 @@ export function getImportFileConvertAndLoadListener(

return true;
},
ListenerErrorReporter.Frontend,
);
}

Expand Down
18 changes: 11 additions & 7 deletions src/ElectronBackend/opossum-file/convertScancodeToOpossum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ export async function convertScancodeToOpossum(
pathToScanCode: string,
pathToOpossum: string,
): Promise<void> {
await execFile(OPOSSUM_FILE_EXECUTABLE, [
'generate',
'-o',
pathToOpossum,
'--scan-code-json',
pathToScanCode,
]);
try {
await execFile(OPOSSUM_FILE_EXECUTABLE, [
'generate',
'-o',
pathToOpossum,
'--scan-code-json',
pathToScanCode,
]);
} catch (error) {
throw new Error('Conversion of ScanCode file to .opossum file failed');
}
}
6 changes: 3 additions & 3 deletions src/shared/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,13 @@ export interface ElectronAPI {
relaunch: () => void;
openLink: (link: string) => Promise<unknown>;
openFile: () => Promise<unknown>;
importFileSelectInput: (fileFormat: FileFormatInfo) => Promise<string | null>;
importFileSelectSaveLocation: (defaultPath: string) => Promise<string | null>;
importFileSelectInput: (fileFormat: FileFormatInfo) => Promise<string>;
importFileSelectSaveLocation: (defaultPath: string) => Promise<string>;
importFileConvertAndLoad: (
inputFilePath: string,
fileType: FileType,
opossumFilePath: string,
) => Promise<boolean | null>;
) => Promise<boolean>;
exportFile: (args: ExportArgsType) => void;
saveFile: (saveFileArgs: SaveFileArgs) => void;
on: (channel: AllowedFrontendChannels, listener: Listener) => () => void;
Expand Down
Loading