@tanstack/router-core 0.0.1-alpha.10 → 0.0.1-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -102,6 +102,7 @@ interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
102
102
  route: AnyRoute;
103
103
  router: Router<any, any>;
104
104
  }) => void;
105
+ createElement?: (element: GetFrameworkGeneric<'Element'> | (() => Promise<GetFrameworkGeneric<'Element'>>)) => Promise<GetFrameworkGeneric<'Element'>>;
105
106
  }
106
107
  interface Action<TPayload = unknown, TResponse = unknown> {
107
108
  submit: (submission?: TPayload) => Promise<TResponse>;
@@ -116,6 +117,29 @@ interface ActionState<TPayload = unknown, TResponse = unknown> {
116
117
  data?: TResponse;
117
118
  error?: unknown;
118
119
  }
120
+ interface Loader<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TRouteLoaderData = AnyLoaderData> {
121
+ fetch: keyof PickRequired<TFullSearchSchema> extends never ? keyof TAllParams extends never ? (loaderContext: {
122
+ signal?: AbortSignal;
123
+ }) => Promise<TRouteLoaderData> : (loaderContext: {
124
+ params: TAllParams;
125
+ search?: TFullSearchSchema;
126
+ signal?: AbortSignal;
127
+ }) => Promise<TRouteLoaderData> : keyof TAllParams extends never ? (loaderContext: {
128
+ search: TFullSearchSchema;
129
+ params: TAllParams;
130
+ signal?: AbortSignal;
131
+ }) => Promise<TRouteLoaderData> : (loaderContext: {
132
+ search: TFullSearchSchema;
133
+ signal?: AbortSignal;
134
+ }) => Promise<TRouteLoaderData>;
135
+ current?: LoaderState<TFullSearchSchema, TAllParams>;
136
+ latest?: LoaderState<TFullSearchSchema, TAllParams>;
137
+ pending: LoaderState<TFullSearchSchema, TAllParams>[];
138
+ }
139
+ interface LoaderState<TFullSearchSchema = unknown, TAllParams = unknown> {
140
+ loadedAt: number;
141
+ loaderContext: LoaderContext<TFullSearchSchema, TAllParams>;
142
+ }
119
143
  interface RouterState {
120
144
  status: 'idle' | 'loading';
121
145
  location: Location;
@@ -125,6 +149,7 @@ interface RouterState {
125
149
  currentAction?: ActionState;
126
150
  latestAction?: ActionState;
127
151
  actions: Record<string, Action>;
152
+ loaders: Record<string, Loader>;
128
153
  pending?: PendingState;
129
154
  isFetching: boolean;
130
155
  isPreloading: boolean;
@@ -231,7 +256,7 @@ declare function createRouter<TRouteConfig extends AnyRouteConfig = RouteConfig,
231
256
  interface RouteMatch<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo, TRouteInfo extends AnyRouteInfo = RouteInfo> extends Route<TAllRouteInfo, TRouteInfo> {
232
257
  matchId: string;
233
258
  pathname: string;
234
- params: AnyPathParams;
259
+ params: TRouteInfo['params'];
235
260
  parentMatch?: RouteMatch;
236
261
  childMatches: RouteMatch[];
237
262
  routeSearch: TRouteInfo['searchSchema'];
@@ -271,9 +296,20 @@ interface RouteMatch<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo
271
296
  resolve: () => void;
272
297
  };
273
298
  cancel: () => void;
274
- load: (opts?: {
299
+ load: (loaderOpts?: {
300
+ withPending?: boolean;
301
+ } & ({
302
+ preload: true;
303
+ maxAge: number;
304
+ gcMaxAge: number;
305
+ } | {
306
+ preload?: false;
307
+ maxAge?: never;
308
+ gcMaxAge?: never;
309
+ })) => Promise<TRouteInfo['routeLoaderData']>;
310
+ fetch: (opts?: {
275
311
  maxAge?: number;
276
- }) => Promise<void>;
312
+ }) => Promise<TRouteInfo['routeLoaderData']>;
277
313
  invalidate: () => void;
278
314
  hasLoaders: () => boolean;
279
315
  }
@@ -298,6 +334,7 @@ interface Route<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo, TRo
298
334
  matchRoute: <TTo extends string = '.', TResolved extends string = ResolveRelativePath<TRouteInfo['id'], TTo>>(matchLocation: CheckRelativePath<TAllRouteInfo, TRouteInfo['fullPath'], NoInfer<TTo>> & Omit<ToOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>, 'from'>, opts?: MatchRouteOptions) => RouteInfoByPath<TAllRouteInfo, TResolved>['allParams'];
299
335
  navigate: <TTo extends string = '.'>(options: Omit<LinkOptions<TAllRouteInfo, TRouteInfo['id'], TTo>, 'from'>) => Promise<void>;
300
336
  action: unknown extends TRouteInfo['actionResponse'] ? Action<TRouteInfo['actionPayload'], TRouteInfo['actionResponse']> | undefined : Action<TRouteInfo['actionPayload'], TRouteInfo['actionResponse']>;
337
+ loader: unknown extends TRouteInfo['routeLoaderData'] ? Action<LoaderContext<TRouteInfo['fullSearchSchema'], TRouteInfo['allParams']>, TRouteInfo['routeLoaderData']> | undefined : Loader<TRouteInfo['fullSearchSchema'], TRouteInfo['allParams'], TRouteInfo['routeLoaderData']>;
301
338
  }
302
339
  declare function createRoute<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo, TRouteInfo extends AnyRouteInfo = RouteInfo>(routeConfig: RouteConfig, options: TRouteInfo['options'], parent: undefined | Route<TAllRouteInfo, any>, router: Router<TAllRouteInfo['routeConfig'], TAllRouteInfo>): Route<TAllRouteInfo, TRouteInfo>;
303
340
  declare function cascadeLoaderData(matches: RouteMatch<any, any>[]): void;
@@ -383,11 +420,12 @@ declare type DefinedPathParamWarning = 'Path params cannot be redefined by child
383
420
  declare type ParentParams<TParentParams> = AnyPathParams extends TParentParams ? {} : {
384
421
  [Key in keyof TParentParams]?: DefinedPathParamWarning;
385
422
  };
386
- declare type LoaderFn<TRouteLoaderData extends AnyLoaderData, TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}> = (loaderContext: {
423
+ declare type LoaderFn<TRouteLoaderData extends AnyLoaderData, TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}> = (loaderContext: LoaderContext<TFullSearchSchema, TAllParams>) => Promise<TRouteLoaderData>;
424
+ interface LoaderContext<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}> {
387
425
  params: TAllParams;
388
426
  search: TFullSearchSchema;
389
427
  signal?: AbortSignal;
390
- }) => Promise<TRouteLoaderData>;
428
+ }
391
429
  declare type ActionFn<TActionPayload = unknown, TActionResponse = unknown> = (submission: TActionPayload) => TActionResponse | Promise<TActionResponse>;
