Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | import type { RetriableOptions, StateObserver } from '@anchorlib/core';
import type { RouteCache, URLCache } from './cache.js';
import type { PRELOAD_MODE, RENDER_MODE, ROUTE_STATUS, ROUTE_TYPE } from './enum.js';
import type { Redirect } from './redirect.js';
import type { Route } from './route.js';
/** A generic record type with string keys and unknown values */
export type TRec = Record<string, unknown>;
/** An empty record type */
export type None = Record<string, never>;
/** Maps parameter type strings to their TypeScript types */
export type ParamTypeMap = {
null: null;
string: string;
number: number;
boolean: boolean;
array: unknown[];
object: Record<string, unknown>;
};
/** Gets the TypeScript type for a parameter type string */
export type ParamType<T> = T extends keyof ParamTypeMap ? ParamTypeMap[T] : string;
/** Extracts a typed parameter from a route path segment */
export type ExtractParamType<T extends string> = T extends `${infer Param}(${infer S})`
? { [K in Param]: ParamType<S> }
: { [K in T]: string };
/** Extracts all parameters from a route path */
export type ExtractParams<TPath extends string> = TPath extends `${infer Path}?${string}`
? ExtractParamsPart<Path>
: ExtractParamsPart<TPath>;
/** Internal helper for extracting parameters from path parts */
export type ExtractParamsPart<T extends string> = T extends `${string}:${infer Param}/${infer Rest}`
? ExtractParamType<Param> & ExtractParams<`/${Rest}`>
: T extends `${string}:${infer Param}`
? ExtractParamType<Param>
: None;
/** Extracts query parameters from a route path */
export type ExtractQueryParams<T extends string> = T extends `${string}?${infer QueryPart}`
? ExtractQueryPart<QueryPart>
: None;
/** Internal helper for extracting query parameters */
export type ExtractQueryPart<T extends string> = T extends `${infer First}&${infer Rest}`
? ExtractSingleQueryParam<First> & ExtractQueryPart<Rest>
: ExtractSingleQueryParam<T>;
/** Extracts a single query parameter */
export type ExtractSingleQueryParam<T extends string> = T extends `${infer Param}=${infer S}`
? S extends `(${infer P})`
? {
[K in Param]: P extends keyof ParamTypeMap ? ParamTypeMap[P] : string;
}
: { [K in Param]: S }
: {
[K in T]?: string;
};
/** Combines path and query parameters */
export type PathParams<TParams, TQueryParams> = {
query: TQueryParams;
params: TParams;
};
/** Extracts both path and query parameters from a route path */
export type ExtractPathParams<TPath extends string> = TPath extends `${infer P}?${string}`
? PathParams<ExtractParams<P>, ExtractQueryParams<TPath>>
: PathParams<ExtractParams<TPath>, None>;
export type NestedParams<PParams, CParams> = PParams extends None ? CParams : PParams & CParams;
export type NestedQueryParams<PQuery, CQuery> = PQuery extends None ? CQuery : PQuery & CQuery;
/** A blocker that can prevent route activation (Error or Redirect) */
export type GuardBlocker = Error | UnknownRedirect;
/** Context passed to guard functions */
export type GuardContext<TParams, TQueryParams> = {
query: TQueryParams;
params: TParams;
};
/** A guard function that can block navigation */
export type GuardHandler<TParams, TQueryParams> = (
context: GuardContext<TParams, TQueryParams>
) => Promise<void> | void;
/** An untyped guard function */
export type UnknownGuard = (context: GuardContext<TRec, TRec>) => Promise<void> | void;
/** Context passed to provider functions */
export type ProviderContext<TParams, TQueryParams, TData> = {
data: TData;
query: TQueryParams;
params: TParams;
};
/** Possible error types for routes */
export type RouteErrorType = 'guard' | 'provider' | 'timeout' | 'cancel';
/** Error information for route failures */
export type RouteError = {
type: RouteErrorType;
cause?: Error;
message: string;
};
/** Options for caching provider data */
export interface CacheOptions {
maxAge?: number;
}
/** Options for providers, including retry and cache settings */
export interface ProviderOptions extends RetriableOptions, CacheOptions {}
/** A provider entry in the route's provider map */
export type ProviderMap = {
name: string;
provider: UnknownProvider;
options?: ProviderOptions;
};
/** The type of a route (static, dynamic, wildcard, or index) */
export type RouteType = (typeof ROUTE_TYPE)[keyof typeof ROUTE_TYPE];
/** Options for configuring a route */
export interface RouteOptions extends ProviderOptions {
/** Blocking mode for route rendering */
renderMode?: RenderMode;
preloadMode?: PreloadMode;
/** Keep the route's context when de-activating */
keepAlive?: boolean;
}
/** Unknown parameters type */
export type UnknownParams = ExtractParams<''>;
/** Unknown query parameters type */
export type UnknownQueryParams = ExtractQueryParams<''>;
/** Unknown route type */
export type UnknownRoute = Route<RoutePath, UnknownParams, UnknownQueryParams, RouteOptions, TRec, unknown>;
/** Unknown provider type */
export type UnknownProvider = (ctx: ProviderContext<TRec, TRec, TRec>) => Promise<unknown> | unknown;
/** Unknown redirect type */
export type UnknownRedirect = Redirect<RoutePath, UnknownParams, UnknownQueryParams, RouteOptions, TRec>;
/** Active context for a route */
export type ActiveContext<TParams, TQueryParams, TData> = {
data: TData;
query: TQueryParams;
params: TParams;
};
/** Options for configuring the router */
export type RouterOptions = RouteOptions & {
baseUrl?: string;
cacheSize?: number;
};
/** Flattens a record type */
export type FlatRec<TParams> = {
[K in keyof TParams]: TParams[K];
};
export type RouteStatus = (typeof ROUTE_STATUS)[keyof typeof ROUTE_STATUS];
/** Internal state for a route */
export type RouteState<TParams, TQueryParams, TData> = {
status: RouteStatus;
active: boolean;
resolved: boolean;
resolving: boolean;
authenticated: boolean;
authenticating: boolean;
data?: TData;
error?: RouteError;
context?: ActiveContext<FlatRec<TParams>, FlatRec<TQueryParams>, FlatRec<TData>>;
};
/** A route path string */
export type RoutePath = `${'/'}${string | never}`;
/** Extracts the route name from a path */
export type RouteName<TPath extends RoutePath> = TPath extends `/${infer TParam}`
? TParam extends `:${infer Param}`
? Param extends `${infer TName}(${string})`
? TName
: Param
: TParam
: never;
/** Computes the full path output including parent paths */
export type RoutePathOutput<TParent, TPath extends RoutePath> = TParent extends Route<
infer _PPath,
infer _PParams,
infer _PQueryParams,
infer _POptions,
infer _PData,
infer _P
>
? TParent['path'] extends '/'
? TPath
: `${TParent['path']}${TPath}`
: TPath;
/** A matched route result */
export type MatchedRoute = {
route: UnknownRoute;
params: TRec;
segments: UnknownRoute[];
};
/** A complete match result with URL and context */
export type MatchResult = MatchedRoute & {
url: URL;
query: TRec;
context: ProviderContext<TRec, TRec, TRec>;
};
/** Cached route data with expiration */
export type CachedRouteData = {
data: unknown;
timestamp: number;
scheduler: number;
};
/** Cache for provider data */
export type ProviderCache = Map<string, CachedRouteData>;
/** Observer for provider reactivity */
export type ProviderObserver = {
observer: StateObserver;
resolver: () => Promise<unknown>;
};
export type RouteStorage = {
state: RouteState<unknown, unknown, unknown>;
cache: RouteCache;
dataCache: WeakMap<ProviderContext<TRec, TRec, TRec>, TRec>;
activeResolvers: Map<ProviderContext<TRec, TRec, TRec>, AbortController>;
guardObserver: StateObserver;
providerObservers: WeakMap<UnknownProvider, ProviderObserver>;
};
export type RouterStorage = {
cache: URLCache;
activeUrl: string | undefined;
activeRoute: UnknownRoute | undefined;
activeContext: ActiveContext<TRec, TRec, TRec>;
activeSegments: UnknownRoute[] | undefined;
};
export type PreloadMode = (typeof PRELOAD_MODE)[keyof typeof PRELOAD_MODE];
export type RenderMode = (typeof RENDER_MODE)[keyof typeof RENDER_MODE];
export type RouteInternalRenderer<TOutput> = (props: { children?: TOutput }) => TOutput;
export type RouteRendererFn<Params, QueryParams, Data, Output> = (
state: RouteState<Params, QueryParams, Data>,
context?: ActiveContext<Params, QueryParams, Data>,
children?: Output
) => Output;
|