import { mkdir } from 'fs/promises' import { existsSync } from 'fs' import { join } from 'path' import { keycloakClient } from '~/server/utils/keycloak-client' let isAppReady = false export default defineNitroPlugin(async (nitroApp) => { console.log('[STARTUP] Server-side initialization starting...') try { // Ensure data directories exist const dataDir = './data' const oidcSessionsDir = './data/oidc-sessions' const sessionsDir = './data/sessions' console.log('[STARTUP] Checking storage directories...') // Create directories if they don't exist const dirs = [dataDir, oidcSessionsDir, sessionsDir] for (const dir of dirs) { if (!existsSync(dir)) { console.log(`[STARTUP] Creating directory: ${dir}`) await mkdir(dir, { recursive: true }) console.log(`[STARTUP] Successfully created: ${dir}`) } else { console.log(`[STARTUP] Directory exists: ${dir}`) } } // Check environment variables console.log('[STARTUP] Checking authentication environment variables...') const requiredEnvVars = [ 'KEYCLOAK_CLIENT_SECRET', 'COOKIE_DOMAIN' ] let envVarsOk = true for (const envVar of requiredEnvVars) { const value = process.env[envVar] if (value) { console.log(`[STARTUP] ✅ ${envVar}: present (length: ${value.length})`) } else { console.error(`[STARTUP] ❌ ${envVar}: MISSING`) envVarsOk = false } } if (!envVarsOk) { console.error('[STARTUP] ❌ Required environment variables missing - authentication may fail') } // Warm up Keycloak connections console.log('[STARTUP] Warming up Keycloak connections...') try { // Test the circuit breaker status endpoint (doesn't require auth) const circuitStatus = keycloakClient.getCircuitBreakerStatus() console.log('[STARTUP] ✅ Keycloak client initialized:', circuitStatus) // Optionally test connectivity (uncomment if needed) // const testUrl = 'https://auth.portnimara.dev/realms/client-portal/.well-known/openid-configuration' // await keycloakClient.fetch(testUrl, {}, { timeout: 5000, retries: 1 }) // console.log('[STARTUP] ✅ Keycloak connectivity verified') } catch (error) { console.error('[STARTUP] ⚠️ Keycloak warmup failed:', error) // Continue anyway - circuit breaker will handle runtime failures } // Mark app as ready isAppReady = true console.log('[STARTUP] ✅ Server-side initialization complete - app ready') } catch (error) { console.error('[STARTUP] ❌ Server-side initialization error:', error) // Don't throw - let the app continue with fallback behavior isAppReady = true // Allow app to start even with initialization errors } }) // Export readiness check for health endpoint export const getAppReadiness = () => ({ ready: isAppReady, keycloakCircuitBreaker: keycloakClient.getCircuitBreakerStatus() })