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

@m4ike1/ion-client

v0.1.1

Published

Transport-neutral client for remote ion sessions over framed CBOR bytes

Readme

@m4ike1/ion-client

Transport-neutral client for remote ion sessions over framed CBOR bytes. Bring your own ordered byte transport (WebSocket, Unix socket, or equivalent); the client handles the hello handshake, serverId verification, request correlation, service subscriptions, and attachment routing.

import { Client, type ByteTransportFactory } from "@m4ike1/ion-client";

const transportFactory: ByteTransportFactory = (handlers) => {
  // Open a fresh authenticated connection; call
  // handlers.onData(chunk) / onClose() / onError(err) as events arrive.
  return { send: async (chunk) => {}, close: () => {} };
};

const client = await Client.connect({
  serverId: "01234567-89ab-4def-8123-456789abcdef",
  transportFactory,
});

const result = await client.request(
  { serverId: client.hello!.serverId },
  { serviceId: "example.service", member: "read", args: [] },
);

What it does

  • Verifies the physical endpoint reports the expected logical serverId during the hello handshake. A mismatch fails the connection.
  • Sends low-level Chord service calls via request() and subscribeService() against an explicit routed target: { serverId } for server-wide calls, or the full live { serverId, sessionId, attachmentId } for session calls.
  • Tracks the live attachment from out-of-band server messages (client.attachment, onAttachmentChange()). The server-generated attachmentId rejects delayed frames after switching or reattaching.
  • Adapts to typed Chord service bindings via createClientServiceTransport(client, getTarget). The client itself never constructs typed proxies or interprets application contracts.

Lifecycle

  • Client.connect(options) constructs and connects; new Client(options) + connect() defers the handshake. connect() rejects while already connecting/connected.
  • On disconnect or dispose(), pending requests reject locally; accepted work may still complete remotely. The client clears the live attachment, drops service listeners, and never reconnects or replays automatically. Call reconnect(), re-attach through the application's management service, and repeat only operations known to be safe.
  • disconnect() and dispose() are idempotent. dispose() also supports await using.
  • connectionState is disconnected | connecting | connected; observe with onConnectionStateChange(). Listener errors go to onListenerError and never corrupt client state.

Errors

  • ServerError (with .code) for server-rejected calls, including handshake hello_error rejections.
  • DisconnectedError when sending while not connected, or when the transport closes/fails.
  • ClientDisposedError after dispose().
  • Abort a single call with an AbortSignal; the client sends a cancel frame when the request was already sent.

Limits

  • ClientOptions.maxFrameLength bounds inbound protocol payloads.
  • Unix transports add maxPendingBytes for queued output. Configure matching limits on both peers.

Unix-domain sockets

Node.js and Bun consumers can use the separate entrypoint:

import { Client } from "@m4ike1/ion-client";
import { createUnixTransportFactory, discoverUnixServers } from "@m4ike1/ion-client/unix";

const client = new Client({
  serverId: "01234567-89ab-4def-8123-456789abcdef",
  transportFactory: createUnixTransportFactory({ path: "/tmp/ion.sock" }),
});
await client.connect();

const routes = await discoverUnixServers({ directory: "/run/user/1000/ion" });
// [{ serverId: "...", path: "/run/user/1000/ion/<serverId>.sock" }]

Discovery probes <serverId>.sock files (at most 16 concurrently, 1s default per-probe timeout via timeoutMs), ignores malformed/non-socket/stale/mismatched endpoints, and throws on unexpected filesystem or socket errors. Not supported on Windows.

Further reading

  • docs/reference.md — full API reference for Client, transports, subscriptions, and errors.
  • docs/how-to.md — recipes: custom transports, Unix setup and discovery, subscriptions, cancellation, reconnect.
  • docs/concepts.md — why transport neutrality, serverId verification, and attachment routing work the way they do.