Route - greydragon888/real-router GitHub Wiki

Route

Overview

The Route interface defines the structure of a route configuration object. Routes describe how URL paths map to named destinations in your application, including path patterns, guards, redirects, and nested children.

Type Definition

interface Route<
  Dependencies extends DefaultDependencies = DefaultDependencies,
> {
  [key: string]: unknown;

  name: string;
  path: string;
  canActivate?: GuardFnFactory<Dependencies>;
  canDeactivate?: GuardFnFactory<Dependencies>;
  forwardTo?: string | ForwardToCallback<Dependencies>;
  children?: Route<Dependencies>[];
  encodeParams?: (stateParams: Params) => Params;
  decodeParams?: (pathParams: Params) => Params;
  defaultParams?: Params;
  // Extended by @real-router/search-schema-plugin:
  searchSchema?: StandardSchemaV1;
}

Properties

Property Type Required Description
name string Yes Route name (dot-separated for nested routes)
path string Yes URL path pattern for this route
canActivate GuardFnFactory No Factory function returning activation guard
canDeactivate GuardFnFactory No Factory function returning deactivation guard
forwardTo string | ForwardToCallback No Redirect to another route (static or dynamic)
children Route[] No Nested child routes
encodeParams (params) => Params No Encode state params to URL params
decodeParams (params) => Params No Decode URL params to state params
defaultParams Params No Default parameters for this route
searchSchema StandardSchemaV1 No Standard Schema V1 object for runtime search parameter validation (requires @real-router/search-schema-plugin)

Path Pattern Syntax

URL Parameters

// Required parameter
{ name: "user", path: "/users/:id" }
// Matches: /users/123 → { id: "123" }

// Optional parameter
{ name: "user", path: "/users/:id?" }
// Matches: /users → {}, /users/123 → { id: "123" }

// Splat (catch-all)
{ name: "files", path: "/files/*path" }
// Matches: /files/a/b/c → { path: "a/b/c" }

Query Parameters

// Declared query params
{ name: "users", path: "/users?page&sort" }
// Matches: /users?page=1&sort=name → { page: "1", sort: "name" }

// Matrix parameters (within path segments)
{ name: "product", path: "/products;category/:id" }

Usage Examples

Basic Routes

import { createRouter } from "@real-router/core";

const routes = [
  { name: "home", path: "/" },
  { name: "about", path: "/about" },
  { name: "users", path: "/users" },
  { name: "users.profile", path: "/:id" },
];

const router = createRouter(routes);

Nested Routes

const routes = [
  { name: "home", path: "/" },
  {
    name: "admin",
    path: "/admin",
    children: [
      { name: "admin.dashboard", path: "/dashboard" },
      { name: "admin.users", path: "/users" },
      {
        name: "admin.users.edit",
        path: "/:id/edit",
      },
    ],
  },
];

// URLs:
// /admin/dashboard → admin.dashboard
// /admin/users → admin.users
// /admin/users/123/edit → admin.users.edit { id: "123" }

With Guards

const routes = [
  {
    name: "dashboard",
    path: "/dashboard",
    canActivate: (router, getDependency) => (toState, fromState) => {
      const isAuthenticated = getDependency("auth").isLoggedIn();
      return isAuthenticated;
    },
  },
];

With Deactivation Guards

const routes = [
  {
    name: "editor",
    path: "/editor",
    canDeactivate: (router, getDependency) => (toState, fromState) => {
      const hasUnsaved = getDependency("formState").isDirty();
      return !hasUnsaved;
    },
  },
];

With Redirects

const routes = [
  { name: "home", path: "/" },
  { name: "dashboard", path: "/dashboard" },
  // Old URL redirects to new location (static)
  { name: "old-dashboard", path: "/app", forwardTo: "dashboard" },
];

// Navigation to "old-dashboard" or /app redirects to /dashboard

With Dynamic Redirects

const routes = [
  { name: "home", path: "/" },
  { name: "admin", path: "/admin" },
  { name: "user", path: "/user" },
  {
    name: "landing",
    path: "/landing",
    // Dynamic redirect based on dependencies
    forwardTo: (getDependency) =>
      getDependency("auth").isAdmin ? "admin" : "user",
  },
];

// Navigation to "landing" resolves at runtime based on auth dependency

With Parameter Encoding/Decoding

const routes = [
  {
    name: "search",
    path: "/search/:query",
    // Encode spaces as + for URL
    encodeParams: (params) => ({
      ...params,
      query: params.query?.replace(/ /g, "+"),
    }),
    // Decode + back to spaces
    decodeParams: (params) => ({
      ...params,
      query: params.query?.replace(/\+/g, " "),
    }),
  },
];

With Default Parameters

const routes = [
  {
    name: "users",
    path: "/users?page&limit",
    defaultParams: {
      page: "1",
      limit: "20",
    },
  },
];

// router.navigate("users") → /users?page=1&limit=20

Related Types

GuardFnFactory

Factory function that creates guards:

type GuardFnFactory<Dependencies> = (
  router: Router<Dependencies>,
  getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
) => GuardFn;

type GuardFn = (
  toState: State,
  fromState: State | undefined,
  signal?: AbortSignal,
) => boolean | Promise<boolean>;

Important Notes

  • Route names must be unique across the entire route tree
  • Child routes inherit parent path prefix automatically
  • forwardTo creates URL aliases, not redirect chains
  • forwardTo can be a callback (getDependency, params) => string for runtime-conditional routing
  • Dynamic forwardTo callbacks must be synchronous (async throws TypeError)
  • Static forwardTo chains are cached (O(1)), dynamic chains are resolved per-navigation
  • Guards (canActivate, canDeactivate) on forwardTo source routes are NOT executed (warning emitted)
  • encodeParams is called when building URLs
  • decodeParams is called when matching URLs

Related Methods

Route management is available via getRoutesApi(router):

Method Description
getRoutesApi(router).add(routes) Add routes dynamically
getRoutesApi(router).remove(name) Remove a route
getRoutesApi(router).get(name) Get route by name
getRoutesApi(router).has(name) Check if route exists
getRoutesApi(router).update(name, config) Update route properties
getRoutesApi(router).clear() Remove all routes
⚠️ **GitHub.com Fallback** ⚠️