@tanstack/router-core 1.132.0-alpha.8 → 1.132.0

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.
Files changed (92) hide show
  1. package/dist/cjs/Matches.cjs +2 -1
  2. package/dist/cjs/Matches.cjs.map +1 -1
  3. package/dist/cjs/fileRoute.d.cts +3 -3
  4. package/dist/cjs/index.cjs +7 -2
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/cjs/index.d.cts +8 -4
  7. package/dist/cjs/load-matches.cjs +5 -3
  8. package/dist/cjs/load-matches.cjs.map +1 -1
  9. package/dist/cjs/location.d.cts +38 -0
  10. package/dist/cjs/path.cjs +27 -64
  11. package/dist/cjs/path.cjs.map +1 -1
  12. package/dist/cjs/path.d.cts +6 -7
  13. package/dist/cjs/process-route-tree.cjs +144 -0
  14. package/dist/cjs/process-route-tree.cjs.map +1 -0
  15. package/dist/cjs/process-route-tree.d.cts +10 -0
  16. package/dist/cjs/redirect.cjs +1 -1
  17. package/dist/cjs/redirect.cjs.map +1 -1
  18. package/dist/cjs/rewrite.cjs +63 -0
  19. package/dist/cjs/rewrite.cjs.map +1 -0
  20. package/dist/cjs/rewrite.d.cts +22 -0
  21. package/dist/cjs/route.cjs.map +1 -1
  22. package/dist/cjs/route.d.cts +55 -42
  23. package/dist/cjs/router.cjs +77 -184
  24. package/dist/cjs/router.cjs.map +1 -1
  25. package/dist/cjs/router.d.cts +68 -37
  26. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  27. package/dist/cjs/scroll-restoration.d.cts +9 -0
  28. package/dist/cjs/ssr/createRequestHandler.cjs +4 -1
  29. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  30. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
  31. package/dist/cjs/ssr/serializer/transformer.d.cts +10 -8
  32. package/dist/cjs/ssr/server.d.cts +0 -5
  33. package/dist/cjs/ssr/ssr-server.cjs +5 -2
  34. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  35. package/dist/cjs/ssr/ssr-server.d.cts +4 -1
  36. package/dist/cjs/utils.cjs +68 -46
  37. package/dist/cjs/utils.cjs.map +1 -1
  38. package/dist/esm/Matches.js +2 -1
  39. package/dist/esm/Matches.js.map +1 -1
  40. package/dist/esm/fileRoute.d.ts +3 -3
  41. package/dist/esm/index.d.ts +8 -4
  42. package/dist/esm/index.js +8 -3
  43. package/dist/esm/index.js.map +1 -1
  44. package/dist/esm/load-matches.js +5 -3
  45. package/dist/esm/load-matches.js.map +1 -1
  46. package/dist/esm/location.d.ts +38 -0
  47. package/dist/esm/path.d.ts +6 -7
  48. package/dist/esm/path.js +27 -64
  49. package/dist/esm/path.js.map +1 -1
  50. package/dist/esm/process-route-tree.d.ts +10 -0
  51. package/dist/esm/process-route-tree.js +144 -0
  52. package/dist/esm/process-route-tree.js.map +1 -0
  53. package/dist/esm/redirect.js +1 -1
  54. package/dist/esm/redirect.js.map +1 -1
  55. package/dist/esm/rewrite.d.ts +22 -0
  56. package/dist/esm/rewrite.js +63 -0
  57. package/dist/esm/rewrite.js.map +1 -0
  58. package/dist/esm/route.d.ts +55 -42
  59. package/dist/esm/route.js.map +1 -1
  60. package/dist/esm/router.d.ts +68 -37
  61. package/dist/esm/router.js +79 -186
  62. package/dist/esm/router.js.map +1 -1
  63. package/dist/esm/scroll-restoration.d.ts +9 -0
  64. package/dist/esm/scroll-restoration.js.map +1 -1
  65. package/dist/esm/ssr/createRequestHandler.js +4 -1
  66. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  67. package/dist/esm/ssr/serializer/transformer.d.ts +10 -8
  68. package/dist/esm/ssr/serializer/transformer.js.map +1 -1
  69. package/dist/esm/ssr/server.d.ts +0 -5
  70. package/dist/esm/ssr/ssr-server.d.ts +4 -1
  71. package/dist/esm/ssr/ssr-server.js +5 -2
  72. package/dist/esm/ssr/ssr-server.js.map +1 -1
  73. package/dist/esm/utils.js +68 -46
  74. package/dist/esm/utils.js.map +1 -1
  75. package/package.json +2 -2
  76. package/src/Matches.ts +2 -1
  77. package/src/fileRoute.ts +16 -6
  78. package/src/index.ts +11 -6
  79. package/src/load-matches.ts +29 -19
  80. package/src/location.ts +38 -0
  81. package/src/path.ts +44 -82
  82. package/src/process-route-tree.ts +233 -0
  83. package/src/redirect.ts +1 -1
  84. package/src/rewrite.ts +70 -0
  85. package/src/route.ts +214 -80
  86. package/src/router.ts +208 -329
  87. package/src/scroll-restoration.ts +1 -1
  88. package/src/ssr/createRequestHandler.ts +4 -1
  89. package/src/ssr/serializer/transformer.ts +17 -17
  90. package/src/ssr/server.ts +5 -5
  91. package/src/ssr/ssr-server.ts +8 -5
  92. package/src/utils.ts +83 -61
