Skip to main content
ClaudeWave
Skill58 estrellas del repoactualizado 2mo ago

drizzle-orm

Drizzle ORM schema definition, type-safe queries, relational queries, CRUD operations, transactions, migrations with drizzle-kit, and database setup for PostgreSQL, MySQL, and SQLite. Use when defining database schemas, writing queries or joins, managing migrations, setting up a new Drizzle project, or working with drizzle-kit.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/monkilabs/opencastle /tmp/drizzle-orm && cp -r /tmp/drizzle-orm/src/orchestrator/plugins/drizzle ~/.claude/skills/drizzle-orm
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Drizzle ORM

## Topic Routing

Read the matching reference before writing code for any of these topics:

| Topic | Reference |
|-------|-----------|
| Schema definition & column types | `references/schema-patterns.md` |
| Queries, joins, & CRUD operations | `references/query-patterns.md` |
| Migrations & drizzle-kit | `references/migrations.md` |

## Critical Rules

**Schema**
- Define schemas in dedicated `schema.ts` files using `pgTable` / `mysqlTable` / `sqliteTable` from the correct dialect package
- Use `$inferSelect` and `$inferInsert` for TypeScript types — never duplicate type definitions manually
- Foreign keys require explicit `references(() => table.column)` — omitting this creates an unconstrained column
- Pass `{ schema }` to `drizzle()` when initializing the client to enable relational queries

**Relations**
- Define with `relations()` from `drizzle-orm` alongside the table definition
- Relations are required for `db.query` relational API — the SQL-like API does not use them
- Do not use relations as a substitute for foreign key constraints; define both

**Queries**
- Use SQL-like API (`db.select().from()`) for complex joins and aggregations
- Use relational API (`db.query.table.findMany({ with: { ... } })`) for nested data fetching
- Import `eq`, `and`, `or`, `gt`, `like`, `isNull` etc. from `drizzle-orm` for `where` clauses
- Always use `returning()` to get the inserted, updated, or deleted rows back

**Migrations**
- Use `drizzle-kit` for all migrations: `npx drizzle-kit generate` then `npx drizzle-kit migrate`
- Configure in `drizzle.config.ts` — connections string must be set before running commands
- Never manually edit generated migration SQL files — regenerate if changes are needed
- Use `npx drizzle-kit push` in development only; always use `migrate` for production

**Transactions**
- Wrap multi-step operations in `db.transaction(async (tx) => { ... })`
- Use `tx` (the transaction argument) instead of `db` for all queries inside the callback

**Performance**
- Use `db.select({ col: table.col })` for partial selects — avoids loading unused columns
- Add indexes in the schema definition for frequently queried columns
- Use `.prepare()` for repeated queries (prepared statements)

## Schema Definition

```typescript
import { pgTable, text, integer, timestamp, boolean } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';

export const users = pgTable('users', {
  id: text('id').primaryKey(),
  email: text('email').notNull().unique(),
  name: text('name').notNull(),
  createdAt: timestamp('created_at').defaultNow().notNull(),
});

export const posts = pgTable('posts', {
  id: text('id').primaryKey(),
  title: text('title').notNull(),
  authorId: text('author_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
  published: boolean('published').default(false).notNull(),
});

export const usersRelations = relations(users, ({ many }) => ({
  posts: many(posts),
}));

export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, { fields: [posts.authorId], references: [users.id] }),
}));

// Type inference — no manual duplication
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
```

## Query Patterns

```typescript
import { db } from './db';
import { eq } from 'drizzle-orm';
import { users, posts } from './schema';

// SQL-like: select with join
const results = await db
  .select({ user: users, postCount: count(posts.id) })
  .from(users)
  .leftJoin(posts, eq(posts.authorId, users.id))
  .groupBy(users.id);

// Relational: nested fetch
const usersWithPosts = await db.query.users.findMany({
  where: eq(users.id, userId),
  with: { posts: { where: eq(posts.published, true) } },
});

// Insert with returning
const [newUser] = await db.insert(users).values({ id, email, name }).returning();
```

## Reference Files

- `references/schema-patterns.md` — Table definitions, column types, constraints, indexes, relations, type inference
- `references/query-patterns.md` — Select, joins, where clauses, relational API, CRUD, transactions, prepared statements
- `references/migrations.md` — drizzle.config.ts, generate/migrate/push commands, migration workflow

## Quick Workflow: Set up Drizzle in a project
1. Install: `npm install drizzle-orm` + dialect driver (`postgres` / `@libsql/client` / `better-sqlite3`)
2. Install drizzle-kit: `npm install -D drizzle-kit`
3. Define schema in `src/db/schema.ts` using the correct dialect table builder
4. Create `drizzle.config.ts` with database URL and schema path — verify the config before running commands
5. Generate migration: `npx drizzle-kit generate` — inspect the SQL output before applying
6. Apply migration: `npx drizzle-kit migrate`
   - **If migration fails:** check DB connection string → verify schema matches existing tables → use `npx drizzle-kit push` for dev environments
7. Initialize client: `const db = drizzle(pool, { schema })` and run a test query to confirm connectivity
astro-frameworkSkill

Creates pages/layouts, defines content collections, configures hydration directives, and wires integrations. Use when adding or modifying Astro pages, layouts, components, or content collections. Trigger terms: Astro, content collection, client:load, client:visible, astro:content

browser-testingSkill

Drive real browsers via Chrome DevTools MCP: navigate pages, capture snapshots, run responsive checks, and collect console/perf traces. Use when the user mentions: 'validate UI change in Chrome', 'capture a screenshot', 'run responsive checks', or 'collect console logs'. Trigger terms: browser testing, DevTools, console logs, screenshot, responsive testing

cloudflare-platformSkill

Creates and deploys Cloudflare Workers, configures wrangler.toml bindings, sets up KV/D1/R2 storage and Durable Objects, manages Pages deployments, and implements edge function patterns. Use when building or deploying Cloudflare Workers, setting up Pages, working with KV/D1/R2 storage, configuring wrangler.toml, or deploying edge applications.

contentful-cmsSkill

Creates Contentful content types, queries entries via GraphQL/REST, runs CLI migrations, and manages assets and locales. Use when building or modifying Contentful content models, writing queries, or migrating content.

convex-databaseSkill

Convex reactive database patterns, schema design, real-time queries, mutations, actions, authentication, migrations, performance optimization, and component creation. Use when designing Convex schemas, writing queries/mutations, managing the Convex backend, setting up auth, migrating data, optimizing performance, or building Convex components.

coolify-deploymentSkill

Deploys applications, databases, and services on self-hosted Coolify instances, manages environments and env vars, runs infrastructure diagnostics, and performs batch operations. Use when deploying apps to Coolify, managing Coolify servers, debugging deployment issues, setting up databases, or managing Coolify infrastructure.

cypress-testingSkill

Writes Cypress E2E/component tests, configures `cy.intercept()` and `cy.session()`, authors custom commands, and wires CI artifacts. Use when creating E2E specs, component tests, or CI test pipelines. Trigger terms: cypress, e2e, component test, cy.intercept, cy.session

expo-developmentSkill

Scaffolds Expo/React Native apps, configures EAS Build profiles, manages native modules via CNG, sets up Expo Router navigation, and uses EAS Update for OTA deployments. Use when creating React Native apps with Expo, configuring EAS builds, setting up Expo Router, managing native modules, or deploying OTA updates.