Created
December 20, 2023 15:24
-
-
Save notrab/40a06d279d0794083f920dbf14584698 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import NextAuth, { type NextAuthConfig } from "next-auth"; | |
| import GitHub from "next-auth/providers/github"; | |
| import type { | |
| Adapter, | |
| AdapterAccount, | |
| AdapterSession, | |
| AdapterUser, | |
| VerificationToken as AdapterVerificationToken, | |
| } from "@auth/core/adapters"; | |
| import { createClient, type Client as TursoClient } from "@libsql/client"; | |
| import { v4 as uuidv4 } from "uuid"; | |
| const client = createClient({ | |
| url: process.env.LIBSQL_URL!, | |
| authToken: process.env.LIBSQL_AUTH_TOKEN!, | |
| }); | |
| function isDate(date: any) { | |
| return ( | |
| new Date(date).toString() !== "Invalid Date" && !isNaN(Date.parse(date)) | |
| ); | |
| } | |
| function TursoAdapter(client: TursoClient): Adapter { | |
| return { | |
| async createUser(user) { | |
| console.log({ user }); | |
| const userId = uuidv4(); | |
| const result = await client.execute({ | |
| sql: "INSERT INTO users (id, name, email, emailVerified, image) VALUES (?, ?, ?, ?, ?)", | |
| args: [ | |
| userId, | |
| user.name ?? null, | |
| user.email, | |
| user.emailVerified?.toISOString() ?? null, | |
| user.image ?? null, | |
| ], | |
| }); | |
| console.log(JSON.stringify({ result }, null, 2)); | |
| const { rows } = await client.execute({ | |
| sql: "SELECT * FROM users WHERE id = ?", | |
| args: [userId], | |
| }); | |
| return rows?.[0]; | |
| }, | |
| async getUser(id) { | |
| const { rows } = await client.execute({ | |
| sql: "SELECT * FROM users WHERE id = ?", | |
| args: [id], | |
| }); | |
| return rows?.[0]; | |
| }, | |
| async getUserByEmail(email) { | |
| const { rows } = await client.execute({ | |
| sql: "SELECT * FROM users WHERE email = ?", | |
| args: [email], | |
| }); | |
| return rows?.[0]; | |
| }, | |
| async getUserByAccount(providerAccountId) { | |
| const { rows } = await client.execute({ | |
| sql: "SELECT u.* FROM users u JOIN accounts a ON a.userId = u.id WHERE a.providerAccountId = ? AND a.provider = ?", | |
| args: [providerAccountId.providerAccountId, providerAccountId.provider], | |
| }); | |
| return rows?.[0]; | |
| }, | |
| async updateUser(user) { | |
| const { rows } = await client.execute({ | |
| sql: "UPDATE users SET name = ?, email = ?, emailVerified = ?, image = ? WHERE id = ?", | |
| args: [ | |
| user.name!, | |
| user.email!, | |
| user.emailVerified!, | |
| user.image!, | |
| user.id, | |
| ], | |
| }); | |
| return rows?.[0]; | |
| }, | |
| async deleteUser(userId) { | |
| await client.batch([ | |
| { | |
| sql: "DELETE FROM accounts WHERE userId = ?", | |
| args: [userId], | |
| }, | |
| { | |
| sql: "DELETE FROM sessions WHERE userId = ?", | |
| args: [userId], | |
| }, | |
| { | |
| sql: "DELETE FROM users WHERE id = ?", | |
| args: [userId], | |
| }, | |
| ]); | |
| return null; | |
| }, | |
| async linkAccount(account) { | |
| console.log({ account }); | |
| try { | |
| const { rows } = await client.execute({ | |
| sql: "INSERT INTO accounts (id, userId, type, provider, providerAccountId, refresh_token, access_token, expires_at, token_type, scope, id_token, session_state, oauth_token, oauth_token_secret) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", | |
| args: [ | |
| uuidv4(), | |
| account.userId, | |
| account.type, | |
| account.provider, | |
| account.providerAccountId, | |
| account.refresh_token ?? null, | |
| account.access_token ?? null, | |
| account.expires_at ?? null, | |
| account.token_type ?? null, | |
| account.scope ?? null, | |
| account.id_token ?? null, | |
| account.session_state ?? null, | |
| account.oauth_token ?? null, | |
| account.oauth_token_secret ?? null, | |
| ], | |
| }); | |
| return rows?.[0]; | |
| } catch (err) { | |
| console.log("oops", err); | |
| return null; | |
| } | |
| }, | |
| async unlinkAccount(providerAccountId) { | |
| throw new Error("unlinkAccount Not implemented"); | |
| }, | |
| async createSession(session) { | |
| const sessionId = uuidv4(); | |
| console.log({ expires: session.expires.toISOString() }); | |
| await client.execute({ | |
| sql: "INSERT INTO sessions (id, sessionToken, userId, expires) VALUES (?,?,?,?)", | |
| args: [ | |
| sessionId, | |
| session.sessionToken, | |
| session.userId, | |
| session.expires.toISOString(), | |
| ], | |
| }); | |
| const { rows } = await client.execute({ | |
| sql: "SELECT * FROM sessions WHERE id = ?", | |
| args: [sessionId], | |
| }); | |
| const { expires, ...sesh } = rows?.[0]; | |
| return { | |
| ...sesh, | |
| expires: isDate(expires) ? new Date(expires) : expires, | |
| }; | |
| }, | |
| async deleteSession(sessionToken) { | |
| await client.execute({ | |
| sql: "DELETE FROM sessions WHERE sessionToken = ?", | |
| args: [sessionToken], | |
| }); | |
| return null; | |
| }, | |
| async getSessionAndUser(sessionToken) { | |
| const sessionResult = await client.execute({ | |
| sql: "SELECT id, sessionToken, userId, expires FROM sessions WHERE sessionToken = ?", | |
| args: [sessionToken], | |
| }); | |
| const userResult = await client.execute({ | |
| sql: "SELECT * FROM users WHERE id = ?", | |
| args: [sessionResult?.rows?.[0]?.userId], | |
| }); | |
| return { | |
| session: { | |
| ...sessionResult.rows[0], | |
| expires: isDate(sessionResult.rows[0].expires) | |
| ? new Date(sessionResult.rows[0].expires) | |
| : sessionResult.rows[0].expires, | |
| }, | |
| user: userResult.rows[0], | |
| }; | |
| }, | |
| async updateSession(session) { | |
| throw new Error("updateSession Not implemented"); | |
| }, | |
| async createVerificationToken(verificationToken) { | |
| throw new Error("createVerificationToken Not implemented"); | |
| }, | |
| async useVerificationToken(params) { | |
| throw new Error("useVerificationToken Not implemented"); | |
| }, | |
| }; | |
| } | |
| export const config = { | |
| providers: [GitHub], | |
| adapter: TursoAdapter(client), | |
| callbacks: {}, | |
| // debug: true, | |
| } satisfies NextAuthConfig; | |
| export const { handlers, auth, signIn, signOut } = NextAuth(config); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment