[]previous and next page

Filters on params

A route may decide by its params whether it matches.

For agentsUpdated

A route may decide by its params whether it matches. Export matchFilters from the route file: a rule per param, given as a RegExp, a list of allowed strings, a predicate, or a Standard Schema whose validate answers synchronously. A value that fails its rule is not a match: the next route with that shape is tried, and when none matches the URL is not found. An optional param that is absent is not checked. The matcher of @shadow-js/router/core is the one the server and the browser use, so both make the same decision.

filters.tsts
import { matchRoutes } from "@shadow-js/router/core";
import { compileMatchFilter } from "@shadow-js/router/filters";

const tree = [
  { id: "post", path: "/posts/:id", matchFilters: { id: /^\d+$/ } },
  { id: "slug", path: "/posts/:slug" },
];
for (const path of ["/posts/42", "/posts/abc", "/other"]) {
  const [match] = matchRoutes(tree, path, { compileFilter: compileMatchFilter });
  console.log(match === undefined ? "none" : `${match.id} ${Object.values(match.params)[0]}`);
}
Expected output
post 42
slug abc
none

In a route file the same rule is an export. The scanner reads the file's exports, so the filter sits next to the page:

src/routes/posts/[id].tsxtsx
import type { JSX } from "@shadow-js/web";

export const matchFilters = {
  id: (value: string): boolean => /^\d+$/.test(value),
};

export default function Post(): JSX.Element {
  return <h1>Post</h1>;
}

A link built with params is checked against the same rules: navigate("/posts/:id", { params: { id: "abc" } }) throws a RangeError that names the param, instead of producing a URL that would not match.