392
430
  declare type UnloaderFn<TPath extends string> = (routeMatch: RouteMatch<any, RouteInfo<string, TPath>>) => void;
393
431
  declare type RouteOptions<TRouteId extends string = string, TPath extends string = string, TRouteLoaderData extends AnyLoaderData = {}, TLoaderData extends AnyLoaderData = {}, TActionPayload = unknown, TActionResponse = unknown, TParentSearchSchema extends {} = {}, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = TSearchSchema, TParentParams extends AnyPathParams = {}, TParams extends Record<ParsePathParams<TPath>, unknown> = Record<ParsePathParams<TPath>, string>, TAllParams extends AnyPathParams = {}> = ({
@@ -401,18 +439,6 @@ declare type RouteOptions<TRouteId extends string = string, TPath extends string
401
439
  postSearchFilters?: SearchFilter<TFullSearchSchema>[];
402
440
  pendingMs?: number;
403
441
  pendingMinMs?: number;
404
- } & ({
405
- parseParams?: never;
406
- stringifyParams?: never;
407
- } | {
408
- parseParams: (rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>) => TParams;
409
- stringifyParams: (params: TParams) => Record<ParsePathParams<TPath>, string>;
410
- }) & RouteLoaders<TRouteLoaderData, TLoaderData, TActionPayload, TActionResponse, TFullSearchSchema, TAllParams> & {
411
- import?: (opts: {
412
- params: AnyPathParams;
413
- }) => Promise<RouteLoaders<TRouteLoaderData, TLoaderData, TActionPayload, TActionResponse, TFullSearchSchema, TAllParams>>;
414
- } & (PickUnsafe<TParentParams, ParsePathParams<TPath>> extends never ? {} : 'Cannot redefined path params in child routes!');
415
- interface RouteLoaders<TRouteLoaderData extends AnyLoaderData = {}, TLoaderData extends AnyLoaderData = {}, TActionPayload = unknown, TActionResponse = unknown, TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}> {
416
442
  element?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
417
443
  errorElement?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
418
444
  catchElement?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
@@ -434,7 +460,13 @@ interface RouteLoaders<TRouteLoaderData extends AnyLoaderData = {}, TLoaderData
434
460
  search: TFullSearchSchema;
435
461
  }) => void;
