one 1.25.12 → 1.25.15

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 (308) hide show
  1. package/dist/cjs/cli/build.cjs +37 -186
  2. package/dist/cjs/cli/build.native.js +270 -423
  3. package/dist/cjs/cli/build.native.js.map +1 -1
  4. package/dist/cjs/cli/buildPage.cjs +7 -7
  5. package/dist/cjs/cli/buildPage.native.js +7 -7
  6. package/dist/cjs/cli/buildPage.native.js.map +1 -1
  7. package/dist/cjs/cli/buildPageWorker.cjs +1 -1
  8. package/dist/cjs/cli/buildPageWorker.native.js +1 -1
  9. package/dist/cjs/cli/buildPageWorker.native.js.map +1 -1
  10. package/dist/cjs/cli/serverRouteModules.cjs +47 -0
  11. package/dist/cjs/cli/serverRouteModules.native.js +52 -0
  12. package/dist/cjs/cli/serverRouteModules.native.js.map +1 -0
  13. package/dist/cjs/cli/workerPool.native.js.map +1 -1
  14. package/dist/cjs/createApp.cjs +3 -0
  15. package/dist/cjs/createDevHandleRequest.cjs +151 -0
  16. package/dist/cjs/createDevHandleRequest.native.js +194 -0
  17. package/dist/cjs/createDevHandleRequest.native.js.map +1 -0
  18. package/dist/cjs/createHandleRequest.cjs +1 -123
  19. package/dist/cjs/createHandleRequest.native.js +1 -163
  20. package/dist/cjs/createHandleRequest.native.js.map +1 -1
  21. package/dist/cjs/createHandleRequest.test.cjs +25 -25
  22. package/dist/cjs/createHandleRequest.test.native.js +25 -25
  23. package/dist/cjs/createHandleRequest.test.native.js.map +1 -1
  24. package/dist/cjs/headless-server.native.js.map +1 -1
  25. package/dist/cjs/headless.cjs +4 -0
  26. package/dist/cjs/headless.native.js +4 -0
  27. package/dist/cjs/headless.native.js.map +1 -1
  28. package/dist/cjs/layouts/Drawer.cjs +0 -2
  29. package/dist/cjs/layouts/Drawer.native.js.map +1 -1
  30. package/dist/cjs/layouts/Tabs.cjs +0 -2
  31. package/dist/cjs/layouts/Tabs.native.js.map +1 -1
  32. package/dist/cjs/router/diagnoseRouteLoadFailure.native.js.map +1 -1
  33. package/dist/cjs/router/useViteRoutes.cjs +9 -1
  34. package/dist/cjs/router/useViteRoutes.native.js +9 -1
  35. package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
  36. package/dist/cjs/router/web/WebStackView.cjs +0 -2
  37. package/dist/cjs/router/web/WebStackView.native.js +0 -2
  38. package/dist/cjs/router/web/WebStackView.native.js.map +1 -1
  39. package/dist/cjs/serve-worker.cjs +3 -2
  40. package/dist/cjs/serve-worker.native.js +3 -2
  41. package/dist/cjs/serve-worker.native.js.map +1 -1
  42. package/dist/cjs/server/oneServe.cjs +23 -4
  43. package/dist/cjs/server/oneServe.native.js +25 -6
  44. package/dist/cjs/server/oneServe.native.js.map +1 -1
  45. package/dist/cjs/server/routeExportsFromEntry.cjs +47 -0
  46. package/dist/cjs/server/routeExportsFromEntry.native.js +52 -0
  47. package/dist/cjs/server/routeExportsFromEntry.native.js.map +1 -0
  48. package/dist/cjs/server/workerHandler.cjs +30 -12
  49. package/dist/cjs/server/workerHandler.native.js +32 -13
  50. package/dist/cjs/server/workerHandler.native.js.map +1 -1
  51. package/dist/cjs/server/workerHandler.test.cjs +43 -10
  52. package/dist/cjs/server/workerHandler.test.native.js +46 -10
  53. package/dist/cjs/server/workerHandler.test.native.js.map +1 -1
  54. package/dist/cjs/views/ScrollBehavior.native.js.map +1 -1
  55. package/dist/cjs/vite/cloudflareWranglerConfig.cjs +247 -0
  56. package/dist/cjs/vite/cloudflareWranglerConfig.native.js +392 -0
  57. package/dist/cjs/vite/cloudflareWranglerConfig.native.js.map +1 -0
  58. package/dist/cjs/vite/cloudflareWranglerConfig.test.cjs +116 -0
  59. package/dist/cjs/vite/cloudflareWranglerConfig.test.native.js +120 -0
  60. package/dist/cjs/vite/cloudflareWranglerConfig.test.native.js.map +1 -0
  61. package/dist/cjs/vite/one.cjs +4 -2
  62. package/dist/cjs/vite/one.native.js +8 -6
  63. package/dist/cjs/vite/one.native.js.map +1 -1
  64. package/dist/cjs/vite/plugins/SSRCSSPlugin.cjs +10 -1
  65. package/dist/cjs/vite/plugins/SSRCSSPlugin.native.js +52 -3
  66. package/dist/cjs/vite/plugins/SSRCSSPlugin.native.js.map +1 -1
  67. package/dist/cjs/vite/plugins/environmentGuardPlugin.cjs +1 -1
  68. package/dist/cjs/vite/plugins/environmentGuardPlugin.native.js +1 -1
  69. package/dist/cjs/vite/plugins/environmentGuardPlugin.native.js.map +1 -1
  70. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.cjs +4 -0
  71. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.native.js +4 -0
  72. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.native.js.map +1 -1
  73. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +14 -5
  74. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +15 -5
  75. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  76. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.test.cjs +47 -0
  77. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.test.native.js +47 -0
  78. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.test.native.js.map +1 -1
  79. package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +9 -7
  80. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +11 -7
  81. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  82. package/dist/cjs/vite/plugins/virtualEntryPlugin.test.cjs +12 -0
  83. package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js +12 -0
  84. package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
  85. package/dist/cjs/vite/plugins/workerdDevPlugin.cjs +364 -0
  86. package/dist/cjs/vite/plugins/workerdDevPlugin.native.js +461 -0
  87. package/dist/cjs/vite/plugins/workerdDevPlugin.native.js.map +1 -0
  88. package/dist/cjs/vite/plugins/workerdDevPlugin.test.cjs +42 -0
  89. package/dist/cjs/vite/plugins/workerdDevPlugin.test.native.js +45 -0
  90. package/dist/cjs/vite/plugins/workerdDevPlugin.test.native.js.map +1 -0
  91. package/dist/cjs/vite/replaceLoader.cjs +6 -3
  92. package/dist/cjs/vite/replaceLoader.native.js +8 -3
  93. package/dist/cjs/vite/replaceLoader.native.js.map +1 -1
  94. package/dist/esm/cli/build.mjs +31 -180
  95. package/dist/esm/cli/build.mjs.map +1 -1
  96. package/dist/esm/cli/build.native.js +264 -417
  97. package/dist/esm/cli/build.native.js.map +1 -1
  98. package/dist/esm/cli/buildPage.mjs +7 -7
  99. package/dist/esm/cli/buildPage.mjs.map +1 -1
  100. package/dist/esm/cli/buildPage.native.js +7 -7
  101. package/dist/esm/cli/buildPage.native.js.map +1 -1
  102. package/dist/esm/cli/buildPageWorker.mjs +1 -1
  103. package/dist/esm/cli/buildPageWorker.mjs.map +1 -1
  104. package/dist/esm/cli/buildPageWorker.native.js +1 -1
  105. package/dist/esm/cli/buildPageWorker.native.js.map +1 -1
  106. package/dist/esm/cli/serverRouteModules.mjs +22 -0
  107. package/dist/esm/cli/serverRouteModules.mjs.map +1 -0
  108. package/dist/esm/cli/serverRouteModules.native.js +24 -0
  109. package/dist/esm/cli/serverRouteModules.native.js.map +1 -0
  110. package/dist/esm/cli/workerPool.mjs.map +1 -1
  111. package/dist/esm/cli/workerPool.native.js.map +1 -1
  112. package/dist/esm/createApp.mjs +4 -1
  113. package/dist/esm/createApp.mjs.map +1 -1
  114. package/dist/esm/createDevHandleRequest.mjs +126 -0
  115. package/dist/esm/createDevHandleRequest.mjs.map +1 -0
  116. package/dist/esm/createDevHandleRequest.native.js +166 -0
  117. package/dist/esm/createDevHandleRequest.native.js.map +1 -0
  118. package/dist/esm/createHandleRequest.mjs +1 -123
  119. package/dist/esm/createHandleRequest.mjs.map +1 -1
  120. package/dist/esm/createHandleRequest.native.js +1 -163
  121. package/dist/esm/createHandleRequest.native.js.map +1 -1
  122. package/dist/esm/createHandleRequest.test.mjs +1 -1
  123. package/dist/esm/createHandleRequest.test.native.js +1 -1
  124. package/dist/esm/headless-server.mjs.map +1 -1
  125. package/dist/esm/headless-server.native.js.map +1 -1
  126. package/dist/esm/headless.mjs +4 -0
  127. package/dist/esm/headless.mjs.map +1 -1
  128. package/dist/esm/headless.native.js +4 -0
  129. package/dist/esm/headless.native.js.map +1 -1
  130. package/dist/esm/layouts/Drawer.mjs +0 -2
  131. package/dist/esm/layouts/Drawer.mjs.map +1 -1
  132. package/dist/esm/layouts/Drawer.native.js.map +1 -1
  133. package/dist/esm/layouts/Tabs.mjs +0 -2
  134. package/dist/esm/layouts/Tabs.mjs.map +1 -1
  135. package/dist/esm/layouts/Tabs.native.js.map +1 -1
  136. package/dist/esm/router/diagnoseRouteLoadFailure.mjs.map +1 -1
  137. package/dist/esm/router/diagnoseRouteLoadFailure.native.js.map +1 -1
  138. package/dist/esm/router/useViteRoutes.mjs +9 -1
  139. package/dist/esm/router/useViteRoutes.mjs.map +1 -1
  140. package/dist/esm/router/useViteRoutes.native.js +9 -1
  141. package/dist/esm/router/useViteRoutes.native.js.map +1 -1
  142. package/dist/esm/router/web/WebStackView.mjs +0 -2
  143. package/dist/esm/router/web/WebStackView.mjs.map +1 -1
  144. package/dist/esm/router/web/WebStackView.native.js +0 -2
  145. package/dist/esm/router/web/WebStackView.native.js.map +1 -1
  146. package/dist/esm/serve-worker.mjs +3 -2
  147. package/dist/esm/serve-worker.mjs.map +1 -1
  148. package/dist/esm/serve-worker.native.js +3 -2
  149. package/dist/esm/serve-worker.native.js.map +1 -1
  150. package/dist/esm/server/oneServe.mjs +23 -4
  151. package/dist/esm/server/oneServe.mjs.map +1 -1
  152. package/dist/esm/server/oneServe.native.js +25 -6
  153. package/dist/esm/server/oneServe.native.js.map +1 -1
  154. package/dist/esm/server/routeExportsFromEntry.mjs +21 -0
  155. package/dist/esm/server/routeExportsFromEntry.mjs.map +1 -0
  156. package/dist/esm/server/routeExportsFromEntry.native.js +23 -0
  157. package/dist/esm/server/routeExportsFromEntry.native.js.map +1 -0
  158. package/dist/esm/server/workerHandler.mjs +30 -12
  159. package/dist/esm/server/workerHandler.mjs.map +1 -1
  160. package/dist/esm/server/workerHandler.native.js +32 -13
  161. package/dist/esm/server/workerHandler.native.js.map +1 -1
  162. package/dist/esm/server/workerHandler.test.mjs +43 -10
  163. package/dist/esm/server/workerHandler.test.mjs.map +1 -1
  164. package/dist/esm/server/workerHandler.test.native.js +46 -10
  165. package/dist/esm/server/workerHandler.test.native.js.map +1 -1
  166. package/dist/esm/views/ScrollBehavior.mjs.map +1 -1
  167. package/dist/esm/views/ScrollBehavior.native.js.map +1 -1
  168. package/dist/esm/vite/cloudflareWranglerConfig.mjs +202 -0
  169. package/dist/esm/vite/cloudflareWranglerConfig.mjs.map +1 -0
  170. package/dist/esm/vite/cloudflareWranglerConfig.native.js +344 -0
  171. package/dist/esm/vite/cloudflareWranglerConfig.native.js.map +1 -0
  172. package/dist/esm/vite/cloudflareWranglerConfig.test.mjs +117 -0
  173. package/dist/esm/vite/cloudflareWranglerConfig.test.mjs.map +1 -0
  174. package/dist/esm/vite/cloudflareWranglerConfig.test.native.js +118 -0
  175. package/dist/esm/vite/cloudflareWranglerConfig.test.native.js.map +1 -0
  176. package/dist/esm/vite/one.mjs +4 -2
  177. package/dist/esm/vite/one.mjs.map +1 -1
  178. package/dist/esm/vite/one.native.js +8 -6
  179. package/dist/esm/vite/one.native.js.map +1 -1
  180. package/dist/esm/vite/plugins/SSRCSSPlugin.mjs +10 -1
  181. package/dist/esm/vite/plugins/SSRCSSPlugin.mjs.map +1 -1
  182. package/dist/esm/vite/plugins/SSRCSSPlugin.native.js +52 -3
  183. package/dist/esm/vite/plugins/SSRCSSPlugin.native.js.map +1 -1
  184. package/dist/esm/vite/plugins/environmentGuardPlugin.mjs +1 -1
  185. package/dist/esm/vite/plugins/environmentGuardPlugin.mjs.map +1 -1
  186. package/dist/esm/vite/plugins/environmentGuardPlugin.native.js +1 -1
  187. package/dist/esm/vite/plugins/environmentGuardPlugin.native.js.map +1 -1
  188. package/dist/esm/vite/plugins/environmentGuardPlugin.test.mjs +4 -0
  189. package/dist/esm/vite/plugins/environmentGuardPlugin.test.mjs.map +1 -1
  190. package/dist/esm/vite/plugins/environmentGuardPlugin.test.native.js +4 -0
  191. package/dist/esm/vite/plugins/environmentGuardPlugin.test.native.js.map +1 -1
  192. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +13 -4
  193. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
  194. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +14 -4
  195. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  196. package/dist/esm/vite/plugins/fileSystemRouterPlugin.test.mjs +47 -0
  197. package/dist/esm/vite/plugins/fileSystemRouterPlugin.test.mjs.map +1 -1
  198. package/dist/esm/vite/plugins/fileSystemRouterPlugin.test.native.js +47 -0
  199. package/dist/esm/vite/plugins/fileSystemRouterPlugin.test.native.js.map +1 -1
  200. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +9 -7
  201. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
  202. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +11 -7
  203. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  204. package/dist/esm/vite/plugins/virtualEntryPlugin.test.mjs +12 -0
  205. package/dist/esm/vite/plugins/virtualEntryPlugin.test.mjs.map +1 -1
  206. package/dist/esm/vite/plugins/virtualEntryPlugin.test.native.js +12 -0
  207. package/dist/esm/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
  208. package/dist/esm/vite/plugins/workerdDevPlugin.mjs +336 -0
  209. package/dist/esm/vite/plugins/workerdDevPlugin.mjs.map +1 -0
  210. package/dist/esm/vite/plugins/workerdDevPlugin.native.js +430 -0
  211. package/dist/esm/vite/plugins/workerdDevPlugin.native.js.map +1 -0
  212. package/dist/esm/vite/plugins/workerdDevPlugin.test.mjs +43 -0
  213. package/dist/esm/vite/plugins/workerdDevPlugin.test.mjs.map +1 -0
  214. package/dist/esm/vite/plugins/workerdDevPlugin.test.native.js +43 -0
  215. package/dist/esm/vite/plugins/workerdDevPlugin.test.native.js.map +1 -0
  216. package/dist/esm/vite/replaceLoader.mjs +6 -3
  217. package/dist/esm/vite/replaceLoader.mjs.map +1 -1
  218. package/dist/esm/vite/replaceLoader.native.js +8 -3
  219. package/dist/esm/vite/replaceLoader.native.js.map +1 -1
  220. package/package.json +9 -9
  221. package/src/cli/build.ts +48 -224
  222. package/src/cli/buildPage.ts +9 -7
  223. package/src/cli/buildPageWorker.ts +1 -0
  224. package/src/cli/serverRouteModules.ts +33 -0
  225. package/src/cli/workerPool.ts +1 -0
  226. package/src/createApp.tsx +5 -1
  227. package/src/createDevHandleRequest.ts +186 -0
  228. package/src/createHandleRequest.test.ts +1 -1
  229. package/src/createHandleRequest.ts +2 -172
  230. package/src/headless-server.ts +0 -1
  231. package/src/headless.tsx +5 -0
  232. package/src/layouts/Drawer.web.tsx +0 -3
  233. package/src/layouts/Tabs.web.tsx +0 -2
  234. package/src/router/diagnoseRouteLoadFailure.ts +3 -1
  235. package/src/router/useViteRoutes.tsx +9 -1
  236. package/src/router/web/WebStackView.tsx +0 -3
  237. package/src/serve-worker.ts +6 -1
  238. package/src/server/oneServe.ts +40 -16
  239. package/src/server/routeExportsFromEntry.ts +59 -0
  240. package/src/server/workerHandler.test.ts +37 -9
  241. package/src/server/workerHandler.ts +39 -13
  242. package/src/views/ScrollBehavior.tsx +5 -1
  243. package/src/vite/cloudflareWranglerConfig.test.ts +101 -0
  244. package/src/vite/cloudflareWranglerConfig.ts +252 -0
  245. package/src/vite/one.ts +14 -1
  246. package/src/vite/plugins/SSRCSSPlugin.ts +17 -2
  247. package/src/vite/plugins/environmentGuardPlugin.test.ts +5 -0
  248. package/src/vite/plugins/environmentGuardPlugin.ts +2 -2
  249. package/src/vite/plugins/fileSystemRouterPlugin.test.ts +44 -0
  250. package/src/vite/plugins/fileSystemRouterPlugin.tsx +20 -8
  251. package/src/vite/plugins/virtualEntryPlugin.test.ts +13 -0
  252. package/src/vite/plugins/virtualEntryPlugin.ts +13 -9
  253. package/src/vite/plugins/workerdDevPlugin.test.ts +44 -0
  254. package/src/vite/plugins/workerdDevPlugin.ts +398 -0
  255. package/src/vite/replaceLoader.ts +10 -2
  256. package/types/cli/build.d.ts.map +1 -1
  257. package/types/cli/buildPage.d.ts +1 -1
  258. package/types/cli/buildPage.d.ts.map +1 -1
  259. package/types/cli/serverRouteModules.d.ts +2 -0
  260. package/types/cli/serverRouteModules.d.ts.map +1 -0
  261. package/types/cli/workerPool.d.ts +1 -0
  262. package/types/cli/workerPool.d.ts.map +1 -1
  263. package/types/createApp.d.ts.map +1 -1
  264. package/types/createDevHandleRequest.d.ts +10 -0
  265. package/types/createDevHandleRequest.d.ts.map +1 -0
  266. package/types/createHandleRequest.d.ts +2 -9
  267. package/types/createHandleRequest.d.ts.map +1 -1
  268. package/types/headless-server.d.ts +0 -1
  269. package/types/headless-server.d.ts.map +1 -1
  270. package/types/headless.d.ts.map +1 -1
  271. package/types/layouts/Drawer.web.d.ts.map +1 -1
  272. package/types/layouts/Tabs.web.d.ts.map +1 -1
  273. package/types/router/diagnoseRouteLoadFailure.d.ts.map +1 -1
  274. package/types/router/useViteRoutes.d.ts.map +1 -1
  275. package/types/router/web/WebStackView.d.ts.map +1 -1
  276. package/types/serve-worker.d.ts +3 -1
  277. package/types/serve-worker.d.ts.map +1 -1
  278. package/types/server/oneServe.d.ts +1 -1
  279. package/types/server/oneServe.d.ts.map +1 -1
  280. package/types/server/routeExportsFromEntry.d.ts +29 -0
  281. package/types/server/routeExportsFromEntry.d.ts.map +1 -0
  282. package/types/server/workerHandler.d.ts +2 -1
  283. package/types/server/workerHandler.d.ts.map +1 -1
  284. package/types/views/ScrollBehavior.d.ts.map +1 -1
  285. package/types/vite/cloudflareWranglerConfig.d.ts +21 -0
  286. package/types/vite/cloudflareWranglerConfig.d.ts.map +1 -0
  287. package/types/vite/cloudflareWranglerConfig.test.d.ts +2 -0
  288. package/types/vite/cloudflareWranglerConfig.test.d.ts.map +1 -0
  289. package/types/vite/one.d.ts.map +1 -1
  290. package/types/vite/plugins/SSRCSSPlugin.d.ts.map +1 -1
  291. package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
  292. package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
  293. package/types/vite/plugins/workerdDevPlugin.d.ts +15 -0
  294. package/types/vite/plugins/workerdDevPlugin.d.ts.map +1 -0
  295. package/types/vite/plugins/workerdDevPlugin.test.d.ts +2 -0
  296. package/types/vite/plugins/workerdDevPlugin.test.d.ts.map +1 -0
  297. package/types/vite/replaceLoader.d.ts +2 -1
  298. package/types/vite/replaceLoader.d.ts.map +1 -1
  299. package/dist/cjs/headless/devHeadlessNote.cjs +0 -34
  300. package/dist/cjs/headless/devHeadlessNote.native.js +0 -37
  301. package/dist/cjs/headless/devHeadlessNote.native.js.map +0 -1
  302. package/dist/esm/headless/devHeadlessNote.mjs +0 -9
  303. package/dist/esm/headless/devHeadlessNote.mjs.map +0 -1
  304. package/dist/esm/headless/devHeadlessNote.native.js +0 -9
  305. package/dist/esm/headless/devHeadlessNote.native.js.map +0 -1
  306. package/src/headless/devHeadlessNote.ts +0 -13
  307. package/types/headless/devHeadlessNote.d.ts +0 -2
  308. package/types/headless/devHeadlessNote.d.ts.map +0 -1
