The schema builder is the entry point for everything in Drizzle Castor. You callDocumentation 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.
createSchemaBuilder once, chain configuration methods to register tables, profiles, policies, middleware, and logging, then call .build() to produce a CastorInstance — the object that exposes repoFactory and subscribeToTelemetry. Because each method returns a new or mutated builder, the entire configuration reads as a single fluent expression.
createSchemaBuilder
createSchemaBuilder accepts three parameters and returns a SchemaBuilder instance.
A Drizzle ORM database instance. Supported drivers:
BunSQLiteDatabase, BetterSQLite3Database, LibSQLDatabase, PostgresJsDatabase, NodePgDatabase, MySql2Database, and AnyD1Database.An array of Drizzle table objects passed
as const. These are the tables Castor will manage. Any table referenced in relations or repoFactory calls must appear here.Controls access-control behaviour for tables that have no policy registered. See the section below for details.
Strict vs lenient mode
- lenient (default)
- strict
When
mode is "lenient", any table that has no policy defined allows all actions for all profiles. This is safe for local development and internal tools, but you should switch to "strict" before exposing endpoints to untrusted callers.Builder methods
Every method below is available on theSchemaBuilder instance returned by createSchemaBuilder. Methods that require type-level changes (.profiles(), .table()) return a new builder carrying updated generics; all other methods mutate and return this.
.profiles(profiles)
Registers the valid profile strings that callers may pass to repository methods. TypeScript uses this tuple to narrow the profile parameter across the entire instance.
Always declare profiles before calling
.policies() so that TypeScript can enforce that policy keys match a declared profile name..withLogger(config)
Configures the internal Pino-based logger. Accepts a LoggerConfig object with a level and an optional Quarkus-style format string.
Minimum log level to emit.
Format string. Supports
%d{HH:mm:ss} (datetime), %p (level), %c (category), %t (traceId), %s (message), and %{key.path} (ExecutionContext injection)..table(tableName, config)
Registers relation and soft-delete metadata for a named table. This is the primary way to teach Castor about your data model without touching the physical Drizzle schema.
Each call returns a new SchemaBuilder with the table’s config merged into the type-level metadata map, so TypeScript can validate relation paths used in queries.
joinTable shape.
.policies(tableName, policy) and .policies(globalPolicy)
Registers an access-control policy. Two overloads are available.
- Table-specific policy
- Global fallback policy
Pass a table name and a policy map where each key is a profile name. Values can be static config objects or async functions.
.use(middleware, config?)
Registers a Koa-style middleware that wraps every repository action. Middlewares execute in registration order before the RBAC layer.
An async function
(ctx, next) => Promise<any>. Call next() to pass control downstream.Restrict this middleware to specific tables. If omitted, it applies to all tables.
Restrict this middleware to specific actions (
"create", "read", "update", "softDelete", "restore", "hardDelete")..on(type, handler) and .off(type, handler)
Subscribe or unsubscribe from telemetry events emitted via the internal mitt event bus. Events are emitted asynchronously and never block query execution.
Available event types: "execution", "security", "error", "soft-deleted", "restored", "hard-deleted".
.build()
Finalises configuration and returns a CastorInstance. Call this exactly once after all builder methods have been chained.
The original Drizzle database instance.
The table array passed to
createSchemaBuilder.The accumulated table configs registered via
.table() calls.Factory function that creates a fully typed repository for a named table. See Working with Repositories.
Programmatic alternative to
.on(). Returns an unsubscribe function.Full example
The following example chains all builder methods in the order recommended for production use.Related pages
Working with Repositories
Explore every repository method, factory helpers, and how TypeScript infers return types from your projection.
Access control policies
Deep-dive into action-level and field-level RBAC configuration.
Middleware pipeline
Learn how the Koa-style middleware stack wraps every database action.
API: createSchemaBuilder
Full API reference for the builder factory function and all its parameters.