Procedures
Creating oRPC procedures
Procedure Types
Import from @/rpc/procedures/rpc:
import {
authProcedure,
createRPCRouter,
publicProcedure,
roleProcedure,
} from "@/rpc/procedures/rpc";| Procedure | Description |
|---|---|
publicProcedure | No authentication required |
authProcedure | Requires an authenticated user |
roleProcedure(role) | Requires one or more roles |
Basic Patterns
Public procedure
export const healthRouter = createRPCRouter({
ping: publicProcedure
.meta({ rateLimit: false })
.query(async () => ({ success: true, payload: { status: "ok" } })),
});Authenticated procedure
import { type ActionResponse } from "@/lib/utils/schema-utils";
export const todosRouter = createRPCRouter({
list: authProcedure
.meta({ rateLimit: "QUERY" })
.query(async ({ ctx }) => {
const items = await ctx.db.todos.getByOrganizationId("org-id");
return {
success: true,
payload: items,
} satisfies ActionResponse;
}),
});Role-based procedure
import { UserRole } from "@/db/enums";
export const adminRouter = createRPCRouter({
stats: roleProcedure(UserRole.ADMIN)
.meta({ rateLimit: "ADMIN" })
.query(async () => ({ success: true })),
});Rate Limits
Rate limits are configured via .meta({ rateLimit: ... }).
Supported keys in this project include:
"QUERY""MUTATION""AUTH""ADMIN"false(disable)
OpenAPI Exposure
Expose a procedure through REST using .route(...) and explicit schemas:
import { actionResponseSchema } from "@/lib/utils/schema-utils";
import { z } from "zod";
list: authProcedure
.meta({ rateLimit: "QUERY", acceptApiKey: true })
.route({
method: "GET",
path: "/todos/list",
tags: ["todos"],
summary: "List todos",
})
.input(z.object({ organizationId: z.string().uuid() }))
.output(actionResponseSchema(z.array(z.object({ id: z.string() }))))
.query(async ({ ctx, input }) => {
const items = await ctx.db.todos.getByOrganizationId(input.organizationId);
return { success: true, payload: items };
});Error Handling
Use ActionResponse for expected failures and ORPCError for hard failures:
import { ORPCError } from "@/rpc/procedures/rpc";
if (!canAccess) {
throw new ORPCError("FORBIDDEN", { message: "Not allowed" });
}See Error Handling for the full project pattern.