@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.
Files changed (78) hide show
  1. package/dist/esm/constants.d.ts +2 -1
  2. package/dist/esm/constants.js +3 -2
  3. package/dist/esm/constants.js.map +1 -1
  4. package/dist/esm/create-server-fn-plugin/compiler.d.ts +8 -5
  5. package/dist/esm/create-server-fn-plugin/compiler.js +74 -46
  6. package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -1
  7. package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.d.ts +5 -0
  8. package/dist/esm/{start-compiler-plugin/middleware.js → create-server-fn-plugin/handleCreateMiddleware.js} +11 -11
  9. package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.js.map +1 -0
  10. package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js +8 -8
  11. package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js.map +1 -1
  12. package/dist/esm/create-server-fn-plugin/plugin.d.ts +1 -1
  13. package/dist/esm/create-server-fn-plugin/plugin.js +22 -7
  14. package/dist/esm/create-server-fn-plugin/plugin.js.map +1 -1
  15. package/dist/esm/dev-server-plugin/plugin.d.ts +4 -2
  16. package/dist/esm/dev-server-plugin/plugin.js +6 -2
  17. package/dist/esm/dev-server-plugin/plugin.js.map +1 -1
  18. package/dist/esm/plugin.d.ts +12 -6
  19. package/dist/esm/plugin.js +54 -65
  20. package/dist/esm/plugin.js.map +1 -1
  21. package/dist/esm/resolve-entries.d.ts +0 -1
  22. package/dist/esm/resolve-entries.js +1 -1
  23. package/dist/esm/resolve-entries.js.map +1 -1
  24. package/dist/esm/schema.d.ts +375 -308
  25. package/dist/esm/schema.js +23 -11
  26. package/dist/esm/schema.js.map +1 -1
  27. package/dist/esm/start-compiler-plugin/compilers.js +17 -49
  28. package/dist/esm/start-compiler-plugin/compilers.js.map +1 -1
  29. package/dist/esm/start-compiler-plugin/constants.d.ts +1 -1
  30. package/dist/esm/start-compiler-plugin/constants.js +1 -5
  31. package/dist/esm/start-compiler-plugin/constants.js.map +1 -1
  32. package/dist/esm/start-router-plugin/constants.d.ts +1 -0
  33. package/dist/esm/start-router-plugin/constants.js +5 -0
  34. package/dist/esm/start-router-plugin/constants.js.map +1 -0
  35. package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js +3 -9
  36. package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js.map +1 -1
  37. package/dist/esm/start-router-plugin/plugin.d.ts +3 -2
  38. package/dist/esm/start-router-plugin/plugin.js +191 -31
  39. package/dist/esm/start-router-plugin/plugin.js.map +1 -1
  40. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.d.ts +8 -0
  41. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js +34 -0
  42. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js.map +1 -0
  43. package/package.json +8 -8
  44. package/src/constants.ts +3 -2
  45. package/src/create-server-fn-plugin/compiler.ts +99 -57
  46. package/src/{start-compiler-plugin/middleware.ts → create-server-fn-plugin/handleCreateMiddleware.ts} +15 -12
  47. package/src/create-server-fn-plugin/handleCreateServerFn.ts +11 -8
  48. package/src/create-server-fn-plugin/plugin.ts +24 -9
  49. package/src/dev-server-plugin/plugin.ts +6 -3
  50. package/src/plugin.ts +76 -84
  51. package/src/resolve-entries.ts +1 -2
  52. package/src/schema.ts +31 -14
  53. package/src/start-compiler-plugin/compilers.ts +18 -51
  54. package/src/start-compiler-plugin/constants.ts +0 -4
  55. package/src/start-router-plugin/constants.ts +1 -0
  56. package/src/start-router-plugin/generator-plugins/routes-manifest-plugin.ts +3 -9
  57. package/src/start-router-plugin/plugin.ts +233 -45
  58. package/src/start-router-plugin/pruneServerOnlySubtrees.ts +51 -0
  59. package/dist/esm/debug.js +0 -5
  60. package/dist/esm/debug.js.map +0 -1
  61. package/dist/esm/start-compiler-plugin/middleware.d.ts +0 -4
  62. package/dist/esm/start-compiler-plugin/middleware.js.map +0 -1
  63. package/dist/esm/start-compiler-plugin/serverFileRoute.d.ts +0 -4
  64. package/dist/esm/start-compiler-plugin/serverFileRoute.js +0 -38
  65. package/dist/esm/start-compiler-plugin/serverFileRoute.js.map +0 -1
  66. package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.d.ts +0 -2
  67. package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js +0 -119
  68. package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js.map +0 -1
  69. package/dist/esm/start-router-plugin/route-tree-client-plugin.d.ts +0 -6
  70. package/dist/esm/start-router-plugin/route-tree-client-plugin.js +0 -56
  71. package/dist/esm/start-router-plugin/route-tree-client-plugin.js.map +0 -1
  72. package/dist/esm/start-router-plugin/virtual-route-tree-plugin.d.ts +0 -3
  73. package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js +0 -29
  74. package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js.map +0 -1
  75. package/src/start-compiler-plugin/serverFileRoute.ts +0 -59
  76. package/src/start-router-plugin/generator-plugins/server-routes-plugin.ts +0 -138
  77. package/src/start-router-plugin/route-tree-client-plugin.ts +0 -77
  78. 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-alpha.9",
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-alpha.8",
61
- "@tanstack/router-generator": "1.132.0-alpha.9",
62
- "@tanstack/router-plugin": "1.132.0-alpha.9",
63
- "@tanstack/router-utils": "1.132.0-alpha.9",
64
- "@tanstack/server-functions-plugin": "1.132.0-alpha.9",
65
- "@tanstack/start-server-core": "1.132.0-alpha.9"
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 router entry point must always be provided by the user
18
- router: '#tanstack-start-router-entry',
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' | 'Root' | 'Builder' | 'ServerFn'
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
- libName: string
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
- const libId = await this.options.resolveId(this.options.libName, id)
55
- if (!libId) {
56
- throw new Error(`could not resolve "${this.options.libName}"`)
57
- }
58
- // insert root binding
59
- const rootModule = {
60
- ast: null as any,
61
- bindings: new Map(),
62
- exports: new Map(),
63
- code: '',
64
- id: libId,
65
- }
66
- rootModule.exports.set(this.options.rootExport, {
67
- tag: 'Normal',
68
- name: this.options.rootExport,
69
- })
70
- rootModule.bindings.set(this.options.rootExport, {
71
- type: 'var',
72
- init: t.identifier(this.options.rootExport),
73
- resolvedKind: 'Root',
74
- })
75
- this.moduleCache.set(libId, rootModule)
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.collectHandlerCandidates(bindings)
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<t.CallExpression> = []
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 === 'ServerFn') {
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
- const pathsToRewrite: Array<babel.NodePath<t.CallExpression>> = []
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
- handleCreateServerFn(p, { env: this.options.env, code }),
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 `.handler(...)` CallExpressions at top-level
227
- private collectHandlerCandidates(bindings: Map<string, Binding>) {
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 = isHandlerCall(binding.init)
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 === 'Root' || calleeKind === 'Builder') {
342
- return 'Builder'
343
- }
344
- if (calleeKind === 'ServerFn') {
345
- return 'ServerFn'
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 isHandlerCall(
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
- !t.isMemberExpression(callee) ||
450
- !t.isIdentifier(callee.property, { name: 'handler' })
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 './utils'
2
+ import { getRootCallExpression } from '../start-compiler-plugin/utils'
3
3
  import type * as babel from '@babel/core'
4
4
 
5
- import type { CompileOptions } from './compilers'
6
-
7
- export function handleCreateMiddlewareCallExpression(
5
+ export function handleCreateMiddleware(
8
6
  path: babel.NodePath<t.CallExpression>,
9
- opts: CompileOptions,
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
- validator: null as babel.NodePath<t.CallExpression> | null,
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.validator) {
45
- const innerInputExpression = callExpressionPaths.validator.node.arguments[0]
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().validator() must be called with a validator!',
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 (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {
56
- callExpressionPaths.validator.replaceWith(
57
- callExpressionPaths.validator.node.callee.object,
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', 'validator', 'handler'] as const
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
- validator: null,
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.validator) {
63
- const innerInputExpression = callExpressionPaths.validator.node.arguments[0]
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().validator() must be called with a validator!',
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 (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {
74
- callExpressionPaths.validator.replaceWith(
75
- callExpressionPaths.validator.node.callee.object,
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
- libName,
80
- rootExport,
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
- return r ? cleanId(r.id) : null
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
- startConfig,
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
- viteDevServer.ssrFixStacktrace(e as Error)
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')