Schema Sync
The velox sync command reads your entire Prisma schema and interactively generates complete Zod validation schemas and CRUD procedure files for every model — in one shot.
Quick Start
Section titled “Quick Start”-
Define your Prisma models in
prisma/schema.prisma -
Push the schema to your database
Terminal window pnpm db:push -
Run sync
Terminal window velox sync -
Follow the interactive prompts for each model
The command walks you through each model and generates type-safe schemas, procedures, and router registrations.
How It Works
Section titled “How It Works”The sync pipeline has five stages:
Prisma Schema │ 1. Analyze ─── Parse models, fields, relations, constraints │ 2. Detect ──── Scan for existing schema/procedure files │ 3. Prompt ──── Interactive choices per model │ 4. Plan ────── Build file generation plan │ 5. Generate ── Write files + register in routerInteractive Prompts
Section titled “Interactive Prompts”For each model, the command asks:
- Action — Generate, regenerate (if files exist), or skip
- Output strategy —
.output()with plain Zod schema or.output()with tagged resource view (visibility tiers) - CRUD operations — Which endpoints to generate (get, list, create, update, delete)
- Schema relations — Which relations to include in the Zod schema
- Query includes — Which relations to fetch via Prisma
include - Field visibility (resource strategy only) — Per-field access level (public, authenticated, admin)
Output Strategies
Section titled “Output Strategies”Plain output generates procedures with .output(Schema):
getPost: procedure() .input(z.object({ id: z.string().uuid() })) .output(PostSchema) .query(async ({ input, ctx }) => { return ctx.db.post.findUniqueOrThrow({ where: { id: input.id }, }); }),Resource generates procedures with resource() projection and a resourceSchema() with visibility tiers:
// Generated schema with per-field visibilityexport const PostSchema = resourceSchema() .public('id', z.string().uuid()) .public('title', z.string()) .authenticated('authorId', z.string().uuid()) .admin('internalNotes', z.string().nullable()) .build();
// Generated procedure using resource projectiongetPost: procedure() .input(z.object({ id: z.string().uuid() })) .query(async ({ input, ctx }) => { const post = await ctx.db.post.findUniqueOrThrow({ where: { id: input.id }, }); return resource(post, PostSchema.public); }),Generated Files
Section titled “Generated Files”For each model, sync creates:
src/├── schemas/│ └── post.schema.ts # Zod schemas (base, Create, Update, List)└── procedures/ └── posts.ts # CRUD procedures with Prisma queriesAnd auto-registers the procedures in your router (src/index.ts).
Schema File
Section titled “Schema File”The generated schema file includes:
- Base schema — All non-sensitive fields with correct Zod types
- CreateSchema — Input fields for creation (excludes auto-managed, sensitive, and user FK fields)
- UpdateSchema — Same fields as Create, all optional
- ListSchema — Pagination with
pageandperPagedefaults - WithRelationsSchema (output strategy with relations) — Extends base with relation shapes
Procedure File
Section titled “Procedure File”The generated procedure file includes whichever CRUD operations you selected:
- get —
findUniqueOrThrowby ID, with relation includes - list — Paginated
findMany+count, ordered bycreatedAtwhen available - create — Auto-injects
ctx.user.idfor user foreign key fields - update — Merges ID input with update schema
- delete — Supports compound unique keys for join tables
Smart Defaults
Section titled “Smart Defaults”The sync command applies intelligent defaults based on your schema:
- Join tables default to only
createanddeleteoperations (no get/list/update) - Models with sensitive fields (password, token, secret) default to the resource strategy
belongsTorelations are pre-selected for schema inclusion- User foreign key fields (
userId,authorIdreferencing User) are auto-injected from context
CLI Options
Section titled “CLI Options”| Option | Short | Description |
|---|---|---|
--dry-run | -d | Preview the generation plan without writing files |
--force | -f | Skip all prompts, generate all models with defaults |
--skip-registration | Skip auto-registering procedures in the router |
Dry Run
Section titled “Dry Run”Preview what would be generated without writing any files:
velox sync --dry-runForce Mode
Section titled “Force Mode”Skip all prompts and generate everything with defaults (output strategy, all CRUD operations):
velox sync --forceExamples
Section titled “Examples”Syncing a Fresh Project
Section titled “Syncing a Fresh Project”# After defining models in prisma/schema.prismapnpm db:pushvelox syncWalk through each model interactively, choosing output strategies and CRUD operations.
Regenerating After Schema Changes
Section titled “Regenerating After Schema Changes”# After adding fields or relations to a Prisma modelpnpm db:pushvelox syncThe command detects existing files and offers to regenerate them while preserving your choices.
CI/Scripting
Section titled “CI/Scripting”# Generate all models with defaults, no promptsvelox sync --force --skip-registrationRelated Content
Section titled “Related Content”- Code Generators - Single-model generators (
velox make) - Procedures - Procedure API reference
- Resource API - Visibility-based field projection
- Nested Relations - Auto-detected relation projection