@tanstack/start-plugin-core 1.167.34 → 1.168.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 (197) hide show
  1. package/dist/esm/import-protection/adapterUtils.d.ts +27 -0
  2. package/dist/esm/import-protection/adapterUtils.js +31 -0
  3. package/dist/esm/import-protection/adapterUtils.js.map +1 -0
  4. package/dist/esm/import-protection/analysis.d.ts +36 -0
  5. package/dist/esm/import-protection/analysis.js +407 -0
  6. package/dist/esm/import-protection/analysis.js.map +1 -0
  7. package/dist/esm/{import-protection-plugin → import-protection}/ast.js +1 -1
  8. package/dist/esm/import-protection/ast.js.map +1 -0
  9. package/dist/esm/import-protection/constants.d.ts +11 -0
  10. package/dist/esm/{import-protection-plugin → import-protection}/constants.js +7 -2
  11. package/dist/esm/import-protection/constants.js.map +1 -0
  12. package/dist/esm/{import-protection-plugin → import-protection}/defaults.js +1 -1
  13. package/dist/esm/import-protection/defaults.js.map +1 -0
  14. package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.js +1 -1
  15. package/dist/esm/import-protection/extensionlessAbsoluteIdResolver.js.map +1 -0
  16. package/dist/esm/{import-protection-plugin → import-protection}/matchers.js +1 -1
  17. package/dist/esm/import-protection/matchers.js.map +1 -0
  18. package/dist/esm/{import-protection-plugin/rewriteDeniedImports.d.ts → import-protection/rewrite.d.ts} +0 -4
  19. package/dist/esm/import-protection/rewrite.js +121 -0
  20. package/dist/esm/import-protection/rewrite.js.map +1 -0
  21. package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.d.ts +32 -3
  22. package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.js +65 -10
  23. package/dist/esm/import-protection/sourceLocation.js.map +1 -0
  24. package/dist/esm/{import-protection-plugin → import-protection}/trace.d.ts +0 -1
  25. package/dist/esm/{import-protection-plugin → import-protection}/trace.js +1 -1
  26. package/dist/esm/import-protection/trace.js.map +1 -0
  27. package/dist/esm/{import-protection-plugin → import-protection}/utils.d.ts +18 -1
  28. package/dist/esm/{import-protection-plugin → import-protection}/utils.js +12 -19
  29. package/dist/esm/import-protection/utils.js.map +1 -0
  30. package/dist/esm/import-protection/virtualModules.d.ts +25 -0
  31. package/dist/esm/{import-protection-plugin → import-protection}/virtualModules.js +5 -117
  32. package/dist/esm/import-protection/virtualModules.js.map +1 -0
  33. package/dist/esm/index.d.ts +4 -0
  34. package/dist/esm/index.js +3 -1
  35. package/dist/esm/post-build.d.ts +9 -0
  36. package/dist/esm/post-build.js +37 -0
  37. package/dist/esm/post-build.js.map +1 -0
  38. package/dist/esm/prerender.d.ts +11 -0
  39. package/dist/esm/prerender.js +159 -0
  40. package/dist/esm/prerender.js.map +1 -0
  41. package/dist/esm/rsbuild/dev-server.d.ts +21 -0
  42. package/dist/esm/rsbuild/dev-server.js +76 -0
  43. package/dist/esm/rsbuild/dev-server.js.map +1 -0
  44. package/dist/esm/rsbuild/import-protection.d.ts +10 -0
  45. package/dist/esm/rsbuild/import-protection.js +775 -0
  46. package/dist/esm/rsbuild/import-protection.js.map +1 -0
  47. package/dist/esm/rsbuild/normalized-client-build.d.ts +18 -0
  48. package/dist/esm/rsbuild/normalized-client-build.js +207 -0
  49. package/dist/esm/rsbuild/normalized-client-build.js.map +1 -0
  50. package/dist/esm/rsbuild/planning.d.ts +52 -0
  51. package/dist/esm/rsbuild/planning.js +108 -0
  52. package/dist/esm/rsbuild/planning.js.map +1 -0
  53. package/dist/esm/rsbuild/plugin.d.ts +4 -0
  54. package/dist/esm/rsbuild/plugin.js +344 -0
  55. package/dist/esm/rsbuild/plugin.js.map +1 -0
  56. package/dist/esm/rsbuild/post-build.d.ts +6 -0
  57. package/dist/esm/rsbuild/post-build.js +57 -0
  58. package/dist/esm/rsbuild/post-build.js.map +1 -0
  59. package/dist/esm/rsbuild/schema.d.ts +3372 -0
  60. package/dist/esm/rsbuild/schema.js +12 -0
  61. package/dist/esm/rsbuild/schema.js.map +1 -0
  62. package/dist/esm/rsbuild/start-compiler-host.d.ts +20 -0
  63. package/dist/esm/rsbuild/start-compiler-host.js +150 -0
  64. package/dist/esm/rsbuild/start-compiler-host.js.map +1 -0
  65. package/dist/esm/rsbuild/start-router-plugin.d.ts +18 -0
  66. package/dist/esm/rsbuild/start-router-plugin.js +63 -0
  67. package/dist/esm/rsbuild/start-router-plugin.js.map +1 -0
  68. package/dist/esm/rsbuild/swc-rsc.d.ts +14 -0
  69. package/dist/esm/rsbuild/swc-rsc.js +93 -0
  70. package/dist/esm/rsbuild/swc-rsc.js.map +1 -0
  71. package/dist/esm/rsbuild/types.d.ts +17 -0
  72. package/dist/esm/rsbuild/types.js +0 -0
  73. package/dist/esm/rsbuild/virtual-modules.d.ts +53 -0
  74. package/dist/esm/rsbuild/virtual-modules.js +287 -0
  75. package/dist/esm/rsbuild/virtual-modules.js.map +1 -0
  76. package/dist/esm/schema.d.ts +43 -43
  77. package/dist/esm/schema.js +1 -1
  78. package/dist/esm/start-compiler/compiler.d.ts +1 -1
  79. package/dist/esm/start-compiler/compiler.js +80 -9
  80. package/dist/esm/start-compiler/compiler.js.map +1 -1
  81. package/dist/esm/start-compiler/handleCreateServerFn.js +9 -0
  82. package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -1
  83. package/dist/esm/start-compiler/host.js +5 -1
  84. package/dist/esm/start-compiler/host.js.map +1 -1
  85. package/dist/esm/start-compiler/types.d.ts +1 -0
  86. package/dist/esm/start-manifest-plugin/manifestBuilder.d.ts +3 -6
  87. package/dist/esm/start-manifest-plugin/manifestBuilder.js +34 -81
  88. package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
  89. package/dist/esm/utils.d.ts +1 -0
  90. package/dist/esm/utils.js +4 -1
  91. package/dist/esm/utils.js.map +1 -1
  92. package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.js +41 -92
  93. package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -0
  94. package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/types.d.ts +5 -5
  95. package/dist/esm/vite/import-protection-plugin/virtualModules.d.ts +8 -0
  96. package/dist/esm/vite/import-protection-plugin/virtualModules.js +49 -0
  97. package/dist/esm/vite/import-protection-plugin/virtualModules.js.map +1 -0
  98. package/dist/esm/vite/plugin.js +4 -12
  99. package/dist/esm/vite/plugin.js.map +1 -1
  100. package/dist/esm/vite/plugins.d.ts +1 -5
  101. package/dist/esm/vite/plugins.js +2 -17
  102. package/dist/esm/vite/plugins.js.map +1 -1
  103. package/dist/esm/vite/post-server-build.js +14 -32
  104. package/dist/esm/vite/post-server-build.js.map +1 -1
  105. package/dist/esm/vite/prerender.d.ts +2 -2
  106. package/dist/esm/vite/prerender.js +17 -147
  107. package/dist/esm/vite/prerender.js.map +1 -1
  108. package/dist/esm/vite/schema.d.ts +23 -23
  109. package/dist/esm/vite/start-compiler-plugin/hot-update.d.ts +2 -0
  110. package/dist/esm/vite/start-compiler-plugin/hot-update.js +16 -0
  111. package/dist/esm/vite/start-compiler-plugin/hot-update.js.map +1 -0
  112. package/dist/esm/vite/start-compiler-plugin/module-specifier.js +9 -4
  113. package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -1
  114. package/dist/esm/vite/start-compiler-plugin/plugin.js +86 -13
  115. package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -1
  116. package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js +2 -2
  117. package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js.map +1 -1
  118. package/dist/esm/vite/start-manifest-plugin/plugin.d.ts +1 -2
  119. package/dist/esm/vite/start-manifest-plugin/plugin.js +48 -14
  120. package/dist/esm/vite/start-manifest-plugin/plugin.js.map +1 -1
  121. package/package.json +17 -4
  122. package/src/import-protection/INTERNALS.md +266 -0
  123. package/src/import-protection/adapterUtils.ts +94 -0
  124. package/src/import-protection/analysis.ts +853 -0
  125. package/src/{import-protection-plugin → import-protection}/constants.ts +7 -0
  126. package/src/import-protection/rewrite.ts +229 -0
  127. package/src/{import-protection-plugin → import-protection}/sourceLocation.ts +125 -9
  128. package/src/{import-protection-plugin → import-protection}/trace.ts +0 -1
  129. package/src/{import-protection-plugin → import-protection}/utils.ts +35 -20
  130. package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
  131. package/src/index.ts +5 -0
  132. package/src/post-build.ts +64 -0
  133. package/src/prerender.ts +292 -0
  134. package/src/rsbuild/INTERNALS-import-protection.md +169 -0
  135. package/src/rsbuild/dev-server.ts +129 -0
  136. package/src/rsbuild/import-protection.ts +1600 -0
  137. package/src/rsbuild/normalized-client-build.ts +346 -0
  138. package/src/rsbuild/planning.ts +234 -0
  139. package/src/rsbuild/plugin.ts +754 -0
  140. package/src/rsbuild/post-build.ts +96 -0
  141. package/src/rsbuild/schema.ts +31 -0
  142. package/src/rsbuild/start-compiler-host.ts +250 -0
  143. package/src/rsbuild/start-router-plugin.ts +86 -0
  144. package/src/rsbuild/swc-rsc.ts +166 -0
  145. package/src/rsbuild/types.ts +20 -0
  146. package/src/rsbuild/virtual-modules.ts +565 -0
  147. package/src/start-compiler/compiler.ts +153 -19
  148. package/src/start-compiler/handleCreateServerFn.ts +18 -0
  149. package/src/start-compiler/types.ts +1 -0
  150. package/src/start-manifest-plugin/manifestBuilder.ts +53 -116
  151. package/src/utils.ts +4 -0
  152. package/src/vite/import-protection-plugin/INTERNALS.md +187 -0
  153. package/src/{import-protection-plugin → vite/import-protection-plugin}/plugin.ts +73 -158
  154. package/src/{import-protection-plugin → vite/import-protection-plugin}/types.ts +5 -5
  155. package/src/vite/import-protection-plugin/virtualModules.ts +122 -0
  156. package/src/vite/plugin.ts +1 -18
  157. package/src/vite/plugins.ts +2 -33
  158. package/src/vite/post-server-build.ts +14 -57
  159. package/src/vite/prerender.ts +19 -260
  160. package/src/vite/start-compiler-plugin/hot-update.ts +24 -0
  161. package/src/vite/start-compiler-plugin/module-specifier.ts +15 -5
  162. package/src/vite/start-compiler-plugin/plugin.ts +193 -18
  163. package/src/vite/start-manifest-plugin/normalized-client-build.ts +15 -16
  164. package/src/vite/start-manifest-plugin/plugin.ts +121 -38
  165. package/dist/esm/import-protection-plugin/ast.js.map +0 -1
  166. package/dist/esm/import-protection-plugin/constants.d.ts +0 -6
  167. package/dist/esm/import-protection-plugin/constants.js.map +0 -1
  168. package/dist/esm/import-protection-plugin/defaults.js.map +0 -1
  169. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +0 -1
  170. package/dist/esm/import-protection-plugin/matchers.js.map +0 -1
  171. package/dist/esm/import-protection-plugin/plugin.js.map +0 -1
  172. package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +0 -13
  173. package/dist/esm/import-protection-plugin/postCompileUsage.js +0 -63
  174. package/dist/esm/import-protection-plugin/postCompileUsage.js.map +0 -1
  175. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +0 -205
  176. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +0 -1
  177. package/dist/esm/import-protection-plugin/sourceLocation.js.map +0 -1
  178. package/dist/esm/import-protection-plugin/trace.js.map +0 -1
  179. package/dist/esm/import-protection-plugin/utils.js.map +0 -1
  180. package/dist/esm/import-protection-plugin/virtualModules.d.ts +0 -78
  181. package/dist/esm/import-protection-plugin/virtualModules.js.map +0 -1
  182. package/dist/esm/start-compiler/load-module.d.ts +0 -14
  183. package/dist/esm/start-compiler/load-module.js +0 -18
  184. package/dist/esm/start-compiler/load-module.js.map +0 -1
  185. package/src/import-protection-plugin/INTERNALS.md +0 -700
  186. package/src/import-protection-plugin/postCompileUsage.ts +0 -100
  187. package/src/import-protection-plugin/rewriteDeniedImports.ts +0 -379
  188. package/src/start-compiler/load-module.ts +0 -31
  189. /package/dist/esm/{import-protection-plugin → import-protection}/ast.d.ts +0 -0
  190. /package/dist/esm/{import-protection-plugin → import-protection}/defaults.d.ts +0 -0
  191. /package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.d.ts +0 -0
  192. /package/dist/esm/{import-protection-plugin → import-protection}/matchers.d.ts +0 -0
  193. /package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.d.ts +0 -0
  194. /package/src/{import-protection-plugin → import-protection}/ast.ts +0 -0
  195. /package/src/{import-protection-plugin → import-protection}/defaults.ts +0 -0
  196. /package/src/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.ts +0 -0
  197. /package/src/{import-protection-plugin → import-protection}/matchers.ts +0 -0
