Socket
Book a DemoInstallSign in
Socket

electron-ipc-decorator

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

electron-ipc-decorator

A TypeScript-first decorator library that simplifies Electron IPC communication with type safety and automatic proxy generation

latest
Source
npmnpm
Version
0.2.0
Version published
Maintainers
1
Created
Source

Electron IPC Decorator

A TypeScript-first decorator library that simplifies Electron IPC communication with type safety and automatic proxy generation.

Features

  • 🎯 Type-Safe: Full TypeScript support with automatic type inference
  • 🚀 Decorator-Based: Clean and intuitive API using decorators
  • 🔄 Auto Proxy: Automatic client-side proxy generation
  • 📦 Service Groups: Organize IPC methods into logical service groups
  • 🛡️ Error Handling: Built-in error handling and logging
  • Async Support: Native support for async/await patterns

Installation

npm install electron-ipc-decorator
# or
pnpm add electron-ipc-decorator
# or
yarn add electron-ipc-decorator

Quick Start

1. Define IPC Services (Main Process)

import { app } from 'electron'
import { IpcService, IpcMethod, IpcContext } from 'electron-ipc-decorator'

export class AppService extends IpcService {
  static readonly groupName = 'app' // Define static group name

  @IpcMethod()
  getAppVersion(): string {
    return app.getVersion()
  }

  @IpcMethod()
  switchAppLocale(context: IpcContext, locale: string): void {
    // The first parameter is always IpcContext
    // Additional parameters follow after context
    i18n.changeLanguage(locale)
    app.commandLine.appendSwitch('lang', locale)
  }

  @IpcMethod()
  async search(
    context: IpcContext,
    input: SearchInput,
  ): Promise<Electron.Result | null> {
    const { sender: webContents } = context

    const { promise, resolve } = Promise.withResolvers<Electron.Result | null>()

    let requestId = -1
    webContents.once('found-in-page', (_, result) => {
      resolve(result.requestId === requestId ? result : null)
    })

    requestId = webContents.findInPage(input.text, input.options)
    return promise
  }
}

2. Initialize Services (Main Process)

import { createServices, MergeIpcService } from 'electron-ipc-decorator'
import { AppService } from './app-service'

// Create services with automatic type inference
export const services = createServices([AppService])

// Generate type definition for all services
export type IpcServices = MergeIpcService<typeof services>

3. Create Client Proxy (Renderer Process)

import { createIpcProxy } from 'electron-ipc-decorator/client'
import type { IpcServices } from './main/services' // Import from main process

// ipcRenderer should be exposed through electron's context bridge
export const ipcServices = createIpcProxy<IpcServices>(ipcRenderer)

4. Use in Renderer Process

// Synchronous methods
const version = await ipcServices.app.getAppVersion()

// Methods with parameters (context is automatically handled)
await ipcServices.app.switchAppLocale('en')

// Async methods
const searchResult = await ipcServices.app.search({
  text: 'search term',
  options: {
    findNext: false,
    forward: true,
  },
})

API Reference

Decorators

@IpcMethod()

Marks a method as an IPC endpoint.

@IpcMethod()
someMethod() { }

Classes

IpcService

Base class for creating IPC service groups.

abstract class IpcService {
  static readonly groupName: string // Must be defined by subclasses
}

IpcContext

Context object passed as the first parameter to all IPC methods.

interface IpcContext {
  sender: WebContents // The WebContents that sent the request
  event: IpcMainInvokeEvent // The original IPC event
}

Functions

createServices<T>(serviceConstructors: T): ServicesResult<T>

Creates services from an array of service constructors with automatic type inference. Each service class must define a static groupName property.

// Define services
class AppService extends IpcService {
  static readonly groupName = 'app'
  // methods...
}

class UserService extends IpcService {
  static readonly groupName = 'user'
  // methods...
}

// Create services with type safety
const services = createServices([AppService, UserService])
// Type is: { app: AppService, user: UserService }

createIpcProxy<T>(ipcRenderer: IpcRenderer): T

Creates a type-safe proxy for calling IPC methods from the renderer process.

Type Utilities

MergeIpcService<T>

Merges multiple service instances into a single type definition.

ExtractServiceMethods<T>

Extracts and transforms service methods for client-side usage, automatically:

  • Removes the IpcContext parameter
  • Wraps return types in Promise<T>

Important Notes

Method Signatures

  • Context Parameter: The first parameter of every IPC method must be IpcContext
  • Return Types: All methods return Promise<T> on the client side, even if they're synchronous on the server
  • Error Handling: Errors are automatically propagated from main to renderer process

Example Method Signatures

// Main process method signature
@IpcMethod()
someMethod(context: IpcContext, param1: string, param2: number): string {
  // Implementation
}

// Renderer process usage (auto-generated type)
ipcServices.group.someMethod(param1: string, param2: number): Promise<string>

Migration Guide

From Constructor-based to Static groupName

If you're upgrading from a version that used constructor-based group names, here's how to migrate:

Old way:

export class AppService extends IpcService {
  constructor() {
    super('app') // Group name in constructor
  }
}

// Manual service object creation
export const services = {
  app: new AppService(),
}

New way (recommended):

export class AppService extends IpcService {
  static readonly groupName = 'app' // Static group name
}

// Automatic service creation with type safety
export const services = createServices([AppService])

Benefits of the new approach:

  • Type Safety: Prevents mismatch between service keys and group names
  • Auto-completion: Full IntelliSense support for service methods
  • Runtime Safety: Compile-time errors if groupName is missing
  • Simpler: No need to manually maintain service object keys

Advanced Usage

Error Handling

Errors thrown in main process methods are automatically caught and re-thrown in the renderer process:

@IpcMethod()
riskyOperation(context: IpcContext): string {
  throw new Error("Something went wrong")
}

// In renderer
try {
  await ipcServices.app.riskyOperation()
} catch (error) {
  console.error("IPC Error:", error.message) // "Something went wrong"
}

Using WebContents

@IpcMethod()
sendNotification(context: IpcContext, message: string): void {
  const { sender } = context

  // Send data back to the specific renderer
  sender.send('notification', { message, timestamp: Date.now() })
}

TypeScript Configuration

Ensure your tsconfig.json has decorator support enabled:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

License

2025 © Innei, Released under the MIT License.

Personal Website · GitHub @Innei

Keywords

electron

FAQs

Package last updated on 23 Aug 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts