بنقرة واحدة
drizzle-orm
Guidelines for developing with Drizzle ORM, a lightweight type-safe TypeScript ORM with SQL-like syntax
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Guidelines for developing with Drizzle ORM, a lightweight type-safe TypeScript ORM with SQL-like syntax
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Configure rate limiting, manage auth secrets, set up CSRF protection, define trusted origins, secure sessions and cookies, encrypt OAuth tokens, track IP addresses, and implement audit logging for Better Auth. Use when users need to secure their auth setup, prevent brute force attacks, or harden a Better Auth deployment.
Use when building Hono web applications or when the user asks about Hono APIs, routing, middleware, JSX, validation, testing, or streaming. TRIGGER when code imports from 'hono' or 'hono/*', or user mentions Hono. Use `npx hono request` to test endpoints.
Universal release workflow. Auto-detects version files and changelogs. Supports Node.js, Python, Rust, Claude Plugin, and generic projects. Use when user says "release", "发布", "new version", "bump version", "push", "推送".
Powerful asynchronous state management, server-state utilities, and data fetching for TS/JS, React, Vue, Solid, Svelte & Angular.
Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines, dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure/best practices, and boundaries. Use when user: configures tasks/workflows/pipelines, creates packages, sets up monorepo, shares code between apps, runs changed/affected packages, debugs cache, or has apps/packages directories.
| name | drizzle-orm |
| description | Guidelines for developing with Drizzle ORM, a lightweight type-safe TypeScript ORM with SQL-like syntax |
You are an expert in Drizzle ORM, TypeScript, and SQL database design with a focus on type safety and performance.
import {
pgTable,
serial,
text,
varchar,
timestamp,
boolean,
integer,
} from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: serial("id").primaryKey(),
email: varchar("email", { length: 255 }).notNull().unique(),
name: text("name"),
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const posts = pgTable("posts", {
id: serial("id").primaryKey(),
title: varchar("title", { length: 255 }).notNull(),
content: text("content"),
authorId: integer("author_id").references(() => users.id),
publishedAt: timestamp("published_at"),
createdAt: timestamp("created_at").defaultNow(),
});
You can organize schemas in multiple ways:
// Option 1: Single schema.ts file (recommended for smaller projects)
// src/db/schema.ts
// Option 2: Split by domain (recommended for larger projects)
// src/db/schema/users.ts
// src/db/schema/posts.ts
// src/db/schema/index.ts (re-exports all)
Use the casing option for automatic camelCase to snake_case mapping:
import { drizzle } from "drizzle-orm/node-postgres";
const db = drizzle(pool, {
casing: "snake_case", // Automatically maps camelCase to snake_case
});
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],
}),
}));
import {
pgTable,
serial,
varchar,
index,
uniqueIndex,
} from "drizzle-orm/pg-core";
export const users = pgTable(
"users",
{
id: serial("id").primaryKey(),
email: varchar("email", { length: 255 }).notNull(),
name: varchar("name", { length: 255 }),
},
(table) => [
uniqueIndex("email_idx").on(table.email),
index("name_idx").on(table.name),
],
);
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import * as schema from "./schema";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
export const db = drizzle(pool, { schema });
import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
import * as schema from "./schema";
const sqlite = new Database("sqlite.db");
export const db = drizzle(sqlite, { schema });
import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client";
import * as schema from "./schema";
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN,
});
export const db = drizzle(client, { schema });
// Select all columns
const allUsers = await db.select().from(users);
// Select specific columns
const userEmails = await db.select({ email: users.email }).from(users);
// With conditions
import { eq, and, or, gt, like } from "drizzle-orm";
const activeUsers = await db
.select()
.from(users)
.where(eq(users.isActive, true));
const filteredUsers = await db
.select()
.from(users)
.where(and(eq(users.isActive, true), like(users.email, "%@example.com")));
// Query with relations (requires schema with relations defined)
const usersWithPosts = await db.query.users.findMany({
with: {
posts: true,
},
});
// Nested relations
const postsWithAuthor = await db.query.posts.findMany({
with: {
author: {
columns: {
id: true,
name: true,
},
},
},
});
// Single insert
const newUser = await db
.insert(users)
.values({
email: "user@example.com",
name: "John Doe",
})
.returning();
// Bulk insert
await db.insert(users).values([
{ email: "user1@example.com", name: "User 1" },
{ email: "user2@example.com", name: "User 2" },
]);
// Upsert (insert or update on conflict)
await db
.insert(users)
.values({ email: "user@example.com", name: "John" })
.onConflictDoUpdate({
target: users.email,
set: { name: "John Updated" },
});
await db
.update(users)
.set({ name: "Jane Doe", updatedAt: new Date() })
.where(eq(users.id, 1));
await db.delete(users).where(eq(users.id, 1));
await db.transaction(async (tx) => {
const [user] = await tx
.insert(users)
.values({ email: "user@example.com", name: "User" })
.returning();
await tx.insert(posts).values({
title: "First Post",
authorId: user.id,
});
});
# Generate migration based on schema changes
npx drizzle-kit generate
# Apply migrations to database
npx drizzle-kit migrate
# Push schema directly (development only)
npx drizzle-kit push
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./src/db/schema.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});
import { InferSelectModel, InferInsertModel } from "drizzle-orm";
// Infer types from table definitions
export type User = InferSelectModel<typeof users>;
export type NewUser = InferInsertModel<typeof users>;
// Use in application code
function createUser(data: NewUser): Promise<User> {
return db
.insert(users)
.values(data)
.returning()
.then((r) => r[0]);
}
Ensure strict mode is enabled in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true
}
}
Always add indexes for columns used in WHERE clauses and JOINs:
export const orders = pgTable(
"orders",
{
id: serial("id").primaryKey(),
userId: integer("user_id").notNull(),
status: varchar("status", { length: 50 }).notNull(),
createdAt: timestamp("created_at").defaultNow(),
},
(table) => [
index("user_id_idx").on(table.userId),
index("status_idx").on(table.status),
index("created_at_idx").on(table.createdAt),
],
);
// Bad: Fetches all columns
const users = await db.select().from(users);
// Good: Fetches only needed columns
const userNames = await db
.select({ id: users.id, name: users.name })
.from(users);
const page = 1;
const pageSize = 20;
const paginatedUsers = await db
.select()
.from(users)
.limit(pageSize)
.offset((page - 1) * pageSize)
.orderBy(users.createdAt);
// Bad: N+1 query pattern
const users = await db.select().from(users);
for (const user of users) {
const posts = await db
.select()
.from(posts)
.where(eq(posts.authorId, user.id));
}
// Good: Use relational queries or joins
const usersWithPosts = await db.query.users.findMany({
with: { posts: true },
});