import { createClient, type GenericCtx } from '@convex-dev/better-auth'; import { convex } from '@convex-dev/better-auth/plugins'; import { betterAuth } from 'better-auth'; import { components } from './_generated/api'; import type { DataModel } from './_generated/dataModel'; import { type MutationCtx, type QueryCtx, query } from './_generated/server'; // Usar SITE_URL se disponível, caso contrário usar CONVEX_SITE_URL ou um valor padrão const siteUrl = process.env.SITE_URL || process.env.CONVEX_SITE_URL || 'http://localhost:5173'; console.log('siteUrl:', siteUrl); // The component client has methods needed for integrating Convex with Better Auth, // as well as helper methods for general use. export const authComponent = createClient(components.betterAuth); export const createAuth = ( ctx: GenericCtx, { optionsOnly } = { optionsOnly: false } ) => { return betterAuth({ // disable logging when createAuth is called just to generate options. // this is not required, but there's a lot of noise in logs without it. logger: { disabled: optionsOnly }, trustedOrigins: ['https://vite.kilder.dev'], baseURL: siteUrl, database: authComponent.adapter(ctx), // Configure simple, non-verified email/password to get started emailAndPassword: { enabled: true, requireEmailVerification: false }, plugins: [ // The Convex plugin is required for Convex compatibility convex() ] }); }; // Example function for getting the current user // Feel free to edit, omit, etc. export const getCurrentUser = query({ args: {}, handler: async (ctx) => { try { const authUser = await authComponent.safeGetAuthUser(ctx); if (!authUser) { return; } const user = await ctx.db .query('usuarios') .withIndex('authId', (q) => q.eq('authId', authUser._id)) .unique(); if (!user) { return; } // Buscar foto de perfil e role em paralelo para melhor performance const [fotoPerfilUrl, role] = await Promise.all([ user.fotoPerfil ? ctx.storage.getUrl(user.fotoPerfil).catch(() => null) : Promise.resolve(null), user.roleId ? ctx.db .query('roles') .withIndex('by_id', (q) => q.eq('_id', user.roleId)) .unique() .catch(() => null) : Promise.resolve(null) ]); return { ...user, role: role || null, fotoPerfilUrl }; } catch (error) { // Log do erro mas não falhar completamente - retornar null para permitir retry console.error('Erro ao buscar usuário atual:', error); return; } } }); export const getCurrentUserFunction = async (ctx: QueryCtx | MutationCtx) => { const authUser = await authComponent.safeGetAuthUser(ctx); if (!authUser) { return; } const user = await ctx.db .query('usuarios') .withIndex('authId', (q) => q.eq('authId', authUser._id)) .unique(); if (!user) { return; } return user; }; export const createAuthUser = async ( ctx: MutationCtx, args: { nome: string; email: string; password: string } ) => { const { auth, headers } = await authComponent.getAuth(createAuth, ctx); const result = await auth.api.signUpEmail({ headers, body: { name: args.nome, email: args.email, password: args.password } }); return result.user.id; }; export const updatePassword = async ( ctx: MutationCtx, args: { newPassword: string; currentPassword: string } ) => { const { auth, headers } = await authComponent.getAuth(createAuth, ctx); await auth.api.changePassword({ headers, body: { currentPassword: args.currentPassword, newPassword: args.newPassword } }); };