Use when integrating Drizzle ORM with Bun's SQLite driver for type-safe schema definitions and migrations.
63
75%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./plugins/bun/skills/bun-drizzle-integration/SKILL.mdDrizzle ORM provides type-safe database access with Bun's SQLite driver.
bun add drizzle-orm
bun add -D drizzle-kit// src/db/schema.ts
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
export const users = sqliteTable("users", {
id: integer("id").primaryKey({ autoIncrement: true }),
name: text("name").notNull(),
email: text("email").notNull().unique(),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.default(sql`(unixepoch())`),
});
export const posts = sqliteTable("posts", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
content: text("content"),
authorId: integer("author_id")
.notNull()
.references(() => users.id),
});// src/db/index.ts
import { drizzle } from "drizzle-orm/bun-sqlite";
import { Database } from "bun:sqlite";
import * as schema from "./schema";
const sqlite = new Database("app.db");
export const db = drizzle(sqlite, { schema });// drizzle.config.ts
import type { Config } from "drizzle-kit";
export default {
schema: "./src/db/schema.ts",
out: "./drizzle",
dialect: "sqlite",
dbCredentials: {
url: "./app.db",
},
} satisfies Config;# Generate migration
bun drizzle-kit generate
# Apply migrations
bun drizzle-kit migrate
# Push schema directly (dev only)
bun drizzle-kit push
# Open Drizzle Studio
bun drizzle-kit studioimport { db } from "./db";
import { users, posts } from "./db/schema";
// Single insert
const user = await db.insert(users).values({
name: "Alice",
email: "alice@example.com",
}).returning();
// Multiple insert
await db.insert(users).values([
{ name: "Bob", email: "bob@example.com" },
{ name: "Charlie", email: "charlie@example.com" },
]);
// Insert or ignore
await db.insert(users)
.values({ name: "Alice", email: "alice@example.com" })
.onConflictDoNothing();
// Upsert
await db.insert(users)
.values({ name: "Alice", email: "alice@example.com" })
.onConflictDoUpdate({
target: users.email,
set: { name: "Alice Updated" },
});import { eq, gt, like, and, or, desc, asc } from "drizzle-orm";
// All rows
const allUsers = await db.select().from(users);
// With conditions
const activeUsers = await db
.select()
.from(users)
.where(eq(users.status, "active"));
// Multiple conditions
const filtered = await db
.select()
.from(users)
.where(and(
gt(users.age, 18),
like(users.name, "%Alice%")
));
// Specific columns
const names = await db
.select({ name: users.name, email: users.email })
.from(users);
// Order and limit
const topUsers = await db
.select()
.from(users)
.orderBy(desc(users.createdAt))
.limit(10);
// First result
const first = await db.query.users.findFirst({
where: eq(users.id, 1),
});// Update with condition
await db
.update(users)
.set({ name: "Alice Updated" })
.where(eq(users.id, 1));
// Update multiple fields
await db
.update(users)
.set({
name: "New Name",
updatedAt: new Date(),
})
.where(eq(users.email, "alice@example.com"));// Delete with condition
await db.delete(users).where(eq(users.id, 1));
// Delete multiple
await db.delete(users).where(gt(users.createdAt, cutoffDate));// schema.ts
import { relations } from "drizzle-orm";
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}));
// Query with relations
const usersWithPosts = await db.query.users.findMany({
with: {
posts: true,
},
});
// Nested relations
const detailed = await db.query.users.findFirst({
where: eq(users.id, 1),
with: {
posts: {
with: {
comments: true,
},
},
},
});// Transaction
await db.transaction(async (tx) => {
const [user] = await tx.insert(users)
.values({ name: "Alice", email: "alice@example.com" })
.returning();
await tx.insert(posts).values({
title: "First Post",
authorId: user.id,
});
});
// Rollback on error
await db.transaction(async (tx) => {
await tx.insert(users).values({ name: "Bob" });
if (someCondition) {
tx.rollback(); // Throws to rollback
}
await tx.insert(posts).values({ ... });
});// Create prepared statement
const getUserById = db
.select()
.from(users)
.where(eq(users.id, sql.placeholder("id")))
.prepare();
// Execute with parameter
const user = await getUserById.execute({ id: 1 });
// Reuse for performance
for (const id of userIds) {
const user = await getUserById.execute({ id });
processUser(user);
}import { sql } from "drizzle-orm";
// Raw query
const result = await db.run(sql`
UPDATE users SET last_login = ${new Date()} WHERE id = ${userId}
`);
// In select
const users = await db.select({
name: users.name,
upperName: sql<string>`UPPER(${users.name})`,
}).from(users);
// Raw expressions in where
await db.select().from(users).where(
sql`${users.age} > 18 AND ${users.status} = 'active'`
);import {
sqliteTable,
text,
integer,
real,
blob,
numeric,
} from "drizzle-orm/sqlite-core";
const example = sqliteTable("example", {
// Integer
id: integer("id").primaryKey(),
age: integer("age"),
// Text
name: text("name"),
status: text("status", { enum: ["active", "inactive"] }),
// Real (float)
price: real("price"),
// Blob
data: blob("data", { mode: "buffer" }),
// Boolean (stored as integer)
active: integer("active", { mode: "boolean" }),
// Timestamp (stored as integer)
createdAt: integer("created_at", { mode: "timestamp" }),
updatedMs: integer("updated_ms", { mode: "timestamp_ms" }),
// JSON (stored as text)
metadata: text("metadata", { mode: "json" }),
});| Error | Cause | Fix |
|---|---|---|
SQLITE_CONSTRAINT | FK/unique violation | Check constraints |
no such column | Schema mismatch | Run migrations |
Cannot find module | Missing driver | Use drizzle-orm/bun-sqlite |
| Type mismatch | Wrong column type | Check schema definition |
Load references/migrations.md when:
Load references/performance.md when:
ad16332
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.