436
462
  meta?: RouteMeta;
437
- }
463
+ } & ({
464
+ parseParams?: never;
465
+ stringifyParams?: never;
466
+ } | {
467
+ parseParams: (rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>) => TParams;
468
+ stringifyParams: (params: TParams) => Record<ParsePathParams<TPath>, string>;
469
+ }) & (PickUnsafe<TParentParams, ParsePathParams<TPath>> extends never ? {} : 'Cannot redefined path params in child routes!');
438
470
  declare type SearchFilter<T, U = T> = (prev: T) => U;
439
471
  interface RouteConfig<TId extends string = string, TRouteId extends string = string, TPath extends string = string, TFullPath extends string = string, TRouteLoaderData extends AnyLoaderData = AnyLoaderData, TLoaderData extends AnyLoaderData = AnyLoaderData, TActionPayload = unknown, TActionResponse = unknown, TParentSearchSchema extends {} = {}, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = {}, TParentParams extends AnyPathParams = {}, TParams extends Record<ParsePathParams<TPath>, unknown> = Record<ParsePathParams<TPath>, string>, TAllParams extends AnyPathParams = {}, TKnownChildren = unknown> {
440
472
  id: TId;
@@ -482,7 +514,7 @@ declare type LinkInfo = {
482
514
  };
483
515
  declare type StartsWith<A, B> = A extends `${B extends string ? B : never}${infer _}` ? true : false;
484
516
  declare type CleanPath<T extends string> = T extends `${infer L}//${infer R}` ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`> : T extends `${infer L}//` ? `${CleanPath<L>}/` : T extends `//${infer L}` ? `/${CleanPath<L>}` : T;
485
- declare type Split<S, TTrailing = true> = S extends unknown ? string extends S ? string[] : S extends string ? CleanPath<S> extends '' ? [] : TTrailing extends true ? CleanPath<S> extends `${infer T}/` ? [T, '/'] : CleanPath<S> extends `/${infer U}` ? ['/', U] : CleanPath<S> extends `${infer T}/${infer U}` ? [T, ...Split<U>] : [S] : CleanPath<S> extends `${infer T}/${infer U}` ? [T, ...Split<U>] : [S] : never : never;
517
+ declare type Split<S, TIncludeTrailingSlash = true> = S extends unknown ? string extends S ? string[] : S extends string ? CleanPath<S> extends '' ? [] : TIncludeTrailingSlash extends true ? CleanPath<S> extends `${infer T}/` ? [...Split<T>, '/'] : CleanPath<S> extends `/${infer U}` ? Split<U> : CleanPath<S> extends `${infer T}/${infer U}` ? [...Split<T>, ...Split<U>] : [S] : CleanPath<S> extends `${infer T}/${infer U}` ? [...Split<T>, ...Split<U>] : S extends string ? [S] : never : never : never;
486
518
  declare type ParsePathParams<T extends string> = Split<T>[number] extends infer U ? U extends `:${infer V}` ? V : never : never;
487
519
  declare type Join<T> = T extends [] ? '' : T extends [infer L extends string] ? L : T extends [infer L extends string, ...infer Tail extends [...string[]]] ? CleanPath<`${L}/${Join<Tail>}`> : never;
488
520
  declare type RelativeToPathAutoComplete<AllPaths extends string, TFrom extends string, TTo extends string, SplitPaths extends string[] = Split<AllPaths, false>> = TTo extends `..${infer _}` ? SplitPaths extends [
@@ -503,7 +535,7 @@ declare type ToOptions<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteIn
503
535
  to?: ToPathOption<TAllRouteInfo, TFrom, TTo>;
504
536
  hash?: Updater<string>;
505
537
  from?: TFrom;
506
- } & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>> & SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> & PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>;
538
+ } & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>, {}> & SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> & PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>;
507
539
  declare type SearchParamOptions<TAllRouteInfo extends AnyAllRouteInfo, TFrom, TTo, TFromSchema = RouteInfoByPath<TAllRouteInfo, TFrom>['fullSearchSchema'], TToSchema = RouteInfoByPath<TAllRouteInfo, TTo>['fullSearchSchema']> = StartsWith<TFrom, TTo> extends true ? {
508
540
  search?: SearchReducer<TFromSchema, TToSchema>;
509
541
  } : keyof PickRequired<TToSchema> extends never ? {
@@ -541,12 +573,17 @@ declare type CheckRelativePath<TAllRouteInfo extends AnyAllRouteInfo, TFrom, TTo
541
573
  Error: `${TFrom} + ${TTo} resolves to ${ResolveRelativePath<TFrom, TTo>}, which is not a valid route path.`;
542
574
  'Valid Route Paths': TAllRouteInfo['routePaths'];
543
575
  } : {} : {};