@@ -4,37 +4,38 @@ import { ParsePathnameCache } from './path.js';
4
4
  import { SearchParser, SearchSerializer } from './searchParams.js';
5
5
  import { AnyRedirect, ResolvedRedirect } from './redirect.js';
6
6
  import { HistoryLocation, HistoryState, ParsedHistoryState, RouterHistory } from '@tanstack/history';
7
- import { Awaitable, ControlledPromise, NoInfer, NonNullableUpdater, PickAsRequired, Updater } from './utils.js';
7
+ import { Awaitable, Constrain, ControlledPromise, NoInfer, NonNullableUpdater, PickAsRequired, Updater } from './utils.js';
8
8
  import { ParsedLocation } from './location.js';
9
- import { AnyContext, AnyRoute, AnyRouteWithContext, MakeRemountDepsOptionsUnion, RouteMask } from './route.js';
9
+ import { AnyContext, AnyRoute, AnyRouteWithContext, MakeRemountDepsOptionsUnion, RouteLike, RouteMask } from './route.js';
10
10
  import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.js';
11
11
  import { AnyRouteMatch, MakeRouteMatchUnion, MatchRouteOptions } from './Matches.js';
12
12
  import { BuildLocationFn, CommitLocationOptions, NavigateFn } from './RouterProvider.js';
13
13
  import { Manifest } from './manifest.js';
14
14
  import { AnySchema } from './validators.js';
15
15
  import { NavigateOptions, ResolveRelativePath, ToOptions } from './link.js';
16
- import { AnySerializationAdapter } from './ssr/serializer/transformer.js';
17
- import { AnyRouterConfig } from './config.js';
16
+ import { AnySerializationAdapter, ValidateSerializableInput } from './ssr/serializer/transformer.js';
18
17
  export type ControllablePromise<T = any> = Promise<T> & {
19
18
  resolve: (value: T) => void;
20
19
  reject: (value?: any) => void;
21
20
  };
22
21
  export type InjectedHtmlEntry = Promise<string>;
