@tanstack/router-core 0.0.1-beta.16 → 0.0.1-beta.161

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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/build/cjs/fileRoute.js +29 -0
  3. package/build/cjs/fileRoute.js.map +1 -0
  4. package/build/cjs/history.js +226 -0
  5. package/build/cjs/history.js.map +1 -0
  6. package/build/cjs/index.js +78 -0
  7. package/build/cjs/{packages/router-core/src/index.js.map → index.js.map} +1 -1
  8. package/build/cjs/{packages/router-core/src/path.js → path.js} +45 -56
  9. package/build/cjs/path.js.map +1 -0
  10. package/build/cjs/{packages/router-core/src/qss.js → qss.js} +10 -16
  11. package/build/cjs/qss.js.map +1 -0
  12. package/build/cjs/route.js +101 -0
  13. package/build/cjs/route.js.map +1 -0
  14. package/build/cjs/router.js +1134 -0
  15. package/build/cjs/router.js.map +1 -0
  16. package/build/cjs/{packages/router-core/src/searchParams.js → searchParams.js} +34 -19
  17. package/build/cjs/searchParams.js.map +1 -0
  18. package/build/cjs/{packages/router-core/src/utils.js → utils.js} +54 -64
  19. package/build/cjs/utils.js.map +1 -0
  20. package/build/esm/index.js +1439 -2091
  21. package/build/esm/index.js.map +1 -1
  22. package/build/stats-html.html +59 -49
  23. package/build/stats-react.json +203 -234
  24. package/build/types/index.d.ts +573 -431
  25. package/build/umd/index.development.js +1673 -2221
  26. package/build/umd/index.development.js.map +1 -1
  27. package/build/umd/index.production.js +13 -2
  28. package/build/umd/index.production.js.map +1 -1
  29. package/package.json +11 -7
  30. package/src/fileRoute.ts +162 -0
  31. package/src/history.ts +292 -0
  32. package/src/index.ts +3 -10
  33. package/src/link.ts +121 -118
  34. package/src/path.ts +37 -17
  35. package/src/qss.ts +1 -2
  36. package/src/route.ts +874 -218
  37. package/src/routeInfo.ts +47 -211
  38. package/src/router.ts +1511 -1024
  39. package/src/searchParams.ts +33 -9
  40. package/src/utils.ts +80 -49
  41. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
  42. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  43. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
  44. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
  45. package/build/cjs/node_modules/history/index.js +0 -815
  46. package/build/cjs/node_modules/history/index.js.map +0 -1
  47. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
  48. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
  49. package/build/cjs/packages/router-core/src/index.js +0 -58
  50. package/build/cjs/packages/router-core/src/path.js.map +0 -1
  51. package/build/cjs/packages/router-core/src/qss.js.map +0 -1
  52. package/build/cjs/packages/router-core/src/route.js +0 -147
  53. package/build/cjs/packages/router-core/src/route.js.map +0 -1
  54. package/build/cjs/packages/router-core/src/routeConfig.js +0 -69
  55. package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
  56. package/build/cjs/packages/router-core/src/routeMatch.js +0 -231
  57. package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
  58. package/build/cjs/packages/router-core/src/router.js +0 -833
  59. package/build/cjs/packages/router-core/src/router.js.map +0 -1
  60. package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
  61. package/build/cjs/packages/router-core/src/utils.js.map +0 -1
  62. package/src/frameworks.ts +0 -11
  63. package/src/routeConfig.ts +0 -514
  64. package/src/routeMatch.ts +0 -319
package/src/link.ts CHANGED
@@ -1,11 +1,14 @@
1
- import { AnyPathParams } from './routeConfig'
1
+ import { Trim } from './fileRoute'
2
+ import { AnyRoute } from './route'
2
3
  import {
3
- AnyAllRouteInfo,
4
- DefaultAllRouteInfo,
5
- RouteInfoByPath,
4
+ AllParams,
5
+ FullSearchSchema,
6
+ RouteByPath,
7
+ RouteIds,
8
+ RoutePaths,
6
9
  } from './routeInfo'
