interprocess
Version:
A scalable and type-safe Electron IPC management tool with enhanced DX
110 lines (104 loc) • 11.4 kB
TypeScript
declare type IPCMainEvent = Electron.IpcMainInvokeEvent;
declare type IPCRendererEvent = Electron.IpcRendererEvent;
declare type String<T extends string> = T | Omit<string, T>;
declare type ProcessKeys<P> = keyof P extends string ? keyof P : never;
declare type Merge<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
declare type NormalizeCombinedIPCs<T extends Object[], S extends Merge<T[number]>> = {
[K in keyof S]: S[K];
};
declare type IPC<Type = {}, Event = Electron.Event> = {
[Property in keyof Type]: Type[Property] extends (event: Event, value: infer V) => infer R ? Type[Property] : never;
};
declare type IPCFactoryProps<T extends Record<string, unknown>> = {
main?: {
[K in keyof T['main']]?: (event: IPCMainEvent, args: any) => Promise<any>;
};
renderer?: {
[K in keyof T['renderer']]?: (event: IPCRendererEvent, args: any) => Promise<any>;
};
};
declare type MainHandler<Key, Target> = Target extends (event: IPCMainEvent, value: infer V) => infer R ? (handler?: (event: IPCMainEvent, handler: {
[K in Key extends string ? Key : string]: Target;
} & {
data: V;
}, ...rest: any[]) => R) => void : never;
declare type RendererHandler<Key, Target> = Target extends (event: IPCRendererEvent, value: infer V) => infer R ? (handler?: (event: IPCRendererEvent, handler: {
[K in Key extends string ? Key : string]: Target;
} & {
data: V;
}, ...rest: any[]) => R) => void : never;
declare type APIHandlers<H, I, R> = {
handle: H;
invoke: I;
remove: R;
};
declare type APIExpose<H, I, R, S extends (handlers: APIHandlers<H, I, R>) => any, Key, Append extends any> = {
apiKey?: String<Key extends string ? Key : any>;
exposeAll?: boolean;
append?: {
[K in keyof Append]: Append[K];
};
override?: (handlers: APIHandlers<H, I, R>) => ReturnType<S>;
};
declare type API<Handle, Invoke, Remove, APIConfig extends Record<string, unknown>> = APIExpose<Handle, Invoke, Remove, (handlers: APIHandlers<Handle, Invoke, Remove>) => any, '', APIConfig['append']>;
declare function combineIpcs<T extends {
main?: Object;
renderer?: Object;
}[]>(...props: [...T]): {
ipcs: NormalizeCombinedIPCs<T, Merge<T[number]>>;
exposeApiToGlobalWindow: <APIConfig extends API<{ [Property in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: RendererHandler<Property, IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>[Property]>; }, { [Property_1 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>; }, { [Property_2 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: () => void; }, APIConfig>>(props?: APIConfig) => {
key: APIConfig["apiKey"] extends string ? APIConfig["apiKey"] : "api";
api: (APIConfig["override"] extends Function ? ReturnType<APIConfig["override"]> : APIConfig["exposeAll"] extends true ? {
invoke: { [Property_1 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>; };
handle: { [Property in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: RendererHandler<Property, IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>[Property]>; };
remove: { [Property_2 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: () => void; };
} : {
invoke: { [Property_1 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>; };
}) & ((APIConfig["append"] extends infer T_1 ? { [K in keyof T_1]: APIConfig["append"][K]; } : never) | undefined);
};
ipcMain: {
handle: { [Property_3 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>>]: MainHandler<Property_3, IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_3]>; };
invoke: { [Property_4 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: (window: Electron.BrowserWindow, arg: Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>[Property_4]>[1] extends undefined ? void : Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>[Property_4]>[1], ...restOfArgs: any[]) => ReturnType<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>[Property_4]>; };
remove: { [Property_5 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>>]: () => void; };
};
ipcRenderer: {
handle: { [Property in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: RendererHandler<Property, IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>[Property]>; };
invoke: { [Property_1 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["main"], Electron.IpcMainInvokeEvent>[Property_1]>; };
remove: { [Property_2 in ProcessKeys<IPC<NormalizeCombinedIPCs<T, Merge<T[number]>>["renderer"], Electron.IpcRendererEvent>>]: () => void; };
};
};
declare function createApiToGlobalWindowExposer<Handle, Invoke, Remove>(rendererHandle: Handle, rendererInvoke: Invoke, rendererRemove: Remove): <APIConfig extends API<Handle, Invoke, Remove, APIConfig>>(props?: APIConfig) => {
key: APIConfig["apiKey"] extends string ? APIConfig["apiKey"] : "api";
api: (APIConfig["override"] extends Function ? ReturnType<APIConfig["override"]> : APIConfig["exposeAll"] extends true ? {
invoke: Invoke;
handle: Handle;
remove: Remove;
} : {
invoke: Invoke;
}) & ((APIConfig["append"] extends infer T ? { [K in keyof T]: APIConfig["append"][K]; } : never) | undefined);
};
declare function createInterprocess<T extends IPCFactoryProps<T>>(props: T): {
ipcs: T;
exposeApiToGlobalWindow: <APIConfig extends API<{ [Property in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: RendererHandler<Property, IPC<T["renderer"], Electron.IpcRendererEvent>[Property]>; }, { [Property_1 in ProcessKeys<IPC<T["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>; }, { [Property_2 in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: () => void; }, APIConfig>>(props?: APIConfig) => {
key: APIConfig["apiKey"] extends string ? APIConfig["apiKey"] : "api";
api: (APIConfig["override"] extends Function ? ReturnType<APIConfig["override"]> : APIConfig["exposeAll"] extends true ? {
invoke: { [Property_1 in ProcessKeys<IPC<T["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>; };
handle: { [Property in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: RendererHandler<Property, IPC<T["renderer"], Electron.IpcRendererEvent>[Property]>; };
remove: { [Property_2 in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: () => void; };
} : {
invoke: { [Property_1 in ProcessKeys<IPC<T["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>; };
}) & ((APIConfig["append"] extends infer T_1 ? { [K in keyof T_1]: APIConfig["append"][K]; } : never) | undefined);
};
ipcMain: {
handle: { [Property_3 in ProcessKeys<IPC<T["main"], Electron.IpcMainInvokeEvent>>]: MainHandler<Property_3, IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_3]>; };
invoke: { [Property_4 in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: (window: Electron.BrowserWindow, arg: Parameters<IPC<T["renderer"], Electron.IpcRendererEvent>[Property_4]>[1] extends undefined ? void : Parameters<IPC<T["renderer"], Electron.IpcRendererEvent>[Property_4]>[1], ...restOfArgs: any[]) => ReturnType<IPC<T["renderer"], Electron.IpcRendererEvent>[Property_4]>; };
remove: { [Property_5 in ProcessKeys<IPC<T["main"], Electron.IpcMainInvokeEvent>>]: () => void; };
};
ipcRenderer: {
handle: { [Property in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: RendererHandler<Property, IPC<T["renderer"], Electron.IpcRendererEvent>[Property]>; };
invoke: { [Property_1 in ProcessKeys<IPC<T["main"], Electron.IpcMainInvokeEvent>>]: (arg: Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1] extends undefined ? void : Parameters<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>[1], ...restOfArgs: any[]) => ReturnType<IPC<T["main"], Electron.IpcMainInvokeEvent>[Property_1]>; };
remove: { [Property_2 in ProcessKeys<IPC<T["renderer"], Electron.IpcRendererEvent>>]: () => void; };
};
};
declare function createIpcSlice<T extends IPCFactoryProps<T>>(props: T): T;
export { combineIpcs, createApiToGlobalWindowExposer, createInterprocess, createIpcSlice };