one 1.17.9 → 1.17.10

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 (557) hide show
  1. package/dist/cjs/Root.native.js.map +1 -1
  2. package/dist/cjs/__mocks__/@react-navigation/native-stack.native.js.map +1 -1
  3. package/dist/cjs/__mocks__/expo-linking.native.js.map +1 -1
  4. package/dist/cjs/__mocks__/expo-modules-core.native.js.map +1 -1
  5. package/dist/cjs/__mocks__/react-native-screens.native.js.map +1 -1
  6. package/dist/cjs/babel-plugins/environment-guard.native.js.map +1 -1
  7. package/dist/cjs/babel-plugins/inline-one-server-url.native.js.map +1 -1
  8. package/dist/cjs/babel-plugins/one-router-metro.native.js.map +1 -1
  9. package/dist/cjs/babel-plugins/one-router-metro.test.native.js.map +1 -1
  10. package/dist/cjs/babel-plugins/remove-server-code.native.js.map +1 -1
  11. package/dist/cjs/babel-preset/index.cjs +7 -2
  12. package/dist/cjs/babel-preset/index.native.js +7 -2
  13. package/dist/cjs/babel-preset/index.native.js.map +1 -1
  14. package/dist/cjs/babel-preset/index.test.cjs +13 -0
  15. package/dist/cjs/babel-preset/index.test.native.js +13 -0
  16. package/dist/cjs/babel-preset/index.test.native.js.map +1 -1
  17. package/dist/cjs/babel-preset/integration.test.native.js.map +1 -1
  18. package/dist/cjs/cli/build.cjs +14 -11
  19. package/dist/cjs/cli/build.native.js +14 -11
  20. package/dist/cjs/cli/build.native.js.map +1 -1
  21. package/dist/cjs/cli/buildPage.cjs +2 -1
  22. package/dist/cjs/cli/buildPage.native.js +2 -1
  23. package/dist/cjs/cli/buildPage.native.js.map +1 -1
  24. package/dist/cjs/cli/buildPageWorker.native.js.map +1 -1
  25. package/dist/cjs/cli/checkNodeVersion.native.js.map +1 -1
  26. package/dist/cjs/cli/daemon.native.js.map +1 -1
  27. package/dist/cjs/cli/dev.native.js.map +1 -1
  28. package/dist/cjs/cli/generateBundlerConfig.native.js.map +1 -1
  29. package/dist/cjs/cli/generateBundlerConfig.test.native.js.map +1 -1
  30. package/dist/cjs/cli/generateRoutes.native.js.map +1 -1
  31. package/dist/cjs/cli/generateSitemap.native.js.map +1 -1
  32. package/dist/cjs/cli/generateSitemap.test.native.js.map +1 -1
  33. package/dist/cjs/cli/install-error-handlers.native.js.map +1 -1
  34. package/dist/cjs/cli/label-process.native.js.map +1 -1
  35. package/dist/cjs/cli/main.native.js.map +1 -1
  36. package/dist/cjs/cli/patch.native.js.map +1 -1
  37. package/dist/cjs/cli/patch.test.native.js.map +1 -1
  38. package/dist/cjs/cli/prebuild.native.js.map +1 -1
  39. package/dist/cjs/cli/runAndroid.native.js.map +1 -1
  40. package/dist/cjs/cli/runIos.native.js.map +1 -1
  41. package/dist/cjs/cli/securityScan.native.js.map +1 -1
  42. package/dist/cjs/cli/workerPool.native.js.map +1 -1
  43. package/dist/cjs/cli.native.js.map +1 -1
  44. package/dist/cjs/clientLoaderResolver.native.js.map +1 -1
  45. package/dist/cjs/config.native.js.map +1 -1
  46. package/dist/cjs/constants.cjs +17 -5
  47. package/dist/cjs/constants.native.js +13 -1
  48. package/dist/cjs/constants.native.js.map +1 -1
  49. package/dist/cjs/constants.test.cjs +60 -0
  50. package/dist/cjs/constants.test.native.js +63 -0
  51. package/dist/cjs/constants.test.native.js.map +1 -0
  52. package/dist/cjs/createAPIRoute.native.js.map +1 -1
  53. package/dist/cjs/createApp.cjs +3 -2
  54. package/dist/cjs/createHandleRequest.native.js.map +1 -1
  55. package/dist/cjs/createHandleRequest.test.native.js.map +1 -1
  56. package/dist/cjs/createMiddleware.native.js.map +1 -1
  57. package/dist/cjs/daemon/index.native.js.map +1 -1
  58. package/dist/cjs/daemon/ipc.native.js.map +1 -1
  59. package/dist/cjs/daemon/picker.native.js.map +1 -1
  60. package/dist/cjs/daemon/proxy.native.js.map +1 -1
  61. package/dist/cjs/daemon/registry.native.js.map +1 -1
  62. package/dist/cjs/daemon/server.cjs +23 -0
  63. package/dist/cjs/daemon/server.native.js +61 -0
  64. package/dist/cjs/daemon/server.native.js.map +1 -1
  65. package/dist/cjs/daemon/tui.native.js.map +1 -1
  66. package/dist/cjs/daemon/types.native.js.map +1 -1
  67. package/dist/cjs/daemon/utils.native.js.map +1 -1
  68. package/dist/cjs/devtools/registry.native.js.map +1 -1
  69. package/dist/cjs/drawer.native.js.map +1 -1
  70. package/dist/cjs/fallbackViews/Sitemap.native.js.map +1 -1
  71. package/dist/cjs/fallbackViews/Unmatched.native.js.map +1 -1
  72. package/dist/cjs/fork/NavigationContainer.native.js.map +1 -1
  73. package/dist/cjs/fork/SSRNavigationContainer.native.js.map +1 -1
  74. package/dist/cjs/fork/__tests__/getPathFromState.test.native.js.map +1 -1
  75. package/dist/cjs/fork/__tests__/getStateFromPath.test.native.js.map +1 -1
  76. package/dist/cjs/fork/_shared.native.js.map +1 -1
  77. package/dist/cjs/fork/createMemoryHistory.native.js.map +1 -1
  78. package/dist/cjs/fork/createMemoryHistory.test.native.js.map +1 -1
  79. package/dist/cjs/fork/extractPathFromURL.native.js.map +1 -1
  80. package/dist/cjs/fork/extractPathFromURL.test.native.js.map +1 -1
  81. package/dist/cjs/fork/findFocusedRoute.native.js.map +1 -1
  82. package/dist/cjs/fork/getPathFromState-mods.native.js.map +1 -1
  83. package/dist/cjs/fork/getPathFromState.native.js.map +1 -1
  84. package/dist/cjs/fork/getPathFromState.test.native.js.map +1 -1
  85. package/dist/cjs/fork/getStateFromPath-mods.native.js.map +1 -1
  86. package/dist/cjs/fork/getStateFromPath.native.js.map +1 -1
  87. package/dist/cjs/fork/getStateFromPath.test.native.js.map +1 -1
  88. package/dist/cjs/fork/useThenable.native.js.map +1 -1
  89. package/dist/cjs/fork/validatePathConfig.native.js.map +1 -1
  90. package/dist/cjs/getReactNavigationConfig.native.js.map +1 -1
  91. package/dist/cjs/head/Head.native.js.map +1 -1
  92. package/dist/cjs/head/HeadModule.native.js.map +1 -1
  93. package/dist/cjs/head/index.native.js.map +1 -1
  94. package/dist/cjs/head/types.native.js.map +1 -1
  95. package/dist/cjs/head/url.native.js.map +1 -1
  96. package/dist/cjs/headless-server.native.js.map +1 -1
  97. package/dist/cjs/headless.native.js.map +1 -1
  98. package/dist/cjs/hooks.native.js.map +1 -1
  99. package/dist/cjs/hooks.test.native.js.map +1 -1
  100. package/dist/cjs/href.native.js.map +1 -1
  101. package/dist/cjs/image/getImageData.native.js.map +1 -1
  102. package/dist/cjs/image.native.js.map +1 -1
  103. package/dist/cjs/index.cjs +6 -0
  104. package/dist/cjs/index.native.js +7 -1
  105. package/dist/cjs/index.native.js.map +1 -1
  106. package/dist/cjs/interfaces/router.native.js.map +1 -1
  107. package/dist/cjs/layouts/Drawer.native.js.map +1 -1
  108. package/dist/cjs/layouts/NativeTabs.native.js.map +1 -1
  109. package/dist/cjs/layouts/Stack.native.js +1 -1
  110. package/dist/cjs/layouts/Stack.native.js.map +1 -1
  111. package/dist/cjs/layouts/Tabs.native.js.map +1 -1
  112. package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.native.js.map +1 -1
  113. package/dist/cjs/layouts/stack-utils/StackHeaderComponent.native.js.map +1 -1
  114. package/dist/cjs/layouts/stack-utils/StackHeaderLeft.native.js.map +1 -1
  115. package/dist/cjs/layouts/stack-utils/StackHeaderRight.native.js.map +1 -1
  116. package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.native.js.map +1 -1
  117. package/dist/cjs/layouts/stack-utils/StackHeaderTitle.native.js.map +1 -1
  118. package/dist/cjs/layouts/stack-utils/StackScreen.native.js.map +1 -1
  119. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js.map +1 -1
  120. package/dist/cjs/layouts/stack-utils/index.native.js.map +1 -1
  121. package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
  122. package/dist/cjs/lazyWithRetry.cjs +32 -0
  123. package/dist/cjs/lazyWithRetry.native.js +37 -0
  124. package/dist/cjs/lazyWithRetry.native.js.map +1 -0
  125. package/dist/cjs/link/Link.native.js.map +1 -1
  126. package/dist/cjs/link/Redirect.native.js.map +1 -1
  127. package/dist/cjs/link/getLinking.native.js.map +1 -1
  128. package/dist/cjs/link/href.native.js.map +1 -1
  129. package/dist/cjs/link/path.native.js.map +1 -1
  130. package/dist/cjs/link/prefetchIntent.native.js.map +1 -1
  131. package/dist/cjs/link/prefetchIntent.test.native.js.map +1 -1
  132. package/dist/cjs/link/prefetchViewport.native.js.map +1 -1
  133. package/dist/cjs/link/prefetchViewport.test.native.js.map +1 -1
  134. package/dist/cjs/link/useLinkTo.native.js.map +1 -1
  135. package/dist/cjs/link/useLoadedNavigation.native.js.map +1 -1
  136. package/dist/cjs/metro-config/buildOneMetroResolverOverrides.native.js.map +1 -1
  137. package/dist/cjs/metro-config/getViteMetroPluginOptions.integration.test.native.js.map +1 -1
  138. package/dist/cjs/metro-config/getViteMetroPluginOptions.native.js +1 -1
  139. package/dist/cjs/metro-config/getViteMetroPluginOptions.native.js.map +1 -1
  140. package/dist/cjs/metro-config/withOne.native.js.map +1 -1
  141. package/dist/cjs/metro-config/withOne.test.native.js.map +1 -1
  142. package/dist/cjs/native-tabs.native.js.map +1 -1
  143. package/dist/cjs/notFoundState.native.js.map +1 -1
  144. package/dist/cjs/polyfills-mobile.native.js.map +1 -1
  145. package/dist/cjs/polyfills-server.native.js.map +1 -1
  146. package/dist/cjs/router/FlagsContext.native.js.map +1 -1
  147. package/dist/cjs/router/Route.native.js.map +1 -1
  148. package/dist/cjs/router/RouteInfoContext.native.js.map +1 -1
  149. package/dist/cjs/router/RouterStore.native.js.map +1 -1
  150. package/dist/cjs/router/SpaShellContext.native.js.map +1 -1
  151. package/dist/cjs/router/createRoute.native.js.map +1 -1
  152. package/dist/cjs/router/filterRootHTML.native.js.map +1 -1
  153. package/dist/cjs/router/findRouteNode.native.js.map +1 -1
  154. package/dist/cjs/router/getLinkingConfig.native.js.map +1 -1
  155. package/dist/cjs/router/getLinkingConfig.test.native.js.map +1 -1
  156. package/dist/cjs/router/getNormalizedStatePath.native.js.map +1 -1
  157. package/dist/cjs/router/getRouteInfo.native.js.map +1 -1
  158. package/dist/cjs/router/getRoutes.native.js.map +1 -1
  159. package/dist/cjs/router/getRoutes.test.native.js.map +1 -1
  160. package/dist/cjs/router/glob-patterns.native.js.map +1 -1
  161. package/dist/cjs/router/imperative-api.native.js.map +1 -1
  162. package/dist/cjs/router/interceptRoutes.native.js.map +1 -1
  163. package/dist/cjs/router/isIndexPath.native.js.map +1 -1
  164. package/dist/cjs/router/lastAction.native.js.map +1 -1
  165. package/dist/cjs/router/linkingConfig.native.js.map +1 -1
  166. package/dist/cjs/router/matchers.native.js.map +1 -1
  167. package/dist/cjs/router/matchers.test.native.js.map +1 -1
  168. package/dist/cjs/router/params.native.js.map +1 -1
  169. package/dist/cjs/router/router.cjs +22 -7
  170. package/dist/cjs/router/router.native.js.map +1 -1
  171. package/dist/cjs/router/serverLocationContext.native.js.map +1 -1
  172. package/dist/cjs/router/sitemap.native.js.map +1 -1
  173. package/dist/cjs/router/sitemap.test.native.js.map +1 -1
  174. package/dist/cjs/router/sortRoutes.native.js.map +1 -1
  175. package/dist/cjs/router/useInitializeOneRouter.native.js.map +1 -1
  176. package/dist/cjs/router/useNavigation.native.js.map +1 -1
  177. package/dist/cjs/router/useScreens.cjs +17 -2
  178. package/dist/cjs/router/useScreens.native.js +24 -4
  179. package/dist/cjs/router/useScreens.native.js.map +1 -1
  180. package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
  181. package/dist/cjs/router/utils/getNavigateAction.native.js.map +1 -1
  182. package/dist/cjs/router/utils/getNavigateAction.test.native.js.map +1 -1
  183. package/dist/cjs/screensFeatureFlags.native.js.map +1 -1
  184. package/dist/cjs/serve-worker.native.js.map +1 -1
  185. package/dist/cjs/serve.cjs +2 -1
  186. package/dist/cjs/serve.native.js +2 -1
  187. package/dist/cjs/serve.native.js.map +1 -1
  188. package/dist/cjs/server/ServerContextScript.cjs +4 -3
  189. package/dist/cjs/server/ServerContextScript.native.js +6 -4
  190. package/dist/cjs/server/ServerContextScript.native.js.map +1 -1
  191. package/dist/cjs/server/createRoutesManifest.native.js.map +1 -1
  192. package/dist/cjs/server/getServerManifest.native.js.map +1 -1
  193. package/dist/cjs/server/getServerManifest.test.native.js.map +1 -1
  194. package/dist/cjs/server/oneServe.cjs +21 -8
  195. package/dist/cjs/server/oneServe.native.js +21 -8
  196. package/dist/cjs/server/oneServe.native.js.map +1 -1
  197. package/dist/cjs/server/setServerGlobals.native.js.map +1 -1
  198. package/dist/cjs/server/setupBuildOptions.cjs +6 -1
  199. package/dist/cjs/server/setupBuildOptions.native.js +10 -4
  200. package/dist/cjs/server/setupBuildOptions.native.js.map +1 -1
  201. package/dist/cjs/server/setupServerGlobals.native.js.map +1 -1
  202. package/dist/cjs/server/ssrLoaderData.native.js.map +1 -1
  203. package/dist/cjs/server/staticHtmlFetcher.native.js.map +1 -1
  204. package/dist/cjs/server/workerHandler.cjs +2 -2
  205. package/dist/cjs/server/workerHandler.native.js +2 -2
  206. package/dist/cjs/server/workerHandler.native.js.map +1 -1
  207. package/dist/cjs/server-render.native.js.map +1 -1
  208. package/dist/cjs/skewProtection.native.js.map +1 -1
  209. package/dist/cjs/testing-utils.native.js.map +1 -1
  210. package/dist/cjs/typed-routes/generateRouteTypes.native.js.map +1 -1
  211. package/dist/cjs/typed-routes/generateRouteTypes.test.native.js.map +1 -1
  212. package/dist/cjs/typed-routes/getTypedRoutesDeclarationFile.native.js.map +1 -1
  213. package/dist/cjs/typed-routes/getTypedRoutesDeclarationFile.test.native.js.map +1 -1
  214. package/dist/cjs/typed-routes/injectRouteHelpers.native.js.map +1 -1
  215. package/dist/cjs/types.native.js.map +1 -1
  216. package/dist/cjs/ui/Slot.native.js.map +1 -1
  217. package/dist/cjs/ui/TabContext.native.js.map +1 -1
  218. package/dist/cjs/ui/TabList.native.js.map +1 -1
  219. package/dist/cjs/ui/TabRouter.native.js.map +1 -1
  220. package/dist/cjs/ui/TabSlot.native.js.map +1 -1
  221. package/dist/cjs/ui/TabTrigger.native.js.map +1 -1
  222. package/dist/cjs/ui/Tabs.native.js.map +1 -1
  223. package/dist/cjs/ui/common.native.js.map +1 -1
  224. package/dist/cjs/ui/index.native.js.map +1 -1
  225. package/dist/cjs/ui/useComponent.native.js.map +1 -1
  226. package/dist/cjs/useFocusEffect.native.js.map +1 -1
  227. package/dist/cjs/useLoader.cjs +30 -7
  228. package/dist/cjs/useLoader.native.js +30 -7
  229. package/dist/cjs/useLoader.native.js.map +1 -1
  230. package/dist/cjs/useMatches.native.js.map +1 -1
  231. package/dist/cjs/useMatches.test.native.js.map +1 -1
  232. package/dist/cjs/useServerHeadInsertion.native.js.map +1 -1
  233. package/dist/cjs/utils/assertIsReady.native.js.map +1 -1
  234. package/dist/cjs/utils/buildOutputPointer.cjs +81 -0
  235. package/dist/cjs/utils/buildOutputPointer.native.js +92 -0
  236. package/dist/cjs/utils/buildOutputPointer.native.js.map +1 -0
  237. package/dist/cjs/utils/buildOutputPointer.test.cjs +94 -0
  238. package/dist/cjs/utils/buildOutputPointer.test.native.js +97 -0
  239. package/dist/cjs/utils/buildOutputPointer.test.native.js.map +1 -0
  240. package/dist/cjs/utils/children.native.js.map +1 -1
  241. package/dist/cjs/utils/cleanUrl.native.js.map +1 -1
  242. package/dist/cjs/utils/cleanUrl.test.native.js.map +1 -1
  243. package/dist/cjs/utils/dynamicImport.cjs +32 -6
  244. package/dist/cjs/utils/dynamicImport.native.js +35 -2
  245. package/dist/cjs/utils/dynamicImport.native.js.map +1 -1
  246. package/dist/cjs/utils/dynamicImport.test.cjs +87 -0
  247. package/dist/cjs/utils/dynamicImport.test.native.js +108 -0
  248. package/dist/cjs/utils/dynamicImport.test.native.js.map +1 -0
  249. package/dist/cjs/utils/ensureExists.native.js.map +1 -1
  250. package/dist/cjs/utils/evictOldest.native.js.map +1 -1
  251. package/dist/cjs/utils/existsAsync.native.js.map +1 -1
  252. package/dist/cjs/utils/findRootLayout.native.js.map +1 -1
  253. package/dist/cjs/utils/getPageExport.native.js.map +1 -1
  254. package/dist/cjs/utils/getPathnameFromFilePath.native.js.map +1 -1
  255. package/dist/cjs/utils/getPathnameFromFilePath.test.native.js.map +1 -1
  256. package/dist/cjs/utils/getRouterRootFromOneOptions.native.js.map +1 -1
  257. package/dist/cjs/utils/globDir.native.js.map +1 -1
  258. package/dist/cjs/utils/hashString.native.js.map +1 -1
  259. package/dist/cjs/utils/htmlEscape.native.js.map +1 -1
  260. package/dist/cjs/utils/isResponse.native.js.map +1 -1
  261. package/dist/cjs/utils/isRolldown.native.js.map +1 -1
  262. package/dist/cjs/utils/isStatus.native.js.map +1 -1
  263. package/dist/cjs/utils/pLimit.native.js.map +1 -1
  264. package/dist/cjs/utils/posixPathContract.test.cjs +66 -0
  265. package/dist/cjs/utils/posixPathContract.test.native.js +89 -0
  266. package/dist/cjs/utils/posixPathContract.test.native.js.map +1 -0
  267. package/dist/cjs/utils/promiseWithResolvers.native.js.map +1 -1
  268. package/dist/cjs/utils/rand.native.js.map +1 -1
  269. package/dist/cjs/utils/redirect.native.js.map +1 -1
  270. package/dist/cjs/utils/removeParams.native.js.map +1 -1
  271. package/dist/cjs/utils/removeSearch.native.js.map +1 -1
  272. package/dist/cjs/utils/removeUndefined.native.js.map +1 -1
  273. package/dist/cjs/utils/routeFileWatch.native.js.map +1 -1
  274. package/dist/cjs/utils/routeFileWatch.test.native.js.map +1 -1
  275. package/dist/cjs/utils/style.native.js.map +1 -1
  276. package/dist/cjs/utils/toAbsolute.native.js.map +1 -1
  277. package/dist/cjs/utils/toServerOutputPath.cjs +36 -0
  278. package/dist/cjs/utils/toServerOutputPath.native.js +39 -0
  279. package/dist/cjs/utils/toServerOutputPath.native.js.map +1 -0
  280. package/dist/cjs/utils/toServerOutputPath.test.cjs +27 -0
  281. package/dist/cjs/utils/toServerOutputPath.test.native.js +30 -0
  282. package/dist/cjs/utils/toServerOutputPath.test.native.js.map +1 -0
  283. package/dist/cjs/utils/trackLoaderDependencies.native.js.map +1 -1
  284. package/dist/cjs/utils/url.native.js.map +1 -1
  285. package/dist/cjs/utils/useConstant.native.js.map +1 -1
  286. package/dist/cjs/utils/watchFile.native.js.map +1 -1
  287. package/dist/cjs/utils/weakKey.native.js.map +1 -1
  288. package/dist/cjs/utils/weakMemo.native.js.map +1 -1
  289. package/dist/cjs/utils/withStaticProperties.native.js.map +1 -1
  290. package/dist/cjs/utils/workerImport.native.js.map +1 -1
  291. package/dist/cjs/validateParams.native.js.map +1 -1
  292. package/dist/cjs/validateSearch.native.js.map +1 -1
  293. package/dist/cjs/vercel/build/buildVercelOutputDirectory.native.js.map +1 -1
  294. package/dist/cjs/vercel/build/config/vc-build-output-config-base.native.js.map +1 -1
  295. package/dist/cjs/vercel/build/config/vc-config-base.native.js.map +1 -1
  296. package/dist/cjs/vercel/build/config/vc-package-base.native.js.map +1 -1
  297. package/dist/cjs/vercel/build/generate/createApiServerlessFunction.native.js.map +1 -1
  298. package/dist/cjs/vercel/build/generate/createSsrServerlessFunction.native.js.map +1 -1
  299. package/dist/cjs/vercel/build/getPathFromRoute.native.js.map +1 -1
  300. package/dist/cjs/views/EmptyRoute.native.js.map +1 -1
  301. package/dist/cjs/views/ErrorBoundary.native.js.map +1 -1
  302. package/dist/cjs/views/LoadProgressBar.native.js.map +1 -1
  303. package/dist/cjs/views/Navigator.native.js.map +1 -1
  304. package/dist/cjs/views/OneStackRouter.native.js.map +1 -1
  305. package/dist/cjs/views/Protected.native.js.map +1 -1
  306. package/dist/cjs/views/RootErrorBoundary.native.js.map +1 -1
  307. package/dist/cjs/views/Screen.native.js.map +1 -1
  308. package/dist/cjs/views/ScrollBehavior.native.js.map +1 -1
  309. package/dist/cjs/views/SourceInspector.native.js.map +1 -1
  310. package/dist/cjs/views/Try.native.js.map +1 -1
  311. package/dist/cjs/vite/DevHead.native.js.map +1 -1
  312. package/dist/cjs/vite/constants.native.js.map +1 -1
  313. package/dist/cjs/vite/customNodeExternals.native.js.map +1 -1
  314. package/dist/cjs/vite/ensureTsConfig.native.js.map +1 -1
  315. package/dist/cjs/vite/findDepsToOptimize.native.js.map +1 -1
  316. package/dist/cjs/vite/getManifest.native.js.map +1 -1
  317. package/dist/cjs/vite/getManifest.test.cjs +46 -0
  318. package/dist/cjs/vite/getManifest.test.native.js +52 -0
  319. package/dist/cjs/vite/getManifest.test.native.js.map +1 -0
  320. package/dist/cjs/vite/loadConfig.native.js.map +1 -1
  321. package/dist/cjs/vite/makePluginWebOnly.native.js.map +1 -1
  322. package/dist/cjs/vite/one-server-only.test.native.js.map +1 -1
  323. package/dist/cjs/vite/one.cjs +4 -3
  324. package/dist/cjs/vite/one.native.js +4 -3
  325. package/dist/cjs/vite/one.native.js.map +1 -1
  326. package/dist/cjs/vite/plugins/SSRCSSPlugin.native.js.map +1 -1
  327. package/dist/cjs/vite/plugins/clientTreeShakePlugin.native.js.map +1 -1
  328. package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.native.js.map +1 -1
  329. package/dist/cjs/vite/plugins/criticalCSSPlugin.native.js.map +1 -1
  330. package/dist/cjs/vite/plugins/criticalCSSPlugin.test.native.js.map +1 -1
  331. package/dist/cjs/vite/plugins/devtoolsPlugin.native.js.map +1 -1
  332. package/dist/cjs/vite/plugins/environmentGuardPlugin.native.js.map +1 -1
  333. package/dist/cjs/vite/plugins/environmentGuardPlugin.test.native.js.map +1 -1
  334. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +25 -16
  335. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +25 -16
  336. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  337. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.test.native.js.map +1 -1
  338. package/dist/cjs/vite/plugins/fixDependenciesPlugin.native.js.map +1 -1
  339. package/dist/cjs/vite/plugins/generateFileSystemRouteTypesPlugin.native.js.map +1 -1
  340. package/dist/cjs/vite/plugins/imageDataPlugin.native.js.map +1 -1
  341. package/dist/cjs/vite/plugins/imageDataPlugin.test.native.js.map +1 -1
  342. package/dist/cjs/vite/plugins/removeReactNativeWebAnimatedPlugin.native.js.map +1 -1
  343. package/dist/cjs/vite/plugins/sourceInspectorPlugin.cjs +1 -1
  344. package/dist/cjs/vite/plugins/sourceInspectorPlugin.native.js +1 -1
  345. package/dist/cjs/vite/plugins/sourceInspectorPlugin.native.js.map +1 -1
  346. package/dist/cjs/vite/plugins/sourceInspectorPlugin.test.native.js.map +1 -1
  347. package/dist/cjs/vite/plugins/useDomPlugin.native.js.map +1 -1
  348. package/dist/cjs/vite/plugins/virtualEntryConstants.native.js.map +1 -1
  349. package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +2 -1
  350. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +2 -1
  351. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  352. package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
  353. package/dist/cjs/vite/plugins/warmRoutesPlugin.native.js.map +1 -1
  354. package/dist/cjs/vite/replaceLoader.native.js.map +1 -1
  355. package/dist/cjs/vite/resolveResponse.native.js.map +1 -1
  356. package/dist/cjs/vite/types.native.js.map +1 -1
  357. package/dist/cjs/vite-auto-warm.native.js.map +1 -1
  358. package/dist/cjs/vite.native.js.map +1 -1
  359. package/dist/cjs/zero/getQueryKey.native.js.map +1 -1
  360. package/dist/cjs/zero/isZeroQuery.native.js.map +1 -1
  361. package/dist/cjs/zero/resolveQuery.native.js.map +1 -1
  362. package/dist/cjs/zero/subscribeToQuery.native.js.map +1 -1
  363. package/dist/cjs/zero/types.native.js.map +1 -1
  364. package/dist/cjs/zero/useQuery.native.js.map +1 -1
  365. package/dist/cjs/zero/useQueryZero.native.js.map +1 -1
  366. package/dist/cjs/zero.native.js.map +1 -1
  367. package/dist/esm/babel-preset/index.mjs +7 -2
  368. package/dist/esm/babel-preset/index.mjs.map +1 -1
  369. package/dist/esm/babel-preset/index.native.js +7 -2
  370. package/dist/esm/babel-preset/index.native.js.map +1 -1
  371. package/dist/esm/babel-preset/index.test.mjs +13 -0
  372. package/dist/esm/babel-preset/index.test.mjs.map +1 -1
  373. package/dist/esm/babel-preset/index.test.native.js +13 -0
  374. package/dist/esm/babel-preset/index.test.native.js.map +1 -1
  375. package/dist/esm/cli/build.mjs +15 -12
  376. package/dist/esm/cli/build.mjs.map +1 -1
  377. package/dist/esm/cli/build.native.js +15 -12
  378. package/dist/esm/cli/build.native.js.map +1 -1
  379. package/dist/esm/cli/buildPage.mjs +2 -1
  380. package/dist/esm/cli/buildPage.mjs.map +1 -1
  381. package/dist/esm/cli/buildPage.native.js +2 -1
  382. package/dist/esm/cli/buildPage.native.js.map +1 -1
  383. package/dist/esm/constants.mjs +14 -5
  384. package/dist/esm/constants.mjs.map +1 -1
  385. package/dist/esm/constants.native.js +10 -1
  386. package/dist/esm/constants.native.js.map +1 -1
  387. package/dist/esm/constants.test.mjs +37 -0
  388. package/dist/esm/constants.test.mjs.map +1 -0
  389. package/dist/esm/constants.test.native.js +37 -0
  390. package/dist/esm/constants.test.native.js.map +1 -0
  391. package/dist/esm/createApp.mjs +3 -2
  392. package/dist/esm/createApp.mjs.map +1 -1
  393. package/dist/esm/daemon/server.mjs +23 -0
  394. package/dist/esm/daemon/server.mjs.map +1 -1
  395. package/dist/esm/daemon/server.native.js +61 -0
  396. package/dist/esm/daemon/server.native.js.map +1 -1
  397. package/dist/esm/index.js +3 -1
  398. package/dist/esm/index.js.map +1 -1
  399. package/dist/esm/index.mjs +3 -1
  400. package/dist/esm/index.mjs.map +1 -1
  401. package/dist/esm/index.native.js +3 -1
  402. package/dist/esm/index.native.js.map +1 -1
  403. package/dist/esm/lazyWithRetry.mjs +7 -0
  404. package/dist/esm/lazyWithRetry.mjs.map +1 -0
  405. package/dist/esm/lazyWithRetry.native.js +9 -0
  406. package/dist/esm/lazyWithRetry.native.js.map +1 -0
  407. package/dist/esm/router/router.mjs +22 -7
  408. package/dist/esm/router/router.mjs.map +1 -1
  409. package/dist/esm/router/router.native.js.map +1 -1
  410. package/dist/esm/router/useScreens.mjs +18 -3
  411. package/dist/esm/router/useScreens.mjs.map +1 -1
  412. package/dist/esm/router/useScreens.native.js +25 -5
  413. package/dist/esm/router/useScreens.native.js.map +1 -1
  414. package/dist/esm/serve.mjs +2 -1
  415. package/dist/esm/serve.mjs.map +1 -1
  416. package/dist/esm/serve.native.js +2 -1
  417. package/dist/esm/serve.native.js.map +1 -1
  418. package/dist/esm/server/ServerContextScript.mjs +4 -3
  419. package/dist/esm/server/ServerContextScript.mjs.map +1 -1
  420. package/dist/esm/server/ServerContextScript.native.js +6 -4
  421. package/dist/esm/server/ServerContextScript.native.js.map +1 -1
  422. package/dist/esm/server/oneServe.mjs +23 -10
  423. package/dist/esm/server/oneServe.mjs.map +1 -1
  424. package/dist/esm/server/oneServe.native.js +23 -10
  425. package/dist/esm/server/oneServe.native.js.map +1 -1
  426. package/dist/esm/server/setupBuildOptions.mjs +6 -1
  427. package/dist/esm/server/setupBuildOptions.mjs.map +1 -1
  428. package/dist/esm/server/setupBuildOptions.native.js +10 -4
  429. package/dist/esm/server/setupBuildOptions.native.js.map +1 -1
  430. package/dist/esm/server/workerHandler.mjs +3 -3
  431. package/dist/esm/server/workerHandler.mjs.map +1 -1
  432. package/dist/esm/server/workerHandler.native.js +3 -3
  433. package/dist/esm/server/workerHandler.native.js.map +1 -1
  434. package/dist/esm/useLoader.mjs +30 -7
  435. package/dist/esm/useLoader.mjs.map +1 -1
  436. package/dist/esm/useLoader.native.js +30 -7
  437. package/dist/esm/useLoader.native.js.map +1 -1
  438. package/dist/esm/utils/buildOutputPointer.mjs +43 -0
  439. package/dist/esm/utils/buildOutputPointer.mjs.map +1 -0
  440. package/dist/esm/utils/buildOutputPointer.native.js +51 -0
  441. package/dist/esm/utils/buildOutputPointer.native.js.map +1 -0
  442. package/dist/esm/utils/buildOutputPointer.test.mjs +71 -0
  443. package/dist/esm/utils/buildOutputPointer.test.mjs.map +1 -0
  444. package/dist/esm/utils/buildOutputPointer.test.native.js +71 -0
  445. package/dist/esm/utils/buildOutputPointer.test.native.js.map +1 -0
  446. package/dist/esm/utils/dynamicImport.mjs +29 -6
  447. package/dist/esm/utils/dynamicImport.mjs.map +1 -1
  448. package/dist/esm/utils/dynamicImport.native.js +32 -2
  449. package/dist/esm/utils/dynamicImport.native.js.map +1 -1
  450. package/dist/esm/utils/dynamicImport.test.mjs +88 -0
  451. package/dist/esm/utils/dynamicImport.test.mjs.map +1 -0
  452. package/dist/esm/utils/dynamicImport.test.native.js +106 -0
  453. package/dist/esm/utils/dynamicImport.test.native.js.map +1 -0
  454. package/dist/esm/utils/posixPathContract.test.mjs +67 -0
  455. package/dist/esm/utils/posixPathContract.test.mjs.map +1 -0
  456. package/dist/esm/utils/posixPathContract.test.native.js +87 -0
  457. package/dist/esm/utils/posixPathContract.test.native.js.map +1 -0
  458. package/dist/esm/utils/toServerOutputPath.mjs +11 -0
  459. package/dist/esm/utils/toServerOutputPath.mjs.map +1 -0
  460. package/dist/esm/utils/toServerOutputPath.native.js +11 -0
  461. package/dist/esm/utils/toServerOutputPath.native.js.map +1 -0
  462. package/dist/esm/utils/toServerOutputPath.test.mjs +28 -0
  463. package/dist/esm/utils/toServerOutputPath.test.mjs.map +1 -0
  464. package/dist/esm/utils/toServerOutputPath.test.native.js +28 -0
  465. package/dist/esm/utils/toServerOutputPath.test.native.js.map +1 -0
  466. package/dist/esm/vite/getManifest.test.mjs +47 -0
  467. package/dist/esm/vite/getManifest.test.mjs.map +1 -0
  468. package/dist/esm/vite/getManifest.test.native.js +50 -0
  469. package/dist/esm/vite/getManifest.test.native.js.map +1 -0
  470. package/dist/esm/vite/one.mjs +4 -3
  471. package/dist/esm/vite/one.mjs.map +1 -1
  472. package/dist/esm/vite/one.native.js +4 -3
  473. package/dist/esm/vite/one.native.js.map +1 -1
  474. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +26 -17
  475. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
  476. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +26 -17
  477. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  478. package/dist/esm/vite/plugins/sourceInspectorPlugin.mjs +1 -1
  479. package/dist/esm/vite/plugins/sourceInspectorPlugin.mjs.map +1 -1
  480. package/dist/esm/vite/plugins/sourceInspectorPlugin.native.js +1 -1
  481. package/dist/esm/vite/plugins/sourceInspectorPlugin.native.js.map +1 -1
  482. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +2 -1
  483. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
  484. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +2 -1
  485. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  486. package/package.json +23 -9
  487. package/src/babel-preset/index.test.ts +20 -0
  488. package/src/babel-preset/index.ts +21 -4
  489. package/src/cli/build.ts +23 -15
  490. package/src/cli/buildPage.ts +3 -1
  491. package/src/constants.test.ts +55 -0
  492. package/src/constants.ts +32 -4
  493. package/src/createApp.tsx +7 -2
  494. package/src/daemon/server.ts +30 -0
  495. package/src/index.ts +9 -0
  496. package/src/lazyWithRetry.tsx +21 -0
  497. package/src/router/router.ts +32 -7
  498. package/src/router/useScreens.tsx +22 -3
  499. package/src/serve.ts +2 -2
  500. package/src/server/ServerContextScript.tsx +9 -3
  501. package/src/server/oneServe.ts +33 -15
  502. package/src/server/setupBuildOptions.ts +11 -2
  503. package/src/server/workerHandler.ts +9 -5
  504. package/src/useLoader.ts +41 -6
  505. package/src/utils/buildOutputPointer.test.ts +97 -0
  506. package/src/utils/buildOutputPointer.ts +71 -0
  507. package/src/utils/dynamicImport.test.ts +92 -0
  508. package/src/utils/dynamicImport.ts +80 -13
  509. package/src/utils/posixPathContract.test.ts +97 -0
  510. package/src/utils/toServerOutputPath.test.ts +49 -0
  511. package/src/utils/toServerOutputPath.ts +11 -0
  512. package/src/vite/getManifest.test.ts +49 -0
  513. package/src/vite/one.ts +9 -5
  514. package/src/vite/plugins/fileSystemRouterPlugin.tsx +31 -17
  515. package/src/vite/plugins/sourceInspectorPlugin.ts +2 -1
  516. package/src/vite/plugins/virtualEntryPlugin.ts +5 -2
  517. package/types/babel-preset/index.d.ts.map +1 -1
  518. package/types/cli/build.d.ts.map +1 -1
  519. package/types/cli/buildPage.d.ts.map +1 -1
  520. package/types/constants.d.ts +7 -4
  521. package/types/constants.d.ts.map +1 -1
  522. package/types/constants.test.d.ts +2 -0
  523. package/types/constants.test.d.ts.map +1 -0
  524. package/types/createApp.d.ts.map +1 -1
  525. package/types/daemon/server.d.ts.map +1 -1
  526. package/types/index.d.ts +2 -0
  527. package/types/index.d.ts.map +1 -1
  528. package/types/lazyWithRetry.d.ts +6 -0
  529. package/types/lazyWithRetry.d.ts.map +1 -0
  530. package/types/router/router.d.ts.map +1 -1
  531. package/types/router/useScreens.d.ts.map +1 -1
  532. package/types/serve.d.ts.map +1 -1
  533. package/types/server/ServerContextScript.d.ts.map +1 -1
  534. package/types/server/oneServe.d.ts.map +1 -1
  535. package/types/server/setupBuildOptions.d.ts.map +1 -1
  536. package/types/server/workerHandler.d.ts.map +1 -1
  537. package/types/useLoader.d.ts.map +1 -1
  538. package/types/utils/buildOutputPointer.d.ts +4 -0
  539. package/types/utils/buildOutputPointer.d.ts.map +1 -0
  540. package/types/utils/buildOutputPointer.test.d.ts +2 -0
  541. package/types/utils/buildOutputPointer.test.d.ts.map +1 -0
  542. package/types/utils/dynamicImport.d.ts +10 -2
  543. package/types/utils/dynamicImport.d.ts.map +1 -1
  544. package/types/utils/dynamicImport.test.d.ts +2 -0
  545. package/types/utils/dynamicImport.test.d.ts.map +1 -0
  546. package/types/utils/posixPathContract.test.d.ts +2 -0
  547. package/types/utils/posixPathContract.test.d.ts.map +1 -0
  548. package/types/utils/toServerOutputPath.d.ts +2 -0
  549. package/types/utils/toServerOutputPath.d.ts.map +1 -0
  550. package/types/utils/toServerOutputPath.test.d.ts +2 -0
  551. package/types/utils/toServerOutputPath.test.d.ts.map +1 -0
  552. package/types/vite/getManifest.test.d.ts +2 -0
  553. package/types/vite/getManifest.test.d.ts.map +1 -0
  554. package/types/vite/one.d.ts.map +1 -1
  555. package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
  556. package/types/vite/plugins/sourceInspectorPlugin.d.ts.map +1 -1
  557. package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
