UNPKG

automate-electron-ipc

Version:

Node library for automating the generation of IPC components for Electron apps.

102 lines (101 loc) 4.19 kB
/* * Apache License 2.0 * * Copyright (c) 2024, Mattias Aabmets * * The contents of this file are subject to the terms and conditions defined in the License. * You may not use, modify, or distribute this file except in compliance with the License. * * SPDX-License-Identifier: Apache-2.0 */ import utils from "../utils.js"; import { BaseWriter } from "./base-writer.js"; export class PreloadBindingsWriter extends BaseWriter { getTargetFilePath() { return this.config.preloadBindingsFilePath; } renderEmptyFileContents() { return [ 'import { contextBridge } from "electron";\n', "contextBridge.exposeInMainWorld('ipc', {});", ].join("\n"); } renderFileContents() { const portNamesArray = []; const callablesArray = []; for (const parsedFileSpecs of this.pfsArray) { for (const spec of parsedFileSpecs.specs.channelSpecArray) { if (spec.direction === "RendererToMain") { callablesArray.push(this.buildRendererToMainCallable(spec)); } else if (spec.direction === "MainToRenderer") { this.addMainToRendererCallables(spec, callablesArray); } else if (spec.direction === "RendererToRenderer") { portNamesArray.push(spec.name); } } } const out = ['import { contextBridge, ipcRenderer } from "electron";']; const sortedCallablesArray = this.sortCallablesArray(callablesArray); const sortedCallables = sortedCallablesArray.join(`,\n${this.indents[0]}`); const bindingsExpression = [ "\ncontextBridge.exposeInMainWorld('ipc', {", `\n${this.indents[0]}${sortedCallables},`, ]; if (portNamesArray.length > 0) { const portComponents = [ 'import type { IpcRendererEvent } from "electron";', this.getPortComponents(), ...portNamesArray.map((portName) => this.getPortInitializer(portName).trim()), ]; out.push(...portComponents); const portBindings = [ `\n${this.indents[0]}ports: {`, ...portNamesArray.map((portName) => this.getPortProperty(portName)), `\n${this.indents[0]}},`, ]; bindingsExpression.push(...portBindings); } bindingsExpression.push("\n});\n"); out.push(bindingsExpression.join("")); return out.join("\n"); } buildRendererToMainCallable(spec) { const method = spec.kind === "Broadcast" ? "send" : "invoke"; const ipcRenderer = `ipcRenderer.${method}('${spec.name}', ...args)`; return `send${spec.name}: (...args: any[]) => ${ipcRenderer}`; } addMainToRendererCallables(spec, callablesArray) { const callback = "(_event: any, ...args: any[]) => callback(...args)"; const ipcRenderer = `ipcRenderer.on('${spec.name}', ${callback})`; const callableNames = spec.listeners ? spec.listeners : [`on${spec.name}`]; callableNames.forEach((name) => { callablesArray.push(`${name}: (callback: Function) => ${ipcRenderer}`); }); } getPortComponents() { return utils.dedent(` const ports: { [key: string]: MessagePort } = {};\n type PortObject = { sendMessage: Function, onMessage: Function };\n function getPortObject(portName: string): PortObject { return { sendMessage: (...args: any[]) => ports[portName].postMessage(args), onMessage: (callback: Function) => { ports[portName].onmessage = (event: MessageEvent) => callback(...event.data); }, } } `); } getPortInitializer(portName) { return utils.dedent(` ipcRenderer.on('${portName}', (event: IpcRendererEvent) => { ports.${portName} = event.ports[0]; }); `); } getPortProperty(portName) { return `\n${this.indents[1]}${portName}: getPortObject('${portName}'),`; } }