ServerSchema
Authoring Schemas
How to create and organize Valibot schemas for CRM data models.
Schema Structure
Schemas are organized by model:
// packages/crm/schema/src/contact.ts
import { v } from "valibot";
export const ContactSchema = v.object({
id: v.string(),
name: v.string(),
email: v.string(),
phone: v.optional(v.string()),
orgId: v.string(),
createdAt: v.date(),
updatedAt: v.date(),
});
export const ContactCreateSchema = v.object({
name: v.pipe(v.string(), v.minLength(1)),
email: v.pipe(v.string(), v.email()),
phone: v.optional(v.string()),
});
export const ContactUpdateSchema = v.partial(ContactCreateSchema);
export const ContactFindManySchema = v.object({
where: v.optional(v.record(v.string(), v.unknown())),
orderBy: v.optional(v.record(v.string(), v.string())),
limit: v.optional(v.pipe(v.number(), v.integer(), v.min(1), v.max(100))),
cursor: v.optional(v.string()),
});Schema Exports
Export schemas from an index file:
// packages/crm/schema/src/index.ts
export * from "./contact";
export * from "./organization";
export * from "./entity";Using with Hono
import { zValidator } from "@hono/zod-validator";
import { ContactCreateSchema } from "@repo/crm-schema";
app.post("/contacts", zValidator("json", ContactCreateSchema), async (c) => {
const input = c.req.valid("json");
// input is fully typed
});Best Practices
- Separate create/update schemas: Use
v.partial()for updates - Use pipes: Add validation like
v.minLength(),v.email() - Include orgId: Always include organization context
- Export for RPC: Schemas enable typed RPC client