@octanejs/tanstack-start 0.1.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 (266) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +52 -0
  3. package/THIRD_PARTY_NOTICES.md +11 -0
  4. package/package.json +149 -0
  5. package/src/client-only.d.ts +1 -0
  6. package/src/client-only.js +0 -0
  7. package/src/client-rpc.d.ts +1 -0
  8. package/src/client-rpc.js +1 -0
  9. package/src/client.d.ts +3 -0
  10. package/src/client.js +2 -0
  11. package/src/default-entry/client.js +12 -0
  12. package/src/default-entry/server.js +13 -0
  13. package/src/default-entry/start.js +1 -0
  14. package/src/default-entry-paths.d.ts +5 -0
  15. package/src/default-entry-paths.js +11 -0
  16. package/src/index.d.ts +11 -0
  17. package/src/index.js +22 -0
  18. package/src/internal/README.md +15 -0
  19. package/src/internal/router-generator/config.d.ts +255 -0
  20. package/src/internal/router-generator/config.js +134 -0
  21. package/src/internal/router-generator/filesystem/physical/getRouteNodes.d.ts +53 -0
  22. package/src/internal/router-generator/filesystem/physical/getRouteNodes.js +335 -0
  23. package/src/internal/router-generator/filesystem/physical/rootPathId.d.ts +1 -0
  24. package/src/internal/router-generator/filesystem/physical/rootPathId.js +4 -0
  25. package/src/internal/router-generator/filesystem/virtual/config.d.ts +3 -0
  26. package/src/internal/router-generator/filesystem/virtual/config.js +36 -0
  27. package/src/internal/router-generator/filesystem/virtual/getRouteNodes.d.ts +31 -0
  28. package/src/internal/router-generator/filesystem/virtual/getRouteNodes.js +272 -0
  29. package/src/internal/router-generator/filesystem/virtual/loadConfigFile.d.ts +1 -0
  30. package/src/internal/router-generator/filesystem/virtual/loadConfigFile.js +10 -0
  31. package/src/internal/router-generator/generator.d.ts +119 -0
  32. package/src/internal/router-generator/generator.js +1080 -0
  33. package/src/internal/router-generator/index.d.ts +40 -0
  34. package/src/internal/router-generator/index.js +49 -0
  35. package/src/internal/router-generator/logger.d.ts +8 -0
  36. package/src/internal/router-generator/logger.js +30 -0
  37. package/src/internal/router-generator/plugin/types.d.ts +37 -0
  38. package/src/internal/router-generator/template.d.ts +38 -0
  39. package/src/internal/router-generator/template.js +220 -0
  40. package/src/internal/router-generator/transform/transform.d.ts +8 -0
  41. package/src/internal/router-generator/transform/transform.js +385 -0
  42. package/src/internal/router-generator/transform/types.d.ts +34 -0
  43. package/src/internal/router-generator/types.d.ts +73 -0
  44. package/src/internal/router-generator/utils.d.ts +270 -0
  45. package/src/internal/router-generator/utils.js +864 -0
  46. package/src/internal/router-generator/validate-route-params.d.ts +13 -0
  47. package/src/internal/router-generator/validate-route-params.js +75 -0
  48. package/src/internal/router-plugin/context.d.ts +2 -0
  49. package/src/internal/router-plugin/context.js +2 -0
  50. package/src/internal/router-plugin/core/code-splitter/compilers.d.ts +69 -0
  51. package/src/internal/router-plugin/core/code-splitter/compilers.js +1042 -0
  52. package/src/internal/router-plugin/core/code-splitter/framework-options.d.ts +11 -0
  53. package/src/internal/router-plugin/core/code-splitter/framework-options.js +41 -0
  54. package/src/internal/router-plugin/core/code-splitter/plugins/framework-plugins.d.ts +12 -0
  55. package/src/internal/router-plugin/core/code-splitter/plugins/framework-plugins.js +35 -0
  56. package/src/internal/router-plugin/core/code-splitter/plugins/octane-hmr-split-route-components.d.ts +5 -0
  57. package/src/internal/router-plugin/core/code-splitter/plugins/octane-hmr-split-route-components.js +106 -0
  58. package/src/internal/router-plugin/core/code-splitter/plugins/octane-split-route-components.d.ts +8 -0
  59. package/src/internal/router-plugin/core/code-splitter/plugins/octane-split-route-components.js +85 -0
  60. package/src/internal/router-plugin/core/code-splitter/plugins/react-refresh-ignored-route-exports.d.ts +2 -0
  61. package/src/internal/router-plugin/core/code-splitter/plugins/react-refresh-ignored-route-exports.js +55 -0
  62. package/src/internal/router-plugin/core/code-splitter/plugins/react-refresh-route-components.d.ts +2 -0
  63. package/src/internal/router-plugin/core/code-splitter/plugins/react-refresh-route-components.js +50 -0
  64. package/src/internal/router-plugin/core/code-splitter/plugins/react-stable-hmr-split-route-components.d.ts +5 -0
  65. package/src/internal/router-plugin/core/code-splitter/plugins/react-stable-hmr-split-route-components.js +54 -0
  66. package/src/internal/router-plugin/core/code-splitter/plugins.d.ts +62 -0
  67. package/src/internal/router-plugin/core/code-splitter/types.d.ts +9 -0
  68. package/src/internal/router-plugin/core/config.d.ts +294 -0
  69. package/src/internal/router-plugin/core/config.js +56 -0
  70. package/src/internal/router-plugin/core/constants.d.ts +12 -0
  71. package/src/internal/router-plugin/core/constants.js +13 -0
  72. package/src/internal/router-plugin/core/framework-plugin-order.d.ts +8 -0
  73. package/src/internal/router-plugin/core/framework-plugin-order.js +78 -0
  74. package/src/internal/router-plugin/core/hmr/handle-route-update.d.ts +1 -0
  75. package/src/internal/router-plugin/core/hmr/handle-route-update.js +126 -0
  76. package/src/internal/router-plugin/core/hmr/index.d.ts +5 -0
  77. package/src/internal/router-plugin/core/hmr/select-adapter.d.ts +17 -0
  78. package/src/internal/router-plugin/core/hmr/select-adapter.js +24 -0
  79. package/src/internal/router-plugin/core/hmr/vite-adapter.d.ts +18 -0
  80. package/src/internal/router-plugin/core/hmr/vite-adapter.js +73 -0
  81. package/src/internal/router-plugin/core/hmr/webpack-adapter.d.ts +22 -0
  82. package/src/internal/router-plugin/core/hmr/webpack-adapter.js +78 -0
  83. package/src/internal/router-plugin/core/router-code-splitter-plugin.d.ts +10 -0
  84. package/src/internal/router-plugin/core/router-code-splitter-plugin.js +244 -0
  85. package/src/internal/router-plugin/core/router-composed-plugin.d.ts +5 -0
  86. package/src/internal/router-plugin/core/router-composed-plugin.js +62 -0
  87. package/src/internal/router-plugin/core/router-generator-plugin.d.ts +10 -0
  88. package/src/internal/router-plugin/core/router-generator-plugin.js +125 -0
  89. package/src/internal/router-plugin/core/router-hmr-plugin.d.ts +13 -0
  90. package/src/internal/router-plugin/core/router-hmr-plugin.js +101 -0
  91. package/src/internal/router-plugin/core/router-plugin-context.d.ts +5 -0
  92. package/src/internal/router-plugin/core/router-plugin-context.js +6 -0
  93. package/src/internal/router-plugin/core/utils.d.ts +17 -0
  94. package/src/internal/router-plugin/core/utils.js +47 -0
  95. package/src/internal/router-plugin/esbuild.d.ts +197 -0
  96. package/src/internal/router-plugin/esbuild.js +58 -0
  97. package/src/internal/router-plugin/index.d.ts +19 -0
  98. package/src/internal/router-plugin/index.js +17 -0
  99. package/src/internal/router-plugin/rspack.d.ts +61 -0
  100. package/src/internal/router-plugin/rspack.js +92 -0
  101. package/src/internal/router-plugin/vite.d.ts +201 -0
  102. package/src/internal/router-plugin/vite.js +62 -0
  103. package/src/internal/router-plugin/webpack.d.ts +50 -0
  104. package/src/internal/router-plugin/webpack.js +77 -0
  105. package/src/internal/start-plugin-core/build-sitemap.d.ts +34 -0
  106. package/src/internal/start-plugin-core/build-sitemap.js +125 -0
  107. package/src/internal/start-plugin-core/config-context.d.ts +30 -0
  108. package/src/internal/start-plugin-core/config-context.js +89 -0
  109. package/src/internal/start-plugin-core/constants.d.ts +20 -0
  110. package/src/internal/start-plugin-core/constants.js +24 -0
  111. package/src/internal/start-plugin-core/debug.d.ts +1 -0
  112. package/src/internal/start-plugin-core/hydrate-when-transform.d.ts +5 -0
  113. package/src/internal/start-plugin-core/hydrate-when-transform.js +661 -0
  114. package/src/internal/start-plugin-core/hydration-constants.d.ts +1 -0
  115. package/src/internal/start-plugin-core/hydration-constants.js +4 -0
  116. package/src/internal/start-plugin-core/import-protection/adapterUtils.d.ts +40 -0
  117. package/src/internal/start-plugin-core/import-protection/adapterUtils.js +42 -0
  118. package/src/internal/start-plugin-core/import-protection/analysis.d.ts +63 -0
  119. package/src/internal/start-plugin-core/import-protection/analysis.js +533 -0
  120. package/src/internal/start-plugin-core/import-protection/constants.d.ts +11 -0
  121. package/src/internal/start-plugin-core/import-protection/constants.js +39 -0
  122. package/src/internal/start-plugin-core/import-protection/defaults.d.ts +19 -0
  123. package/src/internal/start-plugin-core/import-protection/defaults.js +34 -0
  124. package/src/internal/start-plugin-core/import-protection/extensionlessAbsoluteIdResolver.d.ts +22 -0
  125. package/src/internal/start-plugin-core/import-protection/extensionlessAbsoluteIdResolver.js +94 -0
  126. package/src/internal/start-plugin-core/import-protection/matchers.d.ts +18 -0
  127. package/src/internal/start-plugin-core/import-protection/matchers.js +39 -0
  128. package/src/internal/start-plugin-core/import-protection/rewrite.d.ts +29 -0
  129. package/src/internal/start-plugin-core/import-protection/rewrite.js +184 -0
  130. package/src/internal/start-plugin-core/import-protection/sourceLocation.d.ts +170 -0
  131. package/src/internal/start-plugin-core/import-protection/sourceLocation.js +376 -0
  132. package/src/internal/start-plugin-core/import-protection/trace.d.ts +89 -0
  133. package/src/internal/start-plugin-core/import-protection/trace.js +186 -0
  134. package/src/internal/start-plugin-core/import-protection/utils.d.ts +78 -0
  135. package/src/internal/start-plugin-core/import-protection/utils.js +171 -0
  136. package/src/internal/start-plugin-core/import-protection/virtualModules.d.ts +38 -0
  137. package/src/internal/start-plugin-core/import-protection/virtualModules.js +241 -0
  138. package/src/internal/start-plugin-core/index.d.ts +8 -0
  139. package/src/internal/start-plugin-core/index.js +2 -0
  140. package/src/internal/start-plugin-core/planning.d.ts +44 -0
  141. package/src/internal/start-plugin-core/planning.js +98 -0
  142. package/src/internal/start-plugin-core/post-build.d.ts +12 -0
  143. package/src/internal/start-plugin-core/post-build.js +40 -0
  144. package/src/internal/start-plugin-core/prerender.d.ts +17 -0
  145. package/src/internal/start-plugin-core/prerender.js +172 -0
  146. package/src/internal/start-plugin-core/queue.d.ts +37 -0
  147. package/src/internal/start-plugin-core/queue.js +118 -0
  148. package/src/internal/start-plugin-core/resolve-entries.d.ts +10 -0
  149. package/src/internal/start-plugin-core/resolve-entries.js +32 -0
  150. package/src/internal/start-plugin-core/schema.d.ts +1799 -0
  151. package/src/internal/start-plugin-core/schema.js +252 -0
  152. package/src/internal/start-plugin-core/serialization-adapters-module.d.ts +18 -0
  153. package/src/internal/start-plugin-core/serialization-adapters-module.js +37 -0
  154. package/src/internal/start-plugin-core/start-compiler/compiler.d.ts +181 -0
  155. package/src/internal/start-plugin-core/start-compiler/compiler.js +1078 -0
  156. package/src/internal/start-plugin-core/start-compiler/config.d.ts +20 -0
  157. package/src/internal/start-plugin-core/start-compiler/config.js +84 -0
  158. package/src/internal/start-plugin-core/start-compiler/handleClientOnlyJSX.d.ts +24 -0
  159. package/src/internal/start-plugin-core/start-compiler/handleClientOnlyJSX.js +25 -0
  160. package/src/internal/start-plugin-core/start-compiler/handleCreateIsomorphicFn.d.ts +11 -0
  161. package/src/internal/start-plugin-core/start-compiler/handleCreateIsomorphicFn.js +24 -0
  162. package/src/internal/start-plugin-core/start-compiler/handleCreateMiddleware.d.ts +11 -0
  163. package/src/internal/start-plugin-core/start-compiler/handleCreateMiddleware.js +35 -0
  164. package/src/internal/start-plugin-core/start-compiler/handleCreateServerFn.d.ts +22 -0
  165. package/src/internal/start-plugin-core/start-compiler/handleCreateServerFn.js +292 -0
  166. package/src/internal/start-plugin-core/start-compiler/handleEnvOnly.d.ts +14 -0
  167. package/src/internal/start-plugin-core/start-compiler/handleEnvOnly.js +41 -0
  168. package/src/internal/start-plugin-core/start-compiler/host.d.ts +44 -0
  169. package/src/internal/start-plugin-core/start-compiler/host.js +75 -0
  170. package/src/internal/start-plugin-core/start-compiler/server-fn-resolver-module.d.ts +10 -0
  171. package/src/internal/start-plugin-core/start-compiler/server-fn-resolver-module.js +87 -0
  172. package/src/internal/start-plugin-core/start-compiler/types.d.ts +119 -0
  173. package/src/internal/start-plugin-core/start-compiler/utils.d.ts +27 -0
  174. package/src/internal/start-plugin-core/start-compiler/utils.js +36 -0
  175. package/src/internal/start-plugin-core/start-manifest-plugin/inlineCss.d.ts +16 -0
  176. package/src/internal/start-plugin-core/start-manifest-plugin/inlineCss.js +131 -0
  177. package/src/internal/start-plugin-core/start-manifest-plugin/manifestBuilder.d.ts +64 -0
  178. package/src/internal/start-plugin-core/start-manifest-plugin/manifestBuilder.js +441 -0
  179. package/src/internal/start-plugin-core/start-router-plugin/constants.d.ts +1 -0
  180. package/src/internal/start-plugin-core/start-router-plugin/constants.js +4 -0
  181. package/src/internal/start-plugin-core/start-router-plugin/generator-plugins/compose-generator-plugins.d.ts +6 -0
  182. package/src/internal/start-plugin-core/start-router-plugin/generator-plugins/compose-generator-plugins.js +6 -0
  183. package/src/internal/start-plugin-core/start-router-plugin/generator-plugins/prerender-routes-plugin.d.ts +6 -0
  184. package/src/internal/start-plugin-core/start-router-plugin/generator-plugins/prerender-routes-plugin.js +27 -0
  185. package/src/internal/start-plugin-core/start-router-plugin/generator-plugins/routes-manifest-plugin.d.ts +6 -0
  186. package/src/internal/start-plugin-core/start-router-plugin/generator-plugins/routes-manifest-plugin.js +34 -0
  187. package/src/internal/start-plugin-core/start-router-plugin/pruneServerOnlySubtrees.d.ts +11 -0
  188. package/src/internal/start-plugin-core/start-router-plugin/pruneServerOnlySubtrees.js +42 -0
  189. package/src/internal/start-plugin-core/start-router-plugin/route-tree-footer.d.ts +6 -0
  190. package/src/internal/start-plugin-core/start-router-plugin/route-tree-footer.js +59 -0
  191. package/src/internal/start-plugin-core/types.d.ts +135 -0
  192. package/src/internal/start-plugin-core/types.js +4 -0
  193. package/src/internal/start-plugin-core/utils.d.ts +13 -0
  194. package/src/internal/start-plugin-core/utils.js +42 -0
  195. package/src/internal/start-plugin-core/vite/createVirtualModule.d.ts +15 -0
  196. package/src/internal/start-plugin-core/vite/createVirtualModule.js +27 -0
  197. package/src/internal/start-plugin-core/vite/dev-server-plugin/dev-styles.d.ts +26 -0
  198. package/src/internal/start-plugin-core/vite/dev-server-plugin/dev-styles.js +165 -0
  199. package/src/internal/start-plugin-core/vite/dev-server-plugin/plugin.d.ts +11 -0
  200. package/src/internal/start-plugin-core/vite/dev-server-plugin/plugin.js +170 -0
  201. package/src/internal/start-plugin-core/vite/import-protection-plugin/plugin.d.ts +4 -0
  202. package/src/internal/start-plugin-core/vite/import-protection-plugin/plugin.js +1553 -0
  203. package/src/internal/start-plugin-core/vite/import-protection-plugin/types.d.ts +103 -0
  204. package/src/internal/start-plugin-core/vite/import-protection-plugin/virtualModules.d.ts +40 -0
  205. package/src/internal/start-plugin-core/vite/import-protection-plugin/virtualModules.js +68 -0
  206. package/src/internal/start-plugin-core/vite/index.d.ts +13 -0
  207. package/src/internal/start-plugin-core/vite/index.js +4 -0
  208. package/src/internal/start-plugin-core/vite/load-env-plugin/plugin.d.ts +2 -0
  209. package/src/internal/start-plugin-core/vite/load-env-plugin/plugin.js +13 -0
  210. package/src/internal/start-plugin-core/vite/output-directory.d.ts +7 -0
  211. package/src/internal/start-plugin-core/vite/output-directory.js +18 -0
  212. package/src/internal/start-plugin-core/vite/planning.d.ts +112 -0
  213. package/src/internal/start-plugin-core/vite/planning.js +152 -0
  214. package/src/internal/start-plugin-core/vite/plugin.d.ts +7 -0
  215. package/src/internal/start-plugin-core/vite/plugin.js +208 -0
  216. package/src/internal/start-plugin-core/vite/plugins.d.ts +17 -0
  217. package/src/internal/start-plugin-core/vite/plugins.js +72 -0
  218. package/src/internal/start-plugin-core/vite/post-server-build.d.ts +9 -0
  219. package/src/internal/start-plugin-core/vite/post-server-build.js +22 -0
  220. package/src/internal/start-plugin-core/vite/prerender.d.ts +9 -0
  221. package/src/internal/start-plugin-core/vite/prerender.js +52 -0
  222. package/src/internal/start-plugin-core/vite/preview-server-plugin/plugin.d.ts +2 -0
  223. package/src/internal/start-plugin-core/vite/preview-server-plugin/plugin.js +54 -0
  224. package/src/internal/start-plugin-core/vite/schema.d.ts +2423 -0
  225. package/src/internal/start-plugin-core/vite/schema.js +17 -0
  226. package/src/internal/start-plugin-core/vite/serialization-adapters-plugin.d.ts +5 -0
  227. package/src/internal/start-plugin-core/vite/serialization-adapters-plugin.js +63 -0
  228. package/src/internal/start-plugin-core/vite/start-compiler-plugin/hot-update.d.ts +5 -0
  229. package/src/internal/start-plugin-core/vite/start-compiler-plugin/hot-update.js +14 -0
  230. package/src/internal/start-plugin-core/vite/start-compiler-plugin/module-specifier.d.ts +5 -0
  231. package/src/internal/start-plugin-core/vite/start-compiler-plugin/module-specifier.js +25 -0
  232. package/src/internal/start-plugin-core/vite/start-compiler-plugin/plugin.d.ts +29 -0
  233. package/src/internal/start-plugin-core/vite/start-compiler-plugin/plugin.js +380 -0
  234. package/src/internal/start-plugin-core/vite/start-manifest-plugin/normalized-client-build.d.ts +11 -0
  235. package/src/internal/start-plugin-core/vite/start-manifest-plugin/normalized-client-build.js +114 -0
  236. package/src/internal/start-plugin-core/vite/start-manifest-plugin/plugin.d.ts +3 -0
  237. package/src/internal/start-plugin-core/vite/start-manifest-plugin/plugin.js +103 -0
  238. package/src/internal/start-plugin-core/vite/start-router-plugin/plugin.d.ts +9 -0
  239. package/src/internal/start-plugin-core/vite/start-router-plugin/plugin.js +143 -0
  240. package/src/internal/start-plugin-core/vite/types.d.ts +17 -0
  241. package/src/package-names.js +10 -0
  242. package/src/plugin-vite.d.ts +23 -0
  243. package/src/plugin-vite.js +62 -0
  244. package/src/runtime/client/StartClient.d.ts +11 -0
  245. package/src/runtime/client/StartClient.js +16 -0
  246. package/src/runtime/client/hydrateStart.d.ts +4 -0
  247. package/src/runtime/client/hydrateStart.js +30 -0
  248. package/src/runtime/server/StartServer.d.ts +10 -0
  249. package/src/runtime/server/StartServer.js +6 -0
  250. package/src/runtime/server/defaultRenderHandler.d.ts +3 -0
  251. package/src/runtime/server/defaultRenderHandler.js +11 -0
  252. package/src/runtime/server/defaultStreamHandler.d.ts +3 -0
  253. package/src/runtime/server/defaultStreamHandler.js +13 -0
  254. package/src/server-entry.d.ts +11 -0
  255. package/src/server-entry.js +13 -0
  256. package/src/server-only.d.ts +1 -0
  257. package/src/server-only.js +0 -0
  258. package/src/server-rpc.d.ts +1 -0
  259. package/src/server-rpc.js +1 -0
  260. package/src/server.d.ts +6 -0
  261. package/src/server.js +4 -0
  262. package/src/ssr-rpc.d.ts +1 -0
  263. package/src/ssr-rpc.js +1 -0
  264. package/src/use-server-fn.d.ts +3 -0
  265. package/src/use-server-fn.js +18 -0
  266. package/src/validate-options.js +7 -0