544
- declare type CheckPath<TAllRouteInfo extends AnyAllRouteInfo, TPath> = Exclude<TPath, TAllRouteInfo['routePaths']> extends never ? {} : CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>;
545
- declare type CheckPathError<TAllRouteInfo extends AnyAllRouteInfo, TInvalids> = {
576
+ declare type CheckPath<TAllRouteInfo extends AnyAllRouteInfo, TPath, TPass> = Exclude<TPath, TAllRouteInfo['routePaths']> extends never ? TPass : CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>;
577
+ declare type CheckPathError<TAllRouteInfo extends AnyAllRouteInfo, TInvalids> = Expand<{
546
578
  Error: `${TInvalids extends string ? TInvalids : never} is not a valid route path.`;
547
579
  'Valid Route Paths': TAllRouteInfo['routePaths'];
548
- };
549
- declare type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string ? TTo extends string ? TTo extends '.' ? TFrom : TTo extends `./` ? Join<[TFrom, '/']> : TTo extends `./${infer TRest}` ? ResolveRelativePath<TFrom, TRest> : TTo extends `/${infer TRest}` ? TTo : Split<TTo> extends ['..', ...infer ToRest] ? Split<TFrom> extends [...infer FromRest, infer FromTail] ? ResolveRelativePath<Join<FromRest>, Join<ToRest>> : never : Split<TTo> extends ['.', ...infer ToRest] ? ResolveRelativePath<TFrom, Join<ToRest>> : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>> : never : never;
580
+ }>;
581
+ declare type CheckId<TAllRouteInfo extends AnyAllRouteInfo, TPath, TPass> = Exclude<TPath, TAllRouteInfo['routeIds']> extends never ? TPass : CheckIdError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routeIds']>>;
582
+ declare type CheckIdError<TAllRouteInfo extends AnyAllRouteInfo, TInvalids> = Expand<{
583
+ Error: `${TInvalids extends string ? TInvalids : never} is not a valid route ID.`;
584
+ 'Valid Route IDs': TAllRouteInfo['routeIds'];
585
+ }>;
586
+ declare type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string ? TTo extends string ? TTo extends '.' ? TFrom : TTo extends `./` ? Join<[TFrom, '/']> : TTo extends `./${infer TRest}` ? ResolveRelativePath<TFrom, TRest> : TTo extends `/${infer TRest}` ? TTo : Split<TTo> extends ['..', ...infer ToRest] ? Split<TFrom> extends [...infer FromRest, infer FromTail] ? ToRest extends ['/'] ? Join<[...FromRest, '/']> : ResolveRelativePath<Join<FromRest>, Join<ToRest>> : never : Split<TTo> extends ['.', ...infer ToRest] ? ToRest extends ['/'] ? Join<[TFrom, '/']> : ResolveRelativePath<TFrom, Join<ToRest>> : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>> : never : never;
550
587
  declare type ValidFromPath<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo> = undefined | (string extends TAllRouteInfo['routePaths'] ? string : TAllRouteInfo['routePaths']);
