@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
| Export | Description |
|---|---|
o | Base oRPC builder bound to the Context type |
publicProcedure | Alias for o -- accessible without authentication |
protectedProcedure | publicProcedure 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:
| Router | Description |
|---|---|
profile | User profile read and update |
documents | Document CRUD operations |
conversations | AI conversation management |
usage | Usage 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:
| Type | Description |
|---|---|
AppRouter | Full router type inferred from appRouter |
AppRouterClient | oRPC RouterClient type for calling procedures from the client |
Context | The 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 } }