import { Mutator } from '@seleniumhq/side-api' import { ipcMain } from 'electron' import noop from 'lodash/fp/noop' import { AsyncHandler, HandlerFactory } from './Handler' import { Session, SessionControllerKeys } from '../../types' export type ParametersExceptFirst = F extends ( arg0: any, ...rest: infer R ) => any ? R : never export type EventApiHandler = ( event: Electron.IpcMainEvent, ...args: any[] ) => any export type ModifiedHandler = ( ...args: ParametersExceptFirst ) => ReturnType const defaultHandler = ( path: string, session: Session ): AsyncHandler => { const [namespace, method] = path.split('.') const controller = session[namespace as SessionControllerKeys] if (controller && method in controller) { // @ts-expect-error return controller[method].bind(controller) as AsyncHandler } console.warn(`Missing method for path ${path}, using passthrough`) return noop as unknown as AsyncHandler } const Handler = ( factory: HandlerFactory = defaultHandler ) => ( path: string, session: Session, mutator?: Mutator> ) => { const handler = factory(path, session) const doAPI = async (...params: Parameters) => { const result = await handler(...params) const serializableParams = params.slice( 1 ) as ParametersExceptFirst await session.state.mutate(mutator, serializableParams, result, path) return result } ipcMain.handle(path, async (...args) => { session.system.loggers.api('Received API Request', path, args.slice(1)) const result = await doAPI(...(args as Parameters)) session.system.loggers.api('Resolved API Request', path, result) return result }) return doAPI } export default Handler