@tanstack/router-core 1.171.25 → 1.171.26

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.
package/src/path.ts CHANGED
@@ -112,13 +112,25 @@ export function resolvePath({
112
112
  trailingSlash = 'never',
113
113
  cache,
114
114
  }: ResolvePathOptions) {
115
- const isBase = to === '.'
116
- const isAbsolute = to.startsWith('/')
115
+ if (to.includes('//')) {
116
+ to = cleanPath(to)
117
+ }
118
+
119
+ if (to.startsWith('/')) {
120
+ if (to.length === 1 || trailingSlash === 'preserve') {
121
+ return to
122
+ }
123
+ if (trailingSlash === 'always') {
124
+ return to.endsWith('/') ? to : `${to}/`
125
+ }
126
+ return to.endsWith('/') ? to.slice(0, -1) : to
127
+ }
117
128
 
129
+ const isBase = to === '.'
118
130
  let key
119
131
  if (cache) {
120
132
  // `trailingSlash` is static per router, so it doesn't need to be part of the cache key
121
- key = isAbsolute ? to : isBase ? base : base + '\0' + to
133
+ key = isBase ? base : base + '\0' + to
122
134
  const cached = cache.get(key)
123
135
  if (cached) return cached
124
136
  }
@@ -126,9 +138,10 @@ export function resolvePath({
126
138
  let baseSegments: Array<string>
127
139
  if (isBase) {
128
140
  baseSegments = base.split('/')
129
- } else if (isAbsolute) {
130
- baseSegments = to.split('/')
131
141
  } else {
142
+ if (base.includes('//')) {
143
+ base = cleanPath(base)
144
+ }
132
145
  baseSegments = base.split('/')
133
146
  while (baseSegments.length > 1 && last(baseSegments) === '') {
134
147
  baseSegments.pop()
@@ -171,7 +184,8 @@ export function resolvePath({
171
184
  }
172
185
  }
173
186
 
174
- const result = cleanPath(baseSegments.join('/')) || '/'
187
+ const joined = baseSegments.join('/')
188
+ const result = (isBase ? cleanPath(joined) : joined) || '/'
175
189
  if (key && cache) cache.set(key, result)
176
190
  return result
177
191
  }
package/src/router.ts CHANGED
@@ -22,7 +22,6 @@ import {
22
22
  processRouteTree,
23
23
  } from './new-process-route-tree'
24
24
  import {
25
- cleanPath,
26
25
  compileDecodeCharMap,
27
26
  interpolatePath,
28
27
  resolvePath,
@@ -1469,7 +1468,7 @@ export class RouterCore<
1469
1468
  resolvePathWithBase = (from: string, path: string) => {
1470
1469
  return resolvePath({
1471
1470
  base: from,
1472
- to: path.includes('//') ? cleanPath(path) : path,
1471
+ to: path,
1473
1472
  trailingSlash: this.options.trailingSlash,
1474
1473
  cache: this.resolvePathCache,
1475
1474
  })
@@ -1892,28 +1891,19 @@ export class RouterCore<
1892
1891
  dest.unsafeRelative === 'path'
1893
1892
  ? currentLocation.pathname
1894
1893
  : (dest.from ?? lightweightResult[1 /* fullPath */])
1895
- const destTo = dest.to ? `${dest.to}` : undefined
1896
1894
 
1897
1895
  // From search should always use the current location
1898
1896
  const fromSearch = lightweightResult[2 /* search */]
1899
1897
  // Same with params. It can't hurt to provide as many as possible
1900
- const fromParams = Object.assign(
1901
- Object.create(null),
1902
- lightweightResult[3 /* params */],
1903
- )
1904
-
1905
- const isAbsoluteTo = destTo?.charCodeAt(0) === 47
1906
- const sourcePath = isAbsoluteTo
1907
- ? '/'
1908
- : this.resolvePathWithBase(defaultedFromPath, '.')
1898
+ const fromParams = lightweightResult[3 /* params */]
1909
1899
 
1910
- // Resolve the destination. Absolute destinations don't need the source path.
1911
- const nextTo = destTo
1912
- ? this.resolvePathWithBase(sourcePath, destTo)
1913
- : sourcePath
1900
+ const nextTo = this.resolvePathWithBase(
1901
+ defaultedFromPath,
1902
+ dest.to ? `${dest.to}` : '.',
1903
+ )
1914
1904
 
1915
1905
  // Resolve the next params
1916
- const nextParams = resolveNextParams(dest.params, fromParams)
1906
+ let nextParams = resolveNextParams(dest.params, fromParams)
1917
1907
 
1918
1908
  const destRoute = this.routesByPath[
1919
1909
  trimPathRight(nextTo) as keyof typeof this.routesByPath
@@ -1945,6 +1935,9 @@ export class RouterCore<
1945
1935
  const fn =
1946
1936
  route.options.params?.stringify ?? route.options.stringifyParams
1947
1937
  if (fn) {
1938
+ if (nextParams === fromParams) {
1939
+ nextParams = Object.assign(Object.create(null), nextParams)
1940
+ }
1948
1941
  try {
1949
1942
  Object.assign(nextParams, fn(nextParams))
1950
1943
  } catch {
@@ -2043,7 +2036,9 @@ export class RouterCore<
2043
2036
  : {}
2044
2037
 
2045
2038
  // Replace the equal deep
2046
- nextState = replaceEqualDeep(currentLocation.state, nextState)
2039
+ if (dest.state) {
2040
+ nextState = replaceEqualDeep(currentLocation.state, nextState)
2041
+ }
2047
2042
 
2048
2043
  // Create the full path of the location
2049
2044
  const fullPath = `${nextPathname}${searchStr}${hashStr}`
@@ -2777,24 +2772,22 @@ function applySearchMiddleware(
2777
2772
  }
2778
2773
 
2779
2774
  const routeValidateSearch = routeOptions.validateSearch
2780
- if (routeValidateSearch) {
2775
+ if (includeValidateSearch && routeValidateSearch) {
2781
2776
  const validate: SearchMiddleware<any> = ({ search, next, meta }) => {
2782
2777
  const result = next(search)
2783
- if (includeValidateSearch) {
2784
- try {
2785
- const validated = validateSearch(routeValidateSearch, result) as any
2786
-
2787
- if (meta && validated) {
2788
- for (const key in validated) {
2789
- if (!(key in result)) {
2790
- ;(meta.defaulted ||= new Map()).set(key, validated[key])
2791
- }
2778
+ try {
2779
+ const validated = validateSearch(routeValidateSearch, result) as any
2780
+
2781
+ if (meta && validated) {
2782
+ for (const key in validated) {
2783
+ if (!(key in result)) {
2784
+ ;(meta.defaulted ||= new Map()).set(key, validated[key])
2792
2785
  }
2793
2786
  }
2794
- return { ...result, ...validated }
2795
- } catch {
2796
- // ignore errors here because they are already handled in matchRoutes
2797
2787
  }
2788
+ return { ...result, ...validated }
2789
+ } catch {
2790
+ // ignore errors here because they are already handled in matchRoutes
2798
2791
  }
2799
2792
  return result
2800
2793
  }
@@ -2864,11 +2857,14 @@ function resolveNextParams(
2864
2857
  spec: unknown,
2865
2858
  base: Record<string, unknown>,
2866
2859
  ): Record<string, unknown> {
2867
- return spec === false || spec === null
2868
- ? Object.create(null)
2869
- : (spec ?? true) === true
2870
- ? base
2871
- : Object.assign(base, functionalUpdate(spec as any, base))
2860
+ if (spec === false || spec === null) {
2861
+ return Object.create(null)
2862
+ }
2863
+ if ((spec ?? true) === true) {
2864
+ return base
2865
+ }
2866
+ const next = Object.assign(Object.create(null), base)
2867
+ return Object.assign(next, functionalUpdate(spec as any, next))
2872
2868
  }
2873
2869
 
2874
2870
  function extractStrictParams(