npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@amazingcat/electron-ipc-router

v1.3.2

Published

Small Electron IPC router, which implements request-response pattern

Downloads

89

Readme

Amazing Electron IPC Router

Простой роутер, реализующий request-response паттерн при работе с Electron IPC.

Установка и зависимости

Так как он пока ещё не выложен в репозитории пакетного менеджера, то установка происходит через указание репозитория в Git. Идём в package.json, и в секцию dependencies прописываем следующее

// Если работа с гитом осуществляется через SSH
"amazing-electron-ipc-router": "git+ssh://[email protected]:AmazingTime/amazing-electron-ipc-router.git"

// .. или, если работаем через HTTPS
"amazing-electron-ipc-router": "git+https://[email protected]/AmazingTime/amazing-electron-ipc-router.git"

После этого делаем npm install и всё хорошо. Данный модуль содержит у себя в зависимостях пакет uuid.

Простые примеры

Простой пример работы с IPC-роутером для общего понимания.

Main-процесс

// Получаем стандартный IPC в Electron
const { ipcMain } = require('electron');

// Подгружаем наш IPCRouter и создаём его инстанс
const IPCRouter = require('amazing-electron-ipc-router');

// Второй аргумент не обязателен - при его отсутствии будет присовен идентификатор по умолчанию
// Для обращения к нему, в эндпоинтах следует не указывать routerId
const ipc = new IPCRouter(ipcMain, 'sampleRouterId');

// Устанавливаем хэндлер для эндпойнта
// Стоит отметить, что функция обработчика может так же быть AsyncFunction или Promise (что, в целом, одно и то же)
ipc.serve('misc/say-hi', request => {

    // Производим какие-то операции над запросом
    let greeting = `Hello, ${request.packet.body.name}!`;

    // Возвращаем ответ
    request.send(200, { greeting });

});

// Роутер может работать в обе стороны, то есть, как renderer, так и main-процессы могут обслуживать роуты и совершать запросы.
// Это пример функции, выполняющей запрос, который ожидает что-то получить в ответ
const sendCatFace = async () => {

    const result = await ipc.request('catface:sampleRouterId', { catface: '(,,◕ ⋏ ◕,,)' })
    console.log(result.body.message); // выведет: Thank you for this pretty catface!

};

// А вот так можно сделать запрос, который не ожидает ничего получить в ответ
ipc.emit('playback/control:sampleRouterId', { action: 'NextSong' });

Renderer-процесс

// Получаем стандартный IPC в Electron
const { ipcRenderer } = require('electron');

// Подгружаем наш IPC и создаём его инстанс
const IPCRouter = require('amazing-electron-ipc-router');

// Второй аргумент не обязателен - при его отсутствии будет присовен идентификатор по умолчанию
// Для обращения к нему, в эндпоинтах следует не указывать routerId
const ipc = new IPCRouter(ipcRenderer, 'sampleRouterId');

// Обслуживаем эндпойнт, который принимаешь кошачьи морды с main-процесса
ipc.serve('catface', request => {

    // Выводим морду в консоль
    console.log(request.packet.body.catface);

    // Возвращаем ответ
    request.send(200, { message: 'Thank you for this pretty catface!' });

});

// Функция, тыркающая эндпойнт в main-процессе
const sayHi = async name => {

    const result = await ipc.request('misc/say-hi:sampleRouterId', { name: 'Mark' })
    console.log(result.body); // выведет: Hello, Mark!

};

Как работает внутри?

Очень муторно и костыльно, но фигли делать, не хттп же сервер на локалхосте поднимать, в самом деле? Вкратце, модуль организует связь по четырём событиям (они выполняют роль, как бы, каналов / соединений):

  • ipc-req:main - получение входящих запросов от Renderer-процесса
  • ipc-res:main - получение ответов на запросы от Renderer-процесса
  • ipc-req:renderer - получение входящих запросов от Main-процесса
  • ipc-res:renderer - получение ответов на запросы от Main-процесса

Пакеты являются следующими структурами:

<Request> {

    // Заголовок запроса
    _header: {

        // Уникальный идентификатор пакета (UUIDv4)
        id: String<UUID>,

        // IPC endpoint на который отправляется этот запрос
        endpoint: String,

    },

    // Тело (данные) запроса
    body: Object,

    // Функция отправки ответа
    send: Function

}

