From e4155b0fe10e57ed6a21590a39fc4d2891b6401f Mon Sep 17 00:00:00 2001 From: Alex Kozack Date: Thu, 20 May 2021 19:57:46 +0300 Subject: [PATCH] =?UTF-8?q?refactor:=20=D0=A0=D0=B5=D1=84=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20IPC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/main/src/ipc/index.ts | 19 +++++++++++++++---- packages/renderer/src/ipc/index.ts | 5 ++--- packages/renderer/src/utils/dialogs.ts | 3 ++- .../shared/types/ipc/DialogsControllers.ts | 9 +++------ packages/shared/types/ipc/Host.ts | 3 +-- .../shared/types/ipc/WindowControllers.ts | 9 +++------ packages/shared/types/ipc/index.ts | 6 +++--- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/packages/main/src/ipc/index.ts b/packages/main/src/ipc/index.ts index e2b3620b..9d0508c3 100644 --- a/packages/main/src/ipc/index.ts +++ b/packages/main/src/ipc/index.ts @@ -2,16 +2,27 @@ import {ipcMain} from 'electron'; import type {IpcNameHostsMap} from '/@shared/types/ipc'; +function hasProperty(host: T, prop: string): prop is string & keyof T { + return !!(host as never)[prop]; +} + + export function registerIpcHost(hostName: T, host: IpcNameHostsMap[T]): void { - ipcMain.handle(hostName, async (event, methodName: keyof IpcNameHostsMap[T], ...args: unknown[]) => { + ipcMain.handle(hostName, async (event, methodName: unknown, ...args) => { + if (typeof methodName !== 'string') { + throw new Error(`methodName must be a string (got ${JSON.stringify(methodName)}) when called host "${hostName}"`); + } + + if (!hasProperty(host, methodName)) { + throw new Error(`"${methodName}" is undefined method on host "${hostName}"`); + } + const method = host[methodName]; - // If requested method does not exist, reject. if (typeof method !== 'function') { - throw new Error(`Invalid method name "${methodName}" on host "${hostName}"`); + throw new Error(`"${methodName}" in not a function on host "${hostName}"`); } return method(...args); }); - } diff --git a/packages/renderer/src/ipc/index.ts b/packages/renderer/src/ipc/index.ts index b1c67371..d81c0002 100644 --- a/packages/renderer/src/ipc/index.ts +++ b/packages/renderer/src/ipc/index.ts @@ -7,14 +7,13 @@ const {invoke} = useElectron(); export function createIpcClient(hostName: T): Promisified { return new Proxy({} as never, { - get: (obj, methodName: string) => { + get: (obj, methodName) => { // Chrome runtime could try to call those method if the proxy object // is passed in a resolve or reject Promise function - if (methodName === 'then' || methodName === 'catch') + if (methodName === 'then' || methodName === 'catch' || methodName === 'finally') return undefined; - // If accessed field effectivly exist on proxied object, act as a noop if (Object.prototype.hasOwnProperty.call(obj, methodName)) { return obj[methodName]; } diff --git a/packages/renderer/src/utils/dialogs.ts b/packages/renderer/src/utils/dialogs.ts index f3df9dcc..22d5f8a2 100644 --- a/packages/renderer/src/utils/dialogs.ts +++ b/packages/renderer/src/utils/dialogs.ts @@ -1,7 +1,8 @@ import {createIpcClient} from '/@/ipc'; -export function showErrorMessage({title = 'Ошибка', message = 'Неизвестная ошибка'}) { +export function showErrorMessage({title = 'Ошибка', message = 'Неизвестная ошибка'}): Promise { const dialog = createIpcClient('DialogsControllers'); return dialog.showError(title, message); } + diff --git a/packages/shared/types/ipc/DialogsControllers.ts b/packages/shared/types/ipc/DialogsControllers.ts index 0c98d667..c7fadc21 100644 --- a/packages/shared/types/ipc/DialogsControllers.ts +++ b/packages/shared/types/ipc/DialogsControllers.ts @@ -1,9 +1,6 @@ -import type {HostBase, MethodOnlyHost} from './Host'; +import type {IpcHost} from './Host'; -interface DialogsControllersBase extends HostBase { +export type DialogsControllers = IpcHost<{ showError: (title: string, content: string) => void -} - - -export type DialogsControllers = MethodOnlyHost +}> diff --git a/packages/shared/types/ipc/Host.ts b/packages/shared/types/ipc/Host.ts index 0b934399..4825ac6d 100644 --- a/packages/shared/types/ipc/Host.ts +++ b/packages/shared/types/ipc/Host.ts @@ -1,5 +1,4 @@ import type {ClearIndex, Fn, NonFunctionKeys} from '../utils'; -export type HostBase = Record -export type MethodOnlyHost = Omit, NonFunctionKeys>> +export type IpcHost> = Omit, NonFunctionKeys>> diff --git a/packages/shared/types/ipc/WindowControllers.ts b/packages/shared/types/ipc/WindowControllers.ts index 3e28421c..7949c4b1 100644 --- a/packages/shared/types/ipc/WindowControllers.ts +++ b/packages/shared/types/ipc/WindowControllers.ts @@ -1,13 +1,10 @@ -import type {HostBase, MethodOnlyHost} from './Host'; +import type {IpcHost} from './Host'; -interface WindowControllersBase extends HostBase { +export type WindowControllers = IpcHost<{ minimize: () => void maximize: () => void unmaximize: () => void close: () => void isMaximized: () => boolean -} - - -export type WindowControllers = MethodOnlyHost +}> diff --git a/packages/shared/types/ipc/index.ts b/packages/shared/types/ipc/index.ts index aeb86545..bebcdce1 100644 --- a/packages/shared/types/ipc/index.ts +++ b/packages/shared/types/ipc/index.ts @@ -1,11 +1,11 @@ import type {WindowControllers} from './WindowControllers'; import type {DialogsControllers} from './DialogsControllers'; -import type {HostBase} from './Host'; -import type {ClearIndex} from '../utils'; +import type {IpcHost} from './Host'; +import type {ClearIndex, Fn} from '../utils'; -interface IpcNameHostsMapBase extends Record { +interface IpcNameHostsMapBase extends Record>> { 'WindowControllers': WindowControllers 'DialogsControllers': DialogsControllers }