@@ -1,15 +1,20 @@
1
1
  //#region src/vite/start-compiler-plugin/module-specifier.ts
2
2
  function createViteDevServerFnModuleSpecifierEncoder(root) {
3
- const rootWithTrailingSlash = root.endsWith("/") ? root : `${root}/`;
3
+ const normalizedRoot = root.replace(/\\/g, "/");
4
+ const rootWithTrailingSlash = normalizedRoot.endsWith("/") ? normalizedRoot : `${normalizedRoot}/`;
4
5
  return ({ extractedFilename }) => {
5
- let file = extractedFilename;
6
- if (file.startsWith(rootWithTrailingSlash)) file = file.slice(rootWithTrailingSlash.length);
7
- return `/@id/${file}`;
6
+ const normalizedFile = extractedFilename.replace(/\\/g, "/");
7
+ if (normalizedFile.startsWith(rootWithTrailingSlash)) return `/${normalizedFile.slice(rootWithTrailingSlash.length)}`;
8
+ return normalizedFile.startsWith("/") ? `/@fs${normalizedFile}` : `/@fs/${normalizedFile}`;
8
9
  };
9
10
  }
10
11
  function decodeViteDevServerModuleSpecifier(moduleSpecifier) {
11
12
  let sourceFile = moduleSpecifier;
12
13
  if (sourceFile.startsWith("/@id/")) sourceFile = sourceFile.slice(5);
14
+ else if (sourceFile.startsWith("/@fs/")) {
15
+ sourceFile = sourceFile.slice(4);
16
+ sourceFile = sourceFile.replace(/^\/([A-Za-z]:\/)/, "$1");
17
+ } else if (sourceFile.startsWith("/")) sourceFile = sourceFile.slice(1);
13
18
  const queryIndex = sourceFile.indexOf("?");
14
19
  return queryIndex === -1 ? sourceFile : sourceFile.slice(0, queryIndex);
15
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module-specifier.js","names":[],"sources":["../../../../src/vite/start-compiler-plugin/module-specifier.ts"],"sourcesContent":["import type { DevServerFnModuleSpecifierEncoder } from '../../start-compiler/types'\n\nexport function createViteDevServerFnModuleSpecifierEncoder(\n root: string,\n): DevServerFnModuleSpecifierEncoder {\n const rootWithTrailingSlash = root.endsWith('/') ? root : `${root}/`\n\n return ({ extractedFilename }) => {\n let file = extractedFilename\n\n if (file.startsWith(rootWithTrailingSlash)) {\n file = file.slice(rootWithTrailingSlash.length)\n }\n\n return `/@id/${file}`\n }\n}\n\nexport function decodeViteDevServerModuleSpecifier(\n moduleSpecifier: string,\n): string {\n let sourceFile = moduleSpecifier\n\n if (sourceFile.startsWith('/@id/')) {\n sourceFile = sourceFile.slice('/@id/'.length)\n }\n\n const queryIndex = sourceFile.indexOf('?')\n\n return queryIndex === -1 ? sourceFile : sourceFile.slice(0, queryIndex)\n}\n"],"mappings":";AAEA,SAAgB,4CACd,MACmC;CACnC,MAAM,wBAAwB,KAAK,SAAS,IAAI,GAAG,OAAO,GAAG,KAAK;AAElE,SAAQ,EAAE,wBAAwB;EAChC,IAAI,OAAO;AAEX,MAAI,KAAK,WAAW,sBAAsB,CACxC,QAAO,KAAK,MAAM,sBAAsB,OAAO;AAGjD,SAAO,QAAQ;;;AAInB,SAAgB,mCACd,iBACQ;CACR,IAAI,aAAa;AAEjB,KAAI,WAAW,WAAW,QAAQ,CAChC,cAAa,WAAW,MAAM,EAAe;CAG/C,MAAM,aAAa,WAAW,QAAQ,IAAI;AAE1C,QAAO,eAAe,KAAK,aAAa,WAAW,MAAM,GAAG,WAAW"}
1
+ {"version":3,"file":"module-specifier.js","names":[],"sources":["../../../../src/vite/start-compiler-plugin/module-specifier.ts"],"sourcesContent":["import type { DevServerFnModuleSpecifierEncoder } from '../../start-compiler/types'\n\nexport function createViteDevServerFnModuleSpecifierEncoder(\n root: string,\n): DevServerFnModuleSpecifierEncoder {\n const normalizedRoot = root.replace(/\\\\/g, '/')\n const rootWithTrailingSlash = normalizedRoot.endsWith('/')\n ? normalizedRoot\n : `${normalizedRoot}/`\n\n return ({ extractedFilename }) => {\n const normalizedFile = extractedFilename.replace(/\\\\/g, '/')\n\n if (normalizedFile.startsWith(rootWithTrailingSlash)) {\n return `/${normalizedFile.slice(rootWithTrailingSlash.length)}`\n }\n\n return normalizedFile.startsWith('/')\n ? `/@fs${normalizedFile}`\n : `/@fs/${normalizedFile}`\n }\n}\n\nexport function decodeViteDevServerModuleSpecifier(\n moduleSpecifier: string,\n): string {\n let sourceFile = moduleSpecifier\n\n if (sourceFile.startsWith('/@id/')) {\n sourceFile = sourceFile.slice('/@id/'.length)\n } else if (sourceFile.startsWith('/@fs/')) {\n sourceFile = sourceFile.slice('/@fs'.length)\n sourceFile = sourceFile.replace(/^\\/([A-Za-z]:\\/)/, '$1')\n } else if (sourceFile.startsWith('/')) {\n sourceFile = sourceFile.slice(1)\n }\n\n const queryIndex = sourceFile.indexOf('?')\n\n return queryIndex === -1 ? sourceFile : sourceFile.slice(0, queryIndex)\n}\n"],"mappings":";AAEA,SAAgB,4CACd,MACmC;CACnC,MAAM,iBAAiB,KAAK,QAAQ,OAAO,IAAI;CAC/C,MAAM,wBAAwB,eAAe,SAAS,IAAI,GACtD,iBACA,GAAG,eAAe;AAEtB,SAAQ,EAAE,wBAAwB;EAChC,MAAM,iBAAiB,kBAAkB,QAAQ,OAAO,IAAI;AAE5D,MAAI,eAAe,WAAW,sBAAsB,CAClD,QAAO,IAAI,eAAe,MAAM,sBAAsB,OAAO;AAG/D,SAAO,eAAe,WAAW,IAAI,GACjC,OAAO,mBACP,QAAQ;;;AAIhB,SAAgB,mCACd,iBACQ;CACR,IAAI,aAAa;AAEjB,KAAI,WAAW,WAAW,QAAQ,CAChC,cAAa,WAAW,MAAM,EAAe;UACpC,WAAW,WAAW,QAAQ,EAAE;AACzC,eAAa,WAAW,MAAM,EAAc;AAC5C,eAAa,WAAW,QAAQ,oBAAoB,KAAK;YAChD,WAAW,WAAW,IAAI,CACnC,cAAa,WAAW,MAAM,EAAE;CAGlC,MAAM,aAAa,WAAW,QAAQ,IAAI;AAE1C,QAAO,eAAe,KAAK,aAAa,WAAW,MAAM,GAAG,WAAW"}
@@ -5,14 +5,46 @@ import { cleanId } from "../../start-compiler/utils.js";
5
5
  import { detectKindsInCode } from "../../start-compiler/compiler.js";
6
6
  import { getTransformCodeFilterForEnv } from "../../start-compiler/config.js";
7
7
  import { createStartCompiler, mergeServerFnsById } from "../../start-compiler/host.js";
8
- import { loadModuleForViteCompiler } from "../../start-compiler/load-module.js";
9
8
  import { generateServerFnResolverModule } from "../../start-compiler/server-fn-resolver-module.js";
10
9
  import { createViteDevServerFnModuleSpecifierEncoder, decodeViteDevServerModuleSpecifier } from "./module-specifier.js";
10
+ import { mergeHotUpdateModules } from "./hot-update.js";
11
11
  import { resolve } from "pathe";
12
- import assert from "node:assert";
13
12
  import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
14
13
  //#region src/vite/start-compiler-plugin/plugin.ts
15
14
  var validateServerFnIdVirtualModule = `virtual:tanstack-start-validate-server-fn-id`;
15
+ var TSS_SERVERFN_SPLIT_PARAM = "tss-serverfn-split";
16
+ function invalidateMatchingFileModules(environment, ids, shouldInvalidate) {
17
+ const seen = /* @__PURE__ */ new Set();
18
+ const invalidatedModules = [];
19
+ for (const id of ids) {
20
+ const fileModules = environment.moduleGraph.getModulesByFile(cleanId(id));
21
+ if (!fileModules) continue;
22
+ for (const fileModule of fileModules) {
23
+ if (!shouldInvalidate(fileModule)) continue;
24
+ environment.moduleGraph.invalidateModule(fileModule, seen);
25
+ invalidatedModules.push(fileModule);
26
+ }
27
+ }
28
+ return invalidatedModules;
29
+ }
30
+ function invalidateServerFnProviderModules(environment, ids) {
31
+ return invalidateMatchingFileModules(environment, ids, (fileModule) => fileModule.id?.includes(TSS_SERVERFN_SPLIT_PARAM) ?? false);
32
+ }
33
+ function invalidateServerFnLookupModules(environment, ids) {
34
+ invalidateMatchingFileModules(environment, ids, (fileModule) => fileModule.id?.includes("server-fn-module-lookup") ?? false);
35
+ }
36
+ function getServerFnProviderIds(ids) {
37
+ const providerIds = /* @__PURE__ */ new Set();
38
+ for (const id of ids) {
39
+ const cleanedId = cleanId(id);
40
+ providerIds.add(`${cleanedId}?${TSS_SERVERFN_SPLIT_PARAM}`);
41
+ }
42
+ return providerIds;
43
+ }
44
+ function invalidateModuleNodes(environment, modules) {
45
+ const seen = /* @__PURE__ */ new Set();
46
+ for (const mod of modules) environment.moduleGraph.invalidateModule(mod, seen);
47
+ }
16
48
  function getDevServerFnValidatorModule() {
17
49
  return `
18
50
  export async function getServerFnById(id, _access) {
@@ -81,13 +113,16 @@ function startCompilerPlugin(opts) {
81
113
  getKnownServerFns: () => serverFnsById,
82
114
  encodeModuleSpecifierInDev: mode === "dev" ? createViteDevServerFnModuleSpecifierEncoder(root) : void 0,
83
115
  loadModule: async (id) => {
84
- await loadModuleForViteCompiler({
85
- compiler,
86
- mode: this.environment.mode,
87
- fetchModule: this.environment.mode === "dev" ? this.environment.fetchModule.bind(this.environment) : void 0,
88
- loadModule: this.load.bind(this),
89
- id
90
- });
116
+ if (mode === "build") {
117
+ const code = (await this.load({ id })).code ?? "";
118
+ compiler.ingestModule({
119
+ code,
120
+ id
121
+ });
122
+ return;
123
+ }
124
+ if (this.environment.mode !== "dev") this.error(`could not load module ${id}: unknown environment mode ${this.environment.mode}`);
125
+ await this.environment.transformRequest(`${id}?${SERVER_FN_LOOKUP}`);
91
126
  },
92
127
  resolveId: async (source, importer) => {
93
128
  const r = await this.resolve(source, importer);
@@ -109,13 +144,51 @@ function startCompilerPlugin(opts) {
109
144
  },
110
145
  hotUpdate(ctx) {
111
146
  const compiler = compilers.get(this.environment.name);
147
+ const idsToInvalidate = /* @__PURE__ */ new Set();
148
+ const transitiveCompilerImportersToInvalidate = /* @__PURE__ */ new Set();
149
+ const importerModulesToInvalidate = /* @__PURE__ */ new Set();
112
150
  ctx.modules.forEach((m) => {
113
151
  if (m.id) {
114
- if (compiler?.invalidateModule(m.id)) m.importers.forEach((importer) => {
115
- if (importer.id) compiler?.invalidateModule(importer.id);
152
+ idsToInvalidate.add(m.id);
153
+ const deleted = compiler?.invalidateModule(m.id);
154
+ if (deleted) transitiveCompilerImportersToInvalidate.add(cleanId(m.id));
155
+ if (deleted) m.importers.forEach((importer) => {
156
+ if (importer.id) {
157
+ idsToInvalidate.add(importer.id);
158
+ importerModulesToInvalidate.add(importer);
159
+ transitiveCompilerImportersToInvalidate.add(cleanId(importer.id));
160
+ }
116
161
  });
117
162
  }
118
163
  });
164
+ const finishHotUpdate = async () => {
165
+ if (environment.type === "server" && compiler) {
166
+ const pendingImporters = [...transitiveCompilerImportersToInvalidate];
167
+ const seenImporters = new Set(pendingImporters);
168
+ while (pendingImporters.length > 0) {
169
+ const importerId = pendingImporters.pop();
170
+ const nestedImporters = await compiler.getTransitiveImporters(importerId);
171
+ for (const nestedImporterId of nestedImporters) {
172
+ if (seenImporters.has(nestedImporterId)) continue;
173
+ seenImporters.add(nestedImporterId);
174
+ pendingImporters.push(nestedImporterId);
175
+ }
176
+ }
177
+ for (const importerId of seenImporters) {
178
+ idsToInvalidate.add(importerId);
179
+ compiler.invalidateModule(importerId);
180
+ }
181
+ }
182
+ invalidateModuleNodes(this.environment, importerModulesToInvalidate);
183
+ invalidateServerFnLookupModules(this.environment, idsToInvalidate);
184
+ if (environment.type !== "server") return;
185
+ invalidateModuleNodes(this.environment, ctx.modules);
186
+ const providerIdsToInvalidate = getServerFnProviderIds(idsToInvalidate);
187
+ for (const providerId of providerIdsToInvalidate) compiler?.invalidateModule(providerId);
188
+ const providerModules = invalidateServerFnProviderModules(this.environment, [...idsToInvalidate, ...providerIdsToInvalidate]);
189
+ return mergeHotUpdateModules(ctx.modules, providerModules);
190
+ };
191
+ return finishHotUpdate();
119
192
  }
120
193
  };
121
194
  }
@@ -151,8 +224,8 @@ function startCompilerPlugin(opts) {
151
224
  const sourceFile = decodeViteDevServerModuleSpecifier(decoded.file);
152
225
  if (sourceFile) {
153
226
  const absPath = resolve(root, sourceFile);
154
- assert(this.environment.mode === "dev");
155
- await this.environment.fetchModule(absPath);
227
+ if (this.environment.mode !== "dev") this.error(`could not validate server function ID ${fnId}: unknown environment mode ${this.environment.mode}`);
228
+ await this.environment.transformRequest(`${absPath}?${SERVER_FN_LOOKUP}`);
156
229
  if (serverFnsById[fnId]) return `export {}`;
157
230
  }
158
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../../../src/vite/start-compiler-plugin/plugin.ts"],"sourcesContent":["import assert from 'node:assert'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { resolve as resolvePath } from 'pathe'\nimport {\n SERVER_FN_LOOKUP,\n TRANSFORM_ID_REGEX,\n VITE_ENVIRONMENT_NAMES,\n} from '../../constants'\nimport { detectKindsInCode } from '../../start-compiler/compiler'\nimport { getTransformCodeFilterForEnv } from '../../start-compiler/config'\nimport {\n createStartCompiler,\n mergeServerFnsById,\n} from '../../start-compiler/host'\nimport { loadModuleForViteCompiler } from '../../start-compiler/load-module'\nimport { generateServerFnResolverModule } from '../../start-compiler/server-fn-resolver-module'\nimport { cleanId } from '../../start-compiler/utils'\nimport { createVirtualModule } from '../createVirtualModule'\nimport { resolveViteId } from '../../utils'\nimport {\n createViteDevServerFnModuleSpecifierEncoder,\n decodeViteDevServerModuleSpecifier,\n} from './module-specifier'\nimport type { CompileStartFrameworkOptions } from '../../types'\nimport type {\n GenerateFunctionIdFnOptional,\n ServerFn,\n} from '../../start-compiler/types'\nimport type { PluginOption } from 'vite'\n\n// Re-export from shared constants for backwards compatibility\nexport { SERVER_FN_LOOKUP }\n\nconst validateServerFnIdVirtualModule = `virtual:tanstack-start-validate-server-fn-id`\n\nfunction getDevServerFnValidatorModule(): string {\n return `\nexport async function getServerFnById(id, _access) {\n const validateIdImport = ${JSON.stringify(validateServerFnIdVirtualModule)} + '?id=' + id\n await import(/* @vite-ignore */ '/@id/__x00__' + validateIdImport)\n const decoded = Buffer.from(id, 'base64url').toString('utf8')\n const devServerFn = JSON.parse(decoded)\n const mod = await import(/* @vite-ignore */ devServerFn.file)\n return mod[devServerFn.export]\n}\n`\n}\n\nfunction parseIdQuery(id: string): {\n filename: string\n query: {\n [k: string]: string\n }\n} {\n if (!id.includes('?')) return { filename: id, query: {} }\n const [filename, rawQuery] = id.split(`?`, 2) as [string, string]\n const query = Object.fromEntries(new URLSearchParams(rawQuery))\n return { filename, query }\n}\n\nexport interface StartCompilerPluginOptions {\n framework: CompileStartFrameworkOptions\n environments: Array<{\n name: string\n type: 'client' | 'server'\n getServerFnById?: string\n }>\n /**\n * Custom function ID generator (optional).\n */\n generateFunctionId?: GenerateFunctionIdFnOptional\n /**\n * The Vite environment name for the server function provider.\n */\n providerEnvName: string\n}\n\nexport function startCompilerPlugin(\n opts: StartCompilerPluginOptions,\n): PluginOption {\n const compilers = new Map<string, ReturnType<typeof createStartCompiler>>()\n\n // Shared registry of server functions across all environments\n const serverFnsById: Record<string, ServerFn> = {}\n\n const onServerFnsById = (d: Record<string, ServerFn>) => {\n mergeServerFnsById(serverFnsById, d)\n }\n\n let root = process.cwd()\n // Determine which environments need the resolver (getServerFnById)\n // SSR environment always needs the resolver for server-side calls\n // Provider environment needs it for the actual implementation\n const ssrEnvName = VITE_ENVIRONMENT_NAMES.server\n\n // SSR is the provider when the provider environment is the default server environment\n const ssrIsProvider = opts.providerEnvName === ssrEnvName\n\n // Environments that need the resolver: SSR (for server calls) and provider (for implementation)\n const appliedResolverEnvironments = new Set(\n ssrIsProvider ? [opts.providerEnvName] : [ssrEnvName, opts.providerEnvName],\n )\n\n function perEnvServerFnPlugin(environment: {\n name: string\n type: 'client' | 'server'\n }): PluginOption {\n // Derive transform code filter from KindDetectionPatterns (single source of truth)\n const transformCodeFilter = getTransformCodeFilterForEnv(environment.type)\n return {\n name: `tanstack-start-core::server-fn:${environment.name}`,\n enforce: 'pre',\n applyToEnvironment(env) {\n return env.name === environment.name\n },\n configResolved(config) {\n root = config.root\n },\n transform: {\n filter: {\n id: {\n exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),\n include: TRANSFORM_ID_REGEX,\n },\n code: {\n include: transformCodeFilter,\n },\n },\n async handler(code, id) {\n let compiler = compilers.get(this.environment.name)\n\n if (!compiler) {\n // Default to 'dev' mode for unknown environments (conservative: no caching)\n const mode = this.environment.mode === 'build' ? 'build' : 'dev'\n\n compiler = createStartCompiler({\n env: environment.type,\n envName: environment.name,\n root,\n mode,\n framework: opts.framework,\n providerEnvName: opts.providerEnvName,\n generateFunctionId: opts.generateFunctionId,\n onServerFnsById,\n getKnownServerFns: () => serverFnsById,\n encodeModuleSpecifierInDev:\n mode === 'dev'\n ? createViteDevServerFnModuleSpecifierEncoder(root)\n : undefined,\n loadModule: async (id: string) => {\n await loadModuleForViteCompiler({\n compiler: compiler!,\n mode: this.environment.mode,\n fetchModule:\n this.environment.mode === 'dev'\n ? this.environment.fetchModule.bind(this.environment)\n : undefined,\n loadModule: this.load.bind(this),\n id,\n })\n },\n\n resolveId: async (source: string, importer?: string) => {\n const r = await this.resolve(source, importer)\n\n if (r) {\n if (!r.external) {\n return cleanId(r.id)\n }\n }\n\n return null\n },\n })\n\n compilers.set(this.environment.name, compiler)\n }\n\n // Detect which kinds are present in this file before parsing\n const detectedKinds = detectKindsInCode(code, environment.type)\n\n const result = await compiler.compile({\n id,\n code,\n detectedKinds,\n })\n return result\n },\n },\n\n hotUpdate(ctx) {\n const compiler = compilers.get(this.environment.name)\n\n ctx.modules.forEach((m) => {\n if (m.id) {\n const deleted = compiler?.invalidateModule(m.id)\n if (deleted) {\n m.importers.forEach((importer) => {\n if (importer.id) {\n compiler?.invalidateModule(importer.id)\n }\n })\n }\n }\n })\n },\n }\n }\n\n return [\n ...opts.environments.map(perEnvServerFnPlugin),\n {\n name: 'tanstack-start-core:capture-server-fn-module-lookup',\n // we only need this plugin in dev mode\n apply: 'serve',\n applyToEnvironment(env) {\n return !!opts.environments.find((e) => e.name === env.name)\n },\n transform: {\n filter: {\n id: new RegExp(`${SERVER_FN_LOOKUP}$`),\n },\n handler(code, id) {\n const compiler = compilers.get(this.environment.name)\n compiler?.ingestModule({ code, id: cleanId(id) })\n },\n },\n },\n // Validate server function ID in dev mode\n {\n name: 'tanstack-start-core:validate-server-fn-id',\n apply: 'serve',\n load: {\n filter: {\n id: new RegExp(resolveViteId(validateServerFnIdVirtualModule)),\n },\n async handler(id) {\n const parsed = parseIdQuery(id)\n const fnId = parsed.query.id\n if (fnId && serverFnsById[fnId]) {\n return `export {}`\n }\n\n // ID not yet registered — the source file may not have been\n // transformed in this dev session yet (e.g. cold restart with\n // cached client). Try to decode the ID, discover the source\n // file, trigger its compilation, and re-check.\n if (fnId) {\n try {\n const decoded = JSON.parse(\n Buffer.from(fnId, 'base64url').toString('utf8'),\n )\n if (\n typeof decoded.file === 'string' &&\n typeof decoded.export === 'string'\n ) {\n // Use the Vite strategy to decode the module specifier\n // back to the original source file path.\n const sourceFile = decodeViteDevServerModuleSpecifier(\n decoded.file,\n )\n\n if (sourceFile) {\n // Resolve to absolute path\n const absPath = resolvePath(root, sourceFile)\n\n // Trigger transform of the source file in this environment,\n // which will compile createServerFn calls and populate\n // serverFnsById as a side effect.\n // This plugin only runs in dev (apply: 'serve'), so mode\n // must be 'dev' — assert to narrow to DevEnvironment.\n assert(this.environment.mode === 'dev')\n await this.environment.fetchModule(absPath)\n\n // Re-check after lazy compilation\n if (serverFnsById[fnId]) {\n return `export {}`\n }\n }\n }\n } catch {\n // Decoding or fetching failed — fall through to error\n }\n }\n\n this.error(`Invalid server function ID: ${fnId}`)\n },\n },\n },\n // Manifest plugin for server environments\n createVirtualModule({\n name: 'tanstack-start-core:server-fn-resolver',\n moduleId: VIRTUAL_MODULES.serverFnResolver,\n enforce: 'pre',\n applyToEnvironment: (env) => {\n return appliedResolverEnvironments.has(env.name)\n },\n load() {\n if (this.environment.name !== opts.providerEnvName) {\n const mod = opts.environments.find(\n (e) => e.name === this.environment.name,\n )?.getServerFnById\n if (mod) {\n return mod\n }\n\n this.error(\n `No getServerFnById implementation found for caller environment: ${this.environment.name}`,\n )\n }\n\n if (this.environment.mode !== 'build') {\n return getDevServerFnValidatorModule()\n }\n\n // When SSR is the provider, server-only-referenced functions aren't in the manifest,\n // so no isClientReferenced check is needed.\n // When SSR is NOT the provider (custom provider env), server-only-referenced\n // functions ARE in the manifest and need the isClientReferenced check to\n // block direct client HTTP requests to server-only-referenced functions.\n return generateServerFnResolverModule({\n serverFnsById,\n includeClientReferencedCheck: !ssrIsProvider,\n })\n },\n }),\n ]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../../../../src/vite/start-compiler-plugin/plugin.ts"],"sourcesContent":["import { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { resolve as resolvePath } from 'pathe'\nimport {\n SERVER_FN_LOOKUP,\n TRANSFORM_ID_REGEX,\n VITE_ENVIRONMENT_NAMES,\n} from '../../constants'\nimport { detectKindsInCode } from '../../start-compiler/compiler'\nimport { getTransformCodeFilterForEnv } from '../../start-compiler/config'\nimport {\n createStartCompiler,\n mergeServerFnsById,\n} from '../../start-compiler/host'\nimport { generateServerFnResolverModule } from '../../start-compiler/server-fn-resolver-module'\nimport { cleanId } from '../../start-compiler/utils'\nimport { createVirtualModule } from '../createVirtualModule'\nimport { resolveViteId } from '../../utils'\nimport {\n createViteDevServerFnModuleSpecifierEncoder,\n decodeViteDevServerModuleSpecifier,\n} from './module-specifier'\nimport { mergeHotUpdateModules } from './hot-update'\nimport type { CompileStartFrameworkOptions } from '../../types'\nimport type {\n GenerateFunctionIdFnOptional,\n ServerFn,\n} from '../../start-compiler/types'\nimport type { EnvironmentModuleNode, PluginOption } from 'vite'\n\n// Re-export from shared constants for backwards compatibility\nexport { SERVER_FN_LOOKUP }\n\nconst validateServerFnIdVirtualModule = `virtual:tanstack-start-validate-server-fn-id`\nconst TSS_SERVERFN_SPLIT_PARAM = 'tss-serverfn-split'\n\ntype ModuleInvalidationEnvironment = {\n moduleGraph: {\n getModulesByFile: (file: string) => Set<EnvironmentModuleNode> | undefined\n invalidateModule: (\n mod: EnvironmentModuleNode,\n seen?: Set<EnvironmentModuleNode>,\n ) => void\n }\n}\n\nfunction invalidateMatchingFileModules(\n environment: ModuleInvalidationEnvironment,\n ids: Iterable<string>,\n shouldInvalidate: (mod: EnvironmentModuleNode) => boolean,\n) {\n const seen = new Set<EnvironmentModuleNode>()\n const invalidatedModules: Array<EnvironmentModuleNode> = []\n\n for (const id of ids) {\n const fileModules = environment.moduleGraph.getModulesByFile(cleanId(id))\n\n if (!fileModules) {\n continue\n }\n\n for (const fileModule of fileModules) {\n if (!shouldInvalidate(fileModule)) {\n continue\n }\n\n environment.moduleGraph.invalidateModule(fileModule, seen)\n invalidatedModules.push(fileModule)\n }\n }\n\n return invalidatedModules\n}\n\nfunction invalidateServerFnProviderModules(\n environment: {\n moduleGraph: {\n getModulesByFile: (file: string) => Set<EnvironmentModuleNode> | undefined\n invalidateModule: (\n mod: EnvironmentModuleNode,\n seen?: Set<EnvironmentModuleNode>,\n ) => void\n }\n },\n ids: Iterable<string>,\n) {\n return invalidateMatchingFileModules(\n environment,\n ids,\n (fileModule) => fileModule.id?.includes(TSS_SERVERFN_SPLIT_PARAM) ?? false,\n )\n}\n\nfunction invalidateServerFnLookupModules(\n environment: ModuleInvalidationEnvironment,\n ids: Iterable<string>,\n) {\n invalidateMatchingFileModules(\n environment,\n ids,\n (fileModule) => fileModule.id?.includes(SERVER_FN_LOOKUP) ?? false,\n )\n}\n\nfunction getServerFnProviderIds(ids: Iterable<string>) {\n const providerIds = new Set<string>()\n\n for (const id of ids) {\n const cleanedId = cleanId(id)\n providerIds.add(`${cleanedId}?${TSS_SERVERFN_SPLIT_PARAM}`)\n }\n\n return providerIds\n}\n\nfunction invalidateModuleNodes(\n environment: {\n moduleGraph: {\n invalidateModule: (\n mod: EnvironmentModuleNode,\n seen?: Set<EnvironmentModuleNode>,\n ) => void\n }\n },\n modules: Iterable<EnvironmentModuleNode>,\n) {\n const seen = new Set<EnvironmentModuleNode>()\n\n for (const mod of modules) {\n environment.moduleGraph.invalidateModule(mod, seen)\n }\n}\n\nfunction getDevServerFnValidatorModule(): string {\n return `\nexport async function getServerFnById(id, _access) {\n const validateIdImport = ${JSON.stringify(validateServerFnIdVirtualModule)} + '?id=' + id\n await import(/* @vite-ignore */ '/@id/__x00__' + validateIdImport)\n const decoded = Buffer.from(id, 'base64url').toString('utf8')\n const devServerFn = JSON.parse(decoded)\n const mod = await import(/* @vite-ignore */ devServerFn.file)\n return mod[devServerFn.export]\n}\n`\n}\n\nfunction parseIdQuery(id: string): {\n filename: string\n query: {\n [k: string]: string\n }\n} {\n if (!id.includes('?')) return { filename: id, query: {} }\n const [filename, rawQuery] = id.split(`?`, 2) as [string, string]\n const query = Object.fromEntries(new URLSearchParams(rawQuery))\n return { filename, query }\n}\n\nexport interface StartCompilerPluginOptions {\n framework: CompileStartFrameworkOptions\n environments: Array<{\n name: string\n type: 'client' | 'server'\n getServerFnById?: string\n }>\n /**\n * Custom function ID generator (optional).\n */\n generateFunctionId?: GenerateFunctionIdFnOptional\n /**\n * The Vite environment name for the server function provider.\n */\n providerEnvName: string\n}\n\nexport function startCompilerPlugin(\n opts: StartCompilerPluginOptions,\n): PluginOption {\n const compilers = new Map<string, ReturnType<typeof createStartCompiler>>()\n\n // Shared registry of server functions across all environments\n const serverFnsById: Record<string, ServerFn> = {}\n\n const onServerFnsById = (d: Record<string, ServerFn>) => {\n mergeServerFnsById(serverFnsById, d)\n }\n\n let root = process.cwd()\n // Determine which environments need the resolver (getServerFnById)\n // SSR environment always needs the resolver for server-side calls\n // Provider environment needs it for the actual implementation\n const ssrEnvName = VITE_ENVIRONMENT_NAMES.server\n\n // SSR is the provider when the provider environment is the default server environment\n const ssrIsProvider = opts.providerEnvName === ssrEnvName\n\n // Environments that need the resolver: SSR (for server calls) and provider (for implementation)\n const appliedResolverEnvironments = new Set(\n ssrIsProvider ? [opts.providerEnvName] : [ssrEnvName, opts.providerEnvName],\n )\n\n function perEnvServerFnPlugin(environment: {\n name: string\n type: 'client' | 'server'\n }): PluginOption {\n // Derive transform code filter from KindDetectionPatterns (single source of truth)\n const transformCodeFilter = getTransformCodeFilterForEnv(environment.type)\n return {\n name: `tanstack-start-core::server-fn:${environment.name}`,\n enforce: 'pre',\n applyToEnvironment(env) {\n return env.name === environment.name\n },\n configResolved(config) {\n root = config.root\n },\n transform: {\n filter: {\n id: {\n exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),\n include: TRANSFORM_ID_REGEX,\n },\n code: {\n include: transformCodeFilter,\n },\n },\n async handler(code, id) {\n let compiler = compilers.get(this.environment.name)\n\n if (!compiler) {\n // Default to 'dev' mode for unknown environments (conservative: no caching)\n const mode = this.environment.mode === 'build' ? 'build' : 'dev'\n\n compiler = createStartCompiler({\n env: environment.type,\n envName: environment.name,\n root,\n mode,\n framework: opts.framework,\n providerEnvName: opts.providerEnvName,\n generateFunctionId: opts.generateFunctionId,\n onServerFnsById,\n getKnownServerFns: () => serverFnsById,\n encodeModuleSpecifierInDev:\n mode === 'dev'\n ? createViteDevServerFnModuleSpecifierEncoder(root)\n : undefined,\n loadModule: async (id: string) => {\n if (mode === 'build') {\n const loaded = await this.load({ id })\n const code = loaded.code ?? ''\n\n compiler!.ingestModule({ code, id })\n return\n }\n\n if (this.environment.mode !== 'dev') {\n this.error(\n `could not load module ${id}: unknown environment mode ${this.environment.mode}`,\n )\n }\n\n await this.environment.transformRequest(\n `${id}?${SERVER_FN_LOOKUP}`,\n )\n },\n\n resolveId: async (source: string, importer?: string) => {\n const r = await this.resolve(source, importer)\n\n if (r) {\n if (!r.external) {\n return cleanId(r.id)\n }\n }\n\n return null\n },\n })\n\n compilers.set(this.environment.name, compiler)\n }\n\n // Detect which kinds are present in this file before parsing\n const detectedKinds = detectKindsInCode(code, environment.type)\n\n const result = await compiler.compile({\n id,\n code,\n detectedKinds,\n })\n return result\n },\n },\n\n hotUpdate(ctx) {\n const compiler = compilers.get(this.environment.name)\n const idsToInvalidate = new Set<string>()\n const transitiveCompilerImportersToInvalidate = new Set<string>()\n const importerModulesToInvalidate = new Set<EnvironmentModuleNode>()\n\n ctx.modules.forEach((m) => {\n if (m.id) {\n idsToInvalidate.add(m.id)\n const deleted = compiler?.invalidateModule(m.id)\n\n if (deleted) {\n transitiveCompilerImportersToInvalidate.add(cleanId(m.id))\n }\n\n if (deleted) {\n m.importers.forEach((importer) => {\n if (importer.id) {\n idsToInvalidate.add(importer.id)\n importerModulesToInvalidate.add(importer)\n transitiveCompilerImportersToInvalidate.add(\n cleanId(importer.id),\n )\n }\n })\n }\n }\n })\n\n const finishHotUpdate = async () => {\n if (environment.type === 'server' && compiler) {\n const pendingImporters = [\n ...transitiveCompilerImportersToInvalidate,\n ]\n const seenImporters = new Set(pendingImporters)\n\n while (pendingImporters.length > 0) {\n const importerId = pendingImporters.pop()!\n const nestedImporters =\n await compiler.getTransitiveImporters(importerId)\n\n for (const nestedImporterId of nestedImporters) {\n if (seenImporters.has(nestedImporterId)) {\n continue\n }\n\n seenImporters.add(nestedImporterId)\n pendingImporters.push(nestedImporterId)\n }\n }\n\n for (const importerId of seenImporters) {\n idsToInvalidate.add(importerId)\n compiler.invalidateModule(importerId)\n }\n }\n\n invalidateModuleNodes(this.environment, importerModulesToInvalidate)\n invalidateServerFnLookupModules(this.environment, idsToInvalidate)\n\n if (environment.type !== 'server') {\n return\n }\n\n invalidateModuleNodes(this.environment, ctx.modules)\n\n const providerIdsToInvalidate =\n getServerFnProviderIds(idsToInvalidate)\n for (const providerId of providerIdsToInvalidate) {\n compiler?.invalidateModule(providerId)\n }\n\n const providerModules = invalidateServerFnProviderModules(\n this.environment,\n [...idsToInvalidate, ...providerIdsToInvalidate],\n )\n\n return mergeHotUpdateModules(ctx.modules, providerModules)\n }\n\n return finishHotUpdate()\n },\n }\n }\n\n return [\n ...opts.environments.map(perEnvServerFnPlugin),\n {\n name: 'tanstack-start-core:capture-server-fn-module-lookup',\n // we only need this plugin in dev mode\n apply: 'serve',\n applyToEnvironment(env) {\n return !!opts.environments.find((e) => e.name === env.name)\n },\n transform: {\n filter: {\n id: new RegExp(`${SERVER_FN_LOOKUP}$`),\n },\n handler(code, id) {\n const compiler = compilers.get(this.environment.name)\n compiler?.ingestModule({ code, id: cleanId(id) })\n },\n },\n },\n // Validate server function ID in dev mode\n {\n name: 'tanstack-start-core:validate-server-fn-id',\n apply: 'serve',\n load: {\n filter: {\n id: new RegExp(resolveViteId(validateServerFnIdVirtualModule)),\n },\n async handler(id) {\n const parsed = parseIdQuery(id)\n const fnId = parsed.query.id\n if (fnId && serverFnsById[fnId]) {\n return `export {}`\n }\n\n // ID not yet registered — the source file may not have been\n // transformed in this dev session yet (e.g. cold restart with\n // cached client). Try to decode the ID, discover the source\n // file, trigger its compilation, and re-check.\n if (fnId) {\n try {\n const decoded = JSON.parse(\n Buffer.from(fnId, 'base64url').toString('utf8'),\n )\n if (\n typeof decoded.file === 'string' &&\n typeof decoded.export === 'string'\n ) {\n // Use the Vite strategy to decode the module specifier\n // back to the original source file path.\n const sourceFile = decodeViteDevServerModuleSpecifier(\n decoded.file,\n )\n\n if (sourceFile) {\n // Resolve to absolute path\n const absPath = resolvePath(root, sourceFile)\n\n // Trigger transform of the source file in this environment,\n // which will compile createServerFn calls and populate\n // serverFnsById as a side effect.\n if (this.environment.mode !== 'dev') {\n this.error(\n `could not validate server function ID ${fnId}: unknown environment mode ${this.environment.mode}`,\n )\n }\n\n await this.environment.transformRequest(\n `${absPath}?${SERVER_FN_LOOKUP}`,\n )\n\n // Re-check after lazy compilation\n if (serverFnsById[fnId]) {\n return `export {}`\n }\n }\n }\n } catch {\n // Decoding or fetching failed — fall through to error\n }\n }\n\n this.error(`Invalid server function ID: ${fnId}`)\n },\n },\n },\n // Manifest plugin for server environments\n createVirtualModule({\n name: 'tanstack-start-core:server-fn-resolver',\n moduleId: VIRTUAL_MODULES.serverFnResolver,\n enforce: 'pre',\n applyToEnvironment: (env) => {\n return appliedResolverEnvironments.has(env.name)\n },\n load() {\n if (this.environment.name !== opts.providerEnvName) {\n const mod = opts.environments.find(\n (e) => e.name === this.environment.name,\n )?.getServerFnById\n if (mod) {\n return mod\n }\n\n this.error(\n `No getServerFnById implementation found for caller environment: ${this.environment.name}`,\n )\n }\n\n if (this.environment.mode !== 'build') {\n return getDevServerFnValidatorModule()\n }\n\n // When SSR is the provider, server-only-referenced functions aren't in the manifest,\n // so no isClientReferenced check is needed.\n // When SSR is NOT the provider (custom provider env), server-only-referenced\n // functions ARE in the manifest and need the isClientReferenced check to\n // block direct client HTTP requests to server-only-referenced functions.\n return generateServerFnResolverModule({\n serverFnsById,\n includeClientReferencedCheck: !ssrIsProvider,\n })\n },\n }),\n ]\n}\n"],"mappings":"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"}
@@ -26,6 +26,7 @@ function normalizeViteClientBuild(clientBundle) {
26
26
  const chunkFileNamesByRouteFilePath = /* @__PURE__ */ new Map();
27
27
  const cssFilesBySourcePath = /* @__PURE__ */ new Map();
28
28
  for (const chunk of chunksByFileName.values()) {
29
+ const bundleEntry = clientBundle[chunk.fileName];
29
30
  if (chunk.isEntry) {
30
31
  if (entryChunkFileName) throw new Error(`multiple entries detected: ${entryChunkFileName} ${chunk.fileName}`);
31
32
  entryChunkFileName = chunk.fileName;
@@ -38,8 +39,7 @@ function normalizeViteClientBuild(clientBundle) {
38
39
  }
39
40
  chunkFileNames.push(chunk.fileName);
40
41
  }
41
- const bundleEntry = clientBundle[chunk.fileName];
42
- if (bundleEntry?.type === "chunk") for (const moduleId of bundleEntry.moduleIds) {
42
+ for (const moduleId of bundleEntry.moduleIds) {
43
43
  const queryIndex = moduleId.indexOf("?");
44
44
  const sourcePath = queryIndex >= 0 ? moduleId.slice(0, queryIndex) : moduleId;
45
45
  if (!sourcePath) continue;
@@ -1 +1 @@
1
- {"version":3,"file":"normalized-client-build.js","names":[],"sources":["../../../../src/vite/start-manifest-plugin/normalized-client-build.ts"],"sourcesContent":["import { tsrSplit } from '@tanstack/router-plugin'\nimport type { Rollup } from 'vite'\nimport type { NormalizedClientBuild, NormalizedClientChunk } from '../../types'\n\nexport function normalizeViteClientChunk(\n chunk: Rollup.OutputChunk,\n): NormalizedClientChunk {\n return {\n fileName: chunk.fileName,\n isEntry: chunk.isEntry,\n imports: chunk.imports,\n dynamicImports: chunk.dynamicImports,\n css: Array.from(chunk.viteMetadata?.importedCss ?? []),\n routeFilePaths: getRouteFilePathsFromModuleIds(chunk.moduleIds),\n }\n}\n\nexport function normalizeViteClientChunks(\n clientBundle: Rollup.OutputBundle,\n): ReadonlyMap<string, NormalizedClientChunk> {\n const chunksByFileName = new Map<string, NormalizedClientChunk>()\n\n for (const fileName in clientBundle) {\n const bundleEntry = clientBundle[fileName]!\n if (bundleEntry.type !== 'chunk') {\n continue\n }\n\n const normalizedChunk = normalizeViteClientChunk(bundleEntry)\n chunksByFileName.set(normalizedChunk.fileName, normalizedChunk)\n }\n\n return chunksByFileName\n}\n\nexport function normalizeViteClientBuild(\n clientBundle: Rollup.OutputBundle,\n): NormalizedClientBuild {\n let entryChunkFileName: string | undefined\n const chunksByFileName = normalizeViteClientChunks(clientBundle)\n const chunkFileNamesByRouteFilePath = new Map<string, Array<string>>()\n const cssFilesBySourcePath = new Map<string, Array<string>>()\n\n for (const chunk of chunksByFileName.values()) {\n if (chunk.isEntry) {\n if (entryChunkFileName) {\n throw new Error(\n `multiple entries detected: ${entryChunkFileName} ${chunk.fileName}`,\n )\n }\n entryChunkFileName = chunk.fileName\n }\n\n for (const routeFilePath of chunk.routeFilePaths) {\n let chunkFileNames = chunkFileNamesByRouteFilePath.get(routeFilePath)\n if (chunkFileNames === undefined) {\n chunkFileNames = []\n chunkFileNamesByRouteFilePath.set(routeFilePath, chunkFileNames)\n }\n chunkFileNames.push(chunk.fileName)\n }\n\n const bundleEntry = clientBundle[chunk.fileName]\n if (bundleEntry?.type === 'chunk') {\n for (const moduleId of bundleEntry.moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n const sourcePath =\n queryIndex >= 0 ? moduleId.slice(0, queryIndex) : moduleId\n if (!sourcePath) continue\n\n const existing = cssFilesBySourcePath.get(sourcePath)\n cssFilesBySourcePath.set(\n sourcePath,\n existing\n ? Array.from(new Set([...existing, ...chunk.css]))\n : chunk.css.slice(),\n )\n }\n }\n }\n\n if (!entryChunkFileName) {\n throw new Error('No entry file found')\n }\n\n return {\n entryChunkFileName,\n chunksByFileName,\n chunkFileNamesByRouteFilePath,\n cssFilesBySourcePath,\n }\n}\n\nexport function getRouteFilePathsFromModuleIds(moduleIds: Array<string>) {\n let routeFilePaths: Array<string> | undefined\n let seenRouteFilePaths: Set<string> | undefined\n\n for (const moduleId of moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n\n if (queryIndex < 0) {\n continue\n }\n\n const query = moduleId.slice(queryIndex + 1)\n\n if (!query.includes(tsrSplit)) {\n continue\n }\n\n if (!new URLSearchParams(query).has(tsrSplit)) {\n continue\n }\n\n const routeFilePath = moduleId.slice(0, queryIndex)\n\n if (seenRouteFilePaths?.has(routeFilePath)) {\n continue\n }\n\n if (routeFilePaths === undefined || seenRouteFilePaths === undefined) {\n routeFilePaths = []\n seenRouteFilePaths = new Set<string>()\n }\n\n routeFilePaths.push(routeFilePath)\n seenRouteFilePaths.add(routeFilePath)\n }\n\n return routeFilePaths ?? []\n}\n"],"mappings":";;AAIA,SAAgB,yBACd,OACuB;AACvB,QAAO;EACL,UAAU,MAAM;EAChB,SAAS,MAAM;EACf,SAAS,MAAM;EACf,gBAAgB,MAAM;EACtB,KAAK,MAAM,KAAK,MAAM,cAAc,eAAe,EAAE,CAAC;EACtD,gBAAgB,+BAA+B,MAAM,UAAU;EAChE;;AAGH,SAAgB,0BACd,cAC4C;CAC5C,MAAM,mCAAmB,IAAI,KAAoC;AAEjE,MAAK,MAAM,YAAY,cAAc;EACnC,MAAM,cAAc,aAAa;AACjC,MAAI,YAAY,SAAS,QACvB;EAGF,MAAM,kBAAkB,yBAAyB,YAAY;AAC7D,mBAAiB,IAAI,gBAAgB,UAAU,gBAAgB;;AAGjE,QAAO;;AAGT,SAAgB,yBACd,cACuB;CACvB,IAAI;CACJ,MAAM,mBAAmB,0BAA0B,aAAa;CAChE,MAAM,gDAAgC,IAAI,KAA4B;CACtE,MAAM,uCAAuB,IAAI,KAA4B;AAE7D,MAAK,MAAM,SAAS,iBAAiB,QAAQ,EAAE;AAC7C,MAAI,MAAM,SAAS;AACjB,OAAI,mBACF,OAAM,IAAI,MACR,8BAA8B,mBAAmB,GAAG,MAAM,WAC3D;AAEH,wBAAqB,MAAM;;AAG7B,OAAK,MAAM,iBAAiB,MAAM,gBAAgB;GAChD,IAAI,iBAAiB,8BAA8B,IAAI,cAAc;AACrE,OAAI,mBAAmB,KAAA,GAAW;AAChC,qBAAiB,EAAE;AACnB,kCAA8B,IAAI,eAAe,eAAe;;AAElE,kBAAe,KAAK,MAAM,SAAS;;EAGrC,MAAM,cAAc,aAAa,MAAM;AACvC,MAAI,aAAa,SAAS,QACxB,MAAK,MAAM,YAAY,YAAY,WAAW;GAC5C,MAAM,aAAa,SAAS,QAAQ,IAAI;GACxC,MAAM,aACJ,cAAc,IAAI,SAAS,MAAM,GAAG,WAAW,GAAG;AACpD,OAAI,CAAC,WAAY;GAEjB,MAAM,WAAW,qBAAqB,IAAI,WAAW;AACrD,wBAAqB,IACnB,YACA,WACI,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,GAChD,MAAM,IAAI,OAAO,CACtB;;;AAKP,KAAI,CAAC,mBACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,QAAO;EACL;EACA;EACA;EACA;EACD;;AAGH,SAAgB,+BAA+B,WAA0B;CACvE,IAAI;CACJ,IAAI;AAEJ,MAAK,MAAM,YAAY,WAAW;EAChC,MAAM,aAAa,SAAS,QAAQ,IAAI;AAExC,MAAI,aAAa,EACf;EAGF,MAAM,QAAQ,SAAS,MAAM,aAAa,EAAE;AAE5C,MAAI,CAAC,MAAM,SAAS,SAAS,CAC3B;AAGF,MAAI,CAAC,IAAI,gBAAgB,MAAM,CAAC,IAAI,SAAS,CAC3C;EAGF,MAAM,gBAAgB,SAAS,MAAM,GAAG,WAAW;AAEnD,MAAI,oBAAoB,IAAI,cAAc,CACxC;AAGF,MAAI,mBAAmB,KAAA,KAAa,uBAAuB,KAAA,GAAW;AACpE,oBAAiB,EAAE;AACnB,wCAAqB,IAAI,KAAa;;AAGxC,iBAAe,KAAK,cAAc;AAClC,qBAAmB,IAAI,cAAc;;AAGvC,QAAO,kBAAkB,EAAE"}
1
+ {"version":3,"file":"normalized-client-build.js","names":[],"sources":["../../../../src/vite/start-manifest-plugin/normalized-client-build.ts"],"sourcesContent":["import { tsrSplit } from '@tanstack/router-plugin'\nimport type { Rollup } from 'vite'\nimport type { NormalizedClientBuild, NormalizedClientChunk } from '../../types'\n\nexport function normalizeViteClientChunk(\n chunk: Rollup.OutputChunk,\n): NormalizedClientChunk {\n return {\n fileName: chunk.fileName,\n isEntry: chunk.isEntry,\n imports: chunk.imports,\n dynamicImports: chunk.dynamicImports,\n css: Array.from(chunk.viteMetadata?.importedCss ?? []),\n routeFilePaths: getRouteFilePathsFromModuleIds(chunk.moduleIds),\n }\n}\n\nexport function normalizeViteClientChunks(\n clientBundle: Rollup.OutputBundle,\n): ReadonlyMap<string, NormalizedClientChunk> {\n const chunksByFileName = new Map<string, NormalizedClientChunk>()\n\n for (const fileName in clientBundle) {\n const bundleEntry = clientBundle[fileName]!\n if (bundleEntry.type !== 'chunk') {\n continue\n }\n\n const normalizedChunk = normalizeViteClientChunk(bundleEntry)\n chunksByFileName.set(normalizedChunk.fileName, normalizedChunk)\n }\n\n return chunksByFileName\n}\n\nexport function normalizeViteClientBuild(\n clientBundle: Rollup.OutputBundle,\n): NormalizedClientBuild {\n let entryChunkFileName: string | undefined\n const chunksByFileName = normalizeViteClientChunks(clientBundle)\n const chunkFileNamesByRouteFilePath = new Map<string, Array<string>>()\n const cssFilesBySourcePath = new Map<string, Array<string>>()\n\n for (const chunk of chunksByFileName.values()) {\n const bundleEntry = clientBundle[chunk.fileName] as Rollup.OutputChunk\n\n if (chunk.isEntry) {\n if (entryChunkFileName) {\n throw new Error(\n `multiple entries detected: ${entryChunkFileName} ${chunk.fileName}`,\n )\n }\n entryChunkFileName = chunk.fileName\n }\n\n for (const routeFilePath of chunk.routeFilePaths) {\n let chunkFileNames = chunkFileNamesByRouteFilePath.get(routeFilePath)\n if (chunkFileNames === undefined) {\n chunkFileNames = []\n chunkFileNamesByRouteFilePath.set(routeFilePath, chunkFileNames)\n }\n chunkFileNames.push(chunk.fileName)\n }\n\n for (const moduleId of bundleEntry.moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n const sourcePath =\n queryIndex >= 0 ? moduleId.slice(0, queryIndex) : moduleId\n if (!sourcePath) continue\n\n const existing = cssFilesBySourcePath.get(sourcePath)\n cssFilesBySourcePath.set(\n sourcePath,\n existing\n ? Array.from(new Set([...existing, ...chunk.css]))\n : chunk.css.slice(),\n )\n }\n }\n\n if (!entryChunkFileName) {\n throw new Error('No entry file found')\n }\n\n return {\n entryChunkFileName,\n chunksByFileName,\n chunkFileNamesByRouteFilePath,\n cssFilesBySourcePath,\n }\n}\n\nexport function getRouteFilePathsFromModuleIds(moduleIds: Array<string>) {\n let routeFilePaths: Array<string> | undefined\n let seenRouteFilePaths: Set<string> | undefined\n\n for (const moduleId of moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n\n if (queryIndex < 0) {\n continue\n }\n\n const query = moduleId.slice(queryIndex + 1)\n\n if (!query.includes(tsrSplit)) {\n continue\n }\n\n if (!new URLSearchParams(query).has(tsrSplit)) {\n continue\n }\n\n const routeFilePath = moduleId.slice(0, queryIndex)\n\n if (seenRouteFilePaths?.has(routeFilePath)) {\n continue\n }\n\n if (routeFilePaths === undefined || seenRouteFilePaths === undefined) {\n routeFilePaths = []\n seenRouteFilePaths = new Set<string>()\n }\n\n routeFilePaths.push(routeFilePath)\n seenRouteFilePaths.add(routeFilePath)\n }\n\n return routeFilePaths ?? []\n}\n"],"mappings":";;AAIA,SAAgB,yBACd,OACuB;AACvB,QAAO;EACL,UAAU,MAAM;EAChB,SAAS,MAAM;EACf,SAAS,MAAM;EACf,gBAAgB,MAAM;EACtB,KAAK,MAAM,KAAK,MAAM,cAAc,eAAe,EAAE,CAAC;EACtD,gBAAgB,+BAA+B,MAAM,UAAU;EAChE;;AAGH,SAAgB,0BACd,cAC4C;CAC5C,MAAM,mCAAmB,IAAI,KAAoC;AAEjE,MAAK,MAAM,YAAY,cAAc;EACnC,MAAM,cAAc,aAAa;AACjC,MAAI,YAAY,SAAS,QACvB;EAGF,MAAM,kBAAkB,yBAAyB,YAAY;AAC7D,mBAAiB,IAAI,gBAAgB,UAAU,gBAAgB;;AAGjE,QAAO;;AAGT,SAAgB,yBACd,cACuB;CACvB,IAAI;CACJ,MAAM,mBAAmB,0BAA0B,aAAa;CAChE,MAAM,gDAAgC,IAAI,KAA4B;CACtE,MAAM,uCAAuB,IAAI,KAA4B;AAE7D,MAAK,MAAM,SAAS,iBAAiB,QAAQ,EAAE;EAC7C,MAAM,cAAc,aAAa,MAAM;AAEvC,MAAI,MAAM,SAAS;AACjB,OAAI,mBACF,OAAM,IAAI,MACR,8BAA8B,mBAAmB,GAAG,MAAM,WAC3D;AAEH,wBAAqB,MAAM;;AAG7B,OAAK,MAAM,iBAAiB,MAAM,gBAAgB;GAChD,IAAI,iBAAiB,8BAA8B,IAAI,cAAc;AACrE,OAAI,mBAAmB,KAAA,GAAW;AAChC,qBAAiB,EAAE;AACnB,kCAA8B,IAAI,eAAe,eAAe;;AAElE,kBAAe,KAAK,MAAM,SAAS;;AAGrC,OAAK,MAAM,YAAY,YAAY,WAAW;GAC5C,MAAM,aAAa,SAAS,QAAQ,IAAI;GACxC,MAAM,aACJ,cAAc,IAAI,SAAS,MAAM,GAAG,WAAW,GAAG;AACpD,OAAI,CAAC,WAAY;GAEjB,MAAM,WAAW,qBAAqB,IAAI,WAAW;AACrD,wBAAqB,IACnB,YACA,WACI,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,GAChD,MAAM,IAAI,OAAO,CACtB;;;AAIL,KAAI,CAAC,mBACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,QAAO;EACL;EACA;EACA;EACA;EACD;;AAGH,SAAgB,+BAA+B,WAA0B;CACvE,IAAI;CACJ,IAAI;AAEJ,MAAK,MAAM,YAAY,WAAW;EAChC,MAAM,aAAa,SAAS,QAAQ,IAAI;AAExC,MAAI,aAAa,EACf;EAGF,MAAM,QAAQ,SAAS,MAAM,aAAa,EAAE;AAE5C,MAAI,CAAC,MAAM,SAAS,SAAS,CAC3B;AAGF,MAAI,CAAC,IAAI,gBAAgB,MAAM,CAAC,IAAI,SAAS,CAC3C;EAGF,MAAM,gBAAgB,SAAS,MAAM,GAAG,WAAW;AAEnD,MAAI,oBAAoB,IAAI,cAAc,CACxC;AAGF,MAAI,mBAAmB,KAAA,KAAa,uBAAuB,KAAA,GAAW;AACpE,oBAAiB,EAAE;AACnB,wCAAqB,IAAI,KAAa;;AAGxC,iBAAe,KAAK,cAAc;AAClC,qBAAmB,IAAI,cAAc;;AAGvC,QAAO,kBAAkB,EAAE"}
@@ -1,6 +1,5 @@
1
- import { GetConfigFn, NormalizedClientBuild } from '../../types.js';
1
+ import { GetConfigFn } from '../../types.js';
2
2
  import { PluginOption } from 'vite';
3
3
  export declare function startManifestPlugin(opts: {
4
- getClientBuild: () => NormalizedClientBuild | undefined;
5
4
  getConfig: GetConfigFn;
6
5
  }): PluginOption;
@@ -1,34 +1,68 @@
1
1
  import { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from "../../constants.js";
2
2
  import { createVirtualModule } from "../createVirtualModule.js";
3
- import { buildStartManifest, serializeStartManifest } from "../../start-manifest-plugin/manifestBuilder.js";
3
+ import { normalizeViteClientBuild } from "./normalized-client-build.js";
4
+ import { buildStartManifest, createManifestAssetResolvers, serializeStartManifest } from "../../start-manifest-plugin/manifestBuilder.js";
5
+ import { rootRouteId } from "@tanstack/router-core";
4
6
  import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
5
7
  import { joinURL } from "ufo";
6
8
  //#region src/vite/start-manifest-plugin/plugin.ts
7
9
  function startManifestPlugin(opts) {
8
- return createVirtualModule({
10
+ let clientBuild;
11
+ let cssCodeSplitDisabledFileName;
12
+ return [{
13
+ name: "tanstack-start:start-manifest-capture-client-build",
14
+ applyToEnvironment(environment) {
15
+ return environment.name === START_ENVIRONMENT_NAMES.client;
16
+ },
17
+ enforce: "post",
18
+ generateBundle(_options, bundle) {
19
+ if (this.environment.name !== START_ENVIRONMENT_NAMES.client) throw new Error(`Unexpected environment for client build capture: ${this.environment.name}`);
20
+ clientBuild = normalizeViteClientBuild(bundle);
21
+ cssCodeSplitDisabledFileName = getAssetFileNameByName(bundle, "style.css");
22
+ }
23
+ }, createVirtualModule({
9
24
  name: "tanstack-start:start-manifest-plugin",
10
25
  moduleId: VIRTUAL_MODULES.startManifest,
11
26
  enforce: "pre",
12
27
  load() {
13
28
  const { resolvedStartConfig } = opts.getConfig();
14
- if (this.environment.name !== START_ENVIRONMENT_NAMES.server) return "export default {}";
15
- if (this.environment.config.command === "serve") return `export const tsrStartManifest = () => ({
16
- routes: {},
17
- clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, "@id", ENTRY_POINTS.client)}',
18
- })`;
29
+ const clientEntry = joinURL(resolvedStartConfig.basePaths.publicBase, "@id", ENTRY_POINTS.client);
30
+ if (this.environment.name !== START_ENVIRONMENT_NAMES.server) return getEmptyStartManifestModule(clientEntry);
31
+ if (this.environment.config.command === "serve") return getEmptyStartManifestModule(clientEntry);
19
32
  const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST;
20
- const clientBuild = opts.getClientBuild();
21
- if (!clientBuild) return `export const tsrStartManifest = () => ({
22
- routes: {},
23
- clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, "@id", ENTRY_POINTS.client)}',
24
- })`;
33
+ if (!clientBuild) return getEmptyStartManifestModule(clientEntry);
25
34
  return `export const tsrStartManifest = () => (${serializeStartManifest(buildStartManifest({
26
35
  clientBuild,
27
36
  routeTreeRoutes,
28
- basePath: resolvedStartConfig.basePaths.publicBase
37
+ basePath: resolvedStartConfig.basePaths.publicBase,
38
+ additionalRouteAssets: getViteAdditionalRouteAssets({
39
+ cssCodeSplitDisabledFileName,
40
+ basePath: resolvedStartConfig.basePaths.publicBase,
41
+ cssCodeSplit: this.environment.config.build.cssCodeSplit
42
+ })
29
43
  }))})`;
30
44
  }
31
- });
45
+ })];
46
+ }
47
+ function getViteAdditionalRouteAssets(options) {
48
+ if (options.cssCodeSplit !== false) return;
49
+ if (!options.cssCodeSplitDisabledFileName) throw new Error("TanStack Start could not find Vite's generated `style.css` manifest entry while `build.cssCodeSplit` is disabled");
50
+ const { getStylesheetAsset } = createManifestAssetResolvers(options.basePath);
51
+ return { [rootRouteId]: [getStylesheetAsset(options.cssCodeSplitDisabledFileName)] };
52
+ }
53
+ function getAssetFileNameByName(bundle, assetName) {
54
+ for (const fileName in bundle) {
55
+ const bundleEntry = bundle[fileName];
56
+ if (bundleEntry.type !== "asset") continue;
57
+ if (bundleEntry.name === assetName) return fileName;
58
+ if ("names" in bundleEntry && bundleEntry.names.includes(assetName)) return fileName;
59
+ }
60
+ }
61
+ function getEmptyStartManifestModule(clientEntry) {
62
+ return `export const tsrStartManifest = () => ({
63
+ routes: {},
64
+ clientEntry: '${clientEntry}',
65
+ })`;
32
66
  }
33
67
  //#endregion
34
68
  export { startManifestPlugin };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../../../src/vite/start-manifest-plugin/plugin.ts"],"sourcesContent":["import { joinURL } from 'ufo'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from '../../constants'\nimport {\n buildStartManifest,\n serializeStartManifest,\n} from '../../start-manifest-plugin/manifestBuilder'\nimport { createVirtualModule } from '../createVirtualModule'\nimport type { GetConfigFn, NormalizedClientBuild } from '../../types'\nimport type { PluginOption } from 'vite'\n\nexport function startManifestPlugin(opts: {\n getClientBuild: () => NormalizedClientBuild | undefined\n getConfig: GetConfigFn\n}): PluginOption {\n return createVirtualModule({\n name: 'tanstack-start:start-manifest-plugin',\n moduleId: VIRTUAL_MODULES.startManifest,\n enforce: 'pre',\n load() {\n const { resolvedStartConfig } = opts.getConfig()\n if (this.environment.name !== START_ENVIRONMENT_NAMES.server) {\n return 'export default {}'\n }\n\n if (this.environment.config.command === 'serve') {\n return `export const tsrStartManifest = () => ({\n routes: {},\n clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, '@id', ENTRY_POINTS.client)}',\n })`\n }\n\n const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST\n const clientBuild = opts.getClientBuild()\n // TODO this needs further discussion with vite-rsc, this is a temporary workaround\n // If the client bundle isn't available yet (e.g., during RSC scan builds),\n // return a dummy manifest. The real manifest will be generated in the actual build.\n if (!clientBuild) {\n return `export const tsrStartManifest = () => ({\n routes: {},\n clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, '@id', ENTRY_POINTS.client)}',\n })`\n }\n const startManifest = buildStartManifest({\n clientBuild,\n routeTreeRoutes,\n basePath: resolvedStartConfig.basePaths.publicBase,\n })\n\n return `export const tsrStartManifest = () => (${serializeStartManifest(startManifest)})`\n },\n })\n}\n"],"mappings":";;;;;;AAWA,SAAgB,oBAAoB,MAGnB;AACf,QAAO,oBAAoB;EACzB,MAAM;EACN,UAAU,gBAAgB;EAC1B,SAAS;EACT,OAAO;GACL,MAAM,EAAE,wBAAwB,KAAK,WAAW;AAChD,OAAI,KAAK,YAAY,SAAS,wBAAwB,OACpD,QAAO;AAGT,OAAI,KAAK,YAAY,OAAO,YAAY,QACtC,QAAO;;4BAEa,QAAQ,oBAAoB,UAAU,YAAY,OAAO,aAAa,OAAO,CAAC;;GAIpG,MAAM,kBAAkB,WAAW;GACnC,MAAM,cAAc,KAAK,gBAAgB;AAIzC,OAAI,CAAC,YACH,QAAO;;8BAEe,QAAQ,oBAAoB,UAAU,YAAY,OAAO,aAAa,OAAO,CAAC;;AAStG,UAAO,0CAA0C,uBAN3B,mBAAmB;IACvC;IACA;IACA,UAAU,oBAAoB,UAAU;IACzC,CAAC,CAEoF,CAAC;;EAE1F,CAAC"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../../../../src/vite/start-manifest-plugin/plugin.ts"],"sourcesContent":["import { joinURL } from 'ufo'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from '../../constants'\nimport {\n buildStartManifest,\n createManifestAssetResolvers,\n normalizeViteClientBuild,\n serializeStartManifest,\n} from '../../start-manifest-plugin/manifestBuilder'\nimport { createVirtualModule } from '../createVirtualModule'\nimport type { GetConfigFn, NormalizedClientBuild } from '../../types'\nimport type { PluginOption, Rollup } from 'vite'\n\nexport function startManifestPlugin(opts: {\n getConfig: GetConfigFn\n}): PluginOption {\n let clientBuild: NormalizedClientBuild | undefined\n let cssCodeSplitDisabledFileName: string | undefined\n\n return [\n {\n name: 'tanstack-start:start-manifest-capture-client-build',\n applyToEnvironment(environment) {\n return environment.name === START_ENVIRONMENT_NAMES.client\n },\n enforce: 'post',\n generateBundle(_options, bundle) {\n if (this.environment.name !== START_ENVIRONMENT_NAMES.client) {\n throw new Error(\n `Unexpected environment for client build capture: ${this.environment.name}`,\n )\n }\n\n clientBuild = normalizeViteClientBuild(bundle)\n cssCodeSplitDisabledFileName = getAssetFileNameByName(\n bundle,\n 'style.css',\n )\n },\n },\n createVirtualModule({\n name: 'tanstack-start:start-manifest-plugin',\n moduleId: VIRTUAL_MODULES.startManifest,\n enforce: 'pre',\n load() {\n const { resolvedStartConfig } = opts.getConfig()\n const clientEntry = joinURL(\n resolvedStartConfig.basePaths.publicBase,\n '@id',\n ENTRY_POINTS.client,\n )\n\n if (this.environment.name !== START_ENVIRONMENT_NAMES.server) {\n return getEmptyStartManifestModule(clientEntry)\n }\n\n if (this.environment.config.command === 'serve') {\n return getEmptyStartManifestModule(clientEntry)\n }\n\n const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST\n // TODO this needs further discussion with vite-rsc, this is a temporary workaround\n // If the client bundle isn't available yet (e.g., during RSC scan builds),\n // return a dummy manifest. The real manifest will be generated in the actual build.\n if (!clientBuild) {\n return getEmptyStartManifestModule(clientEntry)\n }\n const startManifest = buildStartManifest({\n clientBuild,\n routeTreeRoutes,\n basePath: resolvedStartConfig.basePaths.publicBase,\n additionalRouteAssets: getViteAdditionalRouteAssets({\n cssCodeSplitDisabledFileName,\n basePath: resolvedStartConfig.basePaths.publicBase,\n cssCodeSplit: this.environment.config.build.cssCodeSplit,\n }),\n })\n\n return `export const tsrStartManifest = () => (${serializeStartManifest(startManifest)})`\n },\n }),\n ]\n}\n\nfunction getViteAdditionalRouteAssets(options: {\n cssCodeSplitDisabledFileName: string | undefined\n basePath: string\n cssCodeSplit: boolean | undefined\n}) {\n if (options.cssCodeSplit !== false) {\n return undefined\n }\n\n if (!options.cssCodeSplitDisabledFileName) {\n throw new Error(\n \"TanStack Start could not find Vite's generated `style.css` manifest entry while `build.cssCodeSplit` is disabled\",\n )\n }\n\n const { getStylesheetAsset } = createManifestAssetResolvers(options.basePath)\n\n return {\n [rootRouteId]: [getStylesheetAsset(options.cssCodeSplitDisabledFileName)],\n }\n}\n\nfunction getAssetFileNameByName(\n bundle: Rollup.OutputBundle,\n assetName: string,\n) {\n for (const fileName in bundle) {\n const bundleEntry = bundle[fileName]!\n\n if (bundleEntry.type !== 'asset') {\n continue\n }\n\n if (bundleEntry.name === assetName) {\n return fileName\n }\n\n if ('names' in bundleEntry && bundleEntry.names.includes(assetName)) {\n return fileName\n }\n }\n\n return undefined\n}\n\nfunction getEmptyStartManifestModule(clientEntry: string) {\n return `export const tsrStartManifest = () => ({\n routes: {},\n clientEntry: '${clientEntry}',\n })`\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,oBAAoB,MAEnB;CACf,IAAI;CACJ,IAAI;AAEJ,QAAO,CACL;EACE,MAAM;EACN,mBAAmB,aAAa;AAC9B,UAAO,YAAY,SAAS,wBAAwB;;EAEtD,SAAS;EACT,eAAe,UAAU,QAAQ;AAC/B,OAAI,KAAK,YAAY,SAAS,wBAAwB,OACpD,OAAM,IAAI,MACR,oDAAoD,KAAK,YAAY,OACtE;AAGH,iBAAc,yBAAyB,OAAO;AAC9C,kCAA+B,uBAC7B,QACA,YACD;;EAEJ,EACD,oBAAoB;EAClB,MAAM;EACN,UAAU,gBAAgB;EAC1B,SAAS;EACT,OAAO;GACL,MAAM,EAAE,wBAAwB,KAAK,WAAW;GAChD,MAAM,cAAc,QAClB,oBAAoB,UAAU,YAC9B,OACA,aAAa,OACd;AAED,OAAI,KAAK,YAAY,SAAS,wBAAwB,OACpD,QAAO,4BAA4B,YAAY;AAGjD,OAAI,KAAK,YAAY,OAAO,YAAY,QACtC,QAAO,4BAA4B,YAAY;GAGjD,MAAM,kBAAkB,WAAW;AAInC,OAAI,CAAC,YACH,QAAO,4BAA4B,YAAY;AAajD,UAAO,0CAA0C,uBAX3B,mBAAmB;IACvC;IACA;IACA,UAAU,oBAAoB,UAAU;IACxC,uBAAuB,6BAA6B;KAClD;KACA,UAAU,oBAAoB,UAAU;KACxC,cAAc,KAAK,YAAY,OAAO,MAAM;KAC7C,CAAC;IACH,CAAC,CAEoF,CAAC;;EAE1F,CAAC,CACH;;AAGH,SAAS,6BAA6B,SAInC;AACD,KAAI,QAAQ,iBAAiB,MAC3B;AAGF,KAAI,CAAC,QAAQ,6BACX,OAAM,IAAI,MACR,mHACD;CAGH,MAAM,EAAE,uBAAuB,6BAA6B,QAAQ,SAAS;AAE7E,QAAO,GACJ,cAAc,CAAC,mBAAmB,QAAQ,6BAA6B,CAAC,EAC1E;;AAGH,SAAS,uBACP,QACA,WACA;AACA,MAAK,MAAM,YAAY,QAAQ;EAC7B,MAAM,cAAc,OAAO;AAE3B,MAAI,YAAY,SAAS,QACvB;AAGF,MAAI,YAAY,SAAS,UACvB,QAAO;AAGT,MAAI,WAAW,eAAe,YAAY,MAAM,SAAS,UAAU,CACjE,QAAO;;;AAOb,SAAS,4BAA4B,aAAqB;AACxD,QAAO;;sBAEa,YAAY"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-plugin-core",