7
- import { Location, LocationState } from './router'
8
- import { Expand, NoInfer, PickAsRequired, PickRequired, Updater } from './utils'
10
+ import { ParsedLocation, LocationState } from './router'
11
+ import { NoInfer, PickRequired, UnionToIntersection, Updater } from './utils'
9
12
 
10
13
  export type LinkInfo =
11
14
  | {
@@ -14,20 +17,17 @@ export type LinkInfo =
14
17
  }
15
18
  | {
16
19
  type: 'internal'
17
- next: Location
20
+ next: ParsedLocation
18
21
  handleFocus: (e: any) => void
19
22
  handleClick: (e: any) => void
20
23
  handleEnter: (e: any) => void
21
24
  handleLeave: (e: any) => void
25
+ handleTouchStart: (e: any) => void
22
26
  isActive: boolean
23
27
  disabled?: boolean
24
28
  }
25
29
 
26
- type StartsWith<A, B> = A extends `${B extends string ? B : never}${infer _}`
27
- ? true
28
- : false
29
-
30
- type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
30
+ export type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
31
31
  ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>
32
32
  : T extends `${infer L}//`
33
33
  ? `${CleanPath<L>}/`
@@ -57,20 +57,20 @@ export type Split<S, TIncludeTrailingSlash = true> = S extends unknown
57
57
  : never
58
58
  : never
59
59
 
60
- export type ParsePathParams<T extends string> = Split<T>[number] extends infer U
61
- ? U extends `:${infer V}`
62
- ? V
63
- : never
64
- : never
60
+ export type ParsePathParams<T extends string> = keyof {
61
+ [K in Trim<Split<T>[number], '_'> as K extends `$${infer L}` ? L : never]: K
62
+ }
65
63
 
66
- type Join<T> = T extends []
64
+ export type Join<T, Delimiter extends string = '/'> = T extends []
67
65
  ? ''
68
66
  : T extends [infer L extends string]
69
67
  ? L
70
68
  : T extends [infer L extends string, ...infer Tail extends [...string[]]]
71
- ? CleanPath<`${L}/${Join<Tail>}`>
69
+ ? CleanPath<`${L}${Delimiter}${Join<Tail>}`>
72
70
  : never
73
71
 
72
+ export type Last<T extends any[]> = T extends [...infer _, infer L] ? L : never
73
+
74
74
  export type RelativeToPathAutoComplete<
75
75
  AllPaths extends string,
76
76
  TFrom extends string,
@@ -106,24 +106,33 @@ export type RelativeToPathAutoComplete<
106
106
  ]
107
107
  ? `${TTo}${Join<RestPath>}`
108
108
  : never
109
- : './' | '../' | AllPaths
109
+ :
110
+ | (TFrom extends `/`
111
+ ? never
112
+ : SplitPaths extends [...Split<TFrom, false>, ...infer RestPath]
113
+ ? Join<RestPath> extends { length: 0 }
114
+ ? never
115
+ : './'
116
+ : never)
117
+ | (TFrom extends `/` ? never : '../')
118
+ | AllPaths
110
119
 
111
- export type NavigateOptionsAbsolute<
112
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
113
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
114
- TTo extends string = '.',
115
- > = ToOptions<TAllRouteInfo, TFrom, TTo> & {
116
- // Whether to replace the current history stack instead of pushing a new one
120
+ export type NavigateOptions<
121
+ TRouteTree extends AnyRoute = AnyRoute,
122
+ TFrom extends RoutePaths<TRouteTree> = '/',
123
+ TTo extends string = '',
124
+ > = ToOptions<TRouteTree, TFrom, TTo> & {
125
+ // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
117
126
  replace?: boolean
118
127
  }
119
128
 
120
129
  export type ToOptions<
121
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
122
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
123
- TTo extends string = '.',
130
+ TRouteTree extends AnyRoute = AnyRoute,
131
+ TFrom extends RoutePaths<TRouteTree> = '/',
132
+ TTo extends string = '',
124
133
  TResolvedTo = ResolveRelativePath<TFrom, NoInfer<TTo>>,
125
134
  > = {
126
- to?: ToPathOption<TAllRouteInfo, TFrom, TTo>
135
+ to?: ToPathOption<TRouteTree, TFrom, TTo>
127
136
  // The new has string or a function to update it
128
137
  hash?: Updater<string>
129
138
  // State to pass to the history stack
@@ -132,102 +141,115 @@ export type ToOptions<
132
141
  from?: TFrom
133
142
  // // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
134
143
  // fromCurrent?: boolean
135
- } & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>, {}> &
136
- SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> &
137
- PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>
144
+ } & CheckPath<TRouteTree, NoInfer<TResolvedTo>, {}> &
145
+ SearchParamOptions<TRouteTree, TFrom, TResolvedTo> &
146
+ PathParamOptions<TRouteTree, TFrom, TResolvedTo>
138
147
 
