UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

179 lines (156 loc) • 6.12 kB
import type { AdapterAuthenticator, AdapterSession, AdapterUser, VerificationToken, } from '@auth/core/adapters'; import debug from 'debug'; import { Adapter, AdapterAccount } from 'next-auth/adapters'; import urlJoin from 'url-join'; import { serverDBEnv } from '@/config/db'; import { appEnv } from '@/envs/app'; const log = debug('lobe-next-auth:adapter'); interface BackendAdapterResponse { data?: any; error?: string; success: boolean; } // Due to use direct HTTP Post, the date string cannot parse automatically export const dateKeys = ['expires', 'emailVerified']; /** * @description LobeNextAuthDbAdapter is implemented to handle the database operations * for NextAuth, this function do the same things as `src/app/api/webhooks/clerk/route.ts` * @returns {Adapter} */ export function LobeNextAuthDbAdapter(): Adapter { const baseUrl = appEnv.APP_URL; // Ensure the baseUrl is set, otherwise throw an error if (!baseUrl) { throw new Error('LobeNextAuthDbAdapter: APP_URL is not set in environment variables'); } const interactionUrl = urlJoin(baseUrl, '/api/auth/adapter'); log(`LobeNextAuthDbAdapter initialized with url: ${interactionUrl}`); // Ensure serverDBEnv.KEY_VAULTS_SECRET is set, otherwise throw an error if (!serverDBEnv.KEY_VAULTS_SECRET) { throw new Error('LobeNextAuthDbAdapter: KEY_VAULTS_SECRET is not set in environment variables'); } const fetcher = (action: string, data: any) => fetch(interactionUrl, { body: JSON.stringify({ action, data }), headers: { 'Authorization': `Bearer ${serverDBEnv.KEY_VAULTS_SECRET}`, 'Content-Type': 'application/json', }, method: 'POST', }); const postProcessor = async (res: Response) => { const data = (await res.json()) as BackendAdapterResponse; log('LobeNextAuthDbAdapter: postProcessor called with data:', data); if (!data.success) { log('LobeNextAuthDbAdapter: Error in postProcessor:'); log(data); throw new Error(`LobeNextAuthDbAdapter: ${data.error}`); } if (data?.data) { for (const key of dateKeys) { if (data.data[key]) { data.data[key] = new Date(data.data[key]); continue; } } } return data.data; }; return { async createAuthenticator(authenticator): Promise<AdapterAuthenticator> { const data = await fetcher('createAuthenticator', authenticator); return await postProcessor(data); }, async createSession(session): Promise<AdapterSession> { const data = await fetcher('createSession', session); return await postProcessor(data); }, async createUser(user): Promise<AdapterUser> { const data = await fetcher('createUser', user); return await postProcessor(data); }, async createVerificationToken(data): Promise<VerificationToken | null | undefined> { const result = await fetcher('createVerificationToken', data); return await postProcessor(result); }, async deleteSession(sessionToken): Promise<AdapterSession | null | undefined> { const result = await fetcher('deleteSession', sessionToken); await postProcessor(result); return; }, async deleteUser(id): Promise<AdapterUser | null | undefined> { const result = await fetcher('deleteUser', id); await postProcessor(result); return; }, async getAccount(providerAccountId, provider): Promise<AdapterAccount | null> { const data = await fetcher('getAccount', { provider, providerAccountId, }); return await postProcessor(data); }, async getAuthenticator(credentialID): Promise<AdapterAuthenticator | null> { const result = await fetcher('getAuthenticator', credentialID); return await postProcessor(result); }, async getSessionAndUser(sessionToken): Promise<{ session: AdapterSession; user: AdapterUser; } | null> { const result = await fetcher('getSessionAndUser', sessionToken); return await postProcessor(result); }, async getUser(id): Promise<AdapterUser | null> { log('getUser called with id:', id); const result = await fetcher('getUser', id); return await postProcessor(result); }, async getUserByAccount(account): Promise<AdapterUser | null> { const data = await fetcher('getUserByAccount', account); return await postProcessor(data); }, async getUserByEmail(email): Promise<AdapterUser | null> { const data = await fetcher('getUserByEmail', email); return await postProcessor(data); }, async linkAccount(data): Promise<AdapterAccount | null | undefined> { const result = await fetcher('linkAccount', data); return await postProcessor(result); }, async listAuthenticatorsByUserId(userId): Promise<AdapterAuthenticator[]> { const result = await fetcher('listAuthenticatorsByUserId', userId); return await postProcessor(result); }, // @ts-ignore: The return type is {Promise<void> | Awaitable<AdapterAccount | undefined>} async unlinkAccount(account): Promise<void | AdapterAccount | undefined> { const result = await fetcher('unlinkAccount', account); await postProcessor(result); return; }, async updateAuthenticatorCounter(credentialID, counter): Promise<AdapterAuthenticator> { const result = await fetcher('updateAuthenticatorCounter', { counter, credentialID, }); return await postProcessor(result); }, async updateSession(data): Promise<AdapterSession | null | undefined> { const result = await fetcher('updateSession', data); return await postProcessor(result); }, async updateUser(user): Promise<AdapterUser> { const result = await fetcher('updateUser', user); return await postProcessor(result); }, async useVerificationToken(identifier_token): Promise<VerificationToken | null> { const result = await fetcher('useVerificationToken', identifier_token); return await postProcessor(result); }, }; }