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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ipsme/reflector-electron-msgenv-ipc-main

v1.0.15

Published

Reflector between a messaging environment (MQTT on win32, NSDNC on darwin, or an injected one) and Electron IPC (main process).

Readme

npm-reflector-electron-MsgEnv-ipc-main

A reflector between a messaging environment and Electron IPC (main process). Messages published to the messaging environment are forwarded to every registered renderer window, and messages sent from a renderer are published back to it. Duplicate reflections are suppressed via @ipsme/msgcache-dedup.

The messaging environment is chosen per platform by default:

| Platform | Default messaging environment | |-------------------|--------------------------------------------------------------------------------------| | win32 | @ipsme/msgenv-mqtt (mqtt://localhost:1883) | | darwin | @ipsme/msgenv-electron-nsdnc (NSDistributedNotificationCenter) | | anything else | none — you must inject one (see Overriding the default below) |

Both msgenv packages are optionalDependencies, and only the one for your platform is ever required at runtime -- default_MsgEnv() loads MQTT on win32, NSDNC on darwin. So the app runs with just the platform's package present, and if you inject your own (see Overriding the default below) you need neither.

Note: optionalDependencies does not make npm install only the platform's package. It means "don't fail the whole install if one of these can't be installed" -- npm skips an optional dep only when it actually fails (e.g. an os/cpu mismatch or a build error). Neither msgenv-* package declares an os field, so a default npm install installs both on every platform; the per-platform choice happens purely at runtime in default_MsgEnv(). If you want npm to prune the wrong one automatically, those packages would each need an os field (darwin on NSDNC, win32 on MQTT) -- nothing in this repo can enforce that. In the meantime you can remove the unused one yourself, or just leave it (harmless, only ever required on its platform).

IPSME — Idempotent Publish/Subscribe Messaging Environment

https://dl.acm.org/doi/abs/10.1145/3458307.3460966

main.js | electron.js
//-------------------------------------------------------------------------------------------------
// reflector msgenv <-> ipc

const { Reflector_IPC_main } = require('@ipsme/reflector-electron-msgenv-ipc-main');
const { ipcMain } = require('electron');

// No second argument -> uses the platform default (MQTT on win32, NSDNC on darwin).
const reflector_IPC_main_ = new Reflector_IPC_main(ipcMain);
reflector_IPC_main_.subscribe();

//-------------------------------------------------------------------------------------------------

function createWindow() {
	// Create the browser window.
	const win = new BrowserWindow({
		// ...
		webPreferences: {
			// nodeIntegration: true,
			preload: __dirname + '/preload.js'
		},
	});

	// ...

	reflector_IPC_main_.add_window(win);

	win.on('closed', () => {
		reflector_IPC_main_.remove_window(win);
		// ...
	});
}

Overriding the default messaging environment

Pass a messaging environment as the second constructor argument and it is used instead of the platform default (which is then never resolved -- so you don't even need the platform's msgenv-* package installed). This is how you run on an unsupported platform, select a non-default ME, or inject a mock/stub in tests.

The injected object must expose:

  • publish(msg) -- publish a message to the ME;
  • subscribe(handler) -- register handler(msg) for messages arriving from the ME;
  • (optional) logr -- a bitlogr-3.x logger; if present it is wired into the reflector's logging (see Logging below).

A provided-but-unusable env (missing publish/subscribe, or an explicit null) throws at construction: Reflector_IPC_main: msgEnv must expose .publish(msg) and .subscribe(handler).

const { Reflector_IPC_main } = require('@ipsme/reflector-electron-msgenv-ipc-main');
const IPSME_MsgEnv = require('@ipsme/msgenv-mqtt'); // or any ME you like

const reflector_IPC_main_ = new Reflector_IPC_main(ipcMain, IPSME_MsgEnv);
reflector_IPC_main_.subscribe();

A stub is enough for tests -- no broker required:

const bus = [];
const fake_env = {
	publish:   (msg) => bus.push(msg),
	// keep the handler so a test can push an inbound ME message: fake_env.deliver(msg)
	subscribe: (handler) => { fake_env.deliver = handler; }
};
const reflector_IPC_main_ = new Reflector_IPC_main(ipcMain, fake_env);

Preload (context bridge)

//-------------------------------------------------------------------------------------------------
// preload.js

// https://github.com/electron/electron/issues/9920#issuecomment-947170941

const { contextBridge, ipcRenderer } = require("electron");

// As an example, here we use the exposeInMainWorld API to expose the IPC renderer
// to the main window. They'll be accessible at "window.ipc_reflector".
process.once("loaded", () => {
    contextBridge.exposeInMainWorld('ipc_reflector',
		{
			// https://github.com/electron/electron/issues/21437#issuecomment-573522360
			send: (msg) => ipcRenderer.send('ipc-reflector-to-main', msg),
			recv: (fn) => {
				// Deliberately strip event as it includes `sender`
				ipcRenderer.on('ipc-reflector-to-window', (event, ...args) => fn(...args));
			}
		}
	);
});

Logging

Logging uses @knev/bitlogr (3.x). On construction the reflector wire()s its own logger (labels DUPLICATES, CONNECTIONS, REFLECTION) together with the loggers of the participants it uses -- the @ipsme/msgcache-dedup dedup cache and the configured messaging environment -- so every label shares one toggle mask on the shared LOGR instance. Only a participant exposing a bitlogr-3.x logger (one with a .lref) is wired; a legacy build is simply left to log on its own.

The wired logger is exported as logr. Toggle categories through the shared LOGR instance, after a reflector has been constructed (construction is when the wire happens):

const { logr } = require('@ipsme/reflector-electron-msgenv-ipc-main');
const { LOGR } = require('@knev/bitlogr');

LOGR.get_instance().toggle(logr.l, { REFLECTION: true, CONNECTIONS: true });

Note: options is currently an inert instance setter -- it stores the value but does not (yet) toggle logging or forward to the messaging environment's config.