initial better auth config
This commit is contained in:
16
apps/web/src/app.d.ts
vendored
16
apps/web/src/app.d.ts
vendored
@@ -1,13 +1,7 @@
|
||||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
namespace App {
|
||||
interface Locals {
|
||||
token: string | undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Handle } from "@sveltejs/kit";
|
||||
|
||||
// Middleware desabilitado - proteção de rotas feita no lado do cliente
|
||||
// para compatibilidade com localStorage do authStore
|
||||
import { getToken } from "@mmailaender/convex-better-auth-svelte/sveltekit";
|
||||
import { createAuth } from "@sgse-app/backend/convex/auth";
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
event.locals.token = await getToken(createAuth, event.cookies);
|
||||
|
||||
return resolve(event);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
/**
|
||||
* Cliente Better Auth para frontend SvelteKit
|
||||
*
|
||||
*
|
||||
* Configurado para trabalhar com Convex via plugin convexClient.
|
||||
* Este cliente será usado para autenticação quando Better Auth estiver ativo.
|
||||
*/
|
||||
|
||||
import { createAuthClient } from "better-auth/svelte";
|
||||
import { convexClient } from "@convex-dev/better-auth/client/plugins";
|
||||
|
||||
export const authClient = createAuthClient({
|
||||
// Base URL da API Better Auth (mesma do app)
|
||||
baseURL: typeof window !== "undefined"
|
||||
? window.location.origin // Usar origem atual em produção
|
||||
: "http://localhost:5173", // Fallback para desenvolvimento
|
||||
plugins: [
|
||||
// Plugin Convex integra Better Auth com Convex backend
|
||||
convexClient({
|
||||
convexUrl: import.meta.env.PUBLIC_CONVEX_URL || "",
|
||||
}),
|
||||
],
|
||||
plugins: [convexClient()],
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user