/** * Mount-aware path helpers (pure). Pass `appBasePath` from packageContext (Worker) * or `document.documentElement.dataset.appBase` (browser) — never import kody:runtime here. */ export type AppRoutes = ReturnType export function createRoutes(appBasePath = '') { const base = String(appBasePath ?? '').replace(/\/+$/, '') const href = (path: string) => { if (!path || path === '/') return base || '/' const normalized = path.startsWith('/') ? path : `/${path}` return `${base}${normalized}` } return { home: { path: '/', href: () => href('/') }, about: { path: '/about', href: () => href('/about') }, notes: { path: '/notes', index: { href: () => href('/notes') }, action: { href: () => href('/notes') }, }, manifest: { path: '/manifest.webmanifest', href: () => href('/manifest.webmanifest') }, icon192: { path: '/icons/icon-192.png', href: () => href('/icons/icon-192.png') }, icon512: { path: '/icons/icon-512.png', href: () => href('/icons/icon-512.png') }, versionApi: { path: '/api/version', href: () => href('/api/version') }, health: { path: '/health', href: () => href('/health') }, } } /** Relative path under the mount (leading slash, no trailing slash except root). */ export function relativePath(pathname: string, appBasePath: string): string { const base = String(appBasePath ?? '').replace(/\/+$/, '') let path = pathname || '/' if (base && (path === base || path.startsWith(base + '/'))) { path = path.slice(base.length) || '/' } if (path.length > 1 && path.endsWith('/')) path = path.slice(0, -1) return path || '/' }