A TypeSpec emitter that generates Drizzle ORM schema definitions and types from TypeSpec specifications. Learn about TypeSpec emitters here.
Important
Project Status: 🚧 This project is brand new. Use at your own risk.
This emitter allows you to define your database schema using TypeSpec's type-safe language with specialized decorators and automatically generate Drizzle ORM schema files, enabling a single source of truth for your database schema definitions alongside other artifacts.
- Generate Drizzle schema definitions from TypeSpec models
- Decorator-based configuration for database-specific concerns
- Support for table customization, constraints, and relationships
- Primary keys, unique constraints, indexes, and default values
- One-to-one, one-to-many, and many-to-many relationships
- Junction table support for many-to-many relationships
- Schema namespacing and custom table/column names
- Type-safe database schema generation
- Integration with TypeSpec's existing ecosystem
bun add -D @omnidotdev/typespec-drizzle- Add the emitter to your TypeSpec configuration (
tspconfig.yaml):
emit:
- "@omnidotdev/typespec-drizzle"- Define your models in TypeSpec with decorators:
import "@omnidotdev/typespec-drizzle";
@table({ name: "users" })
model User {
@id
id: string;
@unique
email: string;
name: string;
@default("now()")
createdAt: utcDateTime;
}
@table({ name: "posts" })
model Post {
@id
id: string;
title: string;
content: string;
@manyToOne({
foreignKey: "authorId",
references: "id",
})
authorId: string;
@default("now()")
createdAt: utcDateTime;
}- Add a
tspconfig.yamlfile:
emit:
- "@omnidotdev/typespec-drizzle"
- "@typespec/json-schema"
options:
"@omnidotdev/typespec-drizzle":
outputDir: "./tsp-output"- Run the TypeSpec compiler:
tsp compile .The emitter will generate Drizzle schema files in the output directory, plus JSON schemas for your models.
Mark a model as a database table.
@table({ name: "custom_users", schema: "auth" })
model User {
// ...
}Options:
name?: string- Custom table name (defaults to model name in lowercase)schema?: string- Database schema name
Mark a model as a junction table for many-to-many relationships.
@junction
@table({ name: "user_roles" })
model UserRole {
@manyToOne({ foreignKey: "userId", references: "id" })
userId: string;
@manyToOne({ foreignKey: "roleId", references: "id" })
roleId: string;
}Configure column-specific options.
@column({ name: "user_email" })
email: string;Options:
name?: string- Custom column name (defaults to property name)
Mark a property as the primary key.
@id
id: string;Mark a numeric primary key as auto-incrementing.
@id
@autoIncrement
id: int64;Set a default value for a column.
@default("'active'")
status: string;
@default("now()")
createdAt: utcDateTime;
@default("0")
count: int32;
@default("false")
isActive: boolean;Add a unique constraint to a column.
@unique("unique_email")
email: string;
@unique // Uses default constraint name
username: string;Add an index to a column.
@index("idx_created_at")
createdAt: utcDateTime;
@index // Uses default index name
title: string;Define a one-to-one relationship.
@oneToOne({ foreignKey: "profileId", references: "id" })
profileId: string;Define a one-to-many relationship.
@oneToMany({ foreignKey: "categoryId", references: "id" })
posts: Post[];Define a many-to-one relationship.
@manyToOne({ foreignKey: "authorId", references: "id" })
authorId: string;Define a many-to-many relationship.
@manyToMany({ through: "post_tags" })
tags: Tag[];Relationship Options:
foreignKey?: string- Name of the foreign key fieldreferences?: string- Field in the target table (defaults to "id")through?: string- Junction table name (required for many-to-many)
import "@omnidotdev/typespec-drizzle";
@table({ name: "users" })
model User {
@id
id: string;
@unique
@index("idx_username")
username: string;
@unique
@index("idx_email")
email: string;
@default("now()")
createdAt: utcDateTime;
}
@table({ name: "categories" })
model Category {
@id
id: string;
@unique
name: string;
@manyToOne({ foreignKey: "parentId", references: "id" })
parentId?: string;
}
@table({ name: "posts" })
model Post {
@id
id: string;
title: string;
content: string;
@manyToOne({ foreignKey: "authorId", references: "id" })
authorId: string;
@manyToOne({ foreignKey: "categoryId", references: "id" })
categoryId?: string;
@manyToMany({ through: "post_tags" })
tags: Tag[];
@default("now()")
createdAt: utcDateTime;
}
@table({ name: "tags" })
model Tag {
@id
id: string;
@unique
name: string;
@default("now()")
createdAt: utcDateTime;
}
@junction
@table({ name: "post_tags" })
model PostTag {
@id
id: string;
@manyToOne({ foreignKey: "postId", references: "id" })
postId: string;
@manyToOne({ foreignKey: "tagId", references: "id" })
tagId: string;
@default("now()")
createdAt: utcDateTime;
}Use Tilt for a unified development experience:
tilt upor manually install and build:
bun install
bun run build # or `bun run build:watch`Tests can be run with bun test.
See Omni's contributing docs.
The code in this repository is licensed under MIT, © Omni LLC. See LICENSE.md for more information.
