diff --git a/apps/calendar/apps/web/src/lib/api/client.ts b/apps/calendar/apps/web/src/lib/api/client.ts index 91e1fa9d6..3e6a3b7e5 100644 --- a/apps/calendar/apps/web/src/lib/api/client.ts +++ b/apps/calendar/apps/web/src/lib/api/client.ts @@ -1,9 +1,12 @@ /** * API Client for Calendar Backend + * + * Token handling: Uses authStore.getValidToken() which automatically + * refreshes expired tokens before making requests. */ -import { browser } from '$app/environment'; import { env } from '$env/dynamic/public'; +import { authStore } from '$lib/stores/auth.svelte'; const API_BASE = env.PUBLIC_BACKEND_URL || 'http://localhost:3014'; @@ -20,10 +23,8 @@ export async function fetchApi( ): Promise<{ data: T | null; error: Error | null }> { const { method = 'GET', body, token, isFormData = false } = options; - let authToken = token; - if (!authToken && browser) { - authToken = localStorage.getItem('@auth/appToken') || undefined; - } + // Get a valid token (auto-refreshes if expired) + const authToken = token || (await authStore.getValidToken()); try { const headers: Record = {}; diff --git a/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts b/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts index 874675890..9ede84176 100644 --- a/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts @@ -34,6 +34,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -184,7 +191,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -193,4 +201,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/chat/apps/web/src/lib/services/api.ts b/apps/chat/apps/web/src/lib/services/api.ts index 9df7c5ef2..813268b33 100644 --- a/apps/chat/apps/web/src/lib/services/api.ts +++ b/apps/chat/apps/web/src/lib/services/api.ts @@ -3,10 +3,13 @@ * * This replaces direct Supabase calls with backend API calls. * All database operations now go through the NestJS backend. + * + * Token handling: Uses authStore.getValidToken() which automatically + * refreshes expired tokens before making requests. */ -import { browser } from '$app/environment'; import { env } from '$env/dynamic/public'; +import { authStore } from '$lib/stores/auth.svelte'; import type { Conversation, Message, @@ -46,12 +49,8 @@ async function fetchApi( ): Promise<{ data: T | null; error: Error | null }> { const { method = 'GET', body, token } = options; - // Get token from localStorage if not provided - // Token is stored by @manacore/shared-auth under '@auth/appToken' - let authToken = token; - if (!authToken && browser) { - authToken = localStorage.getItem('@auth/appToken') || undefined; - } + // Get a valid token (auto-refreshes if expired) + const authToken = token || (await authStore.getValidToken()); if (!authToken) { return { data: null, error: new Error('No authentication token') }; diff --git a/apps/chat/apps/web/src/lib/stores/auth.svelte.ts b/apps/chat/apps/web/src/lib/stores/auth.svelte.ts index 6e9647cf3..92064596d 100644 --- a/apps/chat/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/chat/apps/web/src/lib/stores/auth.svelte.ts @@ -34,6 +34,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -202,7 +209,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -211,4 +219,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/clock/apps/web/src/lib/stores/auth.svelte.ts b/apps/clock/apps/web/src/lib/stores/auth.svelte.ts index 6be177cbe..2613ee0b5 100644 --- a/apps/clock/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/clock/apps/web/src/lib/stores/auth.svelte.ts @@ -33,6 +33,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -183,7 +190,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -192,4 +200,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts b/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts index 32acec4fc..3122bf4f1 100644 --- a/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts @@ -25,6 +25,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -175,7 +182,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -184,4 +192,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts b/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts index 617b41d21..703cf974f 100644 --- a/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts @@ -34,6 +34,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -240,7 +247,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -249,4 +257,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts b/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts index dbc47a88f..40107f7ca 100644 --- a/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts @@ -1,5 +1,5 @@ import type { ManaUser } from '$lib/types/auth'; -import { authService } from '$lib/auth'; +import { authService, tokenManager } from '$lib/auth'; import type { UserData } from '$lib/auth'; // Svelte 5 runes-based auth store @@ -109,4 +109,20 @@ export const authStore = { async forgotPassword(email: string) { return authService.forgotPassword(email); }, + + /** + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh + */ + async getAccessToken(): Promise { + return await authService.getAppToken(); + }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/picture/apps/web/src/lib/api/client.ts b/apps/picture/apps/web/src/lib/api/client.ts index 4d6ff07cb..5e15d3754 100644 --- a/apps/picture/apps/web/src/lib/api/client.ts +++ b/apps/picture/apps/web/src/lib/api/client.ts @@ -1,10 +1,13 @@ /** * API Client for Picture Backend * Replaces direct Supabase calls with backend API calls. + * + * Token handling: Uses authStore.getValidToken() which automatically + * refreshes expired tokens before making requests. */ -import { browser } from '$app/environment'; import { env } from '$env/dynamic/public'; +import { authStore } from '$lib/stores/auth.svelte'; const API_BASE = env.PUBLIC_BACKEND_URL || 'http://localhost:3003'; @@ -21,10 +24,8 @@ export async function fetchApi( ): Promise<{ data: T | null; error: Error | null }> { const { method = 'GET', body, token, isFormData = false } = options; - let authToken = token; - if (!authToken && browser) { - authToken = localStorage.getItem('@auth/appToken') || undefined; - } + // Get a valid token (auto-refreshes if expired) + const authToken = token || (await authStore.getValidToken()); try { const headers: Record = {}; @@ -75,10 +76,8 @@ export async function uploadFile( file: File, token?: string ): Promise<{ data: any; error: Error | null }> { - let authToken = token; - if (!authToken && browser) { - authToken = localStorage.getItem('@auth/appToken') || undefined; - } + // Get a valid token (auto-refreshes if expired) + const authToken = token || (await authStore.getValidToken()); try { const formData = new FormData(); @@ -121,10 +120,8 @@ export async function uploadFiles( files: File[], token?: string ): Promise<{ data: any; error: Error | null }> { - let authToken = token; - if (!authToken && browser) { - authToken = localStorage.getItem('@auth/appToken') || undefined; - } + // Get a valid token (auto-refreshes if expired) + const authToken = token || (await authStore.getValidToken()); try { const formData = new FormData(); diff --git a/apps/picture/apps/web/src/lib/stores/auth.svelte.ts b/apps/picture/apps/web/src/lib/stores/auth.svelte.ts index e7823cb85..b9ad5b753 100644 --- a/apps/picture/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/picture/apps/web/src/lib/stores/auth.svelte.ts @@ -39,6 +39,13 @@ async function getAuthService() { return _authService; } +async function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + await getAuthService(); + return _tokenManager; +} + // State using Svelte 5 runes let user = $state(null); let loading = $state(true); @@ -164,12 +171,28 @@ export const authStore = { } }, + /** + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh + */ async getAccessToken(): Promise { const authService = await getAuthService(); if (!authService) return null; return authService.getAppToken(); }, + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = await getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, + // For compatibility with old code that reads user store directly setUser(userData: UserData | null) { user = userData; diff --git a/apps/todo/apps/web/src/lib/stores/auth.svelte.ts b/apps/todo/apps/web/src/lib/stores/auth.svelte.ts index 885a63266..7c3210601 100644 --- a/apps/todo/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/todo/apps/web/src/lib/stores/auth.svelte.ts @@ -34,6 +34,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -199,7 +206,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -208,4 +216,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, }; diff --git a/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts b/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts index 32acec4fc..3122bf4f1 100644 --- a/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts @@ -25,6 +25,13 @@ function getAuthService() { return _authService; } +function getTokenManager() { + if (!browser) return null; + // Ensure auth service is initialized first + getAuthService(); + return _tokenManager; +} + // State let user = $state(null); let loading = $state(true); @@ -175,7 +182,8 @@ export const authStore = { }, /** - * Get access token for API calls + * Get access token for API calls (raw token, no refresh) + * @deprecated Use getValidToken() instead for automatic refresh */ async getAccessToken() { const authService = getAuthService(); @@ -184,4 +192,16 @@ export const authStore = { } return await authService.getAppToken(); }, + + /** + * Get a valid access token for API calls + * Automatically refreshes if the token is expired or about to expire + */ + async getValidToken(): Promise { + const tokenManager = getTokenManager(); + if (!tokenManager) { + return null; + } + return await tokenManager.getValidToken(); + }, };