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

@spinejs/electron-ipc-gateway

v0.1.5

Published

Electron IPC gateway for SpineJS.

Readme

@spinejs/electron-ipc-gateway

Electron IPC transport for @spinejs/gateway-core. Each handle(channel, …) route becomes an ipcMain.handle(channel, …) listener. It composes the pipeline (it does not extend a base class).

Quick start

Register your context once, write a controller, register it.

// electron-ipc.types.ts — register your context ONCE as the default `ctx` of every route
import type { ElectronIpcBaseContext } from "@spinejs/electron-ipc-gateway";

export interface ElectronIpcContext extends ElectronIpcBaseContext {
  session: { userId: string };
}

declare module "@spinejs/electron-ipc-gateway" {
  interface IpcContextRegistry {
    context: ElectronIpcContext;
  }
}
// projects.controller.ts
import { z } from "zod";
import { Controller, UseGuards } from "@spinejs/gateway-core";
import { handle } from "@spinejs/electron-ipc-gateway";
import { SessionGuard } from "./session.guard";

@UseGuards(SessionGuard)
@Controller({ inject: [ProjectsService] })
export class ProjectsController {
  constructor(private readonly projects: ProjectsService) {}

  list = handle("projects:list", {}, (_input, ctx) =>
    this.projects.findAll(ctx.session.userId)
  );
  create = handle(
    "projects:create",
    { input: z.object({ name: z.string().min(1) }) },
    (input, ctx) => this.projects.create(ctx.session.userId, input.name)
  );
}
// projects.ipc.module.ts
import { IpcModule } from "./electron-ipc-module";
import { ProjectsController } from "./projects.controller";

@IpcModule({ controllers: [ProjectsController] })
export class ProjectsIpcModule {}

On the renderer, discriminate on the envelope:

const res = await ipcRenderer.invoke("projects:list");
if (res.ok) console.log(res.data);
else console.error(res.code); // 'UNAUTHORIZED', 'SERVER', …

Wiring the transport module

ElectronIpcGatewayModule wires the three ports and produces the gateway. Build it once per app; it defaults to ZodValidator. Then bind the feature helpers:

// electron-ipc-module.ts
import {
  gatewayFeatureFactory,
  gatewayModuleDecorator,
} from "@spinejs/gateway-core";
import { ElectronIpcGateway } from "@spinejs/electron-ipc-gateway";
import { ElectronIpcGatewayModule } from "./electron-ipc-gateway.module";

export const ipcFeature = gatewayFeatureFactory(
  ElectronIpcGateway,
  ElectronIpcGatewayModule
);
export const IpcModule = gatewayModuleDecorator(
  ElectronIpcGateway,
  ElectronIpcGatewayModule
);

Implementing the ports

// ContextFactory — enrich the context
export class SessionContextFactory
  implements ContextFactory<ElectronIpcRaw, ElectronIpcContext>
{
  constructor(private readonly sessionStore: SessionStore) {}
  create(raw: ElectronIpcRaw): ElectronIpcContext {
    return { event: raw.event, session: this.sessionStore.current() };
  }
}
// ErrorMapper — no raw message ever reaches the renderer
import {
  ErrorMapper,
  UnauthorizedError,
  ValidationError,
} from "@spinejs/gateway-core";

type ErrorCode = "UNAUTHORIZED" | "INVALID_INPUT" | "NOT_FOUND" | "SERVER";

export class AppErrorMapper implements ErrorMapper<ErrorCode> {
  toCode(err: unknown): ErrorCode {
    if (err instanceof UnauthorizedError) return "UNAUTHORIZED";
    if (err instanceof ValidationError) return "INVALID_INPUT";
    if (err instanceof NotFoundError) return "NOT_FOUND";
    return "SERVER";
  }
}

Reference

  • Exports: ElectronIpcGateway, ElectronIpcGatewayModule, the route helper handle (and the deprecated ipcRoutes factory), ipcFeature, IpcModule, IpcLoggingInterceptor, IpcLogRedactor, ZodValidator, DefaultErrorMapper, and the ElectronIpcBaseContext / ElectronIpcRaw / IpcContextRegistry / DefaultCtx types.
  • Log redaction: new IpcLoggingInterceptor(logger, redact) — the optional IpcLogRedactor (channel, input) => unknown masks what gets logged (per-channel), never the input passed to the handler.
  • Raw input: ipcRenderer.invoke(channel, arg)arg as rawInput; multiple args → [a, b]. Prefer a single object argument per call.

Full docs

apps/docs-site/docs/transports/electron-ipc