建立資料庫轉接器
Auth.js 轉接器允許您與任何(甚至是多個)資料庫/後端服務整合,即使我們還沒有可用的官方套件。(我們歡迎針對新的轉接器提交 PR!請參閱下面的指南。)
Auth.js 轉接器非常靈活,您可以僅實作您需要的方法,並且僅建立實際會使用的資料庫表格/欄位。
Auth.js 轉接器是一個函式,它會接收一個 ORM/資料庫用戶端,並傳回一個物件,其中包含與資料庫互動的方法(基於Adapter
介面)。相同的資料庫轉接器將與任何 Auth.js 程式庫相容。
您可以選擇在您的轉接器上執行我們的轉接器測試,以確保它符合 Auth.js 的規定。
使用者管理
Auth.js 區分使用者和帳戶。一個使用者可以有多個帳戶。每個使用者首次登入的提供者類型都會建立一個帳戶。例如,如果使用者使用 Google 登入,然後使用 Facebook 登入,他們將會有兩個帳戶,每個提供者一個。使用者首次登入的提供者也會用於建立使用者物件。請參閱profile()
提供者方法。
方法與模型
尚未被 Auth.js 呼叫
雖然 Auth.js 沒有要求,但為了基本顯示目的,我們建議在 User
表格中新增以下欄位:name
、email
、image
。您可以使用profile()
提供者方法設定欄位。如果您不需要儲存這些屬性,請建立一個空的 profile() {}
方法。
雖然 Auth.js 沒有要求,但 Account
表格通常會儲存從提供者擷取的 Token。您可以使用account()
提供者方法設定欄位。如果您不需要儲存 Token,請建立一個空的 account() {}
方法。
資料庫 Session 管理
Auth.js 可以透過兩種方式管理 Session。請參閱概念:Session 策略,瞭解它們及其優缺點。
方法與模型
如果您想要使用資料庫 Session,您將需要實作以下方法
若要新增資料庫 Session 管理,您將需要如下擴充資料庫表格/欄位
另請參閱:Session 模型。
驗證 Token
當您想要支援電子郵件/無密碼登入時,Auth.js 會使用資料庫來儲存與使用者電子郵件地址相關聯的臨時驗證 Token。
方法與模型
另請參閱:驗證 Token 模型。
官方轉接器指南
完成以下所有步驟後,您就可以將 PR 提交到我們的儲存庫。
如果您建立了一個轉接器,並希望我們將其作為官方套件發佈,請確保它符合以下要求。請查看此現有的轉接器,以瞭解套件結構、所需檔案、測試設定、組態等。
-
轉接器必須實作
Adapter
介面的所有方法 -
必須包含轉接器測試,並且必須通過。Docker 比服務更受青睞,以使 CI 對網路錯誤具有彈性,並減少 GitHub Action Secrets 的數量(這也讓我們可以在 Fork PR 中執行這些測試)
-
轉接器必須遵循以下編碼風格
- 以 TypeScript 編寫
- 通過 Monorepo 的 Linting 規則
- 不包含 Polyfill
- 設定為 ES 模組 (ESM)
- 透過 JSDoc 註解記錄
- 至少有一個具名匯出,從其主要模組匯出。(例如
export function MyAdapter(): Adapter {}
) - 集合/表格名稱應遵循底層 ORM/資料庫文件/慣例的慣例(複數/單數、camelCase/snake_case)
-
設定 Monorepo 以協助我們維護套件
- 將 (最好是
.svg
) 標誌新增至此目錄 - 將轉接器新增至我們的 GitHub 工作流程檔案此處和此處
- 請務必
.gitignore
產生檔案(如果有的話)
- 將 (最好是
-
轉接器必須能夠處理來自使用者的任何屬性
ORM/資料庫用戶端可能有其自己的資料類型,但 Auth.js 希望這些類型能夠標準化為純 JavaScript 物件以保持一致性。如果您的 ORM/資料庫用戶端不會自動轉換,您需要在從/向資料庫讀取/寫入值時轉換這些值。
您可能會想檢查屬性的名稱並根據名稱進行轉換,但這並不可擴展(例如:
User
物件可能有多個Date
屬性,而不僅僅是emailVerified
)。我們建議您建立轉換數值的工具函式。以下是如何轉換日期的範例(如果您的 ORM/資料庫客戶端使用其他資料類型,請記得也要轉換它們,而不僅僅是日期)。它會檢查該值是否可以解析為日期,如果可以,則將其轉換為
Date
物件。否則,它會保留原始值不變。
// https://github.com/honeinc/is-iso-date/blob/8831e79b5b5ee615920dcb350a355ffc5cbf7aed/index.js#L5
const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
const isDate = (val: any): val is ConstructorParameters<typeof Date>[0] =>
!!(val && isoDateRE.test(val) && !isNaN(Date.parse(val)))
export const format = {
/** Takes an object that's coming from a database and converts it to plain JavaScript. */
from<T>(object: Record<string, any> = {}): T {
const newObject: Record<string, unknown> = {}
for (const [key, value] of Object.entries(object))
if (isDate(value)) newObject[key] = new Date(value)
else newObject[key] = value
return newObject as T
},
/** Takes an object that's coming from Auth.js and prepares it to be written to the database. */
to<T>(object: Record<string, any>): T {
const newObject: Record<string, unknown> = {}
for (const [key, value] of Object.entries(object))
if (value instanceof Date) newObject[key] = value.toISOString()
else newObject[key] = value
return newObject as T
},
}
TypeScript
您可以利用框架套件所提供的類型(例如,next-auth/adapters
、@auth/sveltekit/adapters
)。
import type { Adapter } from "next-auth/adapters"
function MyAdapter(): Adapter {
return {
// your adapter methods here
}
}
當您在 JavaScript 中編寫您的 Adapter 時,您仍然可以使用 JSDoc 來獲得有用的編輯器提示和自動完成功能。
/** @return { import("next-auth/adapters").Adapter } */
function MyAdapter() {
return {
// your adapter methods here
}
}