Main Process API
import { mainPortLink, createWindowMessagePortHandler, createPortBroker, createPortHandler,} from 'electron-messageport-trpc/main';createWindowMessagePortHandler(opts)
Section titled “createWindowMessagePortHandler(opts)”Creates and maintains MessagePort-backed tRPC handlers for one or more Electron windows.
Parameters
Section titled “Parameters”interface CreateWindowMessagePortHandlerOptions<TRouter extends AnyRouter> { router: TRouter; windows: readonly BrowserWindow[]; createContext?: (opts: { window: BrowserWindow }) => Promise<unknown>;}| Parameter | Type | Required | Description |
|---|---|---|---|
router | AnyRouter | Yes | Your tRPC router instance |
windows | readonly BrowserWindow[] | Yes | Windows that should receive a renderer-side port |
createContext | (opts: { window: BrowserWindow }) => Promise<unknown> | No | Factory invoked for each request with the matching window |
Returns
Section titled “Returns”A WindowMessagePortHandler object.
WindowMessagePortHandler
Section titled “WindowMessagePortHandler”handler.destroy()
Section titled “handler.destroy()”Stops all managed window handlers and removes their Electron event listeners.
Example
Section titled “Example”import { createWindowMessagePortHandler } from 'electron-messageport-trpc/main';import { appRouter } from './router';
app.whenReady().then(() => { const win = new BrowserWindow({ /* ... */ });
createWindowMessagePortHandler({ router: appRouter, windows: [win], createContext: async ({ window }) => ({ windowId: window.id, }), });});mainPortLink(opts)
Section titled “mainPortLink(opts)”Creates a tRPC client link for MessagePortMain-compatible ports in the main process. Use this when the main process is the tRPC client, such as calling a utility process over MessageChannelMain.
Parameters
Section titled “Parameters”interface MainPortLinkOptions { port: MessagePortMain | Promise<MessagePortMain>;}| Parameter | Type | Required | Description |
|---|---|---|---|
port | MessagePortMain | Promise<MessagePortMain> | Yes | The client-side main-process port |
Example
Section titled “Example”import { createTRPCClient } from '@trpc/client';import { MessageChannelMain, utilityProcess } from 'electron';import { mainPortLink } from 'electron-messageport-trpc/main';
const child = utilityProcess.fork('utility-worker.js');const { port1, port2 } = new MessageChannelMain();
child.postMessage({ type: 'connect' }, [port1]);
const client = createTRPCClient({ links: [mainPortLink({ port: port2 })],});createPortBroker()
Section titled “createPortBroker()”Creates a port broker that generates MessagePort pairs for connecting renderers to the main process.
Returns
Section titled “Returns”A PortBroker object.
PortBroker
Section titled “PortBroker”broker.createRendererPort(webContents)
Section titled “broker.createRendererPort(webContents)”Creates a MessageChannelMain pair, sends one port to the specified renderer, and returns the other.
Parameters:
| Parameter | Type | Description |
|---|---|---|
webContents | WebContents | The target renderer’s webContents object (e.g., win.webContents) |
Returns:
{ serverPort: MessagePortMain;}The serverPort is the main-process side of the channel. Pass it to createPortHandler() to start handling tRPC requests.
Example
Section titled “Example”import { createPortBroker } from 'electron-messageport-trpc/main';
const broker = createPortBroker();
// After the window loads:const { serverPort } = broker.createRendererPort(win.webContents);createPortHandler(opts)
Section titled “createPortHandler(opts)”Attaches a tRPC request handler to a MessagePort. It listens for incoming tRPC requests (queries, mutations, subscriptions) and routes them to the given router.
Parameters
Section titled “Parameters”interface CreatePortHandlerOptions<TRouter extends AnyRouter> { port: MessagePortLike; router: TRouter; createContext?: () => Promise<unknown>;}| Parameter | Type | Required | Description |
|---|---|---|---|
port | MessagePortMain | Yes | The server-side MessagePort (from createRendererPort) |
router | AnyRouter | Yes | Your tRPC router instance |
createContext | () => Promise<unknown> | No | Factory function called for every request to create the context object |
Returns
Section titled “Returns”A PortHandler object.
PortHandler
Section titled “PortHandler”handler.destroy()
Section titled “handler.destroy()”Stops all active subscriptions, aborts their AbortControllers, and closes the underlying MessagePort.
Call this when the associated BrowserWindow is closed or the connection is no longer needed.
Example
Section titled “Example”import { createPortBroker, createPortHandler } from 'electron-messageport-trpc/main';import { appRouter } from './router';
const broker = createPortBroker();
app.whenReady().then(() => { const win = new BrowserWindow({ /* ... */ });
win.webContents.on('did-finish-load', () => { const { serverPort } = broker.createRendererPort(win.webContents);
const handler = createPortHandler({ port: serverPort, router: appRouter, createContext: async () => ({ // per-request context windowId: win.id, }), });
// Clean up when the window closes win.on('closed', () => { handler.destroy(); }); });});Subscription Handling
Section titled “Subscription Handling”When a subscription request arrives:
- The procedure is called and must return an async iterable.
- The handler sends
{ kind: 'result', type: 'started' }. - Each yielded value is sent as a
{ kind: 'result', type: 'data' }message. - If the procedure yields
tracked(id, data), the handler sends the tracked event ID for tRPC v11 resumption. - When the client sends
{ kind: 'subscription.stop' }, theAbortControlleris aborted. - When the port closes, all active subscriptions are aborted automatically.