feat(adapters-surrealdb): update surrealdb.js to enable http connection strategy (#8823)

* update surrealdb.js which fixes rest/http strategy

* uncomment rest test

* add docs

* update package dependencies

* run both strategies

* Apply suggestions from code review

* add fetch to jest globals

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
This commit is contained in:
Martin Schaer
2023-10-25 21:32:40 -06:00
committed by GitHub
parent 21288ad461
commit c555356895
7 changed files with 143 additions and 37 deletions

View File

@@ -45,7 +45,7 @@
"@auth/core": "workspace:*"
},
"peerDependencies": {
"surrealdb.js": "^0.9.0"
"surrealdb.js": "^0.9.1"
},
"devDependencies": {
"@auth/adapter-test": "workspace:*",
@@ -55,4 +55,4 @@
"jest": {
"preset": "@auth/adapter-test/jest"
}
}
}

View File

@@ -1,3 +1,19 @@
/**
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: 16}}>
* <p style={{fontWeight: "normal"}}>Official <a href="https://www.surrealdb.com">SurrealDB</a> adapter for Auth.js / NextAuth.js.</p>
* <a href="https://www.surrealdb.com">
* <img style={{display: "block"}} src="https://authjs.dev/img/adapters/surrealdb.png" width="30" />
* </a>
* </div>
*
* ## Installation
*
* ```bash npm2yarn2pnpm
* npm install @auth/surrealdb-adapter surrealdb.js
* ```
*
* @module @auth/surrealdb-adapter
*/
import Surreal, { ExperimentalSurrealHTTP } from "surrealdb.js"
import type {
Adapter,
@@ -24,6 +40,7 @@ export type SessionDoc<T = string> = Document & { userId: T }
const extractId = (surrealId: string) => surrealId.split(":")[1] ?? surrealId
/** @internal */
// Convert DB object to AdapterUser
export const docToUser = (doc: UserDoc): AdapterUser => ({
...doc,
@@ -31,6 +48,7 @@ export const docToUser = (doc: UserDoc): AdapterUser => ({
emailVerified: doc.emailVerified ? new Date(doc.emailVerified) : null,
})
/** @internal */
// Convert DB object to AdapterAccount
export const docToAccount = (doc: AccountDoc) => {
const account: AdapterAccount = {
@@ -41,6 +59,7 @@ export const docToAccount = (doc: AccountDoc) => {
return account
}
/** @internal */
// Convert DB object to AdapterSession
export const docToSession = (
doc: SessionDoc<string | UserDoc>
@@ -52,6 +71,7 @@ export const docToSession = (
sessionToken: doc.sessionToken ?? "",
})
/** @internal */
// Convert AdapterUser to DB object
const userToDoc = (
user: Omit<AdapterUser, "id"> | Partial<AdapterUser>
@@ -63,6 +83,7 @@ const userToDoc = (
return doc
}
/** @internal */
// Convert AdapterAccount to DB object
const accountToDoc = (account: AdapterAccount): Omit<AccountDoc, "id"> => {
const doc = {
@@ -72,6 +93,7 @@ const accountToDoc = (account: AdapterAccount): Omit<AccountDoc, "id"> => {
return doc
}
/** @internal */
// Convert AdapterSession to DB object
export const sessionToDoc = (
session: AdapterSession
@@ -83,6 +105,86 @@ export const sessionToDoc = (
return doc
}
/**
* ## Setup
*
* The SurrealDB adapter does not handle connections automatically, so you will have to make sure that you pass the Adapter a `SurrealDBClient` that is connected already. Below you can see an example how to do this.
*
* ### Add the SurrealDB client
*
* #### Option 1/2 Using RPC:
*
* ```js
* import { Surreal } from "surrealdb.js";
*
* const connectionString = ... // i.e. "http://0.0.0.0:8000"
* const user = ...
* const pass = ...
* const ns = ...
* const db = ...
*
* const clientPromise = new Promise<Surreal>(async (resolve, reject) => {
* const db = new Surreal();
* try {
* await db.connect(`${connectionString}/rpc`, {
* ns, db, auth: { user, pass }
* })
* resolve(db)
* } catch (e) {
* reject(e)
* }
* })
*
* // Export a module-scoped MongoClient promise. By doing this in a
* // separate module, the client can be shared across functions.
* export default clientPromise
* ```
*
* #### Option 2/2 Using HTTP:
*
* Usefull in serverlees environments like Vercel.
*
* ```js
* import { ExperimentalSurrealHTTP } from "surrealdb.js"
*
* const connectionString = ... // i.e. "http://0.0.0.0:8000"
* const user = ...
* const pass = ...
* const ns = ...
* const db = ...
*
* const clientPromise = new Promise<ExperimentalSurrealHTTP<typeof fetch>>(async (resolve, reject) => {
* try {
* const db = new ExperimentalSurrealHTTP(connectionString, {
* fetch,
* ns, db, auth: { user, pass }
* })
* resolve(db)
* } catch (e) {
* reject(e)
* }
* })
*
* // Export a module-scoped MongoClient promise. By doing this in a
* // separate module, the client can be shared across functions.
* export default clientPromise
* ```
*
* ### Configure Auth.js
*
* ```js
* import NextAuth from "next-auth"
* import { SurrealDBAdapter } from "@auth/surrealdb-adapter"
* import clientPromise from "../../../lib/surrealdb"
*
* // For more information on each option (and a full list of options) go to
* // https://authjs.dev/reference/providers/oauth
* export default NextAuth({
* adapter: SurrealDBAdapter(clientPromise),
* ...
* })
* ```
**/
export function SurrealDBAdapter<T>(
client: Promise<Surreal | ExperimentalSurrealHTTP<T>>
// options = {}

View File

@@ -15,6 +15,13 @@ export const config = (
db: {
async disconnect() {
const surreal = await clientPromise
try {
await surreal.delete("account")
await surreal.delete("session")
await surreal.delete("verification_token")
} catch (e) {
console.log(e)
}
if (surreal.close) surreal.close()
},
async user(id: string) {

View File

@@ -1,18 +1,18 @@
import Surreal from "surrealdb.js"
import Surreal, { ExperimentalSurrealHTTP } from "surrealdb.js"
import { runBasicTests } from "@auth/adapter-test"
import { config } from "./common"
const clientPromise = new Promise<Surreal>(async (resolve, reject) => {
const db = new Surreal();
const db = new Surreal()
try {
await db.connect('http://0.0.0.0:8000/rpc', {
await db.connect("http://0.0.0.0:8000/rpc", {
ns: "test",
db: "test",
auth: {
user: "test",
pass: "test",
}
},
})
resolve(db)
} catch (e) {
@@ -21,3 +21,24 @@ const clientPromise = new Promise<Surreal>(async (resolve, reject) => {
})
runBasicTests(config(clientPromise))
const clientPromiseRest = new Promise<ExperimentalSurrealHTTP<typeof fetch>>(
async (resolve, reject) => {
try {
const db = new ExperimentalSurrealHTTP("http://0.0.0.0:8000", {
fetch,
auth: {
user: "test",
pass: "test",
},
ns: "test",
db: "test",
})
resolve(db)
} catch (e) {
reject(e)
}
}
)
runBasicTests(config(clientPromiseRest))

View File

@@ -1,27 +0,0 @@
test("TODO: test rest", () => {
expect(true).toBe(true)
})
// import { ExperimentalSurrealHTTP } from "surrealdb.js"
// import { runBasicTests } from "@auth/adapter-test"
// import fetch from "node-fetch"
// import { config } from "./common"
// const clientPromise = new Promise<ExperimentalSurrealHTTP<typeof fetch>>(async (resolve, reject) => {
// try {
// const db = new ExperimentalSurrealHTTP("http://0.0.0.0:8000", {
// fetch,
// auth: {
// user: "test",
// pass: "test",
// },
// ns: "test",
// db: "test",
// })
// resolve(db)
// } catch (e) {
// reject(e)
// }
// })
// runBasicTests(config(clientPromise))

View File

@@ -10,6 +10,9 @@ const swcConfig = {
/** @type {import("jest").Config} */
module.exports = {
globals: {
fetch: global.fetch,
},
transform: {
".(ts|tsx)$": ["@swc/jest", swcConfig],
".(js|jsx)$": ["@swc/jest", swcConfig],

8
pnpm-lock.yaml generated
View File

@@ -710,8 +710,8 @@ importers:
specifier: workspace:*
version: link:../core
surrealdb.js:
specifier: ^0.9.0
version: 0.9.0
specifier: ^0.9.1
version: 0.9.1
devDependencies:
'@auth/adapter-test':
specifier: workspace:*
@@ -29344,8 +29344,8 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
/surrealdb.js@0.9.0:
resolution: {integrity: sha512-JV1lSzeSF4GftfxSvrOd0fDAw0AwRTSTsn+smp4BzhVuvcfJH/2zceEMwsMLzQcUao386pq4xk5JKoieayFJqQ==}
/surrealdb.js@0.9.1:
resolution: {integrity: sha512-Lw7gds+u5966ng00/yOOkeW90VFj2tI5YNZ1cY7t9fyl9yEEcrFOkR5djqXwuJ1V3ORVORP5l+Hv2N6Sfgh5PQ==}
dependencies:
unws: 0.2.4(ws@8.14.1)
ws: 8.14.1