Skip to content

Node library for generating IPC components for Electron apps.

License

Notifications You must be signed in to change notification settings

aabmets/automate-electron-ipc

Repository files navigation

Automate Electron IPC

Node LTS NPM License Code Coverage NPM Downloads

Quality Gate Status Security Rating Reliability Rating Maintainability Rating
Vulnerabilities Bugs Code Smells Lines of Code

Description

Node library for generating IPC components for Electron apps.

Features

  1. Declarative IPC schema using channel expressions
  2. Generation of sender and listener callables for the main process
  3. Generation of preload bindings for renderer processes
  4. Generation of typehints for the renderer Window object
  5. Automatic import of user-defined types for generated components
  6. BrowserWindow event triggers for MainToRenderer Broadcast channels

Installation

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

Optional Configuration

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 when moduleResolution in tsconfig.json is nodenext.
  • 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.

Getting Started

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.

Channel Expressions

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.

Simple Example

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.

Channel Directions and Kinds

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

About

Node library for generating IPC components for Electron apps.

Resources

License

Stars

Watchers

Forks