551
588
 
552
589
  interface Segment {
@@ -572,4 +609,4 @@ declare const defaultStringifySearch: (search: Record<string, any>) => string;
572
609
  declare function parseSearchWith(parser: (str: string) => any): (searchStr: string) => AnySearchSchema;
573
610
  declare function stringifySearchWith(stringify: (search: any) => string): (search: Record<string, any>) => string;
574
611
 
575
- export { Action, ActionFn, ActionState, AllRouteInfo, AnyAllRouteInfo, AnyLoaderData, AnyPathParams, AnyRoute, AnyRouteConfig, AnyRouteConfigWithChildren, AnyRouteInfo, AnySearchSchema, BuildNextOptions, CheckPath, CheckPathError, CheckRelativePath, DeepAwaited, DefaultAllRouteInfo, DefinedPathParamWarning, Expand, FilterRoutesFn, FrameworkGenerics, FromLocation, GetFrameworkGeneric, IsAny, IsAnyBoolean, IsKnown, LinkInfo, LinkOptions, ListenerFn, LoaderFn, Location, LocationState, MatchCacheEntry, MatchLocation, MatchRouteOptions, NavigateOptionsAbsolute, NoInfer, ParentParams, ParsePathParams, ParseRouteConfig, PathParamMask, PendingState, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, RelativeToPathAutoComplete, ResolveRelativePath, RootRouteId, Route, RouteConfig, RouteConfigRoute, RouteInfo, RouteInfoById, RouteInfoByPath, RouteLoaders, RouteMatch, RouteMeta, RouteOptions, Router, RouterOptions, RouterState, RoutesById, RoutesInfoInner, SearchFilter, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, Timeout, ToIdOption, ToOptions, ToPathOption, UnloaderFn, Updater, ValidFromPath, ValueKeys, Values, cascadeLoaderData, cleanPath, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning };
612
+ export { Action, ActionFn, ActionState, AllRouteInfo, AnyAllRouteInfo, AnyLoaderData, AnyPathParams, AnyRoute, AnyRouteConfig, AnyRouteConfigWithChildren, AnyRouteInfo, AnySearchSchema, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, DeepAwaited, DefaultAllRouteInfo, DefinedPathParamWarning, Expand, FilterRoutesFn, FrameworkGenerics, FromLocation, GetFrameworkGeneric, IsAny, IsAnyBoolean, IsKnown, LinkInfo, LinkOptions, ListenerFn, Loader, LoaderContext, LoaderFn, LoaderState, Location, LocationState, MatchCacheEntry, MatchLocation, MatchRouteOptions, NavigateOptionsAbsolute, NoInfer, ParentParams, ParsePathParams, ParseRouteConfig, PathParamMask, PendingState, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, RelativeToPathAutoComplete, ResolveRelativePath, RootRouteId, Route, RouteConfig, RouteConfigRoute, RouteInfo, RouteInfoById, RouteInfoByPath, RouteMatch, RouteMeta, RouteOptions, Router, RouterOptions, RouterState, RoutesById, RoutesInfoInner, SearchFilter, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, Timeout, ToIdOption, ToOptions, ToPathOption, UnloaderFn, Updater, ValidFromPath, ValueKeys, Values, cascadeLoaderData, cleanPath, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning };
@@ -1260,6 +1260,40 @@
1260
1260
  return router.state.actions[id];
1261
1261
  })();
1262
1262
 