@@ -0,0 +1,1080 @@
1
+ import { logging } from './logger.js';
2
+ import { rootPathId } from './filesystem/physical/rootPathId.js';
3
+ import {
4
+ RoutePrefixMap,
5
+ buildFileRoutesByPathInterface,
6
+ buildImportString,
7
+ buildRouteTreeConfig,
8
+ checkFileExists,
9
+ checkRouteFullPathUniqueness,
10
+ countRoutePathSegments,
11
+ countSlashSeparatedParts,
12
+ createRouteNodesByFullPath,
13
+ createRouteNodesById,
14
+ createRouteNodesByTo,
15
+ createTokenRegex,
16
+ determineNodePath,
17
+ findParent,
18
+ format,
19
+ getImportForRouteNode,
20
+ getResolvedRouteNodeVariableName,
21
+ hasParentRoute,
22
+ isSegmentPathless,
23
+ mergeImportDeclarations,
24
+ multiSortBy,
25
+ removeExt,
26
+ removeGroups,
27
+ removeLastSegmentFromPath,
28
+ removeLayoutSegmentsAndUnderscoresWithEscape,
29
+ removeTrailingSlash,
30
+ replaceBackslash,
31
+ sortRouteNodes,
32
+ trimPathLeft,
33
+ } from './utils.js';
34
+ import { getRouteNodes } from './filesystem/virtual/getRouteNodes.js';
35
+ import {
36
+ getRouteNodes as getRouteNodes$1,
37
+ isVirtualConfigFile,
38
+ } from './filesystem/physical/getRouteNodes.js';
39
+ import { fillTemplate, getTargetTemplate } from './template.js';
40
+ import { transform } from './transform/transform.js';
41
+ import { validateRouteParams } from './validate-route-params.js';
42
+ import path from 'node:path';
43
+ import { existsSync, mkdirSync } from 'node:fs';
44
+ import * as fsp from 'node:fs/promises';
45
+ import crypto from 'node:crypto';
46
+ import { rootRouteId } from '@tanstack/router-core';
47
+ //#region src/generator.ts
48
+ function getRootRouteFileExtension(config) {
49
+ switch (config.target) {
50
+ case 'vue':
51
+ return 'vue';
52
+ case 'octane':
53
+ return 'tsrx';
54
+ default:
55
+ return config.disableTypes ? 'js' : 'tsx';
56
+ }
57
+ }
58
+ function getRoutePathSegmentMetadataForPath(node, routePath, parentRoutePath) {
59
+ if (!node._routePathSegmentMetadata) return void 0;
60
+ const segments = routePath.split('/');
61
+ const result = new Array(segments.length);
62
+ const parentSegmentCount = countRoutePathSegments(parentRoutePath);
63
+ let hasMetadata = false;
64
+ let segmentCount = 0;
65
+ for (let i = 0; i < segments.length; i++) {
66
+ if (!segments[i]) continue;
67
+ const sourceIndex = parentSegmentCount + segmentCount + 1;
68
+ result[i] = node._routePathSegmentMetadata[sourceIndex];
69
+ hasMetadata ||= !!result[i];
70
+ segmentCount++;
71
+ }
72
+ return hasMetadata ? result : void 0;
73
+ }
74
+ var DefaultFileSystem = {
75
+ stat: async (filePath) => {
76
+ const res = await fsp.stat(filePath, { bigint: true });
77
+ return {
78
+ mtimeMs: res.mtimeMs,
79
+ mode: Number(res.mode),
80
+ uid: Number(res.uid),
81
+ gid: Number(res.gid),
82
+ };
83
+ },
84
+ rename: (oldPath, newPath) => fsp.rename(oldPath, newPath),
85
+ writeFile: (filePath, content) => fsp.writeFile(filePath, content),
86
+ readFile: async (filePath) => {
87
+ try {
88
+ const fileHandle = await fsp.open(filePath, 'r');
89
+ const stat = await fileHandle.stat({ bigint: true });
90
+ const fileContent = (await fileHandle.readFile()).toString();
91
+ await fileHandle.close();
92
+ return {
93
+ stat,
94
+ fileContent,
95
+ };
96
+ } catch (e) {
97
+ if ('code' in e) {
98
+ if (e.code === 'ENOENT') return 'file-not-existing';
99
+ }
100
+ throw e;
101
+ }
102
+ },
103
+ chmod: (filePath, mode) => fsp.chmod(filePath, mode),
104
+ chown: (filePath, uid, gid) => fsp.chown(filePath, uid, gid),
105
+ };
106
+ function rerun(opts) {
107
+ const { event, ...rest } = opts;
108
+ return {
109
+ rerun: true,
110
+ event: event ?? { type: 'rerun' },
111
+ ...rest,
112
+ };
113
+ }
114
+ function isRerun(result) {
115
+ return (
116
+ typeof result === 'object' && result !== null && 'rerun' in result && result.rerun === true
117
+ );
118
+ }
119
+ var Generator = class Generator {
120
+ static {
121
+ this.routeGroupPatternRegex = /\(.+\)/;
122
+ }
123
+ static {
124
+ this.componentPieceRegex =
125
+ /[./](component|errorComponent|notFoundComponent|pendingComponent|loader|lazy)[.]/;
126
+ }
127
+ constructor(opts) {
128
+ this.routeNodeCache = /* @__PURE__ */ new Map();
129
+ this.routeNodeShadowCache = /* @__PURE__ */ new Map();
130
+ this.fileEventQueue = [];
131
+ this.plugins = [];
132
+ this.physicalDirectories = [];
133
+ this.config = opts.config;
134
+ this.logger = logging({ disabled: this.config.disableLogging });
135
+ this.root = opts.root;
136
+ this.fs = opts.fs || DefaultFileSystem;
137
+ this.generatedRouteTreePath = this.getGeneratedRouteTreePath();
138
+ this.targetTemplate = getTargetTemplate(this.config);
139
+ this.routesDirectoryPath = this.getRoutesDirectoryPath();
140
+ this.plugins.push(...(opts.config.plugins || []));
141
+ this.indexTokenFilenameRegex = createTokenRegex(this.config.indexToken, { type: 'filename' });
142
+ this.routeTokenFilenameRegex = createTokenRegex(this.config.routeToken, { type: 'filename' });
143
+ this.indexTokenSegmentRegex = createTokenRegex(this.config.indexToken, { type: 'segment' });
144
+ this.routeTokenSegmentRegex = createTokenRegex(this.config.routeToken, { type: 'segment' });
145
+ for (const plugin of this.plugins) plugin.init?.({ generator: this });
146
+ }
147
+ getGeneratedRouteTreePath() {
148
+ const generatedRouteTreePath = path.isAbsolute(this.config.generatedRouteTree)
149
+ ? this.config.generatedRouteTree
150
+ : path.resolve(this.root, this.config.generatedRouteTree);
151
+ const generatedRouteTreeDir = path.dirname(generatedRouteTreePath);
152
+ if (!existsSync(generatedRouteTreeDir)) mkdirSync(generatedRouteTreeDir, { recursive: true });
153
+ return generatedRouteTreePath;
154
+ }
155
+ getRoutesDirectoryPath() {
156
+ return path.isAbsolute(this.config.routesDirectory)
157
+ ? this.config.routesDirectory
158
+ : path.resolve(this.root, this.config.routesDirectory);
159
+ }
160
+ getRoutesByFileMap() {
161
+ return new Map(
162
+ [...this.routeNodeCache.entries()].map(([filePath, cacheEntry]) => [
163
+ filePath,
164
+ { routeId: cacheEntry.routeId },
165
+ ]),
166
+ );
167
+ }
168
+ async fillRouteTemplate(node, template, values) {
169
+ return fillTemplate(this.config, template, values, async (source) => {
170
+ let result = source;
171
+ let wasFormatted = false;
172
+ for (const plugin of this.plugins) {
173
+ const pluginResult = await plugin.formatRoute?.({
174
+ source: result,
175
+ node,
176
+ });
177
+ if (pluginResult !== void 0) {
178
+ result = pluginResult;
179
+ wasFormatted = true;
180
+ }
181
+ }
182
+ return wasFormatted ? result : format(source, this.config);
183
+ });
184
+ }
185
+ async getParseSource(opts) {
186
+ let result = opts.source;
187
+ let wasTransformed = false;
188
+ for (const plugin of this.plugins) {
189
+ const pluginResult = await plugin.transformRouteSource?.({
190
+ source: result,
191
+ filename: opts.filename ?? opts.node.fullPath,
192
+ node: opts.node,
193
+ });
194
+ if (pluginResult !== void 0) {
195
+ result = pluginResult;
196
+ wasTransformed = true;
197
+ }
198
+ }
199
+ return wasTransformed ? result : void 0;
200
+ }
201
+ async run(event) {
202
+ if (event && event.type !== 'rerun' && !this.isFileRelevantForRouteTreeGeneration(event.path))
203
+ return;
204
+ this.fileEventQueue.push(event ?? { type: 'rerun' });
205
+ if (this.runPromise) return this.runPromise;
206
+ this.runPromise = (async () => {
207
+ do {
208
+ const tempQueue = this.fileEventQueue;
209
+ this.fileEventQueue = [];
210
+ if (
211
+ (
212
+ await Promise.all(
213
+ tempQueue.map(async (e) => {
214
+ if (e.type === 'update') {
215
+ let cacheEntry;
216
+ if (e.path === this.generatedRouteTreePath) cacheEntry = this.routeTreeFileCache;
217
+ else cacheEntry = this.routeNodeCache.get(e.path);
218
+ if (
219
+ (await this.didFileChangeComparedToCache({ path: e.path }, cacheEntry))
220
+ .result === false
221
+ )
222
+ return null;
223
+ }
224
+ return e;
225
+ }),
226
+ )
227
+ ).filter((e) => e !== null).length === 0
228
+ )
229
+ break;
230
+ try {
231
+ await this.generatorInternal();
232
+ } catch (err) {
233
+ const errArray = !Array.isArray(err) ? [err] : err;
234
+ const recoverableErrors = errArray.filter((e) => isRerun(e));
235
+ if (recoverableErrors.length === errArray.length) {
236
+ this.fileEventQueue.push(...recoverableErrors.map((e) => e.event));
237
+ recoverableErrors.forEach((e) => {
238
+ if (e.msg) this.logger.info(e.msg);
239
+ });
240
+ } else {
241
+ const unrecoverableErrors = errArray.filter((e) => !isRerun(e));
242
+ this.runPromise = void 0;
243
+ throw new Error(unrecoverableErrors.map((e) => e.message).join());
244
+ }
245
+ }
246
+ } while (this.fileEventQueue.length);
247
+ this.runPromise = void 0;
248
+ })();
249
+ return this.runPromise;
250
+ }
251
+ async generatorInternal() {
252
+ let writeRouteTreeFile = false;
253
+ let getRouteNodesResult;
254
+ if (this.config.virtualRouteConfig)
255
+ getRouteNodesResult = await getRouteNodes(this.config, this.root, {
256
+ indexTokenSegmentRegex: this.indexTokenSegmentRegex,
257
+ routeTokenSegmentRegex: this.routeTokenSegmentRegex,
258
+ });
259
+ else
260
+ getRouteNodesResult = await getRouteNodes$1(this.config, this.root, {
261
+ indexTokenSegmentRegex: this.indexTokenSegmentRegex,
262
+ routeTokenSegmentRegex: this.routeTokenSegmentRegex,
263
+ });
264
+ const {
265
+ rootRouteNode,
266
+ routeNodes: beforeRouteNodes,
267
+ physicalDirectories,
268
+ } = getRouteNodesResult;
269
+ if (rootRouteNode === void 0) {
270
+ let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`;
271
+ if (!this.config.virtualRouteConfig) {
272
+ const rootRouteExtension = getRootRouteFileExtension(this.config);
273
+ errorMessage += `\nMake sure that you add a "${rootPathId}.${rootRouteExtension}" file to your routes directory.\nAdd the file in: "${this.config.routesDirectory}/${rootPathId}.${rootRouteExtension}"`;
274
+ }
275
+ throw new Error(errorMessage);
276
+ }
277
+ this.physicalDirectories = physicalDirectories;
278
+ await this.handleRootNode(rootRouteNode);
279
+ const preRouteNodes = multiSortBy(beforeRouteNodes, [
280
+ (d) => (d.routePath === '/' ? -1 : 1),
281
+ (d) => (d.routePath === void 0 ? void 0 : countSlashSeparatedParts(d.routePath)),
282
+ (d) => (d.filePath.match(this.indexTokenFilenameRegex) ? 1 : -1),
283
+ (d) => (d.filePath.match(Generator.componentPieceRegex) ? 1 : -1),
284
+ (d) => (d.filePath.match(this.routeTokenFilenameRegex) ? -1 : 1),
285
+ (d) => (d.routePath?.endsWith('/') ? -1 : 1),
286
+ (d) => d.routePath,
287
+ ]).filter((d) => {
288
+ if (d.routePath === `/__root`)
289
+ return [
290
+ 'component',
291
+ 'errorComponent',
292
+ 'notFoundComponent',
293
+ 'pendingComponent',
294
+ 'loader',
295
+ 'lazy',
296
+ ].includes(d._fsRouteType);
297
+ return true;
298
+ });
299
+ const routeFileAllResult = await Promise.allSettled(
300
+ preRouteNodes
301
+ .filter((n) => !n.isVirtualParentRoute && !n.isVirtual)
302
+ .map((n) => this.processRouteNodeFile(n)),
303
+ );
304
+ const rejections = routeFileAllResult.filter((result) => result.status === 'rejected');
305
+ if (rejections.length > 0) throw rejections.map((e) => e.reason);
306
+ const routeFileResult = routeFileAllResult.flatMap((result) => {
307
+ if (result.status === 'fulfilled' && result.value !== null) {
308
+ if (result.value.shouldWriteTree) writeRouteTreeFile = true;
309
+ return result.value.node;
310
+ }
311
+ return [];
312
+ });
313
+ routeFileResult.forEach((r) => (r.children = void 0));
314
+ const acc = {
315
+ routeTree: [],
316
+ routeNodes: [],
317
+ routePiecesByPath: {},
318
+ routeNodesByPath: /* @__PURE__ */ new Map(),
319
+ };
320
+ const prefixMap = new RoutePrefixMap(routeFileResult);
321
+ for (const node of routeFileResult) Generator.handleNode(node, acc, prefixMap, this.config);
322
+ this.crawlingResult = {
323
+ rootRouteNode,
324
+ routeFileResult,
325
+ acc,
326
+ };
327
+ if (!this.routeTreeFileCache) {
328
+ const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath);
329
+ if (routeTreeFile !== 'file-not-existing')
330
+ this.routeTreeFileCache = {
331
+ fileContent: routeTreeFile.fileContent,
332
+ mtimeMs: routeTreeFile.stat.mtimeMs,
333
+ };
334
+ writeRouteTreeFile = true;
335
+ } else {
336
+ const routeTreeFileChange = await this.didFileChangeComparedToCache(
337
+ { path: this.generatedRouteTreePath },
338
+ this.routeTreeFileCache,
339
+ );
340
+ if (routeTreeFileChange.result !== false) {
341
+ writeRouteTreeFile = 'force';
342
+ if (routeTreeFileChange.result === true) {
343
+ const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath);
344
+ if (routeTreeFile !== 'file-not-existing')
345
+ this.routeTreeFileCache = {
346
+ fileContent: routeTreeFile.fileContent,
347
+ mtimeMs: routeTreeFile.stat.mtimeMs,
348
+ };
349
+ }
350
+ }
351
+ }
352
+ if (!writeRouteTreeFile) {
353
+ if (this.routeNodeCache.size !== this.routeNodeShadowCache.size) writeRouteTreeFile = true;
354
+ else
355
+ for (const fullPath of this.routeNodeCache.keys())
356
+ if (!this.routeNodeShadowCache.has(fullPath)) {
357
+ writeRouteTreeFile = true;
358
+ break;
359
+ }
360
+ }
361
+ if (!writeRouteTreeFile) {
362
+ this.swapCaches();
363
+ return;
364
+ }
365
+ const buildResult = this.buildRouteTree({
366
+ rootRouteNode,
367
+ acc,
368
+ routeFileResult,
369
+ });
370
+ let routeTreeContent = buildResult.routeTreeContent;
371
+ routeTreeContent = this.config.enableRouteTreeFormatting
372
+ ? await format(routeTreeContent, this.config)
373
+ : routeTreeContent;
374
+ let newMtimeMs;
375
+ if (this.routeTreeFileCache)
376
+ if (this.routeTreeFileCache.fileContent === routeTreeContent) {
377
+ } else
378
+ newMtimeMs = (
379
+ await this.safeFileWrite({
380
+ filePath: this.generatedRouteTreePath,
381
+ newContent: routeTreeContent,
382
+ strategy: {
383
+ type: 'mtime',
384
+ expectedMtimeMs: this.routeTreeFileCache.mtimeMs,
385
+ },
386
+ })
387
+ ).mtimeMs;
388
+ else
389
+ newMtimeMs = (
390
+ await this.safeFileWrite({
391
+ filePath: this.generatedRouteTreePath,
392
+ newContent: routeTreeContent,
393
+ strategy: { type: 'new-file' },
394
+ })
395
+ ).mtimeMs;
396
+ if (newMtimeMs !== void 0)
397
+ this.routeTreeFileCache = {
398
+ fileContent: routeTreeContent,
399
+ mtimeMs: newMtimeMs,
400
+ };
401
+ this.plugins.map((plugin) => {
402
+ return plugin.onRouteTreeChanged?.({
403
+ routeTree: buildResult.routeTree,
404
+ routeNodes: buildResult.routeNodes,
405
+ acc,
406
+ rootRouteNode,
407
+ });
408
+ });
409
+ this.swapCaches();
410
+ }
411
+ swapCaches() {
412
+ this.routeNodeCache = this.routeNodeShadowCache;
413
+ this.routeNodeShadowCache = /* @__PURE__ */ new Map();
414
+ }
415
+ buildRouteTree(opts) {
416
+ const config = {
417
+ ...this.config,
418
+ ...(opts.config || {}),
419
+ };
420
+ const { rootRouteNode, acc } = opts;
421
+ const indexTokenSegmentRegex =
422
+ config.indexToken === this.config.indexToken
423
+ ? this.indexTokenSegmentRegex
424
+ : createTokenRegex(config.indexToken, { type: 'segment' });
425
+ const sortedRouteNodes = sortRouteNodes(acc.routeNodes, indexTokenSegmentRegex);
426
+ const routeImports = [];
427
+ const virtualRouteNodes = [];
428
+ for (const node of sortedRouteNodes)
429
+ if (node.isVirtual)
430
+ virtualRouteNodes.push(
431
+ `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`,
432
+ );
433
+ else
434
+ routeImports.push(
435
+ getImportForRouteNode(node, config, this.generatedRouteTreePath, this.root),
436
+ );
437
+ const imports = [];
438
+ if (virtualRouteNodes.length > 0)
439
+ imports.push({
440
+ specifiers: [{ imported: 'createFileRoute' }],
441
+ source: this.targetTemplate.fullPkg,
442
+ });
443
+ let hasComponentPieces = false;
444
+ let hasLoaderPieces = false;
445
+ for (const node of sortedRouteNodes) {
446
+ const pieces = acc.routePiecesByPath[node.routePath];
447
+ if (pieces) {
448
+ if (
449
+ pieces.component ||
450
+ pieces.errorComponent ||
451
+ pieces.notFoundComponent ||
452
+ pieces.pendingComponent
453
+ )
454
+ hasComponentPieces = true;
455
+ if (pieces.loader) hasLoaderPieces = true;
456
+ if (hasComponentPieces && hasLoaderPieces) break;
457
+ }
458
+ }
459
+ if (hasComponentPieces || hasLoaderPieces) {
460
+ const runtimeImport = {
461
+ specifiers: [],
462
+ source: this.targetTemplate.fullPkg,
463
+ };
464
+ if (hasComponentPieces) runtimeImport.specifiers.push({ imported: 'lazyRouteComponent' });
465
+ if (hasLoaderPieces) runtimeImport.specifiers.push({ imported: 'lazyFn' });
466
+ imports.push(runtimeImport);
467
+ }
468
+ const routeTreeConfig = buildRouteTreeConfig(acc.routeTree, config.disableTypes);
469
+ const createUpdateRoutes = sortedRouteNodes.map((node) => {
470
+ const pieces = acc.routePiecesByPath[node.routePath];
471
+ const loaderNode = pieces?.loader;
472
+ const componentNode = pieces?.component;
473
+ const errorComponentNode = pieces?.errorComponent;
474
+ const notFoundComponentNode = pieces?.notFoundComponent;
475
+ const pendingComponentNode = pieces?.pendingComponent;
476
+ const lazyComponentNode = pieces?.lazy;
477
+ return [
478
+ [
479
+ `const ${node.variableName}Route = ${node.variableName}RouteImport.update({
480
+ ${[
481
+ `id: '${node.path}'`,
482
+ !node.isNonPath || (node._fsRouteType === 'pathless_layout' && node.cleanedPath)
483
+ ? `path: '${node.cleanedPath}'`
484
+ : void 0,
485
+ `getParentRoute: () => ${findParent(node)}`,
486
+ ]
487
+ .filter(Boolean)
488
+ .join(',')}
489
+ }${config.disableTypes ? '' : 'as any'})`,
490
+ loaderNode
491
+ ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, loaderNode.filePath)), config.addExtensions))}'), 'loader') })`
492
+ : '',
493
+ componentNode || errorComponentNode || notFoundComponentNode || pendingComponentNode
494
+ ? `.update({
495
+ ${[
496
+ ['component', componentNode],
497
+ ['errorComponent', errorComponentNode],
498
+ ['notFoundComponent', notFoundComponentNode],
499
+ ['pendingComponent', pendingComponentNode],
500
+ ]
501
+ .filter((d) => d[1])
502
+ .map((d) => {
503
+ const isVueFile = d[1].filePath.endsWith('.vue');
504
+ const exportName = isVueFile ? 'default' : d[0];
505
+ const importPath = replaceBackslash(
506
+ isVueFile
507
+ ? path.relative(
508
+ path.dirname(config.generatedRouteTree),
509
+ path.resolve(config.routesDirectory, d[1].filePath),
510
+ )
511
+ : removeExt(
512
+ path.relative(
513
+ path.dirname(config.generatedRouteTree),
514
+ path.resolve(config.routesDirectory, d[1].filePath),
515
+ ),
516
+ config.addExtensions,
517
+ ),
518
+ );
519
+ return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`;
520
+ })
521
+ .join('\n,')}
522
+ })`
523
+ : '',
524
+ lazyComponentNode
525
+ ? (() => {
526
+ const isVueFile = lazyComponentNode.filePath.endsWith('.vue');
527
+ const exportAccessor = isVueFile ? 'd.default' : 'd.Route';
528
+ return `.lazy(() => import('./${replaceBackslash(isVueFile ? path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, lazyComponentNode.filePath)) : removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, lazyComponentNode.filePath)), config.addExtensions))}').then((d) => ${exportAccessor}))`;
529
+ })()
530
+ : '',
531
+ ].join(''),
532
+ ].join('\n\n');
533
+ });
534
+ const rootRoutePath = `/${rootPathId}`;
535
+ const rootPieces = acc.routePiecesByPath[rootRoutePath];
536
+ const rootComponentNode = rootPieces?.component;
537
+ const rootErrorComponentNode = rootPieces?.errorComponent;
538
+ const rootNotFoundComponentNode = rootPieces?.notFoundComponent;
539
+ const rootPendingComponentNode = rootPieces?.pendingComponent;
540
+ let rootRouteUpdate = '';
541
+ if (
542
+ rootComponentNode ||
543
+ rootErrorComponentNode ||
544
+ rootNotFoundComponentNode ||
545
+ rootPendingComponentNode
546
+ )
547
+ rootRouteUpdate = `const rootRouteWithChildren = rootRouteImport${
548
+ rootComponentNode ||
549
+ rootErrorComponentNode ||
550
+ rootNotFoundComponentNode ||
551
+ rootPendingComponentNode
552
+ ? `.update({
553
+ ${[
554
+ ['component', rootComponentNode],
555
+ ['errorComponent', rootErrorComponentNode],
556
+ ['notFoundComponent', rootNotFoundComponentNode],
557
+ ['pendingComponent', rootPendingComponentNode],
558
+ ]
559
+ .filter((d) => d[1])
560
+ .map((d) => {
561
+ const isVueFile = d[1].filePath.endsWith('.vue');
562
+ const exportName = isVueFile ? 'default' : d[0];
563
+ const importPath = replaceBackslash(
564
+ isVueFile
565
+ ? path.relative(
566
+ path.dirname(config.generatedRouteTree),
567
+ path.resolve(config.routesDirectory, d[1].filePath),
568
+ )
569
+ : removeExt(
570
+ path.relative(
571
+ path.dirname(config.generatedRouteTree),
572
+ path.resolve(config.routesDirectory, d[1].filePath),
573
+ ),
574
+ config.addExtensions,
575
+ ),
576
+ );
577
+ return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`;
578
+ })
579
+ .join('\n,')}
580
+ })`
581
+ : ''
582
+ }._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`;
583
+ let fileRoutesByPathInterface = '';
584
+ let fileRoutesByFullPath = '';
585
+ if (!config.disableTypes) {
586
+ const routeNodesByFullPath = createRouteNodesByFullPath(acc.routeNodes);
587
+ const routeNodesByTo = createRouteNodesByTo(acc.routeNodes);
588
+ const routeNodesById = createRouteNodesById(acc.routeNodes);
589
+ fileRoutesByFullPath = [
590
+ `export interface FileRoutesByFullPath {
591
+ ${[...routeNodesByFullPath.entries()]
592
+ .filter(([fullPath]) => fullPath)
593
+ .map(([fullPath, routeNode]) => {
594
+ return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
595
+ })}
596
+ }`,
597
+ `export interface FileRoutesByTo {
598
+ ${[...routeNodesByTo.entries()]
599
+ .filter(([to]) => to)
600
+ .map(([to, routeNode]) => {
601
+ return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
602
+ })}
603
+ }`,
604
+ `export interface FileRoutesById {
605
+ '${rootRouteId}': typeof rootRouteImport,
606
+ ${[...routeNodesById.entries()].map(([id, routeNode]) => {
607
+ return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
608
+ })}
609
+ }`,
610
+ `export interface FileRouteTypes {
611
+ fileRoutesByFullPath: FileRoutesByFullPath
612
+ fullPaths: ${
613
+ acc.routeNodes.length > 0
614
+ ? [...routeNodesByFullPath.keys()]
615
+ .filter((fullPath) => fullPath)
616
+ .map((fullPath) => `'${fullPath}'`)
617
+ .join('|')
618
+ : 'never'
619
+ }
620
+ fileRoutesByTo: FileRoutesByTo
621
+ to: ${
622
+ acc.routeNodes.length > 0
623
+ ? [...routeNodesByTo.keys()]
624
+ .filter((to) => to)
625
+ .map((to) => `'${to}'`)
626
+ .join('|')
627
+ : 'never'
628
+ }
629
+ id: ${[`'${rootRouteId}'`, ...[...routeNodesById.keys()].map((id) => `'${id}'`)].join('|')}
630
+ fileRoutesById: FileRoutesById
631
+ }`,
632
+ `export interface RootRouteChildren {
633
+ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}
634
+ }`,
635
+ ].join('\n');
636
+ fileRoutesByPathInterface = buildFileRoutesByPathInterface({
637
+ module: this.targetTemplate.fullPkg,
638
+ interfaceName: 'FileRoutesByPath',
639
+ routeNodes: sortedRouteNodes,
640
+ config,
641
+ });
642
+ }
643
+ const routeTree = [
644
+ `const rootRouteChildren${config.disableTypes ? '' : `: RootRouteChildren`} = {
645
+ ${acc.routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}
646
+ }`,
647
+ rootRouteUpdate
648
+ ? rootRouteUpdate.replace('const rootRouteWithChildren = ', 'export const routeTree = ')
649
+ : `export const routeTree = rootRouteImport._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`,
650
+ ].join('\n');
651
+ checkRouteFullPathUniqueness(
652
+ sortedRouteNodes.filter((d) => d.children === void 0 && 'lazy' !== d._fsRouteType),
653
+ config,
654
+ );
655
+ let mergedImports = mergeImportDeclarations(imports);
656
+ if (config.disableTypes) mergedImports = mergedImports.filter((d) => d.importKind !== 'type');
657
+ const importStatements = mergedImports.map(buildImportString);
658
+ const rootRouteImport = getImportForRouteNode(
659
+ rootRouteNode,
660
+ config,
661
+ this.generatedRouteTreePath,
662
+ this.root,
663
+ );
664
+ routeImports.unshift(rootRouteImport);
665
+ let footer = [];
666
+ if (config.routeTreeFileFooter)
667
+ if (Array.isArray(config.routeTreeFileFooter)) footer = config.routeTreeFileFooter;
668
+ else footer = config.routeTreeFileFooter();
669
+ return {
670
+ routeTreeContent: [
671
+ ...config.routeTreeFileHeader,
672
+ `// This file was automatically generated by TanStack Router.
673
+ // You should NOT make any changes in this file as it will be overwritten.
674
+ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,
675
+ [...importStatements].join('\n'),
676
+ mergeImportDeclarations(routeImports).map(buildImportString).join('\n'),
677
+ virtualRouteNodes.join('\n'),
678
+ createUpdateRoutes.join('\n'),
679
+ fileRoutesByFullPath,
680
+ fileRoutesByPathInterface,
681
+ routeTreeConfig.join('\n'),
682
+ routeTree,
683
+ ...footer,
684
+ ]
685
+ .filter(Boolean)
686
+ .join('\n\n'),
687
+ routeTree: acc.routeTree,
688
+ routeNodes: acc.routeNodes,
689
+ };
690
+ }
691
+ async processRouteNodeFile(node) {
692
+ const result = await this.isRouteFileCacheFresh(node);
693
+ if (result.status === 'fresh')
694
+ return {
695
+ node: result.cacheEntry.node,
696
+ shouldWriteTree: false,
697
+ cacheEntry: result.cacheEntry,
698
+ };
699
+ const previousCacheEntry = result.cacheEntry;
700
+ const existingRouteFile = await this.fs.readFile(node.fullPath);
701
+ if (existingRouteFile === 'file-not-existing')
702
+ throw new Error(`⚠️ File ${node.fullPath} does not exist`);
703
+ if (node.routePath) validateRouteParams(node.routePath, node.filePath, this.logger);
704
+ const updatedCacheEntry = {
705
+ fileContent: existingRouteFile.fileContent,
706
+ mtimeMs: existingRouteFile.stat.mtimeMs,
707
+ routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',
708
+ node,
709
+ };
710
+ const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? '';
711
+ let shouldWriteRouteFile = false;
712
+ let shouldWriteTree = false;
713
+ if (!existingRouteFile.fileContent) {
714
+ shouldWriteRouteFile = true;
715
+ shouldWriteTree = true;
716
+ if (node._fsRouteType === 'lazy') {
717
+ const tLazyRouteTemplate = this.targetTemplate.lazyRoute;
718
+ updatedCacheEntry.fileContent = await this.fillRouteTemplate(
719
+ node,
720
+ (this.config.customScaffolding?.lazyRouteTemplate ||
721
+ this.config.customScaffolding?.routeTemplate) ??
722
+ tLazyRouteTemplate.template(),
723
+ {
724
+ tsrImports: tLazyRouteTemplate.imports.tsrImports(),
725
+ tsrPath: escapedRoutePath.replaceAll(/\{(.+?)\}/gm, '$1'),
726
+ tsrExportStart: tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),
727
+ tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd(),
728
+ },
729
+ );
730
+ } else if (
731
+ ['layout', 'static'].some((d) => d === node._fsRouteType) ||
732
+ ['component', 'pendingComponent', 'errorComponent', 'notFoundComponent', 'loader'].every(
733
+ (d) => d !== node._fsRouteType,
734
+ )
735
+ ) {
736
+ const tRouteTemplate = this.targetTemplate.route;
737
+ updatedCacheEntry.fileContent = await this.fillRouteTemplate(
738
+ node,
739
+ this.config.customScaffolding?.routeTemplate ?? tRouteTemplate.template(),
740
+ {
741
+ tsrImports: tRouteTemplate.imports.tsrImports(),
742
+ tsrPath: escapedRoutePath.replaceAll(/\{(.+?)\}/gm, '$1'),
743
+ tsrExportStart: tRouteTemplate.imports.tsrExportStart(escapedRoutePath),
744
+ tsrExportEnd: tRouteTemplate.imports.tsrExportEnd(),
745
+ },
746
+ );
747
+ } else return null;
748
+ }
749
+ if (!node.filePath.endsWith('.vue')) {
750
+ const transformOptions = {
751
+ source: updatedCacheEntry.fileContent,
752
+ filename: node.fullPath,
753
+ ctx: {
754
+ target: this.config.target,
755
+ routeId: escapedRoutePath,
756
+ lazy: node._fsRouteType === 'lazy',
757
+ },
758
+ node,
759
+ };
760
+ const transformResult = await transform({
761
+ ...transformOptions,
762
+ parseSource: await this.getParseSource(transformOptions),
763
+ });
764
+ if (transformResult.result === 'no-route-export') {
765
+ const fileName = path.basename(node.fullPath);
766
+ const dirName = path.dirname(node.fullPath);
767
+ const ignorePrefix = this.config.routeFileIgnorePrefix;
768
+ const ignorePattern = this.config.routeFileIgnorePattern;
769
+ const suggestedFileName = `${ignorePrefix}${fileName}`;
770
+ const suggestedFullPath = path.join(dirName, suggestedFileName);
771
+ let message = `Warning: Route file "${node.fullPath}" does not export a Route. This file will not be included in the route tree.`;
772
+ message += `\n\nIf this file is not intended to be a route, you can exclude it using one of these options:`;
773
+ message += `\n 1. Rename the file to "${suggestedFullPath}" (prefix with "${ignorePrefix}")`;
774
+ message += `\n 2. Use 'routeFileIgnorePattern' in your config to match this file`;
775
+ message += `\n\nCurrent configuration:`;
776
+ message += `\n routeFileIgnorePrefix: "${ignorePrefix}"`;
777
+ message += `\n routeFileIgnorePattern: ${ignorePattern ? `"${ignorePattern}"` : 'undefined'}`;
778
+ this.logger.warn(message);
779
+ return null;
780
+ }
781
+ if (transformResult.result === 'error')
782
+ throw new Error(`Error transforming route file ${node.fullPath}: ${transformResult.error}`);
783
+ if (transformResult.result === 'modified') {
784
+ updatedCacheEntry.fileContent = transformResult.output;
785
+ shouldWriteRouteFile = true;
786
+ }
787
+ }
788
+ for (const plugin of this.plugins)
789
+ plugin.afterTransform?.({
790
+ node,
791
+ prevNode: previousCacheEntry?.node,
792
+ });
793
+ if (shouldWriteRouteFile)
794
+ updatedCacheEntry.mtimeMs = (
795
+ await this.safeFileWrite({
796
+ filePath: node.fullPath,
797
+ newContent: updatedCacheEntry.fileContent,
798
+ strategy: {
799
+ type: 'mtime',
800
+ expectedMtimeMs: updatedCacheEntry.mtimeMs,
801
+ },
802
+ })
803
+ ).mtimeMs;
804
+ this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry);
805
+ return {
806
+ node,
807
+ shouldWriteTree,
808
+ cacheEntry: updatedCacheEntry,
809
+ };
810
+ }
811
+ async didRouteFileChangeComparedToCache(file, cache) {
812
+ const cacheEntry = this[cache].get(file.path);
813
+ return this.didFileChangeComparedToCache(file, cacheEntry);
814
+ }
815
+ async didFileChangeComparedToCache(file, cacheEntry) {
816
+ if (!cacheEntry) return { result: 'file-not-in-cache' };
817
+ let mtimeMs = file.mtimeMs;
818
+ if (mtimeMs === void 0)
819
+ try {
820
+ mtimeMs = (await this.fs.stat(file.path)).mtimeMs;
821
+ } catch {
822
+ return { result: 'cannot-stat-file' };
823
+ }
824
+ return {
825
+ result: mtimeMs !== cacheEntry.mtimeMs,
826
+ mtimeMs,
827
+ cacheEntry,
828
+ };
829
+ }
830
+ async safeFileWrite(opts) {
831
+ const tmpPath = this.getTempFileName(opts.filePath);
832
+ await this.fs.writeFile(tmpPath, opts.newContent);
833
+ if (opts.strategy.type === 'mtime') {
834
+ const beforeStat = await this.fs.stat(opts.filePath);
835
+ if (beforeStat.mtimeMs !== opts.strategy.expectedMtimeMs)
836
+ throw rerun({
837
+ msg: `File ${opts.filePath} was modified by another process during processing.`,
838
+ event: {
839
+ type: 'update',
840
+ path: opts.filePath,
841
+ },
842
+ });
843
+ const newFileState = await this.fs.stat(tmpPath);
844
+ if (newFileState.mode !== beforeStat.mode) await this.fs.chmod(tmpPath, beforeStat.mode);
845
+ if (newFileState.uid !== beforeStat.uid || newFileState.gid !== beforeStat.gid)
846
+ try {
847
+ await this.fs.chown(tmpPath, beforeStat.uid, beforeStat.gid);
848
+ } catch (err) {
849
+ if (typeof err === 'object' && err !== null && 'code' in err && err.code === 'EPERM')
850
+ console.warn(`[safeFileWrite] chown failed: ${err.message}`);
851
+ else throw err;
852
+ }
853
+ } else if (await checkFileExists(opts.filePath))
854
+ throw rerun({
855
+ msg: `File ${opts.filePath} already exists. Cannot overwrite.`,
856
+ event: {
857
+ type: 'update',
858
+ path: opts.filePath,
859
+ },
860
+ });
861
+ await this.fs.rename(tmpPath, opts.filePath);
862
+ return await this.fs.stat(opts.filePath);
863
+ }
864
+ getTempFileName(filePath) {
865
+ const absPath = path.resolve(filePath);
866
+ const hash = crypto.createHash('md5').update(absPath).digest('hex');
867
+ if (!this.sessionId) {
868
+ mkdirSync(this.config.tmpDir, { recursive: true });
869
+ this.sessionId = crypto.randomBytes(4).toString('hex');
870
+ }
871
+ return path.join(this.config.tmpDir, `${this.sessionId}-${hash}`);
872
+ }
873
+ async isRouteFileCacheFresh(node) {
874
+ const fileChangedCache = await this.didRouteFileChangeComparedToCache(
875
+ { path: node.fullPath },
876
+ 'routeNodeCache',
877
+ );
878
+ if (fileChangedCache.result === false) {
879
+ this.routeNodeShadowCache.set(node.fullPath, fileChangedCache.cacheEntry);
880
+ return {
881
+ status: 'fresh',
882
+ cacheEntry: fileChangedCache.cacheEntry,
883
+ };
884
+ }
885
+ if (fileChangedCache.result === 'cannot-stat-file')
886
+ throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`);
887
+ const mtimeMs = fileChangedCache.result === true ? fileChangedCache.mtimeMs : void 0;
888
+ const shadowCacheFileChange = await this.didRouteFileChangeComparedToCache(
889
+ {
890
+ path: node.fullPath,
891
+ mtimeMs,
892
+ },
893
+ 'routeNodeShadowCache',
894
+ );
895
+ if (shadowCacheFileChange.result === 'cannot-stat-file')
896
+ throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`);
897
+ if (shadowCacheFileChange.result === false) {
898
+ if (fileChangedCache.result === true)
899
+ return {
900
+ status: 'fresh',
901
+ cacheEntry: shadowCacheFileChange.cacheEntry,
902
+ };
903
+ }
904
+ if (fileChangedCache.result === 'file-not-in-cache') return { status: 'stale' };
905
+ return {
906
+ status: 'stale',
907
+ cacheEntry: fileChangedCache.cacheEntry,
908
+ };
909
+ }
910
+ async handleRootNode(node) {
911
+ const result = await this.isRouteFileCacheFresh(node);
912
+ if (result.status === 'fresh') this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry);
913
+ const rootNodeFile = await this.fs.readFile(node.fullPath);
914
+ if (rootNodeFile === 'file-not-existing')
915
+ throw new Error(`⚠️ expected root route to exist at ${node.fullPath}`);
916
+ const updatedCacheEntry = {
917
+ fileContent: rootNodeFile.fileContent,
918
+ mtimeMs: rootNodeFile.stat.mtimeMs,
919
+ routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',
920
+ node,
921
+ };
922
+ if (!rootNodeFile.fileContent) {
923
+ const rootTemplate = this.targetTemplate.rootRoute;
924
+ const rootRouteContent = await this.fillRouteTemplate(node, rootTemplate.template(), {
925
+ tsrImports: rootTemplate.imports.tsrImports(),
926
+ tsrPath: rootPathId,
927
+ tsrExportStart: rootTemplate.imports.tsrExportStart(),
928
+ tsrExportEnd: rootTemplate.imports.tsrExportEnd(),
929
+ });
930
+ this.logger.log(`🟡 Creating ${node.fullPath}`);
931
+ const stats = await this.safeFileWrite({
932
+ filePath: node.fullPath,
933
+ newContent: rootRouteContent,
934
+ strategy: {
935
+ type: 'mtime',
936
+ expectedMtimeMs: rootNodeFile.stat.mtimeMs,
937
+ },
938
+ });
939
+ updatedCacheEntry.fileContent = rootRouteContent;
940
+ updatedCacheEntry.mtimeMs = stats.mtimeMs;
941
+ }
942
+ this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry);
943
+ }
944
+ async getCrawlingResult() {
945
+ await this.runPromise;
946
+ return this.crawlingResult;
947
+ }
948
+ static handleNode(node, acc, prefixMap, config) {
949
+ let parentRoute = hasParentRoute(prefixMap, node, node.routePath);
950
+ if (node.routePath) {
951
+ let searchPath = node.routePath;
952
+ while (searchPath.length > 0) {
953
+ const lastSlash = searchPath.lastIndexOf('/');
954
+ if (lastSlash <= 0) break;
955
+ searchPath = searchPath.substring(0, lastSlash);
956
+ const candidate = acc.routeNodesByPath.get(searchPath);
957
+ if (candidate && candidate.routePath !== node.routePath) {
958
+ if (candidate !== parentRoute) {
959
+ if (
960
+ !parentRoute ||
961
+ (candidate.routePath?.length ?? 0) > (parentRoute.routePath?.length ?? 0)
962
+ )
963
+ parentRoute = candidate;
964
+ }
965
+ break;
966
+ }
967
+ }
968
+ }
969
+ if (node._virtualParentRoutePath !== void 0) {
970
+ const explicitParent = acc.routeNodesByPath.get(node._virtualParentRoutePath);
971
+ if (explicitParent) parentRoute = explicitParent;
972
+ else if (node._virtualParentRoutePath === `/__root`) parentRoute = null;
973
+ }
974
+ if (parentRoute) node.parent = parentRoute;
975
+ node.path = determineNodePath(node);
976
+ const trimmedPath = trimPathLeft(node.path ?? '');
977
+ const originalPath =
978
+ node.originalRoutePath && node.parent?.originalRoutePath
979
+ ? node.originalRoutePath.replace(node.parent.originalRoutePath, '') || '/'
980
+ : node.originalRoutePath;
981
+ const routePathSegmentMetadata = getRoutePathSegmentMetadataForPath(
982
+ node,
983
+ node.path ?? '/',
984
+ node.parent?.routePath,
985
+ );
986
+ const trimmedOriginalPath = trimPathLeft(originalPath ?? '');
987
+ const split = trimmedPath.split('/');
988
+ const pathSplit = (node.path ?? '').split('/');
989
+ const originalSplit = trimmedOriginalPath.split('/');
990
+ const lastRouteSegment = split[split.length - 1] ?? trimmedPath;
991
+ const lastOriginalSegment = originalSplit[originalSplit.length - 1] ?? trimmedOriginalPath;
992
+ node.isNonPath =
993
+ (!routePathSegmentMetadata?.[pathSplit.length - 1]?.literalLeadingUnderscore &&
994
+ isSegmentPathless(lastRouteSegment, lastOriginalSegment)) ||
995
+ split.every((part) => this.routeGroupPatternRegex.test(part));
996
+ node.cleanedPath = removeGroups(
997
+ removeLayoutSegmentsAndUnderscoresWithEscape(
998
+ node.path,
999
+ originalPath,
1000
+ routePathSegmentMetadata,
1001
+ ),
1002
+ );
1003
+ if (node._fsRouteType === 'layout' || node._fsRouteType === 'pathless_layout')
1004
+ node.cleanedPath = removeTrailingSlash(node.cleanedPath);
1005
+ if (
1006
+ !node.isVirtual &&
1007
+ [
1008
+ 'lazy',
1009
+ 'loader',
1010
+ 'component',
1011
+ 'pendingComponent',
1012
+ 'errorComponent',
1013
+ 'notFoundComponent',
1014
+ ].some((d) => d === node._fsRouteType)
1015
+ ) {
1016
+ acc.routePiecesByPath[node.routePath] = acc.routePiecesByPath[node.routePath] || {};
1017
+ const pieceKey = node._fsRouteType === 'lazy' ? 'lazy' : node._fsRouteType;
1018
+ acc.routePiecesByPath[node.routePath][pieceKey] = node;
1019
+ if (!acc.routeNodesByPath.get(node.routePath) && node.routePath !== `/__root`)
1020
+ this.handleNode(
1021
+ {
1022
+ ...node,
1023
+ isVirtual: true,
1024
+ _fsRouteType: 'static',
1025
+ },
1026
+ acc,
1027
+ prefixMap,
1028
+ config,
1029
+ );
1030
+ return;
1031
+ }
1032
+ const isPathlessLayoutWithPath =
1033
+ node._fsRouteType === 'pathless_layout' && node.cleanedPath && node.cleanedPath.length > 0;
1034
+ if (!node.isVirtual && isPathlessLayoutWithPath) {
1035
+ const immediateParentPath = removeLastSegmentFromPath(node.routePath) || '/';
1036
+ const immediateParentOriginalPath = removeLastSegmentFromPath(node.originalRoutePath) || '/';
1037
+ let searchPath = immediateParentPath;
1038
+ while (searchPath) {
1039
+ const candidate = acc.routeNodesByPath.get(searchPath);
1040
+ if (candidate && !candidate.isVirtual && candidate.path !== '/') {
1041
+ node.parent = candidate;
1042
+ node.path = node.routePath?.replace(candidate.routePath ?? '', '') || '/';
1043
+ const pathRelativeToParent =
1044
+ immediateParentPath.replace(candidate.routePath ?? '', '') || '/';
1045
+ node.cleanedPath = removeGroups(
1046
+ removeLayoutSegmentsAndUnderscoresWithEscape(
1047
+ pathRelativeToParent,
1048
+ immediateParentOriginalPath.replace(candidate.originalRoutePath ?? '', '') || '/',
1049
+ getRoutePathSegmentMetadataForPath(node, pathRelativeToParent, candidate.routePath),
1050
+ ),
1051
+ );
1052
+ break;
1053
+ }
1054
+ if (searchPath === '/') break;
1055
+ searchPath = removeLastSegmentFromPath(searchPath) || '/';
1056
+ }
1057
+ }
1058
+ if (node.parent) {
1059
+ node.parent.children = node.parent.children ?? [];
1060
+ node.parent.children.push(node);
1061
+ } else acc.routeTree.push(node);
1062
+ acc.routeNodes.push(node);
1063
+ if (node.routePath) acc.routeNodesByPath.set(node.routePath, node);
1064
+ }
1065
+ isFileRelevantForRouteTreeGeneration(filePath) {
1066
+ if (filePath === this.generatedRouteTreePath) return true;
1067
+ if (filePath.startsWith(this.routesDirectoryPath)) return true;
1068
+ if (
1069
+ typeof this.config.virtualRouteConfig === 'string' &&
1070
+ filePath === this.config.virtualRouteConfig
1071
+ )
1072
+ return true;
1073
+ if (this.routeNodeCache.has(filePath)) return true;
1074
+ if (isVirtualConfigFile(path.basename(filePath))) return true;
1075
+ if (this.physicalDirectories.some((dir) => filePath.startsWith(dir))) return true;
1076
+ return false;
1077
+ }
1078
+ };
1079
+ //#endregion
1080
+ export { Generator };