@tanstack/start-plugin-core 1.167.17 → 1.167.19

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 (183) hide show
  1. package/dist/esm/config-context.d.ts +26 -0
  2. package/dist/esm/config-context.js +81 -0
  3. package/dist/esm/config-context.js.map +1 -0
  4. package/dist/esm/constants.d.ts +6 -1
  5. package/dist/esm/constants.js +3 -2
  6. package/dist/esm/constants.js.map +1 -1
  7. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +1 -1
  8. package/dist/esm/import-protection-plugin/plugin.js +1 -1
  9. package/dist/esm/import-protection-plugin/virtualModules.js +1 -1
  10. package/dist/esm/index.d.ts +5 -3
  11. package/dist/esm/index.js +3 -4
  12. package/dist/esm/planning.d.ts +40 -0
  13. package/dist/esm/planning.js +107 -0
  14. package/dist/esm/planning.js.map +1 -0
  15. package/dist/esm/schema.d.ts +3093 -44
  16. package/dist/esm/schema.js +5 -5
  17. package/dist/esm/schema.js.map +1 -1
  18. package/dist/esm/serialization-adapters-module.d.ts +17 -0
  19. package/dist/esm/serialization-adapters-module.js +39 -0
  20. package/dist/esm/serialization-adapters-module.js.map +1 -0
  21. package/dist/esm/{start-compiler-plugin → start-compiler}/compiler.d.ts +2 -3
  22. package/dist/esm/{start-compiler-plugin → start-compiler}/compiler.js +17 -16
  23. package/dist/esm/start-compiler/compiler.js.map +1 -0
  24. package/dist/esm/start-compiler/config.d.ts +4 -0
  25. package/dist/esm/start-compiler/config.js +54 -0
  26. package/dist/esm/start-compiler/config.js.map +1 -0
  27. package/dist/esm/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.js +1 -1
  28. package/dist/esm/start-compiler/handleClientOnlyJSX.js.map +1 -0
  29. package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.js +1 -1
  30. package/dist/esm/start-compiler/handleCreateIsomorphicFn.js.map +1 -0
  31. package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.js +1 -1
  32. package/dist/esm/start-compiler/handleCreateMiddleware.js.map +1 -0
  33. package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateServerFn.js +6 -17
  34. package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -0
  35. package/dist/esm/{start-compiler-plugin → start-compiler}/handleEnvOnly.js +1 -1
  36. package/dist/esm/start-compiler/handleEnvOnly.js.map +1 -0
  37. package/dist/esm/start-compiler/host.d.ts +20 -0
  38. package/dist/esm/start-compiler/host.js +38 -0
  39. package/dist/esm/start-compiler/host.js.map +1 -0
  40. package/dist/esm/start-compiler/load-module.d.ts +14 -0
  41. package/dist/esm/start-compiler/load-module.js +18 -0
  42. package/dist/esm/start-compiler/load-module.js.map +1 -0
  43. package/dist/esm/start-compiler/server-fn-resolver-module.d.ts +8 -0
  44. package/dist/esm/start-compiler/server-fn-resolver-module.js +77 -0
  45. package/dist/esm/start-compiler/server-fn-resolver-module.js.map +1 -0
  46. package/dist/esm/{start-compiler-plugin → start-compiler}/types.d.ts +4 -0
  47. package/dist/esm/{start-compiler-plugin → start-compiler}/utils.js +1 -1
  48. package/dist/esm/start-compiler/utils.js.map +1 -0
  49. package/dist/esm/start-manifest-plugin/manifestBuilder.d.ts +16 -16
  50. package/dist/esm/start-manifest-plugin/manifestBuilder.js +14 -45
  51. package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
  52. package/dist/esm/start-router-plugin/route-tree-footer.d.ts +6 -0
  53. package/dist/esm/start-router-plugin/route-tree-footer.js +44 -0
  54. package/dist/esm/start-router-plugin/route-tree-footer.js.map +1 -0
  55. package/dist/esm/types.d.ts +44 -10
  56. package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.js +1 -1
  57. package/dist/esm/vite/dev-server-plugin/dev-styles.js.map +1 -0
  58. package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.js +1 -1
  59. package/dist/esm/vite/dev-server-plugin/extract-html-scripts.js.map +1 -0
  60. package/dist/esm/vite/dev-server-plugin/plugin.d.ts +7 -0
  61. package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/plugin.js +5 -6
  62. package/dist/esm/vite/dev-server-plugin/plugin.js.map +1 -0
  63. package/dist/esm/{load-env-plugin → vite/load-env-plugin}/plugin.js +1 -1
  64. package/dist/esm/vite/load-env-plugin/plugin.js.map +1 -0
  65. package/dist/esm/{output-directory.js → vite/output-directory.js} +2 -2
  66. package/dist/esm/vite/output-directory.js.map +1 -0
  67. package/dist/esm/vite/planning.d.ts +105 -0
  68. package/dist/esm/vite/planning.js +116 -0
  69. package/dist/esm/vite/planning.js.map +1 -0
  70. package/dist/esm/vite/plugin.d.ts +4 -0
  71. package/dist/esm/vite/plugin.js +169 -0
  72. package/dist/esm/vite/plugin.js.map +1 -0
  73. package/dist/esm/vite/plugins.d.ts +17 -0
  74. package/dist/esm/vite/plugins.js +50 -0
  75. package/dist/esm/vite/plugins.js.map +1 -0
  76. package/dist/esm/{post-server-build.d.ts → vite/post-server-build.d.ts} +1 -1
  77. package/dist/esm/{post-server-build.js → vite/post-server-build.js} +4 -4
  78. package/dist/esm/vite/post-server-build.js.map +1 -0
  79. package/dist/esm/{prerender.d.ts → vite/prerender.d.ts} +1 -1
  80. package/dist/esm/{prerender.js → vite/prerender.js} +5 -10
  81. package/dist/esm/vite/prerender.js.map +1 -0
  82. package/dist/esm/{preview-server-plugin → vite/preview-server-plugin}/plugin.js +4 -4
  83. package/dist/esm/vite/preview-server-plugin/plugin.js.map +1 -0
  84. package/dist/esm/vite/schema.d.ts +3373 -0
  85. package/dist/esm/vite/schema.js +12 -0
  86. package/dist/esm/vite/schema.js.map +1 -0
  87. package/dist/esm/vite/serialization-adapters-plugin.d.ts +5 -0
  88. package/dist/esm/vite/serialization-adapters-plugin.js +42 -0
  89. package/dist/esm/vite/serialization-adapters-plugin.js.map +1 -0
  90. package/dist/esm/vite/start-compiler-plugin/module-specifier.d.ts +3 -0
  91. package/dist/esm/vite/start-compiler-plugin/module-specifier.js +19 -0
  92. package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -0
  93. package/dist/esm/{start-compiler-plugin → vite/start-compiler-plugin}/plugin.d.ts +4 -3
  94. package/dist/esm/vite/start-compiler-plugin/plugin.js +202 -0
  95. package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -0
  96. package/dist/esm/vite/start-manifest-plugin/normalized-client-build.d.ts +6 -0
  97. package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js +81 -0
  98. package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js.map +1 -0
  99. package/dist/esm/vite/start-manifest-plugin/plugin.d.ts +6 -0
  100. package/dist/esm/{start-manifest-plugin → vite/start-manifest-plugin}/plugin.js +14 -9
  101. package/dist/esm/vite/start-manifest-plugin/plugin.js.map +1 -0
  102. package/dist/esm/{start-router-plugin → vite/start-router-plugin}/plugin.d.ts +3 -2
  103. package/dist/esm/{start-router-plugin → vite/start-router-plugin}/plugin.js +14 -37
  104. package/dist/esm/vite/start-router-plugin/plugin.js.map +1 -0
  105. package/dist/esm/vite/types.d.ts +15 -0
  106. package/package.json +14 -3
  107. package/src/config-context.ts +138 -0
  108. package/src/constants.ts +7 -3
  109. package/src/index.ts +5 -5
  110. package/src/planning.ts +151 -0
  111. package/src/schema.ts +93 -93
  112. package/src/serialization-adapters-module.ts +82 -0
  113. package/src/{start-compiler-plugin → start-compiler}/compiler.ts +67 -61
  114. package/src/start-compiler/config.ts +73 -0
  115. package/src/{start-compiler-plugin → start-compiler}/handleCreateServerFn.ts +14 -41
  116. package/src/start-compiler/host.ts +80 -0
  117. package/src/start-compiler/load-module.ts +31 -0
  118. package/src/start-compiler/server-fn-resolver-module.ts +129 -0
  119. package/src/{start-compiler-plugin → start-compiler}/types.ts +5 -0
  120. package/src/start-manifest-plugin/manifestBuilder.ts +65 -107
  121. package/src/start-router-plugin/route-tree-footer.ts +99 -0
  122. package/src/types.ts +53 -10
  123. package/src/{dev-server-plugin → vite/dev-server-plugin}/plugin.ts +7 -6
  124. package/src/{output-directory.ts → vite/output-directory.ts} +2 -2
  125. package/src/vite/planning.ts +234 -0
  126. package/src/vite/plugin.ts +276 -0
  127. package/src/vite/plugins.ts +81 -0
  128. package/src/{post-server-build.ts → vite/post-server-build.ts} +4 -6
  129. package/src/{prerender.ts → vite/prerender.ts} +21 -46
  130. package/src/{preview-server-plugin → vite/preview-server-plugin}/plugin.ts +2 -2
  131. package/src/vite/schema.ts +30 -0
  132. package/src/vite/serialization-adapters-plugin.ts +69 -0
  133. package/src/vite/start-compiler-plugin/module-specifier.ts +31 -0
  134. package/src/vite/start-compiler-plugin/plugin.ts +345 -0
  135. package/src/vite/start-manifest-plugin/normalized-client-build.ts +131 -0
  136. package/src/{start-manifest-plugin → vite/start-manifest-plugin}/plugin.ts +21 -13
  137. package/src/{start-router-plugin → vite/start-router-plugin}/plugin.ts +14 -80
  138. package/src/vite/types.ts +18 -0
  139. package/dist/esm/dev-server-plugin/dev-styles.js.map +0 -1
  140. package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +0 -1
  141. package/dist/esm/dev-server-plugin/plugin.d.ts +0 -6
  142. package/dist/esm/dev-server-plugin/plugin.js.map +0 -1
  143. package/dist/esm/load-env-plugin/plugin.js.map +0 -1
  144. package/dist/esm/output-directory.js.map +0 -1
  145. package/dist/esm/plugin.d.ts +0 -4
  146. package/dist/esm/plugin.js +0 -301
  147. package/dist/esm/plugin.js.map +0 -1
  148. package/dist/esm/post-server-build.js.map +0 -1
  149. package/dist/esm/prerender.js.map +0 -1
  150. package/dist/esm/preview-server-plugin/plugin.js.map +0 -1
  151. package/dist/esm/start-compiler-plugin/compiler.js.map +0 -1
  152. package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js.map +0 -1
  153. package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js.map +0 -1
  154. package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js.map +0 -1
  155. package/dist/esm/start-compiler-plugin/handleCreateServerFn.js.map +0 -1
  156. package/dist/esm/start-compiler-plugin/handleEnvOnly.js.map +0 -1
  157. package/dist/esm/start-compiler-plugin/plugin.js +0 -297
  158. package/dist/esm/start-compiler-plugin/plugin.js.map +0 -1
  159. package/dist/esm/start-compiler-plugin/utils.js.map +0 -1
  160. package/dist/esm/start-manifest-plugin/plugin.d.ts +0 -6
  161. package/dist/esm/start-manifest-plugin/plugin.js.map +0 -1
  162. package/dist/esm/start-router-plugin/plugin.js.map +0 -1
  163. package/src/plugin.ts +0 -471
  164. package/src/start-compiler-plugin/plugin.ts +0 -478
  165. /package/dist/esm/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.d.ts +0 -0
  166. /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.d.ts +0 -0
  167. /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.d.ts +0 -0
  168. /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateServerFn.d.ts +0 -0
  169. /package/dist/esm/{start-compiler-plugin → start-compiler}/handleEnvOnly.d.ts +0 -0
  170. /package/dist/esm/{start-compiler-plugin → start-compiler}/utils.d.ts +0 -0
  171. /package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.d.ts +0 -0
  172. /package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.d.ts +0 -0
  173. /package/dist/esm/{load-env-plugin → vite/load-env-plugin}/plugin.d.ts +0 -0
  174. /package/dist/esm/{output-directory.d.ts → vite/output-directory.d.ts} +0 -0
  175. /package/dist/esm/{preview-server-plugin → vite/preview-server-plugin}/plugin.d.ts +0 -0
  176. /package/src/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.ts +0 -0
  177. /package/src/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.ts +0 -0
  178. /package/src/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.ts +0 -0
  179. /package/src/{start-compiler-plugin → start-compiler}/handleEnvOnly.ts +0 -0
  180. /package/src/{start-compiler-plugin → start-compiler}/utils.ts +0 -0
  181. /package/src/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.ts +0 -0
  182. /package/src/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.ts +0 -0
  183. /package/src/{load-env-plugin → vite/load-env-plugin}/plugin.ts +0 -0