1263
+ const loader = router.state.loaders[id] || (() => {
1264
+ router.state.loaders[id] = {
1265
+ pending: [],
1266
+ fetch: async loaderContext => {
1267
+ if (!route) {
1268
+ return;
1269
+ }
1270
+
1271
+ const loaderState = {
1272
+ loadedAt: Date.now(),
1273
+ loaderContext
1274
+ };
1275
+ loader.current = loaderState;
1276
+ loader.latest = loaderState;
1277
+ loader.pending.push(loaderState); // router.state = {
1278
+ // ...router.state,
1279
+ // currentAction: loaderState,
1280
+ // latestAction: loaderState,
1281
+ // }
1282
+
1283
+ router.notify();
1284
+
1285
+ try {
1286
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1287
+ } finally {
1288
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1289
+
1290
+ router.notify();
1291
+ }
1292
+ }
1293
+ };
1294
+ return router.state.loaders[id];
1295
+ })();
1296
+
1263
1297
  let route = {
1264
1298
  routeId: id,
1265
1299
  routeRouteId: routeId,
@@ -1270,6 +1304,7 @@
1270
1304
  childRoutes: undefined,
1271
1305
  parentRoute: parent,
1272
1306
  action,
1307
+ loader: loader,
1273
1308
  buildLink: options => {
1274
1309
  return router.buildLink(_extends({}, options, {
1275
1310
  from: fullPath
@@ -1459,7 +1494,31 @@
1459
1494
  hasLoaders: () => {
1460
1495
  return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1461
1496
  },
1462
- load: async opts => {
1497
+ load: async loaderOpts => {
1498
+ const now = Date.now();
1499
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1500
+
1501
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1502
+ // If the match is currently active, don't preload it
1503
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1504
+ return;
1505
+ }
1506
+
1507
+ router.matchCache[routeMatch.matchId] = {
1508
+ gc: now + loaderOpts.gcMaxAge,
1509
+ match: routeMatch
1510
+ };
1511
+ } // If the match is invalid, errored or idle, trigger it to load
1512
+
1513
+
1514
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1515
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1516
+ routeMatch.fetch({
1517
+ maxAge
1518
+ });
1519
+ }
1520
+ },
1521
+ fetch: async opts => {
1463
1522
  const id = '' + Date.now() + Math.random();
1464
1523
  routeMatch.__.latestId = id; // If the match was in an error state, set it
1465
1524
  // to a loading state again. Otherwise, keep it
@@ -1489,12 +1548,7 @@
1489
1548
  return;
1490
1549
  }
1491
1550
 
1492
- if (typeof routeElement === 'function') {
1493
- const res = await routeElement(routeMatch);
1494
- routeMatch.__[type] = res;
1495
- } else {
1496
- routeMatch.__[type] = routeMatch.options[type];
1497
- }
1551
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1498
1552
  }));
1499
1553
  })();
1500
1554
 
@@ -1669,6 +1723,7 @@
1669
1723
  location: null,
1670
1724
  matches: [],
1671
1725
  actions: {},
1726
+ loaders: {},
1672
1727
  loaderData: {},
1673
1728
  lastUpdated: Date.now(),
1674
1729
  isFetching: false,
@@ -2005,32 +2060,11 @@
2005
2060
  return matches;
2006
2061
  },
2007
2062
  loadMatches: async (resolvedMatches, loaderOpts) => {
2008
- const now = Date.now();
2009
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2010
2063
  const matchPromises = resolvedMatches.map(async match => {
2011
2064
  // Validate the match (loads search params etc)
2012
- match.__.validate(); // If this is a preload, add it to the preload cache
2013
-
2014
-
2015
- if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2016
- // If the match is currently active, don't preload it
2017
- if (router.state.matches.find(d => d.matchId === match.matchId)) {
2018
- return;
2019
- }
2065
+ match.__.validate();
2020
2066
 
2021
- router.matchCache[match.matchId] = {
2022
- gc: now + loaderOpts.gcMaxAge,
2023
- match
2024
- };
2025
- } // If the match is invalid, errored or idle, trigger it to load
2026
-
2027
-
2028
- if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2029
- const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2030
- match.load({
2031
- maxAge
2032
- });
2033
- }
2067
+ match.load(loaderOpts);
2034
2068
 
2035
2069
  if (match.status === 'loading') {
2036
2070
  // If requested, start the pending timers