139
- type SearchParamOptions<
140
- TAllRouteInfo extends AnyAllRouteInfo,
148
+ export type SearchParamOptions<
149
+ TRouteTree extends AnyRoute,
141
150
  TFrom,
142
151
  TTo,
143
- TFromSchema = RouteInfoByPath<TAllRouteInfo, TFrom>['fullSearchSchema'],
144
- TToSchema = RouteInfoByPath<TAllRouteInfo, TTo>['fullSearchSchema'],
145
- > = StartsWith<TFrom, TTo> extends true // If the next route search extend or cover the from route, params will be optional
146
- ? {
147
- search?: SearchReducer<TFromSchema, TToSchema>
148
- }
149
- : // Optional search params? Allow it
150
- keyof PickRequired<TToSchema> extends never
152
+ TFromSchema = UnionToIntersection<
153
+ FullSearchSchema<TRouteTree> & RouteByPath<TRouteTree, TFrom> extends never
154
+ ? {}
155
+ : RouteByPath<TRouteTree, TFrom>['__types']['fullSearchSchema']
156
+ >,
157
+ // Find the schema for the new path, and make optional any keys
158
+ // that are already defined in the current schema
159
+ TToSchema = Partial<
160
+ RouteByPath<TRouteTree, TFrom>['__types']['fullSearchSchema']
161
+ > &
162
+ Omit<
163
+ RouteByPath<TRouteTree, TTo>['__types']['fullSearchSchema'],
164
+ keyof PickRequired<
165
+ RouteByPath<TRouteTree, TFrom>['__types']['fullSearchSchema']
166
+ >
167
+ >,
168
+ TFromFullSchema = UnionToIntersection<
169
+ FullSearchSchema<TRouteTree> & TFromSchema
170
+ >,
171
+ TToFullSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & TToSchema>,
172
+ > = keyof PickRequired<TToSchema> extends never
151
173
  ? {
152
- search?: SearchReducer<TFromSchema, TToSchema>
174
+ search?: true | SearchReducer<TFromFullSchema, TToFullSchema>
153
175
  }
154
176
  : {
155
- // Must have required search params, enforce it
156
- search: SearchReducer<TFromSchema, TToSchema>
177
+ search: SearchReducer<TFromFullSchema, TToFullSchema>
157
178
  }
158
179
 
159
180
  type SearchReducer<TFrom, TTo> =
160
181
  | { [TKey in keyof TTo]: TTo[TKey] }
161
182
  | ((current: TFrom) => TTo)
162
183
 
163
- type PathParamOptions<
164
- TAllRouteInfo extends AnyAllRouteInfo,
184
+ export type PathParamOptions<
185
+ TRouteTree extends AnyRoute,
165
186
  TFrom,
166
187
  TTo,
