initial better auth config

This commit is contained in:
2025-11-06 11:42:48 -03:00
parent ffeab9cace
commit ca51839082
20 changed files with 1629 additions and 1365 deletions

View File

@@ -1,117 +1,118 @@
<script lang="ts">
import "../app.css";
import Sidebar from "$lib/components/Sidebar.svelte";
import { PUBLIC_CONVEX_URL } from "$env/static/public";
import { setupConvex } from "convex-svelte";
import { authStore } from "$lib/stores/auth.svelte";
import { browser } from "$app/environment";
// import { PUBLIC_CONVEX_URL } from "$env/static/public";
// import { setupConvex } from "convex-svelte";
// import { authStore } from "$lib/stores/auth.svelte";
// import { browser } from "$app/environment";
import { createSvelteAuthClient } from "@mmailaender/convex-better-auth-svelte/svelte";
import { authClient } from "$lib/auth";
const { children } = $props();
// Interfaces TypeScript devem estar no nível superior
interface ConvexHttpClientPrototype {
_authPatched?: boolean;
mutation?: (...args: unknown[]) => Promise<unknown>;
query?: (...args: unknown[]) => Promise<unknown>;
setAuth?: (token: string) => void;
}
interface WindowWithConvexClients extends Window {
__convexClients?: Array<{ setAuth?: (token: string) => void }>;
}
// interface ConvexHttpClientPrototype {
// _authPatched?: boolean;
// mutation?: (...args: unknown[]) => Promise<unknown>;
// query?: (...args: unknown[]) => Promise<unknown>;
// setAuth?: (token: string) => void;
// }
// interface WindowWithConvexClients extends Window {
// __convexClients?: Array<{ setAuth?: (token: string) => void }>;
// }
// Configurar Convex
setupConvex(PUBLIC_CONVEX_URL);
createSvelteAuthClient({ authClient });
// setupConvex(PUBLIC_CONVEX_URL);
// CORREÇÃO CRÍTICA: Configurar token no cliente Convex após setup
// O convex-svelte usa WebSocket, então precisamos configurar via setAuth
if (browser) {
// Aguardar setupConvex inicializar e então configurar token
$effect(() => {
const token = authStore.token;
if (!token) return;
// Aguardar um pouco para garantir que setupConvex inicializou
setTimeout(() => {
// Tentar acessar o cliente Convex interno do convex-svelte
// O convex-svelte pode usar uma instância interna, então vamos tentar várias abordagens
// Abordagem 1: Interceptar WebSocket para adicionar token como query param
const originalWebSocket = window.WebSocket;
if (!(window as { _convexWsPatched?: boolean })._convexWsPatched) {
window.WebSocket = class extends originalWebSocket {
constructor(url: string | URL, protocols?: string | string[]) {
const wsUrl = typeof url === 'string' ? url : url.href;
// Se for conexão Convex e tivermos token, adicionar como query param
if ((wsUrl.includes(PUBLIC_CONVEX_URL) || wsUrl.includes('convex.cloud')) && token) {
try {
const urlObj = new URL(wsUrl);
if (!urlObj.searchParams.has('authToken')) {
urlObj.searchParams.set('authToken', token);
super(urlObj.href, protocols);
if (import.meta.env.DEV) {
console.log("✅ [Convex Auth] Token adicionado ao WebSocket:", token.substring(0, 20) + "...");
}
return;
}
} catch (e) {
// Se falhar, usar URL original
}
}
super(url, protocols);
}
} as typeof WebSocket;
(window as { _convexWsPatched?: boolean })._convexWsPatched = true;
console.log("✅ [Convex Auth] Interceptador WebSocket configurado");
}
// Abordagem 2: Interceptar fetch para requisições HTTP (fallback)
const originalFetch = window.fetch;
if (!(window as { _convexFetchPatched?: boolean })._convexFetchPatched) {
window.fetch = function(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
const currentToken = authStore.token;
if (currentToken && (url.includes(PUBLIC_CONVEX_URL) || url.includes('convex.cloud'))) {
const headers = new Headers(init?.headers);
if (!headers.has('authorization')) {
headers.set('authorization', `Bearer ${currentToken}`);
}
return originalFetch(input, {
...init,
headers: headers,
});
}
return originalFetch(input, init);
};
(window as { _convexFetchPatched?: boolean })._convexFetchPatched = true;
console.log("✅ [Convex Auth] Interceptador Fetch configurado");
}
}, 300);
});
}
// if (browser) {
// // Aguardar setupConvex inicializar e então configurar token
// $effect(() => {
// const token = authStore.token;
// if (!token) return;
// // Aguardar um pouco para garantir que setupConvex inicializou
// setTimeout(() => {
// // Tentar acessar o cliente Convex interno do convex-svelte
// // O convex-svelte pode usar uma instância interna, então vamos tentar várias abordagens
// // Abordagem 1: Interceptar WebSocket para adicionar token como query param
// const originalWebSocket = window.WebSocket;
// if (!(window as { _convexWsPatched?: boolean })._convexWsPatched) {
// window.WebSocket = class extends originalWebSocket {
// constructor(url: string | URL, protocols?: string | string[]) {
// const wsUrl = typeof url === 'string' ? url : url.href;
// // Se for conexão Convex e tivermos token, adicionar como query param
// if ((wsUrl.includes(PUBLIC_CONVEX_URL) || wsUrl.includes('convex.cloud')) && token) {
// try {
// const urlObj = new URL(wsUrl);
// if (!urlObj.searchParams.has('authToken')) {
// urlObj.searchParams.set('authToken', token);
// super(urlObj.href, protocols);
// if (import.meta.env.DEV) {
// console.log("✅ [Convex Auth] Token adicionado ao WebSocket:", token.substring(0, 20) + "...");
// }
// return;
// }
// } catch (e) {
// // Se falhar, usar URL original
// }
// }
// super(url, protocols);
// }
// } as typeof WebSocket;
// (window as { _convexWsPatched?: boolean })._convexWsPatched = true;
// console.log("✅ [Convex Auth] Interceptador WebSocket configurado");
// }
// // Abordagem 2: Interceptar fetch para requisições HTTP (fallback)
// const originalFetch = window.fetch;
// if (!(window as { _convexFetchPatched?: boolean })._convexFetchPatched) {
// window.fetch = function(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
// const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
// const currentToken = authStore.token;
// if (currentToken && (url.includes(PUBLIC_CONVEX_URL) || url.includes('convex.cloud'))) {
// const headers = new Headers(init?.headers);
// if (!headers.has('authorization')) {
// headers.set('authorization', `Bearer ${currentToken}`);
// }
// return originalFetch(input, {
// ...init,
// headers: headers,
// });
// }
// return originalFetch(input, init);
// };
// (window as { _convexFetchPatched?: boolean })._convexFetchPatched = true;
// console.log("✅ [Convex Auth] Interceptador Fetch configurado");
// }
// }, 300);
// });
// }
// FASE 4: Integração Better Auth com Convex
// Better Auth agora está configurado e ativo
// Usar $effect para garantir que seja executado apenas no cliente
if (browser) {
$effect(() => {
try {
createSvelteAuthClient({ authClient });
} catch (error) {
console.warn("⚠️ [Better Auth] Erro ao inicializar cliente:", error);
}
});
}
// if (browser) {
// $effect(() => {
// try {
// createSvelteAuthClient({ authClient });
// } catch (error) {
// console.warn("⚠️ [Better Auth] Erro ao inicializar cliente:", error);
// }
// });
// }
</script>
<div>