utils.d.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. import type { Location, Path, To } from "./history";
  2. /**
  3. * Map of routeId -> data returned from a loader/action/error
  4. */
  5. export interface RouteData {
  6. [routeId: string]: any;
  7. }
  8. export declare enum ResultType {
  9. data = "data",
  10. deferred = "deferred",
  11. redirect = "redirect",
  12. error = "error"
  13. }
  14. /**
  15. * Successful result from a loader or action
  16. */
  17. export interface SuccessResult {
  18. type: ResultType.data;
  19. data: any;
  20. statusCode?: number;
  21. headers?: Headers;
  22. }
  23. /**
  24. * Successful defer() result from a loader or action
  25. */
  26. export interface DeferredResult {
  27. type: ResultType.deferred;
  28. deferredData: DeferredData;
  29. statusCode?: number;
  30. headers?: Headers;
  31. }
  32. /**
  33. * Redirect result from a loader or action
  34. */
  35. export interface RedirectResult {
  36. type: ResultType.redirect;
  37. status: number;
  38. location: string;
  39. revalidate: boolean;
  40. }
  41. /**
  42. * Unsuccessful result from a loader or action
  43. */
  44. export interface ErrorResult {
  45. type: ResultType.error;
  46. error: any;
  47. headers?: Headers;
  48. }
  49. /**
  50. * Result from a loader or action - potentially successful or unsuccessful
  51. */
  52. export declare type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
  53. export declare type MutationFormMethod = "post" | "put" | "patch" | "delete";
  54. export declare type FormMethod = "get" | MutationFormMethod;
  55. export declare type FormEncType = "application/x-www-form-urlencoded" | "multipart/form-data";
  56. /**
  57. * @private
  58. * Internal interface to pass around for action submissions, not intended for
  59. * external consumption
  60. */
  61. export interface Submission {
  62. formMethod: FormMethod;
  63. formAction: string;
  64. formEncType: FormEncType;
  65. formData: FormData;
  66. }
  67. /**
  68. * @private
  69. * Arguments passed to route loader/action functions. Same for now but we keep
  70. * this as a private implementation detail in case they diverge in the future.
  71. */
  72. interface DataFunctionArgs {
  73. request: Request;
  74. params: Params;
  75. context?: any;
  76. }
  77. /**
  78. * Arguments passed to loader functions
  79. */
  80. export interface LoaderFunctionArgs extends DataFunctionArgs {
  81. }
  82. /**
  83. * Arguments passed to action functions
  84. */
  85. export interface ActionFunctionArgs extends DataFunctionArgs {
  86. }
  87. /**
  88. * Route loader function signature
  89. */
  90. export interface LoaderFunction {
  91. (args: LoaderFunctionArgs): Promise<Response> | Response | Promise<any> | any;
  92. }
  93. /**
  94. * Route action function signature
  95. */
  96. export interface ActionFunction {
  97. (args: ActionFunctionArgs): Promise<Response> | Response | Promise<any> | any;
  98. }
  99. /**
  100. * Route shouldRevalidate function signature. This runs after any submission
  101. * (navigation or fetcher), so we flatten the navigation/fetcher submission
  102. * onto the arguments. It shouldn't matter whether it came from a navigation
  103. * or a fetcher, what really matters is the URLs and the formData since loaders
  104. * have to re-run based on the data models that were potentially mutated.
  105. */
  106. export interface ShouldRevalidateFunction {
  107. (args: {
  108. currentUrl: URL;
  109. currentParams: AgnosticDataRouteMatch["params"];
  110. nextUrl: URL;
  111. nextParams: AgnosticDataRouteMatch["params"];
  112. formMethod?: Submission["formMethod"];
  113. formAction?: Submission["formAction"];
  114. formEncType?: Submission["formEncType"];
  115. formData?: Submission["formData"];
  116. actionResult?: DataResult;
  117. defaultShouldRevalidate: boolean;
  118. }): boolean;
  119. }
  120. /**
  121. * Base RouteObject with common props shared by all types of routes
  122. */
  123. declare type AgnosticBaseRouteObject = {
  124. caseSensitive?: boolean;
  125. path?: string;
  126. id?: string;
  127. loader?: LoaderFunction;
  128. action?: ActionFunction;
  129. hasErrorBoundary?: boolean;
  130. shouldRevalidate?: ShouldRevalidateFunction;
  131. handle?: any;
  132. };
  133. /**
  134. * Index routes must not have children
  135. */
  136. export declare type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {
  137. children?: undefined;
  138. index: true;
  139. };
  140. /**
  141. * Non-index routes may have children, but cannot have index
  142. */
  143. export declare type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {
  144. children?: AgnosticRouteObject[];
  145. index?: false;
  146. };
  147. /**
  148. * A route object represents a logical route, with (optionally) its child
  149. * routes organized in a tree-like structure.
  150. */
  151. export declare type AgnosticRouteObject = AgnosticIndexRouteObject | AgnosticNonIndexRouteObject;
  152. export declare type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {
  153. id: string;
  154. };
  155. export declare type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {
  156. children?: AgnosticDataRouteObject[];
  157. id: string;
  158. };
  159. /**
  160. * A data route object, which is just a RouteObject with a required unique ID
  161. */
  162. export declare type AgnosticDataRouteObject = AgnosticDataIndexRouteObject | AgnosticDataNonIndexRouteObject;
  163. declare type _PathParam<Path extends string> = Path extends `${infer L}/${infer R}` ? _PathParam<L> | _PathParam<R> : Path extends `:${infer Param}` ? Param extends `${infer Optional}?` ? Optional : Param : never;
  164. /**
  165. * Examples:
  166. * "/a/b/*" -> "*"
  167. * ":a" -> "a"
  168. * "/a/:b" -> "b"
  169. * "/a/blahblahblah:b" -> "b"
  170. * "/:a/:b" -> "a" | "b"
  171. * "/:a/b/:c/*" -> "a" | "c" | "*"
  172. */
  173. declare type PathParam<Path extends string> = Path extends "*" ? "*" : Path extends `${infer Rest}/*` ? "*" | _PathParam<Rest> : _PathParam<Path>;
  174. export declare type ParamParseKey<Segment extends string> = [
  175. PathParam<Segment>
  176. ] extends [never] ? string : PathParam<Segment>;
  177. /**
  178. * The parameters that were parsed from the URL path.
  179. */
  180. export declare type Params<Key extends string = string> = {
  181. readonly [key in Key]: string | undefined;
  182. };
  183. /**
  184. * A RouteMatch contains info about how a route matched a URL.
  185. */
  186. export interface AgnosticRouteMatch<ParamKey extends string = string, RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject> {
  187. /**
  188. * The names and values of dynamic parameters in the URL.
  189. */
  190. params: Params<ParamKey>;
  191. /**
  192. * The portion of the URL pathname that was matched.
  193. */
  194. pathname: string;
  195. /**
  196. * The portion of the URL pathname that was matched before child routes.
  197. */
  198. pathnameBase: string;
  199. /**
  200. * The route object that was used to match.
  201. */
  202. route: RouteObjectType;
  203. }
  204. export interface AgnosticDataRouteMatch extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
  205. }
  206. export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], parentPath?: number[], allIds?: Set<string>): AgnosticDataRouteObject[];
  207. /**
  208. * Matches the given routes to a location and returns the match data.
  209. *
  210. * @see https://reactrouter.com/utils/match-routes
  211. */
  212. export declare function matchRoutes<RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject>(routes: RouteObjectType[], locationArg: Partial<Location> | string, basename?: string): AgnosticRouteMatch<string, RouteObjectType>[] | null;
  213. /**
  214. * Returns a path with params interpolated.
  215. *
  216. * @see https://reactrouter.com/utils/generate-path
  217. */
  218. export declare function generatePath<Path extends string>(originalPath: Path, params?: {
  219. [key in PathParam<Path>]: string | null;
  220. }): string;
  221. /**
  222. * A PathPattern is used to match on some portion of a URL pathname.
  223. */
  224. export interface PathPattern<Path extends string = string> {
  225. /**
  226. * A string to match against a URL pathname. May contain `:id`-style segments
  227. * to indicate placeholders for dynamic parameters. May also end with `/*` to
  228. * indicate matching the rest of the URL pathname.
  229. */
  230. path: Path;
  231. /**
  232. * Should be `true` if the static portions of the `path` should be matched in
  233. * the same case.
  234. */
  235. caseSensitive?: boolean;
  236. /**
  237. * Should be `true` if this pattern should match the entire URL pathname.
  238. */
  239. end?: boolean;
  240. }
  241. /**
  242. * A PathMatch contains info about how a PathPattern matched on a URL pathname.
  243. */
  244. export interface PathMatch<ParamKey extends string = string> {
  245. /**
  246. * The names and values of dynamic parameters in the URL.
  247. */
  248. params: Params<ParamKey>;
  249. /**
  250. * The portion of the URL pathname that was matched.
  251. */
  252. pathname: string;
  253. /**
  254. * The portion of the URL pathname that was matched before child routes.
  255. */
  256. pathnameBase: string;
  257. /**
  258. * The pattern that was used to match.
  259. */
  260. pattern: PathPattern;
  261. }
  262. /**
  263. * Performs pattern matching on a URL pathname and returns information about
  264. * the match.
  265. *
  266. * @see https://reactrouter.com/utils/match-path
  267. */
  268. export declare function matchPath<ParamKey extends ParamParseKey<Path>, Path extends string>(pattern: PathPattern<Path> | Path, pathname: string): PathMatch<ParamKey> | null;
  269. /**
  270. * @private
  271. */
  272. export declare function stripBasename(pathname: string, basename: string): string | null;
  273. /**
  274. * @private
  275. */
  276. export declare function warning(cond: any, message: string): void;
  277. /**
  278. * Returns a resolved path object relative to the given pathname.
  279. *
  280. * @see https://reactrouter.com/utils/resolve-path
  281. */
  282. export declare function resolvePath(to: To, fromPathname?: string): Path;
  283. /**
  284. * @private
  285. *
  286. * When processing relative navigation we want to ignore ancestor routes that
  287. * do not contribute to the path, such that index/pathless layout routes don't
  288. * interfere.
  289. *
  290. * For example, when moving a route element into an index route and/or a
  291. * pathless layout route, relative link behavior contained within should stay
  292. * the same. Both of the following examples should link back to the root:
  293. *
  294. * <Route path="/">
  295. * <Route path="accounts" element={<Link to=".."}>
  296. * </Route>
  297. *
  298. * <Route path="/">
  299. * <Route path="accounts">
  300. * <Route element={<AccountsLayout />}> // <-- Does not contribute
  301. * <Route index element={<Link to=".."} /> // <-- Does not contribute
  302. * </Route
  303. * </Route>
  304. * </Route>
  305. */
  306. export declare function getPathContributingMatches<T extends AgnosticRouteMatch = AgnosticRouteMatch>(matches: T[]): T[];
  307. /**
  308. * @private
  309. */
  310. export declare function resolveTo(toArg: To, routePathnames: string[], locationPathname: string, isPathRelative?: boolean): Path;
  311. /**
  312. * @private
  313. */
  314. export declare function getToPathname(to: To): string | undefined;
  315. /**
  316. * @private
  317. */
  318. export declare const joinPaths: (paths: string[]) => string;
  319. /**
  320. * @private
  321. */
  322. export declare const normalizePathname: (pathname: string) => string;
  323. /**
  324. * @private
  325. */
  326. export declare const normalizeSearch: (search: string) => string;
  327. /**
  328. * @private
  329. */
  330. export declare const normalizeHash: (hash: string) => string;
  331. export declare type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response;
  332. /**
  333. * This is a shortcut for creating `application/json` responses. Converts `data`
  334. * to JSON and sets the `Content-Type` header.
  335. */
  336. export declare const json: JsonFunction;
  337. export interface TrackedPromise extends Promise<any> {
  338. _tracked?: boolean;
  339. _data?: any;
  340. _error?: any;
  341. }
  342. export declare class AbortedDeferredError extends Error {
  343. }
  344. export declare class DeferredData {
  345. private pendingKeysSet;
  346. private controller;
  347. private abortPromise;
  348. private unlistenAbortSignal;
  349. private subscribers;
  350. data: Record<string, unknown>;
  351. init?: ResponseInit;
  352. deferredKeys: string[];
  353. constructor(data: Record<string, unknown>, responseInit?: ResponseInit);
  354. private trackPromise;
  355. private onSettle;
  356. private emit;
  357. subscribe(fn: (aborted: boolean, settledKey?: string) => void): () => boolean;
  358. cancel(): void;
  359. resolveData(signal: AbortSignal): Promise<boolean>;
  360. get done(): boolean;
  361. get unwrappedData(): {};
  362. get pendingKeys(): string[];
  363. }
  364. export declare type DeferFunction = (data: Record<string, unknown>, init?: number | ResponseInit) => DeferredData;
  365. export declare const defer: DeferFunction;
  366. export declare type RedirectFunction = (url: string, init?: number | ResponseInit) => Response;
  367. /**
  368. * A redirect response. Sets the status code and the `Location` header.
  369. * Defaults to "302 Found".
  370. */
  371. export declare const redirect: RedirectFunction;
  372. /**
  373. * @private
  374. * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
  375. */
  376. export declare class ErrorResponse {
  377. status: number;
  378. statusText: string;
  379. data: any;
  380. error?: Error;
  381. internal: boolean;
  382. constructor(status: number, statusText: string | undefined, data: any, internal?: boolean);
  383. }
  384. /**
  385. * Check if the given error is an ErrorResponse generated from a 4xx/5xx
  386. * Response thrown from an action/loader
  387. */
  388. export declare function isRouteErrorResponse(error: any): error is ErrorResponse;
  389. export {};