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/core

v0.0.0

Published

The inkly server core: typed app, router, rooms/presence, RPC, and resumable streams. Runtime-agnostic.

Readme

@inkly/core

The runtime-agnostic server engine for inkly — typed contracts, actions, events, rooms, lifecycle hooks, and resumable streams without importing any Node, Bun, Deno, or Cloudflare runtime APIs.

This package is the server app layer. Pair it with a runtime adapter such as @inkly/node; adapters consume app.handlers while your app code stays portable.

Why it exists

@inkly/core turns one shared contract() into a server that validates every input/output, injects an authorized peer.context, routes typed actions and streams, and buffers recent events/chunks for reconnect resume. Keeping the engine runtime-free means the same app can run behind the Node reference adapter today and another adapter tomorrow with no handler rewrites.

Install

pnpm add @inkly/core zod

Quickstart

import { inkly, contract } from "@inkly/core";
import { z } from "zod";

const chat = contract({
  actions: {
    joinRoom: { input: z.object({ room: z.string() }), output: z.object({ ok: z.boolean() }) },
    sendMessage: {
      input: z.object({ room: z.string(), text: z.string().min(1) }),
      output: z.object({ id: z.string(), at: z.number() }),
    },
  },
  events: {
    message: z.object({ id: z.string(), room: z.string(), user: z.string(), text: z.string(), at: z.number() }),
  },
  streams: {},
});

export const app = inkly(chat, {
  async authorize(_request, params) {
    const token = (params as { token?: string } | undefined)?.token;
    if (token !== "demo-token") throw new inkly.Unauthorized("bad token");
    return { user: "daryl" };
  },
});

app.defineAction("joinRoom", (peer, input) => {
  peer.join(input.room);
  return { ok: true };
});

app.defineAction("sendMessage", (peer, input) => {
  const message = { id: crypto.randomUUID(), room: input.room, user: peer.context.user, text: input.text, at: Date.now() };
  app.to(input.room).emit("message", message);
  return { id: message.id, at: message.at };
});

API reference

| API | Purpose | | --- | --- | | contract({ actions, events, streams }) | Declares Standard Schema validators for typed RPC, server events, and streams. | | inkly(contract, options) | Creates an app. options include authorize, codec, heartbeat, resume, resumeWindow, backpressure, exposeErrors, and the security options allowedOrigins, reauthorize, and authExpiry. | | inkly.Unauthorized / Forbidden / NotFound / TimeoutError | Static error classes for rejecting auth, hooks, actions, and streams with typed wire errors. | | app.defineAction(name, (peer, input) => output) | Registers a request/response handler. The peer argument is first. | | app.defineStream(name, async function* (peer, input) { ... }, options?) | Registers a server-push stream; pass { resumable, window } to keep chunks replayable. | | app.on("open" | "close" | "error", listener) | Observes connection lifecycle. | | app.use(hook) | Runs per-message authorization; returning false rejects with FORBIDDEN. | | app.emit(event, payload) / app.to(room).emit(event, payload) | Broadcasts typed events to every peer or one room. | | app.room(room).members() / .size() | Inspects room presence. | | app.namespace(name) | Creates a namespaced app surface over the same engine. | | app.authorizeConnection(request, params?) | Lets adapters pre-authorize an upgrade and attach context before hello. | | app.checkOrigin(request) | Adapter-facing CSWSH guard: returns false when allowedOrigins rejects the request's Origin so adapters can answer 403 before the socket opens. | | app.handlers | Adapter-facing open / message / close / error handlers. | | app.shutdown() | Stops the app and releases sessions. | | peer.id, peer.context, peer.request, peer.remoteAddress, peer.rooms | Per-connection identity, auth context, request metadata, and room set. | | peer.send(...), peer.close(...), peer.join(...rooms), peer.leave(...rooms) | Low-level peer operations and room membership helpers. |

Docs

Examples

License

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