Skip to content

Commit

Permalink
fix(start): allow types to override for input and context (#2892)
Browse files Browse the repository at this point in the history
* fix(start): allow types to override for input and context

* fix(start): add type tests and fix other tests
  • Loading branch information
chorobin authored Dec 2, 2024
1 parent a12b4c7 commit 8f1d437
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 114 deletions.
8 changes: 7 additions & 1 deletion packages/react-router/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,13 @@ export type { NotFoundError } from './not-found'
export type { Manifest, RouterManagedTag } from './manifest'

export { createControlledPromise } from './utils'
export type { ControlledPromise, Constrain, Expand, MergeAll } from './utils'
export type {
ControlledPromise,
Constrain,
Expand,
MergeAll,
Assign,
} from './utils'

export type {
ResolveValidatorInput,
Expand Down
179 changes: 72 additions & 107 deletions packages/start/src/client/createMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,125 +1,79 @@
import type { ConstrainValidator, Method } from './createServerFn'
import type {
Assign,
Constrain,
DefaultTransformerStringify,
Expand,
MergeAll,
ResolveValidatorInput,
ResolveValidatorOutput,
} from '@tanstack/react-router'

/**
* Turns all middleware into a union
*/
export type ParseMiddlewares<
export type MergeAllMiddleware<
TMiddlewares,
TAcc = never,
> = unknown extends TMiddlewares
? TAcc
: [] extends TMiddlewares
? TAcc
: TMiddlewares extends ReadonlyArray<AnyMiddleware>
? TMiddlewares[number] extends infer TMiddleware extends AnyMiddleware
? TMiddleware extends any
? ParseMiddlewares<
TMiddleware['_types']['middlewares'],
TAcc | TMiddleware
>
: TAcc
: TAcc
: TAcc
TType extends keyof AnyMiddleware['_types'],
TAcc = undefined,
> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest,
]
? MergeAllMiddleware<TRest, TType, Assign<TAcc, TMiddleware['_types'][TType]>>
: TAcc

export type ResolveAllMiddlewareServerContext<
export type MergeAllClientAfterContext<
TMiddlewares,
TContext = undefined,
> = ParseMiddlewares<TMiddlewares>['_types']['serverContext'] | TContext
TClientContext = undefined,
TClientAfterContext = undefined,
> = unknown extends TClientContext
? TClientContext
: Assign<
MergeAllMiddleware<TMiddlewares, 'allClientAfterContext'>,
Assign<TClientContext, TClientAfterContext>
>

/**
* Recursively resolve the server context type produced by a sequence of middleware
* Recursively resolve the client context type produced by a sequence of middleware
*/
export type MergeAllServerContext<TMiddlewares, TContext = undefined> = Expand<
MergeAll<
ResolveAllMiddlewareServerContext<TMiddlewares, TContext> extends undefined
? undefined
: NonNullable<ResolveAllMiddlewareServerContext<TMiddlewares, TContext>>
>
>

export type ResolveAllMiddlewareClientContext<
export type MergeAllClientContext<
TMiddlewares,
TContext = undefined,
> = ParseMiddlewares<TMiddlewares>['_types']['clientContext'] | TContext
> = unknown extends TContext
? TContext
: Assign<MergeAllMiddleware<TMiddlewares, 'allClientContext'>, TContext>

/**
* Recursively resolve the client context type produced by a sequence of middleware
* Recursively resolve the server context type produced by a sequence of middleware
*/
export type MergeAllClientContext<TMiddlewares, TContext = undefined> = Expand<
MergeAll<
ResolveAllMiddlewareClientContext<TMiddlewares, TContext> extends undefined
? undefined
: NonNullable<ResolveAllMiddlewareClientContext<TMiddlewares, TContext>>
>
>

export type ResolveAllMiddlewareClientAfterContext<
export type MergeAllServerContext<
TMiddlewares,
TContext = undefined,
> =
| ParseMiddlewares<TMiddlewares>['_types']['clientContext']
| ParseMiddlewares<TMiddlewares>['_types']['clientAfterContext']
| TContext

export type MergeAllClientAfterContext<
TMiddlewares,
TClientContext = undefined,
TClientAfterContext = undefined,
> = Expand<
MergeAll<
ResolveAllMiddlewareClientAfterContext<
TMiddlewares,
TClientContext | TClientAfterContext
> extends undefined
? undefined
: NonNullable<
ResolveAllMiddlewareClientAfterContext<
TMiddlewares,
TClientContext | TClientAfterContext
>
>
>
>

export type ResolveAllValidators<TMiddlewares, TValidator> =
| ParseMiddlewares<TMiddlewares>['_types']['validator']
| TValidator

export type ResolveAllValidatorInputs<TMiddlewares, TValidator> =
ResolveAllValidators<TMiddlewares, TValidator> extends undefined
? undefined
: ResolveValidatorInput<
NonNullable<ResolveAllValidators<TMiddlewares, TValidator>>
>
> = unknown extends TContext
? TContext
: Assign<MergeAllMiddleware<TMiddlewares, 'allServerContext'>, TContext>

/**
* Recursively resolve the input type produced by a sequence of middleware
*/
export type MergeAllValidatorInputs<TMiddlewares, TValidator> = Expand<
MergeAll<ResolveAllValidatorInputs<TMiddlewares, TValidator>>
>

export type ResolveAllValidatorOutputs<TMiddlewares, TValidator> =
ResolveAllValidators<TMiddlewares, TValidator> extends undefined
? undefined
: ResolveValidatorOutput<
NonNullable<ResolveAllValidators<TMiddlewares, TValidator>>
export type MergeAllValidatorInputs<TMiddlewares, TValidator> =
unknown extends TValidator
? TValidator
: Assign<
MergeAllMiddleware<TMiddlewares, 'allInput'>,
TValidator extends undefined
? undefined
: ResolveValidatorInput<TValidator>
>

/**
* Recursively merge the output type produced by a sequence of middleware
*/
export type MergeAllValidatorOutputs<TMiddlewares, TValidator> = Expand<
MergeAll<ResolveAllValidatorOutputs<TMiddlewares, TValidator>>
>
export type MergeAllValidatorOutputs<TMiddlewares, TValidator> =
unknown extends TValidator
? TValidator
: Assign<
MergeAllMiddleware<TMiddlewares, 'allOutput'>,
TValidator extends undefined
? undefined
: ResolveValidatorOutput<TValidator>
>

export interface MiddlewareOptions<
in out TMiddlewares,
Expand Down Expand Up @@ -167,8 +121,8 @@ export interface MiddlewareServerFnOptions<
in out TValidator,
in out TServerContext,
> {
data: MergeAllValidatorOutputs<TMiddlewares, NonNullable<TValidator>>
context: MergeAllServerContext<TMiddlewares, NonNullable<TServerContext>>
data: Expand<MergeAllValidatorOutputs<TMiddlewares, TValidator>>
context: Expand<MergeAllServerContext<TMiddlewares, TServerContext>>
next: MiddlewareServerNextFn
}

Expand Down Expand Up @@ -197,8 +151,8 @@ export interface MiddlewareClientFnOptions<
in out TMiddlewares,
in out TValidator,
> {
data: MergeAllValidatorInputs<TMiddlewares, NonNullable<TValidator>>
context: MergeAllClientContext<TMiddlewares>
data: Expand<MergeAllValidatorInputs<TMiddlewares, TValidator>>
context: Expand<MergeAllClientContext<TMiddlewares>>
sendContext?: unknown // cc Chris Horobin
method: Method
next: MiddlewareClientNextFn
Expand Down Expand Up @@ -229,11 +183,13 @@ export interface MiddlewareClientAfterFnOptions<
in out TClientContext,
in out TClientAfterContext,
> {
data: MergeAllValidatorInputs<TMiddlewares, NonNullable<TValidator>>
context: MergeAllClientAfterContext<
TMiddlewares,
TClientContext,
TClientAfterContext
data: Expand<MergeAllValidatorInputs<TMiddlewares, TValidator>>
context: Expand<
MergeAllClientAfterContext<
TMiddlewares,
TClientContext,
TClientAfterContext
>
>
method: Method
next: MiddlewareClientAfterNextFn
Expand Down Expand Up @@ -289,10 +245,19 @@ export interface MiddlewareTypes<
id: TId
middlewares: TMiddlewares
input: ResolveValidatorInput<TValidator>
allInput: MergeAllValidatorInputs<TMiddlewares, TValidator>
output: ResolveValidatorOutput<TValidator>
allOutput: MergeAllValidatorOutputs<TMiddlewares, TValidator>
clientContext: TClientContext
allClientContext: MergeAllClientContext<TMiddlewares, TClientContext>
serverContext: TServerContext
allServerContext: MergeAllServerContext<TMiddlewares, TServerContext>
clientAfterContext: TClientAfterContext
allClientAfterContext: MergeAllClientAfterContext<
TMiddlewares,
TClientContext,
TClientAfterContext
>
validator: TValidator
}
options: MiddlewareOptions<
Expand Down Expand Up @@ -345,7 +310,7 @@ export interface MiddlewareClientAfter<
TValidator,
TServerContext,
TClientContext,
TClientAfterContext | TNewClientAfterContext
Assign<TClientAfterContext, TNewClientAfterContext>
>
}

Expand Down Expand Up @@ -393,9 +358,9 @@ export interface MiddlewareServer<
TId,
TMiddlewares,
TValidator,
TServerContext | TNewServerContext,
Assign<TServerContext, TNewServerContext>,
TClientContext,
TClientAfterContext | TNewClientAfterContext
Assign<TClientAfterContext, TNewClientAfterContext>
>
}

