/** * Single source of truth for app base path. Use instead of hardcoded `/map/`. * All path checks and redirects should use this composable. */ export function useAppPaths() { const config = useRuntimeConfig() const baseURL = (config.app?.baseURL as string) ?? '/' const base = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL /** Path without base prefix, for comparison with route names like 'login', 'setup'. */ function pathWithoutBase(fullPath: string): string { if (!base || base === '/') return fullPath const normalized = fullPath.replace(new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\/?`), '') || '/' return normalized.startsWith('/') ? normalized : `/${normalized}` } /** Full URL for redirects (e.g. window.location.href). */ function fullUrl(relativePath: string): string { if (import.meta.server) return base + (relativePath.startsWith('/') ? relativePath : `/${relativePath}`) const path = relativePath.startsWith('/') ? relativePath.slice(1) : relativePath const withBase = base ? `${base}/${path}` : `/${path}` return `${window.location.origin}${withBase}` } /** Path with base for internal navigation (e.g. navigateTo). Nuxt router uses paths without origin. */ function resolvePath(relativePath: string): string { const path = relativePath.startsWith('/') ? relativePath : `/${relativePath}` return base ? `${base}${path}` : path } /** Whether the path is login page (path without base is /login or ends with /login). */ function isLoginPath(fullPath: string): boolean { const p = pathWithoutBase(fullPath) return p === '/login' || p.endsWith('/login') } /** Whether the path is setup page. */ function isSetupPath(fullPath: string): boolean { const p = pathWithoutBase(fullPath) return p === '/setup' || p.endsWith('/setup') } return { baseURL, base, pathWithoutBase, fullUrl, resolvePath, isLoginPath, isSetupPath, } }