167
- TFromParams = RouteInfoByPath<TAllRouteInfo, TFrom>['allParams'],
168
- TToParams = RouteInfoByPath<TAllRouteInfo, TTo>['allParams'],
169
- > =
170
- // If the next routes params extend or cover the from route, params will be optional
171
- StartsWith<TFrom, TTo> extends true
172
- ? {
173
- params?: ParamsReducer<TFromParams, TToParams>
174
- }
175
- : // If the next route doesn't have params, warn if any have been passed
176
- AnyPathParams extends TToParams
177
- ? {
178
- params?: ParamsReducer<TFromParams, Record<string, never>>
179
- }
180
- : // If the next route has params, enforce them
181
- {
182
- params: ParamsReducer<TFromParams, TToParams>
183
- }
188
+ TFromSchema = UnionToIntersection<
189
+ RouteByPath<TRouteTree, TFrom> extends never
190
+ ? {}
191
+ : RouteByPath<TRouteTree, TFrom>['__types']['allParams']
192
+ >,
193
+ // Find the schema for the new path, and make optional any keys
194
+ // that are already defined in the current schema
195
+ TToSchema = Partial<RouteByPath<TRouteTree, TFrom>['__types']['allParams']> &
196
+ Omit<
197
+ RouteByPath<TRouteTree, TTo>['__types']['allParams'],
198
+ keyof PickRequired<RouteByPath<TRouteTree, TFrom>['__types']['allParams']>
199
+ >,
200
+ TFromFullParams = UnionToIntersection<AllParams<TRouteTree> & TFromSchema>,
201
+ TToFullParams = UnionToIntersection<AllParams<TRouteTree> & TToSchema>,
202
+ > = keyof PickRequired<TToSchema> extends never
203
+ ? {
204
+ params?: ParamsReducer<TFromFullParams, TToFullParams>
205
+ }
206
+ : {
207
+ params: ParamsReducer<TFromFullParams, TToFullParams>
208
+ }
184
209
 
185
210
  type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
186
211
 
187
212
  export type ToPathOption<
188
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
189
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
190
- TTo extends string = '.',
213
+ TRouteTree extends AnyRoute = AnyRoute,
214
+ TFrom extends RoutePaths<TRouteTree> = '/',
215
+ TTo extends string = '',
191
216
  > =
192
217
  | TTo
193
218
  | RelativeToPathAutoComplete<
194
- TAllRouteInfo['routePaths'],
219
+ RoutePaths<TRouteTree>,
195
220
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
196
221
  NoInfer<TTo> & string
197
222
  >
198
223
 
199
224
  export type ToIdOption<
200
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
201
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
202
- TTo extends string = '.',
225
+ TRouteTree extends AnyRoute = AnyRoute,
226
+ TFrom extends RoutePaths<TRouteTree> = '/',
227
+ TTo extends string = '',
203
228
  > =
204
229
  | TTo
205
230
  | RelativeToPathAutoComplete<
206
- TAllRouteInfo['routeIds'],
231
+ RouteIds<TRouteTree>,
207
232
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
208
233
  NoInfer<TTo> & string
209
234
  >
210
235
 