package/src/serve.ts CHANGED
@@ -6,6 +6,7 @@ import type { VXRNOptions } from 'vxrn'
6
6
  import { setServerGlobals } from './server/setServerGlobals'
7
7
  import { setupBuildInfo } from './server/setupBuildOptions'
8
8
  import { ensureExists } from './utils/ensureExists'
9
+ import { resolveServeOutDir } from './utils/buildOutputPointer'
9
10
  import type { One } from './vite/types'
10
11
 
11
12
  // formatErrorSafely + the prepareStackTrace guard prevent a buggy transitive
@@ -191,8 +192,7 @@ async function serveWithCluster(args: Parameters<typeof serve>[0], numWorkers: n
191
192
  }
192
193
 
193
194
  async function startWorker(args: Parameters<typeof serve>[0]) {
194
- const outDir =
195
- args?.outDir || (FSExtra.existsSync('buildInfo.json') ? '.' : null) || 'dist'
195
+ const outDir = await resolveServeOutDir(args?.outDir)
196
196
  const buildInfo = (await FSExtra.readJSON(`${outDir}/buildInfo.json`)) as One.BuildInfo
197
197
  const { oneOptions } = buildInfo
198
198
 
@@ -25,12 +25,18 @@ export function ServerContextScript() {
25
25
  // strip cssContents - read from DOM instead (CSSPrehydrateScript)
26
26
  const { cssContents, ...restContext } = context || {}
27
27
 
28
- // strip page loaderData from matches to avoid double-serialization
29
- const compactMatches = restContext.matches?.map((m: any) => ({
28
+ // strip page loaderData from matches to avoid double-serialization.
29
+ // we always strip the leaf (its data lives in restContext.loaderData and
30
+ // gets restored client-side onto matches[last]). reference equality on
31
+ // restContext.loaderData was too aggressive — if a layout's loaderData
32
+ // happened to ref-equal the page's (e.g. both `null`), the layout would
33
+ // permanently lose its data after hydration.
34
+ const lastMatchIndex = (restContext.matches?.length ?? 0) - 1
35
+ const compactMatches = restContext.matches?.map((m: any, i: number) => ({
30
36
  routeId: m.routeId,
31
37
  pathname: m.pathname,
32
38
  params: m.params,
33
- ...(m.loaderData !== restContext.loaderData ? { loaderData: m.loaderData } : {}),
39
+ ...(i === lastMatchIndex ? {} : { loaderData: m.loaderData }),
34
40
  }))
35
41
 
36
42
  const clientContext = {
@@ -1,11 +1,11 @@
1
1
  import type { Hono, MiddlewareHandler } from 'hono'
2
2
  import type { BlankEnv } from 'hono/types'
3
3
  import { readFile } from 'node:fs/promises'
4
- import { join } from 'node:path'
4
+ import { join, posix } from 'node:path'
5
5
  import {
6
- CSS_PRELOAD_JS_POSTFIX,
6
+ CSS_PRELOAD_JS_POSTFIX_REGEX,
7
7
  LOADER_JS_POSTFIX_UNCACHED,
8
- PRELOAD_JS_POSTFIX,
8
+ PRELOAD_JS_POSTFIX_REGEX,
9
9
  } from '../constants'
10
10
  import {
11
11
  compileManifest,
@@ -17,6 +17,7 @@ import {
17
17
  import type { RenderAppProps } from '../types'
18
18
  import { getPathFromLoaderPath } from '../utils/cleanUrl'
19
19
  import { toAbsoluteUrl } from '../utils/toAbsolute'
20
+ import { toServerOutputPath } from '../utils/toServerOutputPath'
20
21
  import type { One } from '../vite/types'
21
22
  import type { RouteInfoCompiled } from './createRoutesManifest'
22
23
  import { setSSRLoaderData } from './ssrLoaderData'
@@ -24,6 +25,22 @@ import { getFetchStaticHtml } from './staticHtmlFetcher'
24
25
 
25
26
  const debugRouter = process.env.ONE_DEBUG_ROUTER
26
27
 
28
+ // Bounded map helper: prevents unbounded memory growth by evicting the oldest
29
+ // entry when the map exceeds the specified maximum size. Uses insertion order
30
+ // (Map preserves insertion order) — the first-inserted entry is evicted first.
31
+ const MODULE_CACHE_MAX = 500
32
+ function setBounded<K, V>(map: Map<K, V>, key: K, value: V, max: number): void {
33
+ if (map.has(key)) {
34
+ map.set(key, value)
35
+ return
36
+ }
37
+ if (map.size >= max) {
38
+ const firstKey = map.keys().next().value
39
+ if (firstKey !== undefined) map.delete(firstKey as K)
40
+ }
41
+ map.set(key, value)
42
+ }
43
+
27
44
  // forwards response headers to a hono context, preserving individual
28
45
  // set-cookie values (Headers.forEach joins them into one unparseable string)
29
46
  function forwardHeaders(response: Response, context: { header: Function }) {
@@ -164,9 +181,7 @@ export async function oneServe(
164
181
  // cold path - async import
165
182
  return (async () => {
166
183
  const pathToResolve = serverPath || lazyKey || ''
167
- const resolvedPath = pathToResolve.includes(`${outDir}/server`)
168
- ? pathToResolve
169
- : join('./', `${outDir}/server`, pathToResolve)
184
+ const resolvedPath = toServerOutputPath(pathToResolve, outDir)
170
185
 
171
186
  let routeExported: any
172
187
  if (moduleImportCache.has(cacheKey)) {
@@ -177,14 +192,14 @@ export async function oneServe(
177
192
  ? await options.lazyRoutes.pages[lazyKey]()
178
193
  : await import(toAbsoluteUrl(resolvedPath))
179
194
  : await import(toAbsoluteUrl(serverPath!))
180
- moduleImportCache.set(cacheKey, routeExported)
195
+ setBounded(moduleImportCache, cacheKey, routeExported, MODULE_CACHE_MAX)
181
196
  }
182
197
 
183
198
  const loader = routeExported?.loader || null
184
- loaderCache.set(cacheKey, loader)
199
+ setBounded(loaderCache, cacheKey, loader, MODULE_CACHE_MAX)
185
200
  // also cache loaderCache export for coalescing
186
201
  const loaderCacheFn = routeExported?.loaderCache ?? null
187
- loaderCacheFnMap.set(cacheKey, loaderCacheFn)
202
+ setBounded(loaderCacheFnMap, cacheKey, loaderCacheFn, MODULE_CACHE_MAX)
188
203
  return loader
189
204
  })()
190
205
  }
@@ -314,7 +329,8 @@ export async function oneServe(
314
329
  }
315
330
  // both vite and rolldown-vite replace brackets with underscores in output filenames
316
331
  const fileName = route.page.slice(1).replace(/\[/g, '_').replace(/\]/g, '_')
317
- const apiFile = join(outDir, 'api', fileName + (apiCJS ? '.cjs' : '.js'))
332
+ // posix matches the serverJsPath/builtMiddlewares producer convention
333
+ const apiFile = posix.join(outDir, 'api', fileName + (apiCJS ? '.cjs' : '.js'))
318
334
  return await import(toAbsoluteUrl(apiFile))
319
335
  },
320
336
 
@@ -328,9 +344,7 @@ export async function oneServe(
328
344
 
329
345
  async handleLoader({ route, loaderProps }) {
330
346
  const routeFile = (route as any).routeFile || route.file
331
- const serverPath = route.file.includes(`${outDir}/server`)
332
- ? route.file
333
- : join('./', `${outDir}/server`, route.file)
347
+ const serverPath = toServerOutputPath(route.file, outDir)
334
348
 
335
349
  let loader: Function | null
336
350
  try {
@@ -940,7 +954,11 @@ url: ${url}`)
940
954
 
941
955
  // TODO make this inside each page, need to make loader urls just be REGULAR_URL + loaderpostfix
942
956
  app.get('*', async (c, next) => {
943
- if (c.req.path.endsWith(PRELOAD_JS_POSTFIX)) {
957
+ // regex match (not exact CACHE_KEY suffix) — see constants.ts:
958
+ // PRELOAD_JS_POSTFIX_REGEX. handles dynamic segments and the rare
959
+ // CACHE_KEY-drift case by funnelling misses through the graceful
960
+ // empty-200 below instead of the static-handler 404.
961
+ if (PRELOAD_JS_POSTFIX_REGEX.test(c.req.path)) {
944
962
  // TODO handle dynamic segments (i think the below loader has some logic for this)
945
963
  if (!preloads[c.req.path]) {
946
964
  // no preload exists 200 gracefully
@@ -950,7 +968,7 @@ url: ${url}`)
950
968
  }
951
969
  }
952
970
 
953
- if (c.req.path.endsWith(CSS_PRELOAD_JS_POSTFIX)) {
971
+ if (CSS_PRELOAD_JS_POSTFIX_REGEX.test(c.req.path)) {
954
972
  // Return empty resolved promise if no CSS preload exists for this route
955
973
  if (!cssPreloads?.[c.req.path]) {
956
974
  c.header('Content-Type', 'text/javascript')
@@ -1,8 +1,17 @@
1
+ import { setCacheKey } from '../constants'
1
2
  import type { One } from '../vite/types'
2
3
 
3
4
  export function setupBuildInfo(buildInfo: One.BuildInfo) {
4
- // ensure cache key matches build
5
- process.env.ONE_CACHE_KEY ||= buildInfo.constants.CACHE_KEY
5
+ // ensure cache key matches build. env var is for child workers spawned later;
6
+ // setCacheKey rebinds the in-memory postfixes for the current process so any
7
+ // code that imported constants before setupBuildInfo ran (e.g. workerHandler
8
+ // pulled in by serve-worker's static import graph) sees the pinned value.
9
+ // headless-server may not pass `constants` — skip gracefully.
10
+ const key = buildInfo.constants?.CACHE_KEY
11
+ if (key) {
12
+ process.env.ONE_CACHE_KEY ||= key
13
+ setCacheKey(key)
14
+ }
6
15
  process.env.ONE_DEFAULT_RENDER_MODE ||=
7
16
  buildInfo.oneOptions?.web?.defaultRenderMode || 'ssg'
8
17
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
- CSS_PRELOAD_JS_POSTFIX,
2
+ CSS_PRELOAD_JS_POSTFIX_REGEX,
3
3
  LOADER_JS_POSTFIX_UNCACHED,
4
- PRELOAD_JS_POSTFIX,
4
+ PRELOAD_JS_POSTFIX_REGEX,
5
5
  } from '../constants'
6
6
  import {
7
7
  compileManifest,
@@ -597,8 +597,12 @@ export function createWorkerHandler(options: WorkerHandlerOptions) {
597
597
  }
598
598
  }
599
599
 
600
- // 2. preload endpoints (empty response if no preload exists)
601
- if (pathname.endsWith(PRELOAD_JS_POSTFIX)) {
600
+ // 2. preload endpoints (empty response if no preload exists).
601
+ // regex match (not exact CACHE_KEY suffix) — see constants.ts:
602
+ // PRELOAD_JS_POSTFIX_REGEX. handles dynamic segments and the rare
603
+ // CACHE_KEY-drift case by funnelling misses through the graceful
604
+ // empty-200 below instead of the static-handler 404.
605
+ if (PRELOAD_JS_POSTFIX_REGEX.test(pathname)) {
602
606
  if (!currentPreloads[pathname]) {
603
607
  return new Response('', {
604
608
  headers: { 'Content-Type': 'text/javascript' },
@@ -608,7 +612,7 @@ export function createWorkerHandler(options: WorkerHandlerOptions) {
608
612
  return null
609
613
  }
610
614
 
611
- if (pathname.endsWith(CSS_PRELOAD_JS_POSTFIX)) {
615
+ if (CSS_PRELOAD_JS_POSTFIX_REGEX.test(pathname)) {
612
616
  if (!currentCssPreloads?.[pathname]) {
613
617
  return new Response('export default Promise.resolve()', {
614
618
  headers: { 'Content-Type': 'text/javascript' },
package/src/useLoader.ts CHANGED
@@ -90,8 +90,26 @@ registerDevtoolsFunction('recordLoaderTiming', recordLoaderTiming)
90
90
  const loaderState: Record<string, LoaderStateEntry> = {}
91
91
  const subscribers = new Set<() => void>()
92
92
 
93
+ // Prevent unbounded growth of loaderState by pruning the oldest entry when
94
+ // we exceed this limit. Most apps navigate a limited set of routes, but
95
+ // dynamic params (e.g. /users/:id) can generate thousands of unique keys.
96
+ const LOADER_STATE_MAX = 200
97
+ const loaderStateKeys: string[] = []
98
+
99
+ function setBoundedLoaderState(path: string, entry: LoaderStateEntry) {
100
+ if (!(path in loaderState)) {
101
+ loaderStateKeys.push(path)
102
+ if (loaderStateKeys.length > LOADER_STATE_MAX) {
103
+ const oldest = loaderStateKeys.shift()!
104
+ delete loaderState[oldest]
105
+ }
106
+ }
107
+ loaderState[path] = entry
108
+ }
109
+
93
110
  function updateState(path: string, updates: Partial<LoaderStateEntry>) {
94
- loaderState[path] = { ...loaderState[path], ...updates }
111
+ const merged = { ...loaderState[path], ...updates }
112
+ setBoundedLoaderState(path, merged)
95
113
  subscribers.forEach((callback) => {
96
114
  callback()
97
115
  })
@@ -103,14 +121,15 @@ function subscribe(callback: () => void) {
103
121
  }
104
122
 
105
123
  function getLoaderState(path: string, preloadedData?: any): LoaderStateEntry {
106
- if (!loaderState[path]) {
107
- loaderState[path] = {
124
+ if (!(path in loaderState)) {
125
+ const entry: LoaderStateEntry = {
108
126
  data: preloadedData,
109
127
  error: undefined,
110
128
  promise: undefined,
111
129
  state: 'idle',
112
130
  hasLoadedOnce: !!preloadedData,
113
131
  }
132
+ setBoundedLoaderState(path, entry)
114
133
  }
115
134
  return loaderState[path]
116
135
  }
@@ -759,6 +778,22 @@ export function useLoader<
759
778
  const results = new Map()
760
779
  const started = new Map()
761
780
 
781
+ // Prevent unbounded growth of useAsyncFn caches. Under sustained client-side
782
+ // navigation with many unique param combinations, these can accumulate large
783
+ // API responses. 100 entries is generous for typical route counts.
784
+ const USE_ASYNC_FN_CACHE_MAX = 100
785
+
786
+ function setBoundedResults(key: string, value: any) {
787
+ if (results.size >= USE_ASYNC_FN_CACHE_MAX && !results.has(key)) {
788
+ const firstKey = results.keys().next().value
789
+ if (firstKey !== undefined) {
790
+ results.delete(firstKey as string)
791
+ started.delete(firstKey as string)
792
+ }
793
+ }
794
+ results.set(key, value)
795
+ }
796
+
762
797
  // maps loader function → its route's loaderData for SSR
763
798
  // populated before render in oneServe.ts, cleared after
764
799
  // re-export for backwards compat
@@ -780,14 +815,14 @@ function useAsyncFn(val: any, props?: any) {
780
815
  if (next instanceof Promise) {
781
816
  next = next
782
817
  .then((final) => {
783
- results.set(key, final)
818
+ setBoundedResults(key, final)
784
819
  })
785
820
  .catch((err) => {
786
821
  console.error(`Error running loader()`, err)
787
- results.set(key, undefined)
822
+ setBoundedResults(key, undefined)
788
823
  })
789
824
  }
790
- results.set(key, next)
825
+ setBoundedResults(key, next)
791
826
  }
792
827
  }
793
828
 
@@ -0,0 +1,97 @@
1
+ import { mkdtempSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
4
+ import FSExtra from 'fs-extra'
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
6
+ import {
7
+ buildOutputPointerPath,
8
+ resolveServeOutDir,
9
+ writeBuildOutputPointer,
10
+ } from './buildOutputPointer'
11
+
12
+ describe('build output pointer', () => {
13
+ const originalCwd = process.cwd()
14
+ let tempRoot = ''
15
+
16
+ beforeEach(() => {
17
+ tempRoot = mkdtempSync(join(tmpdir(), 'one-build-pointer-'))
18
+ process.chdir(tempRoot)
19
+ })
20
+
21
+ afterEach(async () => {
22
+ process.chdir(originalCwd)
23
+ vi.restoreAllMocks()
24
+ await FSExtra.remove(tempRoot)
25
+ })
26
+
27
+ it('prefers an explicit serve outDir', async () => {
28
+ await FSExtra.ensureDir('build-out')
29
+ await FSExtra.writeJSON(join('build-out', 'buildInfo.json'), {})
30
+ await writeBuildOutputPointer('build-out')
31
+
32
+ expect(await resolveServeOutDir('manual-out')).toBe('manual-out')
33
+ })
34
+
35
+ it('preserves serving from inside the output directory', async () => {
36
+ await FSExtra.writeJSON('buildInfo.json', {})
37
+ await FSExtra.ensureDir('build-out')
38
+ await FSExtra.writeJSON(join('build-out', 'buildInfo.json'), {})
39
+ await writeBuildOutputPointer('build-out')
40
+
41
+ expect(await resolveServeOutDir()).toBe('.')
42
+ })
43
+
44
+ it('resolves the outDir written by build', async () => {
45
+ await FSExtra.ensureDir('build-out')
46
+ await FSExtra.writeJSON(join('build-out', 'buildInfo.json'), {})
47
+
48
+ await writeBuildOutputPointer('build-out')
49
+
50
+ expect(await FSExtra.readJSON(buildOutputPointerPath)).toEqual({
51
+ outDir: 'build-out',
52
+ })
53
+ expect(await resolveServeOutDir()).toBe('build-out')
54
+ })
55
+
56
+ it('falls back to dist when the pointer is stale', async () => {
57
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
58
+
59
+ await writeBuildOutputPointer('missing-out')
60
+
61
+ expect(await resolveServeOutDir()).toBe('dist')
62
+ // both the stale-pointer warning and the missing-dist warning fire
63
+ expect(warn).toHaveBeenCalledTimes(2)
64
+ expect(warn.mock.calls[0][0]).toMatch(/build-pointer\.json points to/)
65
+ expect(warn.mock.calls[1][0]).toMatch(/no build-output pointer/)
66
+ })
67
+
68
+ it('falls back to dist when no pointer exists and warns about missing dist', async () => {
69
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
70
+
71
+ expect(await resolveServeOutDir()).toBe('dist')
72
+ expect(warn).toHaveBeenCalledOnce()
73
+ expect(warn.mock.calls[0][0]).toMatch(/no build-output pointer/)
74
+ })
75
+
76
+ it('does not warn when falling back to an existing dist/ build', async () => {
77
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
78
+ await FSExtra.ensureDir('dist')
79
+ await FSExtra.writeJSON(join('dist', 'buildInfo.json'), {})
80
+
81
+ expect(await resolveServeOutDir()).toBe('dist')
82
+ expect(warn).not.toHaveBeenCalled()
83
+ })
84
+
85
+ it('warns when the pointer write fails', async () => {
86
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
87
+ const writeSpy = vi
88
+ .spyOn(FSExtra, 'writeJSON')
89
+ .mockRejectedValueOnce(new Error('permission denied'))
90
+
91
+ await writeBuildOutputPointer('build-out')
92
+
93
+ expect(writeSpy).toHaveBeenCalled()
94
+ expect(warn).toHaveBeenCalledOnce()
95
+ expect(warn.mock.calls[0][0]).toMatch(/could not write build-output pointer/)
96
+ })
97
+ })
@@ -0,0 +1,71 @@
1
+ import { dirname, join } from 'node:path'
2
+ import FSExtra from 'fs-extra'
3
+ import { toAbsolute } from './toAbsolute'
4
+
5
+ // stored under the project cwd; one build and one serve should run from the same root.
6
+ export const buildOutputPointerPath = join(
7
+ 'node_modules',
8
+ '.cache',
9
+ 'one',
10
+ 'build-pointer.json'
11
+ )
12
+
13
+ type BuildOutputPointer = {
14
+ outDir?: string
15
+ }
16
+
17
+ export async function writeBuildOutputPointer(outDir: string) {
18
+ try {
19
+ const pointerPath = toAbsolute(buildOutputPointerPath)
20
+ await FSExtra.ensureDir(dirname(pointerPath))
21
+ await FSExtra.writeJSON(pointerPath, { outDir })
22
+ } catch (err) {
23
+ // surface the failure so `one serve` doesn't later fall back to `dist/`
24
+ // with no breadcrumb when a custom outDir was used.
25
+ console.warn(
26
+ `[one build] could not write build-output pointer (${buildOutputPointerPath}). \`one serve\` will fall back to 'dist/' unless you pass --outDir.`,
27
+ err instanceof Error ? err.message : err
28
+ )
29
+ }
30
+ }
31
+
32
+ export async function resolveServeOutDir(outDir?: string) {
33
+ if (outDir) {
34
+ return outDir
35
+ }
36
+
37
+ if (FSExtra.existsSync('buildInfo.json')) {
38
+ return '.'
39
+ }
40
+
41
+ // ENOENT here is the common case (no pointer written yet); only warn on
42
+ // unexpected read errors.
43
+ let pointer: BuildOutputPointer | undefined
44
+ try {
45
+ pointer = (await FSExtra.readJSON(buildOutputPointerPath)) as BuildOutputPointer
46
+ } catch (err: any) {
47
+ if (err?.code && err.code !== 'ENOENT') {
48
+ console.warn(
49
+ `[one serve] could not read build-output pointer (${buildOutputPointerPath}):`,
50
+ err.message ?? err
51
+ )
52
+ }
53
+ }
54
+
55
+ if (pointer?.outDir) {
56
+ if (await FSExtra.pathExists(join(pointer.outDir, 'buildInfo.json'))) {
57
+ return pointer.outDir
58
+ }
59
+ console.warn(
60
+ `[one serve] build-pointer.json points to '${pointer.outDir}/' but no buildInfo.json was found there. run \`one build\` to refresh the marker.`
61
+ )
62
+ }
63
+
64
+ if (!FSExtra.existsSync('dist/buildInfo.json')) {
65
+ console.warn(
66
+ `[one serve] no build-output pointer and no 'dist/buildInfo.json'. did \`one build\` run from this cwd? pass --outDir to point at the build output.`
67
+ )
68
+ }
69
+
70
+ return 'dist'
71
+ }
@@ -0,0 +1,92 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import { isChunkLoadError, loadWithRetry } from './dynamicImport'
3
+
4
+ const instantDelay = () => Promise.resolve()
5
+ const chunkError = () =>
6
+ new Error('Failed to fetch dynamically imported module: /assets/EditorPane.js')
7
+
8
+ // let the all-microtask retry chain (instantDelay resolves synchronously) plus
9
+ // the final pending-promise branch fully drain before asserting.
10
+ const drain = () => new Promise((r) => setTimeout(r, 0))
11
+
12
+ describe('isChunkLoadError', () => {
13
+ it('matches the chrome / firefox / safari chunk-load messages, nothing else', () => {
14
+ expect(isChunkLoadError(new Error('Failed to fetch dynamically imported module: /a'))).toBe(
15
+ true
16
+ )
17
+ expect(isChunkLoadError(new Error('error loading dynamically imported module: /a'))).toBe(
18
+ true
19
+ )
20
+ expect(isChunkLoadError(new Error('Importing a module script failed.'))).toBe(true)
21
+ expect(isChunkLoadError('Failed to fetch dynamically imported module')).toBe(true)
22
+ expect(isChunkLoadError(new Error('TypeError: x is not a function'))).toBe(false)
23
+ })
24
+ })
25
+
26
+ describe('loadWithRetry', () => {
27
+ it('resolves on first success without retrying or recovering', async () => {
28
+ const loader = vi.fn().mockResolvedValue({ default: 'ok' })
29
+ const delay = vi.fn(instantDelay)
30
+ const onChunkErrorExhausted = vi.fn(() => false)
31
+ await expect(loadWithRetry(loader, { delay, onChunkErrorExhausted })).resolves.toEqual({
32
+ default: 'ok',
33
+ })
34
+ expect(loader).toHaveBeenCalledTimes(1)
35
+ expect(delay).not.toHaveBeenCalled()
36
+ expect(onChunkErrorExhausted).not.toHaveBeenCalled()
37
+ })
38
+
39
+ it('retries a transient rejection then resolves, re-invoking the loader each attempt', async () => {
40
+ const loader = vi
41
+ .fn()
42
+ .mockRejectedValueOnce(chunkError())
43
+ .mockRejectedValueOnce(chunkError())
44
+ .mockResolvedValue({ default: 'ok' })
45
+ const delay = vi.fn(instantDelay)
46
+ const onChunkErrorExhausted = vi.fn(() => false)
47
+ await expect(
48
+ loadWithRetry(loader, { attempts: 3, delay, onChunkErrorExhausted })
49
+ ).resolves.toEqual({ default: 'ok' })
50
+ expect(loader).toHaveBeenCalledTimes(3)
51
+ expect(delay).toHaveBeenCalledTimes(2)
52
+ expect(onChunkErrorExhausted).not.toHaveBeenCalled()
53
+ })
54
+
55
+ it('exhausts retries on a persistent chunk error, recovers once, and stays pending', async () => {
56
+ const loader = vi.fn().mockRejectedValue(chunkError())
57
+ const delay = vi.fn(instantDelay)
58
+ const onChunkErrorExhausted = vi.fn(() => true) // a reload was scheduled
59
+ const settled = vi.fn()
60
+ void loadWithRetry(loader, { attempts: 2, delay, onChunkErrorExhausted }).then(
61
+ settled,
62
+ settled
63
+ )
64
+ await drain()
65
+ expect(loader).toHaveBeenCalledTimes(3) // initial + 2 retries
66
+ expect(onChunkErrorExhausted).toHaveBeenCalledTimes(1)
67
+ // the page is tearing down for the reload — the promise must never settle so
68
+ // it can't flash a broken/blank tree.
69
+ expect(settled).not.toHaveBeenCalled()
70
+ })
71
+
72
+ it('rethrows a non-chunk error without recovering', async () => {
73
+ const loader = vi.fn().mockRejectedValue(new Error('boom: a real bug'))
74
+ const delay = vi.fn(instantDelay)
75
+ const onChunkErrorExhausted = vi.fn(() => true)
76
+ await expect(
77
+ loadWithRetry(loader, { attempts: 1, delay, onChunkErrorExhausted })
78
+ ).rejects.toThrow('boom: a real bug')
79
+ expect(loader).toHaveBeenCalledTimes(2)
80
+ expect(onChunkErrorExhausted).not.toHaveBeenCalled()
81
+ })
82
+
83
+ it('rethrows a chunk error when the reload was debounced away', async () => {
84
+ const loader = vi.fn().mockRejectedValue(chunkError())
85
+ const delay = vi.fn(instantDelay)
86
+ const onChunkErrorExhausted = vi.fn(() => false) // debounced, no reload happened
87
+ await expect(
88
+ loadWithRetry(loader, { attempts: 1, delay, onChunkErrorExhausted })
89
+ ).rejects.toThrow('Failed to fetch dynamically imported module')
90
+ expect(onChunkErrorExhausted).toHaveBeenCalledTimes(1)
91
+ })
92
+ })
@@ -9,17 +9,23 @@ export const dynamicImport = (path: string) => {
9
9
  return Promise.resolve(undefined)
10
10
  }
11
11
 
12
- if (process.env.TAMAGUI_TARGET !== 'native') {
13
- return import(
14
- /* @vite-ignore */
15
- path
16
- ).catch((err) => {
17
- if (process.env.ONE_SKEW_PROTECTION !== 'false' && isChunkLoadError(err)) {
18
- handleSkewError()
19
- }
20
- throw err
21
- })
22
- }
12
+ // retry a transient chunk-fetch failure in place before giving up, then fall
13
+ // back to one's debounced reload. the in-place retry matters because a single
14
+ // rejection permanently poisons callers that memoize the loader result — most
15
+ // notably React.lazy, which caches the FIRST settled value (rejection
16
+ // included) and re-throws it forever without re-invoking the loader. the retry
17
+ // is always cheap; only the reload honors the ONE_SKEW_PROTECTION opt-out.
18
+ return loadWithRetry(
19
+ () =>
20
+ import(
21
+ /* @vite-ignore */
22
+ path
23
+ ),
24
+ {
25
+ onChunkErrorExhausted: () =>
26
+ process.env.ONE_SKEW_PROTECTION !== 'false' ? handleSkewError() : false,
27
+ }
28
+ )
23
29
  }
24
30
 
25
31
  const CHUNK_ERROR_PATTERNS = [
@@ -33,12 +39,73 @@ export function isChunkLoadError(err: unknown): boolean {
33
39
  return CHUNK_ERROR_PATTERNS.some((p) => msg.includes(p))
34
40
  }
35
41
 
36
- export function handleSkewError() {
37
- if (typeof window === 'undefined') return
42
+ // debounced one-time reload to recover from a deploy skew or a poisoned dev
43
+ // module graph. returns whether it actually scheduled a reload (false when
44
+ // debounced away within the cooldown, or on the server) so callers like
45
+ // loadWithRetry can decide whether to keep waiting for the teardown or surface
46
+ // the underlying error.
47
+ export function handleSkewError(): boolean {
48
+ if (typeof window === 'undefined') return false
38
49
  const key = '__one_skew_reload'
39
50
  const last = sessionStorage.getItem(key)
40
51
  if (!last || Date.now() - Number(last) > 10_000) {
41
52
  sessionStorage.setItem(key, String(Date.now()))
42
53
  window.location.reload()
54
+ return true
55
+ }
56
+ return false
57
+ }
58
+
59
+ // extra attempts after the first before giving up. a transient chunk fetch
60
+ // (ECONNRESET / dev-server 5xx / timeout under load) usually recovers on the
61
+ // next try when the failure is the top-level chunk.
62
+ export const CHUNK_RETRY_ATTEMPTS = 3
63
+ // linear backoff between chunk retries: ride out a brief hiccup, not a long
64
+ // outage.
65
+ export const CHUNK_RETRY_DELAY_MS = 500
66
+
67
+ const realDelay = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms))
68
+
69
+ // wraps a dynamic-import loader so a transient rejection is retried with backoff
70
+ // before it settles, instead of permanently poisoning a caller that memoizes the
71
+ // result (e.g. React.lazy — see dynamicImport above, and lazyWithRetry). when
72
+ // retries are exhausted on a chunk-load error, recover via the injected reload
73
+ // (defaults to one's debounced handleSkewError); the reload tears the page down,
74
+ // so the returned promise is left pending rather than rejecting into a surviving
75
+ // tree. `delay` + `onChunkErrorExhausted` are injectable so this is unit-testable
76
+ // without real timers or a real location.reload.
77
+ export async function loadWithRetry<T>(
78
+ loader: () => Promise<T>,
79
+ options: {
80
+ attempts?: number
81
+ delayMs?: number
82
+ delay?: (ms: number) => Promise<void>
83
+ onChunkErrorExhausted?: () => boolean
84
+ } = {}
85
+ ): Promise<T> {
86
+ const attempts = options.attempts ?? CHUNK_RETRY_ATTEMPTS
87
+ const delayMs = options.delayMs ?? CHUNK_RETRY_DELAY_MS
88
+ const delay = options.delay ?? realDelay
89
+ const recover = options.onChunkErrorExhausted ?? handleSkewError
90
+
91
+ const attempt = async (retriesLeft: number): Promise<T> => {
92
+ try {
93
+ return await loader()
94
+ } catch (err) {
95
+ if (retriesLeft > 0) {
96
+ await delay(delayMs)
97
+ return attempt(retriesLeft - 1)
98
+ }
99
+ // out of retries: a chunk-load failure is a dev module-graph poison or a
100
+ // prod deploy skew — recover via the debounced reload. the reload tears the
101
+ // page down, so leave this promise pending (resolving/rejecting would
102
+ // flash a broken tree). if the reload was debounced away, surface the real
103
+ // error so it isn't swallowed.
104
+ if (isChunkLoadError(err) && recover()) {
105
+ return new Promise<T>(() => {})
106
+ }
107
+ throw err
108
+ }
43
109
  }
110
+ return attempt(attempts)
44
111
  }