@geometra/router
v1.19.5
Published
Routing primitives for Geometra
Maintainers
Readme
@geometra/router
Routing primitives for Geometra.
The package now covers matching, history adapters, router lifecycle, loaders/actions, redirects, blockers, restoration policy, and a declarative link primitive.
Install
npm install @geometra/routerKey Exports
matchPath-- matches path patterns with static, dynamic, optional, and splat segmentsbuildPath-- reverse routing helper with typed paramsparseQuery/stringifyQuery-- query parse/stringify helpers with deterministic key orderingcreateMemoryHistory-- history adapter for non-browser runtimes and testscreateBrowserHistory-- browser adapter using pushState/replaceState/popstatecreateRouter-- router lifecycle (start,navigate,subscribe,dispose)- route
loadersupport -- params/query/requestContext-aware data loading for matched routes state.loaderData-- per-route loader results keyed by routeid- route
actionsupport -- write/mutation handlers with submission payloads router.submitAction(routeId, submission)+state.actionData-- mutation workflow primitivessubmitAction(..., { optimistic })-- optimistic mutation hooks with rollback on failure- automatic loader revalidation after actions + explicit
router.revalidate()support redirect()/response()/json()-- loader/action helpers for redirects and structured results- loader/action contexts include
signalfor AbortController-driven cancellation - router state exposes
pending/submitting/loadingflags for transition-aware UI - router state exposes structured
errorpayloads for loader/action/navigation failures router.isActive(to)/router.isPending(to)-- route state helpers for active and transition statesrouter.addBlocker(fn)-- guards transitions for unsaved-state and confirmation flowsrestorationpolicy + per-navigation options -- scroll/focus restoration control on transitionslink-- declarative link element with click + keyboard activation semanticsscorePathPattern-- computes route specificity score for deterministic rankingcomparePatternSpecificity-- compares two patterns by rankingmatchRouteTree-- matches nested route trees with layout routesrenderMatchedOutlet-- composes matched branch render output from leaf to root
Usage
import { createMemoryHistory, createRouter, redirect } from '@geometra/router'
const router = createRouter({
history: createMemoryHistory({ initialEntries: ['/'] }),
routes: [
{
id: 'home',
path: '/',
loader: async () => ({ ok: true }),
},
{
id: 'users.show',
path: '/users/:id',
loader: async ({ params }) => ({ userId: params.id }),
action: async ({ submission }) => {
return { saved: true, payload: submission.data }
},
},
{
id: 'legacy',
path: '/old-home',
loader: async () => redirect('/'),
},
],
})
router.start()
await router.navigate('/users/42')
router.getState().location.pathname
router.getState().loaderData['users.show']
await router.submitAction('users.show', { method: 'POST', data: { theme: 'dark' } })Notes
- The router is renderer-agnostic. It manages navigation state and data flow; rendering matched content is still your app’s job.
loaderandactioncontexts include route params, parsed query, optional request context, and an abortsignal.router.addBlocker()is the escape hatch for unsaved-changes flows and transition confirmation.router.isActive()androuter.isPending()are intended for link styling and transition-aware UI.
