Галоўная / Артыкулы

Prisma без кліента Prisma: запиты Kysely захіщаныя ад помылак у Next.js

Выучыце, як выкарыстоўваць Prisma для працы з схемамі, ствараць типы Kysely за дапамою prisma-kysely, выбраць діалект Neon або pg, і безпечна выконваць запиты з коду сервера Next.js.

Выдавец: REACTAPP.TOP6 хв чытання1411 слоў

Крыніцы: **Using Prisma for Schema and Kysely for Queries in a Next.js App**

Prisma ўзначны для дизайну схемы, але Prisma Client ўтварае значную залежнасць, якая патрэбна для ўключэння ў кожную функцыю без сервера, калі вам проста трэба SQL з падтрымкай типаў. Практычны спосаб раздзелення: Prisma керуе схемай пад час розработы, генератор ператварае яе на типы TypeScript, а Kysely выкананяе запиты ў режыме працы. Шэрыфакс показвае, як установіць гэта ў проекте Next.js App Router, і параганяе дыалект Neon HTTP з класычным pg pool.

Якщо вы хочаце традыцыйны падход з Prisma Client у час выканання, адзірніце інструкцыю па налаштаванні Prisma 7 у проекте Next.js 16.

Як дзеляцца адпаведальнасці

Кожны інструмент у гэйму мае адну чыткую задачу:

  • Prisma адмініструеяць кантэкст базы дадзеных: файл схемы, сінхронізацыю чыста міграцыю базы дадзеных, а таксама інструменты, такія як Prisma Studio для перагляду дадзеных.
  • Kysely — это средства для стварэння запытак у час выканання. Вы пісвеце запыткі у формате SQL на TypeScript, кампайляр пераканалюе назвы табелей і столбцоў, а сама бібліятэка заступаецца малым розмерам.
  • prisma-kysely — это з’ѐеднальны элемент: генератор Prisma, які стварае адзначэнні типоў Kysely безпасцерага з вашай схемы Prisma.

Prisma застаецца ў вашым процесе разработкі, тады калі Kysely ёсць едыным шаром базы дадзеных у запусканам коде. Аднойчыны: вы трапляецеся без API Prisma Client, які ведае пра адносы межу элементамі, такімі як вярнутыя рэзультаты з include і вярнутыя рэзультаты після багаторазовых змены, а таксама без можлівасці самостойнага стварэння з’еднанняў. Якщо вы яшчэ выбіраеце шар дадзеных, порэванае raw SQL, Prisma і Drizzle дапамагае у прымітным выборе.

Інсталяцыя пакетаў

Для роботы програмы патрэбны Kysely, дыалект і драйвер; гэта дае можлівасць інсталявацыі стаку на аднойчыне з Neon (тут пользуецца pnpm, але працуюць таксама npm і yarn):

pnpm add kysely kysely-neon @neondatabase/serverless
pnpm add -D prisma prisma-kysely

Запамятаце, што prisma і prisma-kysely ўжо ўтвараюць частку дэпэндэнсіяў для разработкі: яны толькі керуюць схемай і генеруюць код.

Апісанне схемы і генераванне типаў Kysely

Шыматлік — звычны Prisma, за выключэнням таго, што генераторам ёсць prisma-kysely (запіс у ./types), а не звычны кліентскі генератор. У ём узначаюцца User і Post з адно-дацяным адносункам.

// db/schema.prisma

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator kysely {
  provider = "prisma-kysely"
  output   = "./types"
}

model User {
  id    Int    @id @default(autoincrement())
  name  String
  email String  @unique
  posts Post[]
}
model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  authorId  Int
  createdAt DateTime @default(now())
  author    User     @relation(fields: [authorId], references: [id])
}

prisma generate тепер стварае типы Kysely замест кліента, а prisma db push застосоўвае шыматлік да базы дадзеных:

pnpm prisma generate
pnpm prisma db push