package/src/cli/build.ts CHANGED
@@ -29,6 +29,13 @@ import { getRouterRootFromOneOptions } from '../utils/getRouterRootFromOneOption
29
29
  import { isRolldown } from '../utils/isRolldown'
30
30
  import { toAbsolute, toAbsoluteUrl } from '../utils/toAbsolute'
31
31
  import { buildVercelOutputDirectory } from '../vercel/build/buildVercelOutputDirectory'
32
+ import {
33
+ createCloudflareWranglerConfig,
34
+ getCloudflareProjectName,
35
+ isPlainObject,
36
+ loadUserWranglerConfig,
37
+ type JsonValue,
38
+ } from '../vite/cloudflareWranglerConfig'
32
39
  import { getManifest } from '../vite/getManifest'
33
40
  import { loadUserOneOptions } from '../vite/loadConfig'
34
41
  import { runWithAsyncLocalContext } from '../vite/one-server-only'
@@ -38,6 +45,7 @@ import { checkNodeVersion } from './checkNodeVersion'
38
45
  import { getWorkerPool, terminateWorkerPool } from './workerPool'
39
46
  import { generateSitemap, type RouteSitemapData } from './generateSitemap'
40
47
  import { labelProcess } from './label-process'
48
+ import { getRouteExports } from './serverRouteModules'
41
49
  import { pLimit } from '../utils/pLimit'
