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

orbit-rpc

v1.2.0

Published

RPC layer for Orbit — auto-converts server.ts functions to Hono routes

Readme

Orbit RPC

Auto-converts server.ts functions to type-safe RPC endpoints — designed for the AI era.

Part of the Orbit frontend toolkit — designed so that AI-generated code and human-written code always look the same.

Features

  • Zero boilerplate — Export a function from server.ts, it becomes an RPC endpoint
  • Automatic Zod validation — Link a Zod schema in schema.ts, get runtime validation for free
  • Vite plugin — Dev middleware with HMR, production build generates a Hono app
  • Cloudflare Workers readyimport app from "virtual:orbit-rpc/server" and deploy
  • Type-safe end-to-end — TypeScript types flow from schema to server to client

Quick Start

pnpm add orbit-rpc hono
// vite.config.ts
import { orbitRpc } from "orbit-rpc";

export default defineConfig({
  plugins: [orbitRpc()],
});

Write a server function:

// src/routes/tasks/server.ts
export async function getTasks(signal?: AbortSignal) {
  const res = await fetch("https://api.example.com/tasks", { signal });
  return res.json();
}

Import it from the client — the plugin replaces the import with an HTTP fetch stub:

// src/routes/tasks/hooks.ts
import { getTasks } from "./server";

export function useTasks() {
  return useQuery(["tasks"], getTasks);
}

That's it. getTasks() on the client calls POST /rpc/tasks/getTasks under the hood.

How It Works

The Vite plugin does two things:

  1. Client-side transformserver.ts imports are replaced with fetch() stubs that call POST /rpc/{route}/{function}
  2. Server-side handler — Dev middleware (or production Hono app) receives those requests and executes the real function
Client                          Server
─────                           ──────
import { getTasks }             server.ts (real function)
  from "./server"                     ↑
        │                             │
        ↓                             │
  fetch("/rpc/tasks/getTasks")  ──→  getTasks()

Automatic Zod Validation

When schema.ts sits next to server.ts, the plugin automatically validates function arguments using the linked Zod schema.

// src/routes/bookmarks/schema.ts
import { z } from "zod";

export const bookmarkInputSchema = z.object({
  url: z.string().url(),
  title: z.string().min(1),
  description: z.string(),
  tags: z.array(z.string()),
});

export type BookmarkInput = z.infer<typeof bookmarkInputSchema>;
// src/routes/bookmarks/server.ts
import type { BookmarkInput } from "./schema";

export async function createBookmark(data: BookmarkInput) {
  // `data` is already validated by Zod — invalid requests get a 400 response
  return db.insert(bookmarks).values(data);
}

The plugin detects export type X = z.infer<typeof ySchema> patterns in schema.ts and binds ySchema to the matching parameter type in server.ts. No manual wiring needed.

Validation errors

Invalid requests receive a 400 response with structured error messages:

{
  "error": "Validation error on \"data\": url: Invalid url, title: String must contain at least 1 character(s)"
}

Production Build

Import the virtual module to get a Hono app with all RPC routes pre-registered:

// worker.ts (Cloudflare Workers entry)
import app from "virtual:orbit-rpc/server";

export default app;

The generated Hono app includes:

  • All server.ts functions as POST routes
  • Zod validation (using safeParse) for validated parameters
  • JSON parsing with error handling
  • 1MB payload size limit

Plugin Options

orbitRpc({
  routesDir: "src/routes", // Where to scan for server.ts files (default: "src/routes")
  rpcBase: "/rpc",         // URL prefix for RPC endpoints (default: "/rpc")
});

Type Flow

schema.ts is the single source of truth. One change propagates through all layers:

schema.ts                          Define Zod schema + export type
    │
    ├─→ server.ts                  Function params use the type → auto-validated
    ├─→ hooks.ts (useForm)         Form binds to the same schema → client validation
    └─→ hooks.ts (useQuery)        Return type inferred from server function

Conventions

  • server.ts — Export async function or export const fn = async () => {}
  • schema.ts — Export Zod schemas and z.infer types for automatic validation
  • AbortSignal parameters are automatically detected and passed through from fetch
  • Dynamic route segments ([id]) in directory names become part of the URL prefix

License

MIT