3
- "version": "1.167.34",
3
+ "version": "1.168.0",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -40,6 +40,12 @@
40
40
  "default": "./dist/esm/utils.js"
41
41
  }
42
42
  },
43
+ "./rsbuild/types": {
44
+ "import": {
45
+ "types": "./dist/esm/rsbuild/types.d.ts",
46
+ "default": "./dist/esm/rsbuild/types.js"
47
+ }
48
+ },
43
49
  "./package.json": "./package.json"
44
50
  },
45
51
  "sideEffects": false,
@@ -68,13 +74,14 @@
68
74
  "xmlbuilder2": "^4.0.3",
69
75
  "zod": "^3.24.2",
70
76
  "@tanstack/router-core": "1.168.15",
71
- "@tanstack/router-generator": "1.166.32",
72
- "@tanstack/router-plugin": "1.167.22",
73
- "@tanstack/router-utils": "1.161.6",
77
+ "@tanstack/router-generator": "1.166.33",
78
+ "@tanstack/router-plugin": "1.167.23",
79
+ "@tanstack/router-utils": "1.161.7",
74
80
  "@tanstack/start-client-core": "1.167.17",
75
81
  "@tanstack/start-server-core": "1.167.19"
76
82
  },
77
83
  "devDependencies": {
84
+ "@rsbuild/core": "^2.0.0",
78
85
  "@types/babel__code-frame": "^7.0.6",
79
86
  "@types/babel__core": "^7.20.5",
80
87
  "@types/picomatch": "^4.0.2",
@@ -82,8 +89,14 @@
82
89
  "@types/node": ">=20"
83
90
  },
84
91
  "peerDependencies": {
92
+ "@rsbuild/core": "^2.0.0",
85
93
  "vite": ">=7.0.0"
86
94
  },
95
+ "peerDependenciesMeta": {
96
+ "@rsbuild/core": {
97
+ "optional": true
98
+ }
99
+ },
87
100
  "scripts": {
88
101
  "clean": "rimraf ./dist && rimraf ./coverage",
89
102
  "clean:snapshots": "rimraf **/*snapshot* --glob",