This guide walks you through every step required to go from a blank project to executing type-safe database queries with Drizzle Castor. You will install the package, write a Drizzle schema, configure the schema builder with profiles and policies, define table relations, and run your first queries — all with full TypeScript inference.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/fajarnugraha37/drizzle-castor/llms.txt
Use this file to discover all available pages before exploring further.
Install the package
Add Drizzle Castor and its required peer dependency to your project. Drizzle ORM is required because Drizzle Castor builds directly on top of it.
Set up your Drizzle schema
Create your standard Drizzle ORM schema. Drizzle Castor reads column types and references directly from this schema to provide full type inference throughout your application — you do not need to change anything here.
schema.ts
Initialize SchemaBuilder with createSchemaBuilder
Import
createSchemaBuilder and pass your Drizzle database instance together with your table definitions. The third argument sets the execution mode.db.ts
The execution mode controls how Drizzle Castor handles tables without an explicit policy:
lenient(default) — tables without a policy allow all actions.strict— every table must have an explicit policy or anAccessDeniedErroris thrown.
Configure profiles and logger
Chain
.profiles() to register the valid role names your application uses, and .withLogger() to enable the built-in hybrid logger. TypeScript uses the profile list to give you autocomplete and type-checking when you pass a profile to a repository method.db.ts
Define table relations
Use
.table() to declare relationships between your Drizzle tables. Drizzle Castor uses these declarations to build the JOIN clauses needed when you use dot-notation paths such as "posts.title" in projections or filters. You can also enable soft-delete behaviour here.db.ts
Relations are defined separately from your physical Drizzle schema. You do not need to modify your
sqliteTable (or pgTable / mysqlTable) definitions.Set up policies
Define who can do what on each table using
.policies(). Policies can be static objects for simple cases or asynchronous functions that resolve rules dynamically from the execution context.db.ts
Build and create a repository with repoFactory
Call
.build() to finalise the configuration and then use repoFactory() to create a typed repository for a specific table. The returned object provides all CRUD methods with full TypeScript inference.db.ts
Run your first createOne, searchMany, and searchPage queries
Every repository method accepts a profile string as its last argument. The RBAC engine validates the profile and applies field-level trimming before the query reaches the database.
queries.ts
Unlike raw SQL,
searchOne and searchMany automatically hydrate flat rows into clean, nested JavaScript objects that mirror your query shape. See JSON querying for the full filter operator reference.What’s next
JSON querying
Explore every filter operator, projection path, and sort key supported by the AST translator.
Access control
Deep dive into profiles, policies, and intelligent data trimming.
Relations
Learn how to define one-to-one, one-to-many, and many-to-many relationships.
Middleware pipeline
Compose custom middlewares and understand the execution context.
Telemetry
Reference for all telemetry events and their payload shapes.
Soft deletes
Configure declarative soft deletes and the restore workflow.