Node library for generating IPC components for Electron apps.
- Declarative IPC schema using channel expressions
- Generation of sender and listener callables for the main process
- Generation of preload bindings for renderer processes
- Generation of typehints for the renderer Window object
- Automatic import of user-defined types for generated components
- BrowserWindow event triggers for MainToRenderer Broadcast channels
bun add automate-electron-ipc --dev
pnpm add automate-electron-ipc --save-dev
yarn add automate-electron-ipc --dev
npm install automate-electron-ipc --save-dev
You can configure IPC automation in the package.json
file using the following options.
If no configuration is provided, IPC automation will use the default values as shown in the example below.
{
"config": {
"autoipc": {
"projectUsesNodeNext": false,
"ipcDataDir": "src/autoipc",
"codeIndent": 3
}
}
}
Config explanation:
-
projectUsesNodeNext
- Must be set to true whenmoduleResolution
intsconfig.json
isnodenext
. -
ipcDataDir
- Relative path to a directory within the users project which will contain the IPC schema expressions and where the IPC bindings will be generated into. -
codeIndent
- How many spaces will one code indentation level have within the generated IPC bindings.
IPC bindings are generated by calling the ipcgen
command provided by this library from the command line.
When you initially run this command, you will get a warning about IPC channels not being found.
Do not let this warning dissuade you, as it's purpose is to guide you where to create the schema
file or directory, which will contain the channel expressions that will be parsed by IPC automation.
By default, IPC automation looks for a file named schema.ts
in the IPC data directory.
If you create a directory named schema
into the IPC data directory, then IPC automation
will recursively parse all files within it for Channel expressions, meaning it is possible
to structure and segment channel expressions according to the needs of larger applications.
IPC automation uses its own Domain-Specific Language to generate IPC bindings. We call this language CHEX
,
which masquerades itself as regular JavaScript/TypeScript, but it's code is never executed by Node. Instead,
this library uses the TypeScript library internally to parse the channel expressions from schema files to
deduce the meanings behind their definitions.
Since this library is well-documented through its type definitions, the developer is encouraged to use an IDE
which facilitates easy type inference and hints within its user interface. To that end, you should configure your
tsconfig.node.json
to include the generated main.ts
and preload.ts
files from within the IPC data directory.
For the renderer process, you should include the generated window.d.ts
file into your tsconfig.web.json
file.
Note: IPC automation does not make a distinction between senders/listeners and invokers/handlers as they are defined in the IPC documentation of the Electron library. Whether an IPC component is generated as a sender/listener or invoker/handler under the hood depends on the direction and the kind of the channel expression. The reason behind this design choice was to allow the user to focus on IPC arguments and return types without having to concern themselves with IPC internals.
Schema file content at path src/autoipc/schema.ts
:
import { Channel, type } from "automate-electron-ipc";
Channel("EchoUserName").RendererToMain.Broadcast({
signature: type as (userName: string) => void
});
After IPC bindings have been generated by running ipcgen
, they can be used as described below.
Note: For brevity sake, other important code related to BrowserWindow has been omitted.
In main process source code file src/main/index.ts
:
import { app } from "electron";
import { ipcMain } from "../autoipc/main";
app.whenReady().then(() => {
ipcMain.onEchoUserName((event, userName) => console.log(`Greetings, ${userName}!`));
});
Anywhere in renderer process source code:
<button onClick={() => window.ipc.sendEchoUserName("Anonymous")}>
The example code provides only basic HTML, because this library is front-end-tech agnostic, meaning you can use any front-end framework or library like React, Vue or Angular.
Channels may be defined with three directions:
Channel("Channel1").RendererToMain // IPC call from a renderer process to the main process
Channel("Channel2").MainToRenderer // IPC call from the main process to a renderer process
Channel("Channel3").RendererToRenderer // Port binding between two renderer processes
Each direction supports specific kinds of transmissions:
Channel("Channel1").RendererToMain.Broadcast() // Message from one sender to one or multiple listeners without return data
Channel("Channel2").RendererToMain.Unicast() // Message from one sender to one listener with return data
Channel("Channel3").MainToRenderer.Broadcast() // Message from one sender to one or multiple listeners without return data
Channel("Channel4").RendererToRenderer.Port() // Sender and listener on same port for each process