Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(router-core): moving the router core into separate package #3171

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@
"@tanstack/react-query": "5.62.3",
"use-sync-external-store": "1.2.2",
"@tanstack/history": "workspace:*",
"@tanstack/router-core": "workspace:*",
"@tanstack/react-cross-context": "workspace:*",
"@tanstack/react-router": "workspace:*",
"@tanstack/router-cli": "workspace:*",
"@tanstack/react-router-with-query": "workspace:*",
"@tanstack/router-devtools": "workspace:*",
"@tanstack/router-generator": "workspace:*",
"@tanstack/virtual-file-routes": "workspace:*",
"@tanstack/router-cli": "workspace:*",
"@tanstack/router-plugin": "workspace:*",
"@tanstack/router-vite-plugin": "workspace:*",
"@tanstack/react-router-with-query": "workspace:*",
"@tanstack/virtual-file-routes": "workspace:*",
"@tanstack/zod-adapter": "workspace:*",
"@tanstack/valibot-adapter": "workspace:*",
"@tanstack/arktype-adapter": "workspace:*",
Expand Down
1 change: 1 addition & 0 deletions packages/react-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"dependencies": {
"@tanstack/history": "workspace:*",
"@tanstack/react-store": "^0.7.0",
"@tanstack/router-core": "workspace:^",
"jsesc": "^3.0.2",
"tiny-invariant": "^1.3.3",
"tiny-warning": "^1.0.3"
Expand Down
10 changes: 7 additions & 3 deletions packages/react-router/src/Match.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
import * as React from 'react'
import invariant from 'tiny-invariant'
import warning from 'tiny-warning'
import {
createControlledPromise,
defaultDeserializeError,
isServerSideError,
pick,
rootRouteId,
} from '@tanstack/router-core'
import { CatchBoundary, ErrorComponent } from './CatchBoundary'
import { useRouterState } from './useRouterState'
import { useRouter } from './useRouter'
import { createControlledPromise, pick } from './utils'
import { CatchNotFound, isNotFound } from './not-found'
import { isRedirect } from './redirects'
import { matchContext } from './matchContext'
import { defaultDeserializeError, isServerSideError } from './isServerSideError'
import { SafeFragment } from './SafeFragment'
import { renderRouteNotFound } from './renderRouteNotFound'
import { rootRouteId } from './root'
import type { AnyRoute } from './route'

export const Match = React.memo(function MatchImpl({
Expand Down
109 changes: 8 additions & 101 deletions packages/react-router/src/Matches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ import type {
StructuralSharingOption,
ValidateSelected,
} from './structuralSharing'
import type { AnyRoute, ReactNode, StaticDataRouteOption } from './route'
import type { AnyRoute, ReactNode } from './route'
import type {
ControlledPromise,
DeepPartial,
NoInfer,
ResolveRelativePath,
StaticDataRouteOption,
} from '@tanstack/router-core'
import type { AnyRouter, RegisteredRouter, RouterState } from './router'
import type {
MakeOptionalPathParams,
MakeOptionalSearchParams,
MaskOptions,
ResolveRelativePath,
ResolveRoute,
ToSubOptionsProps,
} from './link'
Expand All @@ -31,105 +37,6 @@ import type {
RouteByPath,
RouteIds,
} from './routeInfo'
import type {
Constrain,
ControlledPromise,
DeepPartial,
NoInfer,
} from './utils'

export type AnyMatchAndValue = { match: any; value: any }

export type FindValueByIndex<
TKey,
TValue extends ReadonlyArray<any>,
> = TKey extends `${infer TIndex extends number}` ? TValue[TIndex] : never

export type FindValueByKey<TKey, TValue> =
TValue extends ReadonlyArray<any>
? FindValueByIndex<TKey, TValue>
: TValue[TKey & keyof TValue]

export type CreateMatchAndValue<TMatch, TValue> = TValue extends any
? {
match: TMatch
value: TValue
}
: never

export type NextMatchAndValue<
TKey,
TMatchAndValue extends AnyMatchAndValue,
> = TMatchAndValue extends any
? CreateMatchAndValue<
TMatchAndValue['match'],
FindValueByKey<TKey, TMatchAndValue['value']>
>
: never

export type IsMatchKeyOf<TValue> =
TValue extends ReadonlyArray<any>
? number extends TValue['length']
? `${number}`
: keyof TValue & `${number}`
: TValue extends object
? keyof TValue & string
: never

export type IsMatchPath<
TParentPath extends string,
TMatchAndValue extends AnyMatchAndValue,
> = `${TParentPath}${IsMatchKeyOf<TMatchAndValue['value']>}`

export type IsMatchResult<
TKey,
TMatchAndValue extends AnyMatchAndValue,
> = TMatchAndValue extends any
? TKey extends keyof TMatchAndValue['value']
? TMatchAndValue['match']
: never
: never

export type IsMatchParse<
TPath,
TMatchAndValue extends AnyMatchAndValue,
TParentPath extends string = '',
> = TPath extends `${string}.${string}`
? TPath extends `${infer TFirst}.${infer TRest}`
? IsMatchParse<
TRest,
NextMatchAndValue<TFirst, TMatchAndValue>,
`${TParentPath}${TFirst}.`
>
: never
: {
path: IsMatchPath<TParentPath, TMatchAndValue>
result: IsMatchResult<TPath, TMatchAndValue>
}

export type IsMatch<TMatch, TPath> = IsMatchParse<
TPath,
TMatch extends any ? { match: TMatch; value: TMatch } : never
>

/**
* Narrows matches based on a path
* @experimental
*/
export const isMatch = <TMatch, TPath extends string>(
match: TMatch,
path: Constrain<TPath, IsMatch<TMatch, TPath>['path']>,
): match is IsMatch<TMatch, TPath>['result'] => {
const parts = (path as string).split('.')
let part
let value: any = match

while ((part = parts.shift()) != null && value != null) {
value = value[part]
}

return value != null
}

export type MakeRouteMatchFromRoute<TRoute extends AnyRoute> = RouteMatch<
TRoute['types']['id'],
Expand Down
6 changes: 4 additions & 2 deletions packages/react-router/src/RouterProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import * as React from 'react'
import { Matches } from './Matches'
import { getRouterContext } from './routerContext'
import type { NavigateOptions, ToOptions } from './link'
import type { ParsedLocation } from './location'
import type {
ParsedLocation,
ViewTransitionOptions,
} from '@tanstack/router-core'
import type { RoutePaths } from './routeInfo'
import type {
AnyRouter,
RegisteredRouter,
Router,
RouterOptions,
ViewTransitionOptions,
} from './router'

export interface CommitLocationOptions {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-router/src/Transitioner.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react'
import { trimPathRight } from '@tanstack/router-core'
import { useLayoutEffect, usePrevious } from './utils'
import { useRouter } from './useRouter'
import { useRouterState } from './useRouterState'
import { trimPathRight } from './path'

export function Transitioner() {
const router = useRouter()
Expand Down
12 changes: 8 additions & 4 deletions packages/react-router/src/awaited.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import * as React from 'react'
import warning from 'tiny-warning'
import {
TSR_DEFERRED_PROMISE,
defaultDeserializeError,
defaultSerializeError,
defer,
isServerSideError,
} from '@tanstack/router-core'
import { useRouter } from './useRouter'
import { defaultSerializeError } from './router'
import { TSR_DEFERRED_PROMISE, defer } from './defer'
import { defaultDeserializeError, isServerSideError } from './isServerSideError'
import type { DeferredPromise } from './defer'
import type { DeferredPromise } from '@tanstack/router-core'

export type AwaitOptions<T> = {
promise: Promise<T>
Expand Down
9 changes: 6 additions & 3 deletions packages/react-router/src/fileRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import { useNavigate } from './useNavigate'
import type { UseParamsRoute } from './useParams'
import type { UseMatchRoute } from './useMatch'
import type { UseSearchRoute } from './useSearch'
import type { Constrain } from './utils'
import type {
AnyContext,
AnyPathParams,
AnyValidator,
Constrain,
ResolveParams,
} from '@tanstack/router-core'

import type {
AnyRoute,
FileBaseRouteOptions,
ResolveParams,
RootRoute,
Route,
RouteConstraints,
Expand All @@ -25,7 +29,6 @@ import type {
} from './route'
import type { RegisteredRouter } from './router'
import type { RouteById, RouteIds } from './routeInfo'
import type { AnyValidator } from './validators'
import type { UseLoaderDepsRoute } from './useLoaderDeps'
import type { UseLoaderDataRoute } from './useLoaderData'
import type { UseRouteContextRoute } from './useRouteContext'
Expand Down
Loading