@devp0nt/route0 1.0.0-next.21 → 1.0.0-next.23

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// TODO: asterisk\n// TODO: optional params\n// TODO: required search\n\n// TODO: .extension('.json') to not add additional / but just add some extension\n// TODO: search input can be boolean, or even object with qs\n// TODO: Роут0 три пусть три тоже сам генерится вероятно\n// TODO: Роут0 три мод, тогда там все ноуты кончаются на .селф\n// TODO: use splats in param definition \"*\"\n// TODO: ? check extend for search only .extend('&x&z')\n// TODO: .create(route, {useSearch, useParams})\n// TODO: Из пас экзакт, из пасвизквери экзает, из чилдрен, из парент, из экзактОр\n// TODO: isEqual, isChildren, isParent\n// TODO: extractParams, extractSearch\n// TODO: getPathDefinition respecting definitionParamPrefix, definitionSearchPrefix\n// TODO: prepend\n// TODO: Route0.createTree({base:{self: x, children: ...})\n// TODO: overrideTree\n// TODO: .create(route, {baseUrl, useLocation})\n// TODO: ? optional path params as @\n// TODO: prependMany, extendMany, overrideMany, with types\n// TODO: optional route params /x/:id?\n\nexport class Route0<TDefinition extends string> {\n readonly definition: TDefinition\n readonly pathDefinition: _PathDefinition<TDefinition>\n readonly paramsDefinition: _ParamsDefinition<TDefinition>\n readonly searchDefinition: _SearchDefinition<TDefinition>\n baseUrl: string\n\n private constructor(definition: TDefinition, config: RouteConfigInput = {}) {\n this.definition = definition\n this.pathDefinition = Route0._getPathDefinitionBydefinition(definition)\n this.paramsDefinition = Route0._getParamsDefinitionBydefinition(definition)\n this.searchDefinition = Route0._getSearchDefinitionBydefinition(definition)\n\n const { baseUrl } = config\n if (baseUrl && typeof baseUrl === 'string' && baseUrl.length) {\n this.baseUrl = baseUrl\n } else {\n const g = globalThis as unknown as { location?: { origin?: string } }\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (typeof g?.location?.origin === 'string' && g.location.origin.length > 0) {\n this.baseUrl = g.location.origin\n } else {\n this.baseUrl = 'https://example.com'\n }\n }\n }\n\n static create<TDefinition extends string>(\n definition: TDefinition | AnyRoute<TDefinition>,\n config?: RouteConfigInput,\n ): CallabelRoute<TDefinition> {\n if (typeof definition === 'function') {\n return definition\n }\n const original = typeof definition === 'object' ? definition : new Route0<TDefinition>(definition, config)\n const callable = original.get.bind(original)\n Object.setPrototypeOf(callable, original)\n Object.defineProperty(callable, Symbol.toStringTag, {\n value: original.definition,\n })\n return callable as never\n }\n\n private static _splitPathDefinitionAndSearchTailDefinition(definition: string) {\n const i = definition.indexOf('&')\n if (i === -1) return { pathDefinition: definition, searchTailDefinition: '' }\n return {\n pathDefinition: definition.slice(0, i),\n searchTailDefinition: definition.slice(i),\n }\n }\n\n private static _getAbsPath(baseUrl: string, pathWithSearch: string) {\n return new URL(pathWithSearch, baseUrl).toString().replace(/\\/$/, '')\n }\n\n private static _getPathDefinitionBydefinition<TDefinition extends string>(definition: TDefinition) {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n return pathDefinition as _PathDefinition<TDefinition>\n }\n\n private static _getParamsDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _ParamsDefinition<TDefinition> {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n const matches = Array.from(pathDefinition.matchAll(/:([A-Za-z0-9_]+)/g))\n const paramsDefinition = Object.fromEntries(matches.map((m) => [m[1], true]))\n const keysCount = Object.keys(paramsDefinition).length\n if (keysCount === 0) {\n return undefined as _ParamsDefinition<TDefinition>\n }\n return paramsDefinition as _ParamsDefinition<TDefinition>\n }\n\n private static _getSearchDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _SearchDefinition<TDefinition> {\n const { searchTailDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n if (!searchTailDefinition) {\n return undefined as _SearchDefinition<TDefinition>\n }\n const keys = searchTailDefinition.split('&').filter(Boolean)\n const searchDefinition = Object.fromEntries(keys.map((k) => [k, true]))\n const keysCount = Object.keys(searchDefinition).length\n if (keysCount === 0) {\n return undefined as _SearchDefinition<TDefinition>\n }\n return searchDefinition as _SearchDefinition<TDefinition>\n }\n\n extend<TSuffixDefinition extends string>(\n suffixDefinition: TSuffixDefinition,\n ): CallabelRoute<PathExtended<TDefinition, TSuffixDefinition>> {\n const { pathDefinition: parentPathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(this.definition)\n const { pathDefinition: suffixPathDefinition, searchTailDefinition: suffixSearchTailDefinition } =\n Route0._splitPathDefinitionAndSearchTailDefinition(suffixDefinition)\n const pathDefinition = `${parentPathDefinition}/${suffixPathDefinition}`.replace(/\\/{2,}/g, '/')\n const definition = `${pathDefinition}${suffixSearchTailDefinition}` as PathExtended<TDefinition, TSuffixDefinition>\n return Route0.create<PathExtended<TDefinition, TSuffixDefinition>>(definition, { baseUrl: this.baseUrl })\n }\n\n // has params\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n get(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n get(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const { search, abs, ...params } = input\n return { searchInput: search || {}, paramsInput: params, absInput: abs ?? false }\n })()\n\n // validate params\n const neededParamsKeys = this.paramsDefinition ? Object.keys(this.paramsDefinition) : []\n const providedParamsKeys = Object.keys(paramsInput)\n const notProvidedKeys = neededParamsKeys.filter((k) => !providedParamsKeys.includes(k))\n if (notProvidedKeys.length) {\n // throw new Error(`Missing params: not defined keys ${notProvidedKeys.map((k) => `\"${k}\"`).join(\", \")}.`)\n Object.assign(paramsInput, Object.fromEntries(notProvidedKeys.map((k) => [k, 'undefined'])))\n }\n\n // create url\n\n let url = this.pathDefinition as string\n // replace params\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n url = url.replace(/:([A-Za-z0-9_]+)/g, (_m, k) => encodeURIComponent(String(paramsInput?.[k] ?? '')))\n // search params\n const searchInputStringified = Object.fromEntries(Object.entries(searchInput).map(([k, v]) => [k, String(v)]))\n url = [url, new URLSearchParams(searchInputStringified).toString()].filter(Boolean).join('?')\n // dedupe slashes\n url = url.replace(/\\/{2,}/g, '/')\n // absolute\n url = absInput ? Route0._getAbsPath(this.baseUrl, url) : url\n\n return url\n }\n\n // has params\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n flat(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n flat(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: args[1] ?? false }\n }\n const paramsKeys = this.getParamsKeys()\n const paramsInput = paramsKeys.reduce<Record<string, string | number>>((acc, key) => {\n if (input[key] !== undefined) {\n acc[key] = input[key]\n }\n return acc\n }, {})\n const searchKeys = this.getSearchKeys()\n const searchInput = Object.keys(input)\n .filter((k) => {\n if (searchKeys.includes(k)) {\n return true\n }\n if (paramsKeys.includes(k)) {\n return false\n }\n return true\n })\n .reduce<Record<string, string | number>>((acc, key) => {\n acc[key] = input[key]\n return acc\n }, {})\n return { searchInput, paramsInput, absInput: args[1] ?? false }\n })()\n\n return this.get({ ...paramsInput, search: searchInput, abs: absInput } as never)\n }\n\n getParamsKeys(): string[] {\n return Object.keys(this.paramsDefinition || {})\n }\n getSearchKeys(): string[] {\n return Object.keys(this.searchDefinition || {})\n }\n getFlatKeys(): string[] {\n return [...this.getSearchKeys(), ...this.getParamsKeys()]\n }\n\n getDefinition(): string {\n return this.pathDefinition\n }\n\n clone(config?: RouteConfigInput): Route0<TDefinition> {\n return new Route0(this.definition, config)\n }\n\n getRegexString(): string {\n // Normalize the path definition (remove trailing slash except for root)\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n\n // Replace :param with placeholders, escape regex special chars, then restore capture groups\n const pattern = def\n .replace(/:([A-Za-z0-9_]+)/g, '___PARAM___') // temporarily replace params with placeholder\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') // escape regex special chars\n .replace(/___PARAM___/g, '([^/]+)') // replace placeholder with capture group\n\n return pattern\n }\n\n getRegex(): RegExp {\n return new RegExp(`^${this.getRegexString()}$`)\n }\n\n static getRegexString(routes: AnyRoute[] | AnyRoute): string {\n const routesArray = Array.isArray(routes) ? routes : [routes]\n return routesArray.map((route) => route.getRegexString()).join('|')\n }\n static getRegex(routes: AnyRoute[] | AnyRoute): RegExp {\n return new RegExp(`^(${Route0.getRegexString(routes)})$`)\n }\n\n static getLocation(href: `${string}://${string}`): UnknownLocation\n static getLocation(hrefRel: `/${string}`): UnknownLocation\n static getLocation(hrefOrHrefRel: string): UnknownLocation\n static getLocation(location: LocationAny): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation {\n if (typeof hrefOrHrefRelOrLocation !== 'string') {\n hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel\n }\n // Check if it's an absolute URL (starts with scheme://)\n const abs = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:\\/\\//.test(hrefOrHrefRelOrLocation)\n\n // Use dummy base only if relative\n const base = abs ? undefined : 'http://example.com'\n const url = new URL(hrefOrHrefRelOrLocation, base)\n\n // Extract search params\n const searchParams = Object.fromEntries(url.searchParams.entries())\n\n // Normalize pathname (remove trailing slash except for root)\n let pathname = url.pathname\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1)\n }\n\n // Common derived values\n const hrefRel = pathname + url.search + url.hash\n\n // Build the location object consistent with _GeneralLocation\n const location: UnknownLocation = {\n pathname,\n search: url.search,\n hash: url.hash,\n origin: abs ? url.origin : undefined,\n href: abs ? url.href : undefined,\n hrefRel,\n abs,\n\n // extra host-related fields (available even for relative with dummy base)\n host: abs ? url.host : undefined,\n hostname: abs ? url.hostname : undefined,\n port: abs ? url.port || undefined : undefined,\n\n // specific to UnknownLocation\n searchParams,\n params: undefined,\n route: undefined,\n exact: false,\n parent: false,\n children: false,\n }\n\n return location\n }\n\n getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>\n getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>\n getLocation(location: LocationAny): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition> {\n const location = Route0.getLocation(hrefOrHrefRelOrLocation) as never as KnownLocation<TDefinition>\n location.route = this.definition as definition<TDefinition>\n location.params = {}\n\n const escapeRegex = (s: string) => s.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n\n // Normalize pathname (no trailing slash except root)\n const pathname =\n location.pathname.length > 1 && location.pathname.endsWith('/')\n ? location.pathname.slice(0, -1)\n : location.pathname\n\n // Use getRegexString() to get the pattern\n const pattern = this.getRegexString()\n\n // Extract param names from the definition\n const paramNames: string[] = []\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n def.replace(/:([A-Za-z0-9_]+)/g, (_m: string, name: string) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n paramNames.push(String(name))\n return ''\n })\n\n const exactRe = new RegExp(`^${pattern}$`)\n const parentRe = new RegExp(`^${pattern}(?:/.*)?$`) // route matches the beginning of the URL (may have more)\n const exactMatch = pathname.match(exactRe)\n\n // Fill params only for exact match (keeps behavior predictable)\n if (exactMatch) {\n const values = exactMatch.slice(1)\n const params = Object.fromEntries(paramNames.map((n, i) => [n, decodeURIComponent(values[i] ?? '')]))\n location.params = params\n } else {\n location.params = {}\n }\n\n const exact = !!exactMatch\n const parent = !exact && parentRe.test(pathname)\n\n // \"children\": the URL is a prefix of the route definition (ignoring params' concrete values)\n // We check if the definition starts with the URL path boundary-wise.\n const children = !exact && new RegExp(`^${escapeRegex(pathname)}(?:/|$)`).test(def)\n\n return {\n ...location,\n exact,\n parent,\n children,\n } as KnownLocation<TDefinition>\n }\n\n isSame(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean {\n if ((!a && b) || (a && !b)) return false\n if (!a || !b) return true\n return Route0.create(a).isSame(Route0.create(b))\n }\n\n isChildren(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isParent(other: Route0<TDefinition>): boolean {\n return (\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isConflict(other: Route0<any>): boolean {\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Different lengths = no conflict (one is deeper than the other)\n if (thisParts.length !== otherParts.length) {\n return false\n }\n\n // Check if all segments could match\n for (let i = 0; i < thisParts.length; i++) {\n const thisPart = thisParts[i]\n const otherPart = otherParts[i]\n\n // Both params = always match\n if (thisPart.startsWith(':') && otherPart.startsWith(':')) {\n continue\n }\n\n // One is param = can match\n if (thisPart.startsWith(':') || otherPart.startsWith(':')) {\n continue\n }\n\n // Both static = must be same\n if (thisPart !== otherPart) {\n return false\n }\n }\n\n return true\n }\n\n isMoreSpecificThan(other: Route0<any>): boolean {\n // More specific = should come earlier when conflicted\n // Static segments beat param segments at the same position\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Compare segment by segment\n for (let i = 0; i < Math.min(thisParts.length, otherParts.length); i++) {\n const thisIsStatic = !thisParts[i].startsWith(':')\n const otherIsStatic = !otherParts[i].startsWith(':')\n\n if (thisIsStatic && !otherIsStatic) return true\n if (!thisIsStatic && otherIsStatic) return false\n }\n\n // All equal, use lexicographic\n return this.pathDefinition < other.pathDefinition\n }\n}\n\nexport class Routes<const T extends RoutesRecord = RoutesRecord> {\n readonly routes: RoutesRecordHydrated<T>\n readonly pathsOrdering: string[]\n readonly keysOrdering: string[]\n readonly ordered: CallabelRoute[]\n\n private constructor({\n routes,\n isHydrated = false,\n pathsOrdering,\n keysOrdering,\n ordered,\n }: {\n routes: RoutesRecordHydrated<T> | T\n isHydrated?: boolean\n pathsOrdering?: string[]\n keysOrdering?: string[]\n ordered?: CallabelRoute[]\n }) {\n this.routes = (\n isHydrated ? (routes as RoutesRecordHydrated<T>) : Routes._hydrate(routes)\n ) as RoutesRecordHydrated<T>\n if (!pathsOrdering || !keysOrdering || !ordered) {\n const ordering = Routes._makeOrdering(this.routes)\n this.pathsOrdering = ordering.pathsOrdering\n this.keysOrdering = ordering.keysOrdering\n this.ordered = this.keysOrdering.map((key) => this.routes[key])\n } else {\n this.pathsOrdering = pathsOrdering\n this.keysOrdering = keysOrdering\n this.ordered = ordered\n }\n }\n\n static create<const T extends RoutesRecord>(routes: T): RoutesPretty<T> {\n const instance = new Routes({ routes })\n return Routes._prettify(instance)\n }\n\n static _prettify<const T extends RoutesRecord>(instance: Routes<T>): RoutesPretty<T> {\n Object.setPrototypeOf(instance, Routes.prototype)\n Object.defineProperty(instance, Symbol.toStringTag, {\n value: 'Routes',\n })\n Object.assign(instance, {\n override: instance.override.bind(instance),\n })\n Object.assign(instance, instance.routes)\n return instance as unknown as RoutesPretty<T>\n }\n\n static _hydrate<const T extends RoutesRecord>(routes: T): RoutesRecordHydrated<T> {\n const result = {} as RoutesRecordHydrated<T>\n for (const key in routes) {\n if (Object.prototype.hasOwnProperty.call(routes, key)) {\n const value = routes[key]\n result[key] = (typeof value === 'string' ? Route0.create(value) : value) as CallabelRoute<T[typeof key]>\n }\n }\n return result\n }\n\n getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation\n getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation\n getLocation(location: LocationAny): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation {\n // Find the route that exactly matches the given location\n for (const route of this.ordered) {\n const loc = route.getLocation(hrefOrHrefRelOrLocation)\n if (loc.exact) {\n return loc\n }\n }\n // No exact match found, return UnknownLocation\n return Route0.getLocation(hrefOrHrefRelOrLocation)\n }\n\n static _makeOrdering(routes: RoutesRecord): { pathsOrdering: string[]; keysOrdering: string[] } {\n const hydrated = Routes._hydrate(routes)\n const entries = Object.entries(hydrated)\n\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n // Sort: shorter paths first, then by specificity, then alphabetically\n entries.sort(([_keyA, routeA], [_keyB, routeB]) => {\n const partsA = getParts(routeA.pathDefinition)\n const partsB = getParts(routeB.pathDefinition)\n\n // 1. Shorter paths first (by segment count)\n if (partsA.length !== partsB.length) {\n return partsA.length - partsB.length\n }\n\n // 2. Same length: check if they conflict\n if (routeA.isConflict(routeB)) {\n // Conflicting routes: more specific first\n if (routeA.isMoreSpecificThan(routeB)) return -1\n if (routeB.isMoreSpecificThan(routeA)) return 1\n }\n\n // 3. Same length, not conflicting or equal specificity: alphabetically\n return routeA.pathDefinition.localeCompare(routeB.pathDefinition)\n })\n\n const pathsOrdering = entries.map(([_key, route]) => route.definition)\n const keysOrdering = entries.map(([_key, route]) => _key)\n return { pathsOrdering, keysOrdering }\n }\n\n override(config: RouteConfigInput): RoutesPretty<T> {\n const newRoutes = {} as RoutesRecordHydrated<T>\n for (const key in this.routes) {\n if (Object.prototype.hasOwnProperty.call(this.routes, key)) {\n newRoutes[key] = this.routes[key].clone(config) as CallabelRoute<T[typeof key]>\n }\n }\n const instance = new Routes({\n routes: newRoutes,\n isHydrated: true,\n pathsOrdering: this.pathsOrdering,\n keysOrdering: this.keysOrdering,\n ordered: this.keysOrdering.map((key) => newRoutes[key]),\n })\n return Routes._prettify(instance)\n }\n}\n\n// main\n\nexport type AnyRoute<T extends Route0<string> | string = string> = T extends string ? Route0<T> : T\nexport type CallabelRoute<T extends Route0<string> | string = string> = AnyRoute<T> & AnyRoute<T>['get']\nexport type AnyRouteOrDefinition<T extends string> = AnyRoute<T> | T\nexport type RouteConfigInput = {\n baseUrl?: string\n}\n\n// collection\n\nexport type RoutesRecord = Record<string, AnyRoute | string>\nexport type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = RoutesRecord> = {\n [K in keyof TRoutesRecord]: CallabelRoute<TRoutesRecord[K]>\n}\nexport type RoutesPretty<TRoutesRecord extends RoutesRecord = RoutesRecord> = RoutesRecordHydrated<TRoutesRecord> &\n Routes<TRoutesRecord>\nexport type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty\n ? keyof TRoutes['routes']\n : TRoutes extends RoutesRecord\n ? keyof TRoutes\n : never\nexport type ExtractRoute<\n TRoutes extends RoutesPretty | RoutesRecord,\n TKey extends keyof ExtractRoutesKeys<TRoutes>,\n> = TKey extends keyof TRoutes ? TRoutes[TKey] : never\n\n// public utils\n\nexport type definition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['definition']\n : T extends string\n ? T\n : never\nexport type PathDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['pathDefinition']\n : T extends string\n ? _PathDefinition<T>\n : never\nexport type ParamsDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['paramsDefinition']\n : T extends string\n ? _ParamsDefinition<T>\n : undefined\nexport type SearchDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['searchDefinition']\n : T extends string\n ? _SearchDefinition<T>\n : undefined\n\nexport type Extended<T extends AnyRoute | string | undefined, TSuffixDefinition extends string> = T extends AnyRoute\n ? Route0<PathExtended<T['definition'], TSuffixDefinition>>\n : T extends string\n ? Route0<PathExtended<T, TSuffixDefinition>>\n : T extends undefined\n ? Route0<TSuffixDefinition>\n : never\n\nexport type IsParent<T extends AnyRoute | string, TParent extends AnyRoute | string> = _IsParent<\n PathDefinition<T>,\n PathDefinition<TParent>\n>\nexport type IsChildren<T extends AnyRoute | string, TChildren extends AnyRoute | string> = _IsChildren<\n PathDefinition<T>,\n PathDefinition<TChildren>\n>\nexport type IsSame<T extends AnyRoute | string, TExact extends AnyRoute | string> = _IsSame<\n PathDefinition<T>,\n PathDefinition<TExact>\n>\nexport type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | string> = _IsSameParams<\n ParamsDefinition<T1>,\n ParamsDefinition<T2>\n>\n\nexport type HasParams<T extends AnyRoute | string> =\n ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false\nexport type HasSearch<T extends AnyRoute | string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<definition<T>>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? false\n : true\n : false\n : false\n\nexport type ParamsOutput<T extends AnyRoute | string> = {\n [K in keyof ParamsDefinition<T>]: string\n}\nexport type SearchOutput<T extends AnyRoute | string = string> = Partial<\n {\n [K in keyof SearchDefinition<T>]?: string\n } & Record<string, string | undefined>\n>\nexport type StrictSearchOutput<T extends AnyRoute | string> = Partial<{\n [K in keyof SearchDefinition<T>]?: string | undefined\n}>\nexport type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>\nexport type SearchInput<T extends AnyRoute | string = string> = _SearchInput<definition<T>>\nexport type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<definition<T>>\n\n// location\n\nexport type LocationParams<TDefinition extends string> = {\n [K in keyof _ParamsDefinition<TDefinition>]: string\n}\nexport type LocationSearch<TDefinition extends string = string> = {\n [K in keyof _SearchDefinition<TDefinition>]: string | undefined\n} & Record<string, string | undefined>\n\nexport type _GeneralLocation = {\n pathname: string\n search: string\n hash: string\n origin?: string\n href?: string\n hrefRel: string\n abs: boolean\n port?: string\n host?: string\n hostname?: string\n}\nexport type UnknownLocation = _GeneralLocation & {\n params: undefined\n searchParams: SearchOutput\n route: undefined\n exact: false\n parent: false\n children: false\n}\nexport type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Record<never, never>\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: false\n parent: false\n children: false\n}\nexport type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: true\n parent: false\n children: false\n}\nexport type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Partial<ParamsOutput<TRoute>> // in fact maybe there will be whole params object, but does not matter now\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: false\n parent: true\n children: false\n}\nexport type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: false\n parent: false\n children: true\n}\nexport type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string> =\n | UnmatchedLocation<TRoute>\n | ExactLocation<TRoute>\n | ParentLocation<TRoute>\n | ChildrenLocation<TRoute>\nexport type LocationAny<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>\n\n// internal utils\n\nexport type _PathDefinition<T extends string> = T extends string ? TrimSearchTailDefinition<T> : never\nexport type _ParamsDefinition<TDefinition extends string> =\n ExtractPathParams<PathDefinition<TDefinition>> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\nexport type _SearchDefinition<TDefinition extends string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<TDefinition>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\n : undefined\n\nexport type _ParamsInput<TDefinition extends string> =\n _ParamsDefinition<TDefinition> extends undefined\n ? Record<never, never>\n : {\n [K in keyof _ParamsDefinition<TDefinition>]: string | number\n }\nexport type _SearchInput<TDefinition extends string> =\n _SearchDefinition<TDefinition> extends undefined\n ? Record<string, string | number>\n : Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n }> &\n Record<string, string | number>\nexport type _StrictSearchInput<TDefinition extends string> = Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n}>\n\nexport type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S\nexport type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : ''\nexport type SearchTailDefinitionWithFirstAmp<S extends string> = S extends `${string}&${infer T}` ? `&${T}` : ''\nexport type AmpSplit<S extends string> = S extends `${infer A}&${infer B}` ? A | AmpSplit<B> : S\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type NonEmpty<T> = [T] extends ['' | never] ? never : T\nexport type ExtractPathParams<S extends string> = S extends `${string}:${infer After}`\n ? After extends `${infer Name}/${infer Rest}`\n ? Name | ExtractPathParams<`/${Rest}`>\n : After\n : never\nexport type ReplacePathParams<S extends string> = S extends `${infer Head}:${infer Tail}`\n ? // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Tail extends `${infer _Param}/${infer Rest}`\n ? ReplacePathParams<`${Head}${string}/${Rest}`>\n : `${Head}${string}`\n : S\nexport type DedupeSlashes<S extends string> = S extends `${infer A}//${infer B}` ? DedupeSlashes<`${A}/${B}`> : S\nexport type EmptyRecord = Record<never, never>\nexport type JoinPath<Parent extends string, Suffix extends string> = DedupeSlashes<\n PathDefinition<Parent> extends infer A extends string\n ? PathDefinition<Suffix> extends infer B extends string\n ? A extends ''\n ? B extends ''\n ? ''\n : B extends `/${string}`\n ? B\n : `/${B}`\n : B extends ''\n ? A\n : A extends `${string}/`\n ? `${A}${B}`\n : B extends `/${string}`\n ? `${A}${B}`\n : `${A}/${B}`\n : never\n : never\n>\n\nexport type OnlyIfNoParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? Yes : No\nexport type OnlyIfHasParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? No : Yes\n\nexport type PathOnlyRouteValue<TDefinition extends string> = `${ReplacePathParams<PathDefinition<TDefinition>>}`\nexport type WithSearchRouteValue<TDefinition extends string> =\n `${ReplacePathParams<PathDefinition<TDefinition>>}?${string}`\nexport type AbsolutePathOnlyRouteValue<TDefinition extends string> =\n PathOnlyRouteValue<TDefinition> extends '/' ? string : `${string}${PathOnlyRouteValue<TDefinition>}`\nexport type AbsoluteWithSearchRouteValue<TDefinition extends string> = `${string}${WithSearchRouteValue<TDefinition>}`\n\nexport type PathExtended<\n TSourcedefinitionDefinition extends string,\n TSuffixdefinitionDefinition extends string,\n> = `${JoinPath<TSourcedefinitionDefinition, TSuffixdefinitionDefinition>}${SearchTailDefinitionWithFirstAmp<TSuffixdefinitionDefinition>}`\n\nexport type WithParamsInput<\n TDefinition extends string,\n T extends\n | {\n search?: _SearchInput<any>\n abs?: boolean\n }\n | undefined = undefined,\n> = _ParamsInput<TDefinition> & (T extends undefined ? Record<never, never> : T)\n\nexport type _IsSameParams<T1 extends object | undefined, T2 extends object | undefined> = T1 extends undefined\n ? T2 extends undefined\n ? true\n : false\n : T2 extends undefined\n ? false\n : T1 extends T2\n ? T2 extends T1\n ? true\n : false\n : false\n\nexport type _IsParent<T extends string, TParent extends string> = T extends TParent\n ? false\n : T extends `${TParent}${string}`\n ? true\n : false\nexport type _IsChildren<T extends string, TChildren extends string> = TChildren extends T\n ? false\n : TChildren extends `${T}${string}`\n ? true\n : false\nexport type _IsSame<T extends string, TExact extends string> = T extends TExact\n ? TExact extends T\n ? true\n : false\n : false\n"],"mappings":"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","names":["paramsInput","searchInput"]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// TODO: asterisk\n// TODO: optional params\n// TODO: required search\n\n// TODO: .extension('.json') to not add additional / but just add some extension\n// TODO: search input can be boolean, or even object with qs\n// TODO: Роут0 три пусть три тоже сам генерится вероятно\n// TODO: Роут0 три мод, тогда там все ноуты кончаются на .селф\n// TODO: use splats in param definition \"*\"\n// TODO: ? check extend for search only .extend('&x&z')\n// TODO: .create(route, {useSearch, useParams})\n// TODO: Из пас экзакт, из пасвизквери экзает, из чилдрен, из парент, из экзактОр\n// TODO: isEqual, isChildren, isParent\n// TODO: extractParams, extractSearch\n// TODO: getPathDefinition respecting definitionParamPrefix, definitionSearchPrefix\n// TODO: prepend\n// TODO: Route0.createTree({base:{self: x, children: ...})\n// TODO: overrideTree\n// TODO: .create(route, {baseUrl, useLocation})\n// TODO: ? optional path params as @\n// TODO: prependMany, extendMany, overrideMany, with types\n// TODO: optional route params /x/:id?\n\nexport class Route0<TDefinition extends string> {\n readonly definition: TDefinition\n readonly pathDefinition: _PathDefinition<TDefinition>\n readonly paramsDefinition: _ParamsDefinition<TDefinition>\n readonly searchDefinition: _SearchDefinition<TDefinition>\n baseUrl: string\n\n private constructor(definition: TDefinition, config: RouteConfigInput = {}) {\n this.definition = definition\n this.pathDefinition = Route0._getPathDefinitionBydefinition(definition)\n this.paramsDefinition = Route0._getParamsDefinitionBydefinition(definition)\n this.searchDefinition = Route0._getSearchDefinitionBydefinition(definition)\n\n const { baseUrl } = config\n if (baseUrl && typeof baseUrl === 'string' && baseUrl.length) {\n this.baseUrl = baseUrl\n } else {\n const g = globalThis as unknown as { location?: { origin?: string } }\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (typeof g?.location?.origin === 'string' && g.location.origin.length > 0) {\n this.baseUrl = g.location.origin\n } else {\n this.baseUrl = 'https://example.com'\n }\n }\n }\n\n static create<TDefinition extends string>(\n definition: TDefinition | AnyRoute<TDefinition>,\n config?: RouteConfigInput,\n ): CallabelRoute<TDefinition> {\n if (typeof definition === 'function') {\n return definition\n }\n const original = typeof definition === 'object' ? definition : new Route0<TDefinition>(definition, config)\n const callable = original.get.bind(original)\n Object.setPrototypeOf(callable, original)\n Object.defineProperty(callable, Symbol.toStringTag, {\n value: original.definition,\n })\n return callable as never\n }\n\n private static _splitPathDefinitionAndSearchTailDefinition(definition: string) {\n const i = definition.indexOf('&')\n if (i === -1) return { pathDefinition: definition, searchTailDefinition: '' }\n return {\n pathDefinition: definition.slice(0, i),\n searchTailDefinition: definition.slice(i),\n }\n }\n\n private static _getAbsPath(baseUrl: string, pathWithSearch: string) {\n return new URL(pathWithSearch, baseUrl).toString().replace(/\\/$/, '')\n }\n\n private static _getPathDefinitionBydefinition<TDefinition extends string>(definition: TDefinition) {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n return pathDefinition as _PathDefinition<TDefinition>\n }\n\n private static _getParamsDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _ParamsDefinition<TDefinition> {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n const matches = Array.from(pathDefinition.matchAll(/:([A-Za-z0-9_]+)/g))\n const paramsDefinition = Object.fromEntries(matches.map((m) => [m[1], true]))\n const keysCount = Object.keys(paramsDefinition).length\n if (keysCount === 0) {\n return undefined as _ParamsDefinition<TDefinition>\n }\n return paramsDefinition as _ParamsDefinition<TDefinition>\n }\n\n private static _getSearchDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _SearchDefinition<TDefinition> {\n const { searchTailDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n if (!searchTailDefinition) {\n return undefined as _SearchDefinition<TDefinition>\n }\n const keys = searchTailDefinition.split('&').filter(Boolean)\n const searchDefinition = Object.fromEntries(keys.map((k) => [k, true]))\n const keysCount = Object.keys(searchDefinition).length\n if (keysCount === 0) {\n return undefined as _SearchDefinition<TDefinition>\n }\n return searchDefinition as _SearchDefinition<TDefinition>\n }\n\n extend<TSuffixDefinition extends string>(\n suffixDefinition: TSuffixDefinition,\n ): CallabelRoute<PathExtended<TDefinition, TSuffixDefinition>> {\n const { pathDefinition: parentPathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(this.definition)\n const { pathDefinition: suffixPathDefinition, searchTailDefinition: suffixSearchTailDefinition } =\n Route0._splitPathDefinitionAndSearchTailDefinition(suffixDefinition)\n const pathDefinition = `${parentPathDefinition}/${suffixPathDefinition}`.replace(/\\/{2,}/g, '/')\n const definition = `${pathDefinition}${suffixSearchTailDefinition}` as PathExtended<TDefinition, TSuffixDefinition>\n return Route0.create<PathExtended<TDefinition, TSuffixDefinition>>(definition, { baseUrl: this.baseUrl })\n }\n\n // has params\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n get(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n get(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const { search, abs, ...params } = input\n return { searchInput: search || {}, paramsInput: params, absInput: abs ?? false }\n })()\n\n // validate params\n const neededParamsKeys = this.paramsDefinition ? Object.keys(this.paramsDefinition) : []\n const providedParamsKeys = Object.keys(paramsInput)\n const notProvidedKeys = neededParamsKeys.filter((k) => !providedParamsKeys.includes(k))\n if (notProvidedKeys.length) {\n // throw new Error(`Missing params: not defined keys ${notProvidedKeys.map((k) => `\"${k}\"`).join(\", \")}.`)\n Object.assign(paramsInput, Object.fromEntries(notProvidedKeys.map((k) => [k, 'undefined'])))\n }\n\n // create url\n\n let url = this.pathDefinition as string\n // replace params\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n url = url.replace(/:([A-Za-z0-9_]+)/g, (_m, k) => encodeURIComponent(String(paramsInput?.[k] ?? '')))\n // search params\n const searchInputStringified = Object.fromEntries(Object.entries(searchInput).map(([k, v]) => [k, String(v)]))\n url = [url, new URLSearchParams(searchInputStringified).toString()].filter(Boolean).join('?')\n // dedupe slashes\n url = url.replace(/\\/{2,}/g, '/')\n // absolute\n url = absInput ? Route0._getAbsPath(this.baseUrl, url) : url\n\n return url\n }\n\n // has params\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n flat(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n flat(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: args[1] ?? false }\n }\n const paramsKeys = this.getParamsKeys()\n const paramsInput = paramsKeys.reduce<Record<string, string | number>>((acc, key) => {\n if (input[key] !== undefined) {\n acc[key] = input[key]\n }\n return acc\n }, {})\n const searchKeys = this.getSearchKeys()\n const searchInput = Object.keys(input)\n .filter((k) => {\n if (searchKeys.includes(k)) {\n return true\n }\n if (paramsKeys.includes(k)) {\n return false\n }\n return true\n })\n .reduce<Record<string, string | number>>((acc, key) => {\n acc[key] = input[key]\n return acc\n }, {})\n return { searchInput, paramsInput, absInput: args[1] ?? false }\n })()\n\n return this.get({ ...paramsInput, search: searchInput, abs: absInput } as never)\n }\n\n getParamsKeys(): string[] {\n return Object.keys(this.paramsDefinition || {})\n }\n getSearchKeys(): string[] {\n return Object.keys(this.searchDefinition || {})\n }\n getFlatKeys(): string[] {\n return [...this.getSearchKeys(), ...this.getParamsKeys()]\n }\n\n getDefinition(): string {\n return this.pathDefinition\n }\n\n clone(config?: RouteConfigInput): Route0<TDefinition> {\n return new Route0(this.definition, config)\n }\n\n getRegexString(): string {\n // Normalize the path definition (remove trailing slash except for root)\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n\n // Replace :param with placeholders, escape regex special chars, then restore capture groups\n const pattern = def\n .replace(/:([A-Za-z0-9_]+)/g, '___PARAM___') // temporarily replace params with placeholder\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') // escape regex special chars\n .replace(/___PARAM___/g, '([^/]+)') // replace placeholder with capture group\n\n return pattern\n }\n\n getRegex(): RegExp {\n return new RegExp(`^${this.getRegexString()}$`)\n }\n\n static getRegexString(routes: AnyRoute[] | AnyRoute): string {\n const routesArray = Array.isArray(routes) ? routes : [routes]\n return routesArray.map((route) => route.getRegexString()).join('|')\n }\n static getRegex(routes: AnyRoute[] | AnyRoute): RegExp {\n return new RegExp(`^(${Route0.getRegexString(routes)})$`)\n }\n\n static getLocation(href: `${string}://${string}`): UnknownLocation\n static getLocation(hrefRel: `/${string}`): UnknownLocation\n static getLocation(hrefOrHrefRel: string): UnknownLocation\n static getLocation(location: AnyLocation): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation {\n if (typeof hrefOrHrefRelOrLocation !== 'string') {\n hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel\n }\n // Check if it's an absolute URL (starts with scheme://)\n const abs = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:\\/\\//.test(hrefOrHrefRelOrLocation)\n\n // Use dummy base only if relative\n const base = abs ? undefined : 'http://example.com'\n const url = new URL(hrefOrHrefRelOrLocation, base)\n\n // Extract search params\n const searchParams = Object.fromEntries(url.searchParams.entries())\n\n // Normalize pathname (remove trailing slash except for root)\n let pathname = url.pathname\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1)\n }\n\n // Common derived values\n const hrefRel = pathname + url.search + url.hash\n\n // Build the location object consistent with _GeneralLocation\n const location: UnknownLocation = {\n pathname,\n search: url.search,\n hash: url.hash,\n origin: abs ? url.origin : undefined,\n href: abs ? url.href : undefined,\n hrefRel,\n abs,\n\n // extra host-related fields (available even for relative with dummy base)\n host: abs ? url.host : undefined,\n hostname: abs ? url.hostname : undefined,\n port: abs ? url.port || undefined : undefined,\n\n // specific to UnknownLocation\n searchParams,\n params: undefined,\n route: undefined,\n exact: false,\n parent: false,\n children: false,\n }\n\n return location\n }\n\n getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>\n getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>\n getLocation(location: AnyLocation): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition> {\n const location = Route0.getLocation(hrefOrHrefRelOrLocation) as never as KnownLocation<TDefinition>\n location.route = this.definition as Definition<TDefinition>\n location.params = {}\n\n const escapeRegex = (s: string) => s.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n\n // Normalize pathname (no trailing slash except root)\n const pathname =\n location.pathname.length > 1 && location.pathname.endsWith('/')\n ? location.pathname.slice(0, -1)\n : location.pathname\n\n // Use getRegexString() to get the pattern\n const pattern = this.getRegexString()\n\n // Extract param names from the definition\n const paramNames: string[] = []\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n def.replace(/:([A-Za-z0-9_]+)/g, (_m: string, name: string) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n paramNames.push(String(name))\n return ''\n })\n\n const exactRe = new RegExp(`^${pattern}$`)\n const parentRe = new RegExp(`^${pattern}(?:/.*)?$`) // route matches the beginning of the URL (may have more)\n const exactMatch = pathname.match(exactRe)\n\n // Fill params only for exact match (keeps behavior predictable)\n if (exactMatch) {\n const values = exactMatch.slice(1)\n const params = Object.fromEntries(paramNames.map((n, i) => [n, decodeURIComponent(values[i] ?? '')]))\n location.params = params\n } else {\n location.params = {}\n }\n\n const exact = !!exactMatch\n const parent = !exact && parentRe.test(pathname)\n\n // \"children\": the URL is a prefix of the route definition (ignoring params' concrete values)\n // We check if the definition starts with the URL path boundary-wise.\n const children = !exact && new RegExp(`^${escapeRegex(pathname)}(?:/|$)`).test(def)\n\n return {\n ...location,\n exact,\n parent,\n children,\n } as KnownLocation<TDefinition>\n }\n\n isSame(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean {\n if ((!a && b) || (a && !b)) return false\n if (!a || !b) return true\n return Route0.create(a).isSame(Route0.create(b))\n }\n\n isChildren(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isParent(other: Route0<TDefinition>): boolean {\n return (\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isConflict(other: Route0<any>): boolean {\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Different lengths = no conflict (one is deeper than the other)\n if (thisParts.length !== otherParts.length) {\n return false\n }\n\n // Check if all segments could match\n for (let i = 0; i < thisParts.length; i++) {\n const thisPart = thisParts[i]\n const otherPart = otherParts[i]\n\n // Both params = always match\n if (thisPart.startsWith(':') && otherPart.startsWith(':')) {\n continue\n }\n\n // One is param = can match\n if (thisPart.startsWith(':') || otherPart.startsWith(':')) {\n continue\n }\n\n // Both static = must be same\n if (thisPart !== otherPart) {\n return false\n }\n }\n\n return true\n }\n\n isMoreSpecificThan(other: Route0<any>): boolean {\n // More specific = should come earlier when conflicted\n // Static segments beat param segments at the same position\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Compare segment by segment\n for (let i = 0; i < Math.min(thisParts.length, otherParts.length); i++) {\n const thisIsStatic = !thisParts[i].startsWith(':')\n const otherIsStatic = !otherParts[i].startsWith(':')\n\n if (thisIsStatic && !otherIsStatic) return true\n if (!thisIsStatic && otherIsStatic) return false\n }\n\n // All equal, use lexicographic\n return this.pathDefinition < other.pathDefinition\n }\n}\n\nexport class Routes<const T extends RoutesRecord = RoutesRecord> {\n readonly routes: RoutesRecordHydrated<T>\n readonly pathsOrdering: string[]\n readonly keysOrdering: string[]\n readonly ordered: CallabelRoute[]\n\n private constructor({\n routes,\n isHydrated = false,\n pathsOrdering,\n keysOrdering,\n ordered,\n }: {\n routes: RoutesRecordHydrated<T> | T\n isHydrated?: boolean\n pathsOrdering?: string[]\n keysOrdering?: string[]\n ordered?: CallabelRoute[]\n }) {\n this.routes = (\n isHydrated ? (routes as RoutesRecordHydrated<T>) : Routes._hydrate(routes)\n ) as RoutesRecordHydrated<T>\n if (!pathsOrdering || !keysOrdering || !ordered) {\n const ordering = Routes._makeOrdering(this.routes)\n this.pathsOrdering = ordering.pathsOrdering\n this.keysOrdering = ordering.keysOrdering\n this.ordered = this.keysOrdering.map((key) => this.routes[key])\n } else {\n this.pathsOrdering = pathsOrdering\n this.keysOrdering = keysOrdering\n this.ordered = ordered\n }\n }\n\n static create<const T extends RoutesRecord>(routes: T): RoutesPretty<T> {\n const instance = new Routes({ routes })\n return Routes._prettify(instance)\n }\n\n static _prettify<const T extends RoutesRecord>(instance: Routes<T>): RoutesPretty<T> {\n Object.setPrototypeOf(instance, Routes.prototype)\n Object.defineProperty(instance, Symbol.toStringTag, {\n value: 'Routes',\n })\n Object.assign(instance, {\n override: instance.override.bind(instance),\n })\n Object.assign(instance, instance.routes)\n return instance as unknown as RoutesPretty<T>\n }\n\n static _hydrate<const T extends RoutesRecord>(routes: T): RoutesRecordHydrated<T> {\n const result = {} as RoutesRecordHydrated<T>\n for (const key in routes) {\n if (Object.prototype.hasOwnProperty.call(routes, key)) {\n const value = routes[key]\n result[key] = (typeof value === 'string' ? Route0.create(value) : value) as CallabelRoute<T[typeof key]>\n }\n }\n return result\n }\n\n getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation\n getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation\n getLocation(location: AnyLocation): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation {\n // Find the route that exactly matches the given location\n for (const route of this.ordered) {\n const loc = route.getLocation(hrefOrHrefRelOrLocation)\n if (loc.exact) {\n return loc\n }\n }\n // No exact match found, return UnknownLocation\n return Route0.getLocation(hrefOrHrefRelOrLocation)\n }\n\n static _makeOrdering(routes: RoutesRecord): { pathsOrdering: string[]; keysOrdering: string[] } {\n const hydrated = Routes._hydrate(routes)\n const entries = Object.entries(hydrated)\n\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n // Sort: shorter paths first, then by specificity, then alphabetically\n entries.sort(([_keyA, routeA], [_keyB, routeB]) => {\n const partsA = getParts(routeA.pathDefinition)\n const partsB = getParts(routeB.pathDefinition)\n\n // 1. Shorter paths first (by segment count)\n if (partsA.length !== partsB.length) {\n return partsA.length - partsB.length\n }\n\n // 2. Same length: check if they conflict\n if (routeA.isConflict(routeB)) {\n // Conflicting routes: more specific first\n if (routeA.isMoreSpecificThan(routeB)) return -1\n if (routeB.isMoreSpecificThan(routeA)) return 1\n }\n\n // 3. Same length, not conflicting or equal specificity: alphabetically\n return routeA.pathDefinition.localeCompare(routeB.pathDefinition)\n })\n\n const pathsOrdering = entries.map(([_key, route]) => route.definition)\n const keysOrdering = entries.map(([_key, route]) => _key)\n return { pathsOrdering, keysOrdering }\n }\n\n override(config: RouteConfigInput): RoutesPretty<T> {\n const newRoutes = {} as RoutesRecordHydrated<T>\n for (const key in this.routes) {\n if (Object.prototype.hasOwnProperty.call(this.routes, key)) {\n newRoutes[key] = this.routes[key].clone(config) as CallabelRoute<T[typeof key]>\n }\n }\n const instance = new Routes({\n routes: newRoutes,\n isHydrated: true,\n pathsOrdering: this.pathsOrdering,\n keysOrdering: this.keysOrdering,\n ordered: this.keysOrdering.map((key) => newRoutes[key]),\n })\n return Routes._prettify(instance)\n }\n}\n\n// main\n\nexport type AnyRoute<T extends Route0<string> | string = string> = T extends string ? Route0<T> : T\nexport type CallabelRoute<T extends Route0<string> | string = string> = AnyRoute<T> & AnyRoute<T>['get']\nexport type AnyRouteOrDefinition<T extends string> = AnyRoute<T> | T\nexport type RouteConfigInput = {\n baseUrl?: string\n}\n\n// collection\n\nexport type RoutesRecord = Record<string, AnyRoute | string>\nexport type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = RoutesRecord> = {\n [K in keyof TRoutesRecord]: CallabelRoute<TRoutesRecord[K]>\n}\nexport type RoutesPretty<TRoutesRecord extends RoutesRecord = RoutesRecord> = RoutesRecordHydrated<TRoutesRecord> &\n Routes<TRoutesRecord>\nexport type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty\n ? keyof TRoutes['routes']\n : TRoutes extends RoutesRecord\n ? keyof TRoutes\n : never\nexport type ExtractRoute<\n TRoutes extends RoutesPretty | RoutesRecord,\n TKey extends keyof ExtractRoutesKeys<TRoutes>,\n> = TKey extends keyof TRoutes ? TRoutes[TKey] : never\n\n// public utils\n\nexport type Definition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['definition']\n : T extends string\n ? T\n : never\nexport type PathDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['pathDefinition']\n : T extends string\n ? _PathDefinition<T>\n : never\nexport type ParamsDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['paramsDefinition']\n : T extends string\n ? _ParamsDefinition<T>\n : undefined\nexport type SearchDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['searchDefinition']\n : T extends string\n ? _SearchDefinition<T>\n : undefined\n\nexport type Extended<T extends AnyRoute | string | undefined, TSuffixDefinition extends string> = T extends AnyRoute\n ? Route0<PathExtended<T['definition'], TSuffixDefinition>>\n : T extends string\n ? Route0<PathExtended<T, TSuffixDefinition>>\n : T extends undefined\n ? Route0<TSuffixDefinition>\n : never\n\nexport type IsParent<T extends AnyRoute | string, TParent extends AnyRoute | string> = _IsParent<\n PathDefinition<T>,\n PathDefinition<TParent>\n>\nexport type IsChildren<T extends AnyRoute | string, TChildren extends AnyRoute | string> = _IsChildren<\n PathDefinition<T>,\n PathDefinition<TChildren>\n>\nexport type IsSame<T extends AnyRoute | string, TExact extends AnyRoute | string> = _IsSame<\n PathDefinition<T>,\n PathDefinition<TExact>\n>\nexport type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | string> = _IsSameParams<\n ParamsDefinition<T1>,\n ParamsDefinition<T2>\n>\n\nexport type HasParams<T extends AnyRoute | string> =\n ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false\nexport type HasSearch<T extends AnyRoute | string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<Definition<T>>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? false\n : true\n : false\n : false\n\nexport type ParamsOutput<T extends AnyRoute | string> = {\n [K in keyof ParamsDefinition<T>]: string\n}\nexport type SearchOutput<T extends AnyRoute | string = string> = Partial<\n {\n [K in keyof SearchDefinition<T>]?: string\n } & Record<string, string | undefined>\n>\nexport type StrictSearchOutput<T extends AnyRoute | string> = Partial<{\n [K in keyof SearchDefinition<T>]?: string | undefined\n}>\nexport type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>\nexport type SearchInput<T extends AnyRoute | string = string> = _SearchInput<Definition<T>>\nexport type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<Definition<T>>\nexport type FlatInput<T extends AnyRoute | string> = _FlatInput<Definition<T>>\nexport type StrictFlatInput<T extends AnyRoute | string> = _StrictFlatInput<Definition<T>>\nexport type CanInputBeEmpty<T extends AnyRoute | string> = HasParams<Definition<T>> extends true ? false : true\n\n// location\n\nexport type LocationParams<TDefinition extends string> = {\n [K in keyof _ParamsDefinition<TDefinition>]: string\n}\nexport type LocationSearch<TDefinition extends string = string> = {\n [K in keyof _SearchDefinition<TDefinition>]: string | undefined\n} & Record<string, string | undefined>\n\nexport type _GeneralLocation = {\n pathname: string\n search: string\n hash: string\n origin?: string\n href?: string\n hrefRel: string\n abs: boolean\n port?: string\n host?: string\n hostname?: string\n}\nexport type UnknownLocation = _GeneralLocation & {\n params: undefined\n searchParams: SearchOutput\n route: undefined\n exact: false\n parent: false\n children: false\n}\nexport type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Record<never, never>\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: false\n parent: false\n children: false\n}\nexport type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: true\n parent: false\n children: false\n}\nexport type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Partial<ParamsOutput<TRoute>> // in fact maybe there will be whole params object, but does not matter now\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: false\n parent: true\n children: false\n}\nexport type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: false\n parent: false\n children: true\n}\nexport type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string> =\n | UnmatchedLocation<TRoute>\n | ExactLocation<TRoute>\n | ParentLocation<TRoute>\n | ChildrenLocation<TRoute>\nexport type AnyLocation<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>\n\n// internal utils\n\nexport type _PathDefinition<T extends string> = T extends string ? TrimSearchTailDefinition<T> : never\nexport type _ParamsDefinition<TDefinition extends string> =\n ExtractPathParams<PathDefinition<TDefinition>> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\nexport type _SearchDefinition<TDefinition extends string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<TDefinition>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\n : undefined\n\nexport type _ParamsInput<TDefinition extends string> =\n _ParamsDefinition<TDefinition> extends undefined\n ? Record<never, never>\n : {\n [K in keyof _ParamsDefinition<TDefinition>]: string | number\n }\nexport type _SearchInput<TDefinition extends string> =\n _SearchDefinition<TDefinition> extends undefined\n ? Record<string, string | number>\n : Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n }> &\n Record<string, string | number>\nexport type _StrictSearchInput<TDefinition extends string> = Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n}>\nexport type _FlatInput<TDefinition extends string> =\n HasParams<TDefinition> extends true\n ? _ParamsInput<TDefinition> & _SearchInput<TDefinition>\n : _SearchInput<TDefinition>\nexport type _StrictFlatInput<TDefinition extends string> =\n HasParams<TDefinition> extends true\n ? HasSearch<TDefinition> extends true\n ? _StrictSearchInput<TDefinition> & _ParamsInput<TDefinition>\n : _ParamsInput<TDefinition>\n : HasSearch<TDefinition> extends true\n ? _StrictSearchInput<TDefinition>\n : Record<never, never>\n\nexport type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S\nexport type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : ''\nexport type SearchTailDefinitionWithFirstAmp<S extends string> = S extends `${string}&${infer T}` ? `&${T}` : ''\nexport type AmpSplit<S extends string> = S extends `${infer A}&${infer B}` ? A | AmpSplit<B> : S\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type NonEmpty<T> = [T] extends ['' | never] ? never : T\nexport type ExtractPathParams<S extends string> = S extends `${string}:${infer After}`\n ? After extends `${infer Name}/${infer Rest}`\n ? Name | ExtractPathParams<`/${Rest}`>\n : After\n : never\nexport type ReplacePathParams<S extends string> = S extends `${infer Head}:${infer Tail}`\n ? // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Tail extends `${infer _Param}/${infer Rest}`\n ? ReplacePathParams<`${Head}${string}/${Rest}`>\n : `${Head}${string}`\n : S\nexport type DedupeSlashes<S extends string> = S extends `${infer A}//${infer B}` ? DedupeSlashes<`${A}/${B}`> : S\nexport type EmptyRecord = Record<never, never>\nexport type JoinPath<Parent extends string, Suffix extends string> = DedupeSlashes<\n PathDefinition<Parent> extends infer A extends string\n ? PathDefinition<Suffix> extends infer B extends string\n ? A extends ''\n ? B extends ''\n ? ''\n : B extends `/${string}`\n ? B\n : `/${B}`\n : B extends ''\n ? A\n : A extends `${string}/`\n ? `${A}${B}`\n : B extends `/${string}`\n ? `${A}${B}`\n : `${A}/${B}`\n : never\n : never\n>\n\nexport type OnlyIfNoParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? Yes : No\nexport type OnlyIfHasParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? No : Yes\n\nexport type PathOnlyRouteValue<TDefinition extends string> = `${ReplacePathParams<PathDefinition<TDefinition>>}`\nexport type WithSearchRouteValue<TDefinition extends string> =\n `${ReplacePathParams<PathDefinition<TDefinition>>}?${string}`\nexport type AbsolutePathOnlyRouteValue<TDefinition extends string> =\n PathOnlyRouteValue<TDefinition> extends '/' ? string : `${string}${PathOnlyRouteValue<TDefinition>}`\nexport type AbsoluteWithSearchRouteValue<TDefinition extends string> = `${string}${WithSearchRouteValue<TDefinition>}`\n\nexport type PathExtended<\n TSourcedefinitionDefinition extends string,\n TSuffixdefinitionDefinition extends string,\n> = `${JoinPath<TSourcedefinitionDefinition, TSuffixdefinitionDefinition>}${SearchTailDefinitionWithFirstAmp<TSuffixdefinitionDefinition>}`\n\nexport type WithParamsInput<\n TDefinition extends string,\n T extends\n | {\n search?: _SearchInput<any>\n abs?: boolean\n }\n | undefined = undefined,\n> = _ParamsInput<TDefinition> & (T extends undefined ? Record<never, never> : T)\n\nexport type _IsSameParams<T1 extends object | undefined, T2 extends object | undefined> = T1 extends undefined\n ? T2 extends undefined\n ? true\n : false\n : T2 extends undefined\n ? false\n : T1 extends T2\n ? T2 extends T1\n ? true\n : false\n : false\n\nexport type _IsParent<T extends string, TParent extends string> = T extends TParent\n ? false\n : T extends `${TParent}${string}`\n ? true\n : false\nexport type _IsChildren<T extends string, TChildren extends string> = TChildren extends T\n ? false\n : TChildren extends `${T}${string}`\n ? true\n : false\nexport type _IsSame<T extends string, TExact extends string> = T extends TExact\n ? TExact extends T\n ? true\n : false\n : false\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBO,MAAM,OAAmC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAEQ,YAAY,YAAyB,SAA2B,CAAC,GAAG;AAC1E,SAAK,aAAa;AAClB,SAAK,iBAAiB,OAAO,+BAA+B,UAAU;AACtE,SAAK,mBAAmB,OAAO,iCAAiC,UAAU;AAC1E,SAAK,mBAAmB,OAAO,iCAAiC,UAAU;AAE1E,UAAM,EAAE,QAAQ,IAAI;AACpB,QAAI,WAAW,OAAO,YAAY,YAAY,QAAQ,QAAQ;AAC5D,WAAK,UAAU;AAAA,IACjB,OAAO;AACL,YAAM,IAAI;AAEV,UAAI,OAAO,GAAG,UAAU,WAAW,YAAY,EAAE,SAAS,OAAO,SAAS,GAAG;AAC3E,aAAK,UAAU,EAAE,SAAS;AAAA,MAC5B,OAAO;AACL,aAAK,UAAU;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,OACL,YACA,QAC4B;AAC5B,QAAI,OAAO,eAAe,YAAY;AACpC,aAAO;AAAA,IACT;AACA,UAAM,WAAW,OAAO,eAAe,WAAW,aAAa,IAAI,OAAoB,YAAY,MAAM;AACzG,UAAM,WAAW,SAAS,IAAI,KAAK,QAAQ;AAC3C,WAAO,eAAe,UAAU,QAAQ;AACxC,WAAO,eAAe,UAAU,OAAO,aAAa;AAAA,MAClD,OAAO,SAAS;AAAA,IAClB,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,OAAe,4CAA4C,YAAoB;AAC7E,UAAM,IAAI,WAAW,QAAQ,GAAG;AAChC,QAAI,MAAM,GAAI,QAAO,EAAE,gBAAgB,YAAY,sBAAsB,GAAG;AAC5E,WAAO;AAAA,MACL,gBAAgB,WAAW,MAAM,GAAG,CAAC;AAAA,MACrC,sBAAsB,WAAW,MAAM,CAAC;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,OAAe,YAAY,SAAiB,gBAAwB;AAClE,WAAO,IAAI,IAAI,gBAAgB,OAAO,EAAE,SAAS,EAAE,QAAQ,OAAO,EAAE;AAAA,EACtE;AAAA,EAEA,OAAe,+BAA2D,YAAyB;AACjG,UAAM,EAAE,eAAe,IAAI,OAAO,4CAA4C,UAAU;AACxF,WAAO;AAAA,EACT;AAAA,EAEA,OAAe,iCACb,YACgC;AAChC,UAAM,EAAE,eAAe,IAAI,OAAO,4CAA4C,UAAU;AACxF,UAAM,UAAU,MAAM,KAAK,eAAe,SAAS,mBAAmB,CAAC;AACvE,UAAM,mBAAmB,OAAO,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAC5E,UAAM,YAAY,OAAO,KAAK,gBAAgB,EAAE;AAChD,QAAI,cAAc,GAAG;AACnB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAe,iCACb,YACgC;AAChC,UAAM,EAAE,qBAAqB,IAAI,OAAO,4CAA4C,UAAU;AAC9F,QAAI,CAAC,sBAAsB;AACzB,aAAO;AAAA,IACT;AACA,UAAM,OAAO,qBAAqB,MAAM,GAAG,EAAE,OAAO,OAAO;AAC3D,UAAM,mBAAmB,OAAO,YAAY,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AACtE,UAAM,YAAY,OAAO,KAAK,gBAAgB,EAAE;AAChD,QAAI,cAAc,GAAG;AACnB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OACE,kBAC6D;AAC7D,UAAM,EAAE,gBAAgB,qBAAqB,IAAI,OAAO,4CAA4C,KAAK,UAAU;AACnH,UAAM,EAAE,gBAAgB,sBAAsB,sBAAsB,2BAA2B,IAC7F,OAAO,4CAA4C,gBAAgB;AACrE,UAAM,iBAAiB,GAAG,oBAAoB,IAAI,oBAAoB,GAAG,QAAQ,WAAW,GAAG;AAC/F,UAAM,aAAa,GAAG,cAAc,GAAG,0BAA0B;AACjE,WAAO,OAAO,OAAqD,YAAY,EAAE,SAAS,KAAK,QAAQ,CAAC;AAAA,EAC1G;AAAA;AAAA,EA4CA,OAAO,MAAqB;AAC1B,UAAM,EAAE,aAAa,aAAa,SAAS,KAAK,MAI3C;AACH,UAAI,KAAK,WAAW,GAAG;AACrB,eAAO,EAAE,aAAa,CAAC,GAAG,aAAa,CAAC,GAAG,UAAU,MAAM;AAAA,MAC7D;AACA,YAAM,QAAQ,KAAK,CAAC;AACpB,UAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAE/C,eAAO,EAAE,aAAa,CAAC,GAAG,aAAa,CAAC,GAAG,UAAU,MAAM;AAAA,MAC7D;AACA,YAAM,EAAE,QAAQ,KAAK,GAAG,OAAO,IAAI;AACnC,aAAO,EAAE,aAAa,UAAU,CAAC,GAAG,aAAa,QAAQ,UAAU,OAAO,MAAM;AAAA,IAClF,GAAG;AAGH,UAAM,mBAAmB,KAAK,mBAAmB,OAAO,KAAK,KAAK,gBAAgB,IAAI,CAAC;AACvF,UAAM,qBAAqB,OAAO,KAAK,WAAW;AAClD,UAAM,kBAAkB,iBAAiB,OAAO,CAAC,MAAM,CAAC,mBAAmB,SAAS,CAAC,CAAC;AACtF,QAAI,gBAAgB,QAAQ;AAE1B,aAAO,OAAO,aAAa,OAAO,YAAY,gBAAgB,IAAI,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;AAAA,IAC7F;AAIA,QAAI,MAAM,KAAK;AAGf,UAAM,IAAI,QAAQ,qBAAqB,CAAC,IAAI,MAAM,mBAAmB,OAAO,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC;AAEpG,UAAM,yBAAyB,OAAO,YAAY,OAAO,QAAQ,WAAW,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7G,UAAM,CAAC,KAAK,IAAI,gBAAgB,sBAAsB,EAAE,SAAS,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE5F,UAAM,IAAI,QAAQ,WAAW,GAAG;AAEhC,UAAM,WAAW,OAAO,YAAY,KAAK,SAAS,GAAG,IAAI;AAEzD,WAAO;AAAA,EACT;AAAA;AAAA,EAwCA,QAAQ,MAAqB;AAC3B,UAAM,EAAE,aAAa,aAAa,SAAS,KAAK,MAI3C;AACH,UAAI,KAAK,WAAW,GAAG;AACrB,eAAO,EAAE,aAAa,CAAC,GAAG,aAAa,CAAC,GAAG,UAAU,MAAM;AAAA,MAC7D;AACA,YAAM,QAAQ,KAAK,CAAC;AACpB,UAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAE/C,eAAO,EAAE,aAAa,CAAC,GAAG,aAAa,CAAC,GAAG,UAAU,KAAK,CAAC,KAAK,MAAM;AAAA,MACxE;AACA,YAAM,aAAa,KAAK,cAAc;AACtC,YAAMA,eAAc,WAAW,OAAwC,CAAC,KAAK,QAAQ;AACnF,YAAI,MAAM,GAAG,MAAM,QAAW;AAC5B,cAAI,GAAG,IAAI,MAAM,GAAG;AAAA,QACtB;AACA,eAAO;AAAA,MACT,GAAG,CAAC,CAAC;AACL,YAAM,aAAa,KAAK,cAAc;AACtC,YAAMC,eAAc,OAAO,KAAK,KAAK,EAClC,OAAO,CAAC,MAAM;AACb,YAAI,WAAW,SAAS,CAAC,GAAG;AAC1B,iBAAO;AAAA,QACT;AACA,YAAI,WAAW,SAAS,CAAC,GAAG;AAC1B,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT,CAAC,EACA,OAAwC,CAAC,KAAK,QAAQ;AACrD,YAAI,GAAG,IAAI,MAAM,GAAG;AACpB,eAAO;AAAA,MACT,GAAG,CAAC,CAAC;AACP,aAAO,EAAE,aAAAA,cAAa,aAAAD,cAAa,UAAU,KAAK,CAAC,KAAK,MAAM;AAAA,IAChE,GAAG;AAEH,WAAO,KAAK,IAAI,EAAE,GAAG,aAAa,QAAQ,aAAa,KAAK,SAAS,CAAU;AAAA,EACjF;AAAA,EAEA,gBAA0B;AACxB,WAAO,OAAO,KAAK,KAAK,oBAAoB,CAAC,CAAC;AAAA,EAChD;AAAA,EACA,gBAA0B;AACxB,WAAO,OAAO,KAAK,KAAK,oBAAoB,CAAC,CAAC;AAAA,EAChD;AAAA,EACA,cAAwB;AACtB,WAAO,CAAC,GAAG,KAAK,cAAc,GAAG,GAAG,KAAK,cAAc,CAAC;AAAA,EAC1D;AAAA,EAEA,gBAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAgD;AACpD,WAAO,IAAI,OAAO,KAAK,YAAY,MAAM;AAAA,EAC3C;AAAA,EAEA,iBAAyB;AAEvB,UAAM,MACJ,KAAK,eAAe,SAAS,KAAK,KAAK,eAAe,SAAS,GAAG,IAC9D,KAAK,eAAe,MAAM,GAAG,EAAE,IAC/B,KAAK;AAGX,UAAM,UAAU,IACb,QAAQ,qBAAqB,aAAa,EAC1C,QAAQ,uBAAuB,MAAM,EACrC,QAAQ,gBAAgB,SAAS;AAEpC,WAAO;AAAA,EACT;AAAA,EAEA,WAAmB;AACjB,WAAO,IAAI,OAAO,IAAI,KAAK,eAAe,CAAC,GAAG;AAAA,EAChD;AAAA,EAEA,OAAO,eAAe,QAAuC;AAC3D,UAAM,cAAc,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAC5D,WAAO,YAAY,IAAI,CAAC,UAAU,MAAM,eAAe,CAAC,EAAE,KAAK,GAAG;AAAA,EACpE;AAAA,EACA,OAAO,SAAS,QAAuC;AACrD,WAAO,IAAI,OAAO,KAAK,OAAO,eAAe,MAAM,CAAC,IAAI;AAAA,EAC1D;AAAA,EAOA,OAAO,YAAY,yBAAgE;AACjF,QAAI,OAAO,4BAA4B,UAAU;AAC/C,gCAA0B,wBAAwB,QAAQ,wBAAwB;AAAA,IACpF;AAEA,UAAM,MAAM,gCAAgC,KAAK,uBAAuB;AAGxE,UAAM,OAAO,MAAM,SAAY;AAC/B,UAAM,MAAM,IAAI,IAAI,yBAAyB,IAAI;AAGjD,UAAM,eAAe,OAAO,YAAY,IAAI,aAAa,QAAQ,CAAC;AAGlE,QAAI,WAAW,IAAI;AACnB,QAAI,SAAS,SAAS,KAAK,SAAS,SAAS,GAAG,GAAG;AACjD,iBAAW,SAAS,MAAM,GAAG,EAAE;AAAA,IACjC;AAGA,UAAM,UAAU,WAAW,IAAI,SAAS,IAAI;AAG5C,UAAM,WAA4B;AAAA,MAChC;AAAA,MACA,QAAQ,IAAI;AAAA,MACZ,MAAM,IAAI;AAAA,MACV,QAAQ,MAAM,IAAI,SAAS;AAAA,MAC3B,MAAM,MAAM,IAAI,OAAO;AAAA,MACvB;AAAA,MACA;AAAA;AAAA,MAGA,MAAM,MAAM,IAAI,OAAO;AAAA,MACvB,UAAU,MAAM,IAAI,WAAW;AAAA,MAC/B,MAAM,MAAM,IAAI,QAAQ,SAAY;AAAA;AAAA,MAGpC;AAAA,MACA,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAAA,EAOA,YAAY,yBAA2E;AACrF,UAAM,WAAW,OAAO,YAAY,uBAAuB;AAC3D,aAAS,QAAQ,KAAK;AACtB,aAAS,SAAS,CAAC;AAEnB,UAAM,cAAc,CAAC,MAAc,EAAE,QAAQ,yBAAyB,MAAM;AAG5E,UAAM,WACJ,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,SAAS,GAAG,IAC1D,SAAS,SAAS,MAAM,GAAG,EAAE,IAC7B,SAAS;AAGf,UAAM,UAAU,KAAK,eAAe;AAGpC,UAAM,aAAuB,CAAC;AAC9B,UAAM,MACJ,KAAK,eAAe,SAAS,KAAK,KAAK,eAAe,SAAS,GAAG,IAC9D,KAAK,eAAe,MAAM,GAAG,EAAE,IAC/B,KAAK;AACX,QAAI,QAAQ,qBAAqB,CAAC,IAAY,SAAiB;AAE7D,iBAAW,KAAK,OAAO,IAAI,CAAC;AAC5B,aAAO;AAAA,IACT,CAAC;AAED,UAAM,UAAU,IAAI,OAAO,IAAI,OAAO,GAAG;AACzC,UAAM,WAAW,IAAI,OAAO,IAAI,OAAO,WAAW;AAClD,UAAM,aAAa,SAAS,MAAM,OAAO;AAGzC,QAAI,YAAY;AACd,YAAM,SAAS,WAAW,MAAM,CAAC;AACjC,YAAM,SAAS,OAAO,YAAY,WAAW,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,mBAAmB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACpG,eAAS,SAAS;AAAA,IACpB,OAAO;AACL,eAAS,SAAS,CAAC;AAAA,IACrB;AAEA,UAAM,QAAQ,CAAC,CAAC;AAChB,UAAM,SAAS,CAAC,SAAS,SAAS,KAAK,QAAQ;AAI/C,UAAM,WAAW,CAAC,SAAS,IAAI,OAAO,IAAI,YAAY,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG;AAElF,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,OAAqC;AAC1C,WACE,KAAK,eAAe,QAAQ,qBAAqB,WAAW,MAC5D,MAAM,eAAe,QAAQ,qBAAqB,WAAW;AAAA,EAEjE;AAAA,EACA,OAAO,OAAO,GAAkC,GAA2C;AACzF,QAAK,CAAC,KAAK,KAAO,KAAK,CAAC,EAAI,QAAO;AACnC,QAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,WAAO,OAAO,OAAO,CAAC,EAAE,OAAO,OAAO,OAAO,CAAC,CAAC;AAAA,EACjD;AAAA,EAEA,WAAW,OAAqC;AAC9C,WACE,KAAK,eAAe,QAAQ,qBAAqB,WAAW,MAC5D,MAAM,eAAe,QAAQ,qBAAqB,WAAW;AAAA,EAEjE;AAAA,EAEA,SAAS,OAAqC;AAC5C,WACE,MAAM,eAAe,QAAQ,qBAAqB,WAAW,MAC7D,KAAK,eAAe,QAAQ,qBAAqB,WAAW;AAAA,EAEhE;AAAA,EAEA,WAAW,OAA6B;AACtC,UAAM,WAAW,CAAC,SAAiB;AACjC,UAAI,SAAS,IAAK,QAAO,CAAC,GAAG;AAC7B,aAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAAA,IACvC;AAEA,UAAM,YAAY,SAAS,KAAK,cAAc;AAC9C,UAAM,aAAa,SAAS,MAAM,cAAc;AAGhD,QAAI,UAAU,WAAW,WAAW,QAAQ;AAC1C,aAAO;AAAA,IACT;AAGA,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,WAAW,UAAU,CAAC;AAC5B,YAAM,YAAY,WAAW,CAAC;AAG9B,UAAI,SAAS,WAAW,GAAG,KAAK,UAAU,WAAW,GAAG,GAAG;AACzD;AAAA,MACF;AAGA,UAAI,SAAS,WAAW,GAAG,KAAK,UAAU,WAAW,GAAG,GAAG;AACzD;AAAA,MACF;AAGA,UAAI,aAAa,WAAW;AAC1B,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,mBAAmB,OAA6B;AAG9C,UAAM,WAAW,CAAC,SAAiB;AACjC,UAAI,SAAS,IAAK,QAAO,CAAC,GAAG;AAC7B,aAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAAA,IACvC;AAEA,UAAM,YAAY,SAAS,KAAK,cAAc;AAC9C,UAAM,aAAa,SAAS,MAAM,cAAc;AAGhD,aAAS,IAAI,GAAG,IAAI,KAAK,IAAI,UAAU,QAAQ,WAAW,MAAM,GAAG,KAAK;AACtE,YAAM,eAAe,CAAC,UAAU,CAAC,EAAE,WAAW,GAAG;AACjD,YAAM,gBAAgB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG;AAEnD,UAAI,gBAAgB,CAAC,cAAe,QAAO;AAC3C,UAAI,CAAC,gBAAgB,cAAe,QAAO;AAAA,IAC7C;AAGA,WAAO,KAAK,iBAAiB,MAAM;AAAA,EACrC;AACF;AAEO,MAAM,OAAoD;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED,YAAY;AAAA,IAClB;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAMG;AACD,SAAK,SACH,aAAc,SAAqC,OAAO,SAAS,MAAM;AAE3E,QAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,SAAS;AAC/C,YAAM,WAAW,OAAO,cAAc,KAAK,MAAM;AACjD,WAAK,gBAAgB,SAAS;AAC9B,WAAK,eAAe,SAAS;AAC7B,WAAK,UAAU,KAAK,aAAa,IAAI,CAAC,QAAQ,KAAK,OAAO,GAAG,CAAC;AAAA,IAChE,OAAO;AACL,WAAK,gBAAgB;AACrB,WAAK,eAAe;AACpB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,OAAO,OAAqC,QAA4B;AACtE,UAAM,WAAW,IAAI,OAAO,EAAE,OAAO,CAAC;AACtC,WAAO,OAAO,UAAU,QAAQ;AAAA,EAClC;AAAA,EAEA,OAAO,UAAwC,UAAsC;AACnF,WAAO,eAAe,UAAU,OAAO,SAAS;AAChD,WAAO,eAAe,UAAU,OAAO,aAAa;AAAA,MAClD,OAAO;AAAA,IACT,CAAC;AACD,WAAO,OAAO,UAAU;AAAA,MACtB,UAAU,SAAS,SAAS,KAAK,QAAQ;AAAA,IAC3C,CAAC;AACD,WAAO,OAAO,UAAU,SAAS,MAAM;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,SAAuC,QAAoC;AAChF,UAAM,SAAS,CAAC;AAChB,eAAW,OAAO,QAAQ;AACxB,UAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AACrD,cAAM,QAAQ,OAAO,GAAG;AACxB,eAAO,GAAG,IAAK,OAAO,UAAU,WAAW,OAAO,OAAO,KAAK,IAAI;AAAA,MACpE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAOA,YAAY,yBAAgF;AAE1F,eAAW,SAAS,KAAK,SAAS;AAChC,YAAM,MAAM,MAAM,YAAY,uBAAuB;AACrD,UAAI,IAAI,OAAO;AACb,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,OAAO,YAAY,uBAAuB;AAAA,EACnD;AAAA,EAEA,OAAO,cAAc,QAA2E;AAC9F,UAAM,WAAW,OAAO,SAAS,MAAM;AACvC,UAAM,UAAU,OAAO,QAAQ,QAAQ;AAEvC,UAAM,WAAW,CAAC,SAAiB;AACjC,UAAI,SAAS,IAAK,QAAO,CAAC,GAAG;AAC7B,aAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAAA,IACvC;AAGA,YAAQ,KAAK,CAAC,CAAC,OAAO,MAAM,GAAG,CAAC,OAAO,MAAM,MAAM;AACjD,YAAM,SAAS,SAAS,OAAO,cAAc;AAC7C,YAAM,SAAS,SAAS,OAAO,cAAc;AAG7C,UAAI,OAAO,WAAW,OAAO,QAAQ;AACnC,eAAO,OAAO,SAAS,OAAO;AAAA,MAChC;AAGA,UAAI,OAAO,WAAW,MAAM,GAAG;AAE7B,YAAI,OAAO,mBAAmB,MAAM,EAAG,QAAO;AAC9C,YAAI,OAAO,mBAAmB,MAAM,EAAG,QAAO;AAAA,MAChD;AAGA,aAAO,OAAO,eAAe,cAAc,OAAO,cAAc;AAAA,IAClE,CAAC;AAED,UAAM,gBAAgB,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,MAAM,UAAU;AACrE,UAAM,eAAe,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI;AACxD,WAAO,EAAE,eAAe,aAAa;AAAA,EACvC;AAAA,EAEA,SAAS,QAA2C;AAClD,UAAM,YAAY,CAAC;AACnB,eAAW,OAAO,KAAK,QAAQ;AAC7B,UAAI,OAAO,UAAU,eAAe,KAAK,KAAK,QAAQ,GAAG,GAAG;AAC1D,kBAAU,GAAG,IAAI,KAAK,OAAO,GAAG,EAAE,MAAM,MAAM;AAAA,MAChD;AAAA,IACF;AACA,UAAM,WAAW,IAAI,OAAO;AAAA,MAC1B,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe,KAAK;AAAA,MACpB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK,aAAa,IAAI,CAAC,QAAQ,UAAU,GAAG,CAAC;AAAA,IACxD,CAAC;AACD,WAAO,OAAO,UAAU,QAAQ;AAAA,EAClC;AACF;","names":["paramsInput","searchInput"]}
@@ -66,13 +66,13 @@ declare class Route0<TDefinition extends string> {
66
66
  static getLocation(href: `${string}://${string}`): UnknownLocation;
67
67
  static getLocation(hrefRel: `/${string}`): UnknownLocation;
68
68
  static getLocation(hrefOrHrefRel: string): UnknownLocation;
69
- static getLocation(location: LocationAny): UnknownLocation;
70
- static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation;
69
+ static getLocation(location: AnyLocation): UnknownLocation;
70
+ static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation;
71
71
  getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>;
72
72
  getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>;
73
73
  getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>;
74
- getLocation(location: LocationAny): KnownLocation<TDefinition>;
75
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition>;
74
+ getLocation(location: AnyLocation): KnownLocation<TDefinition>;
75
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition>;
76
76
  isSame(other: Route0<TDefinition>): boolean;
77
77
  static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean;
78
78
  isChildren(other: Route0<TDefinition>): boolean;
@@ -92,8 +92,8 @@ declare class Routes<const T extends RoutesRecord = RoutesRecord> {
92
92
  getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation;
93
93
  getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation;
94
94
  getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation;
95
- getLocation(location: LocationAny): UnknownLocation | ExactLocation;
96
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation;
95
+ getLocation(location: AnyLocation): UnknownLocation | ExactLocation;
96
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation;
97
97
  static _makeOrdering(routes: RoutesRecord): {
98
98
  pathsOrdering: string[];
99
99
  keysOrdering: string[];
@@ -113,7 +113,7 @@ type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = RoutesRecord> = {
113
113
  type RoutesPretty<TRoutesRecord extends RoutesRecord = RoutesRecord> = RoutesRecordHydrated<TRoutesRecord> & Routes<TRoutesRecord>;
114
114
  type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty ? keyof TRoutes['routes'] : TRoutes extends RoutesRecord ? keyof TRoutes : never;
115
115
  type ExtractRoute<TRoutes extends RoutesPretty | RoutesRecord, TKey extends keyof ExtractRoutesKeys<TRoutes>> = TKey extends keyof TRoutes ? TRoutes[TKey] : never;
116
- type definition<T extends AnyRoute | string> = T extends AnyRoute ? T['definition'] : T extends string ? T : never;
116
+ type Definition<T extends AnyRoute | string> = T extends AnyRoute ? T['definition'] : T extends string ? T : never;
117
117
  type PathDefinition<T extends AnyRoute | string> = T extends AnyRoute ? T['pathDefinition'] : T extends string ? _PathDefinition<T> : never;
118
118
  type ParamsDefinition<T extends AnyRoute | string> = T extends AnyRoute ? T['paramsDefinition'] : T extends string ? _ParamsDefinition<T> : undefined;
119
119
  type SearchDefinition<T extends AnyRoute | string> = T extends AnyRoute ? T['searchDefinition'] : T extends string ? _SearchDefinition<T> : undefined;
@@ -123,7 +123,7 @@ type IsChildren<T extends AnyRoute | string, TChildren extends AnyRoute | string
123
123
  type IsSame<T extends AnyRoute | string, TExact extends AnyRoute | string> = _IsSame<PathDefinition<T>, PathDefinition<TExact>>;
124
124
  type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | string> = _IsSameParams<ParamsDefinition<T1>, ParamsDefinition<T2>>;
125
125
  type HasParams<T extends AnyRoute | string> = ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false;
126
- type HasSearch<T extends AnyRoute | string> = NonEmpty<SearchTailDefinitionWithoutFirstAmp<definition<T>>> extends infer Tail extends string ? AmpSplit<Tail> extends infer U ? [U] extends [never] ? false : true : false : false;
126
+ type HasSearch<T extends AnyRoute | string> = NonEmpty<SearchTailDefinitionWithoutFirstAmp<Definition<T>>> extends infer Tail extends string ? AmpSplit<Tail> extends infer U ? [U] extends [never] ? false : true : false : false;
127
127
  type ParamsOutput<T extends AnyRoute | string> = {
128
128
  [K in keyof ParamsDefinition<T>]: string;
129
129
  };
@@ -134,8 +134,11 @@ type StrictSearchOutput<T extends AnyRoute | string> = Partial<{
134
134
  [K in keyof SearchDefinition<T>]?: string | undefined;
135
135
  }>;
136
136
  type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>;
137
- type SearchInput<T extends AnyRoute | string = string> = _SearchInput<definition<T>>;
138
- type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<definition<T>>;
137
+ type SearchInput<T extends AnyRoute | string = string> = _SearchInput<Definition<T>>;
138
+ type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<Definition<T>>;
139
+ type FlatInput<T extends AnyRoute | string> = _FlatInput<Definition<T>>;
140
+ type StrictFlatInput<T extends AnyRoute | string> = _StrictFlatInput<Definition<T>>;
141
+ type CanInputBeEmpty<T extends AnyRoute | string> = HasParams<Definition<T>> extends true ? false : true;
139
142
  type LocationParams<TDefinition extends string> = {
140
143
  [K in keyof _ParamsDefinition<TDefinition>]: string;
141
144
  };
@@ -165,7 +168,7 @@ type UnknownLocation = _GeneralLocation & {
165
168
  type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
166
169
  params: Record<never, never>;
167
170
  searchParams: SearchOutput<TRoute>;
168
- route: definition<TRoute>;
171
+ route: Definition<TRoute>;
169
172
  exact: false;
170
173
  parent: false;
171
174
  children: false;
@@ -173,7 +176,7 @@ type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _
173
176
  type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
174
177
  params: ParamsOutput<TRoute>;
175
178
  searchParams: SearchOutput<TRoute>;
176
- route: definition<TRoute>;
179
+ route: Definition<TRoute>;
177
180
  exact: true;
178
181
  parent: false;
179
182
  children: false;
@@ -181,7 +184,7 @@ type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _Gene
181
184
  type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
182
185
  params: Partial<ParamsOutput<TRoute>>;
183
186
  searchParams: SearchOutput<TRoute>;
184
- route: definition<TRoute>;
187
+ route: Definition<TRoute>;
185
188
  exact: false;
186
189
  parent: true;
187
190
  children: false;
@@ -189,13 +192,13 @@ type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _Gen
189
192
  type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
190
193
  params: ParamsOutput<TRoute>;
191
194
  searchParams: SearchOutput<TRoute>;
192
- route: definition<TRoute>;
195
+ route: Definition<TRoute>;
193
196
  exact: false;
194
197
  parent: false;
195
198
  children: true;
196
199
  };
197
200
  type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string> = UnmatchedLocation<TRoute> | ExactLocation<TRoute> | ParentLocation<TRoute> | ChildrenLocation<TRoute>;
198
- type LocationAny<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>;
201
+ type AnyLocation<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>;
199
202
  type _PathDefinition<T extends string> = T extends string ? TrimSearchTailDefinition<T> : never;
200
203
  type _ParamsDefinition<TDefinition extends string> = ExtractPathParams<PathDefinition<TDefinition>> extends infer U ? [U] extends [never] ? undefined : {
201
204
  [K in Extract<U, string>]: true;
@@ -212,6 +215,8 @@ type _SearchInput<TDefinition extends string> = _SearchDefinition<TDefinition> e
212
215
  type _StrictSearchInput<TDefinition extends string> = Partial<{
213
216
  [K in keyof _SearchDefinition<TDefinition>]: string | number;
214
217
  }>;
218
+ type _FlatInput<TDefinition extends string> = HasParams<TDefinition> extends true ? _ParamsInput<TDefinition> & _SearchInput<TDefinition> : _SearchInput<TDefinition>;
219
+ type _StrictFlatInput<TDefinition extends string> = HasParams<TDefinition> extends true ? HasSearch<TDefinition> extends true ? _StrictSearchInput<TDefinition> & _ParamsInput<TDefinition> : _ParamsInput<TDefinition> : HasSearch<TDefinition> extends true ? _StrictSearchInput<TDefinition> : Record<never, never>;
215
220
  type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S;
216
221
  type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : '';
217
222
  type SearchTailDefinitionWithFirstAmp<S extends string> = S extends `${string}&${infer T}` ? `&${T}` : '';
@@ -238,4 +243,4 @@ type _IsParent<T extends string, TParent extends string> = T extends TParent ? f
238
243
  type _IsChildren<T extends string, TChildren extends string> = TChildren extends T ? false : TChildren extends `${T}${string}` ? true : false;
239
244
  type _IsSame<T extends string, TExact extends string> = T extends TExact ? TExact extends T ? true : false : false;
240
245
 
241
- export { type AbsolutePathOnlyRouteValue, type AbsoluteWithSearchRouteValue, type AmpSplit, type AnyRoute, type AnyRouteOrDefinition, type CallabelRoute, type ChildrenLocation, type DedupeSlashes, type EmptyRecord, type ExactLocation, type Extended, type ExtractPathParams, type ExtractRoute, type ExtractRoutesKeys, type HasParams, type HasSearch, type IsChildren, type IsParent, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationAny, type LocationParams, type LocationSearch, type NonEmpty, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsOutput, type ParentLocation, type PathDefinition, type PathExtended, type PathOnlyRouteValue, type ReplacePathParams, Route0, type RouteConfigInput, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SearchDefinition, type SearchInput, type SearchOutput, type SearchTailDefinitionWithFirstAmp, type SearchTailDefinitionWithoutFirstAmp, type StrictSearchInput, type StrictSearchOutput, type TrimSearchTailDefinition, type UnknownLocation, type UnmatchedLocation, type WithParamsInput, type WithSearchRouteValue, type _GeneralLocation, type _IsChildren, type _IsParent, type _IsSame, type _IsSameParams, type _ParamsDefinition, type _ParamsInput, type _PathDefinition, type _SearchDefinition, type _SearchInput, type _StrictSearchInput, type definition };
246
+ export { type AbsolutePathOnlyRouteValue, type AbsoluteWithSearchRouteValue, type AmpSplit, type AnyLocation, type AnyRoute, type AnyRouteOrDefinition, type CallabelRoute, type CanInputBeEmpty, type ChildrenLocation, type DedupeSlashes, type Definition, type EmptyRecord, type ExactLocation, type Extended, type ExtractPathParams, type ExtractRoute, type ExtractRoutesKeys, type FlatInput, type HasParams, type HasSearch, type IsChildren, type IsParent, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationParams, type LocationSearch, type NonEmpty, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsOutput, type ParentLocation, type PathDefinition, type PathExtended, type PathOnlyRouteValue, type ReplacePathParams, Route0, type RouteConfigInput, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SearchDefinition, type SearchInput, type SearchOutput, type SearchTailDefinitionWithFirstAmp, type SearchTailDefinitionWithoutFirstAmp, type StrictFlatInput, type StrictSearchInput, type StrictSearchOutput, type TrimSearchTailDefinition, type UnknownLocation, type UnmatchedLocation, type WithParamsInput, type WithSearchRouteValue, type _FlatInput, type _GeneralLocation, type _IsChildren, type _IsParent, type _IsSame, type _IsSameParams, type _ParamsDefinition, type _ParamsInput, type _PathDefinition, type _SearchDefinition, type _SearchInput, type _StrictFlatInput, type _StrictSearchInput };
@@ -66,13 +66,13 @@ declare class Route0<TDefinition extends string> {
66
66
  static getLocation(href: `${string}://${string}`): UnknownLocation;
67
67
  static getLocation(hrefRel: `/${string}`): UnknownLocation;
68
68
  static getLocation(hrefOrHrefRel: string): UnknownLocation;
69
- static getLocation(location: LocationAny): UnknownLocation;
70
- static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation;
69
+ static getLocation(location: AnyLocation): UnknownLocation;
70
+ static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation;
71
71
  getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>;
72
72
  getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>;
73
73
  getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>;
74
- getLocation(location: LocationAny): KnownLocation<TDefinition>;
75
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition>;
74
+ getLocation(location: AnyLocation): KnownLocation<TDefinition>;
75
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition>;
76
76
  isSame(other: Route0<TDefinition>): boolean;
77
77
  static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean;
78
78
  isChildren(other: Route0<TDefinition>): boolean;
@@ -92,8 +92,8 @@ declare class Routes<const T extends RoutesRecord = RoutesRecord> {
92
92
  getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation;
93
93
  getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation;
94
94
  getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation;
95
- getLocation(location: LocationAny): UnknownLocation | ExactLocation;
96
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation;
95
+ getLocation(location: AnyLocation): UnknownLocation | ExactLocation;
96
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation;
97
97
  static _makeOrdering(routes: RoutesRecord): {
98
98
  pathsOrdering: string[];
99
99
  keysOrdering: string[];
@@ -113,7 +113,7 @@ type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = RoutesRecord> = {
113
113
  type RoutesPretty<TRoutesRecord extends RoutesRecord = RoutesRecord> = RoutesRecordHydrated<TRoutesRecord> & Routes<TRoutesRecord>;
114
114
  type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty ? keyof TRoutes['routes'] : TRoutes extends RoutesRecord ? keyof TRoutes : never;
115
115
  type ExtractRoute<TRoutes extends RoutesPretty | RoutesRecord, TKey extends keyof ExtractRoutesKeys<TRoutes>> = TKey extends keyof TRoutes ? TRoutes[TKey] : never;
116
- type definition<T extends AnyRoute | string> = T extends AnyRoute ? T['definition'] : T extends string ? T : never;
116
+ type Definition<T extends AnyRoute | string> = T extends AnyRoute ? T['definition'] : T extends string ? T : never;
117
117
  type PathDefinition<T extends AnyRoute | string> = T extends AnyRoute ? T['pathDefinition'] : T extends string ? _PathDefinition<T> : never;
118
118
  type ParamsDefinition<T extends AnyRoute | string> = T extends AnyRoute ? T['paramsDefinition'] : T extends string ? _ParamsDefinition<T> : undefined;
119
119
  type SearchDefinition<T extends AnyRoute | string> = T extends AnyRoute ? T['searchDefinition'] : T extends string ? _SearchDefinition<T> : undefined;
@@ -123,7 +123,7 @@ type IsChildren<T extends AnyRoute | string, TChildren extends AnyRoute | string
123
123
  type IsSame<T extends AnyRoute | string, TExact extends AnyRoute | string> = _IsSame<PathDefinition<T>, PathDefinition<TExact>>;
124
124
  type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | string> = _IsSameParams<ParamsDefinition<T1>, ParamsDefinition<T2>>;
125
125
  type HasParams<T extends AnyRoute | string> = ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false;
126
- type HasSearch<T extends AnyRoute | string> = NonEmpty<SearchTailDefinitionWithoutFirstAmp<definition<T>>> extends infer Tail extends string ? AmpSplit<Tail> extends infer U ? [U] extends [never] ? false : true : false : false;
126
+ type HasSearch<T extends AnyRoute | string> = NonEmpty<SearchTailDefinitionWithoutFirstAmp<Definition<T>>> extends infer Tail extends string ? AmpSplit<Tail> extends infer U ? [U] extends [never] ? false : true : false : false;
127
127
  type ParamsOutput<T extends AnyRoute | string> = {
128
128
  [K in keyof ParamsDefinition<T>]: string;
129
129
  };
@@ -134,8 +134,11 @@ type StrictSearchOutput<T extends AnyRoute | string> = Partial<{
134
134
  [K in keyof SearchDefinition<T>]?: string | undefined;
135
135
  }>;
136
136
  type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>;
137
- type SearchInput<T extends AnyRoute | string = string> = _SearchInput<definition<T>>;
138
- type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<definition<T>>;
137
+ type SearchInput<T extends AnyRoute | string = string> = _SearchInput<Definition<T>>;
138
+ type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<Definition<T>>;
139
+ type FlatInput<T extends AnyRoute | string> = _FlatInput<Definition<T>>;
140
+ type StrictFlatInput<T extends AnyRoute | string> = _StrictFlatInput<Definition<T>>;
141
+ type CanInputBeEmpty<T extends AnyRoute | string> = HasParams<Definition<T>> extends true ? false : true;
139
142
  type LocationParams<TDefinition extends string> = {
140
143
  [K in keyof _ParamsDefinition<TDefinition>]: string;
141
144
  };
@@ -165,7 +168,7 @@ type UnknownLocation = _GeneralLocation & {
165
168
  type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
166
169
  params: Record<never, never>;
167
170
  searchParams: SearchOutput<TRoute>;
168
- route: definition<TRoute>;
171
+ route: Definition<TRoute>;
169
172
  exact: false;
170
173
  parent: false;
171
174
  children: false;
@@ -173,7 +176,7 @@ type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _
173
176
  type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
174
177
  params: ParamsOutput<TRoute>;
175
178
  searchParams: SearchOutput<TRoute>;
176
- route: definition<TRoute>;
179
+ route: Definition<TRoute>;
177
180
  exact: true;
178
181
  parent: false;
179
182
  children: false;
@@ -181,7 +184,7 @@ type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _Gene
181
184
  type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
182
185
  params: Partial<ParamsOutput<TRoute>>;
183
186
  searchParams: SearchOutput<TRoute>;
184
- route: definition<TRoute>;
187
+ route: Definition<TRoute>;
185
188
  exact: false;
186
189
  parent: true;
187
190
  children: false;
@@ -189,13 +192,13 @@ type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _Gen
189
192
  type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
190
193
  params: ParamsOutput<TRoute>;
191
194
  searchParams: SearchOutput<TRoute>;
192
- route: definition<TRoute>;
195
+ route: Definition<TRoute>;
193
196
  exact: false;
194
197
  parent: false;
195
198
  children: true;
196
199
  };
197
200
  type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string> = UnmatchedLocation<TRoute> | ExactLocation<TRoute> | ParentLocation<TRoute> | ChildrenLocation<TRoute>;
198
- type LocationAny<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>;
201
+ type AnyLocation<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>;
199
202
  type _PathDefinition<T extends string> = T extends string ? TrimSearchTailDefinition<T> : never;
200
203
  type _ParamsDefinition<TDefinition extends string> = ExtractPathParams<PathDefinition<TDefinition>> extends infer U ? [U] extends [never] ? undefined : {
201
204
  [K in Extract<U, string>]: true;
@@ -212,6 +215,8 @@ type _SearchInput<TDefinition extends string> = _SearchDefinition<TDefinition> e
212
215
  type _StrictSearchInput<TDefinition extends string> = Partial<{
213
216
  [K in keyof _SearchDefinition<TDefinition>]: string | number;
214
217
  }>;
218
+ type _FlatInput<TDefinition extends string> = HasParams<TDefinition> extends true ? _ParamsInput<TDefinition> & _SearchInput<TDefinition> : _SearchInput<TDefinition>;
219
+ type _StrictFlatInput<TDefinition extends string> = HasParams<TDefinition> extends true ? HasSearch<TDefinition> extends true ? _StrictSearchInput<TDefinition> & _ParamsInput<TDefinition> : _ParamsInput<TDefinition> : HasSearch<TDefinition> extends true ? _StrictSearchInput<TDefinition> : Record<never, never>;
215
220
  type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S;
216
221
  type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : '';
217
222
  type SearchTailDefinitionWithFirstAmp<S extends string> = S extends `${string}&${infer T}` ? `&${T}` : '';
@@ -238,4 +243,4 @@ type _IsParent<T extends string, TParent extends string> = T extends TParent ? f
238
243
  type _IsChildren<T extends string, TChildren extends string> = TChildren extends T ? false : TChildren extends `${T}${string}` ? true : false;
239
244
  type _IsSame<T extends string, TExact extends string> = T extends TExact ? TExact extends T ? true : false : false;
240
245
 
241
- export { type AbsolutePathOnlyRouteValue, type AbsoluteWithSearchRouteValue, type AmpSplit, type AnyRoute, type AnyRouteOrDefinition, type CallabelRoute, type ChildrenLocation, type DedupeSlashes, type EmptyRecord, type ExactLocation, type Extended, type ExtractPathParams, type ExtractRoute, type ExtractRoutesKeys, type HasParams, type HasSearch, type IsChildren, type IsParent, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationAny, type LocationParams, type LocationSearch, type NonEmpty, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsOutput, type ParentLocation, type PathDefinition, type PathExtended, type PathOnlyRouteValue, type ReplacePathParams, Route0, type RouteConfigInput, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SearchDefinition, type SearchInput, type SearchOutput, type SearchTailDefinitionWithFirstAmp, type SearchTailDefinitionWithoutFirstAmp, type StrictSearchInput, type StrictSearchOutput, type TrimSearchTailDefinition, type UnknownLocation, type UnmatchedLocation, type WithParamsInput, type WithSearchRouteValue, type _GeneralLocation, type _IsChildren, type _IsParent, type _IsSame, type _IsSameParams, type _ParamsDefinition, type _ParamsInput, type _PathDefinition, type _SearchDefinition, type _SearchInput, type _StrictSearchInput, type definition };
246
+ export { type AbsolutePathOnlyRouteValue, type AbsoluteWithSearchRouteValue, type AmpSplit, type AnyLocation, type AnyRoute, type AnyRouteOrDefinition, type CallabelRoute, type CanInputBeEmpty, type ChildrenLocation, type DedupeSlashes, type Definition, type EmptyRecord, type ExactLocation, type Extended, type ExtractPathParams, type ExtractRoute, type ExtractRoutesKeys, type FlatInput, type HasParams, type HasSearch, type IsChildren, type IsParent, type IsSame, type IsSameParams, type JoinPath, type KnownLocation, type LocationParams, type LocationSearch, type NonEmpty, type OnlyIfHasParams, type OnlyIfNoParams, type ParamsDefinition, type ParamsInput, type ParamsOutput, type ParentLocation, type PathDefinition, type PathExtended, type PathOnlyRouteValue, type ReplacePathParams, Route0, type RouteConfigInput, Routes, type RoutesPretty, type RoutesRecord, type RoutesRecordHydrated, type SearchDefinition, type SearchInput, type SearchOutput, type SearchTailDefinitionWithFirstAmp, type SearchTailDefinitionWithoutFirstAmp, type StrictFlatInput, type StrictSearchInput, type StrictSearchOutput, type TrimSearchTailDefinition, type UnknownLocation, type UnmatchedLocation, type WithParamsInput, type WithSearchRouteValue, type _FlatInput, type _GeneralLocation, type _IsChildren, type _IsParent, type _IsSame, type _IsSameParams, type _ParamsDefinition, type _ParamsInput, type _PathDefinition, type _SearchDefinition, type _SearchInput, type _StrictFlatInput, type _StrictSearchInput };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// TODO: asterisk\n// TODO: optional params\n// TODO: required search\n\n// TODO: .extension('.json') to not add additional / but just add some extension\n// TODO: search input can be boolean, or even object with qs\n// TODO: Роут0 три пусть три тоже сам генерится вероятно\n// TODO: Роут0 три мод, тогда там все ноуты кончаются на .селф\n// TODO: use splats in param definition \"*\"\n// TODO: ? check extend for search only .extend('&x&z')\n// TODO: .create(route, {useSearch, useParams})\n// TODO: Из пас экзакт, из пасвизквери экзает, из чилдрен, из парент, из экзактОр\n// TODO: isEqual, isChildren, isParent\n// TODO: extractParams, extractSearch\n// TODO: getPathDefinition respecting definitionParamPrefix, definitionSearchPrefix\n// TODO: prepend\n// TODO: Route0.createTree({base:{self: x, children: ...})\n// TODO: overrideTree\n// TODO: .create(route, {baseUrl, useLocation})\n// TODO: ? optional path params as @\n// TODO: prependMany, extendMany, overrideMany, with types\n// TODO: optional route params /x/:id?\n\nexport class Route0<TDefinition extends string> {\n readonly definition: TDefinition\n readonly pathDefinition: _PathDefinition<TDefinition>\n readonly paramsDefinition: _ParamsDefinition<TDefinition>\n readonly searchDefinition: _SearchDefinition<TDefinition>\n baseUrl: string\n\n private constructor(definition: TDefinition, config: RouteConfigInput = {}) {\n this.definition = definition\n this.pathDefinition = Route0._getPathDefinitionBydefinition(definition)\n this.paramsDefinition = Route0._getParamsDefinitionBydefinition(definition)\n this.searchDefinition = Route0._getSearchDefinitionBydefinition(definition)\n\n const { baseUrl } = config\n if (baseUrl && typeof baseUrl === 'string' && baseUrl.length) {\n this.baseUrl = baseUrl\n } else {\n const g = globalThis as unknown as { location?: { origin?: string } }\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (typeof g?.location?.origin === 'string' && g.location.origin.length > 0) {\n this.baseUrl = g.location.origin\n } else {\n this.baseUrl = 'https://example.com'\n }\n }\n }\n\n static create<TDefinition extends string>(\n definition: TDefinition | AnyRoute<TDefinition>,\n config?: RouteConfigInput,\n ): CallabelRoute<TDefinition> {\n if (typeof definition === 'function') {\n return definition\n }\n const original = typeof definition === 'object' ? definition : new Route0<TDefinition>(definition, config)\n const callable = original.get.bind(original)\n Object.setPrototypeOf(callable, original)\n Object.defineProperty(callable, Symbol.toStringTag, {\n value: original.definition,\n })\n return callable as never\n }\n\n private static _splitPathDefinitionAndSearchTailDefinition(definition: string) {\n const i = definition.indexOf('&')\n if (i === -1) return { pathDefinition: definition, searchTailDefinition: '' }\n return {\n pathDefinition: definition.slice(0, i),\n searchTailDefinition: definition.slice(i),\n }\n }\n\n private static _getAbsPath(baseUrl: string, pathWithSearch: string) {\n return new URL(pathWithSearch, baseUrl).toString().replace(/\\/$/, '')\n }\n\n private static _getPathDefinitionBydefinition<TDefinition extends string>(definition: TDefinition) {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n return pathDefinition as _PathDefinition<TDefinition>\n }\n\n private static _getParamsDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _ParamsDefinition<TDefinition> {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n const matches = Array.from(pathDefinition.matchAll(/:([A-Za-z0-9_]+)/g))\n const paramsDefinition = Object.fromEntries(matches.map((m) => [m[1], true]))\n const keysCount = Object.keys(paramsDefinition).length\n if (keysCount === 0) {\n return undefined as _ParamsDefinition<TDefinition>\n }\n return paramsDefinition as _ParamsDefinition<TDefinition>\n }\n\n private static _getSearchDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _SearchDefinition<TDefinition> {\n const { searchTailDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n if (!searchTailDefinition) {\n return undefined as _SearchDefinition<TDefinition>\n }\n const keys = searchTailDefinition.split('&').filter(Boolean)\n const searchDefinition = Object.fromEntries(keys.map((k) => [k, true]))\n const keysCount = Object.keys(searchDefinition).length\n if (keysCount === 0) {\n return undefined as _SearchDefinition<TDefinition>\n }\n return searchDefinition as _SearchDefinition<TDefinition>\n }\n\n extend<TSuffixDefinition extends string>(\n suffixDefinition: TSuffixDefinition,\n ): CallabelRoute<PathExtended<TDefinition, TSuffixDefinition>> {\n const { pathDefinition: parentPathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(this.definition)\n const { pathDefinition: suffixPathDefinition, searchTailDefinition: suffixSearchTailDefinition } =\n Route0._splitPathDefinitionAndSearchTailDefinition(suffixDefinition)\n const pathDefinition = `${parentPathDefinition}/${suffixPathDefinition}`.replace(/\\/{2,}/g, '/')\n const definition = `${pathDefinition}${suffixSearchTailDefinition}` as PathExtended<TDefinition, TSuffixDefinition>\n return Route0.create<PathExtended<TDefinition, TSuffixDefinition>>(definition, { baseUrl: this.baseUrl })\n }\n\n // has params\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n get(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n get(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const { search, abs, ...params } = input\n return { searchInput: search || {}, paramsInput: params, absInput: abs ?? false }\n })()\n\n // validate params\n const neededParamsKeys = this.paramsDefinition ? Object.keys(this.paramsDefinition) : []\n const providedParamsKeys = Object.keys(paramsInput)\n const notProvidedKeys = neededParamsKeys.filter((k) => !providedParamsKeys.includes(k))\n if (notProvidedKeys.length) {\n // throw new Error(`Missing params: not defined keys ${notProvidedKeys.map((k) => `\"${k}\"`).join(\", \")}.`)\n Object.assign(paramsInput, Object.fromEntries(notProvidedKeys.map((k) => [k, 'undefined'])))\n }\n\n // create url\n\n let url = this.pathDefinition as string\n // replace params\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n url = url.replace(/:([A-Za-z0-9_]+)/g, (_m, k) => encodeURIComponent(String(paramsInput?.[k] ?? '')))\n // search params\n const searchInputStringified = Object.fromEntries(Object.entries(searchInput).map(([k, v]) => [k, String(v)]))\n url = [url, new URLSearchParams(searchInputStringified).toString()].filter(Boolean).join('?')\n // dedupe slashes\n url = url.replace(/\\/{2,}/g, '/')\n // absolute\n url = absInput ? Route0._getAbsPath(this.baseUrl, url) : url\n\n return url\n }\n\n // has params\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n flat(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n flat(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: args[1] ?? false }\n }\n const paramsKeys = this.getParamsKeys()\n const paramsInput = paramsKeys.reduce<Record<string, string | number>>((acc, key) => {\n if (input[key] !== undefined) {\n acc[key] = input[key]\n }\n return acc\n }, {})\n const searchKeys = this.getSearchKeys()\n const searchInput = Object.keys(input)\n .filter((k) => {\n if (searchKeys.includes(k)) {\n return true\n }\n if (paramsKeys.includes(k)) {\n return false\n }\n return true\n })\n .reduce<Record<string, string | number>>((acc, key) => {\n acc[key] = input[key]\n return acc\n }, {})\n return { searchInput, paramsInput, absInput: args[1] ?? false }\n })()\n\n return this.get({ ...paramsInput, search: searchInput, abs: absInput } as never)\n }\n\n getParamsKeys(): string[] {\n return Object.keys(this.paramsDefinition || {})\n }\n getSearchKeys(): string[] {\n return Object.keys(this.searchDefinition || {})\n }\n getFlatKeys(): string[] {\n return [...this.getSearchKeys(), ...this.getParamsKeys()]\n }\n\n getDefinition(): string {\n return this.pathDefinition\n }\n\n clone(config?: RouteConfigInput): Route0<TDefinition> {\n return new Route0(this.definition, config)\n }\n\n getRegexString(): string {\n // Normalize the path definition (remove trailing slash except for root)\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n\n // Replace :param with placeholders, escape regex special chars, then restore capture groups\n const pattern = def\n .replace(/:([A-Za-z0-9_]+)/g, '___PARAM___') // temporarily replace params with placeholder\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') // escape regex special chars\n .replace(/___PARAM___/g, '([^/]+)') // replace placeholder with capture group\n\n return pattern\n }\n\n getRegex(): RegExp {\n return new RegExp(`^${this.getRegexString()}$`)\n }\n\n static getRegexString(routes: AnyRoute[] | AnyRoute): string {\n const routesArray = Array.isArray(routes) ? routes : [routes]\n return routesArray.map((route) => route.getRegexString()).join('|')\n }\n static getRegex(routes: AnyRoute[] | AnyRoute): RegExp {\n return new RegExp(`^(${Route0.getRegexString(routes)})$`)\n }\n\n static getLocation(href: `${string}://${string}`): UnknownLocation\n static getLocation(hrefRel: `/${string}`): UnknownLocation\n static getLocation(hrefOrHrefRel: string): UnknownLocation\n static getLocation(location: LocationAny): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation {\n if (typeof hrefOrHrefRelOrLocation !== 'string') {\n hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel\n }\n // Check if it's an absolute URL (starts with scheme://)\n const abs = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:\\/\\//.test(hrefOrHrefRelOrLocation)\n\n // Use dummy base only if relative\n const base = abs ? undefined : 'http://example.com'\n const url = new URL(hrefOrHrefRelOrLocation, base)\n\n // Extract search params\n const searchParams = Object.fromEntries(url.searchParams.entries())\n\n // Normalize pathname (remove trailing slash except for root)\n let pathname = url.pathname\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1)\n }\n\n // Common derived values\n const hrefRel = pathname + url.search + url.hash\n\n // Build the location object consistent with _GeneralLocation\n const location: UnknownLocation = {\n pathname,\n search: url.search,\n hash: url.hash,\n origin: abs ? url.origin : undefined,\n href: abs ? url.href : undefined,\n hrefRel,\n abs,\n\n // extra host-related fields (available even for relative with dummy base)\n host: abs ? url.host : undefined,\n hostname: abs ? url.hostname : undefined,\n port: abs ? url.port || undefined : undefined,\n\n // specific to UnknownLocation\n searchParams,\n params: undefined,\n route: undefined,\n exact: false,\n parent: false,\n children: false,\n }\n\n return location\n }\n\n getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>\n getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>\n getLocation(location: LocationAny): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition> {\n const location = Route0.getLocation(hrefOrHrefRelOrLocation) as never as KnownLocation<TDefinition>\n location.route = this.definition as definition<TDefinition>\n location.params = {}\n\n const escapeRegex = (s: string) => s.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n\n // Normalize pathname (no trailing slash except root)\n const pathname =\n location.pathname.length > 1 && location.pathname.endsWith('/')\n ? location.pathname.slice(0, -1)\n : location.pathname\n\n // Use getRegexString() to get the pattern\n const pattern = this.getRegexString()\n\n // Extract param names from the definition\n const paramNames: string[] = []\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n def.replace(/:([A-Za-z0-9_]+)/g, (_m: string, name: string) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n paramNames.push(String(name))\n return ''\n })\n\n const exactRe = new RegExp(`^${pattern}$`)\n const parentRe = new RegExp(`^${pattern}(?:/.*)?$`) // route matches the beginning of the URL (may have more)\n const exactMatch = pathname.match(exactRe)\n\n // Fill params only for exact match (keeps behavior predictable)\n if (exactMatch) {\n const values = exactMatch.slice(1)\n const params = Object.fromEntries(paramNames.map((n, i) => [n, decodeURIComponent(values[i] ?? '')]))\n location.params = params\n } else {\n location.params = {}\n }\n\n const exact = !!exactMatch\n const parent = !exact && parentRe.test(pathname)\n\n // \"children\": the URL is a prefix of the route definition (ignoring params' concrete values)\n // We check if the definition starts with the URL path boundary-wise.\n const children = !exact && new RegExp(`^${escapeRegex(pathname)}(?:/|$)`).test(def)\n\n return {\n ...location,\n exact,\n parent,\n children,\n } as KnownLocation<TDefinition>\n }\n\n isSame(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean {\n if ((!a && b) || (a && !b)) return false\n if (!a || !b) return true\n return Route0.create(a).isSame(Route0.create(b))\n }\n\n isChildren(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isParent(other: Route0<TDefinition>): boolean {\n return (\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isConflict(other: Route0<any>): boolean {\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Different lengths = no conflict (one is deeper than the other)\n if (thisParts.length !== otherParts.length) {\n return false\n }\n\n // Check if all segments could match\n for (let i = 0; i < thisParts.length; i++) {\n const thisPart = thisParts[i]\n const otherPart = otherParts[i]\n\n // Both params = always match\n if (thisPart.startsWith(':') && otherPart.startsWith(':')) {\n continue\n }\n\n // One is param = can match\n if (thisPart.startsWith(':') || otherPart.startsWith(':')) {\n continue\n }\n\n // Both static = must be same\n if (thisPart !== otherPart) {\n return false\n }\n }\n\n return true\n }\n\n isMoreSpecificThan(other: Route0<any>): boolean {\n // More specific = should come earlier when conflicted\n // Static segments beat param segments at the same position\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Compare segment by segment\n for (let i = 0; i < Math.min(thisParts.length, otherParts.length); i++) {\n const thisIsStatic = !thisParts[i].startsWith(':')\n const otherIsStatic = !otherParts[i].startsWith(':')\n\n if (thisIsStatic && !otherIsStatic) return true\n if (!thisIsStatic && otherIsStatic) return false\n }\n\n // All equal, use lexicographic\n return this.pathDefinition < other.pathDefinition\n }\n}\n\nexport class Routes<const T extends RoutesRecord = RoutesRecord> {\n readonly routes: RoutesRecordHydrated<T>\n readonly pathsOrdering: string[]\n readonly keysOrdering: string[]\n readonly ordered: CallabelRoute[]\n\n private constructor({\n routes,\n isHydrated = false,\n pathsOrdering,\n keysOrdering,\n ordered,\n }: {\n routes: RoutesRecordHydrated<T> | T\n isHydrated?: boolean\n pathsOrdering?: string[]\n keysOrdering?: string[]\n ordered?: CallabelRoute[]\n }) {\n this.routes = (\n isHydrated ? (routes as RoutesRecordHydrated<T>) : Routes._hydrate(routes)\n ) as RoutesRecordHydrated<T>\n if (!pathsOrdering || !keysOrdering || !ordered) {\n const ordering = Routes._makeOrdering(this.routes)\n this.pathsOrdering = ordering.pathsOrdering\n this.keysOrdering = ordering.keysOrdering\n this.ordered = this.keysOrdering.map((key) => this.routes[key])\n } else {\n this.pathsOrdering = pathsOrdering\n this.keysOrdering = keysOrdering\n this.ordered = ordered\n }\n }\n\n static create<const T extends RoutesRecord>(routes: T): RoutesPretty<T> {\n const instance = new Routes({ routes })\n return Routes._prettify(instance)\n }\n\n static _prettify<const T extends RoutesRecord>(instance: Routes<T>): RoutesPretty<T> {\n Object.setPrototypeOf(instance, Routes.prototype)\n Object.defineProperty(instance, Symbol.toStringTag, {\n value: 'Routes',\n })\n Object.assign(instance, {\n override: instance.override.bind(instance),\n })\n Object.assign(instance, instance.routes)\n return instance as unknown as RoutesPretty<T>\n }\n\n static _hydrate<const T extends RoutesRecord>(routes: T): RoutesRecordHydrated<T> {\n const result = {} as RoutesRecordHydrated<T>\n for (const key in routes) {\n if (Object.prototype.hasOwnProperty.call(routes, key)) {\n const value = routes[key]\n result[key] = (typeof value === 'string' ? Route0.create(value) : value) as CallabelRoute<T[typeof key]>\n }\n }\n return result\n }\n\n getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation\n getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation\n getLocation(location: LocationAny): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation {\n // Find the route that exactly matches the given location\n for (const route of this.ordered) {\n const loc = route.getLocation(hrefOrHrefRelOrLocation)\n if (loc.exact) {\n return loc\n }\n }\n // No exact match found, return UnknownLocation\n return Route0.getLocation(hrefOrHrefRelOrLocation)\n }\n\n static _makeOrdering(routes: RoutesRecord): { pathsOrdering: string[]; keysOrdering: string[] } {\n const hydrated = Routes._hydrate(routes)\n const entries = Object.entries(hydrated)\n\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n // Sort: shorter paths first, then by specificity, then alphabetically\n entries.sort(([_keyA, routeA], [_keyB, routeB]) => {\n const partsA = getParts(routeA.pathDefinition)\n const partsB = getParts(routeB.pathDefinition)\n\n // 1. Shorter paths first (by segment count)\n if (partsA.length !== partsB.length) {\n return partsA.length - partsB.length\n }\n\n // 2. Same length: check if they conflict\n if (routeA.isConflict(routeB)) {\n // Conflicting routes: more specific first\n if (routeA.isMoreSpecificThan(routeB)) return -1\n if (routeB.isMoreSpecificThan(routeA)) return 1\n }\n\n // 3. Same length, not conflicting or equal specificity: alphabetically\n return routeA.pathDefinition.localeCompare(routeB.pathDefinition)\n })\n\n const pathsOrdering = entries.map(([_key, route]) => route.definition)\n const keysOrdering = entries.map(([_key, route]) => _key)\n return { pathsOrdering, keysOrdering }\n }\n\n override(config: RouteConfigInput): RoutesPretty<T> {\n const newRoutes = {} as RoutesRecordHydrated<T>\n for (const key in this.routes) {\n if (Object.prototype.hasOwnProperty.call(this.routes, key)) {\n newRoutes[key] = this.routes[key].clone(config) as CallabelRoute<T[typeof key]>\n }\n }\n const instance = new Routes({\n routes: newRoutes,\n isHydrated: true,\n pathsOrdering: this.pathsOrdering,\n keysOrdering: this.keysOrdering,\n ordered: this.keysOrdering.map((key) => newRoutes[key]),\n })\n return Routes._prettify(instance)\n }\n}\n\n// main\n\nexport type AnyRoute<T extends Route0<string> | string = string> = T extends string ? Route0<T> : T\nexport type CallabelRoute<T extends Route0<string> | string = string> = AnyRoute<T> & AnyRoute<T>['get']\nexport type AnyRouteOrDefinition<T extends string> = AnyRoute<T> | T\nexport type RouteConfigInput = {\n baseUrl?: string\n}\n\n// collection\n\nexport type RoutesRecord = Record<string, AnyRoute | string>\nexport type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = RoutesRecord> = {\n [K in keyof TRoutesRecord]: CallabelRoute<TRoutesRecord[K]>\n}\nexport type RoutesPretty<TRoutesRecord extends RoutesRecord = RoutesRecord> = RoutesRecordHydrated<TRoutesRecord> &\n Routes<TRoutesRecord>\nexport type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty\n ? keyof TRoutes['routes']\n : TRoutes extends RoutesRecord\n ? keyof TRoutes\n : never\nexport type ExtractRoute<\n TRoutes extends RoutesPretty | RoutesRecord,\n TKey extends keyof ExtractRoutesKeys<TRoutes>,\n> = TKey extends keyof TRoutes ? TRoutes[TKey] : never\n\n// public utils\n\nexport type definition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['definition']\n : T extends string\n ? T\n : never\nexport type PathDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['pathDefinition']\n : T extends string\n ? _PathDefinition<T>\n : never\nexport type ParamsDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['paramsDefinition']\n : T extends string\n ? _ParamsDefinition<T>\n : undefined\nexport type SearchDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['searchDefinition']\n : T extends string\n ? _SearchDefinition<T>\n : undefined\n\nexport type Extended<T extends AnyRoute | string | undefined, TSuffixDefinition extends string> = T extends AnyRoute\n ? Route0<PathExtended<T['definition'], TSuffixDefinition>>\n : T extends string\n ? Route0<PathExtended<T, TSuffixDefinition>>\n : T extends undefined\n ? Route0<TSuffixDefinition>\n : never\n\nexport type IsParent<T extends AnyRoute | string, TParent extends AnyRoute | string> = _IsParent<\n PathDefinition<T>,\n PathDefinition<TParent>\n>\nexport type IsChildren<T extends AnyRoute | string, TChildren extends AnyRoute | string> = _IsChildren<\n PathDefinition<T>,\n PathDefinition<TChildren>\n>\nexport type IsSame<T extends AnyRoute | string, TExact extends AnyRoute | string> = _IsSame<\n PathDefinition<T>,\n PathDefinition<TExact>\n>\nexport type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | string> = _IsSameParams<\n ParamsDefinition<T1>,\n ParamsDefinition<T2>\n>\n\nexport type HasParams<T extends AnyRoute | string> =\n ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false\nexport type HasSearch<T extends AnyRoute | string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<definition<T>>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? false\n : true\n : false\n : false\n\nexport type ParamsOutput<T extends AnyRoute | string> = {\n [K in keyof ParamsDefinition<T>]: string\n}\nexport type SearchOutput<T extends AnyRoute | string = string> = Partial<\n {\n [K in keyof SearchDefinition<T>]?: string\n } & Record<string, string | undefined>\n>\nexport type StrictSearchOutput<T extends AnyRoute | string> = Partial<{\n [K in keyof SearchDefinition<T>]?: string | undefined\n}>\nexport type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>\nexport type SearchInput<T extends AnyRoute | string = string> = _SearchInput<definition<T>>\nexport type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<definition<T>>\n\n// location\n\nexport type LocationParams<TDefinition extends string> = {\n [K in keyof _ParamsDefinition<TDefinition>]: string\n}\nexport type LocationSearch<TDefinition extends string = string> = {\n [K in keyof _SearchDefinition<TDefinition>]: string | undefined\n} & Record<string, string | undefined>\n\nexport type _GeneralLocation = {\n pathname: string\n search: string\n hash: string\n origin?: string\n href?: string\n hrefRel: string\n abs: boolean\n port?: string\n host?: string\n hostname?: string\n}\nexport type UnknownLocation = _GeneralLocation & {\n params: undefined\n searchParams: SearchOutput\n route: undefined\n exact: false\n parent: false\n children: false\n}\nexport type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Record<never, never>\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: false\n parent: false\n children: false\n}\nexport type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: true\n parent: false\n children: false\n}\nexport type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Partial<ParamsOutput<TRoute>> // in fact maybe there will be whole params object, but does not matter now\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: false\n parent: true\n children: false\n}\nexport type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: definition<TRoute>\n exact: false\n parent: false\n children: true\n}\nexport type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string> =\n | UnmatchedLocation<TRoute>\n | ExactLocation<TRoute>\n | ParentLocation<TRoute>\n | ChildrenLocation<TRoute>\nexport type LocationAny<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>\n\n// internal utils\n\nexport type _PathDefinition<T extends string> = T extends string ? TrimSearchTailDefinition<T> : never\nexport type _ParamsDefinition<TDefinition extends string> =\n ExtractPathParams<PathDefinition<TDefinition>> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\nexport type _SearchDefinition<TDefinition extends string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<TDefinition>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\n : undefined\n\nexport type _ParamsInput<TDefinition extends string> =\n _ParamsDefinition<TDefinition> extends undefined\n ? Record<never, never>\n : {\n [K in keyof _ParamsDefinition<TDefinition>]: string | number\n }\nexport type _SearchInput<TDefinition extends string> =\n _SearchDefinition<TDefinition> extends undefined\n ? Record<string, string | number>\n : Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n }> &\n Record<string, string | number>\nexport type _StrictSearchInput<TDefinition extends string> = Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n}>\n\nexport type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S\nexport type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : ''\nexport type SearchTailDefinitionWithFirstAmp<S extends string> = S extends `${string}&${infer T}` ? `&${T}` : ''\nexport type AmpSplit<S extends string> = S extends `${infer A}&${infer B}` ? A | AmpSplit<B> : S\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type NonEmpty<T> = [T] extends ['' | never] ? never : T\nexport type ExtractPathParams<S extends string> = S extends `${string}:${infer After}`\n ? After extends `${infer Name}/${infer Rest}`\n ? Name | ExtractPathParams<`/${Rest}`>\n : After\n : never\nexport type ReplacePathParams<S extends string> = S extends `${infer Head}:${infer Tail}`\n ? // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Tail extends `${infer _Param}/${infer Rest}`\n ? ReplacePathParams<`${Head}${string}/${Rest}`>\n : `${Head}${string}`\n : S\nexport type DedupeSlashes<S extends string> = S extends `${infer A}//${infer B}` ? DedupeSlashes<`${A}/${B}`> : S\nexport type EmptyRecord = Record<never, never>\nexport type JoinPath<Parent extends string, Suffix extends string> = DedupeSlashes<\n PathDefinition<Parent> extends infer A extends string\n ? PathDefinition<Suffix> extends infer B extends string\n ? A extends ''\n ? B extends ''\n ? ''\n : B extends `/${string}`\n ? B\n : `/${B}`\n : B extends ''\n ? A\n : A extends `${string}/`\n ? `${A}${B}`\n : B extends `/${string}`\n ? `${A}${B}`\n : `${A}/${B}`\n : never\n : never\n>\n\nexport type OnlyIfNoParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? Yes : No\nexport type OnlyIfHasParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? No : Yes\n\nexport type PathOnlyRouteValue<TDefinition extends string> = `${ReplacePathParams<PathDefinition<TDefinition>>}`\nexport type WithSearchRouteValue<TDefinition extends string> =\n `${ReplacePathParams<PathDefinition<TDefinition>>}?${string}`\nexport type AbsolutePathOnlyRouteValue<TDefinition extends string> =\n PathOnlyRouteValue<TDefinition> extends '/' ? string : `${string}${PathOnlyRouteValue<TDefinition>}`\nexport type AbsoluteWithSearchRouteValue<TDefinition extends string> = `${string}${WithSearchRouteValue<TDefinition>}`\n\nexport type PathExtended<\n TSourcedefinitionDefinition extends string,\n TSuffixdefinitionDefinition extends string,\n> = `${JoinPath<TSourcedefinitionDefinition, TSuffixdefinitionDefinition>}${SearchTailDefinitionWithFirstAmp<TSuffixdefinitionDefinition>}`\n\nexport type WithParamsInput<\n TDefinition extends string,\n T extends\n | {\n search?: _SearchInput<any>\n abs?: boolean\n }\n | undefined = undefined,\n> = _ParamsInput<TDefinition> & (T extends undefined ? Record<never, never> : T)\n\nexport type _IsSameParams<T1 extends object | undefined, T2 extends object | undefined> = T1 extends undefined\n ? T2 extends undefined\n ? true\n : false\n : T2 extends undefined\n ? false\n : T1 extends T2\n ? T2 extends T1\n ? true\n : false\n : false\n\nexport type _IsParent<T extends string, TParent extends string> = T extends TParent\n ? false\n : T extends `${TParent}${string}`\n ? true\n : false\nexport type _IsChildren<T extends string, TChildren extends string> = TChildren extends T\n ? false\n : TChildren extends `${T}${string}`\n ? true\n : false\nexport type _IsSame<T extends string, TExact extends string> = T extends TExact\n ? TExact extends T\n ? true\n : false\n : false\n"],"mappings":"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","names":["paramsInput","searchInput"]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// TODO: asterisk\n// TODO: optional params\n// TODO: required search\n\n// TODO: .extension('.json') to not add additional / but just add some extension\n// TODO: search input can be boolean, or even object with qs\n// TODO: Роут0 три пусть три тоже сам генерится вероятно\n// TODO: Роут0 три мод, тогда там все ноуты кончаются на .селф\n// TODO: use splats in param definition \"*\"\n// TODO: ? check extend for search only .extend('&x&z')\n// TODO: .create(route, {useSearch, useParams})\n// TODO: Из пас экзакт, из пасвизквери экзает, из чилдрен, из парент, из экзактОр\n// TODO: isEqual, isChildren, isParent\n// TODO: extractParams, extractSearch\n// TODO: getPathDefinition respecting definitionParamPrefix, definitionSearchPrefix\n// TODO: prepend\n// TODO: Route0.createTree({base:{self: x, children: ...})\n// TODO: overrideTree\n// TODO: .create(route, {baseUrl, useLocation})\n// TODO: ? optional path params as @\n// TODO: prependMany, extendMany, overrideMany, with types\n// TODO: optional route params /x/:id?\n\nexport class Route0<TDefinition extends string> {\n readonly definition: TDefinition\n readonly pathDefinition: _PathDefinition<TDefinition>\n readonly paramsDefinition: _ParamsDefinition<TDefinition>\n readonly searchDefinition: _SearchDefinition<TDefinition>\n baseUrl: string\n\n private constructor(definition: TDefinition, config: RouteConfigInput = {}) {\n this.definition = definition\n this.pathDefinition = Route0._getPathDefinitionBydefinition(definition)\n this.paramsDefinition = Route0._getParamsDefinitionBydefinition(definition)\n this.searchDefinition = Route0._getSearchDefinitionBydefinition(definition)\n\n const { baseUrl } = config\n if (baseUrl && typeof baseUrl === 'string' && baseUrl.length) {\n this.baseUrl = baseUrl\n } else {\n const g = globalThis as unknown as { location?: { origin?: string } }\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (typeof g?.location?.origin === 'string' && g.location.origin.length > 0) {\n this.baseUrl = g.location.origin\n } else {\n this.baseUrl = 'https://example.com'\n }\n }\n }\n\n static create<TDefinition extends string>(\n definition: TDefinition | AnyRoute<TDefinition>,\n config?: RouteConfigInput,\n ): CallabelRoute<TDefinition> {\n if (typeof definition === 'function') {\n return definition\n }\n const original = typeof definition === 'object' ? definition : new Route0<TDefinition>(definition, config)\n const callable = original.get.bind(original)\n Object.setPrototypeOf(callable, original)\n Object.defineProperty(callable, Symbol.toStringTag, {\n value: original.definition,\n })\n return callable as never\n }\n\n private static _splitPathDefinitionAndSearchTailDefinition(definition: string) {\n const i = definition.indexOf('&')\n if (i === -1) return { pathDefinition: definition, searchTailDefinition: '' }\n return {\n pathDefinition: definition.slice(0, i),\n searchTailDefinition: definition.slice(i),\n }\n }\n\n private static _getAbsPath(baseUrl: string, pathWithSearch: string) {\n return new URL(pathWithSearch, baseUrl).toString().replace(/\\/$/, '')\n }\n\n private static _getPathDefinitionBydefinition<TDefinition extends string>(definition: TDefinition) {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n return pathDefinition as _PathDefinition<TDefinition>\n }\n\n private static _getParamsDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _ParamsDefinition<TDefinition> {\n const { pathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n const matches = Array.from(pathDefinition.matchAll(/:([A-Za-z0-9_]+)/g))\n const paramsDefinition = Object.fromEntries(matches.map((m) => [m[1], true]))\n const keysCount = Object.keys(paramsDefinition).length\n if (keysCount === 0) {\n return undefined as _ParamsDefinition<TDefinition>\n }\n return paramsDefinition as _ParamsDefinition<TDefinition>\n }\n\n private static _getSearchDefinitionBydefinition<TDefinition extends string>(\n definition: TDefinition,\n ): _SearchDefinition<TDefinition> {\n const { searchTailDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(definition)\n if (!searchTailDefinition) {\n return undefined as _SearchDefinition<TDefinition>\n }\n const keys = searchTailDefinition.split('&').filter(Boolean)\n const searchDefinition = Object.fromEntries(keys.map((k) => [k, true]))\n const keysCount = Object.keys(searchDefinition).length\n if (keysCount === 0) {\n return undefined as _SearchDefinition<TDefinition>\n }\n return searchDefinition as _SearchDefinition<TDefinition>\n }\n\n extend<TSuffixDefinition extends string>(\n suffixDefinition: TSuffixDefinition,\n ): CallabelRoute<PathExtended<TDefinition, TSuffixDefinition>> {\n const { pathDefinition: parentPathDefinition } = Route0._splitPathDefinitionAndSearchTailDefinition(this.definition)\n const { pathDefinition: suffixPathDefinition, searchTailDefinition: suffixSearchTailDefinition } =\n Route0._splitPathDefinitionAndSearchTailDefinition(suffixDefinition)\n const pathDefinition = `${parentPathDefinition}/${suffixPathDefinition}`.replace(/\\/{2,}/g, '/')\n const definition = `${pathDefinition}${suffixSearchTailDefinition}` as PathExtended<TDefinition, TSuffixDefinition>\n return Route0.create<PathExtended<TDefinition, TSuffixDefinition>>(definition, { baseUrl: this.baseUrl })\n }\n\n // has params\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs?: false }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search?: undefined; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfHasParams<\n _ParamsDefinition<TDefinition>,\n WithParamsInput<TDefinition, { search: _SearchInput<TDefinition>; abs: true }>\n >,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n get(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs?: false }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search?: undefined; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n get(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, { search: _SearchInput<TDefinition>; abs: true }>,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n get(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const { search, abs, ...params } = input\n return { searchInput: search || {}, paramsInput: params, absInput: abs ?? false }\n })()\n\n // validate params\n const neededParamsKeys = this.paramsDefinition ? Object.keys(this.paramsDefinition) : []\n const providedParamsKeys = Object.keys(paramsInput)\n const notProvidedKeys = neededParamsKeys.filter((k) => !providedParamsKeys.includes(k))\n if (notProvidedKeys.length) {\n // throw new Error(`Missing params: not defined keys ${notProvidedKeys.map((k) => `\"${k}\"`).join(\", \")}.`)\n Object.assign(paramsInput, Object.fromEntries(notProvidedKeys.map((k) => [k, 'undefined'])))\n }\n\n // create url\n\n let url = this.pathDefinition as string\n // replace params\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n url = url.replace(/:([A-Za-z0-9_]+)/g, (_m, k) => encodeURIComponent(String(paramsInput?.[k] ?? '')))\n // search params\n const searchInputStringified = Object.fromEntries(Object.entries(searchInput).map(([k, v]) => [k, String(v)]))\n url = [url, new URLSearchParams(searchInputStringified).toString()].filter(Boolean).join('?')\n // dedupe slashes\n url = url.replace(/\\/{2,}/g, '/')\n // absolute\n url = absInput ? Route0._getAbsPath(this.baseUrl, url) : url\n\n return url\n }\n\n // has params\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs?: false,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfHasParams<_ParamsDefinition<TDefinition>, WithParamsInput<TDefinition, _SearchInput<TDefinition>>>,\n abs: true,\n ): OnlyIfHasParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // no params\n flat(...args: OnlyIfNoParams<_ParamsDefinition<TDefinition>, [], [never]>): PathOnlyRouteValue<TDefinition>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, PathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs?: false,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, WithSearchRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, Record<never, never>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsolutePathOnlyRouteValue<TDefinition>>\n flat(\n input: OnlyIfNoParams<_ParamsDefinition<TDefinition>, _SearchInput<TDefinition>>,\n abs: true,\n ): OnlyIfNoParams<_ParamsDefinition<TDefinition>, AbsoluteWithSearchRouteValue<TDefinition>>\n\n // implementation\n flat(...args: any[]): string {\n const { searchInput, paramsInput, absInput } = ((): {\n searchInput: Record<string, string | number>\n paramsInput: Record<string, string | number>\n absInput: boolean\n } => {\n if (args.length === 0) {\n return { searchInput: {}, paramsInput: {}, absInput: false }\n }\n const input = args[0]\n if (typeof input !== 'object' || input === null) {\n // throw new Error(\"Invalid get route input: expected object\")\n return { searchInput: {}, paramsInput: {}, absInput: args[1] ?? false }\n }\n const paramsKeys = this.getParamsKeys()\n const paramsInput = paramsKeys.reduce<Record<string, string | number>>((acc, key) => {\n if (input[key] !== undefined) {\n acc[key] = input[key]\n }\n return acc\n }, {})\n const searchKeys = this.getSearchKeys()\n const searchInput = Object.keys(input)\n .filter((k) => {\n if (searchKeys.includes(k)) {\n return true\n }\n if (paramsKeys.includes(k)) {\n return false\n }\n return true\n })\n .reduce<Record<string, string | number>>((acc, key) => {\n acc[key] = input[key]\n return acc\n }, {})\n return { searchInput, paramsInput, absInput: args[1] ?? false }\n })()\n\n return this.get({ ...paramsInput, search: searchInput, abs: absInput } as never)\n }\n\n getParamsKeys(): string[] {\n return Object.keys(this.paramsDefinition || {})\n }\n getSearchKeys(): string[] {\n return Object.keys(this.searchDefinition || {})\n }\n getFlatKeys(): string[] {\n return [...this.getSearchKeys(), ...this.getParamsKeys()]\n }\n\n getDefinition(): string {\n return this.pathDefinition\n }\n\n clone(config?: RouteConfigInput): Route0<TDefinition> {\n return new Route0(this.definition, config)\n }\n\n getRegexString(): string {\n // Normalize the path definition (remove trailing slash except for root)\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n\n // Replace :param with placeholders, escape regex special chars, then restore capture groups\n const pattern = def\n .replace(/:([A-Za-z0-9_]+)/g, '___PARAM___') // temporarily replace params with placeholder\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') // escape regex special chars\n .replace(/___PARAM___/g, '([^/]+)') // replace placeholder with capture group\n\n return pattern\n }\n\n getRegex(): RegExp {\n return new RegExp(`^${this.getRegexString()}$`)\n }\n\n static getRegexString(routes: AnyRoute[] | AnyRoute): string {\n const routesArray = Array.isArray(routes) ? routes : [routes]\n return routesArray.map((route) => route.getRegexString()).join('|')\n }\n static getRegex(routes: AnyRoute[] | AnyRoute): RegExp {\n return new RegExp(`^(${Route0.getRegexString(routes)})$`)\n }\n\n static getLocation(href: `${string}://${string}`): UnknownLocation\n static getLocation(hrefRel: `/${string}`): UnknownLocation\n static getLocation(hrefOrHrefRel: string): UnknownLocation\n static getLocation(location: AnyLocation): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation\n static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation {\n if (typeof hrefOrHrefRelOrLocation !== 'string') {\n hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel\n }\n // Check if it's an absolute URL (starts with scheme://)\n const abs = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:\\/\\//.test(hrefOrHrefRelOrLocation)\n\n // Use dummy base only if relative\n const base = abs ? undefined : 'http://example.com'\n const url = new URL(hrefOrHrefRelOrLocation, base)\n\n // Extract search params\n const searchParams = Object.fromEntries(url.searchParams.entries())\n\n // Normalize pathname (remove trailing slash except for root)\n let pathname = url.pathname\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1)\n }\n\n // Common derived values\n const hrefRel = pathname + url.search + url.hash\n\n // Build the location object consistent with _GeneralLocation\n const location: UnknownLocation = {\n pathname,\n search: url.search,\n hash: url.hash,\n origin: abs ? url.origin : undefined,\n href: abs ? url.href : undefined,\n hrefRel,\n abs,\n\n // extra host-related fields (available even for relative with dummy base)\n host: abs ? url.host : undefined,\n hostname: abs ? url.hostname : undefined,\n port: abs ? url.port || undefined : undefined,\n\n // specific to UnknownLocation\n searchParams,\n params: undefined,\n route: undefined,\n exact: false,\n parent: false,\n children: false,\n }\n\n return location\n }\n\n getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>\n getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>\n getLocation(location: AnyLocation): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition>\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition> {\n const location = Route0.getLocation(hrefOrHrefRelOrLocation) as never as KnownLocation<TDefinition>\n location.route = this.definition as Definition<TDefinition>\n location.params = {}\n\n const escapeRegex = (s: string) => s.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n\n // Normalize pathname (no trailing slash except root)\n const pathname =\n location.pathname.length > 1 && location.pathname.endsWith('/')\n ? location.pathname.slice(0, -1)\n : location.pathname\n\n // Use getRegexString() to get the pattern\n const pattern = this.getRegexString()\n\n // Extract param names from the definition\n const paramNames: string[] = []\n const def =\n this.pathDefinition.length > 1 && this.pathDefinition.endsWith('/')\n ? this.pathDefinition.slice(0, -1)\n : this.pathDefinition\n def.replace(/:([A-Za-z0-9_]+)/g, (_m: string, name: string) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n paramNames.push(String(name))\n return ''\n })\n\n const exactRe = new RegExp(`^${pattern}$`)\n const parentRe = new RegExp(`^${pattern}(?:/.*)?$`) // route matches the beginning of the URL (may have more)\n const exactMatch = pathname.match(exactRe)\n\n // Fill params only for exact match (keeps behavior predictable)\n if (exactMatch) {\n const values = exactMatch.slice(1)\n const params = Object.fromEntries(paramNames.map((n, i) => [n, decodeURIComponent(values[i] ?? '')]))\n location.params = params\n } else {\n location.params = {}\n }\n\n const exact = !!exactMatch\n const parent = !exact && parentRe.test(pathname)\n\n // \"children\": the URL is a prefix of the route definition (ignoring params' concrete values)\n // We check if the definition starts with the URL path boundary-wise.\n const children = !exact && new RegExp(`^${escapeRegex(pathname)}(?:/|$)`).test(def)\n\n return {\n ...location,\n exact,\n parent,\n children,\n } as KnownLocation<TDefinition>\n }\n\n isSame(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean {\n if ((!a && b) || (a && !b)) return false\n if (!a || !b) return true\n return Route0.create(a).isSame(Route0.create(b))\n }\n\n isChildren(other: Route0<TDefinition>): boolean {\n return (\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isParent(other: Route0<TDefinition>): boolean {\n return (\n other.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__') ===\n this.pathDefinition.replace(/:([A-Za-z0-9_]+)/g, '__PARAM__')\n )\n }\n\n isConflict(other: Route0<any>): boolean {\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Different lengths = no conflict (one is deeper than the other)\n if (thisParts.length !== otherParts.length) {\n return false\n }\n\n // Check if all segments could match\n for (let i = 0; i < thisParts.length; i++) {\n const thisPart = thisParts[i]\n const otherPart = otherParts[i]\n\n // Both params = always match\n if (thisPart.startsWith(':') && otherPart.startsWith(':')) {\n continue\n }\n\n // One is param = can match\n if (thisPart.startsWith(':') || otherPart.startsWith(':')) {\n continue\n }\n\n // Both static = must be same\n if (thisPart !== otherPart) {\n return false\n }\n }\n\n return true\n }\n\n isMoreSpecificThan(other: Route0<any>): boolean {\n // More specific = should come earlier when conflicted\n // Static segments beat param segments at the same position\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n const thisParts = getParts(this.pathDefinition)\n const otherParts = getParts(other.pathDefinition)\n\n // Compare segment by segment\n for (let i = 0; i < Math.min(thisParts.length, otherParts.length); i++) {\n const thisIsStatic = !thisParts[i].startsWith(':')\n const otherIsStatic = !otherParts[i].startsWith(':')\n\n if (thisIsStatic && !otherIsStatic) return true\n if (!thisIsStatic && otherIsStatic) return false\n }\n\n // All equal, use lexicographic\n return this.pathDefinition < other.pathDefinition\n }\n}\n\nexport class Routes<const T extends RoutesRecord = RoutesRecord> {\n readonly routes: RoutesRecordHydrated<T>\n readonly pathsOrdering: string[]\n readonly keysOrdering: string[]\n readonly ordered: CallabelRoute[]\n\n private constructor({\n routes,\n isHydrated = false,\n pathsOrdering,\n keysOrdering,\n ordered,\n }: {\n routes: RoutesRecordHydrated<T> | T\n isHydrated?: boolean\n pathsOrdering?: string[]\n keysOrdering?: string[]\n ordered?: CallabelRoute[]\n }) {\n this.routes = (\n isHydrated ? (routes as RoutesRecordHydrated<T>) : Routes._hydrate(routes)\n ) as RoutesRecordHydrated<T>\n if (!pathsOrdering || !keysOrdering || !ordered) {\n const ordering = Routes._makeOrdering(this.routes)\n this.pathsOrdering = ordering.pathsOrdering\n this.keysOrdering = ordering.keysOrdering\n this.ordered = this.keysOrdering.map((key) => this.routes[key])\n } else {\n this.pathsOrdering = pathsOrdering\n this.keysOrdering = keysOrdering\n this.ordered = ordered\n }\n }\n\n static create<const T extends RoutesRecord>(routes: T): RoutesPretty<T> {\n const instance = new Routes({ routes })\n return Routes._prettify(instance)\n }\n\n static _prettify<const T extends RoutesRecord>(instance: Routes<T>): RoutesPretty<T> {\n Object.setPrototypeOf(instance, Routes.prototype)\n Object.defineProperty(instance, Symbol.toStringTag, {\n value: 'Routes',\n })\n Object.assign(instance, {\n override: instance.override.bind(instance),\n })\n Object.assign(instance, instance.routes)\n return instance as unknown as RoutesPretty<T>\n }\n\n static _hydrate<const T extends RoutesRecord>(routes: T): RoutesRecordHydrated<T> {\n const result = {} as RoutesRecordHydrated<T>\n for (const key in routes) {\n if (Object.prototype.hasOwnProperty.call(routes, key)) {\n const value = routes[key]\n result[key] = (typeof value === 'string' ? Route0.create(value) : value) as CallabelRoute<T[typeof key]>\n }\n }\n return result\n }\n\n getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation\n getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation\n getLocation(location: AnyLocation): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation\n getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation {\n // Find the route that exactly matches the given location\n for (const route of this.ordered) {\n const loc = route.getLocation(hrefOrHrefRelOrLocation)\n if (loc.exact) {\n return loc\n }\n }\n // No exact match found, return UnknownLocation\n return Route0.getLocation(hrefOrHrefRelOrLocation)\n }\n\n static _makeOrdering(routes: RoutesRecord): { pathsOrdering: string[]; keysOrdering: string[] } {\n const hydrated = Routes._hydrate(routes)\n const entries = Object.entries(hydrated)\n\n const getParts = (path: string) => {\n if (path === '/') return ['/']\n return path.split('/').filter(Boolean)\n }\n\n // Sort: shorter paths first, then by specificity, then alphabetically\n entries.sort(([_keyA, routeA], [_keyB, routeB]) => {\n const partsA = getParts(routeA.pathDefinition)\n const partsB = getParts(routeB.pathDefinition)\n\n // 1. Shorter paths first (by segment count)\n if (partsA.length !== partsB.length) {\n return partsA.length - partsB.length\n }\n\n // 2. Same length: check if they conflict\n if (routeA.isConflict(routeB)) {\n // Conflicting routes: more specific first\n if (routeA.isMoreSpecificThan(routeB)) return -1\n if (routeB.isMoreSpecificThan(routeA)) return 1\n }\n\n // 3. Same length, not conflicting or equal specificity: alphabetically\n return routeA.pathDefinition.localeCompare(routeB.pathDefinition)\n })\n\n const pathsOrdering = entries.map(([_key, route]) => route.definition)\n const keysOrdering = entries.map(([_key, route]) => _key)\n return { pathsOrdering, keysOrdering }\n }\n\n override(config: RouteConfigInput): RoutesPretty<T> {\n const newRoutes = {} as RoutesRecordHydrated<T>\n for (const key in this.routes) {\n if (Object.prototype.hasOwnProperty.call(this.routes, key)) {\n newRoutes[key] = this.routes[key].clone(config) as CallabelRoute<T[typeof key]>\n }\n }\n const instance = new Routes({\n routes: newRoutes,\n isHydrated: true,\n pathsOrdering: this.pathsOrdering,\n keysOrdering: this.keysOrdering,\n ordered: this.keysOrdering.map((key) => newRoutes[key]),\n })\n return Routes._prettify(instance)\n }\n}\n\n// main\n\nexport type AnyRoute<T extends Route0<string> | string = string> = T extends string ? Route0<T> : T\nexport type CallabelRoute<T extends Route0<string> | string = string> = AnyRoute<T> & AnyRoute<T>['get']\nexport type AnyRouteOrDefinition<T extends string> = AnyRoute<T> | T\nexport type RouteConfigInput = {\n baseUrl?: string\n}\n\n// collection\n\nexport type RoutesRecord = Record<string, AnyRoute | string>\nexport type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = RoutesRecord> = {\n [K in keyof TRoutesRecord]: CallabelRoute<TRoutesRecord[K]>\n}\nexport type RoutesPretty<TRoutesRecord extends RoutesRecord = RoutesRecord> = RoutesRecordHydrated<TRoutesRecord> &\n Routes<TRoutesRecord>\nexport type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty\n ? keyof TRoutes['routes']\n : TRoutes extends RoutesRecord\n ? keyof TRoutes\n : never\nexport type ExtractRoute<\n TRoutes extends RoutesPretty | RoutesRecord,\n TKey extends keyof ExtractRoutesKeys<TRoutes>,\n> = TKey extends keyof TRoutes ? TRoutes[TKey] : never\n\n// public utils\n\nexport type Definition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['definition']\n : T extends string\n ? T\n : never\nexport type PathDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['pathDefinition']\n : T extends string\n ? _PathDefinition<T>\n : never\nexport type ParamsDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['paramsDefinition']\n : T extends string\n ? _ParamsDefinition<T>\n : undefined\nexport type SearchDefinition<T extends AnyRoute | string> = T extends AnyRoute\n ? T['searchDefinition']\n : T extends string\n ? _SearchDefinition<T>\n : undefined\n\nexport type Extended<T extends AnyRoute | string | undefined, TSuffixDefinition extends string> = T extends AnyRoute\n ? Route0<PathExtended<T['definition'], TSuffixDefinition>>\n : T extends string\n ? Route0<PathExtended<T, TSuffixDefinition>>\n : T extends undefined\n ? Route0<TSuffixDefinition>\n : never\n\nexport type IsParent<T extends AnyRoute | string, TParent extends AnyRoute | string> = _IsParent<\n PathDefinition<T>,\n PathDefinition<TParent>\n>\nexport type IsChildren<T extends AnyRoute | string, TChildren extends AnyRoute | string> = _IsChildren<\n PathDefinition<T>,\n PathDefinition<TChildren>\n>\nexport type IsSame<T extends AnyRoute | string, TExact extends AnyRoute | string> = _IsSame<\n PathDefinition<T>,\n PathDefinition<TExact>\n>\nexport type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | string> = _IsSameParams<\n ParamsDefinition<T1>,\n ParamsDefinition<T2>\n>\n\nexport type HasParams<T extends AnyRoute | string> =\n ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false\nexport type HasSearch<T extends AnyRoute | string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<Definition<T>>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? false\n : true\n : false\n : false\n\nexport type ParamsOutput<T extends AnyRoute | string> = {\n [K in keyof ParamsDefinition<T>]: string\n}\nexport type SearchOutput<T extends AnyRoute | string = string> = Partial<\n {\n [K in keyof SearchDefinition<T>]?: string\n } & Record<string, string | undefined>\n>\nexport type StrictSearchOutput<T extends AnyRoute | string> = Partial<{\n [K in keyof SearchDefinition<T>]?: string | undefined\n}>\nexport type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>\nexport type SearchInput<T extends AnyRoute | string = string> = _SearchInput<Definition<T>>\nexport type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<Definition<T>>\nexport type FlatInput<T extends AnyRoute | string> = _FlatInput<Definition<T>>\nexport type StrictFlatInput<T extends AnyRoute | string> = _StrictFlatInput<Definition<T>>\nexport type CanInputBeEmpty<T extends AnyRoute | string> = HasParams<Definition<T>> extends true ? false : true\n\n// location\n\nexport type LocationParams<TDefinition extends string> = {\n [K in keyof _ParamsDefinition<TDefinition>]: string\n}\nexport type LocationSearch<TDefinition extends string = string> = {\n [K in keyof _SearchDefinition<TDefinition>]: string | undefined\n} & Record<string, string | undefined>\n\nexport type _GeneralLocation = {\n pathname: string\n search: string\n hash: string\n origin?: string\n href?: string\n hrefRel: string\n abs: boolean\n port?: string\n host?: string\n hostname?: string\n}\nexport type UnknownLocation = _GeneralLocation & {\n params: undefined\n searchParams: SearchOutput\n route: undefined\n exact: false\n parent: false\n children: false\n}\nexport type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Record<never, never>\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: false\n parent: false\n children: false\n}\nexport type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: true\n parent: false\n children: false\n}\nexport type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: Partial<ParamsOutput<TRoute>> // in fact maybe there will be whole params object, but does not matter now\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: false\n parent: true\n children: false\n}\nexport type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {\n params: ParamsOutput<TRoute>\n searchParams: SearchOutput<TRoute>\n route: Definition<TRoute>\n exact: false\n parent: false\n children: true\n}\nexport type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string> =\n | UnmatchedLocation<TRoute>\n | ExactLocation<TRoute>\n | ParentLocation<TRoute>\n | ChildrenLocation<TRoute>\nexport type AnyLocation<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>\n\n// internal utils\n\nexport type _PathDefinition<T extends string> = T extends string ? TrimSearchTailDefinition<T> : never\nexport type _ParamsDefinition<TDefinition extends string> =\n ExtractPathParams<PathDefinition<TDefinition>> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\nexport type _SearchDefinition<TDefinition extends string> =\n NonEmpty<SearchTailDefinitionWithoutFirstAmp<TDefinition>> extends infer Tail extends string\n ? AmpSplit<Tail> extends infer U\n ? [U] extends [never]\n ? undefined\n : { [K in Extract<U, string>]: true }\n : undefined\n : undefined\n\nexport type _ParamsInput<TDefinition extends string> =\n _ParamsDefinition<TDefinition> extends undefined\n ? Record<never, never>\n : {\n [K in keyof _ParamsDefinition<TDefinition>]: string | number\n }\nexport type _SearchInput<TDefinition extends string> =\n _SearchDefinition<TDefinition> extends undefined\n ? Record<string, string | number>\n : Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n }> &\n Record<string, string | number>\nexport type _StrictSearchInput<TDefinition extends string> = Partial<{\n [K in keyof _SearchDefinition<TDefinition>]: string | number\n}>\nexport type _FlatInput<TDefinition extends string> =\n HasParams<TDefinition> extends true\n ? _ParamsInput<TDefinition> & _SearchInput<TDefinition>\n : _SearchInput<TDefinition>\nexport type _StrictFlatInput<TDefinition extends string> =\n HasParams<TDefinition> extends true\n ? HasSearch<TDefinition> extends true\n ? _StrictSearchInput<TDefinition> & _ParamsInput<TDefinition>\n : _ParamsInput<TDefinition>\n : HasSearch<TDefinition> extends true\n ? _StrictSearchInput<TDefinition>\n : Record<never, never>\n\nexport type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S\nexport type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : ''\nexport type SearchTailDefinitionWithFirstAmp<S extends string> = S extends `${string}&${infer T}` ? `&${T}` : ''\nexport type AmpSplit<S extends string> = S extends `${infer A}&${infer B}` ? A | AmpSplit<B> : S\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type NonEmpty<T> = [T] extends ['' | never] ? never : T\nexport type ExtractPathParams<S extends string> = S extends `${string}:${infer After}`\n ? After extends `${infer Name}/${infer Rest}`\n ? Name | ExtractPathParams<`/${Rest}`>\n : After\n : never\nexport type ReplacePathParams<S extends string> = S extends `${infer Head}:${infer Tail}`\n ? // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Tail extends `${infer _Param}/${infer Rest}`\n ? ReplacePathParams<`${Head}${string}/${Rest}`>\n : `${Head}${string}`\n : S\nexport type DedupeSlashes<S extends string> = S extends `${infer A}//${infer B}` ? DedupeSlashes<`${A}/${B}`> : S\nexport type EmptyRecord = Record<never, never>\nexport type JoinPath<Parent extends string, Suffix extends string> = DedupeSlashes<\n PathDefinition<Parent> extends infer A extends string\n ? PathDefinition<Suffix> extends infer B extends string\n ? A extends ''\n ? B extends ''\n ? ''\n : B extends `/${string}`\n ? B\n : `/${B}`\n : B extends ''\n ? A\n : A extends `${string}/`\n ? `${A}${B}`\n : B extends `/${string}`\n ? `${A}${B}`\n : `${A}/${B}`\n : never\n : never\n>\n\nexport type OnlyIfNoParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? Yes : No\nexport type OnlyIfHasParams<TParams extends object | undefined, Yes, No = never> = TParams extends undefined ? No : Yes\n\nexport type PathOnlyRouteValue<TDefinition extends string> = `${ReplacePathParams<PathDefinition<TDefinition>>}`\nexport type WithSearchRouteValue<TDefinition extends string> =\n `${ReplacePathParams<PathDefinition<TDefinition>>}?${string}`\nexport type AbsolutePathOnlyRouteValue<TDefinition extends string> =\n PathOnlyRouteValue<TDefinition> extends '/' ? string : `${string}${PathOnlyRouteValue<TDefinition>}`\nexport type AbsoluteWithSearchRouteValue<TDefinition extends string> = `${string}${WithSearchRouteValue<TDefinition>}`\n\nexport type PathExtended<\n TSourcedefinitionDefinition extends string,\n TSuffixdefinitionDefinition extends string,\n> = `${JoinPath<TSourcedefinitionDefinition, TSuffixdefinitionDefinition>}${SearchTailDefinitionWithFirstAmp<TSuffixdefinitionDefinition>}`\n\nexport type WithParamsInput<\n TDefinition extends string,\n T extends\n | {\n search?: _SearchInput<any>\n abs?: boolean\n }\n | undefined = undefined,\n> = _ParamsInput<TDefinition> & (T extends undefined ? Record<never, never> : T)\n\nexport type _IsSameParams<T1 extends object | undefined, T2 extends object | undefined> = T1 extends undefined\n ? T2 extends undefined\n ? true\n : false\n : T2 extends undefined\n ? false\n : T1 extends T2\n ? T2 extends T1\n ? true\n : false\n : false\n\nexport type _IsParent<T extends string, TParent extends string> = T extends TParent\n ? false\n : T extends `${TParent}${string}`\n ? true\n : false\nexport type _IsChildren<T extends string, TChildren extends string> = TChildren extends T\n ? false\n : TChildren extends `${T}${string}`\n ? true\n : false\nexport type _IsSame<T extends string, TExact extends string> = T extends TExact\n ? TExact extends T\n ? true\n : false\n : false\n"],"mappings":"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","names":["paramsInput","searchInput"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devp0nt/route0",
3
- "version": "1.0.0-next.21",
3
+ "version": "1.0.0-next.23",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Sergei Dmitriev",
package/src/index.test.ts CHANGED
@@ -2,7 +2,9 @@ import { describe, expect, expectTypeOf, it } from 'bun:test'
2
2
  import type {
3
3
  AnyRoute,
4
4
  CallabelRoute,
5
+ CanInputBeEmpty,
5
6
  Extended,
7
+ FlatInput,
6
8
  HasParams,
7
9
  HasSearch,
8
10
  IsChildren,
@@ -13,6 +15,7 @@ import type {
13
15
  ParamsOutput,
14
16
  SearchInput,
15
17
  SearchOutput,
18
+ StrictFlatInput,
16
19
  StrictSearchInput,
17
20
  StrictSearchOutput,
18
21
  } from './index.js'
@@ -341,6 +344,52 @@ describe('type utilities', () => {
341
344
  expectTypeOf<T1>().toEqualTypeOf<{ x?: string | undefined; y?: string | undefined }>()
342
345
  })
343
346
 
347
+ it('FlatInput', () => {
348
+ type T1 = FlatInput<'/path&x&y'>
349
+ expectTypeOf<T1>().toEqualTypeOf<
350
+ Partial<{
351
+ x: string | number
352
+ y: string | number
353
+ }> &
354
+ Record<string, string | number>
355
+ >()
356
+
357
+ type T2 = FlatInput<'/path/:id&x&y'>
358
+ expectTypeOf<T2>().toEqualTypeOf<
359
+ {
360
+ id: string | number
361
+ } & Partial<{
362
+ x: string | number
363
+ y: string | number
364
+ }> &
365
+ Record<string, string | number>
366
+ >()
367
+ })
368
+ it('StrictFlatInput', () => {
369
+ type T1 = StrictFlatInput<'/path&x&y'>
370
+ expectTypeOf<T1>().toEqualTypeOf<{ x?: string | number; y?: string | number }>()
371
+ type T2 = StrictFlatInput<'/path/:id&x&y'>
372
+ expectTypeOf<T2>().toEqualTypeOf<
373
+ Partial<{
374
+ x: string | number
375
+ y: string | number
376
+ }> & {
377
+ id: string | number
378
+ }
379
+ >()
380
+ })
381
+
382
+ it('CanInputBeEmpty', () => {
383
+ type T1 = CanInputBeEmpty<'/path'>
384
+ expectTypeOf<T1>().toEqualTypeOf<true>()
385
+ type T2 = CanInputBeEmpty<'/path/:id'>
386
+ expectTypeOf<T2>().toEqualTypeOf<false>()
387
+ type T3 = CanInputBeEmpty<'/path&x&y'>
388
+ expectTypeOf<T3>().toEqualTypeOf<true>()
389
+ type T4 = CanInputBeEmpty<'/path/:id&x&y'>
390
+ expectTypeOf<T4>().toEqualTypeOf<false>()
391
+ })
392
+
344
393
  it('IsParent', () => {
345
394
  type T1 = IsParent<'/path/child', '/path'>
346
395
  type T2 = IsParent<'/path', '/path/child'>
@@ -646,7 +695,7 @@ describe('getLocation', () => {
646
695
  expect(loc.pathname).toBe('/')
647
696
  })
648
697
 
649
- it('with LocationAny object as input', () => {
698
+ it('with AnyLocation object as input', () => {
650
699
  const routes = Routes.create({
651
700
  userDetail: '/users/:id',
652
701
  })
package/src/index.ts CHANGED
@@ -337,9 +337,9 @@ export class Route0<TDefinition extends string> {
337
337
  static getLocation(href: `${string}://${string}`): UnknownLocation
338
338
  static getLocation(hrefRel: `/${string}`): UnknownLocation
339
339
  static getLocation(hrefOrHrefRel: string): UnknownLocation
340
- static getLocation(location: LocationAny): UnknownLocation
341
- static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation
342
- static getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation {
340
+ static getLocation(location: AnyLocation): UnknownLocation
341
+ static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation
342
+ static getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation {
343
343
  if (typeof hrefOrHrefRelOrLocation !== 'string') {
344
344
  hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel
345
345
  }
@@ -392,11 +392,11 @@ export class Route0<TDefinition extends string> {
392
392
  getLocation(href: `${string}://${string}`): KnownLocation<TDefinition>
393
393
  getLocation(hrefRel: `/${string}`): KnownLocation<TDefinition>
394
394
  getLocation(hrefOrHrefRel: string): KnownLocation<TDefinition>
395
- getLocation(location: LocationAny): KnownLocation<TDefinition>
396
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition>
397
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): KnownLocation<TDefinition> {
395
+ getLocation(location: AnyLocation): KnownLocation<TDefinition>
396
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition>
397
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): KnownLocation<TDefinition> {
398
398
  const location = Route0.getLocation(hrefOrHrefRelOrLocation) as never as KnownLocation<TDefinition>
399
- location.route = this.definition as definition<TDefinition>
399
+ location.route = this.definition as Definition<TDefinition>
400
400
  location.params = {}
401
401
 
402
402
  const escapeRegex = (s: string) => s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
@@ -604,9 +604,9 @@ export class Routes<const T extends RoutesRecord = RoutesRecord> {
604
604
  getLocation(href: `${string}://${string}`): UnknownLocation | ExactLocation
605
605
  getLocation(hrefRel: `/${string}`): UnknownLocation | ExactLocation
606
606
  getLocation(hrefOrHrefRel: string): UnknownLocation | ExactLocation
607
- getLocation(location: LocationAny): UnknownLocation | ExactLocation
608
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation
609
- getLocation(hrefOrHrefRelOrLocation: string | LocationAny): UnknownLocation | ExactLocation {
607
+ getLocation(location: AnyLocation): UnknownLocation | ExactLocation
608
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation
609
+ getLocation(hrefOrHrefRelOrLocation: string | AnyLocation): UnknownLocation | ExactLocation {
610
610
  // Find the route that exactly matches the given location
611
611
  for (const route of this.ordered) {
612
612
  const loc = route.getLocation(hrefOrHrefRelOrLocation)
@@ -700,7 +700,7 @@ export type ExtractRoute<
700
700
 
701
701
  // public utils
702
702
 
703
- export type definition<T extends AnyRoute | string> = T extends AnyRoute
703
+ export type Definition<T extends AnyRoute | string> = T extends AnyRoute
704
704
  ? T['definition']
705
705
  : T extends string
706
706
  ? T
@@ -749,7 +749,7 @@ export type IsSameParams<T1 extends AnyRoute | string, T2 extends AnyRoute | str
749
749
  export type HasParams<T extends AnyRoute | string> =
750
750
  ExtractPathParams<PathDefinition<T>> extends infer U ? ([U] extends [never] ? false : true) : false
751
751
  export type HasSearch<T extends AnyRoute | string> =
752
- NonEmpty<SearchTailDefinitionWithoutFirstAmp<definition<T>>> extends infer Tail extends string
752
+ NonEmpty<SearchTailDefinitionWithoutFirstAmp<Definition<T>>> extends infer Tail extends string
753
753
  ? AmpSplit<Tail> extends infer U
754
754
  ? [U] extends [never]
755
755
  ? false
@@ -769,8 +769,11 @@ export type StrictSearchOutput<T extends AnyRoute | string> = Partial<{
769
769
  [K in keyof SearchDefinition<T>]?: string | undefined
770
770
  }>
771
771
  export type ParamsInput<T extends AnyRoute | string = string> = _ParamsInput<PathDefinition<T>>
772
- export type SearchInput<T extends AnyRoute | string = string> = _SearchInput<definition<T>>
773
- export type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<definition<T>>
772
+ export type SearchInput<T extends AnyRoute | string = string> = _SearchInput<Definition<T>>
773
+ export type StrictSearchInput<T extends AnyRoute | string> = _StrictSearchInput<Definition<T>>
774
+ export type FlatInput<T extends AnyRoute | string> = _FlatInput<Definition<T>>
775
+ export type StrictFlatInput<T extends AnyRoute | string> = _StrictFlatInput<Definition<T>>
776
+ export type CanInputBeEmpty<T extends AnyRoute | string> = HasParams<Definition<T>> extends true ? false : true
774
777
 
775
778
  // location
776
779
 
@@ -804,7 +807,7 @@ export type UnknownLocation = _GeneralLocation & {
804
807
  export type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
805
808
  params: Record<never, never>
806
809
  searchParams: SearchOutput<TRoute>
807
- route: definition<TRoute>
810
+ route: Definition<TRoute>
808
811
  exact: false
809
812
  parent: false
810
813
  children: false
@@ -812,7 +815,7 @@ export type UnmatchedLocation<TRoute extends AnyRoute | string = AnyRoute | stri
812
815
  export type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
813
816
  params: ParamsOutput<TRoute>
814
817
  searchParams: SearchOutput<TRoute>
815
- route: definition<TRoute>
818
+ route: Definition<TRoute>
816
819
  exact: true
817
820
  parent: false
818
821
  children: false
@@ -820,7 +823,7 @@ export type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string>
820
823
  export type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
821
824
  params: Partial<ParamsOutput<TRoute>> // in fact maybe there will be whole params object, but does not matter now
822
825
  searchParams: SearchOutput<TRoute>
823
- route: definition<TRoute>
826
+ route: Definition<TRoute>
824
827
  exact: false
825
828
  parent: true
826
829
  children: false
@@ -828,7 +831,7 @@ export type ParentLocation<TRoute extends AnyRoute | string = AnyRoute | string>
828
831
  export type ChildrenLocation<TRoute extends AnyRoute | string = AnyRoute | string> = _GeneralLocation & {
829
832
  params: ParamsOutput<TRoute>
830
833
  searchParams: SearchOutput<TRoute>
831
- route: definition<TRoute>
834
+ route: Definition<TRoute>
832
835
  exact: false
833
836
  parent: false
834
837
  children: true
@@ -838,7 +841,7 @@ export type KnownLocation<TRoute extends AnyRoute | string = AnyRoute | string>
838
841
  | ExactLocation<TRoute>
839
842
  | ParentLocation<TRoute>
840
843
  | ChildrenLocation<TRoute>
841
- export type LocationAny<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>
844
+ export type AnyLocation<TRoute extends AnyRoute = AnyRoute> = UnknownLocation | KnownLocation<TRoute>
842
845
 
843
846
  // internal utils
844
847
 
@@ -874,6 +877,18 @@ export type _SearchInput<TDefinition extends string> =
874
877
  export type _StrictSearchInput<TDefinition extends string> = Partial<{
875
878
  [K in keyof _SearchDefinition<TDefinition>]: string | number
876
879
  }>
880
+ export type _FlatInput<TDefinition extends string> =
881
+ HasParams<TDefinition> extends true
882
+ ? _ParamsInput<TDefinition> & _SearchInput<TDefinition>
883
+ : _SearchInput<TDefinition>
884
+ export type _StrictFlatInput<TDefinition extends string> =
885
+ HasParams<TDefinition> extends true
886
+ ? HasSearch<TDefinition> extends true
887
+ ? _StrictSearchInput<TDefinition> & _ParamsInput<TDefinition>
888
+ : _ParamsInput<TDefinition>
889
+ : HasSearch<TDefinition> extends true
890
+ ? _StrictSearchInput<TDefinition>
891
+ : Record<never, never>
877
892
 
878
893
  export type TrimSearchTailDefinition<S extends string> = S extends `${infer P}&${string}` ? P : S
879
894
  export type SearchTailDefinitionWithoutFirstAmp<S extends string> = S extends `${string}&${infer T}` ? T : ''