23
- export interface DefaultRegister {
24
- router: AnyRouter;
25
- config: AnyRouterConfig;
26
- ssr: SSROption;
22
+ export interface Register {
27
23
  }
28
- export interface Register extends DefaultRegister {
29
- }
30
- export type RegisteredRouter = Register['router'];
24
+ export type RegisteredRouter<TRegister = Register> = TRegister extends {
25
+ router: infer TRouter;
26
+ } ? TRouter : AnyRouter;
27
+ export type RegisteredConfigType<TRegister, TKey> = TRegister extends {
28
+ config: infer TConfig;
29
+ } ? TConfig extends {
30
+ '~types': infer TTypes;
31
+ } ? TKey extends keyof TTypes ? TTypes[TKey] : unknown : unknown : unknown;
31
32
  export type DefaultRemountDepsFn<TRouteTree extends AnyRoute> = (opts: MakeRemountDepsOptionsUnion<TRouteTree>) => any;
32
33
  export interface DefaultRouterOptionsExtensions {
33
34
  }
34
35
  export interface RouterOptionsExtensions extends DefaultRouterOptionsExtensions {
35
36
  }
36
37
  export type SSROption = boolean | 'data-only';
37
- export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean = false, TRouterHistory extends RouterHistory = RouterHistory, TDehydrated extends Record<string, any> = Record<string, any>> extends RouterOptionsExtensions {
38
+ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean = false, TRouterHistory extends RouterHistory = RouterHistory, TDehydrated = undefined> extends RouterOptionsExtensions {
38
39
  /**
39
40
  * The history object that will be used to manage the browser history.
40
41
  *
@@ -178,6 +179,18 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
178
179
  /**
179
180
  * The basepath for then entire router. This is useful for mounting a router instance at a subpath.
180
181
  *
182
+ * @deprecated - use `rewrite.input` with the new `rewriteBasepath` utility instead:
183
+ * ```ts
184
+ * const router = createRouter({
185
+ * routeTree,
186
+ * rewrite: rewriteBasepath('/basepath')
187
+ * // Or wrap existing rewrite functionality
188
+ * rewrite: rewriteBasepath('/basepath', {
189
+ * output: ({ url }) => {...},
190
+ * input: ({ url }) => {...},
191
+ * })
192
+ * })
193
+ * ```
181
194
  * @default '/'
182
195
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#basepath-property)
183
196
  */
@@ -193,6 +206,7 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
193
206
  * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/router-context)
194
207
  */
195
208
  context?: InferRouterContext<TRouteTree>;
209
+ additionalContext?: any;
196
210
  /**
197
211
  * A function that will be called when the router is dehydrated.
198
212
  *
@@ -201,7 +215,7 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
201
215
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#dehydrate-method)
202
216
  * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/external-data-loading#critical-dehydrationhydration)
203
217
  */
204
- dehydrate?: () => Awaitable<TDehydrated>;
218
+ dehydrate?: () => Constrain<TDehydrated, ValidateSerializableInput<Register, TDehydrated>>;
205
219
  /**
206
220
  * A function that will be called when the router is hydrated.
207
221
  *
@@ -328,7 +342,44 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
328
342
  */
329
343
  disableGlobalCatchBoundary?: boolean;
330
344
  serializationAdapters?: ReadonlyArray<AnySerializationAdapter>;
345
+ /**
346
+ * Configures how the router will rewrite the location between the actual href and the internal href of the router.
347
+ *
348
+ * @default undefined
349
+ * @description You can provide a custom rewrite pair (in/out) or use the utilities like `rewriteBasepath` as a convenience for common use cases, or even do both!
350
+ * This is useful for basepath rewriting, shifting data from the origin to the path (for things like )
351
+ */
352
+ rewrite?: LocationRewrite;
353
+ origin?: string;
354
+ ssr?: {
355
+ nonce?: string;
356
+ };
331
357
  }
358
+ export type LocationRewrite = {
359
+ /**
360
+ * A function that will be called to rewrite the URL before it is interpreted by the router from the history instance.
361
+ * Utilities like `rewriteBasepath` are provided as a convenience for common use cases.
362
+ *
363
+ * @default undefined
364
+ */
365
+ input?: LocationRewriteFunction;
366
+ /**
367
+ * A function that will be called to rewrite the URL before it is committed to the actual history instance from the router.
368
+ * Utilities like `rewriteBasepath` are provided as a convenience for common use cases.
369
+ *
370
+ * @default undefined
371
+ */
372
+ output?: LocationRewriteFunction;
373
+ };
374
+ /**
375
+ * A function that will be called to rewrite the URL.
376
+ *
377
+ * @param url The URL to rewrite.
378
+ * @returns The rewritten URL (as a URL instance or full href string) or undefined if no rewrite is needed.
379
+ */
380
+ export type LocationRewriteFunction = ({ url, }: {
381
+ url: URL;
382
+ }) => undefined | string | URL;
332
383
  export interface RouterState<in out TRouteTree extends AnyRoute = AnyRoute, in out TRouteMatch = MakeRouteMatchUnion> {
333
384
  status: 'pending' | 'idle';
334
385
  loadedAt: number;
@@ -408,7 +459,7 @@ export type RouterContextOptions<TRouteTree extends AnyRoute> = AnyContext exten
408
459
  } : {
409
460
  context: InferRouterContext<TRouteTree>;
410
461
  };
411
- export type RouterConstructorOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory, TDehydrated extends Record<string, any>> = Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>, 'context'> & RouterContextOptions<TRouteTree>;
462
+ export type RouterConstructorOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory, TDehydrated extends Record<string, any>> = Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>, 'context' | 'serializationAdapters' | 'defaultSsr'> & RouterContextOptions<TRouteTree>;
412
463
  export type PreloadRouteFn<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory> = <TFrom extends RoutePaths<TRouteTree> | string = string, TTo extends string | undefined = undefined, TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom, TMaskTo extends string = ''>(opts: NavigateOptions<RouterCore<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>, TFrom, TTo, TMaskFrom, TMaskTo>) => Promise<Array<AnyRouteMatch> | undefined>;
413
464
  export type MatchRouteFn<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory> = <TFrom extends RoutePaths<TRouteTree> = '/', TTo extends string | undefined = undefined, TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>>(location: ToOptions<RouterCore<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>, TFrom, TTo>, opts?: MatchRouteOptions) => false | RouteById<TRouteTree, TResolved>['types']['allParams'];
414
465
  export type UpdateFn<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory, TDehydrated extends Record<string, any>> = (newOptions: RouterConstructorOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>) => void;
@@ -495,6 +546,8 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
495
546
  __store: Store<RouterState<TRouteTree>>;
496
547
  options: PickAsRequired<RouterOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>, 'stringifySearch' | 'parseSearch' | 'context'>;
497
548
  history: TRouterHistory;
549
+ rewrite?: LocationRewrite;
550
+ origin?: string;
498
551
  latestLocation: ParsedLocation<FullSearchSchema<TRouteTree>>;
499
552
  basepath: string;
500
553
  routeTree: TRouteTree;
@@ -556,31 +609,9 @@ export declare class PathParamError extends Error {
556
609
  }
557
610
  export declare function lazyFn<T extends Record<string, (...args: Array<any>) => any>, TKey extends keyof T = 'default'>(fn: () => Promise<T>, key?: TKey): (...args: Parameters<T[TKey]>) => Promise<Awaited<ReturnType<T[TKey]>>>;
558
611
  export declare function getInitialRouterState(location: ParsedLocation): RouterState<any>;
559
- interface RouteLike {
560
- id: string;
561
- isRoot?: boolean;
562
- path?: string;
563
- fullPath: string;
564
- rank?: number;
565
- parentRoute?: RouteLike;
566
- children?: Array<RouteLike>;
567
- options?: {
568
- caseSensitive?: boolean;
569
- };
570
- }
571
- export type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {
572
- routesById: Record<string, TRouteLike>;
573
- routesByPath: Record<string, TRouteLike>;
574
- flatRoutes: Array<TRouteLike>;
575
- };
576
- export declare function processRouteTree<TRouteLike extends RouteLike>({ routeTree, initRoute, }: {
577
- routeTree: TRouteLike;
578
- initRoute?: (route: TRouteLike, index: number) => void;
579
- }): ProcessRouteTreeResult<TRouteLike>;
580
- export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routePathname, basepath, caseSensitive, routesByPath, routesById, flatRoutes, parseCache, }: {
612
+ export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routePathname, caseSensitive, routesByPath, routesById, flatRoutes, parseCache, }: {
581
613
  pathname: string;
582
614
  routePathname?: string;
583
- basepath: string;
584
615
  caseSensitive?: boolean;
585
616
  routesByPath: Record<string, TRouteLike>;
586
617
  routesById: Record<string, TRouteLike>;
@@ -1,8 +1,8 @@
1
1
  import { Store, batch } from "@tanstack/store";
2
- import { createMemoryHistory, createBrowserHistory, parseHref } from "@tanstack/history";
3
- import invariant from "tiny-invariant";
2
+ import { createBrowserHistory, parseHref } from "@tanstack/history";
4
3
  import { createControlledPromise, deepEqual, replaceEqualDeep, last, findLast, functionalUpdate } from "./utils.js";
5
- import { trimPath, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths, trimPathLeft, parsePathname, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM, SEGMENT_TYPE_WILDCARD, SEGMENT_TYPE_PATHNAME } from "./path.js";
4
+ import { processRouteTree } from "./process-route-tree.js";
5
+ import { resolvePath, cleanPath, trimPathRight, trimPath, matchPathname, interpolatePath } from "./path.js";
6
6
  import { isNotFound } from "./not-found.js";
7
7
  import { setupScrollRestoration } from "./scroll-restoration.js";
8
8
  import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
@@ -10,6 +10,7 @@ import { rootRouteId } from "./root.js";
10
10
  import { redirect, isRedirect } from "./redirect.js";
11
11
  import { createLRUCache } from "./lru-cache.js";
12
12
  import { loadMatches, loadRouteChunk, routeNeedsPreload } from "./load-matches.js";
13
+ import { rewriteBasepath, composeRewrites, executeRewriteInput, executeRewriteOutput } from "./rewrite.js";
13
14
  function defaultSerializeError(err) {
14
15
  if (err instanceof Error) {
15
16
  const obj = {
@@ -54,7 +55,6 @@ class RouterCore {
54
55
  "The notFoundRoute API is deprecated and will be removed in the next major version. See https://tanstack.com/router/v1/docs/framework/react/guide/not-found-errors#migrating-from-notfoundroute for more info."
55
56
  );
56
57
  }
57
- const previousOptions = this.options;
58
58
  this.options = {
59
59
  ...this.options,
60
60
  ...newOptions
@@ -66,24 +66,43 @@ class RouterCore {
66
66
  char
67
67
  ])
68
68
  ) : void 0;
69
- if (!this.basepath || newOptions.basepath && newOptions.basepath !== previousOptions.basepath) {
70
- if (newOptions.basepath === void 0 || newOptions.basepath === "" || newOptions.basepath === "/") {
71
- this.basepath = "/";
69
+ if (!this.history || this.options.history && this.options.history !== this.history) {
70
+ if (!this.options.history) {
71
+ if (!this.isServer) {
72
+ this.history = createBrowserHistory();
73
+ }
72
74
  } else {
73
- this.basepath = `/${trimPath(newOptions.basepath)}`;
75
+ this.history = this.options.history;
74
76
  }
75
77
  }
76
- if (!this.history || this.options.history && this.options.history !== this.history) {
77
- this.history = this.options.history ?? (this.isServer ? createMemoryHistory({
78
- initialEntries: [this.basepath || "/"]
79
- }) : createBrowserHistory());
78
+ if (this.options.basepath) {
79
+ const basepathRewrite = rewriteBasepath({
80
+ basepath: this.options.basepath
81
+ });
82
+ if (this.options.rewrite) {
83
+ this.rewrite = composeRewrites([basepathRewrite, this.options.rewrite]);
84
+ } else {
85
+ this.rewrite = basepathRewrite;
86
+ }
87
+ } else {
88
+ this.rewrite = this.options.rewrite;
89
+ }
90
+ this.origin = this.options.origin;
91
+ if (!this.origin) {
92
+ if (!this.isServer) {
93
+ this.origin = window.origin;
94
+ } else {
95
+ this.origin = "http://localhost";
96
+ }
97
+ }
98
+ if (this.history) {
80
99
  this.updateLatestLocation();
81
100
  }
82
101
  if (this.options.routeTree !== this.routeTree) {
83
102
  this.routeTree = this.options.routeTree;
84
103
  this.buildRouteTree();
85
104
  }
86
- if (!this.__store) {
105
+ if (!this.__store && this.latestLocation) {
87
106
  this.__store = new Store(getInitialRouterState(this.latestLocation), {
88
107
  onUpdate: () => {
89
108
  this.__store.state = {
@@ -147,19 +166,24 @@ class RouterCore {
147
166
  };
148
167
  this.parseLocation = (locationToParse, previousLocation) => {
149
168
  const parse = ({
150
- pathname,
151
- search,
152
- hash,
169
+ href,
153
170
  state
154
171
  }) => {
155
- const parsedSearch = this.options.parseSearch(search);
172
+ const fullUrl = new URL(href, this.origin);
173
+ const url = executeRewriteInput(this.rewrite, fullUrl);
174
+ const parsedSearch = this.options.parseSearch(url.search);
156
175
  const searchStr = this.options.stringifySearch(parsedSearch);
176
+ url.search = searchStr;
177
+ const fullPath = url.href.replace(url.origin, "");
178
+ const { pathname, hash } = url;
157
179
  return {
180
+ href: fullPath,
181
+ publicHref: href,
182
+ url: url.href,
158
183
  pathname,
159
184
  searchStr,
160
185
  search: replaceEqualDeep(previousLocation?.search, parsedSearch),
161
186
  hash: hash.split("#").reverse()[0] ?? "",
162
- href: `${pathname}${searchStr}${hash}`,
163
187
  state: replaceEqualDeep(previousLocation?.state, state)
164
188
  };
165
189
  };
@@ -179,11 +203,9 @@ class RouterCore {
179
203
  };
180
204
  this.resolvePathWithBase = (from, path) => {
181
205
  const resolvedPath = resolvePath({
182
- basepath: this.basepath,
183
206
  base: from,
184
207
  to: cleanPath(path),
185
208
  trailingSlash: this.options.trailingSlash,
186
- caseSensitive: this.options.caseSensitive,
187
209
  parseCache: this.parsePathnameCache
188
210
  });
189
211
  return resolvedPath;
@@ -205,7 +227,6 @@ class RouterCore {
205
227
  return getMatchedRoutes({
206
228
  pathname,
207
229
  routePathname,
208
- basepath: this.basepath,
209
230
  caseSensitive: this.options.caseSensitive,
210
231
  routesByPath: this.routesByPath,
211
232
  routesById: this.routesById,
@@ -313,13 +334,18 @@ class RouterCore {
313
334
  const hashStr = hash ? `#${hash}` : "";
314
335
  let nextState = dest.state === true ? currentLocation.state : dest.state ? functionalUpdate(dest.state, currentLocation.state) : {};
315
336
  nextState = replaceEqualDeep(currentLocation.state, nextState);
337
+ const fullPath = `${nextPathname}${searchStr}${hashStr}`;
338
+ const url = new URL(fullPath, this.origin);
339
+ const rewrittenUrl = executeRewriteOutput(this.rewrite, url);
316
340
  return {
341
+ publicHref: rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
342
+ href: fullPath,
343
+ url: rewrittenUrl.href,
317
344
  pathname: nextPathname,
318
345
  search: nextSearch,
319
346
  searchStr,
320
347
  state: nextState,
321
348
  hash: hash ?? "",
322
- href: `${nextPathname}${searchStr}${hashStr}`,
323
349
  unmaskOnReload: dest.unmaskOnReload
324
350
  };
325
351
  };
@@ -330,7 +356,6 @@ class RouterCore {
330
356
  let params = {};
331
357
  const foundMask = this.options.routeMasks?.find((d) => {
332
358
  const match = matchPathname(
333
- this.basepath,
334
359
  next.pathname,
335
360
  {
336
361
  to: d.from,
@@ -356,8 +381,7 @@ class RouterCore {
356
381
  }
357
382
  }
358
383
  if (maskedNext) {
359
- const maskedFinal = build(maskedDest);
360
- next.maskedLocation = maskedFinal;
384
+ next.maskedLocation = maskedNext;
361
385
  }
362
386
  return next;
363
387
  };
@@ -391,7 +415,7 @@ class RouterCore {
391
415
  });
392
416
  return isEqual;
393
417
  };
394
- const isSameUrl = this.latestLocation.href === next.href;
418
+ const isSameUrl = trimPathRight(this.latestLocation.href) === trimPathRight(next.href);
395
419
  const previousCommitPromise = this.commitLocationPromise;
396
420
  this.commitLocationPromise = createControlledPromise(() => {
397
421
  previousCommitPromise?.resolve();
@@ -427,7 +451,7 @@ class RouterCore {
427
451
  nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
428
452
  this.shouldViewTransition = viewTransition;
429
453
  this.history[next.replace ? "replace" : "push"](
430
- nextHistory.href,
454
+ nextHistory.publicHref,
431
455
  nextHistory.state,
432
456
  { ignoreBlocker }
433
457
  );
@@ -480,7 +504,7 @@ class RouterCore {
480
504
  if (reloadDocument) {
481
505
  if (!href) {
482
506
  const location = this.buildLocation({ to, ...rest });
483
- href = this.history.createHref(location.href);
507
+ href = location.href;
484
508
  }
485
509
  if (rest.replace) {
486
510
  window.location.replace(href);
@@ -827,7 +851,6 @@ class RouterCore {
827
851
  const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
828
852
  const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
829
853
  const match = matchPathname(
830
- this.basepath,
831
854
  baseLocation.pathname,
832
855
  {
833
856
  ...opts,
@@ -913,25 +936,6 @@ class RouterCore {
913
936
  }
914
937
  return rootRouteId;
915
938
  })();
916
- const parseErrors = matchedRoutes.map((route) => {
917
- let parsedParamsError;
918
- const parseParams = route.options.params?.parse ?? route.options.parseParams;
919
- if (parseParams) {
920
- try {
921
- const parsedParams = parseParams(routeParams);
922
- Object.assign(routeParams, parsedParams);
923
- } catch (err) {
924
- parsedParamsError = new PathParamError(err.message, {
925
- cause: err
926
- });
927
- if (opts?.throwOnError) {
928
- throw parsedParamsError;
929
- }
930
- return parsedParamsError;
931
- }
932
- }
933
- return;
934
- });
935
939
  const matches = [];
936
940
  const getParentContext = (parentMatch) => {
937
941
  const parentMatchId = parentMatch?.id;
@@ -970,7 +974,7 @@ class RouterCore {
970
974
  search: preMatchSearch
971
975
  }) ?? "";
972
976
  const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
973
- const { usedParams, interpolatedPath } = interpolatePath({
977
+ const { interpolatedPath, usedParams } = interpolatePath({
974
978
  path: route.fullPath,
975
979
  params: routeParams,
976
980
  decodeCharMap: this.pathParamsDecodeCharMap
@@ -986,6 +990,27 @@ class RouterCore {
986
990
  const previousMatch = this.state.matches.find(
987
991
  (d) => d.routeId === route.id
988
992
  );
993
+ const strictParams = existingMatch?._strictParams ?? usedParams;
994
+ let paramsError = void 0;
995
+ if (!existingMatch) {
996
+ const strictParseParams = route.options.params?.parse ?? route.options.parseParams;
997
+ if (strictParseParams) {
998
+ try {
999
+ Object.assign(
1000
+ strictParams,
1001
+ strictParseParams(strictParams)
1002
+ );
1003
+ } catch (err) {
1004
+ paramsError = new PathParamError(err.message, {
1005
+ cause: err
1006
+ });
1007
+ if (opts?.throwOnError) {
1008
+ throw paramsError;
1009
+ }
1010
+ }
1011
+ }
1012
+ }
1013
+ Object.assign(routeParams, strictParams);
989
1014
  const cause = previousMatch ? "stay" : "enter";
990
1015
  let match;
991
1016
  if (existingMatch) {
@@ -993,7 +1018,7 @@ class RouterCore {
993
1018
  ...existingMatch,
994
1019
  cause,
995
1020
  params: previousMatch ? replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
996
- _strictParams: usedParams,
1021
+ _strictParams: strictParams,
997
1022
  search: previousMatch ? replaceEqualDeep(previousMatch.search, preMatchSearch) : replaceEqualDeep(existingMatch.search, preMatchSearch),
998
1023
  _strictSearch: strictMatchSearch
999
1024
  };
@@ -1004,8 +1029,8 @@ class RouterCore {
1004
1029
  index,
1005
1030
  routeId: route.id,
1006
1031
  params: previousMatch ? replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
1007
- _strictParams: usedParams,
1008
- pathname: joinPaths([this.basepath, interpolatedPath]),
1032
+ _strictParams: strictParams,
1033
+ pathname: interpolatedPath,
1009
1034
  updatedAt: Date.now(),
1010
1035
  search: previousMatch ? replaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
1011
1036
  _strictSearch: strictMatchSearch,
@@ -1013,7 +1038,7 @@ class RouterCore {
1013
1038
  status,
1014
1039
  isFetching: false,
1015
1040
  error: void 0,
1016
- paramsError: parseErrors[index],
1041
+ paramsError,
1017
1042
  __routeContext: void 0,
1018
1043
  _nonReactive: {
1019
1044
  loadPromise: createControlledPromise()
@@ -1125,139 +1150,9 @@ function validateSearch(validateSearch2, input) {
1125
1150
  }
1126
1151
  return {};
1127
1152
  }
1128
- const REQUIRED_PARAM_BASE_SCORE = 0.5;
1129
- const OPTIONAL_PARAM_BASE_SCORE = 0.4;
1130
- const WILDCARD_PARAM_BASE_SCORE = 0.25;
1131
- const BOTH_PRESENCE_BASE_SCORE = 0.05;
1132
- const PREFIX_PRESENCE_BASE_SCORE = 0.02;
1133
- const SUFFIX_PRESENCE_BASE_SCORE = 0.01;
1134
- const PREFIX_LENGTH_SCORE_MULTIPLIER = 2e-4;
1135
- const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1e-4;
1136
- function handleParam(segment, baseScore) {
1137
- if (segment.prefixSegment && segment.suffixSegment) {
1138
- return baseScore + BOTH_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
1139
- }
1140
- if (segment.prefixSegment) {
1141
- return baseScore + PREFIX_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length;
1142
- }
1143
- if (segment.suffixSegment) {
1144
- return baseScore + SUFFIX_PRESENCE_BASE_SCORE + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
1145
- }
1146
- return baseScore;
1147
- }
1148
- function processRouteTree({
1149
- routeTree,
1150
- initRoute
1151
- }) {
1152
- const routesById = {};
1153
- const routesByPath = {};
1154
- const recurseRoutes = (childRoutes) => {
1155
- childRoutes.forEach((childRoute, i) => {
1156
- initRoute?.(childRoute, i);
1157
- const existingRoute = routesById[childRoute.id];
1158
- invariant(
1159
- !existingRoute,
1160
- `Duplicate routes found with id: ${String(childRoute.id)}`
1161
- );
1162
- routesById[childRoute.id] = childRoute;
1163
- if (!childRoute.isRoot && childRoute.path) {
1164
- const trimmedFullPath = trimPathRight(childRoute.fullPath);
1165
- if (!routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
1166
- routesByPath[trimmedFullPath] = childRoute;
1167
- }
1168
- }
1169
- const children = childRoute.children;
1170
- if (children?.length) {
1171
- recurseRoutes(children);
1172
- }
1173
- });
1174
- };
1175
- recurseRoutes([routeTree]);
1176
- const scoredRoutes = [];
1177
- const routes = Object.values(routesById);
1178
- routes.forEach((d, i) => {
1179
- if (d.isRoot || !d.path) {
1180
- return;
1181
- }
1182
- const trimmed = trimPathLeft(d.fullPath);
1183
- let parsed = parsePathname(trimmed);
1184
- let skip = 0;
1185
- while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
1186
- skip++;
1187
- }
1188
- if (skip > 0) parsed = parsed.slice(skip);
1189
- let optionalParamCount = 0;
1190
- let hasStaticAfter = false;
1191
- const scores = parsed.map((segment, index) => {
1192
- if (segment.value === "/") {
1193
- return 0.75;
1194
- }
1195
- let baseScore = void 0;
1196
- if (segment.type === SEGMENT_TYPE_PARAM) {
1197
- baseScore = REQUIRED_PARAM_BASE_SCORE;
1198
- } else if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {
1199
- baseScore = OPTIONAL_PARAM_BASE_SCORE;
1200
- optionalParamCount++;
1201
- } else if (segment.type === SEGMENT_TYPE_WILDCARD) {
1202
- baseScore = WILDCARD_PARAM_BASE_SCORE;
1203
- }
1204
- if (baseScore) {
1205
- for (let i2 = index + 1; i2 < parsed.length; i2++) {
1206
- const nextSegment = parsed[i2];
1207
- if (nextSegment.type === SEGMENT_TYPE_PATHNAME && nextSegment.value !== "/") {
1208
- hasStaticAfter = true;
1209
- return handleParam(segment, baseScore + 0.2);
1210
- }
1211
- }
1212
- return handleParam(segment, baseScore);
1213
- }
1214
- return 1;
1215
- });
1216
- scoredRoutes.push({
1217
- child: d,
1218
- trimmed,
1219
- parsed,
1220
- index: i,
1221
- scores,
1222
- optionalParamCount,
1223
- hasStaticAfter
1224
- });
1225
- });
1226
- const flatRoutes = scoredRoutes.sort((a, b) => {
1227
- const minLength = Math.min(a.scores.length, b.scores.length);
1228
- for (let i = 0; i < minLength; i++) {
1229
- if (a.scores[i] !== b.scores[i]) {
1230
- return b.scores[i] - a.scores[i];
1231
- }
1232
- }
1233
- if (a.scores.length !== b.scores.length) {
1234
- if (a.optionalParamCount !== b.optionalParamCount) {
1235
- if (a.hasStaticAfter === b.hasStaticAfter) {
1236
- return a.optionalParamCount - b.optionalParamCount;
1237
- } else if (a.hasStaticAfter && !b.hasStaticAfter) {
1238
- return -1;
1239
- } else if (!a.hasStaticAfter && b.hasStaticAfter) {
1240
- return 1;
1241
- }
1242
- }
1243
- return b.scores.length - a.scores.length;
1244
- }
1245
- for (let i = 0; i < minLength; i++) {
1246
- if (a.parsed[i].value !== b.parsed[i].value) {
1247
- return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
1248
- }
1249
- }
1250
- return a.index - b.index;
1251
- }).map((d, i) => {
1252
- d.child.rank = i;
1253
- return d.child;
1254
- });
1255
- return { routesById, routesByPath, flatRoutes };
1256
- }
1257
1153
  function getMatchedRoutes({
1258
1154
  pathname,
1259
1155
  routePathname,
1260
- basepath,
1261
1156
  caseSensitive,
1262
1157
  routesByPath,
1263
1158
  routesById,
@@ -1268,7 +1163,6 @@ function getMatchedRoutes({
1268
1163
  const trimmedPath = trimPathRight(pathname);
1269
1164
  const getMatchedParams = (route) => {
1270
1165
  const result = matchPathname(
1271
- basepath,
1272
1166
  trimmedPath,
1273
1167
  {
1274
1168
  to: route.fullPath,
@@ -1398,7 +1292,6 @@ export {
1398
1292
  getInitialRouterState,
1399
1293
  getLocationChangeInfo,
1400
1294
  getMatchedRoutes,
1401
- lazyFn,
1402
- processRouteTree
1295
+ lazyFn
1403
1296
  };
1404
1297
  //# sourceMappingURL=router.js.map