<Response> {

    // Заголовок ответа
    _header: {

        // Уникальный идентификатор пакета, на который мы отвечаем (UUIDv4)
        id: String<UUID>,

        // Статус-код ответа, в случае истечения таймаута ответа, он равен -1
        code: Number

    },

    // Тело (данные) ответа
    body: Object

}

Описание API

Здесь приведено описание основных методов. Больше информации можно найти в JSDoc в самом коде.

IPCRouter.constructor(ipc)

Конструктор класса, принимает на вход electron.ipcMain или electron.ipcRenderer. Пример:

const { ipcMain } = require('electron');
const IPC = require('amazing-electron-ipc-router');
const ipc = new IPC(ipcMain);

IPCRouter.setWebContents(wc)

Позволяет подключить к роутеру WebContents IPC, что даёт возможность отправлять запросы из main-процесса в renderer. Вызывается только в main-процессе. Пример:

const ipc = new IPC(ipcMain);
const window = new BrowserWindow(..);
ipc.setWebContents(window.webContents);

IPCRouter.serve(endpoint, handler, [override = false])

Устанавливает обработчик для эндпойнта. В качестве первого аргумента, принимает название эндпойнта (тип String), а в качестве обработчика может принимать Function (обычные функции) или AsyncFunction (async-функции и Native Promises).

Параметр override отвечает за возможность перезаписи существующего обработчика. При стандартном значении (false), при попытке повторно установить обработчик для одного эндпойнта, функция выкинет ошибку. Если же, выставить параметр override в true, то повторный вызов функции переопределит обработчик на тот, который был передан при последнем вызове.

Пример:

ipc.serve('test', async request => { ... });  // => true
ipc.serve('test', request => { ... })         // => throws Error, потому что override = false
ipc.serve('test', request => { ... }, true);  // => true, потому что override = true

IPCRouter.emit(endpoint, body)

Отправляет запрос, не требующий ответа. Принимает на вход первым аргументом имя эндпойнта (String), вторым - тело запроса (Object). Обратите внимание, что тело запроса является необходимым параметром, поэтому даже если оно пустое, то это нужно явно указать (см. пример).

Пример:

ipc.emit('test', { test: '1234' });  // => true, присутствуют данные в теле запроса
ipc.emit('test', {});               // => true, тело запроса пустое
ipc.emit('test');                    // => throws Error, т.к. тело запроса явно не указано

async IPCRouter.request(endpoint, body, [timeout = 30000])

Отправляет запрос, ожидая получить на него ответ в течении заданного времени (парметр timeout). Принимает на вход первым аргументом имя эндпойнта (String), вторым - тело запроса (Object, обратите внимание, что особенность с пустым телом запроса, описанная для IPC.emit здесь так же справедлива), третьим - таймаут ожидания ответа в миллисекундах (Number, по-дефолту, равен 30000 мс, т.е. 30 секундам).

Для отключения таймаута, необходимо третьим аргументом передать ноль (Number(0)).

Эта функция является AsyncFunction, следовательно её следует использовать в конструкциях async-await или в Promise-chain. Она возвращает объект формата Response (описание структуры которого есть выше). Пример:

async () => {

    // Запрашиваем морду кота
    const freshCatFace = await ipc.request('catface/get', { emotion: 'smile' });

    // Проверяем запрос на таймаут
    if (freshCatFace.code === -1) console.error('Request timed out, no catface for today :( ');

    // Будем считать, что код 200 означает успешное выполнение запроса
    else if (freshCatFace.code === 200) console.log('Just look at this!', freshCatFace.body.packet.face);

    // Сюда свалятся другие ошибки / статусы
    else console.error(`Error ocurred during catface fetching, #${freshCatFace.code}`);
};

Request.send([code], body)

Эта функция содержится в объекте Request, и позволяет на него чёта ответить.

Принимает на вход комбинацию статус-кода + тела ответа, или просто тела ответа (см. пример). В случае, если статус-код не указан, по-дефолту отправляется 200.

Возвращает Boolean(true), если ответ бы отправлен.

Пример:

ipc.serve('test', request => {

  request.send({ meow: 'purr' }); // => true, статус-код 200
  // или
  request.send(200, { meow: 'purr' }); // => true, статус-код 200
  // или
  request.send(400, { meow: 'woof' }); // => true, статус-код 400
  // или
  request.send(200); // => throw Error, потому что не указано тело ответа

});

Контрибьют, лицензия, ту-ду и прочее

Да а чёрт его знает, что здесь писать.