akanjs 2.2.4-rc.5 → 2.2.4

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 (608) hide show
  1. package/base/base.test.ts +135 -0
  2. package/base/base.ts +1 -1
  3. package/base/baseEnv.test.ts +146 -0
  4. package/base/primitiveRegistry.test.ts +127 -0
  5. package/base/primitiveRegistry.ts +10 -6
  6. package/base/symbols.test.ts +29 -0
  7. package/base/types.ts +4 -1
  8. package/base/utils.test.ts +30 -0
  9. package/build.ts +318 -0
  10. package/capacitor.base.config.test.ts +83 -0
  11. package/capacitor.base.config.ts +1 -1
  12. package/client/capacitor.ts +1 -1
  13. package/client/client.auth-storage.test.ts +210 -0
  14. package/client/client.decorators.test.ts +74 -0
  15. package/client/client.device.test.ts +181 -0
  16. package/client/client.page.test.tsx +175 -0
  17. package/client/client.pure.test.ts +146 -0
  18. package/client/client.router.test.ts +290 -0
  19. package/client/cookie.ts +4 -2
  20. package/client/createFont.ts +2 -2
  21. package/client/csrTypes.ts +8 -2
  22. package/client/makePageProto.tsx +10 -4
  23. package/client/router.ts +8 -3
  24. package/client/translator.ts +12 -4
  25. package/common/Logger.test.ts +45 -0
  26. package/common/Logger.ts +4 -1
  27. package/common/formatAndValidation.test.ts +61 -0
  28. package/common/formatNumber.ts +5 -2
  29. package/common/hmrPhase.ts +1 -1
  30. package/common/httpClient.test.ts +91 -0
  31. package/common/isValidDate.ts +3 -0
  32. package/common/objectPath.test.ts +108 -0
  33. package/common/routeConvention.test.ts +132 -0
  34. package/common/runtimeConfig.test.ts +84 -0
  35. package/constant/constant.test.ts +374 -0
  36. package/constant/fieldInfo.ts +3 -3
  37. package/constant/purify.ts +2 -1
  38. package/constant/types.ts +4 -0
  39. package/constant/via.ts +12 -6
  40. package/dictionary/dictionary.test.ts +352 -0
  41. package/document/databaseRegistry.ts +8 -0
  42. package/document/document.test.ts +698 -0
  43. package/document/into.ts +1 -0
  44. package/fetch/client/fetchClient.ts +6 -1
  45. package/fetch/client/httpClient.ts +2 -1
  46. package/fetch/fetch.test.ts +838 -0
  47. package/fetch/fetchType/appliedReturn.type.ts +1 -0
  48. package/fetch/fetchType/endpointFetch.type.ts +3 -0
  49. package/fetch/fetchType/sliceFetch.type.ts +8 -0
  50. package/fetch/requestStorage.ts +10 -2
  51. package/package.json +24 -67
  52. package/server/akanApp.test.ts +130 -0
  53. package/server/akanApp.ts +5 -2
  54. package/server/akanLib.ts +1 -0
  55. package/server/akanServer.test.ts +157 -0
  56. package/server/akanServer.ts +4 -3
  57. package/server/artifact/builderRpc.ts +2 -2
  58. package/server/artifact/ipcTypes.ts +4 -0
  59. package/server/artifact/routeClientCache.test.ts +265 -0
  60. package/server/artifact/routeSeedIndex.test.ts +56 -0
  61. package/server/artifact/routesManifest.test.ts +64 -0
  62. package/server/decorators.ts +1 -1
  63. package/server/di/diLifecycle.contract.test.ts +168 -0
  64. package/server/di/diLifecycle.ts +6 -3
  65. package/server/hmr/clientScript.ts +20 -2
  66. package/server/hmr/devHmrController.ts +4 -0
  67. package/server/logging/rotatingLogWriter.test.ts +119 -0
  68. package/server/processMetrics.test.ts +24 -0
  69. package/server/processMetricsCollector.ts +1 -1
  70. package/server/proxy/webProxyRunner.test.ts +66 -0
  71. package/server/resolver/database.resolver.ts +2 -2
  72. package/server/resolver/resolver.contract.fixture.ts +1 -0
  73. package/server/resolver/resolver.contract.test.ts +594 -0
  74. package/server/resolver/signal.resolver.ts +10 -2
  75. package/server/robots.test.ts +16 -0
  76. package/server/routeTree.test.tsx +198 -0
  77. package/server/routing/apiRouter.test.ts +136 -0
  78. package/server/routing/apiRouter.ts +4 -2
  79. package/server/rscClient.tsx +7 -1
  80. package/server/rscWorkerHost.ts +33 -11
  81. package/server/sitemap.test.ts +61 -0
  82. package/server/ssrFromRscRenderer.tsx +35 -3
  83. package/server/systemPages.test.tsx +93 -0
  84. package/server/types/react-server-dom-webpack.d.ts +7 -1
  85. package/server/vendor/react-dom-client.ts +1 -1
  86. package/server/vendor/react-dom.ts +3 -2
  87. package/server/vendor/react-jsx-dev-runtime.ts +1 -1
  88. package/server/vendor/react-jsx-runtime.ts +1 -1
  89. package/server/vendor/react-refresh-runtime.ts +2 -2
  90. package/server/vendor/react-server-dom-webpack-client-browser.ts +1 -1
  91. package/server/vendor/react.ts +9 -2
  92. package/server/vendor/scheduler.ts +3 -2
  93. package/server/webRouter.test.ts +49 -0
  94. package/server/webRouter.ts +3 -2
  95. package/service/adapt.ts +5 -1
  96. package/service/predefinedAdaptor/cache.adaptor.ts +2 -1
  97. package/service/predefinedAdaptor/compress.adaptor.test.ts +184 -0
  98. package/service/predefinedAdaptor/database.adaptor.ts +2 -2
  99. package/service/predefinedAdaptor/solidCache.adaptor.test.ts +107 -0
  100. package/service/predefinedAdaptor/solidSqlite.test.ts +457 -0
  101. package/service/predefinedAdaptor/solidSqlite.ts +2 -1
  102. package/service/predefinedAdaptor/websocket.adaptor.ts +15 -3
  103. package/service/serve.ts +7 -3
  104. package/service/service.test.ts +732 -0
  105. package/signal/base.signal.ts +1 -0
  106. package/signal/endpointInfo.ts +7 -0
  107. package/signal/intercept.ts +2 -0
  108. package/signal/middleware.ts +2 -1
  109. package/signal/serverSignal.ts +15 -1
  110. package/signal/signal.test.ts +892 -0
  111. package/signal/signalContext.ts +1 -1
  112. package/signal/signalRegistry.ts +5 -0
  113. package/signal/sliceInfo.ts +3 -0
  114. package/signal/trace.ts +11 -0
  115. package/signal/types.ts +11 -2
  116. package/store/action.ts +5 -3
  117. package/store/stateBuilder.test.ts +168 -0
  118. package/store/stateBuilder.ts +2 -0
  119. package/store/stateInfo.ts +2 -1
  120. package/store/store.test.ts +427 -0
  121. package/store/types.ts +1 -1
  122. package/test/playwright.config.base.ts +28 -5
  123. package/test/playwright.pageAgent.ts +1 -1
  124. package/test/sampleOf.ts +1 -1
  125. package/test/testServer.ts +1 -1
  126. package/tsconfig.json +5 -0
  127. package/ui/BottomSheet.tsx +1 -1
  128. package/ui/Clipboard.tsx +1 -1
  129. package/ui/Constant/schemaDoc.test.ts +113 -0
  130. package/ui/CsrImage.tsx +14 -3
  131. package/ui/Data/ListContainer.tsx +1 -1
  132. package/ui/Data/Pagination.tsx +1 -1
  133. package/ui/Data/QueryMaker.tsx +339 -0
  134. package/ui/Data/index.ts +1 -0
  135. package/ui/DatePicker.tsx +95 -1
  136. package/ui/Dialog/Modal.tsx +1 -1
  137. package/ui/DraggableList.tsx +5 -5
  138. package/ui/Field.tsx +3 -2
  139. package/ui/Image.tsx +3 -2
  140. package/ui/InfiniteScroll.test.tsx +155 -0
  141. package/ui/InfiniteScroll.tsx +1 -0
  142. package/ui/Input.tsx +8 -1
  143. package/ui/Layout/BottomTab.tsx +2 -2
  144. package/ui/Link/SsrLink.tsx +2 -1
  145. package/ui/Load/Page.tsx +1 -1
  146. package/ui/Load/PageCSR.tsx +1 -0
  147. package/ui/Load/Units.tsx +2 -1
  148. package/ui/Load/View.tsx +2 -1
  149. package/ui/Menu.tsx +8 -5
  150. package/ui/Model/EditModal.tsx +5 -2
  151. package/ui/Popconfirm.tsx +4 -2
  152. package/ui/ScreenNavigator.tsx +3 -2
  153. package/ui/Signal/Message.tsx +3 -2
  154. package/ui/Signal/PubSub.tsx +2 -0
  155. package/ui/Signal/Response.tsx +1 -1
  156. package/ui/Signal/WebSocket.tsx +11 -2
  157. package/ui/System/Client.tsx +41 -7
  158. package/ui/System/Common.test.ts +37 -0
  159. package/ui/System/Gtag.tsx +5 -2
  160. package/ui/System/Messages.tsx +2 -2
  161. package/ui/System/Reconnect.tsx +6 -5
  162. package/ui/System/Root.tsx +1 -0
  163. package/ui/System/SSR.tsx +7 -1
  164. package/ui/ToggleSelect.tsx +8 -3
  165. package/ui/Unauthorized.tsx +1 -1
  166. package/webkit/bootCsr.test.tsx +153 -0
  167. package/webkit/bootCsr.tsx +6 -3
  168. package/webkit/lazy.tsx +8 -1
  169. package/webkit/native.test.tsx +341 -0
  170. package/webkit/useCamera.tsx +1 -0
  171. package/webkit/useCodepush.tsx +9 -4
  172. package/webkit/useContact.tsx +1 -0
  173. package/webkit/useCsrValues.ts +10 -6
  174. package/webkit/useDebounce.ts +2 -2
  175. package/webkit/usePurchase.tsx +9 -5
  176. package/webkit/usePushNoti.tsx +1 -0
  177. package/webkit/webkit.test.tsx +531 -0
  178. package/types/base/base.d.ts +0 -53
  179. package/types/base/baseEnv.d.ts +0 -68
  180. package/types/base/index.d.ts +0 -6
  181. package/types/base/primitiveRegistry.d.ts +0 -134
  182. package/types/base/symbols.d.ts +0 -11
  183. package/types/base/types.d.ts +0 -68
  184. package/types/base/utils.d.ts +0 -4
  185. package/types/base.d.ts +0 -1
  186. package/types/capacitor.base.config.d.ts +0 -3
  187. package/types/client/capacitor.d.ts +0 -233
  188. package/types/client/clientRuntime.d.ts +0 -63
  189. package/types/client/cookie.d.ts +0 -33
  190. package/types/client/createFont.d.ts +0 -6
  191. package/types/client/csrTypes.d.ts +0 -262
  192. package/types/client/decorators.d.ts +0 -7
  193. package/types/client/device.d.ts +0 -41
  194. package/types/client/fetch.d.ts +0 -1
  195. package/types/client/index.d.ts +0 -14
  196. package/types/client/locale.d.ts +0 -5
  197. package/types/client/makePageProto.d.ts +0 -17002
  198. package/types/client/router.d.ts +0 -66
  199. package/types/client/rscNavigation.d.ts +0 -19
  200. package/types/client/storage.d.ts +0 -5
  201. package/types/client/translator.d.ts +0 -18
  202. package/types/client/types.d.ts +0 -145
  203. package/types/client/useClient.d.ts +0 -1
  204. package/types/client.d.ts +0 -1
  205. package/types/common/Logger.d.ts +0 -41
  206. package/types/common/applyMixins.d.ts +0 -3
  207. package/types/common/capitalize.d.ts +0 -2
  208. package/types/common/deepObjectify.d.ts +0 -4
  209. package/types/common/fileUpload.d.ts +0 -28
  210. package/types/common/formatNumber.d.ts +0 -1
  211. package/types/common/formatPhone.d.ts +0 -2
  212. package/types/common/getAllPropertyDescriptors.d.ts +0 -5
  213. package/types/common/hmrPhase.d.ts +0 -6
  214. package/types/common/httpClient.d.ts +0 -20
  215. package/types/common/index.d.ts +0 -29
  216. package/types/common/isDayjs.d.ts +0 -2
  217. package/types/common/isEmail.d.ts +0 -2
  218. package/types/common/isPhoneNumber.d.ts +0 -2
  219. package/types/common/isQueryEqual.d.ts +0 -1
  220. package/types/common/isValidDate.d.ts +0 -2
  221. package/types/common/jwtDecode.d.ts +0 -2
  222. package/types/common/localeConfig.d.ts +0 -11
  223. package/types/common/lowerlize.d.ts +0 -2
  224. package/types/common/mergeVersion.d.ts +0 -10
  225. package/types/common/objectify.d.ts +0 -1
  226. package/types/common/pathGet.d.ts +0 -1
  227. package/types/common/pathSet.d.ts +0 -3
  228. package/types/common/randomPick.d.ts +0 -1
  229. package/types/common/randomPicks.d.ts +0 -1
  230. package/types/common/routeConvention.d.ts +0 -35
  231. package/types/common/sleep.d.ts +0 -2
  232. package/types/common/splitVersion.d.ts +0 -11
  233. package/types/common/subRoute.d.ts +0 -7
  234. package/types/common/types.d.ts +0 -14
  235. package/types/common.d.ts +0 -1
  236. package/types/constant/constantRegistry.d.ts +0 -89
  237. package/types/constant/crystalize.d.ts +0 -4
  238. package/types/constant/deserialize.d.ts +0 -7
  239. package/types/constant/fieldInfo.d.ts +0 -153
  240. package/types/constant/getDefault.d.ts +0 -3
  241. package/types/constant/immerify.d.ts +0 -2
  242. package/types/constant/index.d.ts +0 -10
  243. package/types/constant/purify.d.ts +0 -12
  244. package/types/constant/serialize.d.ts +0 -11
  245. package/types/constant/types.d.ts +0 -77
  246. package/types/constant/via.d.ts +0 -52
  247. package/types/constant.d.ts +0 -1
  248. package/types/dictionary/base.dictionary.d.ts +0 -1
  249. package/types/dictionary/dictInfo.d.ts +0 -206
  250. package/types/dictionary/dictionary.d.ts +0 -11
  251. package/types/dictionary/index.d.ts +0 -4
  252. package/types/dictionary/locale.d.ts +0 -128
  253. package/types/dictionary/trans.d.ts +0 -82
  254. package/types/dictionary.d.ts +0 -1
  255. package/types/document/by.d.ts +0 -20
  256. package/types/document/dataLoader.d.ts +0 -36
  257. package/types/document/database.d.ts +0 -96
  258. package/types/document/databaseRegistry.d.ts +0 -36
  259. package/types/document/documentQuery.d.ts +0 -105
  260. package/types/document/documentSchema.d.ts +0 -33
  261. package/types/document/filterMeta.d.ts +0 -84
  262. package/types/document/index.d.ts +0 -11
  263. package/types/document/into.d.ts +0 -65
  264. package/types/document/loaderInfo.d.ts +0 -35
  265. package/types/document/schema.d.ts +0 -5
  266. package/types/document/types.d.ts +0 -36
  267. package/types/document.d.ts +0 -1
  268. package/types/fetch/client/fetchClient.d.ts +0 -78
  269. package/types/fetch/client/httpClient.d.ts +0 -39
  270. package/types/fetch/client/index.d.ts +0 -3
  271. package/types/fetch/client/wsClient.d.ts +0 -37
  272. package/types/fetch/client.d.ts +0 -1
  273. package/types/fetch/fetchType/appliedReturn.type.d.ts +0 -67
  274. package/types/fetch/fetchType/buildFetch.type.d.ts +0 -11
  275. package/types/fetch/fetchType/clientSignal.type.d.ts +0 -16
  276. package/types/fetch/fetchType/endpointFetch.type.d.ts +0 -29
  277. package/types/fetch/fetchType/index.d.ts +0 -5
  278. package/types/fetch/fetchType/sliceFetch.type.d.ts +0 -76
  279. package/types/fetch/fetchType.d.ts +0 -1
  280. package/types/fetch/index.d.ts +0 -4
  281. package/types/fetch/requestStorage.d.ts +0 -29
  282. package/types/fetch/serializer/fetch.serializer.d.ts +0 -14
  283. package/types/fetch/serializer/index.d.ts +0 -1
  284. package/types/fetch/serializer.d.ts +0 -1
  285. package/types/fetch/types.d.ts +0 -19
  286. package/types/fetch.d.ts +0 -1
  287. package/types/index.d.ts +0 -213
  288. package/types/server/akanApp.d.ts +0 -17
  289. package/types/server/akanAppHeaders.d.ts +0 -1
  290. package/types/server/akanLib.d.ts +0 -33
  291. package/types/server/akanOption.d.ts +0 -15
  292. package/types/server/akanServer.d.ts +0 -47
  293. package/types/server/artifact/builderRpc.d.ts +0 -42
  294. package/types/server/artifact/index.d.ts +0 -6
  295. package/types/server/artifact/ipcTypes.d.ts +0 -73
  296. package/types/server/artifact/manifestTypes.d.ts +0 -16
  297. package/types/server/artifact/routeClientCache.d.ts +0 -45
  298. package/types/server/artifact/routeSeedIndexStore.d.ts +0 -43
  299. package/types/server/artifact/routesManifestStore.d.ts +0 -16
  300. package/types/server/artifact.d.ts +0 -1
  301. package/types/server/decorators.d.ts +0 -6
  302. package/types/server/di/diLifecycle.d.ts +0 -45
  303. package/types/server/di/index.d.ts +0 -4
  304. package/types/server/di/predefinedAdaptor.d.ts +0 -33
  305. package/types/server/di/resolveAdaptorHierarchy.d.ts +0 -21
  306. package/types/server/di/resolveHierarchy.d.ts +0 -11
  307. package/types/server/di/resolveServiceHierarchy.d.ts +0 -13
  308. package/types/server/di/utils.d.ts +0 -14
  309. package/types/server/di.d.ts +0 -1
  310. package/types/server/hmr/changeBatch.d.ts +0 -13
  311. package/types/server/hmr/clientScript.d.ts +0 -1
  312. package/types/server/hmr/devHmrController.d.ts +0 -24
  313. package/types/server/hmr/index.d.ts +0 -4
  314. package/types/server/hmr/wsHub.d.ts +0 -45
  315. package/types/server/hmr.d.ts +0 -1
  316. package/types/server/imageOptimizer.d.ts +0 -12
  317. package/types/server/imageOptimizerError.d.ts +0 -4
  318. package/types/server/index.d.ts +0 -14
  319. package/types/server/lifecycle/shutdownManager.d.ts +0 -13
  320. package/types/server/logging/rotatingLogWriter.d.ts +0 -20
  321. package/types/server/processMetricsCollector.d.ts +0 -10
  322. package/types/server/proxy/akanResponse.d.ts +0 -7
  323. package/types/server/proxy/bunRequestFields.d.ts +0 -1
  324. package/types/server/proxy/hostBasePathWebProxy.d.ts +0 -6
  325. package/types/server/proxy/index.d.ts +0 -6
  326. package/types/server/proxy/localeWebProxy.d.ts +0 -5
  327. package/types/server/proxy/types.d.ts +0 -37
  328. package/types/server/proxy/webProxyRunner.d.ts +0 -7
  329. package/types/server/proxy.d.ts +0 -1
  330. package/types/server/resolver/database.resolver.d.ts +0 -6
  331. package/types/server/resolver/index.d.ts +0 -3
  332. package/types/server/resolver/service.resolver.d.ts +0 -7
  333. package/types/server/resolver/signal.resolver.d.ts +0 -29
  334. package/types/server/resolver.d.ts +0 -1
  335. package/types/server/robots.d.ts +0 -1
  336. package/types/server/routeElementComposer.d.ts +0 -41
  337. package/types/server/routeTreeBuilder.d.ts +0 -28
  338. package/types/server/routing/apiRouter.d.ts +0 -61
  339. package/types/server/rscClient.d.ts +0 -15
  340. package/types/server/rscWorker.d.ts +0 -3
  341. package/types/server/rscWorkerHost.d.ts +0 -83
  342. package/types/server/sitemap.d.ts +0 -13
  343. package/types/server/ssrFromRscRenderer.d.ts +0 -6
  344. package/types/server/ssrTypes.d.ts +0 -47
  345. package/types/server/systemPages.d.ts +0 -27
  346. package/types/server/types/react-server-dom-webpack.d.ts +0 -91
  347. package/types/server/types.d.ts +0 -67
  348. package/types/server/vendor/akanjs-base.d.ts +0 -1
  349. package/types/server/vendor/akanjs-common.d.ts +0 -1
  350. package/types/server/vendor/akanjs-constant.d.ts +0 -1
  351. package/types/server/vendor/akanjs-store.d.ts +0 -1
  352. package/types/server/vendor/react-dom-client.d.ts +0 -3
  353. package/types/server/vendor/react-dom.d.ts +0 -3
  354. package/types/server/vendor/react-jsx-dev-runtime.d.ts +0 -3
  355. package/types/server/vendor/react-jsx-runtime.d.ts +0 -3
  356. package/types/server/vendor/react-refresh-runtime.d.ts +0 -3
  357. package/types/server/vendor/react-server-dom-webpack-client-browser.d.ts +0 -3
  358. package/types/server/vendor/react.d.ts +0 -11
  359. package/types/server/vendor/scheduler.d.ts +0 -3
  360. package/types/server/webRouter.d.ts +0 -44
  361. package/types/server.d.ts +0 -1
  362. package/types/service/adapt.d.ts +0 -15
  363. package/types/service/base.service.d.ts +0 -18
  364. package/types/service/index.d.ts +0 -10
  365. package/types/service/injectInfo.d.ts +0 -102
  366. package/types/service/ipcTypes.d.ts +0 -194
  367. package/types/service/predefinedAdaptor/cache.adaptor.d.ts +0 -46
  368. package/types/service/predefinedAdaptor/compress.adaptor.d.ts +0 -22
  369. package/types/service/predefinedAdaptor/database.adaptor.d.ts +0 -329
  370. package/types/service/predefinedAdaptor/index.d.ts +0 -13
  371. package/types/service/predefinedAdaptor/logging.adaptor.d.ts +0 -20
  372. package/types/service/predefinedAdaptor/queue.adaptor.d.ts +0 -22
  373. package/types/service/predefinedAdaptor/role.adaptor.d.ts +0 -17
  374. package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +0 -60
  375. package/types/service/predefinedAdaptor/solidCache.adaptor.d.ts +0 -25
  376. package/types/service/predefinedAdaptor/solidPubsub.adaptor.d.ts +0 -20
  377. package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +0 -19
  378. package/types/service/predefinedAdaptor/solidSqlite.d.ts +0 -24
  379. package/types/service/predefinedAdaptor/sqlitePath.d.ts +0 -9
  380. package/types/service/predefinedAdaptor/storage.adaptor.d.ts +0 -80
  381. package/types/service/predefinedAdaptor/websocket.adaptor.d.ts +0 -49
  382. package/types/service/predefinedAdaptor.d.ts +0 -1
  383. package/types/service/serve.d.ts +0 -31
  384. package/types/service/serviceModule.d.ts +0 -50
  385. package/types/service/serviceRegistry.d.ts +0 -9
  386. package/types/service/types.d.ts +0 -55
  387. package/types/service.d.ts +0 -1
  388. package/types/signal/base.signal.d.ts +0 -41
  389. package/types/signal/endpoint.d.ts +0 -28
  390. package/types/signal/endpointInfo.d.ts +0 -77
  391. package/types/signal/exception.d.ts +0 -54786
  392. package/types/signal/guard.d.ts +0 -10
  393. package/types/signal/guards.d.ts +0 -10
  394. package/types/signal/index.d.ts +0 -19
  395. package/types/signal/intercept.d.ts +0 -17
  396. package/types/signal/internal.d.ts +0 -18
  397. package/types/signal/internalArg.d.ts +0 -31
  398. package/types/signal/internalInfo.d.ts +0 -45
  399. package/types/signal/middleware.d.ts +0 -51
  400. package/types/signal/serializer/fetch.serializer.d.ts +0 -14
  401. package/types/signal/serializer/index.d.ts +0 -1
  402. package/types/signal/serializer.d.ts +0 -1
  403. package/types/signal/serverSignal.d.ts +0 -36
  404. package/types/signal/signalContext.d.ts +0 -96
  405. package/types/signal/signalRegistry.d.ts +0 -49
  406. package/types/signal/slice.d.ts +0 -42
  407. package/types/signal/sliceInfo.d.ts +0 -51
  408. package/types/signal/trace.d.ts +0 -97
  409. package/types/signal/types.d.ts +0 -142
  410. package/types/signal.d.ts +0 -1
  411. package/types/store/action.d.ts +0 -145
  412. package/types/store/baseSt.d.ts +0 -412
  413. package/types/store/hooks.d.ts +0 -1
  414. package/types/store/index.d.ts +0 -8
  415. package/types/store/rootStore.d.ts +0 -22
  416. package/types/store/state.d.ts +0 -91
  417. package/types/store/stateBuilder.d.ts +0 -141
  418. package/types/store/stateInfo.d.ts +0 -23
  419. package/types/store/store.d.ts +0 -36
  420. package/types/store/storeInstance.d.ts +0 -38
  421. package/types/store/storeRegistry.d.ts +0 -13
  422. package/types/store/types.d.ts +0 -42
  423. package/types/store/withSelector.d.ts +0 -42
  424. package/types/store.d.ts +0 -1
  425. package/types/test/index.d.ts +0 -4
  426. package/types/test/playwright.config.base.d.ts +0 -9
  427. package/types/test/playwright.pageAgent.d.ts +0 -12
  428. package/types/test/sample.d.ts +0 -15
  429. package/types/test/sampleOf.d.ts +0 -5
  430. package/types/test/signalTest.preload.d.ts +0 -1
  431. package/types/test/signalTestRuntime.d.ts +0 -29
  432. package/types/test/testServer.d.ts +0 -26
  433. package/types/test.d.ts +0 -1
  434. package/types/ui/BottomSheet.d.ts +0 -13
  435. package/types/ui/Button.d.ts +0 -11
  436. package/types/ui/ClientSide.d.ts +0 -8
  437. package/types/ui/Clipboard.d.ts +0 -7
  438. package/types/ui/Constant/Doc.d.ts +0 -29
  439. package/types/ui/Constant/Mermaid.d.ts +0 -8
  440. package/types/ui/Constant/index.d.ts +0 -6
  441. package/types/ui/Constant/schemaDoc.d.ts +0 -84
  442. package/types/ui/Constant.d.ts +0 -1
  443. package/types/ui/Copy.d.ts +0 -10
  444. package/types/ui/CsrImage.d.ts +0 -18
  445. package/types/ui/Data/CardList.d.ts +0 -36
  446. package/types/ui/Data/Dashboard.d.ts +0 -11
  447. package/types/ui/Data/Insight.d.ts +0 -9
  448. package/types/ui/Data/Item.d.ts +0 -75
  449. package/types/ui/Data/ListContainer.d.ts +0 -49
  450. package/types/ui/Data/Pagination.d.ts +0 -9
  451. package/types/ui/Data/QueryMaker.d.ts +0 -8
  452. package/types/ui/Data/TableList.d.ts +0 -26
  453. package/types/ui/Data/index.d.ts +0 -9
  454. package/types/ui/Data/index_.d.ts +0 -8
  455. package/types/ui/Data.d.ts +0 -1
  456. package/types/ui/DatePicker.d.ts +0 -36
  457. package/types/ui/Dialog/Action.d.ts +0 -5
  458. package/types/ui/Dialog/Close.d.ts +0 -6
  459. package/types/ui/Dialog/Content.d.ts +0 -6
  460. package/types/ui/Dialog/Modal.d.ts +0 -9
  461. package/types/ui/Dialog/Provider.d.ts +0 -11
  462. package/types/ui/Dialog/Title.d.ts +0 -5
  463. package/types/ui/Dialog/Trigger.d.ts +0 -6
  464. package/types/ui/Dialog/context.d.ts +0 -10
  465. package/types/ui/Dialog/index.d.ts +0 -9
  466. package/types/ui/Dialog.d.ts +0 -1
  467. package/types/ui/DragAction.d.ts +0 -24
  468. package/types/ui/DraggableList.d.ts +0 -31
  469. package/types/ui/Dropdown.d.ts +0 -14
  470. package/types/ui/Empty.d.ts +0 -12
  471. package/types/ui/Field.d.ts +0 -411
  472. package/types/ui/FontFace.d.ts +0 -6
  473. package/types/ui/Image.d.ts +0 -49
  474. package/types/ui/InfiniteScroll.d.ts +0 -10
  475. package/types/ui/Input.d.ts +0 -95
  476. package/types/ui/KeyboardAvoiding.d.ts +0 -8
  477. package/types/ui/Layout/BottomAction.d.ts +0 -6
  478. package/types/ui/Layout/BottomInset.d.ts +0 -7
  479. package/types/ui/Layout/BottomTab.d.ts +0 -14
  480. package/types/ui/Layout/Header.d.ts +0 -8
  481. package/types/ui/Layout/LeftSider.d.ts +0 -9
  482. package/types/ui/Layout/Navbar.d.ts +0 -11
  483. package/types/ui/Layout/RightSider.d.ts +0 -10
  484. package/types/ui/Layout/Sider.d.ts +0 -7
  485. package/types/ui/Layout/Template.d.ts +0 -7
  486. package/types/ui/Layout/TopLeftAction.d.ts +0 -6
  487. package/types/ui/Layout/Unit.d.ts +0 -9
  488. package/types/ui/Layout/View.d.ts +0 -8
  489. package/types/ui/Layout/Zone.d.ts +0 -6
  490. package/types/ui/Layout/index.d.ts +0 -14
  491. package/types/ui/Layout.d.ts +0 -1
  492. package/types/ui/Link/Back.d.ts +0 -7
  493. package/types/ui/Link/Close.d.ts +0 -7
  494. package/types/ui/Link/CsrLink.d.ts +0 -2
  495. package/types/ui/Link/Lang.d.ts +0 -8
  496. package/types/ui/Link/SsrLink.d.ts +0 -2
  497. package/types/ui/Link/index.d.ts +0 -10
  498. package/types/ui/Link/types.d.ts +0 -42
  499. package/types/ui/Link.d.ts +0 -1
  500. package/types/ui/Load/Edit.d.ts +0 -4
  501. package/types/ui/Load/Edit_Client.d.ts +0 -27
  502. package/types/ui/Load/Page.d.ts +0 -15
  503. package/types/ui/Load/PageCSR.d.ts +0 -3
  504. package/types/ui/Load/Pagination.d.ts +0 -8
  505. package/types/ui/Load/Units.d.ts +0 -30
  506. package/types/ui/Load/View.d.ts +0 -22
  507. package/types/ui/Load/index.d.ts +0 -8
  508. package/types/ui/Load/index_.d.ts +0 -3
  509. package/types/ui/Load.d.ts +0 -1
  510. package/types/ui/Loading/Area.d.ts +0 -1
  511. package/types/ui/Loading/Button.d.ts +0 -7
  512. package/types/ui/Loading/Input.d.ts +0 -7
  513. package/types/ui/Loading/ProgressBar.d.ts +0 -6
  514. package/types/ui/Loading/Skeleton.d.ts +0 -7
  515. package/types/ui/Loading/Spin.d.ts +0 -7
  516. package/types/ui/Loading/index.d.ts +0 -8
  517. package/types/ui/Loading.d.ts +0 -1
  518. package/types/ui/Menu.d.ts +0 -26
  519. package/types/ui/Modal.d.ts +0 -19
  520. package/types/ui/Model/AdminPanel.d.ts +0 -31
  521. package/types/ui/Model/Edit.d.ts +0 -16
  522. package/types/ui/Model/EditModal.d.ts +0 -52
  523. package/types/ui/Model/EditWrapper.d.ts +0 -13
  524. package/types/ui/Model/LoadInit.d.ts +0 -10
  525. package/types/ui/Model/New.d.ts +0 -16
  526. package/types/ui/Model/NewWrapper.d.ts +0 -13
  527. package/types/ui/Model/NewWrapper_Client.d.ts +0 -13
  528. package/types/ui/Model/Remove.d.ts +0 -13
  529. package/types/ui/Model/RemoveWrapper.d.ts +0 -12
  530. package/types/ui/Model/SureToRemove.d.ts +0 -11
  531. package/types/ui/Model/View.d.ts +0 -19
  532. package/types/ui/Model/ViewEditModal.d.ts +0 -12
  533. package/types/ui/Model/ViewModal.d.ts +0 -14
  534. package/types/ui/Model/ViewWrapper.d.ts +0 -12
  535. package/types/ui/Model/index.d.ts +0 -16
  536. package/types/ui/Model/index_.d.ts +0 -14
  537. package/types/ui/Model.d.ts +0 -1
  538. package/types/ui/More.d.ts +0 -12
  539. package/types/ui/ObjectId.d.ts +0 -5
  540. package/types/ui/Pagination.d.ts +0 -20
  541. package/types/ui/Popconfirm.d.ts +0 -28
  542. package/types/ui/Portal.d.ts +0 -6
  543. package/types/ui/Radio.d.ts +0 -19
  544. package/types/ui/RecentTime.d.ts +0 -12
  545. package/types/ui/Refresh.d.ts +0 -7
  546. package/types/ui/ScreenNavigator.d.ts +0 -18
  547. package/types/ui/Select.d.ts +0 -43
  548. package/types/ui/Signal/Arg.d.ts +0 -78
  549. package/types/ui/Signal/Doc.d.ts +0 -33
  550. package/types/ui/Signal/Listener.d.ts +0 -9
  551. package/types/ui/Signal/Message.d.ts +0 -23
  552. package/types/ui/Signal/Object.d.ts +0 -20
  553. package/types/ui/Signal/PubSub.d.ts +0 -24
  554. package/types/ui/Signal/Request.d.ts +0 -8
  555. package/types/ui/Signal/Response.d.ts +0 -14
  556. package/types/ui/Signal/RestApi.d.ts +0 -40
  557. package/types/ui/Signal/WebSocket.d.ts +0 -11
  558. package/types/ui/Signal/index.d.ts +0 -18
  559. package/types/ui/Signal/makeExample.d.ts +0 -4
  560. package/types/ui/Signal/style.d.ts +0 -15
  561. package/types/ui/Signal.d.ts +0 -1
  562. package/types/ui/System/CSR.d.ts +0 -32
  563. package/types/ui/System/Client.d.ts +0 -47
  564. package/types/ui/System/Common.d.ts +0 -47
  565. package/types/ui/System/DevModeToggle.d.ts +0 -1
  566. package/types/ui/System/Gtag.d.ts +0 -4
  567. package/types/ui/System/Messages.d.ts +0 -1
  568. package/types/ui/System/Reconnect.d.ts +0 -1
  569. package/types/ui/System/Root.d.ts +0 -6
  570. package/types/ui/System/SSR.d.ts +0 -24
  571. package/types/ui/System/SelectLanguage.d.ts +0 -5
  572. package/types/ui/System/ThemeToggle.d.ts +0 -4
  573. package/types/ui/System/index.d.ts +0 -12
  574. package/types/ui/System.d.ts +0 -1
  575. package/types/ui/Tab/Menu.d.ts +0 -12
  576. package/types/ui/Tab/Menus.d.ts +0 -6
  577. package/types/ui/Tab/Panel.d.ts +0 -8
  578. package/types/ui/Tab/Provider.d.ts +0 -10
  579. package/types/ui/Tab/context.d.ts +0 -9
  580. package/types/ui/Tab/index.d.ts +0 -7
  581. package/types/ui/Tab.d.ts +0 -1
  582. package/types/ui/Table.d.ts +0 -41
  583. package/types/ui/ToggleSelect.d.ts +0 -33
  584. package/types/ui/Unauthorized.d.ts +0 -9
  585. package/types/ui/animated.d.ts +0 -5
  586. package/types/ui/fontCss.d.ts +0 -11
  587. package/types/ui/index.d.ts +0 -44
  588. package/types/ui.d.ts +0 -1
  589. package/types/webkit/bootCsr.d.ts +0 -16
  590. package/types/webkit/createRobotPage.d.ts +0 -15
  591. package/types/webkit/createSitemapPage.d.ts +0 -4
  592. package/types/webkit/index.d.ts +0 -17
  593. package/types/webkit/lazy.d.ts +0 -11
  594. package/types/webkit/types.d.ts +0 -7
  595. package/types/webkit/useCamera.d.ts +0 -19
  596. package/types/webkit/useCodepush.d.ts +0 -16
  597. package/types/webkit/useContact.d.ts +0 -11
  598. package/types/webkit/useCsrValues.d.ts +0 -30
  599. package/types/webkit/useDebounce.d.ts +0 -2
  600. package/types/webkit/useFetch.d.ts +0 -18
  601. package/types/webkit/useGeoLocation.d.ts +0 -8
  602. package/types/webkit/useHistory.d.ts +0 -23
  603. package/types/webkit/useInterval.d.ts +0 -2
  604. package/types/webkit/useLocation.d.ts +0 -8
  605. package/types/webkit/usePurchase.d.ts +0 -19
  606. package/types/webkit/usePushNoti.d.ts +0 -7
  607. package/types/webkit/useThrottle.d.ts +0 -2
  608. package/types/webkit.d.ts +0 -1
