effect-orpc keeps oRPC’s input and output schema model. Use .input(...) and .output(...) before .effect(...).
import * as z from "zod";
const GetUserInput = z.object({
id: z.string().min(1),
});
const User = z.object({
id: z.string(),
name: z.string(),
});
export const getUser = effectProcedure
.input(GetUserInput)
.output(User)
.effect(function* ({ input }) {
return yield* UsersRepo.findById(input.id);
});
The handler sees the parsed schema output as input.
const SearchInput = z.object({
query: z.string().trim(),
limit: z.number().int().positive().default(20),
});
const search = effectProcedure.input(SearchInput).effect(function* ({ input }) {
// input.limit is a number, including the default when omitted.
return yield* UsersRepo.search(input.query, input.limit);
});
Output validation
Use .output(...) for public response contracts.
const PublicUser = z.object({
id: z.string(),
name: z.string(),
});
const me = effectProcedure.output(PublicUser).effect(function* () {
const user = yield* CurrentUser;
return user;
});
Output schemas validate what leaves the procedure. Keep internal fields out of
public output schemas unless they are intentionally part of the API.
Next step
Provide services with Service injection.