Рэзультатам ёсць файл на кшталт db/types/kysely.d.ts з інтерфейсам DB, які описвае кожную табліцу. Тры застерэжэння:

  • Шыматлік знаходзіцца ў db/schema.prisma, а не у стандартным для Prisma prisma/schema.prisma; таму неабходна націснуць CLI на яго (напрыклад, за дапамою --schema) па трэбаванню вашай версіі Prisma.
  • db push сінхронізуе базу дадзеных без запісву файлаў міграцый. Для даных у працоўнай сэрвісе prisma migrate dev і prisma migrate deploy ствараюць версіяваныя міграцыі, не зменяючы рэшту процесу работы.
  • У няўякнучых выданнях Prisma настройкі з’язку перакладаюцца ў окольны файл конфігурацыі; якщо лінія url не прыманяецца, пераканайцеся ў актуальных інструкцыях.
  • Скрыпты пакетаў для ўседзённага цыклу

    Калькі скрыптав расхляблююць процес работы для каманды:

    {
      "scripts": {
        "db:push": "prisma db push",
        "db:generate": "prisma generate",
        "db:studio": "prisma studio"
      }
    }
    

    З іх наявнасцю змена схемы выражаецца за дапамою двух каманд:

    # To generate the types
    pnpm db:generate
    # To push to the remote DB
    pnpm db:push
    

    Тады база дадзеных і типы Kysely застаюцца сувязанымі, таму кампайляр пазначае будзь-які запыт, який выкарыстоўвае перайменаваны або адчынены столбец.

    Выбір дыялекта Kysely

    Kysely не спілкуецца безпосередна з самай базай дадзеных. Діялект знаходзится межу будоўнікам запытаў і драйверам і ведае, як скомпіляваць і адправляць запыты для адной базай дадзеных і аднаго спосабу з’яўлення. Афіцыйныя діялекты падтрымляюць PostgreSQL, MySQL і SQLite; діялекты спальноты — такія сервісы як Neon, PlanetScale і Turso. Для Postgres два варыянты падтрымліваюць большасць случаў.

    Neon через HTTP для размешчэння без сервера

    На Vercel або падобной платформе HTTP-драйвер Neon чырпаецца добра: кожны запыт ёсць безстановым запитам, таму не трэба падтрымваць стойкія з’яўленне межу короткімі вызывамі. Настройка загортае neon() у NeonDialect і прызначае Kysely з генераваным DB:

    // db/index.ts
    import { Kysely } from 'kysely'
    import { NeonDialect } from 'kysely-neon'
    import { neon } from '@neondatabase/serverless'
    import type { DB } from './types/kysely'
    
    const db = new Kysely<DB>({
      dialect: new NeonDialect({
        neon: neon(process.env.DATABASE_URL!),
      }),
    })
    
    export default db
    

    ! толькі змушвае TypeScript мовчаць; ён нічаго не перакантролюе. Большыя обмежэнні — kysely-neon через HTTP не можа выконваць транзакцыі чыста запыты на адной сесыі, таму ён падходзіць для простых оперэйцыяў CRUD і сторанак, дзе больша частка — чытанне, а не робота з калькамі. З драйверам WebSocket Neon вам абоўсумова не патрэбны kysely-neon: прасуньте Pool Neon у вбудованы PostgresDialect Kysely. API kysely-neon таксама зменяўся між выданнямі, таму пораўнайце яго з актуальным README.

    node-postgres для сервераў, якія працуюць дзёўга

    Для сервера Node.js, які працуе дзёўга, офіцыйны драйвер pg — гэта найболей комплектны выбар, з транзакцыямі, пулінгам і падготавленымі запытамі. Ён падключаецца да власнага PostgresDialect Kysely:

    // db/index.ts
    import { Kysely, PostgresDialect } from 'kysely'
    import { Pool } from 'pg'
    import type { DB } from './types/kysely'
    
    const db = new Kysely<DB>({
      dialect: new PostgresDialect({
        pool: new Pool({
          connectionString: process.env.DATABASE_URL,
        }),
      }),
    })
    
    export default db
    

    Выбір межы ямі

    Разлік заключаецца у модэлі з’яўлення звязку. kysely-neon — это безстановы HTTP: лёгкі і падходзячы для сервероў без адпаведных рэшарактараў, але без падтрымкі транзакцый. pg падтрымвае відкрытыя TCP-з’язкі, а також усю сукупнасць функцый, што падходзіць для сервераў, які працуюць стала. Выкарыстоўваюце kysely-neon на платформах без адпаведных рэшарактараў, такіх як Vercel чы Netlify, а pg чы пул Neon WebSocket — калі вам патрэбныя транзакцыі. Будзьце ажырэйны пулам pg унутранік сервероў без адпаведных рэшарактараў: кожны экземпляр стварае своі з’язкі, і гэта можа выцягнуць максымальную кантэйнернасць базы дадзеных без зусібныя званоўкі званоўніка з’язкаў зза межаў.

    Запытанні з серверскага компонента

    Будзь-які код з боку сервера можа імпортуваць db. Шырыея серверскі компонент перыядычна показвае корыстувальнікаў, выбіраючы тры столбцы, аранжаваныя па id:

    // app/users/page.tsx
    import db from '@/db'
    
    export default async function UsersPage() {
      const users = await db
        .selectFrom('user')
        .select(['id', 'name', 'email'])
        .orderBy('id')
        .execute()
    
      return (
        <div>
          <h1>Users</h1>
          <ul>
            {users.map(u => (
              <li key={u.id}>{u.name} ({u.email})</li>
            ))}
          </ul>
        </div>
      )
    }
    

    Паколькі DB выходзіць з схемы Prisma, неправильна напісанне табліцы або столбца спрычынае парабою пераказвання типаў, а users формуецца толькі з выбраных полей.

    Є адна проблема: Prisma за замовчаннем называе табліцы на імена модэляў, таму гэтая схема стварае табліцу User, і генераваныя типы вжываюць гэтае імя. selectFrom('user') пераказвае типы толькі тады, калі да модэля дадаць @@map("user"); інакша запыт будзе до 'User'. Таксама не трэба включаць db у Кліентскія компаненты, адколькі ён чытае секрэтны данні, доступныя толькі на серверы.

    Паўздневны процес работы

    Калі все налаштавана, цикл выглядае так:

    1. Зменіце модэляў у db/schema.prisma.
    2. Паўтарна генеруйце типы і застосавіце змяны за дапамою двух скрыптав.
    3. Вжывайце db у Серверскіх компанентах, обробніках маршрутаў або Серверскіх дзеяннях.
  • Пераканаць вхідныя даны за дапамою Zod або падобных інструментаў пры ўводзе; типы Kysely пераканаюць форму запиту, а не значэнняя формы.
  • Утварэны лейаут размешчае ўсё, што стосуецца базы дадзенаў, пад db/:

    📦 my-next-app
    ├── 📁 app
    │   └── 📁 users
    │       └── page.tsx
    ├── 📁 db
    │   ├── schema.prisma
    │   ├── index.ts
    │   └── 📁 types
    │       └── kysely.d.ts
    ├── 📁 node_modules
    ├── .env
    ├── package.json
    ├── pnpm-lock.yaml
    └── tsconfig.json
    

    Заключэнне

    Такое раздзелення дазволяе застаўляць робочы процес схемы Prisma і Studio без адправкі Prisma Client, а таксама дае вам невялікы шар запитоў у формате SQL, чыия типы стежаць за схемай.

    • Застаўляйце prisma і prisma-kysely як залежнасці для разработкі; толькі Kysely, дыялект і драйвер адправляюцца у працэс выканання.
    • Для простых безсерверных завадзяў выкорыстоўвайце дыялект Neon HTTP, а калі патрэбны транзакцыі — перайдзіце на PostgresDialect з пулам.
    • Следзіце за называмі табэляў: генераваныя типы паходзяць з называў базы дадзенаў, якія за замовчаннем ўзімаюць назывы модэляў Prisma.
  • Перайдзіце з db push на правильныя міграцыі раней, чым данні ў базе дадзеных пачнуць мяць значэнне.