Skip to main content

ADR-003: Routing abstraction (RouteManager / RouteRepository)

Status

Accepted.

Context

Frontend applications need routing (current route, navigate, optional auth guards). Frameworks provide different APIs. We want application and domain code free of framework routing imports, reuse of the same routing logic across React/Vue/Angular, and testability with a mock.

Decision

We introduce in @c-a-f/core:

RouteRepository (interface)

  • currentRoute: string — Current route (path or pathname).
  • change(route: string): void — Navigate to the given route.

Implementations live in infrastructure (React: useRouteRepository; Vue: composable; Angular: RouteHandler + injectRouteRepository).

RouteManager (class)

  • Constructor: RouteManager(routingSystem: RouteRepository, authOptions?: RouteManagerAuthOptions).
  • authOptions (optional): { loginPath: string; isLoggedIn: () => boolean }.
  • checkForLoginRoute(): void — Redirects to login if not authenticated.
  • isUserLoggedIn(): boolean — Delegates to authOptions.isLoggedIn().
  • changeRoute(route: string): void — Delegates to routingSystem.change(route).

Consequences

Positive: Domain and application stay framework-agnostic; same routing and auth logic across frameworks; easy to test with a mock RouteRepository.

Negative: Abstraction is minimal (no guards, nested routes, params in the interface); currentRoute as string may need normalization per framework.