42
50
  import { getCriticalCSSOutputPaths } from '../vite/plugins/criticalCSSPlugin'
43
51
 
@@ -51,191 +59,10 @@ function normalizeDeploy(
51
59
  return deploy
52
60
  }
53
61
 
54
- type JsonPrimitive = string | number | boolean | null
55
- type JsonValue = JsonPrimitive | JsonValue[] | { [key: string]: JsonValue }
56
-
57
- const GENERATED_CLOUDFLARE_WRANGLER_RULES = [
58
- { type: 'ESModule', globs: ['./server/**/*.js'], fallthrough: true },
59
- { type: 'ESModule', globs: ['./api/**/*.js'], fallthrough: true },
60
- { type: 'ESModule', globs: ['./middlewares/**/*.js'], fallthrough: true },
61
- { type: 'ESModule', globs: ['./assets/**/*.js'], fallthrough: true },
62
- ]
63
-
64
62
  const CLOUDFLARE_DEPLOY_WRANGLER_RULES = [
65
63
  { type: 'ESModule', globs: ['assets/**/*.js', 'assets/**/*.mjs'] },
66
64
  ]
67
65
 
68
- function isPlainObject(value: unknown): value is Record<string, JsonValue> {
69
- return !!value && typeof value === 'object' && !Array.isArray(value)
70
- }
71
-
72
- function mergeJsonObjects(
73
- base: Record<string, JsonValue>,
74
- overrides: Record<string, JsonValue>
75
- ): Record<string, JsonValue> {
76
- const merged: Record<string, JsonValue> = { ...base }
77
-
78
- for (const [key, value] of Object.entries(overrides)) {
79
- const baseValue = merged[key]
80
- if (isPlainObject(baseValue) && isPlainObject(value)) {
81
- merged[key] = mergeJsonObjects(baseValue, value)
82
- } else {
83
- merged[key] = value
84
- }
85
- }
86
-
87
- return merged
88
- }
89
-
90
- function dedupeJsonValues<T extends JsonValue>(values: T[]): T[] {
91
- const seen = new Set<string>()
92
- return values.filter((value) => {
93
- const key = JSON.stringify(value)
94
- if (seen.has(key)) return false
95
- seen.add(key)
96
- return true
97
- })
98
- }
99
-
100
- function mergeCloudflareCompatibilityFlags(flags: unknown): string[] {
101
- const userFlags = Array.isArray(flags)
102
- ? flags.filter((flag): flag is string => typeof flag === 'string')
103
- : []
104
-
105
- return dedupeJsonValues<string>(['nodejs_compat', ...userFlags])
106
- }
107
-
108
- function mergeCloudflareRules(rules: unknown): JsonValue[] {
109
- const userRules = Array.isArray(rules)
110
- ? rules.filter((rule): rule is JsonValue => isPlainObject(rule))
111
- : []
112
-
113
- return dedupeJsonValues<JsonValue>([
114
- ...GENERATED_CLOUDFLARE_WRANGLER_RULES,
115
- ...userRules,
116
- ])
117
- }
118
-
119
- // minimal JSONC parser: strips line/block comments (string-aware) and trailing
120
- // commas, then runs JSON.parse. sufficient for small hand-written config files.
121
- function parseJsonc(text: string): unknown {
122
- let out = ''
123
- let i = 0
124
- let inString = false
125
- let quote = ''
126
- while (i < text.length) {
127
- const ch = text[i]
128
- const next = text[i + 1]
129
- if (inString) {
130
- if (ch === '\\') {
131
- out += ch + (next ?? '')
132
- i += 2
133
- continue
134
- }
135
- if (ch === quote) inString = false
136
- out += ch
137
- i++
138
- continue
139
- }
140
- if (ch === '"' || ch === "'") {
141
- inString = true
142
- quote = ch
143
- out += ch
144
- i++
145
- continue
146
- }
147
- if (ch === '/' && next === '/') {
148
- while (i < text.length && text[i] !== '\n') i++
149
- continue
150
- }
151
- if (ch === '/' && next === '*') {
152
- i += 2
153
- while (i < text.length - 1 && !(text[i] === '*' && text[i + 1] === '/')) i++
154
- i += 2
155
- continue
156
- }
157
- out += ch
158
- i++
159
- }
160
- return JSON.parse(out.replace(/,(\s*[}\]])/g, '$1'))
161
- }
162
-
163
- async function loadUserWranglerConfig(
164
- root: string
165
- ): Promise<{ path: string; config: Record<string, JsonValue> } | null> {
166
- const candidateRoots = [...new Set([root, process.cwd()])]
167
-
168
- for (const candidateRoot of candidateRoots) {
169
- for (const fileName of ['wrangler.jsonc', 'wrangler.json']) {
170
- const configPath = join(candidateRoot, fileName)
171
- if (!(await FSExtra.pathExists(configPath))) {
172
- continue
173
- }
174
-
175
- const contents = await FSExtra.readFile(configPath, 'utf-8')
176
- let parsed: unknown
177
- try {
178
- parsed = parseJsonc(contents)
179
- } catch (err) {
180
- throw new Error(
181
- `Failed to parse ${relative(process.cwd(), configPath)}: ${(err as Error).message}`
182
- )
183
- }
184
-
185
- if (!isPlainObject(parsed)) {
186
- throw new Error(
187
- `Expected ${relative(process.cwd(), configPath)} to contain a top-level JSON object`
188
- )
189
- }
190
-
191
- return {
192
- path: configPath,
193
- config: parsed,
194
- }
195
- }
196
- }
197
-
198
- return null
199
- }
200
-
201
- function createCloudflareWranglerConfig(
202
- projectName: string,
203
- userConfig?: Record<string, JsonValue>
204
- ): Record<string, JsonValue> {
205
- const generatedConfig: Record<string, JsonValue> = {
206
- name: projectName,
207
- main: 'worker.js',
208
- compatibility_date: '2024-12-05',
209
- compatibility_flags: ['nodejs_compat'],
210
- find_additional_modules: true,
211
- rules: GENERATED_CLOUDFLARE_WRANGLER_RULES,
212
- assets: {
213
- directory: 'client',
214
- binding: 'ASSETS',
215
- run_worker_first: true,
216
- },
217
- }
218
-
219
- const mergedConfig = userConfig
220
- ? mergeJsonObjects(generatedConfig, userConfig)
221
- : generatedConfig
222
-
223
- mergedConfig.main = 'worker.js'
224
- mergedConfig.find_additional_modules = true
225
- mergedConfig.compatibility_flags = mergeCloudflareCompatibilityFlags(
226
- mergedConfig.compatibility_flags
227
- )
228
- mergedConfig.rules = mergeCloudflareRules(mergedConfig.rules)
229
- mergedConfig.assets = {
230
- ...(isPlainObject(mergedConfig.assets) ? mergedConfig.assets : {}),
231
- directory: 'client',
232
- binding: 'ASSETS',
233
- run_worker_first: true,
234
- }
235
-
236
- return mergedConfig
237
- }
238
-
239
66
  function omitEmptyJsonValues(value: JsonValue): JsonValue | undefined {
240
67
  if (Array.isArray(value)) {
241
68
  const items = value
@@ -276,17 +103,6 @@ async function finalizeCloudflareWranglerDeployConfig(configPath: string) {
276
103
  await FSExtra.writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`)
277
104
  }
278
105
 
279
- // reads package.json name, strips npm scope prefix for use as cloudflare worker name
280
- async function getCloudflareProjectName(root: string): Promise<string> {
281
- try {
282
- const pkg = JSON.parse(await FSExtra.readFile(join(root, 'package.json'), 'utf-8'))
283
- if (pkg.name) {
284
- return pkg.name.replace(/^@[^/]+\//, '')
285
- }
286
- } catch {}
287
- return 'one-app'
288
- }
289
-
290
106
  // ensure worker threads inherit the same CACHE_KEY as the main process
291
107
  process.env.ONE_CACHE_KEY = constants.CACHE_KEY
292
108
 
@@ -722,17 +538,36 @@ export async function build(args: {
722
538
  }
723
539
 
724
540
  // build a direct mapping from source file path to client chunk info
725
- // this is more reliable than manifest.json which can have ambiguous keys
541
+ // this is more reliable than manifest.json which can have ambiguous keys.
542
+ // index every module a chunk contains, not just its facade: a route that
543
+ // another route re-exports from stops being a dynamic entry and lands in a
544
+ // plain shared chunk, which has no facade and so gets no source-path key in
545
+ // the manifest either. the facade pass runs second so it wins where both hit.
726
546
  const clientChunksBySource = new Map<string, { fileName: string; imports: string[] }>()
727
547
  if (vxrnOutput.clientOutput) {
728
548
  for (const chunk of vxrnOutput.clientOutput) {
729
- if (chunk.type === 'chunk' && chunk.facadeModuleId) {
730
- clientChunksBySource.set(chunk.facadeModuleId, {
731
- fileName: chunk.fileName,
732
- imports: chunk.imports || [],
733
- })
549
+ if (chunk.type !== 'chunk') continue
550
+ const info = { fileName: chunk.fileName, imports: chunk.imports || [] }
551
+ for (const moduleId of chunk.moduleIds ?? []) {
552
+ clientChunksBySource.set(moduleId, info)
734
553
  }
735
554
  }
555
+ for (const chunk of vxrnOutput.clientOutput) {
556
+ if (chunk.type !== 'chunk' || !chunk.facadeModuleId) continue
557
+ clientChunksBySource.set(chunk.facadeModuleId, {
558
+ fileName: chunk.fileName,
559
+ imports: chunk.imports || [],
560
+ })
561
+ }
562
+ }
563
+
564
+ // the manifest keys chunks by source path only when they have a facade, so
565
+ // reach the rest through the chunk file name that clientChunksBySource gives us
566
+ const clientManifestByFile = new Map<string, ClientManifestEntry>()
567
+ for (const entry of Object.values(vxrnOutput.clientManifest) as ClientManifestEntry[]) {
568
+ if (entry.file) {
569
+ clientManifestByFile.set(entry.file, entry)
570
+ }
736
571
  }
737
572
 
738
573
  const outputEntries = [...vxrnOutput.serverOutput.entries()]
@@ -828,7 +663,9 @@ export async function build(args: {
828
663
 
829
664
  // also look up in manifest for additional info (css, nested imports, etc)
830
665
  const manifestKey = `${routerRoot}${foundRoute.file.slice(1)}`
831
- const clientManifestEntry = vxrnOutput.clientManifest[manifestKey]
666
+ const clientManifestEntry: ClientManifestEntry | undefined =
667
+ vxrnOutput.clientManifest[manifestKey] ??
668
+ (clientChunk ? clientManifestByFile.get(clientChunk.fileName) : undefined)
832
669
 
833
670
  // SPA and SSG routes may not have client chunks - that's expected
834
671
  if (!clientChunk && foundRoute.type !== 'spa' && foundRoute.type !== 'ssg') {
@@ -853,7 +690,7 @@ export async function build(args: {
853
690
  }
854
691
 
855
692
  function collectImports(
856
- entry: ClientManifestEntry,
693
+ entry: Partial<ClientManifestEntry>,
857
694
  { type = 'js' }: { type?: 'js' | 'css' } = {}
858
695
  ): string[] {
859
696
  const { imports = [], css } = entry
@@ -924,13 +761,9 @@ export async function build(args: {
924
761
  }
925
762
 
926
763
  // add the page itself using the direct chunk lookup (more reliable than manifest)
927
- if (clientChunk) {
928
- const routeKey = `/${routerRoot}${foundRoute.file.slice(1)}`
929
- routePreloads[routeKey] = `/${clientChunk.fileName}`
930
- } else if (clientManifestEntry) {
931
- // fallback to manifest if no chunk (shouldn't happen normally)
932
- const routeKey = `/${routerRoot}${foundRoute.file.slice(1)}`
933
- routePreloads[routeKey] = `/${clientManifestEntry.file}`
764
+ const routeChunkFile = clientChunk?.fileName ?? clientManifestEntry?.file
765
+ if (routeChunkFile) {
766
+ routePreloads[`/${routerRoot}${foundRoute.file.slice(1)}`] = `/${routeChunkFile}`
934
767
  }
935
768
 
936
769
  const preloadSetupFilePreloads = (() => {
@@ -1106,11 +939,15 @@ export async function build(args: {
1106
939
 
1107
940
  let exported
1108
941
  try {
1109
- exported = await import(toAbsoluteUrl(serverJsPath))
942
+ exported = await getRouteExports(
943
+ vxrnOutput.serverEntry,
944
+ routerRoot,
945
+ foundRoute.file
946
+ )
1110
947
  } catch (err) {
1111
948
  console.error(`Error importing page (original error)`, err)
1112
949
  // err cause not showing in vite or something
1113
- throw new Error(`Error importing page: ${serverJsPath}`, {
950
+ throw new Error(`Error importing page: ${foundRoute.file}`, {
1114
951
  cause: err,
1115
952
  })
1116
953
  }
@@ -1180,6 +1017,7 @@ export async function build(args: {
1180
1017
  return workerPool
1181
1018
  .buildPage({
1182
1019
  serverEntry: vxrnOutput.serverEntry,
1020
+ routerRoot,
1183
1021
  path,
1184
1022
  relativeId,
1185
1023
  params,
@@ -1209,6 +1047,7 @@ export async function build(args: {
1209
1047
  const built = await runWithAsyncLocalContext(async () => {
1210
1048
  return await buildPage(
1211
1049
  vxrnOutput.serverEntry,
1050
+ routerRoot,
1212
1051
  path,
1213
1052
  relativeId,
1214
1053
  params,
@@ -1435,21 +1274,9 @@ export async function build(args: {
1435
1274
  )
1436
1275
  return importPath.startsWith('.') ? importPath : `./${importPath}`
1437
1276
  }
1438
- const pageRouteMap: string[] = []
1439
1277
  const apiRouteMap: string[] = []
1440
1278
  const middlewareRouteMap: string[] = []
1441
1279
 
1442
- // Generate lazy imports for SSR/SSG page server bundles
1443
- for (const [routeFile, info] of Object.entries(
1444
- buildInfoForWriting.routeToBuildInfo
1445
- )) {
1446
- if (info.serverJsPath) {
1447
- const importPath =
1448
- './' + info.serverJsPath.replace(new RegExp(`^${outDir}/`), '')
1449
- pageRouteMap.push(` '${routeFile}': () => import('${importPath}')`)
1450
- }
1451
- }
1452
-
1453
1280
  // Generate lazy imports for API routes
1454
1281
  for (const route of buildInfoForWriting.manifest.apiRoutes) {
1455
1282
  if (route.file) {
@@ -1484,9 +1311,6 @@ import { serve, setFetchStaticHtml } from 'one/serve-worker'
1484
1311
  // Lazy import map - modules load on-demand when route is matched
1485
1312
  const lazyRoutes = {
1486
1313
  serverEntry: () => import('./server/_virtual_one-entry.js'),
1487
- pages: {
1488
- ${pageRouteMap.join(',\n')}
1489
- },
1490
1314
  api: {
1491
1315
  ${apiRouteMap.join(',\n')}
1492
1316
  },
@@ -14,6 +14,7 @@ import { isResponse } from '../utils/isResponse'
14
14
  import { toAbsolute, toAbsoluteUrl } from '../utils/toAbsolute'
15
15
  import { replaceLoader } from '../vite/replaceLoader'
16
16
  import type { One, RouteInfo } from '../vite/types'
17
+ import { getRouteExports } from './serverRouteModules'
17
18
 
18
19
  const { readFile, outputFile } = FSExtra
19
20
 
@@ -45,6 +46,7 @@ export function printBuildTimings() {
45
46
 
46
47
  export async function buildPage(
47
48
  serverEntry: string,
49
+ routerRoot: string,
48
50
  path: string,
49
51
  relativeId: string,
50
52
  params: any,
@@ -186,7 +188,7 @@ prefetchCSS()
186
188
  recordTiming('writeCSSPreload', performance.now() - t0)
187
189
 
188
190
  t0 = performance.now()
189
- const exported = await import(toAbsoluteUrl(serverJsPath))
191
+ const exported = await getRouteExports(serverEntry, routerRoot, foundRoute.file)
190
192
  recordTiming('importServerModule', performance.now() - t0)
191
193
 
192
194
  const loaderProps: LoaderProps = { path, params }
@@ -200,14 +202,13 @@ prefetchCSS()
200
202
  const layoutResults = await Promise.all(
201
203
  foundRoute.layouts.map(async (layout) => {
202
204
  try {
203
- const layoutServerPath = layout.loaderServerPath
204
- if (!layoutServerPath) {
205
+ if (!layout.loaderServerPath) {
205
206
  return { contextKey: layout.contextKey, loaderData: undefined }
206
207
  }
207
- // derive server dir from clientDir (e.g. dist/client -> dist/server)
208
- const serverDir = join(clientDir, '..', 'server')
209
- const layoutExported = await import(
210
- toAbsoluteUrl(join(serverDir, layoutServerPath))
208
+ const layoutExported = await getRouteExports(
209
+ serverEntry,
210
+ routerRoot,
211
+ layout.contextKey
211
212
  )
212
213
  const layoutLoaderData = await layoutExported?.loader?.(loaderProps)
213
214
  return { contextKey: layout.contextKey, loaderData: layoutLoaderData }
@@ -301,6 +302,7 @@ if (typeof document === 'undefined') globalThis.document = {}
301
302
  replaceLoader({
302
303
  code,
303
304
  loaderData,
305
+ routeId: foundRoute.file,
304
306
  })
305
307
  await outputFile(loaderPartialPath, withLoader)
306
308
  // native-friendly CJS version with just the data (no ESM imports)
@@ -68,6 +68,7 @@ parentPort.on('message', async (msg: any) => {
68
68
  const result = await runWithAsyncLocalContext(async () => {
69
69
  return await buildPage(
70
70
  msg.args.serverEntry,
71
+ msg.args.routerRoot,
71
72
  msg.args.path,
72
73
  msg.args.relativeId,
73
74
  msg.args.params,
@@ -0,0 +1,33 @@
1
+ import { getRouteExportsFromEntry } from '../server/routeExportsFromEntry'
2
+ import { toAbsoluteUrl } from '../utils/toAbsolute'
3
+
4
+ // entry evaluation is expensive and every page in a build shares it
5
+ const serverEntries = new Map<string, Promise<any>>()
6
+
7
+ function loadServerEntry(serverEntry: string) {
8
+ let loading = serverEntries.get(serverEntry)
9
+ if (!loading) {
10
+ loading = import(toAbsoluteUrl(serverEntry))
11
+ serverEntries.set(serverEntry, loading)
12
+ }
13
+ return loading
14
+ }
15
+
16
+ export async function getRouteExports(
17
+ serverEntry: string,
18
+ routerRoot: string,
19
+ routeFile: string
20
+ ): Promise<Record<string, any>> {
21
+ const entry = await loadServerEntry(serverEntry)
22
+ const exported = await getRouteExportsFromEntry(entry, routerRoot, routeFile)
23
+
24
+ if (!exported) {
25
+ const routes =
26
+ entry?.default?.options?.routes ?? entry?.default?.default?.options?.routes
27
+ throw new Error(
28
+ `[one] route ${routeFile} is missing from the built server entry route map (looked in: ${Object.keys(routes ?? {}).join(', ')})`
29
+ )
30
+ }
31
+
32
+ return exported
33
+ }
@@ -105,6 +105,7 @@ export class BuildWorkerPool {
105
105
 
106
106
  async buildPage(args: {
107
107
  serverEntry: string
108
+ routerRoot: string
108
109
  path: string
109
110
  relativeId: string
110
111
  params: any
package/src/createApp.tsx CHANGED
@@ -7,7 +7,7 @@ import { render } from './render'
7
7
  import { initClientMatches } from './router/router'
8
8
  import { registerPreloadedRoute } from './router/useViteRoutes'
9
9
  import { setupSkewProtection } from './skewProtection'
10
- import { handleSkewError } from './utils/dynamicImport'
10
+ import { handleSkewError, isChunkLoadError } from './utils/dynamicImport'
11
11
  import { findRootLayout } from './utils/findRootLayout'
12
12
  import type { RenderAppProps } from './types'
13
13
  import type { OneLinkingConfig } from './link/getLinking'
@@ -293,5 +293,9 @@ export function createApp(options: CreateAppProps) {
293
293
  })
294
294
  .catch((err) => {
295
295
  console.error(`Error during client initialization:`, err)
296
+ if (isChunkLoadError(err)) {
297
+ handleSkewError()
298
+ }
296
299
  })
297
300
  }
301
+
@@ -0,0 +1,186 @@
1
+ import { LOADER_JS_POSTFIX_UNCACHED } from './constants'
2
+ import {
3
+ compileManifest,
4
+ getURLfromRequestURL,
5
+ isPageRequestMethod,
6
+ isStaticAssetRequestPath,
7
+ resolveAPIRoute,
8
+ resolveLoaderRoute,
9
+ resolvePageRoute,
10
+ runMiddlewares,
11
+ type RequestHandlerResponse,
12
+ type RequestHandlers,
13
+ } from './createHandleRequest'
14
+ import { getPathFromLoaderPath } from './utils/cleanUrl'
15
+ import { getManifest } from './vite/getManifest'
16
+
17
+ const debugRouter = process.env.ONE_DEBUG_ROUTER
18
+
19
+ // node-dev request handler. kept out of createHandleRequest.ts so the worker
20
+ // graph (one/serve-worker) does not pull getManifest -> micromatch/fast-glob.
21
+ export function createHandleRequest(
22
+ handlers: RequestHandlers,
23
+ {
24
+ routerRoot,
25
+ ignoredRouteFiles,
26
+ routePaths,
27
+ }: { routerRoot: string; ignoredRouteFiles?: string[]; routePaths?: string[] }
28
+ ) {
29
+ const manifest = getManifest({ routerRoot, ignoredRouteFiles, routePaths })
30
+ if (!manifest) {
31
+ throw new Error(`No routes manifest`)
32
+ }
33
+ const compiledManifest = compileManifest(manifest)
34
+
35
+ return {
36
+ manifest,
37
+ handler: async function handleRequest(
38
+ request: Request
39
+ ): Promise<RequestHandlerResponse> {
40
+ const url = getURLfromRequestURL(request)
41
+ const { pathname } = url
42
+
43
+ // skip paths handled by vite internals or react native dev middleware
44
+ if (
45
+ pathname === '/__vxrnhmr' ||
46
+ pathname.startsWith('/@vite/') ||
47
+ pathname.startsWith('/@fs/') ||
48
+ pathname.startsWith('/@id/') ||
49
+ pathname.startsWith('/node_modules/') ||
50
+ pathname.startsWith('/debugger-frontend') ||
51
+ pathname.startsWith('/inspector')
52
+ ) {
53
+ return null
54
+ }
55
+
56
+ const looksLikeStaticFile = isStaticAssetRequestPath(pathname)
57
+
58
+ if (handlers.handleAPI) {
59
+ const apiRoute = compiledManifest.apiRoutes.find((route) => {
60
+ return route.compiledRegex.test(pathname)
61
+ })
62
+ if (apiRoute) {
63
+ if (debugRouter) {
64
+ console.info(`[one] ⚡ ${pathname} → matched API route: ${apiRoute.page}`)
65
+ }
66
+ return await resolveAPIRoute(handlers, request, url, apiRoute)
67
+ }
68
+ }
69
+
70
+ if (!isPageRequestMethod(request.method)) {
71
+ return null
72
+ }
73
+
74
+ if (handlers.handleLoader) {
75
+ const isClientRequestingNewRoute = pathname.endsWith(LOADER_JS_POSTFIX_UNCACHED)
76
+
77
+ if (isClientRequestingNewRoute) {
78
+ const platformParam = url.searchParams.get('platform')
79
+ const isNativePlatform =
80
+ platformParam === 'ios' ||
81
+ platformParam === 'android' ||
82
+ platformParam === 'native'
83
+
84
+ // for native requests, try serving the pre-built .native.js static file first
85
+ // (SSG/SPA routes generate standalone CJS loaders at build time)
86
+ if (isNativePlatform && handlers.handleStaticFile) {
87
+ const nativeLoaderPath = pathname.replace(/\.js$/, '.native.js')
88
+ const staticResponse = await handlers.handleStaticFile(nativeLoaderPath)
89
+ if (staticResponse) {
90
+ return staticResponse
91
+ }
92
+ }
93
+
94
+ const originalUrl = getPathFromLoaderPath(pathname)
95
+
96
+ for (const route of compiledManifest.pageRoutes) {
97
+ if (route.file === '') {
98
+ // ignore not found route
99
+ continue
100
+ }
101
+
102
+ const finalUrl = new URL(originalUrl, url.origin)
103
+ finalUrl.search = url.search
104
+
105
+ if (!route.compiledRegex.test(finalUrl.pathname)) {
106
+ continue
107
+ }
108
+
109
+ // route is known to export no loader → return empty module without
110
+ // importing the page bundle. on workerd/cloudflare, evaluating a
111
+ // no-loader SSG page's server bundle can crash when it pulls in
112
+ // RN/Tamagui modules that aren't compatible with the workers runtime.
113
+ if (route.hasLoader === false) {
114
+ const emptyBody = isNativePlatform
115
+ ? 'exports.loader=function(){return undefined}'
116
+ : 'export function loader() { return undefined }'
117
+ return new Response(emptyBody, {
118
+ headers: { 'Content-Type': 'text/javascript' },
119
+ })
120
+ }
121
+
122
+ const cleanedRequest = new Request(finalUrl, request)
123
+ return resolveLoaderRoute(handlers, cleanedRequest, finalUrl, route)
124
+ }
125
+
126
+ // no matching route - return empty module so client handles gracefully
127
+ const emptyBody = isNativePlatform
128
+ ? 'exports.loader=function(){return{}}'
129
+ : 'export {}'
130
+ return new Response(emptyBody, {
131
+ headers: { 'Content-Type': 'text/javascript' },
132
+ })
133
+ }
134
+ }
135
+
136
+ if (handlers.handlePage) {
137
+ for (const route of compiledManifest.pageRoutes) {
138
+ if (!route.compiledRegex.test(pathname)) {
139
+ continue
140
+ }
141
+
142
+ // static asset requests (sourcemaps, favicons, fonts, …) should not
143
+ // SSR the user's +not-found page or hijack a dynamic route. for
144
+ // +not-found we still run middleware so it can intercept, then
145
+ // short-circuit to a bare 404 instead of rendering the page tree.
146
+ const isDynamicRoute = Object.keys(route.routeKeys).length > 0
147
+ const isNotFoundRoute = route.page.endsWith('/+not-found')
148
+ if (looksLikeStaticFile && isNotFoundRoute) {
149
+ if (debugRouter) {
150
+ console.info(
151
+ `[one] ⚡ ${pathname} → bare 404 for static probe on ${route.page}`
152
+ )
153
+ }
154
+ if (!route.middlewares?.length) {
155
+ return null
156
+ }
157
+ return await runMiddlewares(handlers, request, route, async () => {
158
+ return new Response(null, {
159
+ status: 404,
160
+ headers: { 'Content-Type': 'text/plain' },
161
+ })
162
+ })
163
+ }
164
+ if (looksLikeStaticFile && isDynamicRoute) {
165
+ if (debugRouter) {
166
+ console.info(
167
+ `[one] ⚡ ${pathname} → skipping dynamic route ${route.page} for static asset`
168
+ )
169
+ }
170
+ continue
171
+ }
172
+
173
+ if (debugRouter) {
174
+ console.info(
175
+ `[one] ⚡ ${pathname} → matched page route: ${route.page} (${route.type})`
176
+ )
177
+ }
178
+
179
+ return resolvePageRoute(handlers, request, url, route)
180
+ }
181
+ }
182
+
183
+ return null
184
+ },
185
+ }
186
+ }
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it, vi, beforeEach } from 'vitest'
2
- import { createHandleRequest } from './createHandleRequest'
2
+ import { createHandleRequest } from './createDevHandleRequest'
3
3
 
4
4
  // Mock the manifest. Specific routes come before dynamic ones, matching how
5
5
  // the real manifest is ordered after matchers.sortRoutes().