@tanstack/react-start-client 1.111.15 → 1.112.1
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.
- package/dist/cjs/createMiddleware.cjs.map +1 -1
- package/dist/cjs/createMiddleware.d.cts +27 -25
- package/dist/cjs/createServerFn.cjs +7 -13
- package/dist/cjs/createServerFn.cjs.map +1 -1
- package/dist/cjs/createServerFn.d.cts +46 -37
- package/dist/cjs/index.d.cts +1 -1
- package/dist/esm/createMiddleware.d.ts +27 -25
- package/dist/esm/createMiddleware.js.map +1 -1
- package/dist/esm/createServerFn.d.ts +46 -37
- package/dist/esm/createServerFn.js +7 -13
- package/dist/esm/createServerFn.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/package.json +3 -3
- package/src/createMiddleware.ts +112 -34
- package/src/createServerFn.ts +239 -87
- package/src/index.tsx +1 -0
- package/src/tests/createServerFn.test-d.tsx +175 -64
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expectTypeOf, test } from 'vitest'
|
|
1
|
+
import { describe, expectTypeOf, test } from 'vitest'
|
|
2
2
|
import { createServerFn } from '../createServerFn'
|
|
3
3
|
import { createMiddleware } from '../createMiddleware'
|
|
4
4
|
import type { Constrain, Validator } from '@tanstack/router-core'
|
|
@@ -20,16 +20,17 @@ test('createServerFn without middleware', () => {
|
|
|
20
20
|
context: undefined
|
|
21
21
|
data: undefined
|
|
22
22
|
signal: AbortSignal
|
|
23
|
+
response: 'data'
|
|
23
24
|
}>()
|
|
24
25
|
})
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
test('createServerFn with validator', () => {
|
|
28
|
-
const fnAfterValidator = createServerFn({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
29
|
+
const fnAfterValidator = createServerFn({
|
|
30
|
+
method: 'GET',
|
|
31
|
+
}).validator((input: { input: string }) => ({
|
|
32
|
+
a: input.input,
|
|
33
|
+
}))
|
|
33
34
|
|
|
34
35
|
expectTypeOf(fnAfterValidator).toHaveProperty('handler')
|
|
35
36
|
expectTypeOf(fnAfterValidator).toHaveProperty('middleware')
|
|
@@ -43,6 +44,7 @@ test('createServerFn with validator', () => {
|
|
|
43
44
|
a: string
|
|
44
45
|
}
|
|
45
46
|
signal: AbortSignal
|
|
47
|
+
response: 'data'
|
|
46
48
|
}>()
|
|
47
49
|
})
|
|
48
50
|
|
|
@@ -50,11 +52,10 @@ test('createServerFn with validator', () => {
|
|
|
50
52
|
data: { input: string }
|
|
51
53
|
headers?: HeadersInit
|
|
52
54
|
type?: 'static' | 'dynamic'
|
|
53
|
-
fullResponse?: boolean
|
|
54
55
|
signal?: AbortSignal
|
|
55
56
|
}>()
|
|
56
57
|
|
|
57
|
-
expectTypeOf(
|
|
58
|
+
expectTypeOf<ReturnType<typeof fn>>().resolves.toEqualTypeOf<void>()
|
|
58
59
|
})
|
|
59
60
|
|
|
60
61
|
test('createServerFn with middleware and context', () => {
|
|
@@ -105,11 +106,12 @@ test('createServerFn with middleware and context', () => {
|
|
|
105
106
|
}
|
|
106
107
|
data: undefined
|
|
107
108
|
signal: AbortSignal
|
|
109
|
+
response: 'data'
|
|
108
110
|
}>()
|
|
109
111
|
})
|
|
110
112
|
})
|
|
111
113
|
|
|
112
|
-
|
|
114
|
+
describe('createServerFn with middleware and validator', () => {
|
|
113
115
|
const middleware1 = createMiddleware().validator(
|
|
114
116
|
(input: { readonly inputA: 'inputA' }) =>
|
|
115
117
|
({
|
|
@@ -126,60 +128,96 @@ test('createServerFn with middleware and validator', () => {
|
|
|
126
128
|
|
|
127
129
|
const middleware3 = createMiddleware().middleware([middleware1, middleware2])
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
(
|
|
133
|
-
({
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
131
|
+
test(`response: 'data'`, () => {
|
|
132
|
+
const fn = createServerFn({ method: 'GET', response: 'data' })
|
|
133
|
+
.middleware([middleware3])
|
|
134
|
+
.validator(
|
|
135
|
+
(input: { readonly inputC: 'inputC' }) =>
|
|
136
|
+
({
|
|
137
|
+
outputC: 'outputC',
|
|
138
|
+
}) as const,
|
|
139
|
+
)
|
|
140
|
+
.handler((options) => {
|
|
141
|
+
expectTypeOf(options).toEqualTypeOf<{
|
|
142
|
+
method: 'GET'
|
|
143
|
+
context: undefined
|
|
144
|
+
data: {
|
|
145
|
+
readonly outputA: 'outputA'
|
|
146
|
+
readonly outputB: 'outputB'
|
|
147
|
+
readonly outputC: 'outputC'
|
|
148
|
+
}
|
|
149
|
+
signal: AbortSignal
|
|
150
|
+
response: 'data'
|
|
151
|
+
}>()
|
|
152
|
+
|
|
153
|
+
return 'some-data' as const
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
expectTypeOf(fn).parameter(0).toEqualTypeOf<{
|
|
157
|
+
data: {
|
|
158
|
+
readonly inputA: 'inputA'
|
|
159
|
+
readonly inputB: 'inputB'
|
|
160
|
+
readonly inputC: 'inputC'
|
|
161
|
+
}
|
|
162
|
+
headers?: HeadersInit
|
|
163
|
+
type?: 'static' | 'dynamic'
|
|
164
|
+
signal?: AbortSignal
|
|
165
|
+
}>()
|
|
148
166
|
|
|
149
|
-
|
|
150
|
-
|
|
167
|
+
expectTypeOf(fn).returns.resolves.toEqualTypeOf<'some-data'>()
|
|
168
|
+
expectTypeOf(() =>
|
|
169
|
+
fn({
|
|
170
|
+
data: { inputA: 'inputA', inputB: 'inputB', inputC: 'inputC' },
|
|
171
|
+
}),
|
|
172
|
+
).returns.resolves.toEqualTypeOf<'some-data'>()
|
|
173
|
+
})
|
|
151
174
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
175
|
+
test(`response: 'full'`, () => {
|
|
176
|
+
const fn = createServerFn({ method: 'GET', response: 'full' })
|
|
177
|
+
.middleware([middleware3])
|
|
178
|
+
.validator(
|
|
179
|
+
(input: { readonly inputC: 'inputC' }) =>
|
|
180
|
+
({
|
|
181
|
+
outputC: 'outputC',
|
|
182
|
+
}) as const,
|
|
183
|
+
)
|
|
184
|
+
.handler((options) => {
|
|
185
|
+
expectTypeOf(options).toEqualTypeOf<{
|
|
186
|
+
method: 'GET'
|
|
187
|
+
context: undefined
|
|
188
|
+
data: {
|
|
189
|
+
readonly outputA: 'outputA'
|
|
190
|
+
readonly outputB: 'outputB'
|
|
191
|
+
readonly outputC: 'outputC'
|
|
192
|
+
}
|
|
193
|
+
signal: AbortSignal
|
|
194
|
+
response: 'full'
|
|
195
|
+
}>()
|
|
196
|
+
|
|
197
|
+
return 'some-data' as const
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
expectTypeOf(fn).parameter(0).toEqualTypeOf<{
|
|
201
|
+
data: {
|
|
202
|
+
readonly inputA: 'inputA'
|
|
203
|
+
readonly inputB: 'inputB'
|
|
204
|
+
readonly inputC: 'inputC'
|
|
205
|
+
}
|
|
206
|
+
headers?: HeadersInit
|
|
207
|
+
type?: 'static' | 'dynamic'
|
|
208
|
+
signal?: AbortSignal
|
|
209
|
+
}>()
|
|
163
210
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
fn({
|
|
175
|
-
fullResponse: true,
|
|
176
|
-
data: { inputA: 'inputA', inputB: 'inputB', inputC: 'inputC' },
|
|
177
|
-
}),
|
|
178
|
-
).returns.resolves.toEqualTypeOf<{
|
|
179
|
-
result: 'data'
|
|
180
|
-
context: undefined
|
|
181
|
-
error: unknown
|
|
182
|
-
}>()
|
|
211
|
+
expectTypeOf(() =>
|
|
212
|
+
fn({
|
|
213
|
+
data: { inputA: 'inputA', inputB: 'inputB', inputC: 'inputC' },
|
|
214
|
+
}),
|
|
215
|
+
).returns.resolves.toEqualTypeOf<{
|
|
216
|
+
result: 'some-data'
|
|
217
|
+
context: undefined
|
|
218
|
+
error: unknown
|
|
219
|
+
}>()
|
|
220
|
+
})
|
|
183
221
|
})
|
|
184
222
|
|
|
185
223
|
test('createServerFn overrides properties', () => {
|
|
@@ -255,6 +293,7 @@ test('createServerFn where validator is a primitive', () => {
|
|
|
255
293
|
context: undefined
|
|
256
294
|
data: 'c'
|
|
257
295
|
signal: AbortSignal
|
|
296
|
+
response: 'data'
|
|
258
297
|
}>()
|
|
259
298
|
})
|
|
260
299
|
})
|
|
@@ -268,6 +307,7 @@ test('createServerFn where validator is optional if object is optional', () => {
|
|
|
268
307
|
context: undefined
|
|
269
308
|
data: 'c' | undefined
|
|
270
309
|
signal: AbortSignal
|
|
310
|
+
response: 'data'
|
|
271
311
|
}>()
|
|
272
312
|
})
|
|
273
313
|
|
|
@@ -276,13 +316,12 @@ test('createServerFn where validator is optional if object is optional', () => {
|
|
|
276
316
|
data?: 'c' | undefined
|
|
277
317
|
headers?: HeadersInit
|
|
278
318
|
type?: 'static' | 'dynamic'
|
|
279
|
-
fullResponse?: boolean
|
|
280
319
|
signal?: AbortSignal
|
|
281
320
|
}
|
|
282
321
|
| undefined
|
|
283
322
|
>()
|
|
284
323
|
|
|
285
|
-
expectTypeOf(
|
|
324
|
+
expectTypeOf<ReturnType<typeof fn>>().resolves.toEqualTypeOf<void>()
|
|
286
325
|
})
|
|
287
326
|
|
|
288
327
|
test('createServerFn where data is optional if there is no validator', () => {
|
|
@@ -292,6 +331,7 @@ test('createServerFn where data is optional if there is no validator', () => {
|
|
|
292
331
|
context: undefined
|
|
293
332
|
data: undefined
|
|
294
333
|
signal: AbortSignal
|
|
334
|
+
response: 'data'
|
|
295
335
|
}>()
|
|
296
336
|
})
|
|
297
337
|
|
|
@@ -300,13 +340,12 @@ test('createServerFn where data is optional if there is no validator', () => {
|
|
|
300
340
|
data?: undefined
|
|
301
341
|
headers?: HeadersInit
|
|
302
342
|
type?: 'static' | 'dynamic'
|
|
303
|
-
fullResponse?: boolean
|
|
304
343
|
signal?: AbortSignal
|
|
305
344
|
}
|
|
306
345
|
| undefined
|
|
307
346
|
>()
|
|
308
347
|
|
|
309
|
-
expectTypeOf(
|
|
348
|
+
expectTypeOf<ReturnType<typeof fn>>().resolves.toEqualTypeOf<void>()
|
|
310
349
|
})
|
|
311
350
|
|
|
312
351
|
test('createServerFn returns Date', () => {
|
|
@@ -388,3 +427,75 @@ test('createServerFn can validate FormData', () => {
|
|
|
388
427
|
>
|
|
389
428
|
>()
|
|
390
429
|
})
|
|
430
|
+
|
|
431
|
+
describe('response', () => {
|
|
432
|
+
describe('data', () => {
|
|
433
|
+
test(`response: 'data' is passed into handler without response being set`, () => {
|
|
434
|
+
createServerFn().handler((options) => {
|
|
435
|
+
expectTypeOf(options.response).toEqualTypeOf<'data'>()
|
|
436
|
+
})
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
test(`response: 'data' is passed into handler with explicit response: 'data'`, () => {
|
|
440
|
+
createServerFn({ response: 'data' }).handler((options) => {
|
|
441
|
+
expectTypeOf(options.response).toEqualTypeOf<'data'>()
|
|
442
|
+
})
|
|
443
|
+
})
|
|
444
|
+
})
|
|
445
|
+
describe('full', () => {
|
|
446
|
+
test(`response: 'full' is passed into handler`, () => {
|
|
447
|
+
createServerFn({ response: 'full' }).handler((options) => {
|
|
448
|
+
expectTypeOf(options.response).toEqualTypeOf<'full'>()
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
describe('raw', () => {
|
|
454
|
+
test(`response: 'raw' is passed into handler`, () => {
|
|
455
|
+
createServerFn({ response: 'raw' }).handler((options) => {
|
|
456
|
+
expectTypeOf(options.response).toEqualTypeOf<'raw'>()
|
|
457
|
+
return null
|
|
458
|
+
})
|
|
459
|
+
})
|
|
460
|
+
})
|
|
461
|
+
test(`client receives Response when Response is returned`, () => {
|
|
462
|
+
const fn = createServerFn({ response: 'raw' }).handler(() => {
|
|
463
|
+
return new Response('Hello World')
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
expectTypeOf(fn()).toEqualTypeOf<Promise<Response>>()
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
test(`client receives Response when ReadableStream is returned`, () => {
|
|
470
|
+
const fn = createServerFn({ response: 'raw' }).handler(() => {
|
|
471
|
+
return new ReadableStream()
|
|
472
|
+
})
|
|
473
|
+
|
|
474
|
+
expectTypeOf(fn()).toEqualTypeOf<Promise<Response>>()
|
|
475
|
+
})
|
|
476
|
+
|
|
477
|
+
test(`client receives Response when string is returned`, () => {
|
|
478
|
+
const fn = createServerFn({ response: 'raw' }).handler(() => {
|
|
479
|
+
return 'hello'
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
expectTypeOf(fn()).toEqualTypeOf<Promise<Response>>()
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
test('createServerFn can be used as a mutation function', () => {
|
|
487
|
+
const serverFn = createServerFn()
|
|
488
|
+
.validator((data: number) => data)
|
|
489
|
+
.handler(() => 'foo')
|
|
490
|
+
|
|
491
|
+
type MutationFunction<TData = unknown, TVariables = unknown> = (
|
|
492
|
+
variables: TVariables,
|
|
493
|
+
) => Promise<TData>
|
|
494
|
+
|
|
495
|
+
// simplifeid "clone" of @tansctack/react-query's useMutation
|
|
496
|
+
const useMutation = <TData, TVariables>(
|
|
497
|
+
fn: MutationFunction<TData, TVariables>,
|
|
498
|
+
) => {}
|
|
499
|
+
|
|
500
|
+
useMutation(serverFn)
|
|
501
|
+
})
|