コンテンツへスキップ
NextAuth.js v4 からの移行ですか? 移行ガイドをお読みください.

Kysely アダプター

リソース

セットアップ

インストール

npm install kysely @auth/kysely-adapter

環境変数

DATABASE_HOST=
DATABASE_NAME=
DATABASE_USER=
DATABASE_PASSWORD=

構成

このアダプターは、Kysely (v0.24.2 現在) がサポートするのと同じファーストパーティの方言、つまり PostgreSQL、MySQL、および SQLite をサポートしています。以下の例では、pg クライアントを使用する PostgreSQL を使用します。

npm install pg
npm install --save-dev @types/pg
./auth.ts
import NextAuth from "next-auth"
import { KyselyAdapter } from "@auth/kysely-adapter"
import { db } from "../../../db"
 
export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: KyselyAdapter(db),
  providers: [],
})

Kysely のコンストラクターには、テーブルごとにインターフェースを持つエントリを含むデータベースインターフェースが必要です。これらの型は手動で定義することも、kysely-codegen / prisma-kysely を使用して自動的に生成することもできます。Auth.js で必要なデフォルトのモデルをご覧ください。

db.ts
import { PostgresDialect } from "kysely"
import { Pool } from "pg"
 
// This adapter exports a wrapper of the original `Kysely` class called `KyselyAuth`,
// that can be used to provide additional type-safety.
// While using it isn't required, it is recommended as it will verify
// that the database interface has all the fields that Auth.js expects.
import { KyselyAuth } from "@auth/kysely-adapter"
 
import type { GeneratedAlways } from "kysely"
 
interface Database {
  User: {
    id: GeneratedAlways<string>
    name: string | null
    email: string
    emailVerified: Date | null
    image: string | null
  }
  Account: {
    id: GeneratedAlways<string>
    userId: string
    type: string
    provider: string
    providerAccountId: string
    refresh_token: string | null
    access_token: string | null
    expires_at: number | null
    token_type: string | null
    scope: string | null
    id_token: string | null
    session_state: string | null
  }
  Session: {
    id: GeneratedAlways<string>
    userId: string
    sessionToken: string
    expires: Date
  }
  VerificationToken: {
    identifier: string
    token: string
    expires: Date
  }
}
 
export const db = new KyselyAuth<Database>({
  dialect: new PostgresDialect({
    pool: new Pool({
      host: process.env.DATABASE_HOST,
      database: process.env.DATABASE_NAME,
      user: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
    }),
  }),
})
💡

手動で型を定義する代わりに、kysely-codegen を使用してデータベーススキーマから型を生成するか、prisma-kysely を使用して Prisma スキーマから型を生成することもできます。KyselyAuth で生成された型を使用する場合は、Codegen をインポートし、2 番目のジェネリック引数として渡してください。

import type { Codegen } from "@auth/kysely-adapter"
new KyselyAuth<Database, Codegen>()

スキーマ

db/migrations/001_create_db.ts
import { Kysely, sql } from "kysely"
 
export async function up(db: Kysely<any>): Promise<void> {
  await db.schema
    .createTable("User")
    .addColumn("id", "uuid", (col) =>
      col.primaryKey().defaultTo(sql`gen_random_uuid()`)
    )
    .addColumn("name", "text")
    .addColumn("email", "text", (col) => col.unique().notNull())
    .addColumn("emailVerified", "timestamptz")
    .addColumn("image", "text")
    .execute()
 
  await db.schema
    .createTable("Account")
    .addColumn("id", "uuid", (col) =>
      col.primaryKey().defaultTo(sql`gen_random_uuid()`)
    )
    .addColumn("userId", "uuid", (col) =>
      col.references("User.id").onDelete("cascade").notNull()
    )
    .addColumn("type", "text", (col) => col.notNull())
    .addColumn("provider", "text", (col) => col.notNull())
    .addColumn("providerAccountId", "text", (col) => col.notNull())
    .addColumn("refresh_token", "text")
    .addColumn("access_token", "text")
    .addColumn("expires_at", "bigint")
    .addColumn("token_type", "text")
    .addColumn("scope", "text")
    .addColumn("id_token", "text")
    .addColumn("session_state", "text")
    .execute()
 
  await db.schema
    .createTable("Session")
    .addColumn("id", "uuid", (col) =>
      col.primaryKey().defaultTo(sql`gen_random_uuid()`)
    )
    .addColumn("userId", "uuid", (col) =>
      col.references("User.id").onDelete("cascade").notNull()
    )
    .addColumn("sessionToken", "text", (col) => col.notNull().unique())
    .addColumn("expires", "timestamptz", (col) => col.notNull())
    .execute()
 
  await db.schema
    .createTable("VerificationToken")
    .addColumn("identifier", "text", (col) => col.notNull())
    .addColumn("token", "text", (col) => col.notNull().unique())
    .addColumn("expires", "timestamptz", (col) => col.notNull())
    .execute()
 
  await db.schema
    .createIndex("Account_userId_index")
    .on("Account")
    .column("userId")
    .execute()
 
  await db.schema
    .createIndex("Session_userId_index")
    .on("Session")
    .column("userId")
    .execute()
}
 
export async function down(db: Kysely<any>): Promise<void> {
  await db.schema.dropTable("Account").ifExists().execute()
  await db.schema.dropTable("Session").ifExists().execute()
  await db.schema.dropTable("User").ifExists().execute()
  await db.schema.dropTable("VerificationToken").ifExists().execute()
}

このスキーマは Kysely で使用するために調整されており、メインの スキーマに基づいています。

Kysely でのマイグレーションの作成と実行の詳細については、Kysely マイグレーションのドキュメントを参照してください。

命名規則

snake_case と camelCase の列名が混在していることが問題となる場合や、基盤となるデータベースシステムで問題となる場合は、Kysely の CamelCasePlugin ( ドキュメントはこちら )機能を使用してフィールド名を変更することをお勧めします。これは NextAuth.js には影響しませんが、Kysely を使用する際に一貫したケーシングを使用できるようになります。

Auth.js © Balázs Orbán and Team -2024