@@ -0,0 +1,198 @@
1
+ import type { ReactNode } from "react";
2
+ import { renderToReadableStream } from "react-dom/server.browser";
3
+ import { RouteElementComposer } from "./routeElementComposer";
4
+ import { RouteTreeBuilder } from "./routeTreeBuilder";
5
+
6
+ async function renderToText(node: ReactNode): Promise<string> {
7
+ return new Response(await renderToReadableStream(node)).text();
8
+ }
9
+
10
+ describe("RouteTreeBuilder implicit locale", () => {
11
+ test("matches locale-prefixed routes while keeping special routes at root", () => {
12
+ const routes = new RouteTreeBuilder({
13
+ "./__root_layout.tsx": async () => ({ default: ({ children }: { children: ReactNode }) => children }),
14
+ "./foo.tsx": async () => ({ default: () => null }),
15
+ "./robots.txt.tsx": async () => ({ default: () => null }),
16
+ }).build();
17
+
18
+ const matched = RouteTreeBuilder.match("/ko/foo", routes);
19
+ expect(matched?.params).toEqual({ lang: "ko" });
20
+ expect(matched?.pathRoute.path).toBe("/:lang/foo");
21
+ expect(matched?.pathRoute.renderRootLayouts).toHaveLength(1);
22
+
23
+ const robots = RouteTreeBuilder.match("/robots.txt", routes);
24
+ expect(robots?.params).toEqual({});
25
+ expect(robots?.pathRoute.isSpecialRoute).toBe(true);
26
+ expect(robots?.pathRoute.renderRootLayouts).toHaveLength(0);
27
+ });
28
+
29
+ test("uses the nearest route head without merging parents", async () => {
30
+ const prevBasePaths = process.env.AKAN_PUBLIC_BASE_PATHS;
31
+ process.env.AKAN_PUBLIC_BASE_PATHS = "foo";
32
+ try {
33
+ const routes = new RouteTreeBuilder({
34
+ "./__root_layout.tsx": async () => ({
35
+ default: ({ children }: { children: ReactNode }) => children,
36
+ head: "root",
37
+ }),
38
+ "./foo/__root_layout.tsx": async () => ({
39
+ default: ({ children }: { children: ReactNode }) => children,
40
+ head: "foo-root",
41
+ }),
42
+ "./foo/bar.tsx": async () => ({ default: () => null }),
43
+ "./foo/baz.tsx": async () => ({ default: () => null, head: "baz-page" }),
44
+ }).build();
45
+
46
+ const bar = RouteTreeBuilder.match("/ko/foo/bar", routes);
47
+ const baz = RouteTreeBuilder.match("/ko/foo/baz", routes);
48
+ expect(
49
+ bar &&
50
+ (await RouteElementComposer.resolveHead({ pathRoute: bar.pathRoute, params: bar.params, searchParams: {} })),
51
+ ).toBe("foo-root");
52
+ expect(
53
+ baz &&
54
+ (await RouteElementComposer.resolveHead({ pathRoute: baz.pathRoute, params: baz.params, searchParams: {} })),
55
+ ).toBe("baz-page");
56
+ } finally {
57
+ process.env.AKAN_PUBLIC_BASE_PATHS = prevBasePaths;
58
+ }
59
+ });
60
+
61
+ test("supports route groups, repeated search params, and cached lazy modules", async () => {
62
+ let loadCount = 0;
63
+ const routes = new RouteTreeBuilder({
64
+ "./__root_layout.tsx": async () => ({ default: ({ children }: { children: ReactNode }) => children }),
65
+ "./(marketing)/about.tsx": async () => {
66
+ loadCount += 1;
67
+ return { default: () => null, head: "about" };
68
+ },
69
+ }).build();
70
+ const matched = RouteTreeBuilder.match("/ko/about", routes);
71
+
72
+ expect(matched?.pathRoute.path).toBe("/:lang/about");
73
+ expect(RouteTreeBuilder.parseSearchParams("?tag=a&tag=b&sort=latest")).toEqual({
74
+ tag: ["a", "b"],
75
+ sort: "latest",
76
+ });
77
+
78
+ expect(
79
+ matched &&
80
+ (await RouteElementComposer.resolveHead({
81
+ pathRoute: matched.pathRoute,
82
+ params: matched.params,
83
+ searchParams: {},
84
+ })),
85
+ ).toBe("about");
86
+ expect(
87
+ matched &&
88
+ (await RouteElementComposer.resolveHead({
89
+ pathRoute: matched.pathRoute,
90
+ params: matched.params,
91
+ searchParams: {},
92
+ })),
93
+ ).toBe("about");
94
+ expect(loadCount).toBe(1);
95
+ expect(RouteTreeBuilder.getCacheStats()).toMatchObject({
96
+ moduleCount: 2,
97
+ loadedModuleCount: 1,
98
+ cacheHits: 1,
99
+ cacheMisses: 1,
100
+ });
101
+ });
102
+
103
+ test("rejects duplicate route patterns and unsupported page exports", () => {
104
+ expect(() =>
105
+ new RouteTreeBuilder({
106
+ "./users/[id].tsx": async () => ({ default: () => null }),
107
+ "./users/:id.tsx": async () => ({ default: () => null }),
108
+ }).build(),
109
+ ).toThrow();
110
+
111
+ const routes = new RouteTreeBuilder({
112
+ "./bad.tsx": async () => ({ default: () => null, loader: () => null }) as never,
113
+ }).build();
114
+ const matched = RouteTreeBuilder.match("/ko/bad", routes);
115
+
116
+ expect(
117
+ matched &&
118
+ RouteElementComposer.resolveHead({ pathRoute: matched.pathRoute, params: matched.params, searchParams: {} }),
119
+ ).rejects.toThrow('[route-convention] unsupported export "loader"');
120
+
121
+ const routesWithBadFallback = new RouteTreeBuilder({
122
+ "./bad-fallback.tsx": async () => ({ default: () => null, NotFound: () => null }) as never,
123
+ }).build();
124
+ const badFallback = RouteTreeBuilder.match("/ko/bad-fallback", routesWithBadFallback);
125
+ expect(
126
+ badFallback &&
127
+ RouteElementComposer.resolveHead({
128
+ pathRoute: badFallback.pathRoute,
129
+ params: badFallback.params,
130
+ searchParams: {},
131
+ }),
132
+ ).rejects.toThrow('[route-convention] unsupported export "NotFound"');
133
+ });
134
+
135
+ test("composes nearest layout NotFound and Error fallbacks", async () => {
136
+ const builder = new RouteTreeBuilder({
137
+ "./__root_layout.tsx": async () => ({
138
+ default: ({ children }: { children: ReactNode }) => <main>root:{children}</main>,
139
+ NotFound: ({ pathname }: { pathname: string }) => <p>root missing {pathname}</p>,
140
+ }),
141
+ "./docs/_layout.tsx": async () => ({
142
+ default: ({ children }: { children: ReactNode }) => <section>docs:{children}</section>,
143
+ NotFound: ({ pathname, params }: { pathname: string; params: Record<string, string> }) => (
144
+ <p>
145
+ docs missing {params.lang}:{pathname}
146
+ </p>
147
+ ),
148
+ Error: ({ error }: { error?: unknown }) => (
149
+ <p>docs error {error instanceof Error ? error.message : "unknown"}</p>
150
+ ),
151
+ }),
152
+ "./docs/guide.tsx": async () => ({ default: () => <article>guide</article> }),
153
+ });
154
+ const routes = builder.build();
155
+ const matched = RouteTreeBuilder.match("/ko/docs/guide", routes);
156
+ if (!matched) throw new Error("route did not match");
157
+
158
+ const notFound = await RouteElementComposer.composeFallback({
159
+ kind: "not-found",
160
+ route: matched.pathRoute,
161
+ params: matched.params,
162
+ searchParams: {},
163
+ pathname: "/ko/docs/guide",
164
+ });
165
+ const error = await RouteElementComposer.composeFallback({
166
+ kind: "error",
167
+ route: matched.pathRoute,
168
+ params: matched.params,
169
+ searchParams: {},
170
+ pathname: "/ko/docs/guide",
171
+ error: new Error("boom"),
172
+ });
173
+
174
+ const notFoundHtml = await renderToText(notFound);
175
+ const errorHtml = await renderToText(error);
176
+ expect(notFoundHtml).toContain("root:");
177
+ expect(notFoundHtml).toContain("docs:");
178
+ expect(notFoundHtml).toContain("docs missing");
179
+ expect(notFoundHtml).toContain("/ko/docs/guide");
180
+ expect(errorHtml).toContain("docs error");
181
+ expect(errorHtml).toContain("boom");
182
+
183
+ const unmatched = RouteTreeBuilder.matchFallback("/ko/docs/missing/path", builder.getFallbackRoutes());
184
+ expect(unmatched?.fallbackRoute.path).toBe("/:lang/docs");
185
+ const unmatchedNotFound =
186
+ unmatched &&
187
+ (await RouteElementComposer.composeFallback({
188
+ kind: "not-found",
189
+ route: unmatched.fallbackRoute,
190
+ params: unmatched.params,
191
+ searchParams: {},
192
+ pathname: "/ko/docs/missing/path",
193
+ }));
194
+ const unmatchedHtml = await renderToText(unmatchedNotFound);
195
+ expect(unmatchedHtml).toContain("docs missing");
196
+ expect(unmatchedHtml).toContain("/ko/docs/missing/path");
197
+ });
198
+ });
@@ -0,0 +1,136 @@
1
+ import { getDefaultInjectRegistry } from "akanjs/service";
2
+ import { AkanResponse, WebProxyRunner } from "../proxy";
3
+ import type { HttpRoutes, WebsocketRoutes } from "../types";
4
+
5
+ describe("ApiRouter.buildRoutes", () => {
6
+ test("keeps the global prefix by default", async () => {
7
+ process.env.AKAN_PUBLIC_APP_NAME = "test";
8
+ const { ApiRouter } = await import("./apiRouter");
9
+ const routes = ApiRouter.buildRoutes({
10
+ prefix: "/api",
11
+ websocketPrefix: "/ws",
12
+ routes: { "/admin/ping": () => new Response("ok") } as HttpRoutes,
13
+ renderEnvRoutes: {},
14
+ upgradeAppWs: () => false,
15
+ });
16
+
17
+ expect(Object.keys(routes)).toContain("/api/admin/ping");
18
+ });
19
+
20
+ test("allows selected endpoints to skip the global prefix", async () => {
21
+ process.env.AKAN_PUBLIC_APP_NAME = "test";
22
+ const { ApiRouter } = await import("./apiRouter");
23
+ const routes = ApiRouter.buildRoutes({
24
+ prefix: "/api",
25
+ websocketPrefix: "/ws",
26
+ routes: { "/sitemap.xml": () => new Response("ok") } as HttpRoutes,
27
+ routeOptions: { "/sitemap.xml": { globalPrefix: false } },
28
+ renderEnvRoutes: { "/*": () => new Response("fallback") } as HttpRoutes,
29
+ upgradeAppWs: () => false,
30
+ });
31
+
32
+ expect(Object.keys(routes)).toContain("/sitemap.xml");
33
+ expect(Object.keys(routes)).not.toContain("/api/sitemap.xml");
34
+ });
35
+
36
+ test("wraps only render routes with the web proxy runner", async () => {
37
+ process.env.AKAN_PUBLIC_APP_NAME = "test";
38
+ const { ApiRouter } = await import("./apiRouter");
39
+ class RewriteRenderProxy {
40
+ static refName = "rewriteRenderProxy";
41
+ use() {
42
+ return AkanResponse.rewrite("http://localhost/rendered", { request: { headers: { "x-proxy": "1" } } });
43
+ }
44
+ }
45
+ const routes = ApiRouter.buildRoutes({
46
+ prefix: "/api",
47
+ websocketPrefix: "/ws",
48
+ routes: { "/ping": () => Response.json("api") } as HttpRoutes,
49
+ renderEnvRoutes: {
50
+ "/*": (req) => Response.json({ url: req.url, proxy: req.headers.get("x-proxy") }),
51
+ } as HttpRoutes,
52
+ upgradeAppWs: () => false,
53
+ webProxyRunner: new WebProxyRunner([RewriteRenderProxy]),
54
+ });
55
+
56
+ expect(await (await (routes["/api/ping"] as () => Response)()).json()).toBe("api");
57
+ const renderResponse = await (routes["/*"] as (req: Request) => Response | Promise<Response>)(
58
+ new Request("http://localhost/dashboard"),
59
+ );
60
+ expect(await renderResponse.json()).toEqual({ url: "http://localhost/rendered", proxy: "1" });
61
+ });
62
+ });
63
+
64
+ describe("ApiRouter.buildWebsocketHandlers", () => {
65
+ test("dispatches app websocket messages and returns route errors", async () => {
66
+ process.env.AKAN_PUBLIC_APP_NAME = "test";
67
+ const { ApiRouter } = await import("./apiRouter");
68
+ const sent: string[] = [];
69
+ const loggerErrors: string[] = [];
70
+ const ws = {
71
+ data: {},
72
+ send: (message: string) => sent.push(message),
73
+ } as unknown as Bun.ServerWebSocket<unknown>;
74
+ const handlers = ApiRouter.buildWebsocketHandlers({
75
+ wsRoutes: {
76
+ echo: async (_ws, data, event) => ({ event, data }),
77
+ } as WebsocketRoutes,
78
+ registry: getDefaultInjectRegistry(),
79
+ hmrHub: null,
80
+ hmrState: null,
81
+ logger: { error: (message: string) => loggerErrors.push(message) } as never,
82
+ });
83
+
84
+ await handlers.message?.(ws, JSON.stringify({ key: "echo", data: ["hello"] }));
85
+ const originalConsoleError = console.error;
86
+ console.error = () => undefined;
87
+ try {
88
+ await handlers.message?.(ws, JSON.stringify({ key: "missing", data: [] }));
89
+ } finally {
90
+ console.error = originalConsoleError;
91
+ }
92
+
93
+ expect(JSON.parse(sent[0] ?? "{}")).toEqual({ event: "message", data: ["hello"] });
94
+ expect(JSON.parse(sent[1] ?? "{}").error).toBe('WebSocket route "missing" is not registered');
95
+ expect(loggerErrors).toEqual(['WebSocket route "missing" is not registered']);
96
+ });
97
+
98
+ test("keeps HMR websocket traffic separate from app signal routes", async () => {
99
+ process.env.AKAN_PUBLIC_APP_NAME = "test";
100
+ const { ApiRouter } = await import("./apiRouter");
101
+ const sent: string[] = [];
102
+ let attached = false;
103
+ let detached = false;
104
+ const ws = {
105
+ data: { kind: "akan-hmr" },
106
+ send: (message: string) => sent.push(message),
107
+ } as unknown as Bun.ServerWebSocket<unknown>;
108
+ const handlers = ApiRouter.buildWebsocketHandlers({
109
+ wsRoutes: {
110
+ hmrShouldNotRun: () => {
111
+ throw new Error("should not run");
112
+ },
113
+ } as WebsocketRoutes,
114
+ registry: getDefaultInjectRegistry(),
115
+ hmrHub: {
116
+ attach: () => {
117
+ attached = true;
118
+ },
119
+ detach: () => {
120
+ detached = true;
121
+ },
122
+ } as never,
123
+ hmrState: { state: { buildId: 7, cssAssets: {} } },
124
+ logger: { error: () => undefined } as never,
125
+ });
126
+
127
+ handlers.open?.(ws);
128
+ await handlers.message?.(ws, JSON.stringify({ key: "hmrShouldNotRun" }));
129
+ handlers.close?.(ws);
130
+
131
+ expect(attached).toBe(true);
132
+ expect(detached).toBe(true);
133
+ expect(JSON.parse(sent[0] ?? "{}")).toEqual({ type: "hello", buildId: 7, cssAssets: {} });
134
+ expect(sent).toHaveLength(1);
135
+ });
136
+ });
@@ -109,7 +109,9 @@ export class ApiRouter {
109
109
  }: WebsocketHandlersInputs): Bun.WebSocketHandler<WsTaggedData> {
110
110
  return {
111
111
  open: (ws) => {
112
-
112
+ // HMR sockets live in a separate logical channel from the app's signal
113
+ // websockets. We tag them via `data.kind === "akan-hmr"` at upgrade
114
+ // time so the dispatcher can skip signal handling.
113
115
  const data = ws.data as WsTaggedData | undefined;
114
116
  if (data?.kind === "akan-hmr" && hmrHub && hmrState) {
115
117
  hmrHub.attach(ws as unknown as Bun.ServerWebSocket<HmrWsData>);
@@ -126,7 +128,7 @@ export class ApiRouter {
126
128
  },
127
129
  message: async (ws, message) => {
128
130
  const data = ws.data as WsTaggedData | undefined;
129
- if (data?.kind === "akan-hmr") return;
131
+ if (data?.kind === "akan-hmr") return; // dev HMR is one-way (server→client)
130
132
  try {
131
133
  if (typeof message === "string") {
132
134
  const msg = JSON.parse(message) as WebsocketReqData;
@@ -67,7 +67,13 @@ async function fetchRsc(href: string, options: { buildId?: number } = {}): Promi
67
67
  return { type: "redirected" };
68
68
  }
69
69
  if (!res.ok || !res.body) throw new Error(`[rscClient] RSC fetch failed ${res.status} ${res.statusText}`);
70
-
70
+ // Buffer the entire Flight payload before constructing the thenable. The root
71
+ // `use(thenable)` lives at the document root with no Suspense boundary above it
72
+ // (see Root / ssrFromRscRenderer), so any mid-render suspension during a client
73
+ // navigation transition has no fallback and can leave the transition stuck —
74
+ // committing only when a later navigation flushes the pending lane. Materializing
75
+ // the payload up front means all RSC rows are present and every referenced client
76
+ // module `import()` starts immediately, so the committed render does not suspend.
71
77
  const buffer = await res.arrayBuffer();
72
78
  const completeStream = new ReadableStream<Uint8Array>({
73
79
  start(controller) {
@@ -98,7 +98,9 @@ export class RscWorker {
98
98
 
99
99
  #status: WorkerStatus = "starting";
100
100
  #killed = false;
101
-
101
+ // Render sends issued while the worker is starting / restarting are queued
102
+ // here and flushed on the next `ready`. Each closure re-checks `#pending` so
103
+ // cancelled streams don't forward a stale request to the new worker.
102
104
  #queuedSends: Array<() => void> = [];
103
105
  #restartAttempts = 0;
104
106
  #restartCount = 0;
@@ -138,7 +140,9 @@ export class RscWorker {
138
140
 
139
141
  render(req: Request): ReadableStream<Uint8Array> {
140
142
  const requestId = crypto.randomUUID();
141
-
143
+ // Serialize headers so the worker can rebuild a Request mirror inside its
144
+ // own `requestStorage` scope. Without this, server components running in
145
+ // the worker cannot read cookies/auth headers of the incoming request.
142
146
  const headers: Array<[string, string]> = [];
143
147
  req.headers.forEach((value, key) => {
144
148
  headers.push([key, value]);
@@ -152,7 +156,10 @@ export class RscWorker {
152
156
  onError: (msg) => controller.error(new Error(msg)),
153
157
  });
154
158
  const send = () => {
155
-
159
+ // The stream may have been cancelled, or the worker may have died
160
+ // again between queueing and flushing — both cases drop silently
161
+ // (the pending entry is already gone / will be handled by the exit
162
+ // path).
156
163
  if (!this.#pending.has(requestId)) return;
157
164
  try {
158
165
  this.#proc.send({ type: "render", requestId, url: req.url, method: req.method, headers });
@@ -305,6 +312,8 @@ export class RscWorker {
305
312
  try {
306
313
  this.#proc.send({ type: "updateCssAssets", cssAssets });
307
314
  } catch {
315
+ // If the worker died mid-send we'll pick up the new value on the next
316
+ // `hello` after restart; nothing to do here.
308
317
  }
309
318
  }
310
319
 
@@ -320,10 +329,15 @@ export class RscWorker {
320
329
  this.#cssAssets = input.cssAssets ?? this.#cssAssets;
321
330
  this.#pagesBundleBuildId = input.buildId;
322
331
  if (input.pagesBundlePath) this.#pagesBundlePath = input.pagesBundlePath;
323
-
332
+ // While restarting / starting, the new worker will pick up the latest
333
+ // `#clientManifest` / `#cssAssets` / `#pagesBundlePath` via the `init` reply
334
+ // to its first `hello`, so callers don't need to wait on an explicit
335
+ // `reloaded` ack.
324
336
  if (this.#status !== "ready") return Promise.resolve();
325
337
  return new Promise<void>((resolve, reject) => {
326
-
338
+ // If a previous reload was still in flight, supersede it — the latest
339
+ // build strictly implies the earlier one completed from the caller's
340
+ // perspective.
327
341
  if (this.#pendingReload) this.#pendingReload.resolve();
328
342
  this.#pendingReload = { resolve, reject, targetBuildId: input.buildId };
329
343
  try {
@@ -372,7 +386,10 @@ export class RscWorker {
372
386
  if (proc !== this.#proc) return;
373
387
  switch (message.type) {
374
388
  case "hello":
375
-
389
+ // Re-injecting `#clientManifest` / `#cssAssets` here is what makes crash
390
+ // recovery transparent: after a respawn the new worker's first act is
391
+ // to ask for config, and it receives the latest manifest the host has
392
+ // accumulated via `reload(...)`.
376
393
  this.#proc.send({
377
394
  type: "init",
378
395
  clientManifest: this.#clientManifest,
@@ -417,7 +434,8 @@ export class RscWorker {
417
434
  return;
418
435
  case "error":
419
436
  if (message.requestId === "__init__") {
420
-
437
+ // Init errors are surfaced on `ready` only for the very first spawn;
438
+ // subsequent restarts swallow them and let exponential backoff retry.
421
439
  if (!this.#readyResolved) this.#rejectReady(new Error(String(message.message)));
422
440
  else this.#logger.error(`[rsc] worker init error on restart: ${message.message}`);
423
441
  return;
@@ -491,7 +509,9 @@ export class RscWorker {
491
509
  }
492
510
 
493
511
  #handleExit(proc: Bun.Subprocess<"ignore", "inherit", "inherit">, code: number | null): void {
494
-
512
+ // Stale exits from a proc we've already replaced can still fire if the
513
+ // old subprocess was slow to cleanup; ignore them so we don't
514
+ // double-schedule a restart.
495
515
  if (proc !== this.#proc) return;
496
516
 
497
517
  const err = new Error(`rsc worker exited with code ${code}`);
@@ -501,7 +521,8 @@ export class RscWorker {
501
521
  this.#pendingReload.reject(err);
502
522
  this.#pendingReload = null;
503
523
  }
504
-
524
+ // Drop any sends that were queued against the dead worker. Callers own
525
+ // their streams and will see the `onError` above.
505
526
  this.#queuedSends = [];
506
527
 
507
528
  if (this.#killed) {
@@ -518,7 +539,7 @@ export class RscWorker {
518
539
  this.#status = "stopped";
519
540
  const msg = `[rsc] worker failed ${attempt} restarts; giving up. SSR will return errors until the server restarts.`;
520
541
  this.#logger.error(msg);
521
-
542
+ // Surface a rejection on the initial `ready` if we never succeeded.
522
543
  this.#rejectReady(new Error(msg));
523
544
  return;
524
545
  }
@@ -588,9 +609,10 @@ export class RscWorker {
588
609
  const raw = fs.readFileSync(filePath, "utf8").trim();
589
610
  if (!raw || raw === "max") continue;
590
611
  const parsed = Number.parseInt(raw, 10);
591
-
612
+ // Ignore host-level sentinel values that are effectively unlimited.
592
613
  if (Number.isFinite(parsed) && parsed > 0 && parsed < 1024 ** 5) return parsed;
593
614
  } catch {
615
+ // cgroup files are best-effort; explicit env thresholds still work.
594
616
  }
595
617
  }
596
618
  return null;
@@ -0,0 +1,61 @@
1
+ import { createDefaultSitemapUrls, createSitemapXml, getSitemapBasePath } from "./sitemap";
2
+
3
+ describe("sitemap fallback helpers", () => {
4
+ const i18n = { defaultLocale: "en", locales: ["en", "ko"] };
5
+
6
+ test("creates escaped XML with unique sorted URLs", () => {
7
+ const xml = createSitemapXml(["https://example.com/b?x=1&y=2", "https://example.com/a", "https://example.com/a"]);
8
+
9
+ expect(xml).toContain("<loc>https://example.com/a</loc>");
10
+ expect(xml).toContain("<loc>https://example.com/b?x=1&amp;y=2</loc>");
11
+ expect(xml.match(/<url>/g)).toHaveLength(2);
12
+ });
13
+
14
+ test("expands only static locale routes", () => {
15
+ const urls = createDefaultSitemapUrls({
16
+ origin: "https://example.com",
17
+ entries: [
18
+ { routeId: "/:lang", pattern: "/:lang", seeds: [] },
19
+ { routeId: "/:lang/about", pattern: "/:lang/about", seeds: [] },
20
+ { routeId: "/:lang/post/:postId", pattern: "/:lang/post/:postId", seeds: [] },
21
+ { routeId: "/robots.txt", pattern: "/robots.txt", seeds: [] },
22
+ ],
23
+ i18n,
24
+ });
25
+
26
+ expect(urls).toEqual([
27
+ "https://example.com/en",
28
+ "https://example.com/ko",
29
+ "https://example.com/en/about",
30
+ "https://example.com/ko/about",
31
+ ]);
32
+ });
33
+
34
+ test("uses base path only for filtering subroute sitemap entries", () => {
35
+ const urls = createDefaultSitemapUrls({
36
+ origin: "https://example.com/",
37
+ basePath: "akanjs",
38
+ entries: [
39
+ { routeId: "/:lang/akanjs", pattern: "/:lang/akanjs", seeds: [] },
40
+ { routeId: "/:lang/akanjs/about", pattern: "/:lang/akanjs/about", seeds: [] },
41
+ { routeId: "/:lang/thin/about", pattern: "/:lang/thin/about", seeds: [] },
42
+ { routeId: "/:lang/akanjs/post/:postId", pattern: "/:lang/akanjs/post/:postId", seeds: [] },
43
+ ],
44
+ i18n,
45
+ });
46
+
47
+ expect(urls).toEqual([
48
+ "https://example.com/en",
49
+ "https://example.com/ko",
50
+ "https://example.com/en/about",
51
+ "https://example.com/ko/about",
52
+ ]);
53
+ });
54
+
55
+ test("recognizes root and subroute sitemap paths", () => {
56
+ expect(getSitemapBasePath("/sitemap.xml", [])).toBeNull();
57
+ expect(getSitemapBasePath("/sitemap.xml", ["akanjs"])).toBeUndefined();
58
+ expect(getSitemapBasePath("/sitemap.xml", ["akanjs"], "akanjs")).toBe("akanjs");
59
+ expect(getSitemapBasePath("/akanjs/sitemap.xml", ["akanjs"], "akanjs")).toBeUndefined();
60
+ });
61
+ });
@@ -12,6 +12,11 @@ export class SsrFromRscRenderer {
12
12
  ssrChunkCacheHitCount: 0,
13
13
  };
14
14
 
15
+ // Inline bootstrap that runs as a classic script BEFORE any <script type="module">.
16
+ // - Installs the webpack runtime shims that react-server-dom-webpack/client.browser
17
+ // needs at module initialization time.
18
+ // - Creates a tiny queue so <script>self.__RSC_PUSH__(...)</script> tags
19
+ // emitted after the HTML shell can be buffered until rscClient picks them up.
15
20
  static readonly #clientBootstrap = `(function(){
16
21
  var registry = new Map();
17
22
  function load(id) {
@@ -53,7 +58,8 @@ export class SsrFromRscRenderer {
53
58
  }
54
59
 
55
60
  async render(input: SsrFromRscInput): Promise<ReadableStream<Uint8Array>> {
56
-
61
+ // Split the RSC stream: one branch drives the server-side SSR render, the
62
+ // other is relayed to the client as inline <script> tags for hydration.
57
63
  const [rscForSsr, rscForClient] = input.rscStream.tee();
58
64
 
59
65
  const ssrNodeStream = Readable.fromWeb(rscForSsr as never);
@@ -97,6 +103,19 @@ export class SsrFromRscRenderer {
97
103
  if (g.__rsc_ssr_shims_installed__) return;
98
104
  g.__rsc_ssr_shims_installed__ = true;
99
105
 
106
+ // SSR-side webpack runtime shims. We use dynamic `import()` rather than
107
+ // `require()` because client component chunks may transitively use
108
+ // top-level await, which Bun's `require()` refuses to load.
109
+ //
110
+ // `chunks`/`id` entries in the ssrManifest are absolute filesystem paths
111
+ // to server-importable client chunks. These may differ from the browser
112
+ // chunks referenced by the Flight client manifest because the browser build
113
+ // can rely on import maps while this SSR pass is loaded directly by Bun.
114
+ // HMR cache-busting is filename-based: each rebuild emits a new
115
+ // content-hashed chunk filename, which means a new import
116
+ // specifier, which bypasses Bun's module cache naturally. The
117
+ // `?v=<digits>` stripping below is defensive for any caller that still
118
+ // appends a version query to keep the pre-existing registry keys stable.
100
119
  const registry = new Map<string, Record<string, unknown>>();
101
120
  g.__webpack_chunk_load__ = async (chunkId: string) => {
102
121
  if (registry.has(chunkId)) {
@@ -187,7 +206,8 @@ export class SsrFromRscRenderer {
187
206
  if (tail) controller.enqueue(encoder.encode(tail));
188
207
  return;
189
208
  }
190
-
209
+ // `<head>` never appeared — e.g. error shell. Emit buffered bytes
210
+ // verbatim so we don't swallow the document.
191
211
  const tail = decoder.decode();
192
212
  const rest = withHtmlTheme(buffered + tail);
193
213
  if (rest) controller.enqueue(encoder.encode(rest));
@@ -200,10 +220,20 @@ export class SsrFromRscRenderer {
200
220
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
201
221
  }
202
222
 
223
+ // React-server-dom-webpack/server emits a Flight hint of the form
224
+ // `:HL["<href>","stylesheet"]\n` for every `<link rel="stylesheet">` in the
225
+ // server tree. That string is forwarded verbatim to the browser which then
226
+ // calls `ReactDOM.preload(href, "stylesheet")`, creating an invalid
227
+ // `<link rel="preload" as="stylesheet">` (valid preload `as` is `"style"`).
228
+ // The SSR-side Fizz dispatcher happens to tolerate this, but Chromium logs
229
+ // `<link rel=preload> must have a valid "as" value`. Rewrite the hint for
230
+ // the browser-bound stream to use the spec-correct `"style"`; the SSR-bound
231
+ // tee is left untouched so we don't alter React's server behavior.
203
232
  static #sanitizeFlightForClient(stream: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> {
204
233
  const decoder = new TextDecoder();
205
234
  const encoder = new TextEncoder();
206
-
235
+ // Matches just the trailing `,"stylesheet"]` of an HL hint line. The href is
236
+ // left alone; only the `as` slot is rewritten.
207
237
  const hlStylesheetRe = /(:HL\["[^"\\]*(?:\\.[^"\\]*)*",)"stylesheet"(\])/g;
208
238
 
209
239
  return stream.pipeThrough(
@@ -253,6 +283,8 @@ export class SsrFromRscRenderer {
253
283
  reader.releaseLock();
254
284
  }
255
285
 
286
+ // Inline RSC scripts must not be interleaved with arbitrary HTML bytes:
287
+ // Fizz may split inside SVG path data or attributes, corrupting markup.
256
288
  const rscReader = rscClientStream.getReader();
257
289
  try {
258
290
  while (true) {