Filters on params
A route may decide by its params whether it matches.
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.
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]}`);
}
post 42
slug abc
noneIn a route file the same rule is an export. The scanner reads the file's exports, so the filter sits next to the page:
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.