import type { AdminSection, ApiDocSection, PageKey, PlaygroundMode, WorkspaceSection, WorkspaceTaskQuery } from './types'; export interface AppRouteState { activePage: PageKey; adminSection: AdminSection; apiDocSection: ApiDocSection; playgroundMode: PlaygroundMode; workspaceSection: WorkspaceSection; workspaceTaskQuery: WorkspaceTaskQuery; } export const defaultRouteState: AppRouteState = { activePage: 'home', adminSection: 'overview', apiDocSection: 'chat', playgroundMode: 'chat', workspaceSection: 'overview', workspaceTaskQuery: defaultWorkspaceTaskQuery(), }; const workspacePaths: Record = { overview: '/workspace/overview', billing: '/workspace/billing', apiKeys: '/workspace/api-keys', tasks: '/workspace/tasks', transactions: '/workspace/transactions', }; const adminPaths: Record = { overview: '/admin/overview', globalModels: '/admin/providers', baseModels: '/admin/base-models', pricing: '/admin/pricing', platforms: '/admin/platforms', realtimeLoad: '/admin/realtime-load', tenants: '/admin/tenants', users: '/admin/users', userGroups: '/admin/user-groups', auditLogs: '/admin/audit-logs', runtime: '/admin/runtime', accessRules: '/admin/access-rules', systemSettings: '/admin/system-settings', }; const docsPaths: Record = { guideBaseUrl: '/docs/auth', guideWebhook: '/docs/webhook', guideErrors: '/docs/errors', guideTesting: '/docs/testing', chat: '/docs/chat', responses: '/docs/responses', embeddings: '/docs/embeddings', reranks: '/docs/reranks', imageGeneration: '/docs/images/generations', imageEdit: '/docs/images/edits', videoGeneration: '/docs/videos/generations', asyncMode: '/docs/async', taskRetrieve: '/docs/tasks/retrieve', pricing: '/docs/pricing', files: '/docs/files', }; const playgroundPaths: Record = { chat: '/playground/chat', image: '/playground/image', video: '/playground/video', }; const workspaceSections = reverseMap(workspacePaths); const adminSections = reverseMap(adminPaths); const docsSections = reverseMap(docsPaths); const playgroundSections = reverseMap(playgroundPaths); export function parseAppRoute(input = currentLocationPath()): AppRouteState { const origin = typeof window === 'undefined' ? 'http://localhost' : window.location.origin; const url = new URL(input, origin); const path = normalizePath(url.pathname); const workspaceTaskQuery = parseWorkspaceTaskQuery(url.searchParams); if (path === '/') return { ...defaultRouteState }; if (path.startsWith('/playground')) { return { ...defaultRouteState, activePage: 'playground', playgroundMode: parsePlaygroundMode(path), workspaceTaskQuery }; } if (path === '/models') return { ...defaultRouteState, activePage: 'models', workspaceTaskQuery }; if (path.startsWith('/workspace')) { return { ...defaultRouteState, activePage: 'workspace', workspaceSection: parseWorkspaceSection(path), workspaceTaskQuery }; } if (path.startsWith('/admin')) { return { ...defaultRouteState, activePage: 'admin', adminSection: parseAdminSection(path), workspaceTaskQuery }; } if (path.startsWith('/docs')) { return { ...defaultRouteState, activePage: 'docs', apiDocSection: parseDocSection(path), workspaceTaskQuery }; } return { ...defaultRouteState }; } function currentLocationPath() { if (typeof window === 'undefined') return '/'; return `${window.location.pathname}${window.location.search}`; } export function pathForPage(page: PageKey, route: AppRouteState): string { if (page === 'playground') return pathForPlaygroundMode(route.playgroundMode); if (page === 'models') return '/models'; if (page === 'workspace') return pathForWorkspaceSection(route.workspaceSection); if (page === 'admin') return pathForAdminSection(route.adminSection); if (page === 'docs') return pathForApiDocSection(route.apiDocSection); return '/'; } export function pathForWorkspaceSection(section: WorkspaceSection) { return workspacePaths[section] ?? workspacePaths.overview; } export function pathForWorkspaceTaskQuery(query: WorkspaceTaskQuery) { const normalized = normalizeWorkspaceTaskQuery(query); const search = new URLSearchParams(); if (normalized.query) search.set('q', normalized.query); if (normalized.modelType) search.set('type', normalized.modelType); if (normalized.createdFrom) search.set('from', normalized.createdFrom); if (normalized.createdTo) search.set('to', normalized.createdTo); if (normalized.page !== 1) search.set('page', String(normalized.page)); if (normalized.pageSize !== 10) search.set('pageSize', String(normalized.pageSize)); const suffix = search.toString(); return `${workspacePaths.tasks}${suffix ? `?${suffix}` : ''}`; } export function pathForAdminSection(section: AdminSection) { return adminPaths[section] ?? adminPaths.overview; } export function pathForApiDocSection(section: ApiDocSection) { return docsPaths[section] ?? docsPaths.chat; } export function pathForPlaygroundMode(mode: PlaygroundMode) { return playgroundPaths[mode] ?? playgroundPaths.chat; } function parseWorkspaceSection(path: string): WorkspaceSection { return workspaceSections[path] ?? (path === '/workspace' ? 'overview' : 'overview'); } function parseAdminSection(path: string): AdminSection { if (path === '/admin') return 'overview'; if (path === '/admin/models/global') return 'baseModels'; if (path === '/admin/usergroups') return 'userGroups'; return adminSections[path] ?? 'overview'; } function parseDocSection(path: string): ApiDocSection { if (path === '/docs') return 'chat'; if (path === '/docs/playground') return 'guideTesting'; if (path === '/docs/api/chat') return 'chat'; if (path === '/docs/api/responses') return 'responses'; if (path === '/docs/api/embeddings') return 'embeddings'; if (path === '/docs/api/reranks') return 'reranks'; if (path === '/docs/api/media') return 'imageGeneration'; if (path === '/docs/api/videos') return 'videoGeneration'; if (path === '/docs/api/tasks') return 'taskRetrieve'; return docsSections[path] ?? 'chat'; } function parsePlaygroundMode(path: string): PlaygroundMode { if (path === '/playground') return 'chat'; return playgroundSections[path] ?? 'chat'; } function normalizePath(pathname: string) { const path = pathname.replace(/\/+$/, ''); return path || '/'; } function reverseMap(value: Record) { return Object.fromEntries(Object.entries(value).map(([key, path]) => [path, key])) as Record; } export function defaultWorkspaceTaskQuery(): WorkspaceTaskQuery { return { query: '', modelType: '', createdFrom: '', createdTo: '', page: 1, pageSize: 10, }; } export function normalizeWorkspaceTaskQuery(query: WorkspaceTaskQuery): WorkspaceTaskQuery { return { query: query.query.trim(), modelType: query.modelType.trim(), createdFrom: query.createdFrom.trim(), createdTo: query.createdTo.trim(), page: positiveInt(query.page, 1), pageSize: clampPageSize(query.pageSize), }; } export function workspaceTaskQueryKey(query: WorkspaceTaskQuery) { const normalized = normalizeWorkspaceTaskQuery(query); return JSON.stringify(normalized); } function parseWorkspaceTaskQuery(search: URLSearchParams): WorkspaceTaskQuery { return normalizeWorkspaceTaskQuery({ query: search.get('q') ?? search.get('query') ?? '', modelType: search.get('type') ?? search.get('modelType') ?? '', createdFrom: search.get('from') ?? search.get('createdFrom') ?? '', createdTo: search.get('to') ?? search.get('createdTo') ?? '', page: Number(search.get('page') ?? 1), pageSize: Number(search.get('pageSize') ?? search.get('limit') ?? 10), }); } function positiveInt(value: number, fallback: number) { return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback; } function clampPageSize(value: number) { const normalized = positiveInt(value, 10); return Math.min(100, Math.max(1, normalized)); }