router
Turn files in app/routes into pages, with links, loaders and guards. Web, desktop and mobile apps get it automatically.
Every export of kitr/router, read from the published type definitions. The guide shows them in use.
kitr/router
Re-exports @tanstack/history, @tanstack/react-router, @tanstack/router-core unchanged, plus the following.
can
function can(permission: string, options?: {
subject?: unknown;
to?: string;
}): ({ context }: {
context: {
session?: GuardSession | null;
};
}) => void;
beforeLoad permission guard. Throws a FORBIDDEN KitrError that the route's
errorComponent renders, or redirects when to is given.
createKitrRouter
function createKitrRouter<TRouteTree extends AnyRoute>(options: CreateKitrRouterOptions<TRouteTree>): Router<TRouteTree, 'never', true>;
createRouter with kitr's defaults: queryClient and app in context, intent
preload, scroll restoration, default pending/error/not-found components,
and the app's providers wrapped around the whole tree.
With @kitr/query installed, loaders can context.queryClient.ensureQueryData(...).
DefaultError
function DefaultError({ error, reset }: ErrorComponentProps): import("react").JSX.Element;
DefaultNotFound
function DefaultNotFound(): import("react").JSX.Element;
DefaultPending
function DefaultPending(): import("react").JSX.Element;
Default route-level components. Generated routes reference these so every
page has a loading, error and not-found state without anyone deciding each time.
Override globally in createKitrRouter({ defaultPendingComponent }) or per route.
guards
function guards<Ctx>(...fns: Array<(ctx: Ctx) => unknown | Promise<unknown>>): (ctx: Ctx) => Promise<Record<string, unknown>>;
Compose several beforeLoad guards; each may return context to merge.
requireAuth
function requireAuth(options?: RequireAuthOptions): ({ context, location }: {
context: {
session?: GuardSession | null;
};
location: {
href: string;
};
}) => {
session: GuardSession;
};
beforeLoad guard. Reads context.session (set by @kitr/auth or your own
provider) and redirects anonymous users, remembering where they were going.
export const Route = createFileRoute('/_app')({ beforeLoad: requireAuth() })
CreateKitrRouterOptions
interface CreateKitrRouterOptions<TRouteTree extends AnyRoute> extends Omit<RouterOptions<TRouteTree, 'never', false, any, any>, 'context'> {
app: KitrApp;
/** Defaults to the container's `queryClient` (from @kitr/query). */
queryClient?: QueryClient;
/** Extra context merged into every route (e.g. `session`). */
context?: Record<string, unknown>;
}
GuardSession
interface GuardSession {
user?: unknown | null;
can?: (permission: string, subject?: unknown) => boolean;
}
KitrRouterContext
interface KitrRouterContext {
queryClient: QueryClient;
app: KitrApp;
}
The router context every kitr route sees. Packages extend it by augmentation:
declare module '@kitr/router' { interface KitrRouterContext { session: Session | null } }
RequireAuthOptions
interface RequireAuthOptions {
/** Where to send anonymous users. Default `/sign-in`. */
to?: string;
/** Name of the search param carrying the original URL. Default `redirect`. */
redirectParam?: string | false;
}
RouterContextWith
type RouterContextWith<T> = KitrRouterContext & T;