211
- interface ActiveOptions {
236
+ export interface ActiveOptions {
212
237
  exact?: boolean
213
238
  includeHash?: boolean
239
+ includeSearch?: boolean
214
240
  }
215
241
 
216
242
  export type LinkOptions<
217
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
218
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
219
- TTo extends string = '.',
220
- > = NavigateOptionsAbsolute<TAllRouteInfo, TFrom, TTo> & {
243
+ TRouteTree extends AnyRoute = AnyRoute,
244
+ TFrom extends RoutePaths<TRouteTree> = '/',
245
+ TTo extends string = '',
246
+ > = NavigateOptions<TRouteTree, TFrom, TTo> & {
221
247
  // The standard anchor tag target attribute
222
248
  target?: HTMLAnchorElement['target']
223
249
  // Defaults to `{ exact: false, includeHash: false }`
224
250
  activeOptions?: ActiveOptions
225
251
  // If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
226
252
  preload?: false | 'intent'
227
- // When preloaded, the preloaded result will be considered "fresh" for this duration in milliseconds
228
- preloadMaxAge?: number
229
- // When preloaded and subsequently inactive, the preloaded result will remain in memory for this duration in milliseconds
230
- preloadGcMaxAge?: number
231
253
  // Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
232
254
  preloadDelay?: number
233
255
  // If true, will render the link without the href attribute
@@ -235,58 +257,47 @@ export type LinkOptions<
235
257
  }
236
258
 
237
259
  export type CheckRelativePath<
238
- TAllRouteInfo extends AnyAllRouteInfo,
260
+ TRouteTree extends AnyRoute,
239
261
  TFrom,
240
262
  TTo,
241
263
  > = TTo extends string
242
264
  ? TFrom extends string
243
- ? ResolveRelativePath<TFrom, TTo> extends TAllRouteInfo['routePaths']
265
+ ? ResolveRelativePath<TFrom, TTo> extends RoutePaths<TRouteTree>
244
266
  ? {}
245
267
  : {
246
268
  Error: `${TFrom} + ${TTo} resolves to ${ResolveRelativePath<
247
269
  TFrom,
248
270
  TTo
249
271
  >}, which is not a valid route path.`
250
- 'Valid Route Paths': TAllRouteInfo['routePaths']
272
+ 'Valid Route Paths': RoutePaths<TRouteTree>
251
273
  }
252
274
  : {}
253
275
  : {}
254
276
 
255
- export type CheckPath<
256
- TAllRouteInfo extends AnyAllRouteInfo,
277
+ export type CheckPath<TRouteTree extends AnyRoute, TPath, TPass> = Exclude<
257
278
  TPath,
258
- TPass,
259
- > = Exclude<TPath, TAllRouteInfo['routePaths']> extends never
279
+ RoutePaths<TRouteTree>
280
+ > extends never
260
281
  ? TPass
261
- : CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>
282
+ : CheckPathError<TRouteTree, Exclude<TPath, RoutePaths<TRouteTree>>>
262
283
 
263
- export type CheckPathError<
264
- TAllRouteInfo extends AnyAllRouteInfo,
265
- TInvalids,
266
- > = Expand<{
267
- Error: `${TInvalids extends string
268
- ? TInvalids
269
- : never} is not a valid route path.`
270
- 'Valid Route Paths': TAllRouteInfo['routePaths']
271
- }>
284
+ export type CheckPathError<TRouteTree extends AnyRoute, TInvalids> = {
285
+ to: RoutePaths<TRouteTree>
286
+ }
272
287
 
273
- export type CheckId<
274
- TAllRouteInfo extends AnyAllRouteInfo,
288
+ export type CheckId<TRouteTree extends AnyRoute, TPath, TPass> = Exclude<
275
289
  TPath,
276
- TPass,
277
- > = Exclude<TPath, TAllRouteInfo['routeIds']> extends never
290
+ RouteIds<TRouteTree>
291
+ > extends never
278
292
  ? TPass
279
- : CheckIdError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routeIds']>>
293
+ : CheckIdError<TRouteTree, Exclude<TPath, RouteIds<TRouteTree>>>
280
294
 
281
- export type CheckIdError<
282
- TAllRouteInfo extends AnyAllRouteInfo,
283
- TInvalids,
284
- > = Expand<{
295
+ export type CheckIdError<TRouteTree extends AnyRoute, TInvalids> = {
285
296
  Error: `${TInvalids extends string
286
297
  ? TInvalids
287
298
  : never} is not a valid route ID.`
288
- 'Valid Route IDs': TAllRouteInfo['routeIds']
289
- }>
299
+ 'Valid Route IDs': RouteIds<TRouteTree>
300
+ }
290
301
 
291
302
  export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
292
303
  ? TTo extends string
@@ -311,11 +322,3 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
311
322
  : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>
312
323
  : never
313
324
  : never
314
-
315
- export type ValidFromPath<
316
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
317
- > =
318
- | undefined
319
- | (string extends TAllRouteInfo['routePaths']
320
- ? string
321
- : TAllRouteInfo['routePaths'])
package/src/path.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AnyPathParams } from './routeConfig'
1
+ import { AnyPathParams } from './route'
2
2
  import { MatchLocation } from './router'
3
3
  import { last } from './utils'
4
4
 
@@ -90,14 +90,14 @@ export function parsePathname(pathname?: string): Segment[] {
90
90
 
91
91
  segments.push(
92
92
  ...split.map((part): Segment => {
93
- if (part.startsWith('*')) {
93
+ if (part === '$' || part === '*') {
94
94
  return {
95
95
  type: 'wildcard',
96
96
  value: part,
97
97
  }
98
98
  }
99
99
 
100
- if (part.charAt(0) === ':') {
100
+ if (part.charAt(0) === '$') {
101
101
  return {
102
102
  type: 'param',
103
103
  value: part,
@@ -125,14 +125,16 @@ export function parsePathname(pathname?: string): Segment[] {
125
125
  export function interpolatePath(
126
126
  path: string | undefined,
127
127
  params: any,
128
- leaveWildcard?: boolean,
128
+ leaveWildcards: boolean = false,
129
129
  ) {
130
130
  const interpolatedPathSegments = parsePathname(path)
131
131
 
132
132
  return joinPaths(
133
133
  interpolatedPathSegments.map((segment) => {
134
- if (segment.value === '*' && !leaveWildcard) {
135
- return ''
134
+ if (segment.type === 'wildcard') {
135
+ const value = params[segment.value]
136
+ if (leaveWildcards) return `${segment.value}${value ?? ''}`
137
+ return value
136
138
  }
137
139
 
138
140
  if (segment.type === 'param') {
@@ -145,29 +147,46 @@ export function interpolatePath(
145
147
  }
146
148
 
147
149
  export function matchPathname(
150
+ basepath: string,
148
151
  currentPathname: string,
149
152
  matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,
150
153
  ): AnyPathParams | undefined {
151
- const pathParams = matchByPath(currentPathname, matchLocation)
152
- // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
154
+ const pathParams = matchByPath(basepath, currentPathname, matchLocation)
155
+ // const searchMatched = matchBySearch(location.search, matchLocation)
153
156
 
154
157
  if (matchLocation.to && !pathParams) {
155
158
  return
156
159
  }
157
160
 
158
- // if (matchLocation.search && !searchMatched) {
159
- // return
160
- // }
161
-
162
161
  return pathParams ?? {}
163
162
  }
164
163
 
165
164
  export function matchByPath(
165
+ basepath: string,
166
166
  from: string,
167
167
  matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,
168
168
  ): Record<string, string> | undefined {
169
+ // Remove the base path from the pathname
170
+ from = basepath != '/' ? from.substring(basepath.length) : from
171
+ // Default to to $ (wildcard)
172
+ const to = `${matchLocation.to ?? '$'}`
173
+ // Parse the from and to
169
174
  const baseSegments = parsePathname(from)
170
- const routeSegments = parsePathname(`${matchLocation.to ?? '*'}`)
175
+ const routeSegments = parsePathname(to)
176
+
177
+ if (!from.startsWith('/')) {
178
+ baseSegments.unshift({
179
+ type: 'pathname',
180
+ value: '/',
181
+ })
182
+ }
183
+
184
+ if (!to.startsWith('/')) {
185
+ routeSegments.unshift({
186
+ type: 'pathname',
187
+ value: '/',
188
+ })
189
+ }
171
190
 
172
191
  const params: Record<string, string> = {}
173
192
 
@@ -180,8 +199,8 @@ export function matchByPath(
180
199
  const baseSegment = baseSegments[i]
181
200
  const routeSegment = routeSegments[i]
182
201
 
183
- const isLastRouteSegment = i === routeSegments.length - 1
184
- const isLastBaseSegment = i === baseSegments.length - 1
202
+ const isLastBaseSegment = i >= baseSegments.length - 1
203
+ const isLastRouteSegment = i >= routeSegments.length - 1
185
204
 
186
205
  if (routeSegment) {
187
206
  if (routeSegment.type === 'wildcard') {
@@ -219,16 +238,17 @@ export function matchByPath(
219
238
  if (baseSegment?.value === '/') {
220
239
  return false
221
240
  }
222
- if (!baseSegment.value.startsWith(':')) {
241
+ if (baseSegment.value.charAt(0) !== '$') {
223
242
  params[routeSegment.value.substring(1)] = baseSegment.value
224
243
  }
225
244
  }
226
245
  }
227
246
 
228
- if (isLastRouteSegment && !isLastBaseSegment) {
247
+ if (!isLastBaseSegment && isLastRouteSegment) {
229
248
  return !!matchLocation.fuzzy
230
249
  }
231
250
  }
251
+
232
252
  return true
233
253
  })()
234
254
 
package/src/qss.ts CHANGED
@@ -30,8 +30,7 @@ function toValue(mix) {
30
30
  var str = decodeURIComponent(mix)
31
31
  if (str === 'false') return false
32
32
  if (str === 'true') return true
33
- if (str.charAt(0) === '0') return str
34
- return +str * 0 === 0 ? +str : str
33
+ return +str * 0 === 0 && +str + '' === str ? +str : str
35
34
  }
36
35
 
37
36
  export function decode(str) {