@devp0nt/route0 1.0.0-next.73 → 1.0.0-next.75

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.
@@ -28,6 +28,16 @@ declare class Route0<TDefinition extends string, TSearchInput extends UnknownSea
28
28
  readonly params: _ParamsDefinition<TDefinition>;
29
29
  private _origin;
30
30
  private _callable;
31
+ private _regexBaseStrictString?;
32
+ private _regexBaseString?;
33
+ private _regexStrictString?;
34
+ private _regexString?;
35
+ private _regexStrict?;
36
+ private _regex?;
37
+ private _regexAncestor?;
38
+ private _captureKeys?;
39
+ private _normalizedDefinition?;
40
+ private _definitionParts?;
31
41
  Infer: {
32
42
  ParamsDefinition: _ParamsDefinition<TDefinition>;
33
43
  ParamsInput: _ParamsInput<TDefinition>;
@@ -63,12 +73,18 @@ declare class Route0<TDefinition extends string, TSearchInput extends UnknownSea
63
73
  getTokens(): RouteToken[];
64
74
  /** Clones route with optional config override. */
65
75
  clone(config?: RouteConfigInput): CallableRoute<TDefinition>;
66
- getRegexBaseStrictString(): string;
67
- getRegexBaseString(): string;
68
- getRegexStrictString(): string;
69
- getRegexString(): string;
70
- getRegexStrict(): RegExp;
71
- getRegex(): RegExp;
76
+ get regexBaseStrictString(): string;
77
+ get regexBaseString(): string;
78
+ get regexStrictString(): string;
79
+ get regexString(): string;
80
+ get regexStrict(): RegExp;
81
+ get regex(): RegExp;
82
+ get regexAncestor(): RegExp;
83
+ private get captureKeys();
84
+ private get normalizedDefinition();
85
+ private get definitionParts();
86
+ /** Fast pathname check without building a full location object. */
87
+ isExactPathnameMatch(pathname: string): boolean;
72
88
  /** Creates a grouped strict regex pattern string from many routes. */
73
89
  static getRegexStrictStringGroup(routes: AnyRoute[]): string;
74
90
  /** Creates a strict grouped regex from many routes. */
@@ -353,10 +369,7 @@ type UnknownSearchParsedValue = string | UnknownSearchParsed | Array<UnknownSear
353
369
  interface UnknownSearchParsed {
354
370
  [key: string]: UnknownSearchParsedValue;
355
371
  }
356
- type UnknownSearchInputValue = string | number | boolean | undefined | UnknownSearchInput | Array<UnknownSearchInputValue>;
357
- interface UnknownSearchInput {
358
- [key: string]: UnknownSearchInputValue;
359
- }
372
+ type UnknownSearchInput = Record<string, unknown>;
360
373
  /** It is when route not match at all, but params partially match. */
361
374
  type WeakDescendantLocationState<TRoute extends AnyRoute | string = AnyRoute | string> = {
362
375
  known: true;
@@ -437,4 +450,4 @@ type SchemaRoute0<TInput extends Record<string, unknown>, TOutput extends Record
437
450
  safeParse: (input: unknown) => _SafeParseInputResult<TOutput>;
438
451
  };
439
452
 
440
- export { type AncestorLocation, type AncestorLocationState, type AnyLocation, type AnyRoute, type AnyRouteOrDefinition, type CallableRoute, type DedupeSlashes, type Definition, type DescendantLocation, type DescendantLocationState, type EmptyRecord, type ExactLocation, type ExactLocationState, type Extended, type ExtractRoute, type ExtractRoutesKeys, type GetPathInput, type GetPathInputByRoute, type HasParams, type HasRequiredParams, type HasWildcard, type IsAncestor, type IsAny, type IsDescendant, type IsParamsOptional, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationParams, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsInputStringOnly, type ParamsOutput, type PathExtended, type ReplacePathParams, Route0, type RouteConfigInput, type RouteToken, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SchemaRoute0, type StripTrailingWildcard, type UnknownLocation, type UnknownLocationState, type UnknownSearchInput, type UnknownSearchInputValue, type UnknownSearchParsed, type UnknownSearchParsedValue, type UnmatchedLocation, type UnmatchedLocationState, type WeakAncestorLocation, type WeakAncestorLocationState, type WeakDescendantLocation, type WeakDescendantLocationState, type _ExtractParamsDefinitionBySegments, type _GeneralLocation, type _IfNoKeys, type _IsAncestor, type _IsDescendant, type _IsSame, type _IsSameParams, type _MergeParamDefinitions, type _ParamDefinitionFromSegment, type _ParamsDefinition, type _ParamsInput, type _ParamsInputStringOnly, type _RequiredParamKeys, type _SafeParseInputResult, type _Simplify, type _SplitPathSegments };
453
+ export { type AncestorLocation, type AncestorLocationState, type AnyLocation, type AnyRoute, type AnyRouteOrDefinition, type CallableRoute, type DedupeSlashes, type Definition, type DescendantLocation, type DescendantLocationState, type EmptyRecord, type ExactLocation, type ExactLocationState, type Extended, type ExtractRoute, type ExtractRoutesKeys, type GetPathInput, type GetPathInputByRoute, type HasParams, type HasRequiredParams, type HasWildcard, type IsAncestor, type IsAny, type IsDescendant, type IsParamsOptional, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationParams, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsInputStringOnly, type ParamsOutput, type PathExtended, type ReplacePathParams, Route0, type RouteConfigInput, type RouteToken, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SchemaRoute0, type StripTrailingWildcard, type UnknownLocation, type UnknownLocationState, type UnknownSearchInput, type UnknownSearchParsed, type UnknownSearchParsedValue, type UnmatchedLocation, type UnmatchedLocationState, type WeakAncestorLocation, type WeakAncestorLocationState, type WeakDescendantLocation, type WeakDescendantLocationState, type _ExtractParamsDefinitionBySegments, type _GeneralLocation, type _IfNoKeys, type _IsAncestor, type _IsDescendant, type _IsSame, type _IsSameParams, type _MergeParamDefinitions, type _ParamDefinitionFromSegment, type _ParamsDefinition, type _ParamsInput, type _ParamsInputStringOnly, type _RequiredParamKeys, type _SafeParseInputResult, type _Simplify, type _SplitPathSegments };
@@ -28,6 +28,16 @@ declare class Route0<TDefinition extends string, TSearchInput extends UnknownSea
28
28
  readonly params: _ParamsDefinition<TDefinition>;
29
29
  private _origin;
30
30
  private _callable;
31
+ private _regexBaseStrictString?;
32
+ private _regexBaseString?;
33
+ private _regexStrictString?;
34
+ private _regexString?;
35
+ private _regexStrict?;
36
+ private _regex?;
37
+ private _regexAncestor?;
38
+ private _captureKeys?;
39
+ private _normalizedDefinition?;
40
+ private _definitionParts?;
31
41
  Infer: {
32
42
  ParamsDefinition: _ParamsDefinition<TDefinition>;
33
43
  ParamsInput: _ParamsInput<TDefinition>;
@@ -63,12 +73,18 @@ declare class Route0<TDefinition extends string, TSearchInput extends UnknownSea
63
73
  getTokens(): RouteToken[];
64
74
  /** Clones route with optional config override. */
65
75
  clone(config?: RouteConfigInput): CallableRoute<TDefinition>;
66
- getRegexBaseStrictString(): string;
67
- getRegexBaseString(): string;
68
- getRegexStrictString(): string;
69
- getRegexString(): string;
70
- getRegexStrict(): RegExp;
71
- getRegex(): RegExp;
76
+ get regexBaseStrictString(): string;
77
+ get regexBaseString(): string;
78
+ get regexStrictString(): string;
79
+ get regexString(): string;
80
+ get regexStrict(): RegExp;
81
+ get regex(): RegExp;
82
+ get regexAncestor(): RegExp;
83
+ private get captureKeys();
84
+ private get normalizedDefinition();
85
+ private get definitionParts();
86
+ /** Fast pathname check without building a full location object. */
87
+ isExactPathnameMatch(pathname: string): boolean;
72
88
  /** Creates a grouped strict regex pattern string from many routes. */
73
89
  static getRegexStrictStringGroup(routes: AnyRoute[]): string;
74
90
  /** Creates a strict grouped regex from many routes. */
@@ -353,10 +369,7 @@ type UnknownSearchParsedValue = string | UnknownSearchParsed | Array<UnknownSear
353
369
  interface UnknownSearchParsed {
354
370
  [key: string]: UnknownSearchParsedValue;
355
371
  }
356
- type UnknownSearchInputValue = string | number | boolean | undefined | UnknownSearchInput | Array<UnknownSearchInputValue>;
357
- interface UnknownSearchInput {
358
- [key: string]: UnknownSearchInputValue;
359
- }
372
+ type UnknownSearchInput = Record<string, unknown>;
360
373
  /** It is when route not match at all, but params partially match. */
361
374
  type WeakDescendantLocationState<TRoute extends AnyRoute | string = AnyRoute | string> = {
362
375
  known: true;
@@ -437,4 +450,4 @@ type SchemaRoute0<TInput extends Record<string, unknown>, TOutput extends Record
437
450
  safeParse: (input: unknown) => _SafeParseInputResult<TOutput>;
438
451
  };
439
452
 
440
- export { type AncestorLocation, type AncestorLocationState, type AnyLocation, type AnyRoute, type AnyRouteOrDefinition, type CallableRoute, type DedupeSlashes, type Definition, type DescendantLocation, type DescendantLocationState, type EmptyRecord, type ExactLocation, type ExactLocationState, type Extended, type ExtractRoute, type ExtractRoutesKeys, type GetPathInput, type GetPathInputByRoute, type HasParams, type HasRequiredParams, type HasWildcard, type IsAncestor, type IsAny, type IsDescendant, type IsParamsOptional, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationParams, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsInputStringOnly, type ParamsOutput, type PathExtended, type ReplacePathParams, Route0, type RouteConfigInput, type RouteToken, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SchemaRoute0, type StripTrailingWildcard, type UnknownLocation, type UnknownLocationState, type UnknownSearchInput, type UnknownSearchInputValue, type UnknownSearchParsed, type UnknownSearchParsedValue, type UnmatchedLocation, type UnmatchedLocationState, type WeakAncestorLocation, type WeakAncestorLocationState, type WeakDescendantLocation, type WeakDescendantLocationState, type _ExtractParamsDefinitionBySegments, type _GeneralLocation, type _IfNoKeys, type _IsAncestor, type _IsDescendant, type _IsSame, type _IsSameParams, type _MergeParamDefinitions, type _ParamDefinitionFromSegment, type _ParamsDefinition, type _ParamsInput, type _ParamsInputStringOnly, type _RequiredParamKeys, type _SafeParseInputResult, type _Simplify, type _SplitPathSegments };
453
+ export { type AncestorLocation, type AncestorLocationState, type AnyLocation, type AnyRoute, type AnyRouteOrDefinition, type CallableRoute, type DedupeSlashes, type Definition, type DescendantLocation, type DescendantLocationState, type EmptyRecord, type ExactLocation, type ExactLocationState, type Extended, type ExtractRoute, type ExtractRoutesKeys, type GetPathInput, type GetPathInputByRoute, type HasParams, type HasRequiredParams, type HasWildcard, type IsAncestor, type IsAny, type IsDescendant, type IsParamsOptional, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationParams, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsInputStringOnly, type ParamsOutput, type PathExtended, type ReplacePathParams, Route0, type RouteConfigInput, type RouteToken, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SchemaRoute0, type StripTrailingWildcard, type UnknownLocation, type UnknownLocationState, type UnknownSearchInput, type UnknownSearchParsed, type UnknownSearchParsedValue, type UnmatchedLocation, type UnmatchedLocationState, type WeakAncestorLocation, type WeakAncestorLocationState, type WeakDescendantLocation, type WeakDescendantLocationState, type _ExtractParamsDefinitionBySegments, type _GeneralLocation, type _IfNoKeys, type _IsAncestor, type _IsDescendant, type _IsSame, type _IsSameParams, type _MergeParamDefinitions, type _ParamDefinitionFromSegment, type _ParamsDefinition, type _ParamsInput, type _ParamsInputStringOnly, type _RequiredParamKeys, type _SafeParseInputResult, type _Simplify, type _SplitPathSegments };
package/dist/esm/index.js CHANGED
@@ -71,11 +71,42 @@ const validateRouteDefinition = (definition) => {
71
71
  }
72
72
  };
73
73
  const stripTrailingWildcard = (definition) => definition.replace(/\*\??$/, "");
74
+ const normalizePathname = (pathname) => {
75
+ if (pathname.length > 1 && pathname.endsWith("/")) {
76
+ return pathname.slice(0, -1);
77
+ }
78
+ return pathname;
79
+ };
80
+ const getNormalizedPathnameFromInput = (hrefOrHrefRelOrLocation) => {
81
+ if (hrefOrHrefRelOrLocation instanceof URL) {
82
+ return normalizePathname(hrefOrHrefRelOrLocation.pathname);
83
+ }
84
+ if (typeof hrefOrHrefRelOrLocation !== "string") {
85
+ if (typeof hrefOrHrefRelOrLocation.pathname === "string") {
86
+ return normalizePathname(hrefOrHrefRelOrLocation.pathname);
87
+ }
88
+ hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel;
89
+ }
90
+ const abs = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(hrefOrHrefRelOrLocation);
91
+ const base = abs ? void 0 : "http://example.com";
92
+ const url = new URL(hrefOrHrefRelOrLocation, base);
93
+ return normalizePathname(url.pathname);
94
+ };
74
95
  class Route0 {
75
96
  definition;
76
97
  params;
77
98
  _origin;
78
99
  _callable;
100
+ _regexBaseStrictString;
101
+ _regexBaseString;
102
+ _regexStrictString;
103
+ _regexString;
104
+ _regexStrict;
105
+ _regex;
106
+ _regexAncestor;
107
+ _captureKeys;
108
+ _normalizedDefinition;
109
+ _definitionParts;
79
110
  Infer = null;
80
111
  /** Base URL used when generating absolute URLs (`abs: true`). */
81
112
  get origin() {
@@ -240,27 +271,73 @@ class Route0 {
240
271
  clone(config) {
241
272
  return Route0.create(this.definition, config);
242
273
  }
243
- getRegexBaseStrictString() {
244
- return getRouteRegexBaseStrictString(this.definition);
274
+ get regexBaseStrictString() {
275
+ if (this._regexBaseStrictString === void 0) {
276
+ this._regexBaseStrictString = getRouteRegexBaseStrictString(this.definition);
277
+ }
278
+ return this._regexBaseStrictString;
245
279
  }
246
- getRegexBaseString() {
247
- return this.getRegexBaseStrictString().replace(/\/+$/, "") + "/?";
280
+ get regexBaseString() {
281
+ if (this._regexBaseString === void 0) {
282
+ this._regexBaseString = this.regexBaseStrictString.replace(/\/+$/, "") + "/?";
283
+ }
284
+ return this._regexBaseString;
248
285
  }
249
- getRegexStrictString() {
250
- return `^${this.getRegexBaseStrictString()}$`;
286
+ get regexStrictString() {
287
+ if (this._regexStrictString === void 0) {
288
+ this._regexStrictString = `^${this.regexBaseStrictString}$`;
289
+ }
290
+ return this._regexStrictString;
251
291
  }
252
- getRegexString() {
253
- return `^${this.getRegexBaseString()}$`;
292
+ get regexString() {
293
+ if (this._regexString === void 0) {
294
+ this._regexString = `^${this.regexBaseString}$`;
295
+ }
296
+ return this._regexString;
254
297
  }
255
- getRegexStrict() {
256
- return new RegExp(this.getRegexStrictString());
298
+ get regexStrict() {
299
+ if (this._regexStrict === void 0) {
300
+ this._regexStrict = new RegExp(this.regexStrictString);
301
+ }
302
+ return this._regexStrict;
257
303
  }
258
- getRegex() {
259
- return new RegExp(this.getRegexString());
304
+ get regex() {
305
+ if (this._regex === void 0) {
306
+ this._regex = new RegExp(this.regexString);
307
+ }
308
+ return this._regex;
309
+ }
310
+ get regexAncestor() {
311
+ if (this._regexAncestor === void 0) {
312
+ this._regexAncestor = new RegExp(`^${this.regexBaseString}(?:/.*)?$`);
313
+ }
314
+ return this._regexAncestor;
315
+ }
316
+ get captureKeys() {
317
+ if (this._captureKeys === void 0) {
318
+ this._captureKeys = getRouteCaptureKeys(this.definition);
319
+ }
320
+ return this._captureKeys;
321
+ }
322
+ get normalizedDefinition() {
323
+ if (this._normalizedDefinition === void 0) {
324
+ this._normalizedDefinition = this.definition.length > 1 && this.definition.endsWith("/") ? this.definition.slice(0, -1) : this.definition;
325
+ }
326
+ return this._normalizedDefinition;
327
+ }
328
+ get definitionParts() {
329
+ if (this._definitionParts === void 0) {
330
+ this._definitionParts = this.normalizedDefinition === "/" ? ["/"] : this.normalizedDefinition.split("/").filter(Boolean);
331
+ }
332
+ return this._definitionParts;
333
+ }
334
+ /** Fast pathname check without building a full location object. */
335
+ isExactPathnameMatch(pathname) {
336
+ return this.regex.test(normalizePathname(pathname));
260
337
  }
261
338
  /** Creates a grouped strict regex pattern string from many routes. */
262
339
  static getRegexStrictStringGroup(routes) {
263
- const patterns = routes.map((route) => route.getRegexStrictString()).join("|");
340
+ const patterns = routes.map((route) => route.regexStrictString).join("|");
264
341
  return `(${patterns})`;
265
342
  }
266
343
  /** Creates a strict grouped regex from many routes. */
@@ -270,7 +347,7 @@ class Route0 {
270
347
  }
271
348
  /** Creates a grouped regex pattern string from many routes. */
272
349
  static getRegexStringGroup(routes) {
273
- const patterns = routes.map((route) => route.getRegexString()).join("|");
350
+ const patterns = routes.map((route) => route.regexString).join("|");
274
351
  return `(${patterns})`;
275
352
  }
276
353
  /** Creates a grouped regex from many routes. */
@@ -354,11 +431,11 @@ class Route0 {
354
431
  const location = Route0.getLocation(hrefOrHrefRelOrLocation);
355
432
  location.route = this.definition;
356
433
  location.params = {};
357
- const pathname = location.pathname.length > 1 && location.pathname.endsWith("/") ? location.pathname.slice(0, -1) : location.pathname;
358
- const paramNames = getRouteCaptureKeys(this.definition);
359
- const def = this.definition.length > 1 && this.definition.endsWith("/") ? this.definition.slice(0, -1) : this.definition;
360
- const exactRe = new RegExp(`^${this.getRegexBaseString()}$`);
361
- const ancestorRe = new RegExp(`^${this.getRegexBaseString()}(?:/.*)?$`);
434
+ const pathname = normalizePathname(location.pathname);
435
+ const paramNames = this.captureKeys;
436
+ const defParts = this.definitionParts;
437
+ const exactRe = this.regex;
438
+ const ancestorRe = this.regexAncestor;
362
439
  const exactMatch = pathname.match(exactRe);
363
440
  const ancestorMatch = pathname.match(ancestorRe);
364
441
  const exact = !!exactMatch;
@@ -376,9 +453,7 @@ class Route0 {
376
453
  } else {
377
454
  location.params = {};
378
455
  }
379
- const getParts = (path) => path === "/" ? ["/"] : path.split("/").filter(Boolean);
380
- const defParts = getParts(def);
381
- const pathParts = getParts(pathname);
456
+ const pathParts = pathname === "/" ? ["/"] : pathname.split("/").filter(Boolean);
382
457
  let isPrefix = true;
383
458
  if (pathParts.length > defParts.length) {
384
459
  isPrefix = false;
@@ -579,8 +654,8 @@ class Route0 {
579
654
  isConflict(other) {
580
655
  if (!other) return false;
581
656
  other = Route0.create(other);
582
- const thisRegex = this.getRegex();
583
- const otherRegex = other.getRegex();
657
+ const thisRegex = this.regex;
658
+ const otherRegex = other.regex;
584
659
  const makeCandidates = (definition) => {
585
660
  const tokens = getRouteTokens(definition);
586
661
  const values = (token) => {
@@ -709,8 +784,12 @@ class Routes {
709
784
  }
710
785
  _getLocation(hrefOrHrefRelOrLocation) {
711
786
  const input = hrefOrHrefRelOrLocation;
787
+ const pathname = getNormalizedPathnameFromInput(input);
712
788
  for (const route of this._ordered) {
713
- const loc = route.getLocation(hrefOrHrefRelOrLocation);
789
+ if (!route.isExactPathnameMatch(pathname)) {
790
+ continue;
791
+ }
792
+ const loc = route.getLocation(input);
714
793
  if (loc.exact) {
715
794
  return loc;
716
795
  }