Raypx

@raypx/rpc

Type-safe API layer with oRPC procedures and routers.

@raypx/rpc provides the type-safe API layer built on oRPC. It defines procedures, middleware, and routers that power the /api/rpc endpoint.

Core Exports

ExportDescription
oBase oRPC builder bound to the Context type
publicProcedureAlias for o -- accessible without authentication
protectedProcedurepublicProcedure with an auth middleware that requires session.user

Context Definition

The RPC context is created per-request and contains the authenticated session:

// packages/rpc/src/context.ts
import { auth } from "@raypx/auth"

export async function createContext({ req }: { req: Request }) {
  const session = await auth.api.getSession({ headers: req.headers })
  return { session }
}

export type Context = Awaited<ReturnType<typeof createContext>>

Procedures

Public Procedure

Use publicProcedure for endpoints that do not require authentication:

import { publicProcedure } from "@raypx/rpc"

export const myRouter = {
  hello: publicProcedure.handler(() => {
    return { message: "Hello, world!" }
  }),
}

Protected Procedure

Use protectedProcedure for endpoints that require an authenticated user. The middleware throws UNAUTHORIZED if no session exists:

import { protectedProcedure } from "@raypx/rpc"

export const profileRouter = {
  getProfile: protectedProcedure.handler(({ context }) => {
    return { user: context.session.user }
  }),
}

Router Files

The app router (appRouter) is composed from individual router files:

RouterDescription
profileUser profile read and update
documentsDocument CRUD operations
conversationsAI conversation management
usageUsage tracking and plan limits

App Router Composition

// packages/rpc/src/routers/index.ts
import { profileRouter } from "./profile"
import { documentRouter } from "./document"
import { conversationRouter } from "./conversation"
import { usageRouter } from "./usage"

export const appRouter = {
  healthCheck: publicProcedure.handler(async () => { /* ... */ }),
  privateData: protectedProcedure.handler(({ context }) => { /* ... */ }),
  profile: profileRouter,
  documents: documentRouter,
  conversations: conversationRouter,
  usage: usageRouter,
}

Adding a New Router

Create a new file in packages/rpc/src/routers/, for example settings.ts.

Define the router using publicProcedure or protectedProcedure:

import { protectedProcedure } from "../index"

export const settingsRouter = {
  get: protectedProcedure.handler(({ context }) => {
    return { theme: "dark" }
  }),
}

Import and add the router to appRouter in packages/rpc/src/routers/index.ts:

import { settingsRouter } from "./settings"

export const appRouter = {
  // ...existing routers
  settings: settingsRouter,
}

Type Exports

The router types are available for client-side type safety:

TypeDescription
AppRouterFull router type inferred from appRouter
AppRouterClientoRPC RouterClient type for calling procedures from the client
ContextThe per-request context type

Health Check Endpoint

The appRouter includes a built-in healthCheck procedure that verifies database and storage connectivity:

const result = await appRouter.healthCheck()
// { status: "ok", timestamp: 1234567890, database: { status: "ok", latency: 2 }, storage: { status: "ok", latency: 1 } }

On this page