Starting from drizzle-orm@1.0.0-beta.15, drizzle-typebox has been deprecated in favor of first-class schema generation support within Drizzle ORM itself
You can still use drizzle-typebox package but all new update will be added to Drizzle ORM directly
This version of typebox is legacy by using @sinclair/typebox package
typebox-legacy
Install the dependencies
npm
yarn
pnpm
bun
npm i drizzle-orm@rc @sinclair/typebox
yarn add drizzle-orm@rc @sinclair/typebox
pnpm add drizzle-orm@rc @sinclair/typebox
bun add drizzle-orm@rc @sinclair/typebox
Select schema
Defines the shape of data queried from the database - can be used to validate API responses.
import { int, singlestoreTable, text } from 'drizzle-orm/singlestore-core';import { createSelectSchema } from 'drizzle-orm/typebox-legacy';import { Value } from '@sinclair/typebox/value';const users = singlestoreTable('users', { id: int().primaryKey().autoincrement(), name: text().notNull(), age: int().notNull()});const userSelectSchema = createSelectSchema(users);const rows = await db.select({ id: users.id, name: users.name }).from(users).limit(1);const parsed: { id: number; name: string; age: number } = Value.Parse(userSelectSchema, rows[0]); // Error: `age` is not returned in the above queryconst rows = await db.select().from(users).limit(1);const parsed: { id: number; name: string; age: number } = Value.Parse(userSelectSchema, rows[0]); // Will parse successfully
Column enums are supported through the SingleStore table schema and can be validated with the generated table schemas.
Insert schema
Defines the shape of data to be inserted into the database - can be used to validate API requests.
import { int, singlestoreTable, text } from 'drizzle-orm/singlestore-core';import { createInsertSchema } from 'drizzle-orm/typebox-legacy';import { Value } from '@sinclair/typebox/value';const users = singlestoreTable('users', { id: int().primaryKey().autoincrement(), name: text().notNull(), age: int().notNull()});const userInsertSchema = createInsertSchema(users);const user = { name: 'John' };const parsed: { name: string, age: number } = Value.Parse(userInsertSchema, user); // Error: `age` is not definedconst user = { name: 'Jane', age: 30 };const parsed: { name: string, age: number } = Value.Parse(userInsertSchema, user); // Will parse successfullyawait db.insert(users).values(parsed);
Update schema
Defines the shape of data to be updated in the database - can be used to validate API requests.
import { int, singlestoreTable, text } from 'drizzle-orm/singlestore-core';import { createUpdateSchema } from 'drizzle-orm/typebox-legacy';import { Value } from '@sinclair/typebox/value';const users = singlestoreTable('users', { id: int().primaryKey().autoincrement(), name: text().notNull(), age: int().notNull()});const userUpdateSchema = createUpdateSchema(users);const user = { id: 5, name: 'John' };const parsed: { name?: string | undefined, age?: number | undefined } = Value.Parse(userUpdateSchema, user); // Error: `id` is a generated column, it can't be updatedconst user = { age: 35 };const parsed: { name?: string | undefined, age?: number | undefined } = Value.Parse(userUpdateSchema, user); // Will parse successfullyawait db.update(users).set(parsed).where(eq(users.name, 'Jane'));
Refinements
Each create schema function accepts an additional optional parameter that you can used to extend, modify or completely overwite a field’s schema. Defining a callback function will extend or modify while providing a Typebox schema will overwrite it.
import { int, json, singlestoreTable, text } from 'drizzle-orm/singlestore-core';import { createSelectSchema } from 'drizzle-orm/typebox-legacy';import { Type } from '@sinclair/typebox';import { Value } from '@sinclair/typebox/value';const users = singlestoreTable('users', { id: int().primaryKey().autoincrement(), name: text().notNull(), bio: text(), preferences: json()});const userSelectSchema = createSelectSchema(users, { name: (schema) => Type.String({ ...schema, maxLength: 20 }), // Extends schema bio: (schema) => Type.String({ ...schema, maxLength: 1000 }), // Extends schema before becoming nullable/optional preferences: Type.Object({ theme: Type.String() }) // Overwrites the field, including its nullability});const parsed: { id: number; name: string, bio?: string | undefined; preferences: { theme: string; };} = Value.Parse(userSelectSchema, ...);
Factory functions
For more advanced use cases, you can use the createSchemaFactory function.
Use case: Using an extended Typebox instance
import { int, singlestoreTable, text } from 'drizzle-orm/singlestore-core';import { createSchemaFactory } from 'drizzle-orm/typebox';import { t } from 'elysia'; // Extended Typebox instanceconst users = singlestoreTable('users', { id: int().primaryKey().autoincrement(), name: text().notNull(), age: int().notNull()});const { createInsertSchema } = createSchemaFactory({ typeboxInstance: t });const userInsertSchema = createInsertSchema(users, { // We can now use the extended instance name: (schema) => t.Number({ ...schema }, { error: '`name` must be a string' })});