From 3d717eb16a1a8cbb7ec31d685deb954a96f918b4 Mon Sep 17 00:00:00 2001 From: Wuesteon Date: Mon, 8 Dec 2025 20:49:39 +0100 Subject: [PATCH] fix(web): add runtime env injection for auth URLs in todo, calendar, clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All three apps were hardcoding localhost:3001 for auth, which broke staging deployments. Now uses hooks.server.ts to inject the correct PUBLIC_MANA_CORE_AUTH_URL_CLIENT at runtime (same pattern as chat-web). Changes: - Add hooks.server.ts to todo, calendar, clock web apps - Update auth.svelte.ts to use window.__PUBLIC_MANA_CORE_AUTH_URL__ - Update user-settings.svelte.ts to use runtime URL - Fix feedback services to use runtime URL 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/calendar/apps/web/src/hooks.server.ts | 27 +++++++++++++++++++ .../apps/web/src/lib/services/feedback.ts | 14 +++++++--- .../apps/web/src/lib/stores/auth.svelte.ts | 16 ++++++++--- .../src/lib/stores/user-settings.svelte.ts | 13 +++++++-- apps/clock/apps/web/src/hooks.server.ts | 27 +++++++++++++++++++ .../apps/web/src/lib/stores/auth.svelte.ts | 16 ++++++++--- .../src/lib/stores/user-settings.svelte.ts | 13 +++++++-- .../src/routes/(app)/feedback/+page.svelte | 13 ++++++++- apps/todo/apps/web/src/hooks.server.ts | 27 +++++++++++++++++++ .../apps/web/src/lib/stores/auth.svelte.ts | 16 ++++++++--- .../src/lib/stores/user-settings.svelte.ts | 13 +++++++-- 11 files changed, 176 insertions(+), 19 deletions(-) create mode 100644 apps/calendar/apps/web/src/hooks.server.ts create mode 100644 apps/clock/apps/web/src/hooks.server.ts create mode 100644 apps/todo/apps/web/src/hooks.server.ts diff --git a/apps/calendar/apps/web/src/hooks.server.ts b/apps/calendar/apps/web/src/hooks.server.ts new file mode 100644 index 000000000..6d7a5089d --- /dev/null +++ b/apps/calendar/apps/web/src/hooks.server.ts @@ -0,0 +1,27 @@ +/** + * Server Hooks for SvelteKit + * - Injects runtime environment variables for client-side use + * - Auth is handled client-side via Mana Core Auth + */ + +import type { Handle } from '@sveltejs/kit'; + +// Get client-side URLs from environment (Docker runtime) +const PUBLIC_MANA_CORE_AUTH_URL_CLIENT = + process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT || process.env.PUBLIC_MANA_CORE_AUTH_URL || ''; +const PUBLIC_BACKEND_URL_CLIENT = + process.env.PUBLIC_BACKEND_URL_CLIENT || process.env.PUBLIC_BACKEND_URL || ''; + +export const handle: Handle = async ({ event, resolve }) => { + return resolve(event, { + transformPageChunk: ({ html }) => { + // Inject runtime environment variables into the HTML + // These will be available on window.__PUBLIC_*__ for client-side code + const envScript = ``; + return html.replace('', `${envScript}`); + }, + }); +}; diff --git a/apps/calendar/apps/web/src/lib/services/feedback.ts b/apps/calendar/apps/web/src/lib/services/feedback.ts index 5f86dbd7c..de6a8a6d0 100644 --- a/apps/calendar/apps/web/src/lib/services/feedback.ts +++ b/apps/calendar/apps/web/src/lib/services/feedback.ts @@ -2,14 +2,22 @@ * Feedback Service Instance for Calendar Web App */ +import { browser } from '$app/environment'; import { createFeedbackService } from '@manacore/shared-feedback-service'; import { authStore } from '$lib/stores/auth.svelte'; -import { PUBLIC_MANA_CORE_AUTH_URL } from '$env/static/public'; -const MANA_AUTH_URL = PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001'; +// Get auth URL dynamically at runtime +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + return 'http://localhost:3001'; +} export const feedbackService = createFeedbackService({ - apiUrl: MANA_AUTH_URL, + apiUrl: getAuthUrl(), appId: 'calendar', getAuthToken: async () => authStore.getAccessToken(), }); 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 da5eceae2..874675890 100644 --- a/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts @@ -7,8 +7,18 @@ import { browser } from '$app/environment'; import { initializeWebAuth } from '@manacore/shared-auth'; import type { UserData } from '@manacore/shared-auth'; -// Initialize Mana Core Auth only on the client side -const MANA_AUTH_URL = 'http://localhost:3001'; +// Get auth URL dynamically at runtime - fallback for SSR and client +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + // Client-side: use injected window variable (set by hooks.server.ts) + // Falls back to localhost for local development + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + // Server-side (SSR): use Docker internal URL for container-to-container communication + return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001'; +} // Lazy initialization to avoid SSR issues with localStorage let _authService: ReturnType['authService'] | null = null; @@ -17,7 +27,7 @@ let _tokenManager: ReturnType['tokenManager'] | null = function getAuthService() { if (!browser) return null; if (!_authService) { - const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL }); + const auth = initializeWebAuth({ baseUrl: getAuthUrl() }); _authService = auth.authService; _tokenManager = auth.tokenManager; } diff --git a/apps/calendar/apps/web/src/lib/stores/user-settings.svelte.ts b/apps/calendar/apps/web/src/lib/stores/user-settings.svelte.ts index 6cc7b62ed..a2e5e08b7 100644 --- a/apps/calendar/apps/web/src/lib/stores/user-settings.svelte.ts +++ b/apps/calendar/apps/web/src/lib/stores/user-settings.svelte.ts @@ -7,13 +7,22 @@ * - localStorage caching for offline support */ +import { browser } from '$app/environment'; import { createUserSettingsStore } from '@manacore/shared-theme'; import { authStore } from './auth.svelte'; -const MANA_AUTH_URL = 'http://localhost:3001'; +// Get auth URL dynamically at runtime +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + return 'http://localhost:3001'; +} export const userSettings = createUserSettingsStore({ appId: 'calendar', - authUrl: MANA_AUTH_URL, + authUrl: getAuthUrl(), getAccessToken: () => authStore.getAccessToken(), }); diff --git a/apps/clock/apps/web/src/hooks.server.ts b/apps/clock/apps/web/src/hooks.server.ts new file mode 100644 index 000000000..6d7a5089d --- /dev/null +++ b/apps/clock/apps/web/src/hooks.server.ts @@ -0,0 +1,27 @@ +/** + * Server Hooks for SvelteKit + * - Injects runtime environment variables for client-side use + * - Auth is handled client-side via Mana Core Auth + */ + +import type { Handle } from '@sveltejs/kit'; + +// Get client-side URLs from environment (Docker runtime) +const PUBLIC_MANA_CORE_AUTH_URL_CLIENT = + process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT || process.env.PUBLIC_MANA_CORE_AUTH_URL || ''; +const PUBLIC_BACKEND_URL_CLIENT = + process.env.PUBLIC_BACKEND_URL_CLIENT || process.env.PUBLIC_BACKEND_URL || ''; + +export const handle: Handle = async ({ event, resolve }) => { + return resolve(event, { + transformPageChunk: ({ html }) => { + // Inject runtime environment variables into the HTML + // These will be available on window.__PUBLIC_*__ for client-side code + const envScript = ``; + return html.replace('', `${envScript}`); + }, + }); +}; 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 555153459..6be177cbe 100644 --- a/apps/clock/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/clock/apps/web/src/lib/stores/auth.svelte.ts @@ -6,8 +6,18 @@ import { browser } from '$app/environment'; import { initializeWebAuth, type UserData } from '@manacore/shared-auth'; -// Initialize Mana Core Auth only on the client side -const MANA_AUTH_URL = 'http://localhost:3001'; +// Get auth URL dynamically at runtime - fallback for SSR and client +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + // Client-side: use injected window variable (set by hooks.server.ts) + // Falls back to localhost for local development + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + // Server-side (SSR): use Docker internal URL for container-to-container communication + return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001'; +} // Lazy initialization to avoid SSR issues with localStorage let _authService: ReturnType['authService'] | null = null; @@ -16,7 +26,7 @@ let _tokenManager: ReturnType['tokenManager'] | null = function getAuthService() { if (!browser) return null; if (!_authService) { - const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL }); + const auth = initializeWebAuth({ baseUrl: getAuthUrl() }); _authService = auth.authService; _tokenManager = auth.tokenManager; } diff --git a/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts b/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts index 3b9727cdc..f88fb5453 100644 --- a/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts +++ b/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts @@ -7,13 +7,22 @@ * - localStorage caching for offline support */ +import { browser } from '$app/environment'; import { createUserSettingsStore } from '@manacore/shared-theme'; import { authStore } from './auth.svelte'; -const MANA_AUTH_URL = 'http://localhost:3001'; +// Get auth URL dynamically at runtime +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + return 'http://localhost:3001'; +} export const userSettings = createUserSettingsStore({ appId: 'clock', - authUrl: MANA_AUTH_URL, + authUrl: getAuthUrl(), getAccessToken: () => authStore.getAccessToken(), }); diff --git a/apps/clock/apps/web/src/routes/(app)/feedback/+page.svelte b/apps/clock/apps/web/src/routes/(app)/feedback/+page.svelte index 1a2521e87..1d3c8d9c2 100644 --- a/apps/clock/apps/web/src/routes/(app)/feedback/+page.svelte +++ b/apps/clock/apps/web/src/routes/(app)/feedback/+page.svelte @@ -1,12 +1,23 @@ `; + return html.replace('', `${envScript}`); + }, + }); +}; 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 1d2fd96d9..885a63266 100644 --- a/apps/todo/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/todo/apps/web/src/lib/stores/auth.svelte.ts @@ -7,8 +7,18 @@ import { browser } from '$app/environment'; import { initializeWebAuth, type UserData } from '@manacore/shared-auth'; import { apiClient } from '$lib/api/client'; -// Initialize Mana Core Auth only on the client side -const MANA_AUTH_URL = 'http://localhost:3001'; +// Get auth URL dynamically at runtime - fallback for SSR and client +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + // Client-side: use injected window variable (set by hooks.server.ts) + // Falls back to localhost for local development + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + // Server-side (SSR): use Docker internal URL for container-to-container communication + return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001'; +} // Lazy initialization to avoid SSR issues with localStorage let _authService: ReturnType['authService'] | null = null; @@ -17,7 +27,7 @@ let _tokenManager: ReturnType['tokenManager'] | null = function getAuthService() { if (!browser) return null; if (!_authService) { - const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL }); + const auth = initializeWebAuth({ baseUrl: getAuthUrl() }); _authService = auth.authService; _tokenManager = auth.tokenManager; } diff --git a/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts b/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts index 18af057b7..536074626 100644 --- a/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts +++ b/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts @@ -1,10 +1,19 @@ +import { browser } from '$app/environment'; import { createUserSettingsStore } from '@manacore/shared-theme'; import { authStore } from './auth.svelte'; -const MANA_AUTH_URL = import.meta.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001'; +// Get auth URL dynamically at runtime +function getAuthUrl(): string { + if (browser && typeof window !== 'undefined') { + const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string }) + .__PUBLIC_MANA_CORE_AUTH_URL__; + return injectedUrl || 'http://localhost:3001'; + } + return 'http://localhost:3001'; +} export const userSettings = createUserSettingsStore({ appId: 'todo', - authUrl: MANA_AUTH_URL, + authUrl: getAuthUrl(), getAccessToken: () => authStore.getAccessToken(), });