Skip to content

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.

  1. Define your Prisma models in prisma/schema.prisma

  2. Push the schema to your database

    Terminal window
    pnpm db:push
  3. Run sync

    Terminal window
    velox sync
  4. Follow the interactive prompts for each model

The command walks you through each model and generates type-safe schemas, procedures, and router registrations.

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 router

For each model, the command asks:

  1. Action — Generate, regenerate (if files exist), or skip
  2. Output strategy.output() with plain Zod schema or .output() with tagged resource view (visibility tiers)
  3. CRUD operations — Which endpoints to generate (get, list, create, update, delete)
  4. Schema relations — Which relations to include in the Zod schema
  5. Query includes — Which relations to fetch via Prisma include
  6. Field visibility (resource strategy only) — Per-field access level (public, authenticated, admin)

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 visibility
export 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 projection
getPost: 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);
}),

For each model, sync creates:

src/
├── schemas/
│ └── post.schema.ts # Zod schemas (base, Create, Update, List)
└── procedures/
└── posts.ts # CRUD procedures with Prisma queries

And auto-registers the procedures in your router (src/index.ts).

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 page and perPage defaults
  • WithRelationsSchema (output strategy with relations) — Extends base with relation shapes

The generated procedure file includes whichever CRUD operations you selected:

  • getfindUniqueOrThrow by ID, with relation includes
  • list — Paginated findMany + count, ordered by createdAt when available
  • create — Auto-injects ctx.user.id for user foreign key fields
  • update — Merges ID input with update schema
  • delete — Supports compound unique keys for join tables

The sync command applies intelligent defaults based on your schema:

  • Join tables default to only create and delete operations (no get/list/update)
  • Models with sensitive fields (password, token, secret) default to the resource strategy
  • belongsTo relations are pre-selected for schema inclusion
  • User foreign key fields (userId, authorId referencing User) are auto-injected from context
OptionShortDescription
--dry-run-dPreview the generation plan without writing files
--force-fSkip all prompts, generate all models with defaults
--skip-registrationSkip auto-registering procedures in the router

Preview what would be generated without writing any files:

Terminal window
velox sync --dry-run

Skip all prompts and generate everything with defaults (output strategy, all CRUD operations):

Terminal window
velox sync --force
Terminal window
# After defining models in prisma/schema.prisma
pnpm db:push
velox sync

Walk through each model interactively, choosing output strategies and CRUD operations.

Terminal window
# After adding fields or relations to a Prisma model
pnpm db:push
velox sync

The command detects existing files and offers to regenerate them while preserving your choices.

Terminal window
# Generate all models with defaults, no prompts
velox sync --force --skip-registration