export function loadConfig(environment = process.env) { const publicOrigin = required(environment, 'REMORA_WEB_PUBLIC_ORIGIN') const apiUpstream = required(environment, 'REMORA_WEB_API_UPSTREAM') const oidcAuthority = required(environment, 'REMORA_WEB_OIDC_AUTHORITY') return { root: environment.REMORA_WEB_ROOT || '/app/dist', port: port(environment.REMORA_WEB_PORT || '8080'), publicOrigin: new URL(publicOrigin).origin, apiUpstream: trailingSlash(new URL(apiUpstream)), eventsUpstream: webSocketUrl( environment.REMORA_WEB_EVENTS_UPSTREAM || new URL('events', trailingSlash(new URL(apiUpstream))).toString(), ), oidcAuthority: oidcAuthority.replace(/\/$/, ''), oidcClientId: required(environment, 'REMORA_WEB_OIDC_CLIENT_ID'), oidcClientSecret: required(environment, 'REMORA_WEB_OIDC_CLIENT_SECRET'), oidcScope: environment.REMORA_WEB_OIDC_SCOPE || 'openid profile', sessionUrl: required(environment, 'REMORA_WEB_SESSION_URL'), sessionNamespace: environment.REMORA_WEB_SESSION_NAMESPACE || 'remora:web-session:', sessionTtlSeconds: positiveInteger( environment.REMORA_WEB_SESSION_TTL_SECONDS || '28800', 'REMORA_WEB_SESSION_TTL_SECONDS', ), secureCookie: true, } } function required(environment, name) { const value = environment[name] if (value === undefined || value === '') throw new Error(`${name} is required`) return value } function port(value) { const parsed = positiveInteger(value, 'REMORA_WEB_PORT') if (parsed > 65535) throw new Error('REMORA_WEB_PORT must be a valid port') return parsed } function positiveInteger(value, name) { const parsed = Number(value) if (!Number.isSafeInteger(parsed) || parsed < 1) throw new Error(`${name} must be a positive integer`) return parsed } function trailingSlash(url) { if (!url.pathname.endsWith('/')) url.pathname += '/' return url } function webSocketUrl(value) { const url = new URL(value) if (url.protocol === 'http:') url.protocol = 'ws:' else if (url.protocol === 'https:') url.protocol = 'wss:' if (url.protocol !== 'ws:' && url.protocol !== 'wss:') throw new Error('REMORA_WEB_EVENTS_UPSTREAM must use HTTP or WebSocket') return url }