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

@inkly/client

v0.0.0

Published

The isomorphic inkly client: typed RPC, push events, resumable streams, auto-reconnect.

Readme

@inkly/client

The isomorphic typed client for inklyactions, events, and server-push streams from one shared contract, with automatic reconnect and resumable replay in browsers, Node 22+, Bun, and Deno.

This package is client-only. It expects an inkly server built with @inkly/core and a runtime adapter such as @inkly/node.

Why it exists

@inkly/client gives application code a small, typed surface instead of raw WebSocket frame handling: client.actions.* returns promises, client.on() subscribes to validated events, and client.streams.*() returns cancellable async iterables. Reconnect and resume are transparent, so short network drops do not force every UI or worker to rebuild its own retry, replay, and duplicate-suppression logic.

Install

pnpm add @inkly/client @inkly/protocol zod

Quickstart

import { createClient } from "@inkly/client";
import { contract } from "@inkly/protocol";
import { z } from "zod";

const chat = contract({
  actions: {
    sendMessage: {
      input: z.object({ room: z.string(), text: z.string() }),
      output: z.object({ id: z.string(), at: z.number() }),
    },
  },
  events: {
    message: z.object({ id: z.string(), room: z.string(), text: z.string(), at: z.number() }),
  },
  streams: {
    history: { input: z.object({ room: z.string() }), yields: z.object({ id: z.string(), text: z.string() }) },
  },
});

const client = createClient(chat, {
  url: "ws://localhost:3000/ws",
  params: () => ({ token: localStorage.getItem("token") ?? "" }),
});

client.on("message", (message) => console.log(message.text));

await client.connect();
await client.actions.sendMessage({ room: "general", text: "hello" });

for await (const message of client.streams.history({ room: "general" })) {
  console.log(message.text);
}

API reference

| API | Purpose | | --- | --- | | createClient(contract, options) | Creates a typed client for one contract. | | options.url | ws:// or wss:// endpoint. | | options.params | Static object or function resolved fresh for every connect/reconnect. | | options.reconnect | Backoff options { minDelay?, maxDelay?, jitter? }, or false to disable reconnect. | | options.resume | Enables session resume by default; set false to reconnect with fresh sessions. | | options.timeout | Per-action timeout in milliseconds. | | options.heartbeat | Client ping/pong configuration, or false. | | options.WebSocket | Injectable WebSocket constructor; defaults to globalThis.WebSocket. | | options.codec | Wire codec; must match the server. | | options.autoConnect | Connects immediately by default; set false for manual connect(). | | client.actions.<name>(input) | Calls a typed server action and returns Promise<output>. | | client.streams.<name>(input) | Starts a typed stream; the handle is AsyncIterable and has .cancel(). | | client.on(event, cb) | Subscribes to a typed event and returns an unsubscribe function. | | client.status | Current status: connecting, open, reconnecting, or closed. | | client.onStatus(cb) | Subscribes to status changes and returns an unsubscribe function. | | client.connect() | Resolves on ready; rejects with the server's typed auth error. | | client.auth(token?, params?) | Refreshes auth on the live connection (no reconnect); resolves when the server accepts, rejects if it refuses (the prior auth stays valid). Requires the server to set reauthorize. | | client.close() | Intentionally closes and stops reconnecting. |

Docs

Examples

License

Dazza Public License 1.0 (LicenseRef-Dazza-1.0).