@guanriyue/decurl/routeSpec
@guanriyue/decurl/routeSpec defines React Router paths and Search Fields in one place, then generates type-safe in-app hrefs from business values.
RouteSpec is a URL contract and href builder. It does not define components, loaders, actions, or route hierarchy.
routeSpec
Call Signature
The definition below preserves the concrete types of the path pattern and Search Fields:
Options
Semantically, path contains only the pathname pattern. It should not contain search or hash.
Return Value
routeSpec returns a callable object:
The result is an in-app href string:
If no search params are generated, the result does not append ?.
Whether Input Is Required
RouteSpec decides whether callable input is required based on path params and search input:
- When there are no path params and no search, input is not accepted.
- When there are only optional path params or search, input can be omitted.
- When there is a required path param, input is required.
Path Params
Path param inference and pathname generation follow React Router path patterns:
Non-nullish path params are converted with String(value) first, then passed to React Router generatePath. Pathname param encoding follows React Router. RouteSpec does not reimplement path encoding:
Search
search directly reuses Search Fields. When generating hrefs, RouteSpec only passes the search input to the same codec encode capability. It does not redefine search encoding rules.
Search input is a partial object. Which business values a field accepts, and how they are written to the URL, are determined by the corresponding FieldCodec.
RouteSpec does not decode search. When reading the URL, a page can directly reuse the Search Fields stored on the spec:
Flat Input
When calling RouteSpec directly, path params and search properties are merged into one flat object:
Conflict detection is based on path param names and Search Fields property keys. If the two parts contain the same property, flat input is disabled at the type level and you must use hrefByParts.
hrefByParts
hrefByParts accepts path params and search input separately. It is the unambiguous grouped href generation API:
When optional parts are omitted, runtime treats them as empty objects. The hrefByParts input object itself is always required.
Working with React Router
Link and navigate
RouteSpec returns strings that can be passed directly to React Router:
Router config
Router config can reuse the path pattern stored on RouteSpec:
RouteSpec does not store parent/child relationships. Object or directory hierarchy does not create extra route semantics.
Types
Public type extractors correspond to path params, search encode input, and search decode values:
InferRouteSpecParams
Extracts the path params needed to generate a pathname:
InferRouteSpecSearchInput
Extracts the partial search input accepted when generating hrefs:
It describes the write direction, so every field is optional and nullish input semantics are preserved.
InferRouteSpecSearchValues
Extracts the complete business values after URL decode:
It describes the read direction and reflects the type difference between optional fields and fields with defaultValue.
Boundaries
- RouteSpec only generates in-app href strings. It does not add React Router basename.
- RouteSpec does not match pathname or parse path params. Pages should continue using React Router
useParams. - RouteSpec does not define parent/child route composition and does not replace router config.
- RouteSpec does not generate full URLs with origin.
- Hash contract is a TODO and is not described as RouteSpec API yet.
- Navigation state contract is a TODO and is not described as RouteSpec API yet.