Expand Down Expand Up @@ -442,8 +407,8 @@ export interface MiddlewareClient<
TId,
TMiddlewares,
TValidator,
TServerContext | TNewServerContext,
TClientContext | TNewClientContext,
Assign<TServerContext, TNewServerContext>,
Assign<TClientContext, TNewClientContext>,
TClientAfterContext
>
}
Expand Down Expand Up @@ -503,7 +468,7 @@ export interface Middleware<
TClientContext,
TClientAfterContext
> {
middleware: <const TNewMiddlewares>(
middleware: <const TNewMiddlewares = undefined>(
middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,
) => MiddlewareAfterMiddleware<
TId,
Expand Down
11 changes: 6 additions & 5 deletions packages/start/src/client/createServerFn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
Constrain,
DefaultTransformerParse,
DefaultTransformerStringify,
Expand,
ResolveValidatorInput,
TransformerStringify,
Validator,
Expand Down Expand Up @@ -40,12 +41,12 @@ export type FetcherImpl<TMiddlewares, TValidator, TResponse> =
undefined extends MergeAllValidatorInputs<TMiddlewares, TValidator>
? (
opts?: OptionalFetcherDataOptions<
MergeAllValidatorInputs<TMiddlewares, TValidator>
Expand<MergeAllValidatorInputs<TMiddlewares, TValidator>>
>,
) => Promise<FetcherData<TResponse>>
: (
opts: RequiredFetcherDataOptions<
MergeAllValidatorInputs<TMiddlewares, TValidator>
Expand<MergeAllValidatorInputs<TMiddlewares, TValidator>>
>,
) => Promise<FetcherData<TResponse>>

Expand Down Expand Up @@ -79,8 +80,8 @@ export type ServerFn<TMethod, TMiddlewares, TValidator, TResponse> = (

export interface ServerFnCtx<TMethod, TMiddlewares, TValidator> {
method: TMethod
data: MergeAllValidatorOutputs<TMiddlewares, TValidator>
context: MergeAllServerContext<TMiddlewares>
data: Expand<MergeAllValidatorOutputs<TMiddlewares, TValidator>>
context: Expand<MergeAllServerContext<TMiddlewares>>
}

export type CompiledFetcherFn<TResponse> = {
Expand Down Expand Up @@ -118,7 +119,7 @@ export type ConstrainValidator<TValidator> = unknown extends TValidator
>

export interface ServerFnMiddleware<TMethod extends Method, TValidator> {
middleware: <const TNewMiddlewares>(
middleware: <const TNewMiddlewares = undefined>(
middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,
) => ServerFnAfterMiddleware<TMethod, TNewMiddlewares, TValidator>
}
Expand Down
1 change: 0 additions & 1 deletion packages/start/src/client/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export {
} from './createServerFn'
export {
createMiddleware,
type ParseMiddlewares,
type MergeAllValidatorInputs,
type MergeAllValidatorOutputs,
type MiddlewareServerFn,
Expand Down
Loading

0 comments on commit 8f1d437

Please sign in to comment.