@tanstack/start-client-core 1.120.4-alpha.17 → 1.120.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +27 -6
  2. package/dist/cjs/createMiddleware.cjs +5 -8
  3. package/dist/cjs/createMiddleware.cjs.map +1 -1
  4. package/dist/cjs/createMiddleware.d.cts +81 -125
  5. package/dist/cjs/createServerFn.cjs +0 -1
  6. package/dist/cjs/createServerFn.cjs.map +1 -1
  7. package/dist/cjs/createServerFn.d.cts +5 -6
  8. package/dist/cjs/index.cjs +0 -1
  9. package/dist/cjs/index.cjs.map +1 -1
  10. package/dist/cjs/index.d.cts +2 -2
  11. package/dist/cjs/registerGlobalMiddleware.cjs.map +1 -1
  12. package/dist/cjs/registerGlobalMiddleware.d.cts +3 -3
  13. package/dist/cjs/ssr-client.cjs +25 -24
  14. package/dist/cjs/ssr-client.cjs.map +1 -1
  15. package/dist/cjs/ssr-client.d.cts +1 -2
  16. package/dist/esm/createMiddleware.d.ts +81 -125
  17. package/dist/esm/createMiddleware.js +5 -8
  18. package/dist/esm/createMiddleware.js.map +1 -1
  19. package/dist/esm/createServerFn.d.ts +5 -6
  20. package/dist/esm/createServerFn.js +0 -1
  21. package/dist/esm/createServerFn.js.map +1 -1
  22. package/dist/esm/index.d.ts +2 -2
  23. package/dist/esm/index.js +1 -2
  24. package/dist/esm/registerGlobalMiddleware.d.ts +3 -3
  25. package/dist/esm/registerGlobalMiddleware.js.map +1 -1
  26. package/dist/esm/ssr-client.d.ts +1 -2
  27. package/dist/esm/ssr-client.js +25 -24
  28. package/dist/esm/ssr-client.js.map +1 -1
  29. package/package.json +2 -2
  30. package/src/createMiddleware.ts +368 -479
  31. package/src/createServerFn.ts +16 -31
  32. package/src/index.tsx +21 -22
  33. package/src/registerGlobalMiddleware.ts +3 -3
  34. package/src/ssr-client.tsx +29 -33
  35. package/src/tests/createServerFn.test-d.ts +13 -20
  36. package/src/tests/createServerMiddleware.test-d.ts +73 -186
@@ -16,17 +16,15 @@ import type {
16
16
  } from '@tanstack/router-core'
17
17
  import type { Readable } from 'node:stream'
18
18
  import type {
19
- AnyFunctionMiddleware,
19
+ AnyMiddleware,
20
20
  AssignAllClientSendContext,
21
21
  AssignAllServerContext,
22
- FunctionMiddlewareClientFnResult,
23
- FunctionMiddlewareServerFnResult,
24
22
  IntersectAllValidatorInputs,
25
23
  IntersectAllValidatorOutputs,
24
+ MiddlewareClientFnResult,
25
+ MiddlewareServerFnResult,
26
26
  } from './createMiddleware'
27
27
 
28
- type TODO = any
29
-
30
28
  export function createServerFn<
31
29
  TMethod extends Method,
32
30
  TServerFnResponseType extends ServerFnResponseType = 'data',
@@ -217,8 +215,8 @@ export function createServerFn<
217
215
  }
218
216
  }
219
217
 
