@tanstack/react-start-client 1.114.8 → 1.114.9
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/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.tsx +1 -1
- package/src/tests/createServerFn.test-d.tsx +2 -488
- package/dist/cjs/createServerFn.cjs +0 -146
- package/dist/cjs/createServerFn.cjs.map +0 -1
- package/dist/cjs/createServerFn.d.cts +0 -6
- package/dist/esm/createServerFn.d.ts +0 -6
- package/dist/esm/createServerFn.js +0 -146
- package/dist/esm/createServerFn.js.map +0 -1
- package/src/createServerFn.ts +0 -279
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const startClientCore = require("@tanstack/start-client-core");
|
|
4
|
-
const createServerFn = require("./createServerFn.cjs");
|
|
5
4
|
const Meta = require("./Meta.cjs");
|
|
6
5
|
const Scripts = require("./Scripts.cjs");
|
|
7
6
|
const StartClient = require("./StartClient.cjs");
|
|
@@ -19,6 +18,10 @@ Object.defineProperty(exports, "createMiddleware", {
|
|
|
19
18
|
enumerable: true,
|
|
20
19
|
get: () => startClientCore.createMiddleware
|
|
21
20
|
});
|
|
21
|
+
Object.defineProperty(exports, "createServerFn", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: () => startClientCore.createServerFn
|
|
24
|
+
});
|
|
22
25
|
Object.defineProperty(exports, "globalMiddleware", {
|
|
23
26
|
enumerable: true,
|
|
24
27
|
get: () => startClientCore.globalMiddleware
|
|
@@ -43,7 +46,6 @@ Object.defineProperty(exports, "startSerializer", {
|
|
|
43
46
|
enumerable: true,
|
|
44
47
|
get: () => startClientCore.startSerializer
|
|
45
48
|
});
|
|
46
|
-
exports.createServerFn = createServerFn.createServerFn;
|
|
47
49
|
exports.Meta = Meta.Meta;
|
|
48
50
|
exports.Scripts = Scripts.Scripts;
|
|
49
51
|
exports.StartClient = StartClient.StartClient;
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ export { mergeHeaders } from '@tanstack/start-client-core';
|
|
|
2
2
|
export { startSerializer } from '@tanstack/start-client-core';
|
|
3
3
|
export { type DehydratedRouter, type ClientExtractedBaseEntry, type StartSsrGlobal, type ClientExtractedEntry, type SsrMatch, type ClientExtractedPromise, type ClientExtractedStream, type ResolvePromiseState, } from '@tanstack/start-client-core';
|
|
4
4
|
export { createIsomorphicFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from '@tanstack/start-client-core';
|
|
5
|
-
export { createServerFn } from '
|
|
5
|
+
export { createServerFn } from '@tanstack/start-client-core';
|
|
6
6
|
export { type ServerFn as FetchFn, type ServerFnCtx as FetchFnCtx, type CompiledFetcherFnOptions, type CompiledFetcherFn, type Fetcher, type RscStream, type FetcherData, type FetcherBaseOptions, type ServerFn, type ServerFnCtx, type ServerFnResponseType, } from '@tanstack/start-client-core';
|
|
7
7
|
export { type JsonResponse } from '@tanstack/start-client-core';
|
|
8
8
|
export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type MiddlewareServerFn, type AnyMiddleware, type MiddlewareOptions, type MiddlewareWithTypes, type MiddlewareValidator, type MiddlewareServer, type MiddlewareAfterClient, type MiddlewareAfterMiddleware, type MiddlewareAfterServer, type Middleware, type MiddlewareClientFnOptions, type MiddlewareClientFnResult, type MiddlewareClientNextFn, type ClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type AssignAllServerContext, type MiddlewareAfterValidator, type MiddlewareClientFn, type MiddlewareServerFnResult, type MiddlewareClient, type MiddlewareServerFnOptions, type MiddlewareServerNextFn, type ServerResultWithContext, } from '@tanstack/start-client-core';
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { mergeHeaders } from '@tanstack/start-client-core';
|
|
|
2
2
|
export { startSerializer } from '@tanstack/start-client-core';
|
|
3
3
|
export { type DehydratedRouter, type ClientExtractedBaseEntry, type StartSsrGlobal, type ClientExtractedEntry, type SsrMatch, type ClientExtractedPromise, type ClientExtractedStream, type ResolvePromiseState, } from '@tanstack/start-client-core';
|
|
4
4
|
export { createIsomorphicFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from '@tanstack/start-client-core';
|
|
5
|
-
export { createServerFn } from '
|
|
5
|
+
export { createServerFn } from '@tanstack/start-client-core';
|
|
6
6
|
export { type ServerFn as FetchFn, type ServerFnCtx as FetchFnCtx, type CompiledFetcherFnOptions, type CompiledFetcherFn, type Fetcher, type RscStream, type FetcherData, type FetcherBaseOptions, type ServerFn, type ServerFnCtx, type ServerFnResponseType, } from '@tanstack/start-client-core';
|
|
7
7
|
export { type JsonResponse } from '@tanstack/start-client-core';
|
|
8
8
|
export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type MiddlewareServerFn, type AnyMiddleware, type MiddlewareOptions, type MiddlewareWithTypes, type MiddlewareValidator, type MiddlewareServer, type MiddlewareAfterClient, type MiddlewareAfterMiddleware, type MiddlewareAfterServer, type Middleware, type MiddlewareClientFnOptions, type MiddlewareClientFnResult, type MiddlewareClientNextFn, type ClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type AssignAllServerContext, type MiddlewareAfterValidator, type MiddlewareClientFn, type MiddlewareServerFnResult, type MiddlewareClient, type MiddlewareServerFnOptions, type MiddlewareServerNextFn, type ServerResultWithContext, } from '@tanstack/start-client-core';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { clientOnly, createIsomorphicFn, createMiddleware, globalMiddleware, json, mergeHeaders, registerGlobalMiddleware, serverOnly, startSerializer } from "@tanstack/start-client-core";
|
|
2
|
-
import { createServerFn } from "./createServerFn.js";
|
|
1
|
+
import { clientOnly, createIsomorphicFn, createMiddleware, createServerFn, globalMiddleware, json, mergeHeaders, registerGlobalMiddleware, serverOnly, startSerializer } from "@tanstack/start-client-core";
|
|
3
2
|
import { Meta } from "./Meta.js";
|
|
4
3
|
import { Scripts } from "./Scripts.js";
|
|
5
4
|
import { StartClient } from "./StartClient.js";
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-start-client",
|
|
3
|
-
"version": "1.114.
|
|
3
|
+
"version": "1.114.9",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"vinxi": "^0.5.3",
|
|
55
55
|
"@tanstack/react-router": "^1.114.7",
|
|
56
56
|
"@tanstack/router-core": "^1.114.7",
|
|
57
|
-
"@tanstack/start-client-core": "^1.114.
|
|
57
|
+
"@tanstack/start-client-core": "^1.114.9"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@testing-library/react": "^16.2.0",
|
package/src/index.tsx
CHANGED
|
@@ -18,7 +18,7 @@ export {
|
|
|
18
18
|
type ClientOnlyFn,
|
|
19
19
|
type IsomorphicFnBase,
|
|
20
20
|
} from '@tanstack/start-client-core'
|
|
21
|
-
export { createServerFn } from '
|
|
21
|
+
export { createServerFn } from '@tanstack/start-client-core'
|
|
22
22
|
export {
|
|
23
23
|
type ServerFn as FetchFn,
|
|
24
24
|
type ServerFnCtx as FetchFnCtx,
|
|
@@ -1,360 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createServerFn } from '../createServerFn'
|
|
4
|
-
import type { Constrain, Validator } from '@tanstack/router-core'
|
|
5
|
-
|
|
6
|
-
test('createServerFn method with autocomplete', () => {
|
|
7
|
-
createServerFn().handler((options) => {
|
|
8
|
-
expectTypeOf(options.method).toEqualTypeOf<'GET' | 'POST'>()
|
|
9
|
-
})
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test('createServerFn without middleware', () => {
|
|
13
|
-
expectTypeOf(createServerFn()).toHaveProperty('handler')
|
|
14
|
-
expectTypeOf(createServerFn()).toHaveProperty('middleware')
|
|
15
|
-
expectTypeOf(createServerFn()).toHaveProperty('validator')
|
|
16
|
-
|
|
17
|
-
createServerFn({ method: 'GET' }).handler((options) => {
|
|
18
|
-
expectTypeOf(options).toEqualTypeOf<{
|
|
19
|
-
method: 'GET'
|
|
20
|
-
context: undefined
|
|
21
|
-
data: undefined
|
|
22
|
-
signal: AbortSignal
|
|
23
|
-
response: 'data'
|
|
24
|
-
}>()
|
|
25
|
-
})
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('createServerFn with validator', () => {
|
|
29
|
-
const fnAfterValidator = createServerFn({
|
|
30
|
-
method: 'GET',
|
|
31
|
-
}).validator((input: { input: string }) => ({
|
|
32
|
-
a: input.input,
|
|
33
|
-
}))
|
|
34
|
-
|
|
35
|
-
expectTypeOf(fnAfterValidator).toHaveProperty('handler')
|
|
36
|
-
expectTypeOf(fnAfterValidator).toHaveProperty('middleware')
|
|
37
|
-
expectTypeOf(fnAfterValidator).not.toHaveProperty('validator')
|
|
38
|
-
|
|
39
|
-
const fn = fnAfterValidator.handler((options) => {
|
|
40
|
-
expectTypeOf(options).toEqualTypeOf<{
|
|
41
|
-
method: 'GET'
|
|
42
|
-
context: undefined
|
|
43
|
-
data: {
|
|
44
|
-
a: string
|
|
45
|
-
}
|
|
46
|
-
signal: AbortSignal
|
|
47
|
-
response: 'data'
|
|
48
|
-
}>()
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
expectTypeOf(fn).parameter(0).toEqualTypeOf<{
|
|
52
|
-
data: { input: string }
|
|
53
|
-
headers?: HeadersInit
|
|
54
|
-
type?: 'static' | 'dynamic'
|
|
55
|
-
signal?: AbortSignal
|
|
56
|
-
}>()
|
|
57
|
-
|
|
58
|
-
expectTypeOf<ReturnType<typeof fn>>().resolves.toEqualTypeOf<void>()
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('createServerFn with middleware and context', () => {
|
|
62
|
-
const middleware1 = createMiddleware().server(({ next }) => {
|
|
63
|
-
return next({ context: { a: 'a' } as const })
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const middleware2 = createMiddleware().server(({ next }) => {
|
|
67
|
-
return next({ context: { b: 'b' } as const })
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
const middleware3 = createMiddleware()
|
|
71
|
-
.middleware([middleware1, middleware2])
|
|
72
|
-
.client(({ next }) => {
|
|
73
|
-
return next({ context: { c: 'c' } as const })
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
const middleware4 = createMiddleware()
|
|
77
|
-
.middleware([middleware3])
|
|
78
|
-
.client(({ context, next }) => {
|
|
79
|
-
return next({ sendContext: context })
|
|
80
|
-
})
|
|
81
|
-
.server(({ context, next }) => {
|
|
82
|
-
expectTypeOf(context).toEqualTypeOf<{
|
|
83
|
-
readonly a: 'a'
|
|
84
|
-
readonly b: 'b'
|
|
85
|
-
readonly c: 'c'
|
|
86
|
-
}>()
|
|
87
|
-
return next({ context: { d: 'd' } as const })
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const fnWithMiddleware = createServerFn({ method: 'GET' }).middleware([
|
|
91
|
-
middleware4,
|
|
92
|
-
])
|
|
93
|
-
|
|
94
|
-
expectTypeOf(fnWithMiddleware).toHaveProperty('handler')
|
|
95
|
-
expectTypeOf(fnWithMiddleware).toHaveProperty('validator')
|
|
96
|
-
expectTypeOf(fnWithMiddleware).not.toHaveProperty('middleware')
|
|
97
|
-
|
|
98
|
-
fnWithMiddleware.handler((options) => {
|
|
99
|
-
expectTypeOf(options).toEqualTypeOf<{
|
|
100
|
-
method: 'GET'
|
|
101
|
-
context: {
|
|
102
|
-
readonly a: 'a'
|
|
103
|
-
readonly b: 'b'
|
|
104
|
-
readonly c: 'c'
|
|
105
|
-
readonly d: 'd'
|
|
106
|
-
}
|
|
107
|
-
data: undefined
|
|
108
|
-
signal: AbortSignal
|
|
109
|
-
response: 'data'
|
|
110
|
-
}>()
|
|
111
|
-
})
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
describe('createServerFn with middleware and validator', () => {
|
|
115
|
-
const middleware1 = createMiddleware().validator(
|
|
116
|
-
(input: { readonly inputA: 'inputA' }) =>
|
|
117
|
-
({
|
|
118
|
-
outputA: 'outputA',
|
|
119
|
-
}) as const,
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
const middleware2 = createMiddleware().validator(
|
|
123
|
-
(input: { readonly inputB: 'inputB' }) =>
|
|
124
|
-
({
|
|
125
|
-
outputB: 'outputB',
|
|
126
|
-
}) as const,
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
const middleware3 = createMiddleware().middleware([middleware1, middleware2])
|
|
130
|
-
|
|
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
|
-
}>()
|
|
166
|
-
|
|
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
|
-
})
|
|
174
|
-
|
|
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
|
-
}>()
|
|
210
|
-
|
|
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
|
-
})
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
test('createServerFn overrides properties', () => {
|
|
224
|
-
const middleware1 = createMiddleware()
|
|
225
|
-
.validator(
|
|
226
|
-
() =>
|
|
227
|
-
({
|
|
228
|
-
input: 'a' as 'a' | 'b' | 'c',
|
|
229
|
-
}) as const,
|
|
230
|
-
)
|
|
231
|
-
.client(({ context, next }) => {
|
|
232
|
-
expectTypeOf(context).toEqualTypeOf<undefined>()
|
|
233
|
-
|
|
234
|
-
const newContext = { context: 'a' } as const
|
|
235
|
-
return next({ sendContext: newContext, context: newContext })
|
|
236
|
-
})
|
|
237
|
-
.server(({ data, context, next }) => {
|
|
238
|
-
expectTypeOf(data).toEqualTypeOf<{ readonly input: 'a' | 'b' | 'c' }>()
|
|
239
|
-
|
|
240
|
-
expectTypeOf(context).toEqualTypeOf<{
|
|
241
|
-
readonly context: 'a'
|
|
242
|
-
}>()
|
|
243
|
-
|
|
244
|
-
const newContext = { context: 'b' } as const
|
|
245
|
-
return next({ sendContext: newContext, context: newContext })
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
const middleware2 = createMiddleware()
|
|
249
|
-
.middleware([middleware1])
|
|
250
|
-
.validator(
|
|
251
|
-
() =>
|
|
252
|
-
({
|
|
253
|
-
input: 'b' as 'b' | 'c',
|
|
254
|
-
}) as const,
|
|
255
|
-
)
|
|
256
|
-
.client(({ context, next }) => {
|
|
257
|
-
expectTypeOf(context).toEqualTypeOf<{ readonly context: 'a' }>()
|
|
258
|
-
|
|
259
|
-
const newContext = { context: 'aa' } as const
|
|
260
|
-
|
|
261
|
-
return next({ sendContext: newContext, context: newContext })
|
|
262
|
-
})
|
|
263
|
-
.server(({ context, next }) => {
|
|
264
|
-
expectTypeOf(context).toEqualTypeOf<{ readonly context: 'aa' }>()
|
|
265
|
-
|
|
266
|
-
const newContext = { context: 'bb' } as const
|
|
267
|
-
|
|
268
|
-
return next({ sendContext: newContext, context: newContext })
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
createServerFn()
|
|
272
|
-
.middleware([middleware2])
|
|
273
|
-
.validator(
|
|
274
|
-
() =>
|
|
275
|
-
({
|
|
276
|
-
input: 'c',
|
|
277
|
-
}) as const,
|
|
278
|
-
)
|
|
279
|
-
.handler(({ data, context }) => {
|
|
280
|
-
expectTypeOf(data).toEqualTypeOf<{
|
|
281
|
-
readonly input: 'c'
|
|
282
|
-
}>()
|
|
283
|
-
expectTypeOf(context).toEqualTypeOf<{ readonly context: 'bb' }>()
|
|
284
|
-
})
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
test('createServerFn where validator is a primitive', () => {
|
|
288
|
-
createServerFn({ method: 'GET' })
|
|
289
|
-
.validator(() => 'c' as const)
|
|
290
|
-
.handler((options) => {
|
|
291
|
-
expectTypeOf(options).toEqualTypeOf<{
|
|
292
|
-
method: 'GET'
|
|
293
|
-
context: undefined
|
|
294
|
-
data: 'c'
|
|
295
|
-
signal: AbortSignal
|
|
296
|
-
response: 'data'
|
|
297
|
-
}>()
|
|
298
|
-
})
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
test('createServerFn where validator is optional if object is optional', () => {
|
|
302
|
-
const fn = createServerFn({ method: 'GET' })
|
|
303
|
-
.validator((input: 'c' | undefined) => input)
|
|
304
|
-
.handler((options) => {
|
|
305
|
-
expectTypeOf(options).toEqualTypeOf<{
|
|
306
|
-
method: 'GET'
|
|
307
|
-
context: undefined
|
|
308
|
-
data: 'c' | undefined
|
|
309
|
-
signal: AbortSignal
|
|
310
|
-
response: 'data'
|
|
311
|
-
}>()
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
expectTypeOf(fn).parameter(0).toEqualTypeOf<
|
|
315
|
-
| {
|
|
316
|
-
data?: 'c' | undefined
|
|
317
|
-
headers?: HeadersInit
|
|
318
|
-
type?: 'static' | 'dynamic'
|
|
319
|
-
signal?: AbortSignal
|
|
320
|
-
}
|
|
321
|
-
| undefined
|
|
322
|
-
>()
|
|
323
|
-
|
|
324
|
-
expectTypeOf<ReturnType<typeof fn>>().resolves.toEqualTypeOf<void>()
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
test('createServerFn where data is optional if there is no validator', () => {
|
|
328
|
-
const fn = createServerFn({ method: 'GET' }).handler((options) => {
|
|
329
|
-
expectTypeOf(options).toEqualTypeOf<{
|
|
330
|
-
method: 'GET'
|
|
331
|
-
context: undefined
|
|
332
|
-
data: undefined
|
|
333
|
-
signal: AbortSignal
|
|
334
|
-
response: 'data'
|
|
335
|
-
}>()
|
|
336
|
-
})
|
|
337
|
-
|
|
338
|
-
expectTypeOf(fn).parameter(0).toEqualTypeOf<
|
|
339
|
-
| {
|
|
340
|
-
data?: undefined
|
|
341
|
-
headers?: HeadersInit
|
|
342
|
-
type?: 'static' | 'dynamic'
|
|
343
|
-
signal?: AbortSignal
|
|
344
|
-
}
|
|
345
|
-
| undefined
|
|
346
|
-
>()
|
|
347
|
-
|
|
348
|
-
expectTypeOf<ReturnType<typeof fn>>().resolves.toEqualTypeOf<void>()
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
test('createServerFn returns Date', () => {
|
|
352
|
-
const fn = createServerFn().handler(() => ({
|
|
353
|
-
dates: [new Date(), new Date()] as const,
|
|
354
|
-
}))
|
|
355
|
-
|
|
356
|
-
expectTypeOf(fn()).toEqualTypeOf<Promise<{ dates: readonly [Date, Date] }>>()
|
|
357
|
-
})
|
|
1
|
+
import { expectTypeOf, test } from 'vitest'
|
|
2
|
+
import { createServerFn } from '@tanstack/start-client-core'
|
|
358
3
|
|
|
359
4
|
test('createServerFn returns RSC', () => {
|
|
360
5
|
const fn = createServerFn().handler(() => ({
|
|
@@ -368,134 +13,3 @@ test('createServerFn returns RSC', () => {
|
|
|
368
13
|
Promise<{ rscs: readonly [ReadableStream, ReadableStream] }>
|
|
369
14
|
>()
|
|
370
15
|
})
|
|
371
|
-
|
|
372
|
-
test('createServerFn returns undefined', () => {
|
|
373
|
-
const fn = createServerFn().handler(() => ({
|
|
374
|
-
nothing: undefined,
|
|
375
|
-
}))
|
|
376
|
-
|
|
377
|
-
expectTypeOf(fn()).toEqualTypeOf<Promise<{ nothing: undefined }>>()
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
test('createServerFn cannot return function', () => {
|
|
381
|
-
expectTypeOf(createServerFn().handler<{ func: () => 'func' }>)
|
|
382
|
-
.parameter(0)
|
|
383
|
-
.returns.toEqualTypeOf<
|
|
384
|
-
| { func: 'Function is not serializable' }
|
|
385
|
-
| Promise<{ func: 'Function is not serializable' }>
|
|
386
|
-
>()
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
test('createServerFn cannot validate function', () => {
|
|
390
|
-
const validator = createServerFn().validator<
|
|
391
|
-
(input: { func: () => 'string' }) => { output: 'string' }
|
|
392
|
-
>
|
|
393
|
-
|
|
394
|
-
expectTypeOf(validator)
|
|
395
|
-
.parameter(0)
|
|
396
|
-
.toEqualTypeOf<
|
|
397
|
-
Constrain<
|
|
398
|
-
(input: { func: () => 'string' }) => { output: 'string' },
|
|
399
|
-
Validator<{ func: 'Function is not serializable' }, any>
|
|
400
|
-
>
|
|
401
|
-
>()
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
test('createServerFn can validate Date', () => {
|
|
405
|
-
const validator = createServerFn().validator<
|
|
406
|
-
(input: Date) => { output: 'string' }
|
|
407
|
-
>
|
|
408
|
-
|
|
409
|
-
expectTypeOf(validator)
|
|
410
|
-
.parameter(0)
|
|
411
|
-
.toEqualTypeOf<
|
|
412
|
-
Constrain<(input: Date) => { output: 'string' }, Validator<Date, any>>
|
|
413
|
-
>()
|
|
414
|
-
})
|
|
415
|
-
|
|
416
|
-
test('createServerFn can validate FormData', () => {
|
|
417
|
-
const validator = createServerFn().validator<
|
|
418
|
-
(input: FormData) => { output: 'string' }
|
|
419
|
-
>
|
|
420
|
-
|
|
421
|
-
expectTypeOf(validator)
|
|
422
|
-
.parameter(0)
|
|
423
|
-
.toEqualTypeOf<
|
|
424
|
-
Constrain<
|
|
425
|
-
(input: FormData) => { output: 'string' },
|
|
426
|
-
Validator<FormData, any>
|
|
427
|
-
>
|
|
428
|
-
>()
|
|
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
|
-
})
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const routerCore = require("@tanstack/router-core");
|
|
4
|
-
const startClientCore = require("@tanstack/start-client-core");
|
|
5
|
-
const invariant = require("tiny-invariant");
|
|
6
|
-
function createServerFn(options, __opts) {
|
|
7
|
-
const resolvedOptions = __opts || options || {};
|
|
8
|
-
if (typeof resolvedOptions.method === "undefined") {
|
|
9
|
-
resolvedOptions.method = "GET";
|
|
10
|
-
}
|
|
11
|
-
return {
|
|
12
|
-
options: resolvedOptions,
|
|
13
|
-
middleware: (middleware) => {
|
|
14
|
-
return createServerFn(void 0, Object.assign(resolvedOptions, { middleware }));
|
|
15
|
-
},
|
|
16
|
-
validator: (validator) => {
|
|
17
|
-
return createServerFn(void 0, Object.assign(resolvedOptions, { validator }));
|
|
18
|
-
},
|
|
19
|
-
type: (type) => {
|
|
20
|
-
return createServerFn(void 0, Object.assign(resolvedOptions, { type }));
|
|
21
|
-
},
|
|
22
|
-
handler: (...args) => {
|
|
23
|
-
const [extractedFn, serverFn] = args;
|
|
24
|
-
Object.assign(resolvedOptions, {
|
|
25
|
-
...extractedFn,
|
|
26
|
-
extractedFn,
|
|
27
|
-
serverFn
|
|
28
|
-
});
|
|
29
|
-
const resolvedMiddleware = [
|
|
30
|
-
...resolvedOptions.middleware || [],
|
|
31
|
-
startClientCore.serverFnBaseToMiddleware(resolvedOptions)
|
|
32
|
-
];
|
|
33
|
-
return Object.assign(
|
|
34
|
-
async (opts) => {
|
|
35
|
-
return executeMiddleware(resolvedMiddleware, "client", {
|
|
36
|
-
...extractedFn,
|
|
37
|
-
...resolvedOptions,
|
|
38
|
-
data: opts == null ? void 0 : opts.data,
|
|
39
|
-
headers: opts == null ? void 0 : opts.headers,
|
|
40
|
-
signal: opts == null ? void 0 : opts.signal,
|
|
41
|
-
context: {}
|
|
42
|
-
}).then((d) => {
|
|
43
|
-
if (resolvedOptions.response === "full") {
|
|
44
|
-
return d;
|
|
45
|
-
}
|
|
46
|
-
if (d.error) throw d.error;
|
|
47
|
-
return d.result;
|
|
48
|
-
});
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
// This copies over the URL, function ID
|
|
52
|
-
...extractedFn,
|
|
53
|
-
// The extracted function on the server-side calls
|
|
54
|
-
// this function
|
|
55
|
-
__executeServer: async (opts_, signal) => {
|
|
56
|
-
var _a, _b;
|
|
57
|
-
const opts = opts_ instanceof FormData ? startClientCore.extractFormDataContext(opts_) : opts_;
|
|
58
|
-
opts.type = typeof resolvedOptions.type === "function" ? resolvedOptions.type(opts) : resolvedOptions.type;
|
|
59
|
-
const ctx = {
|
|
60
|
-
...extractedFn,
|
|
61
|
-
...opts,
|
|
62
|
-
signal
|
|
63
|
-
};
|
|
64
|
-
const run = () => executeMiddleware(resolvedMiddleware, "server", ctx).then(
|
|
65
|
-
(d) => ({
|
|
66
|
-
// Only send the result and sendContext back to the client
|
|
67
|
-
result: d.result,
|
|
68
|
-
error: d.error,
|
|
69
|
-
context: d.sendContext
|
|
70
|
-
})
|
|
71
|
-
);
|
|
72
|
-
if (ctx.type === "static") {
|
|
73
|
-
let response;
|
|
74
|
-
if ((_a = startClientCore.serverFnStaticCache) == null ? void 0 : _a.getItem) {
|
|
75
|
-
response = await startClientCore.serverFnStaticCache.getItem(ctx);
|
|
76
|
-
}
|
|
77
|
-
if (!response) {
|
|
78
|
-
response = await run().then((d) => {
|
|
79
|
-
return {
|
|
80
|
-
ctx: d,
|
|
81
|
-
error: null
|
|
82
|
-
};
|
|
83
|
-
}).catch((e) => {
|
|
84
|
-
return {
|
|
85
|
-
ctx: void 0,
|
|
86
|
-
error: e
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
if ((_b = startClientCore.serverFnStaticCache) == null ? void 0 : _b.setItem) {
|
|
90
|
-
await startClientCore.serverFnStaticCache.setItem(ctx, response);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
invariant(
|
|
94
|
-
response,
|
|
95
|
-
"No response from both server and static cache!"
|
|
96
|
-
);
|
|
97
|
-
if (response.error) {
|
|
98
|
-
throw response.error;
|
|
99
|
-
}
|
|
100
|
-
return response.ctx;
|
|
101
|
-
}
|
|
102
|
-
return run();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
async function executeMiddleware(middlewares, env, opts) {
|
|
110
|
-
const flattenedMiddlewares = startClientCore.flattenMiddlewares([
|
|
111
|
-
...startClientCore.globalMiddleware,
|
|
112
|
-
...middlewares
|
|
113
|
-
]);
|
|
114
|
-
const next = async (ctx) => {
|
|
115
|
-
const nextMiddleware = flattenedMiddlewares.shift();
|
|
116
|
-
if (!nextMiddleware) {
|
|
117
|
-
return ctx;
|
|
118
|
-
}
|
|
119
|
-
if (nextMiddleware.options.validator && (env === "client" ? nextMiddleware.options.validateClient : true)) {
|
|
120
|
-
ctx.data = await startClientCore.execValidator(nextMiddleware.options.validator, ctx.data);
|
|
121
|
-
}
|
|
122
|
-
const middlewareFn = env === "client" ? nextMiddleware.options.client : nextMiddleware.options.server;
|
|
123
|
-
if (middlewareFn) {
|
|
124
|
-
return startClientCore.applyMiddleware(middlewareFn, ctx, async (newCtx) => {
|
|
125
|
-
return next(newCtx).catch((error) => {
|
|
126
|
-
if (routerCore.isRedirect(error) || routerCore.isNotFound(error)) {
|
|
127
|
-
return {
|
|
128
|
-
...newCtx,
|
|
129
|
-
error
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
throw error;
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
return next(ctx);
|
|
137
|
-
};
|
|
138
|
-
return next({
|
|
139
|
-
...opts,
|
|
140
|
-
headers: opts.headers || {},
|
|
141
|
-
sendContext: opts.sendContext || {},
|
|
142
|
-
context: opts.context || {}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
exports.createServerFn = createServerFn;
|
|
146
|
-
//# sourceMappingURL=createServerFn.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createServerFn.cjs","sources":["../../src/createServerFn.ts"],"sourcesContent":["import { isNotFound, isRedirect } from '@tanstack/router-core'\nimport {\n applyMiddleware,\n execValidator,\n extractFormDataContext,\n flattenMiddlewares,\n globalMiddleware,\n serverFnBaseToMiddleware,\n serverFnStaticCache,\n} from '@tanstack/start-client-core'\nimport invariant from 'tiny-invariant'\nimport type {\n AnyMiddleware,\n CompiledFetcherFn,\n CompiledFetcherFnOptions,\n Method,\n MiddlewareFn,\n NextFn,\n ServerFn,\n ServerFnBaseOptions,\n ServerFnBuilder,\n ServerFnMiddlewareOptions,\n ServerFnMiddlewareResult,\n ServerFnResponseType,\n ServerFnType,\n StaticCachedResult,\n} from '@tanstack/start-client-core'\n\nexport function createServerFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType = 'data',\n TResponse = unknown,\n TMiddlewares = undefined,\n TValidator = undefined,\n>(\n options?: {\n method?: TMethod\n response?: TServerFnResponseType\n type?: ServerFnType\n },\n __opts?: ServerFnBaseOptions<\n TMethod,\n TServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >,\n): ServerFnBuilder<TMethod, TServerFnResponseType> {\n const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >\n\n if (typeof resolvedOptions.method === 'undefined') {\n resolvedOptions.method = 'GET' as TMethod\n }\n\n return {\n options: resolvedOptions as any,\n middleware: (middleware) => {\n return createServerFn<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >(undefined, Object.assign(resolvedOptions, { middleware })) as any\n },\n validator: (validator) => {\n return createServerFn<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >(undefined, Object.assign(resolvedOptions, { validator })) as any\n },\n type: (type) => {\n return createServerFn<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >(undefined, Object.assign(resolvedOptions, { type })) as any\n },\n handler: (...args) => {\n // This function signature changes due to AST transformations\n // in the babel plugin. We need to cast it to the correct\n // function signature post-transformation\n const [extractedFn, serverFn] = args as unknown as [\n CompiledFetcherFn<TResponse, TServerFnResponseType>,\n ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator,\n TResponse\n >,\n ]\n\n // Keep the original function around so we can use it\n // in the server environment\n Object.assign(resolvedOptions, {\n ...extractedFn,\n extractedFn,\n serverFn,\n })\n\n const resolvedMiddleware = [\n ...(resolvedOptions.middleware || []),\n serverFnBaseToMiddleware(resolvedOptions),\n ]\n\n // We want to make sure the new function has the same\n // properties as the original function\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return Object.assign(\n async (opts?: CompiledFetcherFnOptions) => {\n // Start by executing the client-side middleware chain\n return executeMiddleware(resolvedMiddleware, 'client', {\n ...extractedFn,\n ...resolvedOptions,\n data: opts?.data as any,\n headers: opts?.headers,\n signal: opts?.signal,\n context: {},\n }).then((d) => {\n if (resolvedOptions.response === 'full') {\n return d\n }\n if (d.error) throw d.error\n return d.result\n })\n },\n {\n // This copies over the URL, function ID\n ...extractedFn,\n // The extracted function on the server-side calls\n // this function\n __executeServer: async (opts_: any, signal: AbortSignal) => {\n const opts =\n opts_ instanceof FormData ? extractFormDataContext(opts_) : opts_\n\n opts.type =\n typeof resolvedOptions.type === 'function'\n ? resolvedOptions.type(opts)\n : resolvedOptions.type\n\n const ctx = {\n ...extractedFn,\n ...opts,\n signal,\n }\n\n const run = () =>\n executeMiddleware(resolvedMiddleware, 'server', ctx).then(\n (d) => ({\n // Only send the result and sendContext back to the client\n result: d.result,\n error: d.error,\n context: d.sendContext,\n }),\n )\n\n if (ctx.type === 'static') {\n let response: StaticCachedResult | undefined\n\n // If we can get the cached item, try to get it\n if (serverFnStaticCache?.getItem) {\n // If this throws, it's okay to let it bubble up\n response = await serverFnStaticCache.getItem(ctx)\n }\n\n if (!response) {\n // If there's no cached item, execute the server function\n response = await run()\n .then((d) => {\n return {\n ctx: d,\n error: null,\n }\n })\n .catch((e) => {\n return {\n ctx: undefined,\n error: e,\n }\n })\n\n if (serverFnStaticCache?.setItem) {\n await serverFnStaticCache.setItem(ctx, response)\n }\n }\n\n invariant(\n response,\n 'No response from both server and static cache!',\n )\n\n if (response.error) {\n throw response.error\n }\n\n return response.ctx\n }\n\n return run()\n },\n },\n ) as any\n },\n }\n}\n\nasync function executeMiddleware(\n middlewares: Array<AnyMiddleware>,\n env: 'client' | 'server',\n opts: ServerFnMiddlewareOptions,\n): Promise<ServerFnMiddlewareResult> {\n const flattenedMiddlewares = flattenMiddlewares([\n ...globalMiddleware,\n ...middlewares,\n ])\n\n const next: NextFn = async (ctx) => {\n // Get the next middleware\n const nextMiddleware = flattenedMiddlewares.shift()\n\n // If there are no more middlewares, return the context\n if (!nextMiddleware) {\n return ctx\n }\n\n if (\n nextMiddleware.options.validator &&\n (env === 'client' ? nextMiddleware.options.validateClient : true)\n ) {\n // Execute the middleware's input function\n ctx.data = await execValidator(nextMiddleware.options.validator, ctx.data)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n const middlewareFn = (\n env === 'client'\n ? nextMiddleware.options.client\n : nextMiddleware.options.server\n ) as MiddlewareFn | undefined\n\n if (middlewareFn) {\n // Execute the middleware\n return applyMiddleware(middlewareFn, ctx, async (newCtx) => {\n return next(newCtx).catch((error: any) => {\n if (isRedirect(error) || isNotFound(error)) {\n return {\n ...newCtx,\n error,\n }\n }\n\n throw error\n })\n })\n }\n\n return next(ctx)\n }\n\n // Start the middleware chain\n return next({\n ...opts,\n headers: opts.headers || {},\n sendContext: opts.sendContext || {},\n context: opts.context || {},\n })\n}\n"],"names":["serverFnBaseToMiddleware","extractFormDataContext","serverFnStaticCache","flattenMiddlewares","globalMiddleware","execValidator","applyMiddleware","isRedirect","isNotFound"],"mappings":"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"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { Method, ServerFnBaseOptions, ServerFnBuilder, ServerFnResponseType, ServerFnType } from '@tanstack/start-client-core';
|
|
2
|
-
export declare function createServerFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType = 'data', TResponse = unknown, TMiddlewares = undefined, TValidator = undefined>(options?: {
|
|
3
|
-
method?: TMethod;
|
|
4
|
-
response?: TServerFnResponseType;
|
|
5
|
-
type?: ServerFnType;
|
|
6
|
-
}, __opts?: ServerFnBaseOptions<TMethod, TServerFnResponseType, TResponse, TMiddlewares, TValidator>): ServerFnBuilder<TMethod, TServerFnResponseType>;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { Method, ServerFnBaseOptions, ServerFnBuilder, ServerFnResponseType, ServerFnType } from '@tanstack/start-client-core';
|
|
2
|
-
export declare function createServerFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType = 'data', TResponse = unknown, TMiddlewares = undefined, TValidator = undefined>(options?: {
|
|
3
|
-
method?: TMethod;
|
|
4
|
-
response?: TServerFnResponseType;
|
|
5
|
-
type?: ServerFnType;
|
|
6
|
-
}, __opts?: ServerFnBaseOptions<TMethod, TServerFnResponseType, TResponse, TMiddlewares, TValidator>): ServerFnBuilder<TMethod, TServerFnResponseType>;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { isRedirect, isNotFound } from "@tanstack/router-core";
|
|
2
|
-
import { serverFnBaseToMiddleware, extractFormDataContext, serverFnStaticCache, flattenMiddlewares, globalMiddleware, execValidator, applyMiddleware } from "@tanstack/start-client-core";
|
|
3
|
-
import invariant from "tiny-invariant";
|
|
4
|
-
function createServerFn(options, __opts) {
|
|
5
|
-
const resolvedOptions = __opts || options || {};
|
|
6
|
-
if (typeof resolvedOptions.method === "undefined") {
|
|
7
|
-
resolvedOptions.method = "GET";
|
|
8
|
-
}
|
|
9
|
-
return {
|
|
10
|
-
options: resolvedOptions,
|
|
11
|
-
middleware: (middleware) => {
|
|
12
|
-
return createServerFn(void 0, Object.assign(resolvedOptions, { middleware }));
|
|
13
|
-
},
|
|
14
|
-
validator: (validator) => {
|
|
15
|
-
return createServerFn(void 0, Object.assign(resolvedOptions, { validator }));
|
|
16
|
-
},
|
|
17
|
-
type: (type) => {
|
|
18
|
-
return createServerFn(void 0, Object.assign(resolvedOptions, { type }));
|
|
19
|
-
},
|
|
20
|
-
handler: (...args) => {
|
|
21
|
-
const [extractedFn, serverFn] = args;
|
|
22
|
-
Object.assign(resolvedOptions, {
|
|
23
|
-
...extractedFn,
|
|
24
|
-
extractedFn,
|
|
25
|
-
serverFn
|
|
26
|
-
});
|
|
27
|
-
const resolvedMiddleware = [
|
|
28
|
-
...resolvedOptions.middleware || [],
|
|
29
|
-
serverFnBaseToMiddleware(resolvedOptions)
|
|
30
|
-
];
|
|
31
|
-
return Object.assign(
|
|
32
|
-
async (opts) => {
|
|
33
|
-
return executeMiddleware(resolvedMiddleware, "client", {
|
|
34
|
-
...extractedFn,
|
|
35
|
-
...resolvedOptions,
|
|
36
|
-
data: opts == null ? void 0 : opts.data,
|
|
37
|
-
headers: opts == null ? void 0 : opts.headers,
|
|
38
|
-
signal: opts == null ? void 0 : opts.signal,
|
|
39
|
-
context: {}
|
|
40
|
-
}).then((d) => {
|
|
41
|
-
if (resolvedOptions.response === "full") {
|
|
42
|
-
return d;
|
|
43
|
-
}
|
|
44
|
-
if (d.error) throw d.error;
|
|
45
|
-
return d.result;
|
|
46
|
-
});
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
// This copies over the URL, function ID
|
|
50
|
-
...extractedFn,
|
|
51
|
-
// The extracted function on the server-side calls
|
|
52
|
-
// this function
|
|
53
|
-
__executeServer: async (opts_, signal) => {
|
|
54
|
-
var _a, _b;
|
|
55
|
-
const opts = opts_ instanceof FormData ? extractFormDataContext(opts_) : opts_;
|
|
56
|
-
opts.type = typeof resolvedOptions.type === "function" ? resolvedOptions.type(opts) : resolvedOptions.type;
|
|
57
|
-
const ctx = {
|
|
58
|
-
...extractedFn,
|
|
59
|
-
...opts,
|
|
60
|
-
signal
|
|
61
|
-
};
|
|
62
|
-
const run = () => executeMiddleware(resolvedMiddleware, "server", ctx).then(
|
|
63
|
-
(d) => ({
|
|
64
|
-
// Only send the result and sendContext back to the client
|
|
65
|
-
result: d.result,
|
|
66
|
-
error: d.error,
|
|
67
|
-
context: d.sendContext
|
|
68
|
-
})
|
|
69
|
-
);
|
|
70
|
-
if (ctx.type === "static") {
|
|
71
|
-
let response;
|
|
72
|
-
if ((_a = serverFnStaticCache) == null ? void 0 : _a.getItem) {
|
|
73
|
-
response = await serverFnStaticCache.getItem(ctx);
|
|
74
|
-
}
|
|
75
|
-
if (!response) {
|
|
76
|
-
response = await run().then((d) => {
|
|
77
|
-
return {
|
|
78
|
-
ctx: d,
|
|
79
|
-
error: null
|
|
80
|
-
};
|
|
81
|
-
}).catch((e) => {
|
|
82
|
-
return {
|
|
83
|
-
ctx: void 0,
|
|
84
|
-
error: e
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
if ((_b = serverFnStaticCache) == null ? void 0 : _b.setItem) {
|
|
88
|
-
await serverFnStaticCache.setItem(ctx, response);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
invariant(
|
|
92
|
-
response,
|
|
93
|
-
"No response from both server and static cache!"
|
|
94
|
-
);
|
|
95
|
-
if (response.error) {
|
|
96
|
-
throw response.error;
|
|
97
|
-
}
|
|
98
|
-
return response.ctx;
|
|
99
|
-
}
|
|
100
|
-
return run();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
async function executeMiddleware(middlewares, env, opts) {
|
|
108
|
-
const flattenedMiddlewares = flattenMiddlewares([
|
|
109
|
-
...globalMiddleware,
|
|
110
|
-
...middlewares
|
|
111
|
-
]);
|
|
112
|
-
const next = async (ctx) => {
|
|
113
|
-
const nextMiddleware = flattenedMiddlewares.shift();
|
|
114
|
-
if (!nextMiddleware) {
|
|
115
|
-
return ctx;
|
|
116
|
-
}
|
|
117
|
-
if (nextMiddleware.options.validator && (env === "client" ? nextMiddleware.options.validateClient : true)) {
|
|
118
|
-
ctx.data = await execValidator(nextMiddleware.options.validator, ctx.data);
|
|
119
|
-
}
|
|
120
|
-
const middlewareFn = env === "client" ? nextMiddleware.options.client : nextMiddleware.options.server;
|
|
121
|
-
if (middlewareFn) {
|
|
122
|
-
return applyMiddleware(middlewareFn, ctx, async (newCtx) => {
|
|
123
|
-
return next(newCtx).catch((error) => {
|
|
124
|
-
if (isRedirect(error) || isNotFound(error)) {
|
|
125
|
-
return {
|
|
126
|
-
...newCtx,
|
|
127
|
-
error
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
throw error;
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
return next(ctx);
|
|
135
|
-
};
|
|
136
|
-
return next({
|
|
137
|
-
...opts,
|
|
138
|
-
headers: opts.headers || {},
|
|
139
|
-
sendContext: opts.sendContext || {},
|
|
140
|
-
context: opts.context || {}
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
export {
|
|
144
|
-
createServerFn
|
|
145
|
-
};
|
|
146
|
-
//# sourceMappingURL=createServerFn.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createServerFn.js","sources":["../../src/createServerFn.ts"],"sourcesContent":["import { isNotFound, isRedirect } from '@tanstack/router-core'\nimport {\n applyMiddleware,\n execValidator,\n extractFormDataContext,\n flattenMiddlewares,\n globalMiddleware,\n serverFnBaseToMiddleware,\n serverFnStaticCache,\n} from '@tanstack/start-client-core'\nimport invariant from 'tiny-invariant'\nimport type {\n AnyMiddleware,\n CompiledFetcherFn,\n CompiledFetcherFnOptions,\n Method,\n MiddlewareFn,\n NextFn,\n ServerFn,\n ServerFnBaseOptions,\n ServerFnBuilder,\n ServerFnMiddlewareOptions,\n ServerFnMiddlewareResult,\n ServerFnResponseType,\n ServerFnType,\n StaticCachedResult,\n} from '@tanstack/start-client-core'\n\nexport function createServerFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType = 'data',\n TResponse = unknown,\n TMiddlewares = undefined,\n TValidator = undefined,\n>(\n options?: {\n method?: TMethod\n response?: TServerFnResponseType\n type?: ServerFnType\n },\n __opts?: ServerFnBaseOptions<\n TMethod,\n TServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >,\n): ServerFnBuilder<TMethod, TServerFnResponseType> {\n const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >\n\n if (typeof resolvedOptions.method === 'undefined') {\n resolvedOptions.method = 'GET' as TMethod\n }\n\n return {\n options: resolvedOptions as any,\n middleware: (middleware) => {\n return createServerFn<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >(undefined, Object.assign(resolvedOptions, { middleware })) as any\n },\n validator: (validator) => {\n return createServerFn<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >(undefined, Object.assign(resolvedOptions, { validator })) as any\n },\n type: (type) => {\n return createServerFn<\n TMethod,\n ServerFnResponseType,\n TResponse,\n TMiddlewares,\n TValidator\n >(undefined, Object.assign(resolvedOptions, { type })) as any\n },\n handler: (...args) => {\n // This function signature changes due to AST transformations\n // in the babel plugin. We need to cast it to the correct\n // function signature post-transformation\n const [extractedFn, serverFn] = args as unknown as [\n CompiledFetcherFn<TResponse, TServerFnResponseType>,\n ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator,\n TResponse\n >,\n ]\n\n // Keep the original function around so we can use it\n // in the server environment\n Object.assign(resolvedOptions, {\n ...extractedFn,\n extractedFn,\n serverFn,\n })\n\n const resolvedMiddleware = [\n ...(resolvedOptions.middleware || []),\n serverFnBaseToMiddleware(resolvedOptions),\n ]\n\n // We want to make sure the new function has the same\n // properties as the original function\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return Object.assign(\n async (opts?: CompiledFetcherFnOptions) => {\n // Start by executing the client-side middleware chain\n return executeMiddleware(resolvedMiddleware, 'client', {\n ...extractedFn,\n ...resolvedOptions,\n data: opts?.data as any,\n headers: opts?.headers,\n signal: opts?.signal,\n context: {},\n }).then((d) => {\n if (resolvedOptions.response === 'full') {\n return d\n }\n if (d.error) throw d.error\n return d.result\n })\n },\n {\n // This copies over the URL, function ID\n ...extractedFn,\n // The extracted function on the server-side calls\n // this function\n __executeServer: async (opts_: any, signal: AbortSignal) => {\n const opts =\n opts_ instanceof FormData ? extractFormDataContext(opts_) : opts_\n\n opts.type =\n typeof resolvedOptions.type === 'function'\n ? resolvedOptions.type(opts)\n : resolvedOptions.type\n\n const ctx = {\n ...extractedFn,\n ...opts,\n signal,\n }\n\n const run = () =>\n executeMiddleware(resolvedMiddleware, 'server', ctx).then(\n (d) => ({\n // Only send the result and sendContext back to the client\n result: d.result,\n error: d.error,\n context: d.sendContext,\n }),\n )\n\n if (ctx.type === 'static') {\n let response: StaticCachedResult | undefined\n\n // If we can get the cached item, try to get it\n if (serverFnStaticCache?.getItem) {\n // If this throws, it's okay to let it bubble up\n response = await serverFnStaticCache.getItem(ctx)\n }\n\n if (!response) {\n // If there's no cached item, execute the server function\n response = await run()\n .then((d) => {\n return {\n ctx: d,\n error: null,\n }\n })\n .catch((e) => {\n return {\n ctx: undefined,\n error: e,\n }\n })\n\n if (serverFnStaticCache?.setItem) {\n await serverFnStaticCache.setItem(ctx, response)\n }\n }\n\n invariant(\n response,\n 'No response from both server and static cache!',\n )\n\n if (response.error) {\n throw response.error\n }\n\n return response.ctx\n }\n\n return run()\n },\n },\n ) as any\n },\n }\n}\n\nasync function executeMiddleware(\n middlewares: Array<AnyMiddleware>,\n env: 'client' | 'server',\n opts: ServerFnMiddlewareOptions,\n): Promise<ServerFnMiddlewareResult> {\n const flattenedMiddlewares = flattenMiddlewares([\n ...globalMiddleware,\n ...middlewares,\n ])\n\n const next: NextFn = async (ctx) => {\n // Get the next middleware\n const nextMiddleware = flattenedMiddlewares.shift()\n\n // If there are no more middlewares, return the context\n if (!nextMiddleware) {\n return ctx\n }\n\n if (\n nextMiddleware.options.validator &&\n (env === 'client' ? nextMiddleware.options.validateClient : true)\n ) {\n // Execute the middleware's input function\n ctx.data = await execValidator(nextMiddleware.options.validator, ctx.data)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n const middlewareFn = (\n env === 'client'\n ? nextMiddleware.options.client\n : nextMiddleware.options.server\n ) as MiddlewareFn | undefined\n\n if (middlewareFn) {\n // Execute the middleware\n return applyMiddleware(middlewareFn, ctx, async (newCtx) => {\n return next(newCtx).catch((error: any) => {\n if (isRedirect(error) || isNotFound(error)) {\n return {\n ...newCtx,\n error,\n }\n }\n\n throw error\n })\n })\n }\n\n return next(ctx)\n }\n\n // Start the middleware chain\n return next({\n ...opts,\n headers: opts.headers || {},\n sendContext: opts.sendContext || {},\n context: opts.context || {},\n })\n}\n"],"names":[],"mappings":"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"}
|
package/src/createServerFn.ts
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { isNotFound, isRedirect } from '@tanstack/router-core'
|
|
2
|
-
import {
|
|
3
|
-
applyMiddleware,
|
|
4
|
-
execValidator,
|
|
5
|
-
extractFormDataContext,
|
|
6
|
-
flattenMiddlewares,
|
|
7
|
-
globalMiddleware,
|
|
8
|
-
serverFnBaseToMiddleware,
|
|
9
|
-
serverFnStaticCache,
|
|
10
|
-
} from '@tanstack/start-client-core'
|
|
11
|
-
import invariant from 'tiny-invariant'
|
|
12
|
-
import type {
|
|
13
|
-
AnyMiddleware,
|
|
14
|
-
CompiledFetcherFn,
|
|
15
|
-
CompiledFetcherFnOptions,
|
|
16
|
-
Method,
|
|
17
|
-
MiddlewareFn,
|
|
18
|
-
NextFn,
|
|
19
|
-
ServerFn,
|
|
20
|
-
ServerFnBaseOptions,
|
|
21
|
-
ServerFnBuilder,
|
|
22
|
-
ServerFnMiddlewareOptions,
|
|
23
|
-
ServerFnMiddlewareResult,
|
|
24
|
-
ServerFnResponseType,
|
|
25
|
-
ServerFnType,
|
|
26
|
-
StaticCachedResult,
|
|
27
|
-
} from '@tanstack/start-client-core'
|
|
28
|
-
|
|
29
|
-
export function createServerFn<
|
|
30
|
-
TMethod extends Method,
|
|
31
|
-
TServerFnResponseType extends ServerFnResponseType = 'data',
|
|
32
|
-
TResponse = unknown,
|
|
33
|
-
TMiddlewares = undefined,
|
|
34
|
-
TValidator = undefined,
|
|
35
|
-
>(
|
|
36
|
-
options?: {
|
|
37
|
-
method?: TMethod
|
|
38
|
-
response?: TServerFnResponseType
|
|
39
|
-
type?: ServerFnType
|
|
40
|
-
},
|
|
41
|
-
__opts?: ServerFnBaseOptions<
|
|
42
|
-
TMethod,
|
|
43
|
-
TServerFnResponseType,
|
|
44
|
-
TResponse,
|
|
45
|
-
TMiddlewares,
|
|
46
|
-
TValidator
|
|
47
|
-
>,
|
|
48
|
-
): ServerFnBuilder<TMethod, TServerFnResponseType> {
|
|
49
|
-
const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<
|
|
50
|
-
TMethod,
|
|
51
|
-
ServerFnResponseType,
|
|
52
|
-
TResponse,
|
|
53
|
-
TMiddlewares,
|
|
54
|
-
TValidator
|
|
55
|
-
>
|
|
56
|
-
|
|
57
|
-
if (typeof resolvedOptions.method === 'undefined') {
|
|
58
|
-
resolvedOptions.method = 'GET' as TMethod
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
options: resolvedOptions as any,
|
|
63
|
-
middleware: (middleware) => {
|
|
64
|
-
return createServerFn<
|
|
65
|
-
TMethod,
|
|
66
|
-
ServerFnResponseType,
|
|
67
|
-
TResponse,
|
|
68
|
-
TMiddlewares,
|
|
69
|
-
TValidator
|
|
70
|
-
>(undefined, Object.assign(resolvedOptions, { middleware })) as any
|
|
71
|
-
},
|
|
72
|
-
validator: (validator) => {
|
|
73
|
-
return createServerFn<
|
|
74
|
-
TMethod,
|
|
75
|
-
ServerFnResponseType,
|
|
76
|
-
TResponse,
|
|
77
|
-
TMiddlewares,
|
|
78
|
-
TValidator
|
|
79
|
-
>(undefined, Object.assign(resolvedOptions, { validator })) as any
|
|
80
|
-
},
|
|
81
|
-
type: (type) => {
|
|
82
|
-
return createServerFn<
|
|
83
|
-
TMethod,
|
|
84
|
-
ServerFnResponseType,
|
|
85
|
-
TResponse,
|
|
86
|
-
TMiddlewares,
|
|
87
|
-
TValidator
|
|
88
|
-
>(undefined, Object.assign(resolvedOptions, { type })) as any
|
|
89
|
-
},
|
|
90
|
-
handler: (...args) => {
|
|
91
|
-
// This function signature changes due to AST transformations
|
|
92
|
-
// in the babel plugin. We need to cast it to the correct
|
|
93
|
-
// function signature post-transformation
|
|
94
|
-
const [extractedFn, serverFn] = args as unknown as [
|
|
95
|
-
CompiledFetcherFn<TResponse, TServerFnResponseType>,
|
|
96
|
-
ServerFn<
|
|
97
|
-
TMethod,
|
|
98
|
-
TServerFnResponseType,
|
|
99
|
-
TMiddlewares,
|
|
100
|
-
TValidator,
|
|
101
|
-
TResponse
|
|
102
|
-
>,
|
|
103
|
-
]
|
|
104
|
-
|
|
105
|
-
// Keep the original function around so we can use it
|
|
106
|
-
// in the server environment
|
|
107
|
-
Object.assign(resolvedOptions, {
|
|
108
|
-
...extractedFn,
|
|
109
|
-
extractedFn,
|
|
110
|
-
serverFn,
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
const resolvedMiddleware = [
|
|
114
|
-
...(resolvedOptions.middleware || []),
|
|
115
|
-
serverFnBaseToMiddleware(resolvedOptions),
|
|
116
|
-
]
|
|
117
|
-
|
|
118
|
-
// We want to make sure the new function has the same
|
|
119
|
-
// properties as the original function
|
|
120
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
121
|
-
return Object.assign(
|
|
122
|
-
async (opts?: CompiledFetcherFnOptions) => {
|
|
123
|
-
// Start by executing the client-side middleware chain
|
|
124
|
-
return executeMiddleware(resolvedMiddleware, 'client', {
|
|
125
|
-
...extractedFn,
|
|
126
|
-
...resolvedOptions,
|
|
127
|
-
data: opts?.data as any,
|
|
128
|
-
headers: opts?.headers,
|
|
129
|
-
signal: opts?.signal,
|
|
130
|
-
context: {},
|
|
131
|
-
}).then((d) => {
|
|
132
|
-
if (resolvedOptions.response === 'full') {
|
|
133
|
-
return d
|
|
134
|
-
}
|
|
135
|
-
if (d.error) throw d.error
|
|
136
|
-
return d.result
|
|
137
|
-
})
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
// This copies over the URL, function ID
|
|
141
|
-
...extractedFn,
|
|
142
|
-
// The extracted function on the server-side calls
|
|
143
|
-
// this function
|
|
144
|
-
__executeServer: async (opts_: any, signal: AbortSignal) => {
|
|
145
|
-
const opts =
|
|
146
|
-
opts_ instanceof FormData ? extractFormDataContext(opts_) : opts_
|
|
147
|
-
|
|
148
|
-
opts.type =
|
|
149
|
-
typeof resolvedOptions.type === 'function'
|
|
150
|
-
? resolvedOptions.type(opts)
|
|
151
|
-
: resolvedOptions.type
|
|
152
|
-
|
|
153
|
-
const ctx = {
|
|
154
|
-
...extractedFn,
|
|
155
|
-
...opts,
|
|
156
|
-
signal,
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const run = () =>
|
|
160
|
-
executeMiddleware(resolvedMiddleware, 'server', ctx).then(
|
|
161
|
-
(d) => ({
|
|
162
|
-
// Only send the result and sendContext back to the client
|
|
163
|
-
result: d.result,
|
|
164
|
-
error: d.error,
|
|
165
|
-
context: d.sendContext,
|
|
166
|
-
}),
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
if (ctx.type === 'static') {
|
|
170
|
-
let response: StaticCachedResult | undefined
|
|
171
|
-
|
|
172
|
-
// If we can get the cached item, try to get it
|
|
173
|
-
if (serverFnStaticCache?.getItem) {
|
|
174
|
-
// If this throws, it's okay to let it bubble up
|
|
175
|
-
response = await serverFnStaticCache.getItem(ctx)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (!response) {
|
|
179
|
-
// If there's no cached item, execute the server function
|
|
180
|
-
response = await run()
|
|
181
|
-
.then((d) => {
|
|
182
|
-
return {
|
|
183
|
-
ctx: d,
|
|
184
|
-
error: null,
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
|
-
.catch((e) => {
|
|
188
|
-
return {
|
|
189
|
-
ctx: undefined,
|
|
190
|
-
error: e,
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
if (serverFnStaticCache?.setItem) {
|
|
195
|
-
await serverFnStaticCache.setItem(ctx, response)
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
invariant(
|
|
200
|
-
response,
|
|
201
|
-
'No response from both server and static cache!',
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
if (response.error) {
|
|
205
|
-
throw response.error
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return response.ctx
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return run()
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
) as any
|
|
215
|
-
},
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function executeMiddleware(
|
|
220
|
-
middlewares: Array<AnyMiddleware>,
|
|
221
|
-
env: 'client' | 'server',
|
|
222
|
-
opts: ServerFnMiddlewareOptions,
|
|
223
|
-
): Promise<ServerFnMiddlewareResult> {
|
|
224
|
-
const flattenedMiddlewares = flattenMiddlewares([
|
|
225
|
-
...globalMiddleware,
|
|
226
|
-
...middlewares,
|
|
227
|
-
])
|
|
228
|
-
|
|
229
|
-
const next: NextFn = async (ctx) => {
|
|
230
|
-
// Get the next middleware
|
|
231
|
-
const nextMiddleware = flattenedMiddlewares.shift()
|
|
232
|
-
|
|
233
|
-
// If there are no more middlewares, return the context
|
|
234
|
-
if (!nextMiddleware) {
|
|
235
|
-
return ctx
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (
|
|
239
|
-
nextMiddleware.options.validator &&
|
|
240
|
-
(env === 'client' ? nextMiddleware.options.validateClient : true)
|
|
241
|
-
) {
|
|
242
|
-
// Execute the middleware's input function
|
|
243
|
-
ctx.data = await execValidator(nextMiddleware.options.validator, ctx.data)
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
247
|
-
const middlewareFn = (
|
|
248
|
-
env === 'client'
|
|
249
|
-
? nextMiddleware.options.client
|
|
250
|
-
: nextMiddleware.options.server
|
|
251
|
-
) as MiddlewareFn | undefined
|
|
252
|
-
|
|
253
|
-
if (middlewareFn) {
|
|
254
|
-
// Execute the middleware
|
|
255
|
-
return applyMiddleware(middlewareFn, ctx, async (newCtx) => {
|
|
256
|
-
return next(newCtx).catch((error: any) => {
|
|
257
|
-
if (isRedirect(error) || isNotFound(error)) {
|
|
258
|
-
return {
|
|
259
|
-
...newCtx,
|
|
260
|
-
error,
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
throw error
|
|
265
|
-
})
|
|
266
|
-
})
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return next(ctx)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Start the middleware chain
|
|
273
|
-
return next({
|
|
274
|
-
...opts,
|
|
275
|
-
headers: opts.headers || {},
|
|
276
|
-
sendContext: opts.sendContext || {},
|
|
277
|
-
context: opts.context || {},
|
|
278
|
-
})
|
|
279
|
-
}
|