typesafe-rpc

Type-safe RPC library for Node/TS with end-to-end types. Defines schema (entity/operation/handler), createRpcHandler (server), createRpcClient (client), Route and middlewares. Use when editing typesafe-rpc, adding RPC operations, wiring server or client, or implementing handlers and middlewares in this repo.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "typesafe-rpc" with this command: npx skills add bacali95/typesafe-rpc/bacali95-typesafe-rpc-typesafe-rpc

typesafe-rpc

Overview

This repo is a type-safe RPC library. The server accepts POST bodies { entity, operation, params } and runs the matching handler. The client is a typed proxy: client.entity.operation(params, signal?, context?). Types are shared so client calls are inferred from the schema.

Core types (shared)

  • BaseContext: { request: Request | Express.Request }
  • Args<Params, Context>: { params: Params; context: Context }
  • Handler<Params, Context, Result>: (args: Args<Params, Context>) => Promise<Result>
  • RpcSchema: { [entity: string]: { [operation: string]: Handler<any, any, any> } }

Handlers receive only params and context (no ExtraParams). Extend BaseContext for app-specific context.

Schema and handlers

Schema is a nested object: entity → operation → handler. Use as const so the client gets literal types.

import type { BaseContext, Handler } from 'typesafe-rpc';

type Ctx = BaseContext & { userId?: string };

const getItem: Handler<{ id: string }, Ctx, { name: string }> = async ({ params, context }) => {
  return { name: 'Item ' + params.id };
};

export const apiSchema = {
  items: {
    getById: getItem,
  },
} as const;

Server: createRpcHandler

From typesafe-rpc/server:

import { createRpcHandler } from 'typesafe-rpc/server';

const result = await createRpcHandler({
  context: { request },           // must include request
  operations: apiSchema,
  errorHandler: (error) => new Response(JSON.stringify({ error: '...' }), { status: 500 }),
  hooks: {
    preCall: (args) => {},
    postCall: (args, performance) => {},
    error: (args, performance, error) => {},
  },
});
  • Expects context.request.method === 'POST'; body must be JSON { entity, operation, params }.
  • Hook args: { entity, operation, params, context }.
  • Returns the handler result directly; throws Response on error.
  • If no errorHandler, throws a generic 500 Response.

Client: createRpcClient

From typesafe-rpc/client:

import { createRpcClient } from 'typesafe-rpc/client';
import type { apiSchema } from './api-schema';

// Static headers
const client = createRpcClient<typeof apiSchema>('/api/rpc', { Authorization: 'Bearer ...' });

// Dynamic headers via function (receives context passed to call)
const client = createRpcClient<typeof apiSchema, MyContext>('/api/rpc', (ctx) => ({
  Authorization: ctx.token,
}));

const result = await client.items.getById({ id: '1' });
const withAbort = await client.items.getById({ id: '1' }, signal);
const withContext = await client.items.getById({ id: '1' }, undefined, context);

Client signature: client.entity.operation(params, signal?, context?). Calls POST endpoint?entity::operation with body { entity, operation, params }. Use the same schema type (typeof apiSchema) for full inference.

Route and middlewares

From typesafe-rpc/server: Route, Middleware, orMiddleware.

  • Middleware<Params, Context>: (args: Args<Params, Context>) => Promise<void> (throw to abort).
  • Route: chain .middleware(...fns) then .handle(handler).
    • Multiple .middleware(a, b, c): OR — first success wins (via orMiddleware).
    • Chained .middleware(a).middleware(b): AND — all run in order.
  • orMiddleware(...middlewares): runs middlewares in order; returns on first that doesn't throw; if all throw, rethrows the first error.
  • OverridableHandler: the handler returned by .handle() has an overrideMiddlewares(...middlewares) method to replace middlewares (useful for testing).
import { Route } from 'typesafe-rpc/server';

const handler = new Route<{ id: string }, BaseContext>()
  .middleware(authOrAnonymous)
  .middleware(requireReadPermission)
  .handle(async ({ params, context }) => ({ name: '...' }));

// For testing: bypass middlewares
handler.overrideMiddlewares(mockAuth);

Use the resulting handler as the function stored in the schema (e.g. getById: handler).

Request/response and errors

  • Server reads body via request.json() (Fetch) or request.body (Express).
  • Client sends JSON and parses response with response.json(). Non-ok responses throw FetchError.

FetchError

From typesafe-rpc/client:

import { FetchError } from 'typesafe-rpc/client';

class FetchError extends Error {
  readonly key: string;     // error key from response JSON, or 'internalError'
  readonly status: number;  // HTTP status code
  readonly data?: any;      // optional data from response JSON
}

The client parses error responses as JSON { key, message, data }. If parsing fails, key defaults to 'internalError' and message is the raw response text.

Conventions in this repo

  • Schema and shared types live in shared/; server in server/, client in client/.
  • Implementations follow the types in libs/typesafe-rpc/src/shared/rpc-types.ts. Prefer those over README if they differ (e.g. no ExtraParams in Handler).
  • For full API and examples, see the project README.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

tw-react-components

No summary provided by upstream source.

Repository SourceNeeds Review
Web3

china-sportswear-outdoor-sourcing

Comprehensive sportswear and outdoor equipment sourcing guide for international buyers – provides detailed information about China's athletic apparel, footwear, outdoor gear, and accessories manufacturing clusters, supply chain structure, regional specializations, and industry trends (2026 updated).

Archived SourceRecently Updated
Web3

china-lighting-sourcing

Comprehensive lighting industry sourcing guide for international buyers – provides detailed information about China's LED, smart, outdoor, automotive, and specialty lighting manufacturing clusters, supply chain structure, regional specializations, and industry trends (2026 updated).

Archived SourceRecently Updated
Web3

china-furniture-sourcing

Comprehensive furniture industry sourcing guide for international buyers – provides detailed information about China's residential, office, hotel, outdoor, and custom furniture manufacturing clusters, supply chain structure, regional specializations, and industry trends (2026 updated).

Archived SourceRecently Updated