220
- export async function executeMiddleware(
221
- middlewares: Array<AnyFunctionMiddleware>,
218
+ async function executeMiddleware(
219
+ middlewares: Array<AnyMiddleware>,
222
220
  env: 'client' | 'server',
223
221
  opts: ServerFnMiddlewareOptions,
224
222
  ): Promise<ServerFnMiddlewareResult> {
@@ -400,7 +398,6 @@ export type ServerFnReturnType<
400
398
  > = TServerFnResponseType extends 'raw'
401
399
  ? RawResponse | Promise<RawResponse>
402
400
  : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>
403
-
404
401
  export type ServerFn<
405
402
  TMethod,
406
403
  TServerFnResponseType extends ServerFnResponseType,
@@ -445,7 +442,7 @@ export type ServerFnBaseOptions<
445
442
  method: TMethod
446
443
  response?: TServerFnResponseType
447
444
  validateClient?: boolean
448
- middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyFunctionMiddleware>>
445
+ middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>
449
446
  validator?: ConstrainValidator<TInput>
450
447
  extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>
451
448
  serverFn?: ServerFn<
@@ -488,10 +485,7 @@ export interface ServerFnMiddleware<
488
485
  TValidator,
489
486
  > {
490
487
  middleware: <const TNewMiddlewares = undefined>(
491
- middlewares: Constrain<
492
- TNewMiddlewares,
493
- ReadonlyArray<AnyFunctionMiddleware>
494
- >,
488
+ middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,
495
489
  ) => ServerFnAfterMiddleware<
496
490
  TMethod,
497
491
  TServerFnResponseType,
@@ -818,12 +812,12 @@ export function extractFormDataContext(formData: FormData) {
818
812
  }
819
813
 
820
814
  export function flattenMiddlewares(
821
- middlewares: Array<AnyFunctionMiddleware>,
822
- ): Array<AnyFunctionMiddleware> {
823
- const seen = new Set<AnyFunctionMiddleware>()
824
- const flattened: Array<AnyFunctionMiddleware> = []
815
+ middlewares: Array<AnyMiddleware>,
816
+ ): Array<AnyMiddleware> {
817
+ const seen = new Set<AnyMiddleware>()
818
+ const flattened: Array<AnyMiddleware> = []
825
819
 
826
- const recurse = (middleware: Array<AnyFunctionMiddleware>) => {
820
+ const recurse = (middleware: Array<AnyMiddleware>) => {
827
821
  middleware.forEach((m) => {
828
822
  if (m.options.middleware) {
829
823
  recurse(m.options.middleware)
@@ -935,7 +929,7 @@ export function execValidator(
935
929
 
936
930
  export function serverFnBaseToMiddleware(
937
931
  options: ServerFnBaseOptions<any, any, any, any, any>,
938
- ): AnyFunctionMiddleware {
932
+ ): AnyMiddleware {
939
933
  return {
940
934
  _types: undefined!,
941
935
  options: {
@@ -979,25 +973,16 @@ export function serverFnBaseToMiddleware(
979
973
  // but not before serializing the context
980
974
  const res = await options.extractedFn?.(payload)
981
975
 
982
- return next(res) as unknown as FunctionMiddlewareClientFnResult<
983
- any,
984
- any,
985
- any
986
- >
976
+ return next(res) as unknown as MiddlewareClientFnResult<any, any, any>
987
977
  },
988
978
  server: async ({ next, ...ctx }) => {
989
979
  // Execute the server function
990
- const result = await options.serverFn?.(ctx as TODO)
980
+ const result = await options.serverFn?.(ctx)
991
981
 
992
982
  return next({
993
983
  ...ctx,
994
984
  result,
995
- } as any) as unknown as FunctionMiddlewareServerFnResult<
996
- any,
997
- any,
998
- any,
999
- any
1000
- >
985
+ } as any) as unknown as MiddlewareServerFnResult<any, any, any, any>
1001
986
  },
1002
987
  },
1003
988
  }
package/src/index.tsx CHANGED
@@ -25,30 +25,30 @@ export {
25
25
  createMiddleware,
26
26
  type IntersectAllValidatorInputs,
27
27
  type IntersectAllValidatorOutputs,
28
- type FunctionMiddlewareServerFn,
29
- type AnyFunctionMiddleware,
30
- type FunctionMiddlewareOptions,
31
- type FunctionMiddlewareWithTypes,
32
- type FunctionMiddlewareValidator,
33
- type FunctionMiddlewareServer,
34
- type FunctionMiddlewareAfterClient,
35
- type FunctionMiddlewareAfterServer,
36
- type FunctionMiddleware,
37
- type FunctionMiddlewareClientFnOptions,
38
- type FunctionMiddlewareClientFnResult,
39
- type FunctionMiddlewareClientNextFn,
40
- type FunctionClientResultWithContext,
28
+ type MiddlewareServerFn,
29
+ type AnyMiddleware,
30
+ type MiddlewareOptions,
31
+ type MiddlewareWithTypes,
32
+ type MiddlewareValidator,
33
+ type MiddlewareServer,
34
+ type MiddlewareAfterClient,
35
+ type MiddlewareAfterMiddleware,
36
+ type MiddlewareAfterServer,
37
+ type Middleware,
38
+ type MiddlewareClientFnOptions,
39
+ type MiddlewareClientFnResult,
40
+ type MiddlewareClientNextFn,
41
+ type ClientResultWithContext,
41
42
  type AssignAllClientContextBeforeNext,
42
43
  type AssignAllMiddleware,
43
44
  type AssignAllServerContext,
44
- type FunctionMiddlewareAfterValidator,
45
- type FunctionMiddlewareClientFn,
46
- type FunctionMiddlewareServerFnResult,
47
- type FunctionMiddlewareClient,
48
- type FunctionMiddlewareServerFnOptions,
49
- type FunctionMiddlewareServerNextFn,
50
- type FunctionServerResultWithContext,
51
- type AnyRequestMiddleware,
45
+ type MiddlewareAfterValidator,
46
+ type MiddlewareClientFn,
47
+ type MiddlewareServerFnResult,
48
+ type MiddlewareClient,
49
+ type MiddlewareServerFnOptions,
50
+ type MiddlewareServerNextFn,
51
+ type ServerResultWithContext,
52
52
  } from './createMiddleware'
53
53
  export {
54
54
  registerGlobalMiddleware,
@@ -84,5 +84,4 @@ export {
84
84
  extractFormDataContext,
85
85
  flattenMiddlewares,
86
86
  serverFnStaticCache,
87
- executeMiddleware,
88
87
  } from './createServerFn'
@@ -1,9 +1,9 @@
1
- import type { AnyFunctionMiddleware } from './createMiddleware'
1
+ import type { AnyMiddleware } from './createMiddleware'
2
2
 
3
- export const globalMiddleware: Array<AnyFunctionMiddleware> = []
3
+ export const globalMiddleware: Array<AnyMiddleware> = []
4
4
 
5
5
  export function registerGlobalMiddleware(options: {
6
- middleware: Array<AnyFunctionMiddleware>
6
+ middleware: Array<AnyMiddleware>
7
7
  }) {
8
8
  globalMiddleware.push(...options.middleware)
9
9
  }
@@ -77,16 +77,15 @@ export interface ResolvePromiseState {
77
77
  export interface DehydratedRouter {
78
78
  manifest: Manifest | undefined
79
79
  dehydratedData: any
80
- lastMatchId: string
81
80
  }
82
81
 
83
- export async function hydrate(router: AnyRouter): Promise<any> {
82
+ export function hydrate(router: AnyRouter) {
84
83
  invariant(
85
84
  window.__TSR_SSR__?.dehydrated,
86
85
  'Expected to find a dehydrated data on window.__TSR_SSR__.dehydrated... but we did not. Please file an issue!',
87
86
  )
88
87
 
89
- const { manifest, dehydratedData, lastMatchId } = startSerializer.parse(
88
+ const { manifest, dehydratedData } = startSerializer.parse(
90
89
  window.__TSR_SSR__.dehydrated,
91
90
  ) as DehydratedRouter
92
91
 
@@ -117,7 +116,6 @@ export async function hydrate(router: AnyRouter): Promise<any> {
117
116
 
118
117
  // Hydrate the router state
119
118
  const matches = router.matchRoutes(router.state.location)
120
-
121
119
  // kick off loading the route chunks
122
120
  const routeChunkPromise = Promise.all(
123
121
  matches.map((match) => {
@@ -125,7 +123,6 @@ export async function hydrate(router: AnyRouter): Promise<any> {
125
123
  return router.loadRouteChunk(route)
126
124
  }),
127
125
  )
128
-
129
126
  // Right after hydration and before the first render, we need to rehydrate each match
130
127
  // First step is to reyhdrate loaderData and __beforeLoadContext
131
128
  matches.forEach((match) => {
@@ -133,36 +130,39 @@ export async function hydrate(router: AnyRouter): Promise<any> {
133
130
  (d) => d.id === match.id,
134
131
  )
135
132
 
136
- if (!dehydratedMatch) {
137
- return
138
- }
133
+ if (dehydratedMatch) {
134
+ Object.assign(match, dehydratedMatch)
139
135
 
140
- Object.assign(match, dehydratedMatch)
136
+ // Handle beforeLoadContext
137
+ if (dehydratedMatch.__beforeLoadContext) {
138
+ match.__beforeLoadContext = router.ssr!.serializer.parse(
139
+ dehydratedMatch.__beforeLoadContext,
140
+ ) as any
141
+ }
141
142
 
142
- // Handle beforeLoadContext
143
- if (dehydratedMatch.__beforeLoadContext) {
144
- match.__beforeLoadContext = router.ssr!.serializer.parse(
145
- dehydratedMatch.__beforeLoadContext,
146
- ) as any
147
- }
143
+ // Handle loaderData
144
+ if (dehydratedMatch.loaderData) {
145
+ match.loaderData = router.ssr!.serializer.parse(
146
+ dehydratedMatch.loaderData,
147
+ )
148
+ }
148
149
 
149
- // Handle loaderData
150
- if (dehydratedMatch.loaderData) {
151
- match.loaderData = router.ssr!.serializer.parse(
152
- dehydratedMatch.loaderData,
153
- )
154
- }
150
+ // Handle error
151
+ if (dehydratedMatch.error) {
152
+ match.error = router.ssr!.serializer.parse(dehydratedMatch.error)
153
+ }
155
154
 
156
- // Handle error
157
- if (dehydratedMatch.error) {
158
- match.error = router.ssr!.serializer.parse(dehydratedMatch.error)
155
+ // Handle extracted
156
+ ;(match as unknown as SsrMatch).extracted?.forEach((ex) => {
157
+ deepMutableSetByPath(match, ['loaderData', ...ex.path], ex.value)
158
+ })
159
+ } else {
160
+ Object.assign(match, {
161
+ status: 'success',
162
+ updatedAt: Date.now(),
163
+ })
159
164
  }
160
165
 
161
- // Handle extracted
162
- ;(match as unknown as SsrMatch).extracted?.forEach((ex) => {
163
- deepMutableSetByPath(match, ['loaderData', ...ex.path], ex.value)
164
- })
165
-
166
166
  return match
167
167
  })
168
168
 
@@ -224,10 +224,6 @@ export async function hydrate(router: AnyRouter): Promise<any> {
224
224
  match.scripts = scripts
225
225
  })
226
226
 
227
- if (matches[matches.length - 1]!.id !== lastMatchId) {
228
- return await Promise.all([routeChunkPromise, router.load()])
229
- }
230
-
231
227
  return routeChunkPromise
232
228
  }
233
229
 
@@ -60,25 +60,21 @@ test('createServerFn with validator', () => {
60
60
  })
61
61
 
62
62
  test('createServerFn with middleware and context', () => {
63
- const middleware1 = createMiddleware({ type: 'function' }).server(
64
- ({ next }) => {
65
- return next({ context: { a: 'a' } as const })
66
- },
67
- )
63
+ const middleware1 = createMiddleware().server(({ next }) => {
64
+ return next({ context: { a: 'a' } as const })
65
+ })
68
66
 
69
- const middleware2 = createMiddleware({ type: 'function' }).server(
70
- ({ next }) => {
71
- return next({ context: { b: 'b' } as const })
72
- },
73
- )
67
+ const middleware2 = createMiddleware().server(({ next }) => {
68
+ return next({ context: { b: 'b' } as const })
69
+ })
74
70
 
75
- const middleware3 = createMiddleware({ type: 'function' })
71
+ const middleware3 = createMiddleware()
76
72
  .middleware([middleware1, middleware2])
77
73
  .client(({ next }) => {
78
74
  return next({ context: { c: 'c' } as const })
79
75
  })
80
76
 
81
- const middleware4 = createMiddleware({ type: 'function' })
77
+ const middleware4 = createMiddleware()
82
78
  .middleware([middleware3])
83
79
  .client(({ context, next }) => {
84
80
  return next({ sendContext: context })
@@ -117,24 +113,21 @@ test('createServerFn with middleware and context', () => {
117
113
  })
118
114
 
119
115
  describe('createServerFn with middleware and validator', () => {
120
- const middleware1 = createMiddleware({ type: 'function' }).validator(
116
+ const middleware1 = createMiddleware().validator(
121
117
  (input: { readonly inputA: 'inputA' }) =>
122
118
  ({
123
119
  outputA: 'outputA',
124
120
  }) as const,
125
121
  )
126
122
 
127
- const middleware2 = createMiddleware({ type: 'function' }).validator(
123
+ const middleware2 = createMiddleware().validator(
128
124
  (input: { readonly inputB: 'inputB' }) =>
129
125
  ({
130
126
  outputB: 'outputB',
131
127
  }) as const,
132
128
  )
133
129
 
134
- const middleware3 = createMiddleware({ type: 'function' }).middleware([
135
- middleware1,
136
- middleware2,
137
- ])
130
+ const middleware3 = createMiddleware().middleware([middleware1, middleware2])
138
131
 
139
132
  test(`response: 'data'`, () => {
140
133
  const fn = createServerFn({ method: 'GET', response: 'data' })
@@ -229,7 +222,7 @@ describe('createServerFn with middleware and validator', () => {
229
222
  })
230
223
 
231
224
  test('createServerFn overrides properties', () => {
232
- const middleware1 = createMiddleware({ type: 'function' })
225
+ const middleware1 = createMiddleware()
233
226
  .validator(
234
227
  () =>
235
228
  ({
@@ -253,7 +246,7 @@ test('createServerFn overrides properties', () => {
253
246
  return next({ sendContext: newContext, context: newContext })
254
247
  })
255
248
 
256
- const middleware2 = createMiddleware({ type: 'function' })
249
+ const middleware2 = createMiddleware()
257
250
  .middleware([middleware1])
258
251
  .validator(
259
252
  () =>