UNPKG

@route-weaver/core

Version:

A typesafe navigation package for creating and managing routes.

120 lines (118 loc) 4.54 kB
/** * The basic shape of a navigation item, without the ID. */ interface NavItem<TMeta = unknown> { label: string; path: string; meta?: TMeta; } /** * A map of all declared routes, where the key is a unique route ID. * This will be the single source of truth for all routes. */ type RouteDeclarations<TMeta = unknown> = Record<string, string | { path: string; meta?: TMeta; }>; /** * Defines the structure for navigation groups and their labels. */ type NavDefinitions<T extends string> = Record<string, Partial<Record<T, string>>>; /** * Represents a fully resolved and structured navigation item, * which includes its ID and any potential children. */ interface StructuredNavItem<TMeta = unknown> extends NavItem<TMeta> { id: string; fullPath: string; children?: StructuredNavItem<TMeta>[]; } /** * The final, structured navigation object, ready to be used in your application. * The keys are the names of your contextual groups. */ type StructuredNavigation<TNavDef, TMeta = unknown> = { [K in keyof TNavDef]: StructuredNavItem<TMeta>[]; }; /** * Represents a matched route, including the route definition and any URL parameters. */ interface ActiveRoute<TMeta = unknown> { route: StructuredNavItem<TMeta>; params: Record<string, any>; } /** * A generic function that takes a string key and returns a translated string. * This is compatible with common i18n libraries (e.g., the `t` function). */ type Translator = (key: string) => string; /** * The public interface of the self-contained navigation instance created * by the `build` method. */ interface NavigationInstance<T extends RouteDeclarations<TMeta>, TNavDef, TMeta = unknown> { navigation: StructuredNavigation<TNavDef, TMeta>; getActiveRoute: (pathname: string) => ActiveRoute<TMeta> | undefined; getBreadcrumbs: (pathname: string) => StructuredNavItem<TMeta>[]; filterNavigation: (predicate: (item: StructuredNavItem<TMeta>) => boolean) => StructuredNavigation<TNavDef, TMeta>; generateSitemap: (options: { domain: string; }) => string; on: (event: 'change', callback: () => void) => () => void; buildPath: <R extends keyof T>(...args: BuildPathArgs<RoutePath<T[R]>, R>) => string; } /** * A helper type to extract the path from a route definition. */ type RoutePath<T> = T extends string ? T : T extends { path: string; } ? T['path'] : never; /** * A helper type to define the arguments for `buildPath`. * If the route has no params, the `params` object is optional. * If the route has params, the `params` object is required. */ type BuildPathArgs<TPath extends string, TId> = [ id: TId, ...(ExtractRouteParams<TPath> extends never ? [params?: never] : [params: RouteParams<TPath>]) ]; /** * The public interface of the route-weaver factory instance. */ interface RouteWeaverInstance<T extends RouteDeclarations<TMeta>, TMeta = unknown> { buildNav: <U extends NavDefinitions<keyof T & string>>(definitions: U, options?: { t?: Translator; }) => NavigationInstance<T, U, TMeta>; join: (...parts: string[]) => string; } /** * Extracts parameter names from a route path string. * @example * type P = ExtractRouteParams<'/users/:id/posts/:postId'>; * // P is 'id' | 'postId' */ type ExtractRouteParams<T extends string> = string extends T ? string : T extends `${infer _Start}:${infer Param}/${infer Rest}` ? Param | ExtractRouteParams<Rest> : T extends `${infer _Start}:${infer Param}` ? Param : never; /** * Creates a record type for the parameters of a given route path. * If the path has no parameters, it's an empty object. * @example * type P1 = RouteParams<'/users/:id'>; // { id: string | number } * type P2 = RouteParams<'/about'>; // {} */ type RouteParams<T extends string> = { [P in ExtractRouteParams<T>]: string | number; }; /** * Describes the shape of a route definition in the nested structure. */ interface RouteDefinition<TMeta = unknown> { path: string; label: string; children?: NestedRouteDeclarations<TMeta>; meta?: TMeta; } /** * A map of all declared routes in a nested structure, where the key is a unique route ID. */ type NestedRouteDeclarations<TMeta = unknown> = Record<string, RouteDefinition<TMeta>>; export type { ActiveRoute, BuildPathArgs, ExtractRouteParams, NavDefinitions, NavItem, NavigationInstance, NestedRouteDeclarations, RouteDeclarations, RouteDefinition, RouteParams, RoutePath, RouteWeaverInstance, StructuredNavItem, StructuredNavigation, Translator };