import * as plugins from './plugins.js'; import * as appstate from './appstate.js'; const SmartRouter = plugins.domtools.plugins.smartrouter.SmartRouter; export const validViews = ['overview', 'buckets', 'browser', 'policies', 'config', 'access keys'] as const; export type TValidView = typeof validViews[number]; class AppRouter { private router: InstanceType; private initialized = false; private suppressStateUpdate = false; constructor() { this.router = new SmartRouter({ debug: false }); } public init(): void { if (this.initialized) return; this.setupRoutes(); this.setupStateSync(); this.handleInitialRoute(); this.initialized = true; } private viewToPath(view: string): string { return `/${view.replace(/\s+/g, '-')}`; } private pathToView(path: string): string { const segment = path.split('/').filter(Boolean)[0] || ''; return segment.replace(/-/g, ' '); } private setupRoutes(): void { for (const view of validViews) { this.router.on(this.viewToPath(view), async () => { this.updateViewState(view); }); } // Root redirect this.router.on('/', async () => { this.navigateTo(this.viewToPath('overview')); }); } private setupStateSync(): void { appstate.uiStatePart.state.subscribe((uiState) => { if (this.suppressStateUpdate) return; const currentPath = window.location.pathname; const expectedPath = this.viewToPath(uiState.activeView); if (currentPath !== expectedPath) { this.suppressStateUpdate = true; this.router.pushUrl(expectedPath); this.suppressStateUpdate = false; } }); } private handleInitialRoute(): void { const path = window.location.pathname; if (!path || path === '/') { this.router.pushUrl(this.viewToPath('overview')); } else { const view = this.pathToView(path); if (validViews.includes(view as TValidView)) { this.updateViewState(view as TValidView); } else { this.router.pushUrl(this.viewToPath('overview')); } } } private updateViewState(view: string): void { this.suppressStateUpdate = true; const currentState = appstate.uiStatePart.getState(); if (currentState.activeView !== view) { appstate.uiStatePart.setState({ ...currentState, activeView: view, }); } this.suppressStateUpdate = false; } public navigateTo(path: string): void { this.router.pushUrl(path); } public navigateToView(view: string): void { if (validViews.includes(view as TValidView)) { this.navigateTo(this.viewToPath(view)); } else { this.navigateTo(this.viewToPath('overview')); } } public destroy(): void { this.router.destroy(); this.initialized = false; } } export const appRouter = new AppRouter();