@@ -0,0 +1,131 @@
1
+ import { tsrSplit } from '@tanstack/router-plugin'
2
+ import type { Rollup } from 'vite'
3
+ import type { NormalizedClientBuild, NormalizedClientChunk } from '../../types'
4
+
5
+ export function normalizeViteClientChunk(
6
+ chunk: Rollup.OutputChunk,
7
+ ): NormalizedClientChunk {
8
+ return {
9
+ fileName: chunk.fileName,
10
+ isEntry: chunk.isEntry,
11
+ imports: chunk.imports,
12
+ dynamicImports: chunk.dynamicImports,
13
+ css: Array.from(chunk.viteMetadata?.importedCss ?? []),
14
+ routeFilePaths: getRouteFilePathsFromModuleIds(chunk.moduleIds),
15
+ }
16
+ }
17
+
18
+ export function normalizeViteClientChunks(
19
+ clientBundle: Rollup.OutputBundle,
20
+ ): ReadonlyMap<string, NormalizedClientChunk> {
21
+ const chunksByFileName = new Map<string, NormalizedClientChunk>()
22
+
23
+ for (const fileName in clientBundle) {
24
+ const bundleEntry = clientBundle[fileName]!
25
+ if (bundleEntry.type !== 'chunk') {
26
+ continue
27
+ }
28
+
29
+ const normalizedChunk = normalizeViteClientChunk(bundleEntry)
30
+ chunksByFileName.set(normalizedChunk.fileName, normalizedChunk)
31
+ }
32
+
33
+ return chunksByFileName
34
+ }
35
+
36
+ export function normalizeViteClientBuild(
37
+ clientBundle: Rollup.OutputBundle,
38
+ ): NormalizedClientBuild {
39
+ let entryChunkFileName: string | undefined
40
+ const chunksByFileName = normalizeViteClientChunks(clientBundle)
41
+ const chunkFileNamesByRouteFilePath = new Map<string, Array<string>>()
42
+ const cssFilesBySourcePath = new Map<string, Array<string>>()
43
+
44
+ for (const chunk of chunksByFileName.values()) {
45
+ if (chunk.isEntry) {
46
+ if (entryChunkFileName) {
47
+ throw new Error(
48
+ `multiple entries detected: ${entryChunkFileName} ${chunk.fileName}`,
49
+ )
50
+ }
51
+ entryChunkFileName = chunk.fileName
52
+ }
53
+
54
+ for (const routeFilePath of chunk.routeFilePaths) {
55
+ let chunkFileNames = chunkFileNamesByRouteFilePath.get(routeFilePath)
56
+ if (chunkFileNames === undefined) {
57
+ chunkFileNames = []
58
+ chunkFileNamesByRouteFilePath.set(routeFilePath, chunkFileNames)
59
+ }
60
+ chunkFileNames.push(chunk.fileName)
61
+ }
62
+
63
+ const bundleEntry = clientBundle[chunk.fileName]
64
+ if (bundleEntry?.type === 'chunk') {
65
+ for (const moduleId of bundleEntry.moduleIds) {
66
+ const queryIndex = moduleId.indexOf('?')
67
+ const sourcePath =
68
+ queryIndex >= 0 ? moduleId.slice(0, queryIndex) : moduleId
69
+ if (!sourcePath) continue
70
+
71
+ const existing = cssFilesBySourcePath.get(sourcePath)
72
+ cssFilesBySourcePath.set(
73
+ sourcePath,
74
+ existing
75
+ ? Array.from(new Set([...existing, ...chunk.css]))
76
+ : chunk.css.slice(),
77
+ )
78
+ }
79
+ }
80
+ }
81
+
82
+ if (!entryChunkFileName) {
83
+ throw new Error('No entry file found')
84
+ }
85
+
86
+ return {
87
+ entryChunkFileName,
88
+ chunksByFileName,
89
+ chunkFileNamesByRouteFilePath,
90
+ cssFilesBySourcePath,
91
+ }
92
+ }
93
+
94
+ export function getRouteFilePathsFromModuleIds(moduleIds: Array<string>) {
95
+ let routeFilePaths: Array<string> | undefined
96
+ let seenRouteFilePaths: Set<string> | undefined
97
+
98
+ for (const moduleId of moduleIds) {
99
+ const queryIndex = moduleId.indexOf('?')
100
+
101
+ if (queryIndex < 0) {
102
+ continue
103
+ }
104
+
105
+ const query = moduleId.slice(queryIndex + 1)
106
+
107
+ if (!query.includes(tsrSplit)) {
108
+ continue
109
+ }
110
+
111
+ if (!new URLSearchParams(query).has(tsrSplit)) {
112
+ continue
113
+ }
114
+
115
+ const routeFilePath = moduleId.slice(0, queryIndex)
116
+
117
+ if (seenRouteFilePaths?.has(routeFilePath)) {
118
+ continue
119
+ }
120
+
121
+ if (routeFilePaths === undefined || seenRouteFilePaths === undefined) {
122
+ routeFilePaths = []
123
+ seenRouteFilePaths = new Set<string>()
124
+ }
125
+
126
+ routeFilePaths.push(routeFilePath)
127
+ seenRouteFilePaths.add(routeFilePath)
128
+ }
129
+
130
+ return routeFilePaths ?? []
131
+ }
@@ -1,15 +1,15 @@
1
1
  import { joinURL } from 'ufo'
