Drizzle Castor is designed so that TypeScript catches incorrect queries at compile time, not at runtime. The type system is built from a chain of interlocking generics: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.
InferEntity extracts your table shapes from Drizzle, FlattenPaths and ValidPath enforce which dot-notation strings are legal, FieldOperators restricts which operators are valid for each value type, and DeepPick shapes the inferred return type of each query to exactly match your projection array. This page explains how each piece works and how they compose.
Inferring entity shapes from Drizzle
The foundation of the type system is extracting the row shape from a Drizzle table definition without asking you to write a redundant TypeScript interface.InferEntity and InferModel use Drizzle’s native type inference utilities internally:
UserEntity manually.
Path validation with FlattenPaths and ValidPath
Querying by dot-notation (e.g.,"persona.skills.0") is only safe if TypeScript can verify that the path exists in the entity type. FlattenPaths generates the complete union of valid string paths by recursively traversing the inferred type up to a configurable depth (default: 5 levels):
User type with nested JSON columns, the generated union looks like:
Operator gating with FieldOperators
Not every SQL operator is meaningful for every data type.$like makes no sense on a number column. $arrayContains requires an array. FieldOperators uses conditional types to inspect the value type at the requested path and include only the operators that apply:
The conditional
[NonNullable<T>] extends [string] ? StringOps : {} pattern uses a tuple wrapper to prevent TypeScript from distributing the conditional over union types. This ensures that a string | null path still gets StringOps while a number | null path does not.Shaping return types with DeepPick
When you pass aprojection array to a query, you want the TypeScript return type to reflect exactly the fields you asked for — not the full entity. DeepPick is a recursive mapped type that does this shaping:
projection array:
projection field entirely, DbQueryResult defaults to the full TEntity type.
The SearchQuery type
SearchQuery<T> brings ValidPath, FieldOperators, OrderQuery, and DeepPick together into the single type used by all read methods:
filter and order is constrained to ValidPath<T>, and every value in filter is constrained to FieldOperators<ValueAt<T, K>> where K is the specific path being queried.
SchemaBuilder generics and type propagation
createSchemaBuilder is the root of the generic chain. By passing your tables as a const tuple, TypeScript infers the exact table names as a literal union:
repoFactory("users") receives a literal "users", the repository methods are permanently bound to the UserEntity type and its valid relational paths. Passing "unknown_table" is a compile-time error.
The four generics that propagate through the builder are:
| Generic | Description |
|---|---|
TDb | The Drizzle database instance type. Determines dialect-specific behavior. |
TTables | The const tuple of Drizzle table objects passed to the builder. |
TMetadata | The accumulated relation and soft-delete configuration for each table. |
TProfiles | A literal union of valid profile names derived from builder.profiles(). |
Profile type safety
Callingbuilder.profiles() with a const array establishes a literal union that is checked everywhere profiles are referenced:
UpdateSet type
UpdateSet<T> uses ValidPath and ValueAt to ensure that the value type in a set payload matches the column or JSON property being updated:
boolean to a field that should be a string:
Telemetry event types
The event bus is typed throughmitt. Every event payload is a distinct interface, so subscribers can safely access fields without casting:
Related pages
FilterQuery reference
Full API reference for the
FilterQuery type, all operators, and logical conjunctions.SearchQuery reference
Complete
SearchQuery type reference with projection, filter, order, page, and pageSize.Schema builder methods
How to call
builder.table(), builder.profiles(), builder.policies(), and builder.build().Access control overview
How the RBAC engine uses the profile literal union to enforce action-level and field-level policies.