Skip to content

Drizzle Adapter @ydbjs/drizzle-adapter

Drizzle-совместимый API для YDB: DSL описания схемы, построители запросов, расширения YDB/YQL, DDL-хелперы и миграции.

Это высокоуровневый обзор адаптера YDB для Drizzle. Для получения подробной информации перейдите в соответствующие разделы:

Быстрый старт

ts
import { createDrizzle } from '@ydbjs/drizzle-adapter'
import { integer, text, ydbTable } from '@ydbjs/drizzle-adapter/schema'
import { eq } from 'drizzle-orm'

export const users = ydbTable('users', {
  id: integer('id').primaryKey(),
  name: text('name').notNull(),
})

const db = createDrizzle({
  connectionString: process.env.YDB_CONNECTION_STRING!,
  schema: { users },
})

await db.insert(users).values({ id: 1, name: 'Alice' }).execute()

const row = await db.query.users.findFirst({
  where: (user, { eq }) => eq(user.id, 1),
})

const selected = await db
  .select({ id: users.id, name: users.name })
  .from(users)
  .where(eq(users.id, 1))
  .prepare()
  .get()

Примеры

Более крупное runnable-приложение с CRUD, relations, joins, CTE, raw execution, транзакциями, scripts и DDL builders находится в разделе Примеры.

Схема с опциями YDB

ts
import {
  columnFamily,
  index,
  integer,
  partitionByHash,
  tableOptions,
  text,
  timestamp,
  ttl,
  ydbTable,
} from '@ydbjs/drizzle-adapter/schema'

export const events = ydbTable(
  'events',
  {
    id: integer('id').primaryKey(),
    tenantId: text('tenant_id').notNull(),
    payload: text('payload').notNull(),
    createdAt: timestamp('created_at').notNull(),
  },
  (table) => [
    index('events_tenant_idx').on(table.tenantId),
    partitionByHash(table.tenantId),
    ttl(table.createdAt, 'P30D'),
    columnFamily('hot', { data: 'ssd' }).columns(table.payload),
    tableOptions({ AUTO_PARTITIONING_BY_LOAD: 'ENABLED' }),
  ]
)

CRUD-операции

ts
await db.insert(users).values({ id: 1, name: 'Alice' }).execute()
await db.upsert(users).values({ id: 1, name: 'Alice Updated' }).execute()

const rows = await db.select().from(users).where(eq(users.id, 1)).execute()

await db.update(users).set({ name: 'Alice' }).where(eq(users.id, 1)).execute()
await db.delete(users).where(eq(users.id, 1)).execute()

Отношения (Relations)

ts
const user = await db.query.users.findFirst({
  where: (u, { eq }) => eq(u.id, 1),
  with: {
    posts: {
      limit: 5,
      orderBy: (p, { desc }) => [desc(p.id)],
    },
  },
})

Транзакции

ts
import { sql } from 'drizzle-orm'

await db.transaction(
  async (tx) => {
    await tx.insert(users).values({ id: 1, name: 'Alice' }).execute()
    await tx
      .update(stats)
      .set({ count: sql`count + 1` })
      .execute()
  },
  { accessMode: 'read write', isolationLevel: 'serializableReadWrite' }
)

Миграции

ts
import { migrate } from '@ydbjs/drizzle-adapter/migrator'

await migrate(db, {
  migrationsFolder: './drizzle',
  migrationLock: true,
})

YQL-хелперы

ts
import { asTable, valuesTable } from '@ydbjs/drizzle-adapter/sql'
import { sql } from 'drizzle-orm'

await db
  .select({ id: sql`r.id`, name: sql`r.name` })
  .from(asTable('$rows', 'r'))
  .execute()

const valueSource = valuesTable([{ id: 1, name: 'Alice' }], {
  alias: 'v',
  columns: ['id', 'name'],
})
await db
  .select({ id: sql`v.id`, name: sql`v.name` })
  .from(valueSource)
  .execute()
ts
import { vectorIndexView } from '@ydbjs/drizzle-adapter/schema'
import { knnCosineDistance } from '@ydbjs/drizzle-adapter/sql'
import { sql } from 'drizzle-orm'

const nearest = await db
  .select()
  .from(vectorIndexView(images, 'images_vector_idx', 'images'))
  .orderBy(knnCosineDistance(images.embedding, sql`$target`))
  .limit(10)
  .execute()

Release gates

Готовность адаптера закрывается проверками SDK CI:

  • корневые npm run build, npm run attw и npm run test;
  • интеграционные тесты с Docker-backed YDB через Vitest-проект int;
  • npm run check:surface --workspace=@ydbjs/drizzle-adapter, который проверяет root public API, закрытые deep imports и содержимое npm pack.

Release workflow остается общим для SDK и не кастомизируется на уровне пакета адаптера.