@tanstack/start-plugin-core 1.132.0-alpha.9 → 1.132.0
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/esm/constants.d.ts +2 -1
- package/dist/esm/constants.js +3 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/compiler.d.ts +8 -5
- package/dist/esm/create-server-fn-plugin/compiler.js +74 -46
- package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.d.ts +5 -0
- package/dist/esm/{start-compiler-plugin/middleware.js → create-server-fn-plugin/handleCreateMiddleware.js} +11 -11
- package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.js.map +1 -0
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js +8 -8
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/plugin.d.ts +1 -1
- package/dist/esm/create-server-fn-plugin/plugin.js +22 -7
- package/dist/esm/create-server-fn-plugin/plugin.js.map +1 -1
- package/dist/esm/dev-server-plugin/plugin.d.ts +4 -2
- package/dist/esm/dev-server-plugin/plugin.js +6 -2
- package/dist/esm/dev-server-plugin/plugin.js.map +1 -1
- package/dist/esm/plugin.d.ts +12 -6
- package/dist/esm/plugin.js +54 -65
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/resolve-entries.d.ts +0 -1
- package/dist/esm/resolve-entries.js +1 -1
- package/dist/esm/resolve-entries.js.map +1 -1
- package/dist/esm/schema.d.ts +375 -308
- package/dist/esm/schema.js +23 -11
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/start-compiler-plugin/compilers.js +17 -49
- package/dist/esm/start-compiler-plugin/compilers.js.map +1 -1
- package/dist/esm/start-compiler-plugin/constants.d.ts +1 -1
- package/dist/esm/start-compiler-plugin/constants.js +1 -5
- package/dist/esm/start-compiler-plugin/constants.js.map +1 -1
- package/dist/esm/start-router-plugin/constants.d.ts +1 -0
- package/dist/esm/start-router-plugin/constants.js +5 -0
- package/dist/esm/start-router-plugin/constants.js.map +1 -0
- package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js +3 -9
- package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/plugin.d.ts +3 -2
- package/dist/esm/start-router-plugin/plugin.js +191 -31
- package/dist/esm/start-router-plugin/plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.d.ts +8 -0
- package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js +34 -0
- package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js.map +1 -0
- package/package.json +8 -8
- package/src/constants.ts +3 -2
- package/src/create-server-fn-plugin/compiler.ts +99 -57
- package/src/{start-compiler-plugin/middleware.ts → create-server-fn-plugin/handleCreateMiddleware.ts} +15 -12
- package/src/create-server-fn-plugin/handleCreateServerFn.ts +11 -8
- package/src/create-server-fn-plugin/plugin.ts +24 -9
- package/src/dev-server-plugin/plugin.ts +6 -3
- package/src/plugin.ts +76 -84
- package/src/resolve-entries.ts +1 -2
- package/src/schema.ts +31 -14
- package/src/start-compiler-plugin/compilers.ts +18 -51
- package/src/start-compiler-plugin/constants.ts +0 -4
- package/src/start-router-plugin/constants.ts +1 -0
- package/src/start-router-plugin/generator-plugins/routes-manifest-plugin.ts +3 -9
- package/src/start-router-plugin/plugin.ts +233 -45
- package/src/start-router-plugin/pruneServerOnlySubtrees.ts +51 -0
- package/dist/esm/debug.js +0 -5
- package/dist/esm/debug.js.map +0 -1
- package/dist/esm/start-compiler-plugin/middleware.d.ts +0 -4
- package/dist/esm/start-compiler-plugin/middleware.js.map +0 -1
- package/dist/esm/start-compiler-plugin/serverFileRoute.d.ts +0 -4
- package/dist/esm/start-compiler-plugin/serverFileRoute.js +0 -38
- package/dist/esm/start-compiler-plugin/serverFileRoute.js.map +0 -1
- package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.d.ts +0 -2
- package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js +0 -119
- package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js.map +0 -1
- package/dist/esm/start-router-plugin/route-tree-client-plugin.d.ts +0 -6
- package/dist/esm/start-router-plugin/route-tree-client-plugin.js +0 -56
- package/dist/esm/start-router-plugin/route-tree-client-plugin.js.map +0 -1
- package/dist/esm/start-router-plugin/virtual-route-tree-plugin.d.ts +0 -3
- package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js +0 -29
- package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js.map +0 -1
- package/src/start-compiler-plugin/serverFileRoute.ts +0 -59
- package/src/start-router-plugin/generator-plugins/server-routes-plugin.ts +0 -138
- package/src/start-router-plugin/route-tree-client-plugin.ts +0 -77
- package/src/start-router-plugin/virtual-route-tree-plugin.ts +0 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/start-plugin-core",
|
|
3
|
-
"version": "1.132.0
|
|
3
|
+
"version": "1.132.0",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"src"
|
|
43
43
|
],
|
|
44
44
|
"engines": {
|
|
45
|
-
"node": ">=12"
|
|
45
|
+
"node": ">=22.12.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@babel/code-frame": "7.26.2",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"vitefu": "^1.1.1",
|
|
58
58
|
"xmlbuilder2": "^3.1.1",
|
|
59
59
|
"zod": "^3.24.2",
|
|
60
|
-
"@tanstack/router-core": "1.132.0
|
|
61
|
-
"@tanstack/router-
|
|
62
|
-
"@tanstack/router-
|
|
63
|
-
"@tanstack/
|
|
64
|
-
"@tanstack/
|
|
65
|
-
"@tanstack/start-server-core": "1.132.0
|
|
60
|
+
"@tanstack/router-core": "1.132.0",
|
|
61
|
+
"@tanstack/router-plugin": "1.132.0",
|
|
62
|
+
"@tanstack/router-generator": "1.132.0",
|
|
63
|
+
"@tanstack/server-functions-plugin": "1.132.0",
|
|
64
|
+
"@tanstack/router-utils": "1.132.0",
|
|
65
|
+
"@tanstack/start-server-core": "1.132.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/babel__code-frame": "^7.0.6",
|
package/src/constants.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type ViteEnvironmentNames =
|
|
|
14
14
|
export const ENTRY_POINTS = {
|
|
15
15
|
client: 'virtual:tanstack-start-client-entry',
|
|
16
16
|
server: 'virtual:tanstack-start-server-request-entry',
|
|
17
|
-
// the
|
|
18
|
-
|
|
17
|
+
// the start entry point must always be provided by the user
|
|
18
|
+
start: '#tanstack-start-entry',
|
|
19
|
+
router: '#tanstack-router-entry',
|
|
19
20
|
} as const
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
findReferencedIdentifiers,
|
|
8
8
|
} from 'babel-dead-code-elimination'
|
|
9
9
|
import { handleCreateServerFn } from './handleCreateServerFn'
|
|
10
|
+
import { handleCreateMiddleware } from './handleCreateMiddleware'
|
|
10
11
|
|
|
11
12
|
type Binding =
|
|
12
13
|
| {
|
|
@@ -26,8 +27,16 @@ type ExportEntry =
|
|
|
26
27
|
| { tag: 'Default'; name: string }
|
|
27
28
|
| { tag: 'Namespace'; name: string; targetId: string } // for `export * as ns from './x'`
|
|
28
29
|
|
|
29
|
-
type Kind = 'None' |
|
|
30
|
+
type Kind = 'None' | `Root` | `Builder` | LookupKind
|
|
30
31
|
|
|
32
|
+
type LookupKind = 'ServerFn' | 'Middleware'
|
|
33
|
+
|
|
34
|
+
const validLookupKinds: Array<LookupKind> = ['ServerFn', 'Middleware']
|
|
35
|
+
const candidateCallIdentifier = ['handler', 'server', 'client']
|
|
36
|
+
export type LookupConfig = {
|
|
37
|
+
libName: string
|
|
38
|
+
rootExport: string
|
|
39
|
+
}
|
|
31
40
|
interface ModuleInfo {
|
|
32
41
|
id: string
|
|
33
42
|
code: string
|
|
@@ -38,43 +47,55 @@ interface ModuleInfo {
|
|
|
38
47
|
|
|
39
48
|
export class ServerFnCompiler {
|
|
40
49
|
private moduleCache = new Map<string, ModuleInfo>()
|
|
41
|
-
private resolvedLibId!: string
|
|
42
50
|
private initialized = false
|
|
43
51
|
constructor(
|
|
44
52
|
private options: {
|
|
45
53
|
env: 'client' | 'server'
|
|
46
|
-
|
|
47
|
-
rootExport: string
|
|
54
|
+
lookupConfigurations: Array<LookupConfig>
|
|
48
55
|
loadModule: (id: string) => Promise<void>
|
|
49
56
|
resolveId: (id: string, importer?: string) => Promise<string | null>
|
|
50
57
|
},
|
|
51
58
|
) {}
|
|
52
59
|
|
|
53
60
|
private async init(id: string) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
61
|
+
await Promise.all(
|
|
62
|
+
this.options.lookupConfigurations.map(async (config) => {
|
|
63
|
+
const libId = await this.options.resolveId(config.libName, id)
|
|
64
|
+
if (!libId) {
|
|
65
|
+
throw new Error(`could not resolve "${config.libName}"`)
|
|
66
|
+
}
|
|
67
|
+
let rootModule = this.moduleCache.get(libId)
|
|
68
|
+
if (!rootModule) {
|
|
69
|
+
// insert root binding
|
|
70
|
+
rootModule = {
|
|
71
|
+
ast: null as any,
|
|
72
|
+
bindings: new Map(),
|
|
73
|
+
exports: new Map(),
|
|
74
|
+
code: '',
|
|
75
|
+
id: libId,
|
|
76
|
+
}
|
|
77
|
+
this.moduleCache.set(libId, rootModule)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
rootModule.exports.set(config.rootExport, {
|
|
81
|
+
tag: 'Normal',
|
|
82
|
+
name: config.rootExport,
|
|
83
|
+
})
|
|
84
|
+
rootModule.exports.set('*', {
|
|
85
|
+
tag: 'Namespace',
|
|
86
|
+
name: config.rootExport,
|
|
87
|
+
targetId: libId,
|
|
88
|
+
})
|
|
89
|
+
rootModule.bindings.set(config.rootExport, {
|
|
90
|
+
type: 'var',
|
|
91
|
+
init: t.identifier(config.rootExport),
|
|
92
|
+
resolvedKind: `Root` satisfies Kind,
|
|
93
|
+
})
|
|
94
|
+
this.moduleCache.set(libId, rootModule)
|
|
95
|
+
}),
|
|
96
|
+
)
|
|
97
|
+
|
|
76
98
|
this.initialized = true
|
|
77
|
-
this.resolvedLibId = libId
|
|
78
99
|
}
|
|
79
100
|
|
|
80
101
|
public ingestModule({ code, id }: { code: string; id: string }) {
|
|
@@ -172,30 +193,37 @@ export class ServerFnCompiler {
|
|
|
172
193
|
await this.init(id)
|
|
173
194
|
}
|
|
174
195
|
const { bindings, ast } = this.ingestModule({ code, id })
|
|
175
|
-
const candidates = this.
|
|
196
|
+
const candidates = this.collectCandidates(bindings)
|
|
176
197
|
if (candidates.length === 0) {
|
|
177
|
-
// this hook will only be invoked if there is `.handler(` in the code,
|
|
198
|
+
// this hook will only be invoked if there is `.handler(` | `.server(` | `.client(` in the code,
|
|
178
199
|
// so not discovering a handler candidate is rather unlikely, but maybe possible?
|
|
179
200
|
return null
|
|
180
201
|
}
|
|
181
202
|
|
|
182
203
|
// let's find out which of the candidates are actually server functions
|
|
183
|
-
const toRewrite: Array<
|
|
204
|
+
const toRewrite: Array<{
|
|
205
|
+
callExpression: t.CallExpression
|
|
206
|
+
kind: LookupKind
|
|
207
|
+
}> = []
|
|
184
208
|
for (const handler of candidates) {
|
|
185
209
|
const kind = await this.resolveExprKind(handler, id)
|
|
186
|
-
if (kind
|
|
187
|
-
toRewrite.push(handler)
|
|
210
|
+
if (validLookupKinds.includes(kind as LookupKind)) {
|
|
211
|
+
toRewrite.push({ callExpression: handler, kind: kind as LookupKind })
|
|
188
212
|
}
|
|
189
213
|
}
|
|
190
214
|
if (toRewrite.length === 0) {
|
|
191
215
|
return null
|
|
192
216
|
}
|
|
193
|
-
|
|
217
|
+
|
|
218
|
+
const pathsToRewrite: Array<{
|
|
219
|
+
nodePath: babel.NodePath<t.CallExpression>
|
|
220
|
+
kind: LookupKind
|
|
221
|
+
}> = []
|
|
194
222
|
babel.traverse(ast, {
|
|
195
223
|
CallExpression(path) {
|
|
196
|
-
const found = toRewrite.findIndex((h) => path.node === h)
|
|
224
|
+
const found = toRewrite.findIndex((h) => path.node === h.callExpression)
|
|
197
225
|
if (found !== -1) {
|
|
198
|
-
pathsToRewrite.push(path)
|
|
226
|
+
pathsToRewrite.push({ nodePath: path, kind: toRewrite[found]!.kind })
|
|
199
227
|
// delete from toRewrite
|
|
200
228
|
toRewrite.splice(found, 1)
|
|
201
229
|
}
|
|
@@ -210,9 +238,13 @@ export class ServerFnCompiler {
|
|
|
210
238
|
|
|
211
239
|
const refIdents = findReferencedIdentifiers(ast)
|
|
212
240
|
|
|
213
|
-
pathsToRewrite.map((p) =>
|
|
214
|
-
|
|
215
|
-
|
|
241
|
+
pathsToRewrite.map((p) => {
|
|
242
|
+
if (p.kind === 'ServerFn') {
|
|
243
|
+
handleCreateServerFn(p.nodePath, { env: this.options.env, code })
|
|
244
|
+
} else {
|
|
245
|
+
handleCreateMiddleware(p.nodePath, { env: this.options.env })
|
|
246
|
+
}
|
|
247
|
+
})
|
|
216
248
|
|
|
217
249
|
deadCodeElimination(ast, refIdents)
|
|
218
250
|
|
|
@@ -223,13 +255,13 @@ export class ServerFnCompiler {
|
|
|
223
255
|
})
|
|
224
256
|
}
|
|
225
257
|
|
|
226
|
-
// collects all
|
|
227
|
-
private
|
|
258
|
+
// collects all candidate CallExpressions at top-level
|
|
259
|
+
private collectCandidates(bindings: Map<string, Binding>) {
|
|
228
260
|
const candidates: Array<t.CallExpression> = []
|
|
229
261
|
|
|
230
262
|
for (const binding of bindings.values()) {
|
|
231
263
|
if (binding.type === 'var') {
|
|
232
|
-
const handler =
|
|
264
|
+
const handler = isCandidateCallExpression(binding.init)
|
|
233
265
|
if (handler) {
|
|
234
266
|
candidates.push(handler)
|
|
235
267
|
}
|
|
@@ -280,12 +312,6 @@ export class ServerFnCompiler {
|
|
|
280
312
|
return 'None'
|
|
281
313
|
}
|
|
282
314
|
|
|
283
|
-
if (binding.importedName === '*') {
|
|
284
|
-
throw new Error(
|
|
285
|
-
`should never get here, namespace imports are handled in resolveCalleeKind`,
|
|
286
|
-
)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
315
|
const importedModule = await this.getModuleInfo(target)
|
|
290
316
|
|
|
291
317
|
const moduleExport = importedModule.exports.get(binding.importedName)
|
|
@@ -338,11 +364,15 @@ export class ServerFnCompiler {
|
|
|
338
364
|
fileId,
|
|
339
365
|
visited,
|
|
340
366
|
)
|
|
341
|
-
if (calleeKind
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
367
|
+
if (calleeKind !== 'None') {
|
|
368
|
+
if (calleeKind === `Root` || calleeKind === `Builder`) {
|
|
369
|
+
return `Builder`
|
|
370
|
+
}
|
|
371
|
+
for (const kind of validLookupKinds) {
|
|
372
|
+
if (calleeKind === kind) {
|
|
373
|
+
return kind
|
|
374
|
+
}
|
|
375
|
+
}
|
|
346
376
|
}
|
|
347
377
|
} else if (t.isMemberExpression(expr) && t.isIdentifier(expr.property)) {
|
|
348
378
|
result = await this.resolveCalleeKind(expr.object, fileId, visited)
|
|
@@ -383,6 +413,16 @@ export class ServerFnCompiler {
|
|
|
383
413
|
return 'ServerFn'
|
|
384
414
|
}
|
|
385
415
|
return 'None'
|
|
416
|
+
} else if (
|
|
417
|
+
prop === 'client' ||
|
|
418
|
+
prop === 'server' ||
|
|
419
|
+
prop === 'createMiddleware'
|
|
420
|
+
) {
|
|
421
|
+
const base = await this.resolveExprKind(callee.object, fileId, visited)
|
|
422
|
+
if (base === 'Root' || base === 'Builder' || base === 'Middleware') {
|
|
423
|
+
return 'Middleware'
|
|
424
|
+
}
|
|
425
|
+
return 'None'
|
|
386
426
|
}
|
|
387
427
|
// Check if the object is a namespace import
|
|
388
428
|
if (t.isIdentifier(callee.object)) {
|
|
@@ -413,6 +453,8 @@ export class ServerFnCompiler {
|
|
|
413
453
|
)
|
|
414
454
|
}
|
|
415
455
|
}
|
|
456
|
+
} else {
|
|
457
|
+
return 'None'
|
|
416
458
|
}
|
|
417
459
|
}
|
|
418
460
|
}
|
|
@@ -439,16 +481,16 @@ export class ServerFnCompiler {
|
|
|
439
481
|
}
|
|
440
482
|
}
|
|
441
483
|
|
|
442
|
-
function
|
|
484
|
+
function isCandidateCallExpression(
|
|
443
485
|
node: t.Node | null | undefined,
|
|
444
486
|
): undefined | t.CallExpression {
|
|
445
487
|
if (!t.isCallExpression(node)) return undefined
|
|
446
488
|
|
|
447
489
|
const callee = node.callee
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
) {
|
|
490
|
+
if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property)) {
|
|
491
|
+
return undefined
|
|
492
|
+
}
|
|
493
|
+
if (!candidateCallIdentifier.includes(callee.property.name)) {
|
|
452
494
|
return undefined
|
|
453
495
|
}
|
|
454
496
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as t from '@babel/types'
|
|
2
|
-
import { getRootCallExpression } from '
|
|
2
|
+
import { getRootCallExpression } from '../start-compiler-plugin/utils'
|
|
3
3
|
import type * as babel from '@babel/core'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export function handleCreateMiddlewareCallExpression(
|
|
5
|
+
export function handleCreateMiddleware(
|
|
8
6
|
path: babel.NodePath<t.CallExpression>,
|
|
9
|
-
opts:
|
|
7
|
+
opts: {
|
|
8
|
+
env: 'client' | 'server'
|
|
9
|
+
},
|
|
10
10
|
) {
|
|
11
11
|
const rootCallExpression = getRootCallExpression(path)
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@ export function handleCreateMiddlewareCallExpression(
|
|
|
18
18
|
|
|
19
19
|
const callExpressionPaths = {
|
|
20
20
|
middleware: null as babel.NodePath<t.CallExpression> | null,
|
|
21
|
-
|
|
21
|
+
inputValidator: null as babel.NodePath<t.CallExpression> | null,
|
|
22
22
|
client: null as babel.NodePath<t.CallExpression> | null,
|
|
23
23
|
server: null as babel.NodePath<t.CallExpression> | null,
|
|
24
24
|
}
|
|
@@ -41,20 +41,23 @@ export function handleCreateMiddlewareCallExpression(
|
|
|
41
41
|
},
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
if (callExpressionPaths.
|
|
45
|
-
const innerInputExpression =
|
|
44
|
+
if (callExpressionPaths.inputValidator) {
|
|
45
|
+
const innerInputExpression =
|
|
46
|
+
callExpressionPaths.inputValidator.node.arguments[0]
|
|
46
47
|
|
|
47
48
|
if (!innerInputExpression) {
|
|
48
49
|
throw new Error(
|
|
49
|
-
'createMiddleware().
|
|
50
|
+
'createMiddleware().inputValidator() must be called with a validator!',
|
|
50
51
|
)
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
// If we're on the client, remove the validator call expression
|
|
54
55
|
if (opts.env === 'client') {
|
|
55
|
-
if (
|
|
56
|
-
callExpressionPaths.
|
|
57
|
-
|
|
56
|
+
if (
|
|
57
|
+
t.isMemberExpression(callExpressionPaths.inputValidator.node.callee)
|
|
58
|
+
) {
|
|
59
|
+
callExpressionPaths.inputValidator.replaceWith(
|
|
60
|
+
callExpressionPaths.inputValidator.node.callee.object,
|
|
58
61
|
)
|
|
59
62
|
}
|
|
60
63
|
}
|
|
@@ -16,14 +16,14 @@ export function handleCreateServerFn(
|
|
|
16
16
|
// the validator, handler, and middleware methods. Check to make sure they
|
|
17
17
|
// are children of the createServerFn call expression.
|
|
18
18
|
|
|
19
|
-
const validMethods = ['middleware', '
|
|
19
|
+
const validMethods = ['middleware', 'inputValidator', 'handler'] as const
|
|
20
20
|
type ValidMethods = (typeof validMethods)[number]
|
|
21
21
|
const callExpressionPaths: Record<
|
|
22
22
|
ValidMethods,
|
|
23
23
|
babel.NodePath<t.CallExpression> | null
|
|
24
24
|
> = {
|
|
25
25
|
middleware: null,
|
|
26
|
-
|
|
26
|
+
inputValidator: null,
|
|
27
27
|
handler: null,
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -59,20 +59,23 @@ export function handleCreateServerFn(
|
|
|
59
59
|
},
|
|
60
60
|
})
|
|
61
61
|
|
|
62
|
-
if (callExpressionPaths.
|
|
63
|
-
const innerInputExpression =
|
|
62
|
+
if (callExpressionPaths.inputValidator) {
|
|
63
|
+
const innerInputExpression =
|
|
64
|
+
callExpressionPaths.inputValidator.node.arguments[0]
|
|
64
65
|
|
|
65
66
|
if (!innerInputExpression) {
|
|
66
67
|
throw new Error(
|
|
67
|
-
'createServerFn().
|
|
68
|
+
'createServerFn().inputValidator() must be called with a validator!',
|
|
68
69
|
)
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
// If we're on the client, remove the validator call expression
|
|
72
73
|
if (opts.env === 'client') {
|
|
73
|
-
if (
|
|
74
|
-
callExpressionPaths.
|
|
75
|
-
|
|
74
|
+
if (
|
|
75
|
+
t.isMemberExpression(callExpressionPaths.inputValidator.node.callee)
|
|
76
|
+
) {
|
|
77
|
+
callExpressionPaths.inputValidator.replaceWith(
|
|
78
|
+
callExpressionPaths.inputValidator.node.callee.object,
|
|
76
79
|
)
|
|
77
80
|
}
|
|
78
81
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { VITE_ENVIRONMENT_NAMES } from '../constants'
|
|
2
2
|
import { ServerFnCompiler } from './compiler'
|
|
3
|
+
import type { CompileStartFrameworkOptions } from '../start-compiler-plugin/compilers'
|
|
3
4
|
import type { ViteEnvironmentNames } from '../constants'
|
|
4
5
|
import type { PluginOption } from 'vite'
|
|
5
|
-
import type { CompileStartFrameworkOptions } from '../start-compiler-plugin/compilers'
|
|
6
6
|
|
|
7
7
|
function cleanId(id: string): string {
|
|
8
8
|
return id.split('?')[0]!
|
|
@@ -11,9 +11,6 @@ function cleanId(id: string): string {
|
|
|
11
11
|
export function createServerFnPlugin(
|
|
12
12
|
framework: CompileStartFrameworkOptions,
|
|
13
13
|
): PluginOption {
|
|
14
|
-
const libName = `@tanstack/${framework}-start`
|
|
15
|
-
const rootExport = 'createServerFn'
|
|
16
|
-
|
|
17
14
|
const SERVER_FN_LOOKUP = 'server-fn-module-lookup'
|
|
18
15
|
|
|
19
16
|
const compilers: Partial<Record<ViteEnvironmentNames, ServerFnCompiler>> = {}
|
|
@@ -55,8 +52,8 @@ export function createServerFnPlugin(
|
|
|
55
52
|
exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),
|
|
56
53
|
},
|
|
57
54
|
code: {
|
|
58
|
-
// only scan files that mention `.handler(`
|
|
59
|
-
include: [/\.handler\(/],
|
|
55
|
+
// only scan files that mention `.handler(` | `.server(` | `.client(`
|
|
56
|
+
include: [/\.handler\(/, /\.server\(/, /\.client\(/],
|
|
60
57
|
},
|
|
61
58
|
},
|
|
62
59
|
async handler(code, id) {
|
|
@@ -76,8 +73,21 @@ export function createServerFnPlugin(
|
|
|
76
73
|
|
|
77
74
|
compiler = new ServerFnCompiler({
|
|
78
75
|
env,
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
lookupConfigurations: [
|
|
77
|
+
{
|
|
78
|
+
libName: `@tanstack/${framework}-start`,
|
|
79
|
+
rootExport: 'createMiddleware',
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
libName: `@tanstack/${framework}-start`,
|
|
84
|
+
rootExport: 'createServerFn',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
libName: `@tanstack/${framework}-start`,
|
|
88
|
+
rootExport: 'createStart',
|
|
89
|
+
},
|
|
90
|
+
],
|
|
81
91
|
loadModule: async (id: string) => {
|
|
82
92
|
if (this.environment.mode === 'build') {
|
|
83
93
|
const loaded = await this.load({ id })
|
|
@@ -104,7 +114,12 @@ export function createServerFnPlugin(
|
|
|
104
114
|
},
|
|
105
115
|
resolveId: async (source: string, importer?: string) => {
|
|
106
116
|
const r = await this.resolve(source, importer)
|
|
107
|
-
|
|
117
|
+
if (r) {
|
|
118
|
+
if (!r.external) {
|
|
119
|
+
return cleanId(r.id)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null
|
|
108
123
|
},
|
|
109
124
|
})
|
|
110
125
|
compilers[this.environment.name as ViteEnvironmentNames] = compiler
|
|
@@ -8,9 +8,9 @@ import type { Connect, DevEnvironment, PluginOption } from 'vite'
|
|
|
8
8
|
import type { TanStackStartOutputConfig } from '../schema'
|
|
9
9
|
|
|
10
10
|
export function devServerPlugin({
|
|
11
|
-
|
|
11
|
+
getConfig,
|
|
12
12
|
}: {
|
|
13
|
-
startConfig: TanStackStartOutputConfig
|
|
13
|
+
getConfig: () => { startConfig: TanStackStartOutputConfig }
|
|
14
14
|
}): PluginOption {
|
|
15
15
|
let isTest = false
|
|
16
16
|
|
|
@@ -48,6 +48,7 @@ export function devServerPlugin({
|
|
|
48
48
|
`Server environment ${VITE_ENVIRONMENT_NAMES.server} not found`,
|
|
49
49
|
)
|
|
50
50
|
}
|
|
51
|
+
const { startConfig } = getConfig()
|
|
51
52
|
const installMiddleware = startConfig.vite?.installDevServerMiddleware
|
|
52
53
|
if (installMiddleware === false) {
|
|
53
54
|
return
|
|
@@ -98,7 +99,9 @@ export function devServerPlugin({
|
|
|
98
99
|
return sendNodeResponse(res, webRes)
|
|
99
100
|
} catch (e) {
|
|
100
101
|
console.error(e)
|
|
101
|
-
|
|
102
|
+
try {
|
|
103
|
+
viteDevServer.ssrFixStacktrace(e as Error)
|
|
104
|
+
} catch (_e) {}
|
|
102
105
|
|
|
103
106
|
if (
|
|
104
107
|
webReq.headers.get('content-type')?.includes('application/json')
|