WARNING

Starting from drizzle-orm@1.0.0-beta.15, drizzle-valibot has been deprecated in favor of first-class schema generation support within Drizzle ORM itself

You can still use drizzle-valibot package but all new update will be added to Drizzle ORM directly

valibot

Install the dependencies

npm
yarn
pnpm
bun
npm i valibot

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/valibot';
import { parse } from 'valibot';

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 } = parse(userSelectSchema, rows[0]); // Error: `age` is not returned in the above query

const rows = await db.select().from(users).limit(1);
const parsed: { id: number; name: string; age: number } = 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/valibot';
import { parse } from 'valibot';

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 } = parse(userInsertSchema, user); // Error: `age` is not defined

const user = { name: 'Jane', age: 30 };
const parsed: { name: string, age: number } = parse(userInsertSchema, user); // Will parse successfully
await 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/valibot';
import { parse } from 'valibot';

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 } = parse(userUpdateSchema, user); // Error: `id` is a generated column, it can't be updated

const user = { age: 35 };
const parsed: { name?: string | undefined, age?: number | undefined } = parse(userUpdateSchema, user); // Will parse successfully
await 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 Valibot schema will overwrite it.

import { int, json, singlestoreTable, text } from 'drizzle-orm/singlestore-core';
import { createSelectSchema } from 'drizzle-orm/valibot';
import { parse, pipe, maxLength, object, string } from 'valibot';

const users = singlestoreTable('users', {
  id: int().primaryKey().autoincrement(),
  name: text().notNull(),
  bio: text(),
  preferences: json()
});

const userSelectSchema = createSelectSchema(users, {
  name: (schema) => pipe(schema, maxLength(20)), // Extends schema
  bio: (schema) => pipe(schema, maxLength(1000)), // Extends schema before becoming nullable/optional
  preferences: object({ theme: string() }) // Overwrites the field, including its nullability
});

const parsed: {
  id: number;
  name: string,
  bio?: string | undefined;
  preferences: {
    theme: string;
  };
} = parse(userSelectSchema, ...);

Data type reference

singlestore.boolean();

// Schema
boolean();
singlestore.date({ mode: 'date' });
singlestore.datetime({ mode: 'date' });
singlestore.timestamp({ mode: 'date' });

// Schema
date();
singlestore.binary();
singlestore.date({ mode: 'string' });
singlestore.datetime({ mode: 'string' });
singlestore.decimal();
singlestore.time();
singlestore.timestamp({ mode: 'string' });
singlestore.varbinary();

// Schema
string();
singlestore.char({ length: ... });

// Schema
pipe(string(), length(length));
singlestore.varchar({ length: ... });

// Schema
pipe(string(), maxLength(length));
singlestore.text();

// Schema
pipe(string(), maxLength(65_535)); // unsigned 16-bit integer limit
singlestore.text({ enum: ... });
singlestore.char({ enum: ... });
singlestore.varchar({ enum: ... });
singlestore.singlestoreEnum(..., ...);

// Schema
enum(enum);
singlestore.tinyint();

// Schema
pipe(number(), minValue(-128), maxValue(127), int()); // 8-bit integer lower and upper limit
singlestore.tinyint({ unsigned: true });

// Schema
pipe(number(), minValue(0), maxValue(255), int()); // unsigned 8-bit integer lower and upper limit
singlestore.smallint();

// Schema
pipe(number(), minValue(-32_768), maxValue(32_767), int()); // 16-bit integer lower and upper limit
singlestore.smallint({ unsigned: true });

// Schema
pipe(number(), minValue(0), maxValue(65_535), int()); // unsigned 16-bit integer lower and upper limit
singlestore.float();

// Schema
pipe(number(), minValue(-8_388_608), maxValue(8_388_607)); // 24-bit integer lower and upper limit
singlestore.mediumint();

// Schema
pipe(number(), minValue(-8_388_608), maxValue(8_388_607), int()); // 24-bit integer lower and upper limit
singlestore.float({ unsigned: true });

// Schema
pipe(number(), minValue(0), maxValue(16_777_215)); // unsigned 24-bit integer lower and upper limit
singlestore.mediumint({ unsigned: true });

// Schema
pipe(number(), minValue(0), maxValue(16_777_215), int()); // unsigned 24-bit integer lower and upper limit
singlestore.int();

// Schema
pipe(number(), minValue(-2_147_483_648), maxValue(2_147_483_647), int()); // 32-bit integer lower and upper limit
singlestore.int({ unsigned: true });

// Schema
pipe(number(), minValue(0), maxValue(4_294_967_295), int()); // unsgined 32-bit integer lower and upper limit
singlestore.double();
singlestore.real();

// Schema
pipe(number(), minValue(-140_737_488_355_328), maxValue(140_737_488_355_327)); // 48-bit integer lower and upper limit
singlestore.double({ unsigned: true });

// Schema
pipe(number(), minValue(0), maxValue(281_474_976_710_655)); // unsigned 48-bit integer lower and upper limit
singlestore.bigint({ mode: 'number' });

// Schema
pipe(number(), minValue(-9_007_199_254_740_991), maxValue(9_007_199_254_740_991), int()); // Javascript min. and max. safe integers
singlestore.serial();

// Schema
pipe(number(), minValue(0), maxValue(9_007_199_254_740_991), int()); // Javascript max. safe integer
singlestore.bigint({ mode: 'bigint' });

// Schema
pipe(bigint(), minValue(-9_223_372_036_854_775_808n), maxValue(9_223_372_036_854_775_807n)); // 64-bit integer lower and upper limit
singlestore.bigint({ mode: 'bigint', unsigned: true });

// Schema
pipe(bigint(), minValue(0n), maxValue(18_446_744_073_709_551_615n)); // unsigned 64-bit integer lower and upper limit
singlestore.year();

// Schema
pipe(number(), minValue(1_901), maxValue(2_155), int());
singlestore.json();

// Schema
union([union([string(), number(), boolean(), null_()]), array(any()), record(string(), any())]);