@tanstack/router-core 1.157.7 → 1.157.9
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/dist/cjs/path.cjs +46 -1
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +1 -1
- package/dist/cjs/router.cjs +10 -4
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/esm/path.d.ts +1 -1
- package/dist/esm/path.js +46 -1
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/router.js +10 -4
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
- package/src/path.ts +66 -0
- package/src/router.ts +13 -5
package/package.json
CHANGED
package/src/path.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isServer } from '@tanstack/router-core/isServer'
|
|
1
2
|
import { last } from './utils'
|
|
2
3
|
import {
|
|
3
4
|
SEGMENT_TYPE_OPTIONAL_PARAM,
|
|
@@ -224,6 +225,11 @@ interface InterpolatePathOptions {
|
|
|
224
225
|
* Obtained from `compileDecodeCharMap(pathParamsAllowedCharacters)`.
|
|
225
226
|
*/
|
|
226
227
|
decoder?: (encoded: string) => string
|
|
228
|
+
/**
|
|
229
|
+
* @internal
|
|
230
|
+
* For testing only, in development mode we use the router.isServer value
|
|
231
|
+
*/
|
|
232
|
+
server?: boolean
|
|
227
233
|
}
|
|
228
234
|
|
|
229
235
|
type InterPolatePathResult = {
|
|
@@ -258,6 +264,7 @@ export function interpolatePath({
|
|
|
258
264
|
path,
|
|
259
265
|
params,
|
|
260
266
|
decoder,
|
|
267
|
+
server,
|
|
261
268
|
}: InterpolatePathOptions): InterPolatePathResult {
|
|
262
269
|
// Tracking if any params are missing in the `params` object
|
|
263
270
|
// when interpolating the path
|
|
@@ -269,6 +276,65 @@ export function interpolatePath({
|
|
|
269
276
|
if (!path.includes('$'))
|
|
270
277
|
return { interpolatedPath: path, usedParams, isMissingParams }
|
|
271
278
|
|
|
279
|
+
if (isServer ?? server) {
|
|
280
|
+
// Fast path for common templates like `/posts/$id` or `/files/$`.
|
|
281
|
+
// Braced segments (`{...}`) are more complex (prefix/suffix/optional) and are
|
|
282
|
+
// handled by the general parser below.
|
|
283
|
+
if (path.indexOf('{') === -1) {
|
|
284
|
+
const length = path.length
|
|
285
|
+
let cursor = 0
|
|
286
|
+
let joined = ''
|
|
287
|
+
|
|
288
|
+
while (cursor < length) {
|
|
289
|
+
// Skip slashes between segments. '/' code is 47
|
|
290
|
+
while (cursor < length && path.charCodeAt(cursor) === 47) cursor++
|
|
291
|
+
if (cursor >= length) break
|
|
292
|
+
|
|
293
|
+
const start = cursor
|
|
294
|
+
let end = path.indexOf('/', cursor)
|
|
295
|
+
if (end === -1) end = length
|
|
296
|
+
cursor = end
|
|
297
|
+
|
|
298
|
+
const part = path.substring(start, end)
|
|
299
|
+
if (!part) continue
|
|
300
|
+
|
|
301
|
+
// `$id` or `$` (splat). '$' code is 36
|
|
302
|
+
if (part.charCodeAt(0) === 36) {
|
|
303
|
+
if (part.length === 1) {
|
|
304
|
+
const splat = params._splat
|
|
305
|
+
usedParams._splat = splat
|
|
306
|
+
// TODO: Deprecate *
|
|
307
|
+
usedParams['*'] = splat
|
|
308
|
+
|
|
309
|
+
if (!splat) {
|
|
310
|
+
isMissingParams = true
|
|
311
|
+
continue
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const value = encodeParam('_splat', params, decoder)
|
|
315
|
+
joined += '/' + value
|
|
316
|
+
} else {
|
|
317
|
+
const key = part.substring(1)
|
|
318
|
+
if (!isMissingParams && !(key in params)) {
|
|
319
|
+
isMissingParams = true
|
|
320
|
+
}
|
|
321
|
+
usedParams[key] = params[key]
|
|
322
|
+
|
|
323
|
+
const value = encodeParam(key, params, decoder) ?? 'undefined'
|
|
324
|
+
joined += '/' + value
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
joined += '/' + part
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (path.endsWith('/')) joined += '/'
|
|
332
|
+
|
|
333
|
+
const interpolatedPath = joined || '/'
|
|
334
|
+
return { usedParams, interpolatedPath, isMissingParams }
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
272
338
|
const length = path.length
|
|
273
339
|
let cursor = 0
|
|
274
340
|
let segment
|
package/src/router.ts
CHANGED
|
@@ -1440,6 +1440,7 @@ export class RouterCore<
|
|
|
1440
1440
|
path: route.fullPath,
|
|
1441
1441
|
params: routeParams,
|
|
1442
1442
|
decoder: this.pathParamsDecoder,
|
|
1443
|
+
server: this.isServer,
|
|
1443
1444
|
})
|
|
1444
1445
|
|
|
1445
1446
|
// Waste not, want not. If we already have a match for this route,
|
|
@@ -1804,6 +1805,8 @@ export class RouterCore<
|
|
|
1804
1805
|
const interpolatedNextTo = interpolatePath({
|
|
1805
1806
|
path: nextTo,
|
|
1806
1807
|
params: nextParams,
|
|
1808
|
+
decoder: this.pathParamsDecoder,
|
|
1809
|
+
server: this.isServer,
|
|
1807
1810
|
}).interpolatedPath
|
|
1808
1811
|
|
|
1809
1812
|
// Use lightweight getMatchedRoutes instead of matchRoutesInternal
|
|
@@ -1831,11 +1834,13 @@ export class RouterCore<
|
|
|
1831
1834
|
}
|
|
1832
1835
|
|
|
1833
1836
|
// If there are any params, we need to stringify them
|
|
1837
|
+
let changedParams = false
|
|
1834
1838
|
if (Object.keys(nextParams).length > 0) {
|
|
1835
1839
|
for (const route of destRoutes) {
|
|
1836
1840
|
const fn =
|
|
1837
1841
|
route.options.params?.stringify ?? route.options.stringifyParams
|
|
1838
1842
|
if (fn) {
|
|
1843
|
+
changedParams = true
|
|
1839
1844
|
Object.assign(nextParams, fn(nextParams))
|
|
1840
1845
|
}
|
|
1841
1846
|
}
|
|
@@ -1846,11 +1851,14 @@ export class RouterCore<
|
|
|
1846
1851
|
// This preserves the original parameter syntax including optional parameters
|
|
1847
1852
|
nextTo
|
|
1848
1853
|
: decodePath(
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
+
!changedParams
|
|
1855
|
+
? interpolatedNextTo
|
|
1856
|
+
: interpolatePath({
|
|
1857
|
+
path: nextTo,
|
|
1858
|
+
params: nextParams,
|
|
1859
|
+
decoder: this.pathParamsDecoder,
|
|
1860
|
+
server: this.isServer,
|
|
1861
|
+
}).interpolatedPath,
|
|
1854
1862
|
)
|
|
1855
1863
|
|
|
1856
1864
|
// Resolve the next search
|