2
2
  import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
3
- import { resolveViteId } from '../utils'
4
- import { ENTRY_POINTS } from '../constants'
5
- import { buildStartManifest } from './manifestBuilder'
6
- import type { GetConfigFn } from '../types'
7
- import type { PluginOption, Rollup } from 'vite'
3
+ import { resolveViteId } from '../../utils'
4
+ import { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from '../../constants'
5
+ import { buildStartManifest } from '../../start-manifest-plugin/manifestBuilder'
6
+ import type { GetConfigFn, NormalizedClientBuild } from '../../types'
7
+ import type { PluginOption } from 'vite'
8
8
 
9
9
  const resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)
10
10
 
11
11
  export function startManifestPlugin(opts: {
12
- getClientBundle: () => Rollup.OutputBundle
12
+ getClientBuild: () => NormalizedClientBuild | undefined
13
13
  getConfig: GetConfigFn
14
14
  }): PluginOption {
15
15
  return {
@@ -31,24 +31,32 @@ export function startManifestPlugin(opts: {
31
31
  handler(id) {
32
32
  const { resolvedStartConfig } = opts.getConfig()
33
33
  if (id === resolvedModuleId) {
34
- if (
35
- this.environment.name !== resolvedStartConfig.serverFnProviderEnv
36
- ) {
37
- return `export default {}`
34
+ if (this.environment.name !== START_ENVIRONMENT_NAMES.server) {
35
+ return 'export default {}'
38
36
  }
39
37
 
40
38
  if (this.environment.config.command === 'serve') {
41
39
  return `export const tsrStartManifest = () => ({
42
40
  routes: {},
43
- clientEntry: '${joinURL(resolvedStartConfig.viteAppBase, '@id', ENTRY_POINTS.client)}',
41
+ clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, '@id', ENTRY_POINTS.client)}',
44
42
  })`
45
43
  }
46
44
 
47
45
  const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST
46
+ const clientBuild = opts.getClientBuild()
47
+ // TODO this needs further discussion with vite-rsc, this is a temporary workaround
48
+ // If the client bundle isn't available yet (e.g., during RSC scan builds),
49
+ // return a dummy manifest. The real manifest will be generated in the actual build.
50
+ if (!clientBuild) {
51
+ return `export const tsrStartManifest = () => ({
52
+ routes: {},
53
+ clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, '@id', ENTRY_POINTS.client)}',
54
+ })`
55
+ }
48
56
  const startManifest = buildStartManifest({
49
- clientBundle: opts.getClientBundle(),
57
+ clientBuild,
50
58
  routeTreeRoutes,
51
- basePath: resolvedStartConfig.viteAppBase,
59
+ basePath: resolvedStartConfig.basePaths.publicBase,
52
60
  })
53
61
 
54
62
  return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`
@@ -3,21 +3,23 @@ import {
3
3
  tanstackRouterAutoImport,
4
4
  tanstackRouterGenerator,
5
5
  } from '@tanstack/router-plugin/vite'
6
- import { normalizePath } from 'vite'
7
6
  import path from 'pathe'
8
- import { VITE_ENVIRONMENT_NAMES } from '../constants'
9
- import { routesManifestPlugin } from './generator-plugins/routes-manifest-plugin'
10
- import { prerenderRoutesPlugin } from './generator-plugins/prerender-routes-plugin'
11
- import { pruneServerOnlySubtrees } from './pruneServerOnlySubtrees'
12
- import { SERVER_PROP } from './constants'
13
- import type { GetConfigFn, TanStackStartVitePluginCoreOptions } from '../types'
7
+ import { normalizePath } from 'vite'
8
+ import { VITE_ENVIRONMENT_NAMES } from '../../constants'
9
+ import { routesManifestPlugin } from '../../start-router-plugin/generator-plugins/routes-manifest-plugin'
10
+ import { prerenderRoutesPlugin } from '../../start-router-plugin/generator-plugins/prerender-routes-plugin'
11
+ import { buildRouteTreeFileFooterFromConfig } from '../../start-router-plugin/route-tree-footer'
12
+ import { pruneServerOnlySubtrees } from '../../start-router-plugin/pruneServerOnlySubtrees'
13
+ import { SERVER_PROP } from '../../start-router-plugin/constants'
14
+ import type { GetConfigFn } from '../../types'
15
+ import type { TanStackStartVitePluginCoreOptions } from '../types'
14
16
  import type {
15
17
  Generator,
16
18
  GeneratorPlugin,
17
19
  RouteNode,
18
20
  } from '@tanstack/router-generator'
19
21
  import type { DevEnvironment, Plugin, PluginOption } from 'vite'
20
- import type { TanStackStartInputConfig } from '../schema'
22
+ import type { TanStackStartInputConfig } from '../../schema'
21
23
 
22
24
  function isServerOnlyNode(node: RouteNode | undefined) {
23
25
  if (!node?.createFileRouteProps) {
@@ -29,63 +31,6 @@ function isServerOnlyNode(node: RouteNode | undefined) {
29
31
  )
30
32
  }
31
33
 
32
- function moduleDeclaration({
33
- startFilePath,
34
- routerFilePath,
35
- corePluginOpts,
36
- generatedRouteTreePath,
37
- }: {
38
- startFilePath: string | undefined
39
- routerFilePath: string
40
- corePluginOpts: TanStackStartVitePluginCoreOptions
41
- generatedRouteTreePath: string
42
- }): string {
43
- function getImportPath(absolutePath: string) {
44
- let relativePath = path.relative(
45
- path.dirname(generatedRouteTreePath),
46
- absolutePath,
47
- )
48
-
49
- if (!relativePath.startsWith('.')) {
50
- relativePath = './' + relativePath
51
- }
52
-
53
- // convert to POSIX-style for ESM imports (important on Windows)
54
- relativePath = relativePath.split(path.sep).join('/')
55
- return relativePath
56
- }
57
-
58
- const result: Array<string> = [
59
- `import type { getRouter } from '${getImportPath(routerFilePath)}'`,
60
- ]
61
- if (startFilePath) {
62
- result.push(
63
- `import type { startInstance } from '${getImportPath(startFilePath)}'`,
64
- )
65
- }
66
- // make sure we import something from start to get the server route declaration merge
67
- else {
68
- result.push(
69
- `import type { createStart } from '@tanstack/${corePluginOpts.framework}-start'`,
70
- )
71
- }
72
- result.push(
73
- `declare module '@tanstack/${corePluginOpts.framework}-start' {
74
- interface Register {
75
- ssr: true
76
- router: Awaited<ReturnType<typeof getRouter>>`,
77
- )
78
- if (startFilePath) {
79
- result.push(
80
- ` config: Awaited<ReturnType<typeof startInstance.getOptions>>`,
81
- )
82
- }
83
- result.push(` }
84
- }`)
85
-
86
- return result.join('\n')
87
- }
88
-
89
34
  export function tanStackStartRouter(
90
35
  startPluginOpts: TanStackStartInputConfig,
91
36
  getConfig: GetConfigFn,
@@ -131,23 +76,12 @@ export function tanStackStartRouter(
131
76
  if (routeTreeFileFooter) {
132
77
  return routeTreeFileFooter
133
78
  }
134
- const { startConfig, resolvedStartConfig } = getConfig()
135
- const ogRouteTreeFileFooter = startConfig.router.routeTreeFileFooter
136
- if (ogRouteTreeFileFooter) {
137
- if (Array.isArray(ogRouteTreeFileFooter)) {
138
- routeTreeFileFooter = ogRouteTreeFileFooter
139
- } else {
140
- routeTreeFileFooter = ogRouteTreeFileFooter()
141
- }
142
- }
143
79
  routeTreeFileFooter = [
144
- moduleDeclaration({
80
+ ...buildRouteTreeFileFooterFromConfig({
145
81
  generatedRouteTreePath: getGeneratedRouteTreePath(),
82
+ getConfig,
146
83
  corePluginOpts,
147
- startFilePath: resolvedStartConfig.startFilePath,
148
- routerFilePath: resolvedStartConfig.routerFilePath,
149
84
  }),
150
- ...(routeTreeFileFooter ?? []),
151
85
  ]
152
86
  return routeTreeFileFooter
153
87
  }
@@ -211,7 +145,7 @@ export function tanStackStartRouter(
211
145
  tanstackRouterGenerator(() => {
212
146
  const routerConfig = getConfig().startConfig.router
213
147
  const plugins = [clientTreeGeneratorPlugin, routesManifestPlugin()]
214
- if (startPluginOpts?.prerender?.enabled === true) {
148
+ if (startPluginOpts.prerender?.enabled === true) {
215
149
  plugins.push(prerenderRoutesPlugin())
216
150
  }
217
151
  return {
@@ -248,6 +182,6 @@ export function tanStackStartRouter(
248
182
  },
249
183
  }
250
184
  }),
251
- tanstackRouterAutoImport(startPluginOpts?.router),
185
+ tanstackRouterAutoImport(startPluginOpts.router),
252
186
  ]
253
187
  }
@@ -0,0 +1,18 @@
1
+ import type { TanStackStartCoreOptions } from '../types'
2
+
3
+ export interface ViteRscForwardSsrResolverStrategy {
4
+ type: 'vite-rsc-forward'
5
+ sourceEnvironmentName: string
6
+ sourceEntry: string
7
+ exportName: 'getServerFnById'
8
+ }
9
+
10
+ export type SsrResolverStrategy =
11
+ | { type: 'default' }
12
+ | ViteRscForwardSsrResolverStrategy
13
+
14
+ export type TanStackStartVitePluginCoreOptions = TanStackStartCoreOptions & {
15
+ providerEnvironmentName: string
16
+ ssrIsProvider: boolean
17
+ ssrResolverStrategy: SsrResolverStrategy
18
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-styles.js","names":[],"sources":["../../../src/dev-server-plugin/dev-styles.ts"],"sourcesContent":["/**\n * CSS collection for dev mode.\n * Crawls the Vite module graph to collect CSS from the router entry and all its dependencies.\n */\nimport path from 'node:path'\nimport type { ModuleNode, ViteDevServer } from 'vite'\n\n// CSS file extensions supported by Vite\nconst CSS_FILE_REGEX =\n /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n// CSS modules file pattern - exported for use in plugin hook filters\n// Note: allow query/hash suffix since Vite ids often include them.\nexport const CSS_MODULES_REGEX =\n /\\.module\\.(css|less|sass|scss|styl|stylus)(?:$|[?#])/i\n\nexport function normalizeCssModuleCacheKey(idOrFile: string): string {\n const baseId = idOrFile.split('?')[0]!.split('#')[0]!\n return baseId.replace(/\\\\/g, '/')\n}\n// URL params that indicate CSS should not be injected (e.g., ?url, ?inline)\nconst CSS_SIDE_EFFECT_FREE_PARAMS = ['url', 'inline', 'raw', 'inline-css']\n\n// Marker to find the CSS string in Vite's transformed output\nconst VITE_CSS_MARKER = 'const __vite__css = '\n\nconst ESCAPE_CSS_COMMENT_START_REGEX = /\\/\\*/g\nconst ESCAPE_CSS_COMMENT_END_REGEX = /\\*\\//g\n\nfunction isCssFile(file: string): boolean {\n return CSS_FILE_REGEX.test(file)\n}\n\nexport function isCssModulesFile(file: string): boolean {\n return CSS_MODULES_REGEX.test(file)\n}\n\nfunction hasCssSideEffectFreeParam(url: string): boolean {\n const queryString = url.split('?')[1]\n if (!queryString) return false\n\n const params = new URLSearchParams(queryString)\n return CSS_SIDE_EFFECT_FREE_PARAMS.some(\n (param) =>\n params.get(param) === '' &&\n !url.includes(`?${param}=`) &&\n !url.includes(`&${param}=`),\n )\n}\n\n/**\n * Resolve a file path to a Vite dev server URL.\n * Files within the root directory use relative paths, files outside use /@fs prefix.\n */\nfunction resolveDevUrl(rootDirectory: string, filePath: string): string {\n const normalizedPath = filePath.replace(/\\\\/g, '/')\n const relativePath = path.posix.relative(\n rootDirectory.replace(/\\\\/g, '/'),\n normalizedPath,\n )\n const isWithinRoot =\n !relativePath.startsWith('..') && !path.isAbsolute(relativePath)\n\n if (isWithinRoot) {\n return path.posix.join('/', relativePath)\n }\n // Files outside root need /@fs prefix\n return path.posix.join('/@fs', normalizedPath)\n}\n\nexport interface CollectDevStylesOptions {\n viteDevServer: ViteDevServer\n entries: Array<string>\n /** Cache of CSS modules content captured during transform hook */\n cssModulesCache?: Record<string, string>\n}\n\n/**\n * Collect CSS content from the module graph starting from the given entry points.\n */\nexport async function collectDevStyles(\n opts: CollectDevStylesOptions,\n): Promise<string | undefined> {\n const { viteDevServer, entries, cssModulesCache = {} } = opts\n const styles: Map<string, string> = new Map()\n const visited = new Set<ModuleNode>()\n\n const rootDirectory = viteDevServer.config.root\n\n // Process entries in parallel - each entry is independent\n await Promise.all(\n entries.map((entry) =>\n processEntry(viteDevServer, resolveDevUrl(rootDirectory, entry), visited),\n ),\n )\n\n // Collect CSS from visited modules in parallel\n const cssPromises: Array<Promise<readonly [string, string] | null>> = []\n\n for (const dep of visited) {\n if (hasCssSideEffectFreeParam(dep.url)) {\n continue\n }\n\n if (dep.file && isCssModulesFile(dep.file)) {\n const css = cssModulesCache[normalizeCssModuleCacheKey(dep.file)]\n if (!css) {\n // skip this module - it may not be a real CSS module or it may not have been transformed yet\n continue\n }\n styles.set(dep.url, css)\n continue\n }\n\n const fileOrUrl = dep.file ?? dep.url\n if (!isCssFile(fileOrUrl)) {\n continue\n }\n\n // Load regular CSS files in parallel\n cssPromises.push(\n fetchCssFromModule(viteDevServer, dep).then((css) =>\n css ? ([dep.url, css] as const) : null,\n ),\n )\n }\n\n // Wait for all CSS loads to complete\n const cssResults = await Promise.all(cssPromises)\n for (const result of cssResults) {\n if (result) {\n styles.set(result[0], result[1])\n }\n }\n\n if (styles.size === 0) return undefined\n\n const parts: Array<string> = []\n for (const [fileName, css] of styles.entries()) {\n const escapedFileName = fileName\n .replace(ESCAPE_CSS_COMMENT_START_REGEX, '/\\\\*')\n .replace(ESCAPE_CSS_COMMENT_END_REGEX, '*\\\\/')\n parts.push(`\\n/* ${escapedFileName} */\\n${css}`)\n }\n return parts.join('\\n')\n}\n\n/**\n * Process an entry URL: transform it if needed, get the module node, and crawl its dependencies.\n */\nasync function processEntry(\n viteDevServer: ViteDevServer,\n entryUrl: string,\n visited: Set<ModuleNode>,\n): Promise<void> {\n let node = await viteDevServer.moduleGraph.getModuleByUrl(entryUrl)\n\n // Only transform if not yet SSR-transformed (need ssrTransformResult.deps for crawling)\n if (!node?.ssrTransformResult) {\n try {\n await viteDevServer.transformRequest(entryUrl)\n } catch {\n // ignore - module might not exist yet\n }\n node = await viteDevServer.moduleGraph.getModuleByUrl(entryUrl)\n }\n\n if (!node || visited.has(node)) return\n\n visited.add(node)\n await findModuleDeps(viteDevServer, node, visited)\n}\n\n/**\n * Find all module dependencies by crawling the module graph.\n * Uses transformResult.deps for URL-based lookups (parallel) and\n * importedModules for already-resolved nodes (parallel).\n */\nasync function findModuleDeps(\n viteDevServer: ViteDevServer,\n node: ModuleNode,\n visited: Set<ModuleNode>,\n): Promise<void> {\n // Note: caller must add node to visited BEFORE calling this function\n // to prevent race conditions with parallel traversal\n\n // Process deps from transformResult if available (URLs including bare imports)\n const deps =\n node.ssrTransformResult?.deps ?? node.transformResult?.deps ?? null\n\n const importedModules = node.importedModules\n\n // Fast path: no deps and no imports\n if ((!deps || deps.length === 0) && importedModules.size === 0) {\n return\n }\n\n // Build branches only when needed (avoid array allocation on leaf nodes)\n const branches: Array<Promise<void>> = []\n\n if (deps) {\n for (const depUrl of deps) {\n const dep = await viteDevServer.moduleGraph.getModuleByUrl(depUrl)\n if (!dep) continue\n\n if (visited.has(dep)) continue\n visited.add(dep)\n branches.push(findModuleDeps(viteDevServer, dep, visited))\n }\n }\n\n // ALWAYS also traverse importedModules - this catches:\n // - Code-split chunks (e.g. ?tsr-split=component) not in deps\n // - Already-resolved nodes\n for (const depNode of importedModules) {\n if (visited.has(depNode)) continue\n visited.add(depNode)\n branches.push(findModuleDeps(viteDevServer, depNode, visited))\n }\n\n if (branches.length === 1) {\n await branches[0]\n return\n }\n\n await Promise.all(branches)\n}\n\nasync function fetchCssFromModule(\n viteDevServer: ViteDevServer,\n node: ModuleNode,\n): Promise<string | undefined> {\n // Use cached transform result if available\n const cachedCode = node.transformResult?.code ?? node.ssrTransformResult?.code\n if (cachedCode) {\n return extractCssFromCode(cachedCode)\n }\n\n // Otherwise request a fresh transform\n try {\n const transformResult = await viteDevServer.transformRequest(node.url)\n if (!transformResult?.code) return undefined\n\n return extractCssFromCode(transformResult.code)\n } catch {\n // Preprocessor partials (e.g., Sass files with mixins) can't compile in isolation.\n // The root stylesheet that @imports them will contain the compiled CSS.\n return undefined\n }\n}\n\n/**\n * Extract CSS content from Vite's transformed CSS module code.\n *\n * Vite embeds CSS into the module as a JS string via `JSON.stringify(cssContent)`,\n * e.g. `const __vite__css = ${JSON.stringify('...css...')}`.\n *\n * We locate that JSON string literal and run `JSON.parse` on it to reverse the\n * escaping (\\\\n, \\\\t, \\\\\", \\\\\\\\, \\\\uXXXX, etc.).\n */\nexport function extractCssFromCode(code: string): string | undefined {\n const startIdx = code.indexOf(VITE_CSS_MARKER)\n if (startIdx === -1) return undefined\n\n const valueStart = startIdx + VITE_CSS_MARKER.length\n // Vite emits `const __vite__css = ${JSON.stringify(cssContent)}` which always\n // produces double-quoted JSON string literals.\n if (code.charCodeAt(valueStart) !== 34) return undefined\n\n const codeLength = code.length\n let i = valueStart + 1\n while (i < codeLength) {\n const charCode = code.charCodeAt(i)\n // 34 = '\"'\n if (charCode === 34) {\n try {\n return JSON.parse(code.slice(valueStart, i + 1))\n } catch {\n return undefined\n }\n }\n // 92 = '\\\\'\n if (charCode === 92) {\n i += 2\n } else {\n i++\n }\n }\n\n return undefined\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"extract-html-scripts.js","names":[],"sources":["../../../src/dev-server-plugin/extract-html-scripts.ts"],"sourcesContent":["import * as cheerio from 'cheerio'\n\nexport function extractHtmlScripts(\n html: string,\n): Array<{ content?: string; src?: string }> {\n const $ = cheerio.load(html)\n const scripts: Array<{ content?: string; src?: string }> = []\n\n $('script').each((_, element) => {\n const src = $(element).attr('src')\n const content = $(element).html() ?? undefined\n scripts.push({\n src,\n content,\n })\n })\n\n return scripts\n}\n"],"mappings":";;AAEA,SAAgB,mBACd,MAC2C;CAC3C,MAAM,IAAI,QAAQ,KAAK,KAAK;CAC5B,MAAM,UAAqD,EAAE;AAE7D,GAAE,SAAS,CAAC,MAAM,GAAG,YAAY;EAC/B,MAAM,MAAM,EAAE,QAAQ,CAAC,KAAK,MAAM;EAClC,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,IAAI,KAAA;AACrC,UAAQ,KAAK;GACX;GACA;GACD,CAAC;GACF;AAEF,QAAO"}
@@ -1,6 +0,0 @@
1
- import { PluginOption } from 'vite';
2
- import { GetConfigFn } from '../types.js';
3
- export declare function devServerPlugin({ getConfig, devSsrStylesEnabled, }: {
4
- getConfig: GetConfigFn;
5
- devSsrStylesEnabled: boolean;
6
- }): PluginOption;
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../../src/dev-server-plugin/plugin.ts"],"sourcesContent":["import { isRunnableDevEnvironment } from 'vite'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { NodeRequest, sendNodeResponse } from 'srvx/node'\nimport { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from '../constants'\nimport { resolveViteId } from '../utils'\nimport { extractHtmlScripts } from './extract-html-scripts'\nimport {\n CSS_MODULES_REGEX,\n collectDevStyles,\n normalizeCssModuleCacheKey,\n} from './dev-styles'\nimport type { Connect, DevEnvironment, PluginOption } from 'vite'\nimport type { GetConfigFn } from '../types'\n\nexport function devServerPlugin({\n getConfig,\n devSsrStylesEnabled,\n}: {\n getConfig: GetConfigFn\n devSsrStylesEnabled: boolean\n}): PluginOption {\n let isTest = false\n\n let injectedHeadScripts: string | undefined\n\n // Cache CSS modules content during transform hook.\n // For CSS modules, the transform hook receives the raw CSS content before\n // Vite wraps it in JS. We capture this to use during SSR style collection.\n const cssModulesCache: Record<string, string> = {}\n\n return [\n {\n name: 'tanstack-start-core:dev-server',\n config(_userConfig, { mode }) {\n isTest = isTest ? isTest : mode === 'test'\n },\n // Capture CSS modules content during transform\n transform: {\n filter: {\n id: CSS_MODULES_REGEX,\n },\n handler(code, id) {\n cssModulesCache[normalizeCssModuleCacheKey(id)] = code\n },\n },\n async configureServer(viteDevServer) {\n if (isTest) {\n return\n }\n\n // Extract the scripts that Vite plugins would inject into the initial HTML\n const templateHtml = `<html><head></head><body></body></html>`\n const transformedHtml = await viteDevServer.transformIndexHtml(\n '/',\n templateHtml,\n )\n const scripts = extractHtmlScripts(transformedHtml)\n injectedHeadScripts = scripts\n .flatMap((script) => script.content ?? [])\n .join(';')\n\n // CSS middleware registered in PRE-PHASE (before Vite's internal middlewares)\n // This ensures it handles /@tanstack-start/styles.css before any catch-all middleware\n // from other plugins (like nitro) that may be registered in the post-phase.\n // This makes the CSS endpoint work regardless of plugin order in the Vite config.\n // We check pathname.endsWith() to handle basepaths (e.g., /my-app/@tanstack-start/styles.css)\n // since pre-phase runs before Vite's base middleware strips the basepath.\n if (devSsrStylesEnabled) {\n viteDevServer.middlewares.use(async (req, res, next) => {\n const url = req.url ?? ''\n const pathname = url.split('?')[0]\n if (!pathname?.endsWith('/@tanstack-start/styles.css')) {\n return next()\n }\n\n try {\n // Parse route IDs from query param\n const urlObj = new URL(url, 'http://localhost')\n const routesParam = urlObj.searchParams.get('routes')\n const routeIds = routesParam ? routesParam.split(',') : []\n\n // Build entries list from route file paths\n const entries: Array<string> = []\n\n // Look up route file paths from manifest\n // Only routes registered in the manifest are used - this prevents path injection\n const routesManifest = (globalThis as any).TSS_ROUTES_MANIFEST as\n | Record<string, { filePath: string; children?: Array<string> }>\n | undefined\n\n if (routesManifest && routeIds.length > 0) {\n for (const routeId of routeIds) {\n const route = routesManifest[routeId]\n if (route?.filePath) {\n entries.push(route.filePath)\n }\n }\n }\n\n const css =\n entries.length > 0\n ? await collectDevStyles({\n viteDevServer,\n entries,\n cssModulesCache,\n })\n : undefined\n\n res.setHeader('Content-Type', 'text/css')\n res.setHeader('Cache-Control', 'no-store')\n res.end(css ?? '')\n } catch (e) {\n // Log error but still return valid CSS response to avoid MIME type issues\n console.error('[tanstack-start] Error collecting dev styles:', e)\n res.setHeader('Content-Type', 'text/css')\n res.setHeader('Cache-Control', 'no-store')\n res.end(\n `/* Error collecting styles: ${e instanceof Error ? e.message : String(e)} */`,\n )\n }\n })\n }\n\n return () => {\n const serverEnv = viteDevServer.environments[\n VITE_ENVIRONMENT_NAMES.server\n ] as DevEnvironment | undefined\n\n if (!serverEnv) {\n throw new Error(\n `Server environment ${VITE_ENVIRONMENT_NAMES.server} not found`,\n )\n }\n\n const { startConfig } = getConfig()\n const installMiddleware = startConfig.vite?.installDevServerMiddleware\n if (installMiddleware === false) {\n return\n }\n if (installMiddleware == undefined) {\n // do not install middleware in middlewareMode by default\n if (viteDevServer.config.server.middlewareMode) {\n return\n }\n\n // do not install middleware if SSR env in case another plugin already did\n if (\n !isRunnableDevEnvironment(serverEnv) ||\n // do not check via `isFetchableDevEnvironment` since nitro does implement the `FetchableDevEnvironment` interface but not via inheritance (which this helper checks)\n 'dispatchFetch' in serverEnv\n ) {\n return\n }\n }\n\n if (!isRunnableDevEnvironment(serverEnv)) {\n throw new Error(\n 'cannot install vite dev server middleware for TanStack Start since the SSR environment is not a RunnableDevEnvironment',\n )\n }\n\n viteDevServer.middlewares.use(async (req, res) => {\n // fix the request URL to match the original URL\n // otherwise, the request URL will '/index.html'\n if (req.originalUrl) {\n req.url = req.originalUrl\n }\n const webReq = new NodeRequest({ req, res })\n\n try {\n // Import and resolve the request by running the server request entry point\n // this request entry point must implement the `fetch` API as follows:\n /**\n * export default {\n * fetch(req: Request): Promise<Response>\n * }\n */\n const serverEntry = await serverEnv.runner.import(\n ENTRY_POINTS.server,\n )\n const webRes = await serverEntry['default'].fetch(webReq)\n\n return sendNodeResponse(res, webRes)\n } catch (e) {\n console.error(e)\n try {\n viteDevServer.ssrFixStacktrace(e as Error)\n } catch {}\n\n if (\n webReq.headers.get('content-type')?.includes('application/json')\n ) {\n return sendNodeResponse(\n res,\n new Response(\n JSON.stringify(\n {\n status: 500,\n error: 'Internal Server Error',\n message:\n 'An unexpected error occurred. Please try again later.',\n timestamp: new Date().toISOString(),\n },\n null,\n 2,\n ),\n {\n status: 500,\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ),\n )\n }\n\n return sendNodeResponse(\n res,\n new Response(\n `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>Error</title>\n <script type=\"module\">\n import { ErrorOverlay } from '/@vite/client'\n document.body.appendChild(new ErrorOverlay(${JSON.stringify(\n prepareError(req, e),\n ).replace(/</g, '\\\\u003c')}))\n </script>\n </head>\n <body>\n </body>\n </html>\n `,\n {\n status: 500,\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n ),\n )\n }\n })\n }\n },\n },\n {\n name: 'tanstack-start-core:dev-server:injected-head-scripts',\n sharedDuringBuild: true,\n applyToEnvironment: (env) => env.config.consumer === 'server',\n resolveId: {\n filter: { id: new RegExp(VIRTUAL_MODULES.injectedHeadScripts) },\n handler(_id) {\n return resolveViteId(VIRTUAL_MODULES.injectedHeadScripts)\n },\n },\n load: {\n filter: {\n id: new RegExp(resolveViteId(VIRTUAL_MODULES.injectedHeadScripts)),\n },\n handler() {\n const mod = `\n export const injectedHeadScripts = ${JSON.stringify(injectedHeadScripts) || 'undefined'}`\n return mod\n },\n },\n },\n ]\n}\n\n/**\n * Formats error for SSR message in error overlay\n * @param req\n * @param error\n * @returns\n */\nfunction prepareError(req: Connect.IncomingMessage, error: unknown) {\n const e = error as Error\n return {\n message: `An error occurred while server rendering ${req.url}:\\n\\n\\t${\n typeof e === 'string' ? e : e.message\n } `,\n stack: typeof e === 'string' ? '' : e.stack,\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../../src/load-env-plugin/plugin.ts"],"sourcesContent":["import { loadEnv } from 'vite'\nimport type { Plugin } from 'vite'\n\nexport function loadEnvPlugin(): Plugin {\n return {\n name: 'tanstack-start-core:load-env',\n enforce: 'pre',\n configResolved(config) {\n Object.assign(process.env, loadEnv(config.mode, config.root, ''))\n },\n }\n}\n"],"mappings":";;AAGA,SAAgB,gBAAwB;AACtC,QAAO;EACL,MAAM;EACN,SAAS;EACT,eAAe,QAAQ;AACrB,UAAO,OAAO,QAAQ,KAAK,QAAQ,OAAO,MAAM,OAAO,MAAM,GAAG,CAAC;;EAEpE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-directory.js","names":[],"sources":["../../src/output-directory.ts"],"sourcesContent":["import { join } from 'pathe'\nimport { VITE_ENVIRONMENT_NAMES } from './constants'\nimport type { ViteEnvironmentNames } from './constants'\nimport type * as vite from 'vite'\n\nexport function getClientOutputDirectory(\n userConfig: vite.UserConfig | vite.ResolvedConfig,\n) {\n return getOutputDirectory(userConfig, VITE_ENVIRONMENT_NAMES.client, 'client')\n}\n\nexport function getServerOutputDirectory(\n userConfig: vite.UserConfig | vite.ResolvedConfig,\n) {\n return getOutputDirectory(userConfig, VITE_ENVIRONMENT_NAMES.server, 'server')\n}\n\nfunction getOutputDirectory(\n userConfig: vite.UserConfig | vite.ResolvedConfig,\n environmentName: ViteEnvironmentNames,\n directoryName: string,\n) {\n const rootOutputDirectory = userConfig.build?.outDir ?? 'dist'\n\n return (\n userConfig.environments?.[environmentName]?.build?.outDir ??\n join(rootOutputDirectory, directoryName)\n )\n}\n"],"mappings":";;;AAKA,SAAgB,yBACd,YACA;AACA,QAAO,mBAAmB,YAAY,uBAAuB,QAAQ,SAAS;;AAGhF,SAAgB,yBACd,YACA;AACA,QAAO,mBAAmB,YAAY,uBAAuB,QAAQ,SAAS;;AAGhF,SAAS,mBACP,YACA,iBACA,eACA;CACA,MAAM,sBAAsB,WAAW,OAAO,UAAU;AAExD,QACE,WAAW,eAAe,kBAAkB,OAAO,UACnD,KAAK,qBAAqB,cAAc"}
@@ -1,4 +0,0 @@
1
- import { TanStackStartVitePluginCoreOptions } from './types.js';
2
- import { TanStackStartInputConfig } from './schema.js';
3
- import { PluginOption } from 'vite';
4
- export declare function TanStackStartVitePluginCore(corePluginOpts: TanStackStartVitePluginCoreOptions, startPluginOpts: TanStackStartInputConfig): Array<PluginOption>;