@askrjs/askr 0.0.47 → 0.0.49

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 (394) hide show
  1. package/dist/benchmark.js +6 -6
  2. package/dist/benchmark.js.map +1 -1
  3. package/dist/boot/hydration.js +140 -0
  4. package/dist/boot/hydration.js.map +1 -0
  5. package/dist/boot/index.d.ts +3 -56
  6. package/dist/boot/index.d.ts.map +1 -1
  7. package/dist/boot/index.js +62 -410
  8. package/dist/boot/index.js.map +1 -1
  9. package/dist/boot/root-lifecycle.d.ts +15 -0
  10. package/dist/boot/root-lifecycle.d.ts.map +1 -0
  11. package/dist/boot/root-lifecycle.js +205 -0
  12. package/dist/boot/root-lifecycle.js.map +1 -0
  13. package/dist/boot/route-startup.js +45 -0
  14. package/dist/boot/route-startup.js.map +1 -0
  15. package/dist/boot/types.d.ts +62 -0
  16. package/dist/boot/types.d.ts.map +1 -0
  17. package/dist/common/component.d.ts +3 -1
  18. package/dist/common/component.d.ts.map +1 -1
  19. package/dist/common/jsx.d.ts +1 -1
  20. package/dist/common/jsx.d.ts.map +1 -1
  21. package/dist/common/jsx.js.map +1 -1
  22. package/dist/common/props.d.ts +1 -1
  23. package/dist/common/render-context.js +55 -0
  24. package/dist/common/render-context.js.map +1 -0
  25. package/dist/common/router.d.ts +5 -1
  26. package/dist/common/router.d.ts.map +1 -1
  27. package/dist/common/ssr.d.ts +1 -1
  28. package/dist/common/ssr.js.map +1 -1
  29. package/dist/common/vnode.d.ts +5 -4
  30. package/dist/common/vnode.d.ts.map +1 -1
  31. package/dist/common/vnode.js.map +1 -1
  32. package/dist/components/error-boundary.d.ts +1 -1
  33. package/dist/components/error-boundary.js +2 -1
  34. package/dist/components/error-boundary.js.map +1 -1
  35. package/dist/components/link.js.map +1 -1
  36. package/dist/control/for.js +2 -1
  37. package/dist/control/for.js.map +1 -1
  38. package/dist/data/data-runtime.d.ts +28 -0
  39. package/dist/data/data-runtime.d.ts.map +1 -0
  40. package/dist/data/data-runtime.js +114 -0
  41. package/dist/data/data-runtime.js.map +1 -0
  42. package/dist/data/index.d.ts +6 -142
  43. package/dist/data/index.js +5 -539
  44. package/dist/data/invalidation.d.ts +9 -0
  45. package/dist/data/invalidation.d.ts.map +1 -0
  46. package/dist/data/invalidation.js +27 -0
  47. package/dist/data/invalidation.js.map +1 -0
  48. package/dist/data/mutation-cell.d.ts +28 -0
  49. package/dist/data/mutation-cell.d.ts.map +1 -0
  50. package/dist/data/mutation-cell.js +132 -0
  51. package/dist/data/mutation-cell.js.map +1 -0
  52. package/dist/data/query-cell.d.ts +46 -0
  53. package/dist/data/query-cell.d.ts.map +1 -0
  54. package/dist/data/query-cell.js +290 -0
  55. package/dist/data/query-cell.js.map +1 -0
  56. package/dist/data/query-key.js +42 -0
  57. package/dist/data/query-key.js.map +1 -0
  58. package/dist/data/shared.js +20 -0
  59. package/dist/data/shared.js.map +1 -0
  60. package/dist/data/types.d.ts +161 -0
  61. package/dist/data/types.d.ts.map +1 -0
  62. package/dist/foundations/icon/icon.d.ts.map +1 -1
  63. package/dist/foundations/icon/icon.js.map +1 -1
  64. package/dist/foundations/structures/portal.d.ts +1 -1
  65. package/dist/foundations/structures/portal.d.ts.map +1 -1
  66. package/dist/foundations/structures/portal.js +2 -1
  67. package/dist/foundations/structures/portal.js.map +1 -1
  68. package/dist/fx/fx.d.ts +1 -1
  69. package/dist/fx/fx.js +5 -4
  70. package/dist/fx/fx.js.map +1 -1
  71. package/dist/fx/timing.d.ts.map +1 -1
  72. package/dist/fx/timing.js +10 -6
  73. package/dist/fx/timing.js.map +1 -1
  74. package/dist/index.d.ts +3 -2
  75. package/dist/index.js +4 -2
  76. package/dist/index.js.map +1 -1
  77. package/dist/jsx/index.d.ts +2 -1
  78. package/dist/jsx/index.js +3 -2
  79. package/dist/jsx/types.d.ts +2 -0
  80. package/dist/jsx/types.js +2 -1
  81. package/dist/jsx-runtime2.d.ts +2 -1
  82. package/dist/jsx-runtime2.js +3 -2
  83. package/dist/renderer/attributes.js +231 -0
  84. package/dist/renderer/attributes.js.map +1 -0
  85. package/dist/renderer/boundaries.js +266 -0
  86. package/dist/renderer/boundaries.js.map +1 -0
  87. package/dist/renderer/child-shape.js +85 -0
  88. package/dist/renderer/child-shape.js.map +1 -0
  89. package/dist/renderer/children.js +3 -2
  90. package/dist/renderer/children.js.map +1 -1
  91. package/dist/renderer/cleanup.js +2 -1
  92. package/dist/renderer/cleanup.js.map +1 -1
  93. package/dist/renderer/component-host-cleanup.js +68 -0
  94. package/dist/renderer/component-host-cleanup.js.map +1 -0
  95. package/dist/renderer/component-host-instances.js +65 -0
  96. package/dist/renderer/component-host-instances.js.map +1 -0
  97. package/dist/renderer/component-host.js +247 -0
  98. package/dist/renderer/component-host.js.map +1 -0
  99. package/dist/renderer/dom-host.js +13 -0
  100. package/dist/renderer/dom-host.js.map +1 -0
  101. package/dist/renderer/dom-internal.js +185 -0
  102. package/dist/renderer/dom-internal.js.map +1 -0
  103. package/dist/renderer/dom.js +9 -2356
  104. package/dist/renderer/element-children.js +279 -0
  105. package/dist/renderer/element-children.js.map +1 -0
  106. package/dist/renderer/env.js +2 -1
  107. package/dist/renderer/error-boundary-dom.js +29 -0
  108. package/dist/renderer/error-boundary-dom.js.map +1 -0
  109. package/dist/renderer/evaluate-dom-range.js +85 -0
  110. package/dist/renderer/evaluate-dom-range.js.map +1 -0
  111. package/dist/renderer/evaluate-reconcile.js +281 -0
  112. package/dist/renderer/evaluate-reconcile.js.map +1 -0
  113. package/dist/renderer/evaluate.js +13 -399
  114. package/dist/renderer/evaluate.js.map +1 -1
  115. package/dist/renderer/fastpath.js +6 -5
  116. package/dist/renderer/fastpath.js.map +1 -1
  117. package/dist/renderer/for-commit-dom-map.js +83 -0
  118. package/dist/renderer/for-commit-dom-map.js.map +1 -0
  119. package/dist/renderer/for-commit-removal.js +36 -0
  120. package/dist/renderer/for-commit-removal.js.map +1 -0
  121. package/dist/renderer/for-commit-reorder.js +89 -0
  122. package/dist/renderer/for-commit-reorder.js.map +1 -0
  123. package/dist/renderer/for-commit.js +6 -188
  124. package/dist/renderer/for-commit.js.map +1 -1
  125. package/dist/renderer/index.js +28 -16
  126. package/dist/renderer/index.js.map +1 -1
  127. package/dist/renderer/keyed-children.js +32 -0
  128. package/dist/renderer/keyed-children.js.map +1 -0
  129. package/dist/renderer/keyed.js +2 -15
  130. package/dist/renderer/keyed.js.map +1 -1
  131. package/dist/renderer/namespaces.js +23 -0
  132. package/dist/renderer/namespaces.js.map +1 -0
  133. package/dist/renderer/prop-bindings.js +280 -0
  134. package/dist/renderer/prop-bindings.js.map +1 -0
  135. package/dist/renderer/reactive-child-dom.js +133 -0
  136. package/dist/renderer/reactive-child-dom.js.map +1 -0
  137. package/dist/renderer/reactive-child-sources.js +184 -0
  138. package/dist/renderer/reactive-child-sources.js.map +1 -0
  139. package/dist/renderer/reactive-children.js +294 -0
  140. package/dist/renderer/reactive-children.js.map +1 -0
  141. package/dist/renderer/reconcile-commit.js +38 -0
  142. package/dist/renderer/reconcile-commit.js.map +1 -0
  143. package/dist/renderer/reconcile-fastpaths.js +106 -0
  144. package/dist/renderer/reconcile-fastpaths.js.map +1 -0
  145. package/dist/renderer/reconcile-resolution.js +187 -0
  146. package/dist/renderer/reconcile-resolution.js.map +1 -0
  147. package/dist/renderer/reconcile.js +9 -371
  148. package/dist/renderer/reconcile.js.map +1 -1
  149. package/dist/renderer/retained-element-rollback.js +276 -0
  150. package/dist/renderer/retained-element-rollback.js.map +1 -0
  151. package/dist/renderer/stable-patch.js +82 -0
  152. package/dist/renderer/stable-patch.js.map +1 -0
  153. package/dist/renderer/static-reuse.js +96 -0
  154. package/dist/renderer/static-reuse.js.map +1 -0
  155. package/dist/renderer/types.js +2 -1
  156. package/dist/renderer/utils.js +4 -4
  157. package/dist/renderer/utils.js.map +1 -1
  158. package/dist/resources/index.d.ts +3 -2
  159. package/dist/resources/index.js +5 -2
  160. package/dist/router/access.js +36 -0
  161. package/dist/router/access.js.map +1 -0
  162. package/dist/router/activity.d.ts +10 -0
  163. package/dist/router/activity.d.ts.map +1 -0
  164. package/dist/router/activity.js +89 -0
  165. package/dist/router/activity.js.map +1 -0
  166. package/dist/router/authoring.d.ts +22 -0
  167. package/dist/router/authoring.d.ts.map +1 -0
  168. package/dist/router/authoring.js +198 -0
  169. package/dist/router/authoring.js.map +1 -0
  170. package/dist/router/index.d.ts +12 -4
  171. package/dist/router/index.js +9 -2
  172. package/dist/router/internal-types.d.ts +31 -0
  173. package/dist/router/internal-types.d.ts.map +1 -0
  174. package/dist/router/lazy.d.ts +19 -0
  175. package/dist/router/lazy.d.ts.map +1 -0
  176. package/dist/router/lazy.js +52 -0
  177. package/dist/router/lazy.js.map +1 -0
  178. package/dist/router/manifest.d.ts +10 -0
  179. package/dist/router/manifest.d.ts.map +1 -0
  180. package/dist/router/manifest.js +49 -0
  181. package/dist/router/manifest.js.map +1 -0
  182. package/dist/router/navigate.d.ts +4 -33
  183. package/dist/router/navigate.d.ts.map +1 -1
  184. package/dist/router/navigate.js +17 -414
  185. package/dist/router/navigate.js.map +1 -1
  186. package/dist/router/navigation-registry.d.ts +32 -0
  187. package/dist/router/navigation-registry.d.ts.map +1 -0
  188. package/dist/router/navigation-registry.js +105 -0
  189. package/dist/router/navigation-registry.js.map +1 -0
  190. package/dist/router/navigation-scroll.d.ts +14 -0
  191. package/dist/router/navigation-scroll.d.ts.map +1 -0
  192. package/dist/router/navigation-scroll.js +93 -0
  193. package/dist/router/navigation-scroll.js.map +1 -0
  194. package/dist/router/navigation-targets.d.ts +31 -0
  195. package/dist/router/navigation-targets.d.ts.map +1 -0
  196. package/dist/router/navigation-targets.js +253 -0
  197. package/dist/router/navigation-targets.js.map +1 -0
  198. package/dist/router/policy.d.ts +7 -1
  199. package/dist/router/policy.d.ts.map +1 -1
  200. package/dist/router/policy.js +27 -9
  201. package/dist/router/policy.js.map +1 -1
  202. package/dist/router/rendering.d.ts +10 -0
  203. package/dist/router/rendering.d.ts.map +1 -0
  204. package/dist/router/rendering.js +45 -0
  205. package/dist/router/rendering.js.map +1 -0
  206. package/dist/router/resolution.d.ts +17 -0
  207. package/dist/router/resolution.d.ts.map +1 -0
  208. package/dist/router/resolution.js +253 -0
  209. package/dist/router/resolution.js.map +1 -0
  210. package/dist/router/route-query.d.ts +17 -0
  211. package/dist/router/route-query.d.ts.map +1 -0
  212. package/dist/router/route-query.js +47 -0
  213. package/dist/router/route-query.js.map +1 -0
  214. package/dist/router/route.d.ts +8 -149
  215. package/dist/router/route.js +8 -854
  216. package/dist/router/store.d.ts +50 -0
  217. package/dist/router/store.d.ts.map +1 -0
  218. package/dist/router/store.js +171 -0
  219. package/dist/router/store.js.map +1 -0
  220. package/dist/runtime/access.js +45 -0
  221. package/dist/runtime/access.js.map +1 -0
  222. package/dist/runtime/child-scope.d.ts +1 -1
  223. package/dist/runtime/child-scope.js +4 -1
  224. package/dist/runtime/child-scope.js.map +1 -1
  225. package/dist/runtime/component-cleanup.d.ts +16 -0
  226. package/dist/runtime/component-cleanup.d.ts.map +1 -0
  227. package/dist/runtime/component-cleanup.js +70 -0
  228. package/dist/runtime/component-cleanup.js.map +1 -0
  229. package/dist/runtime/component-commit.js +165 -0
  230. package/dist/runtime/component-commit.js.map +1 -0
  231. package/dist/runtime/component-contracts.js +5 -0
  232. package/dist/runtime/component-facade.d.ts +5 -0
  233. package/dist/runtime/component-facade.js +4 -0
  234. package/dist/runtime/component-internal.d.ts +100 -0
  235. package/dist/runtime/component-internal.d.ts.map +1 -0
  236. package/dist/runtime/component-internal.js +219 -0
  237. package/dist/runtime/component-internal.js.map +1 -0
  238. package/dist/runtime/component-lifecycle.d.ts +49 -0
  239. package/dist/runtime/component-lifecycle.d.ts.map +1 -0
  240. package/dist/runtime/component-lifecycle.js +176 -0
  241. package/dist/runtime/component-lifecycle.js.map +1 -0
  242. package/dist/runtime/component-scope.d.ts +55 -0
  243. package/dist/runtime/component-scope.d.ts.map +1 -0
  244. package/dist/runtime/component-scope.js +154 -0
  245. package/dist/runtime/component-scope.js.map +1 -0
  246. package/dist/runtime/component.d.ts +4 -152
  247. package/dist/runtime/component.js +4 -692
  248. package/dist/runtime/context.d.ts +1 -1
  249. package/dist/runtime/context.js +6 -4
  250. package/dist/runtime/context.js.map +1 -1
  251. package/dist/runtime/control.d.ts +3 -3
  252. package/dist/runtime/control.js +2 -1
  253. package/dist/runtime/control.js.map +1 -1
  254. package/dist/runtime/derive.d.ts.map +1 -1
  255. package/dist/runtime/derive.js +6 -5
  256. package/dist/runtime/derive.js.map +1 -1
  257. package/dist/runtime/effect.d.ts +1 -1
  258. package/dist/runtime/effect.d.ts.map +1 -1
  259. package/dist/runtime/effect.js +2 -2
  260. package/dist/runtime/effect.js.map +1 -1
  261. package/dist/runtime/events.js +3 -3
  262. package/dist/runtime/events.js.map +1 -1
  263. package/dist/runtime/fastlane.js +13 -27
  264. package/dist/runtime/fastlane.js.map +1 -1
  265. package/dist/runtime/for-bench.d.ts +1 -1
  266. package/dist/runtime/for-bench.js +1 -4
  267. package/dist/runtime/for-bench.js.map +1 -1
  268. package/dist/runtime/for-internal.d.ts +43 -0
  269. package/dist/runtime/for-internal.d.ts.map +1 -0
  270. package/dist/runtime/for-internal.js +98 -0
  271. package/dist/runtime/for-internal.js.map +1 -0
  272. package/dist/runtime/for-reconcile.d.ts +8 -0
  273. package/dist/runtime/for-reconcile.d.ts.map +1 -0
  274. package/dist/runtime/for-reconcile.js +389 -0
  275. package/dist/runtime/for-reconcile.js.map +1 -0
  276. package/dist/runtime/for-scopes.d.ts +26 -0
  277. package/dist/runtime/for-scopes.d.ts.map +1 -0
  278. package/dist/runtime/for-scopes.js +160 -0
  279. package/dist/runtime/for-scopes.js.map +1 -0
  280. package/dist/runtime/for-signals.d.ts +30 -0
  281. package/dist/runtime/for-signals.d.ts.map +1 -0
  282. package/dist/runtime/for-signals.js +139 -0
  283. package/dist/runtime/for-signals.js.map +1 -0
  284. package/dist/runtime/for.d.ts +4 -66
  285. package/dist/runtime/for.js +5 -773
  286. package/dist/runtime/lifecycle-operations.d.ts +31 -0
  287. package/dist/runtime/lifecycle-operations.d.ts.map +1 -0
  288. package/dist/runtime/lifecycle-operations.js +195 -0
  289. package/dist/runtime/lifecycle-operations.js.map +1 -0
  290. package/dist/runtime/operations.d.ts +3 -40
  291. package/dist/runtime/operations.js +2 -357
  292. package/dist/runtime/readable.d.ts +2 -3
  293. package/dist/runtime/readable.d.ts.map +1 -1
  294. package/dist/runtime/readable.js +6 -5
  295. package/dist/runtime/readable.js.map +1 -1
  296. package/dist/runtime/resource-cell.js +2 -2
  297. package/dist/runtime/resource-cell.js.map +1 -1
  298. package/dist/runtime/resource-operation.d.ts +13 -0
  299. package/dist/runtime/resource-operation.d.ts.map +1 -0
  300. package/dist/runtime/resource-operation.js +170 -0
  301. package/dist/runtime/resource-operation.js.map +1 -0
  302. package/dist/runtime/runtime.d.ts +42 -0
  303. package/dist/runtime/runtime.d.ts.map +1 -0
  304. package/dist/runtime/runtime.js +59 -0
  305. package/dist/runtime/runtime.js.map +1 -0
  306. package/dist/runtime/scheduler.d.ts +5 -1
  307. package/dist/runtime/scheduler.d.ts.map +1 -1
  308. package/dist/runtime/scheduler.js +17 -17
  309. package/dist/runtime/scheduler.js.map +1 -1
  310. package/dist/runtime/selector.js +4 -3
  311. package/dist/runtime/selector.js.map +1 -1
  312. package/dist/runtime/snapshot-source.d.ts +1 -1
  313. package/dist/runtime/snapshot-source.js +1 -1
  314. package/dist/runtime/state.js +2 -1
  315. package/dist/runtime/state.js.map +1 -1
  316. package/dist/ssg/batch-render.js +2 -1
  317. package/dist/ssg/batch-render.js.map +1 -1
  318. package/dist/ssg/create-static-gen.d.ts +9 -3
  319. package/dist/ssg/create-static-gen.d.ts.map +1 -1
  320. package/dist/ssg/create-static-gen.js +12 -99
  321. package/dist/ssg/create-static-gen.js.map +1 -1
  322. package/dist/ssg/generation-plan.js +70 -0
  323. package/dist/ssg/generation-plan.js.map +1 -0
  324. package/dist/ssg/incremental-manifest.js +1 -1
  325. package/dist/ssg/static-routes.js +101 -0
  326. package/dist/ssg/static-routes.js.map +1 -0
  327. package/dist/ssg/types.d.ts +15 -7
  328. package/dist/ssg/types.d.ts.map +1 -1
  329. package/dist/ssr/boundaries.js +113 -0
  330. package/dist/ssr/boundaries.js.map +1 -0
  331. package/dist/ssr/component-runtime.js +111 -0
  332. package/dist/ssr/component-runtime.js.map +1 -0
  333. package/dist/ssr/context.d.ts +3 -1
  334. package/dist/ssr/context.d.ts.map +1 -1
  335. package/dist/ssr/context.js +9 -2
  336. package/dist/ssr/context.js.map +1 -1
  337. package/dist/ssr/errors.d.ts +2 -0
  338. package/dist/ssr/errors.js +11 -1
  339. package/dist/ssr/errors.js.map +1 -1
  340. package/dist/ssr/escape.js +3 -3
  341. package/dist/ssr/escape.js.map +1 -1
  342. package/dist/ssr/hydration-data.js +10 -0
  343. package/dist/ssr/hydration-data.js.map +1 -0
  344. package/dist/ssr/hydration-verify.d.ts +12 -0
  345. package/dist/ssr/hydration-verify.d.ts.map +1 -0
  346. package/dist/ssr/hydration-verify.js +144 -0
  347. package/dist/ssr/hydration-verify.js.map +1 -0
  348. package/dist/ssr/index-internal.d.ts +15 -0
  349. package/dist/ssr/index-internal.d.ts.map +1 -0
  350. package/dist/ssr/index-internal.js +19 -0
  351. package/dist/ssr/index-internal.js.map +1 -0
  352. package/dist/ssr/index.d.ts +5 -57
  353. package/dist/ssr/index.js +3 -738
  354. package/dist/ssr/render-keys.js +9 -32
  355. package/dist/ssr/render-keys.js.map +1 -1
  356. package/dist/ssr/render-resolved.d.ts +1 -1
  357. package/dist/ssr/render-resolved.d.ts.map +1 -1
  358. package/dist/ssr/render-resolved.js +4 -2
  359. package/dist/ssr/render-resolved.js.map +1 -1
  360. package/dist/ssr/render-sync.d.ts +21 -0
  361. package/dist/ssr/render-sync.d.ts.map +1 -0
  362. package/dist/ssr/render-sync.js +275 -0
  363. package/dist/ssr/render-sync.js.map +1 -0
  364. package/dist/ssr/route-policy-resolution.js +77 -0
  365. package/dist/ssr/route-policy-resolution.js.map +1 -0
  366. package/dist/ssr/route-render.d.ts +77 -0
  367. package/dist/ssr/route-render.d.ts.map +1 -0
  368. package/dist/ssr/route-render.js +119 -0
  369. package/dist/ssr/route-render.js.map +1 -0
  370. package/dist/ssr/sink.d.ts +26 -0
  371. package/dist/ssr/sink.d.ts.map +1 -0
  372. package/dist/ssr/types.d.ts +1 -0
  373. package/dist/ssr/types.d.ts.map +1 -1
  374. package/dist/ssr/verify-hydration.js.map +1 -1
  375. package/dist/testing/index.d.ts +1 -2
  376. package/dist/testing/index.d.ts.map +1 -1
  377. package/dist/testing/index.js +2 -1
  378. package/dist/testing/index.js.map +1 -1
  379. package/package.json +4 -3
  380. package/dist/data/index.d.ts.map +0 -1
  381. package/dist/data/index.js.map +0 -1
  382. package/dist/renderer/dom.js.map +0 -1
  383. package/dist/router/route.d.ts.map +0 -1
  384. package/dist/router/route.js.map +0 -1
  385. package/dist/runtime/component.d.ts.map +0 -1
  386. package/dist/runtime/component.js.map +0 -1
  387. package/dist/runtime/for.d.ts.map +0 -1
  388. package/dist/runtime/for.js.map +0 -1
  389. package/dist/runtime/operations.d.ts.map +0 -1
  390. package/dist/runtime/operations.js.map +0 -1
  391. package/dist/runtime/ssr-bridge.js +0 -24
  392. package/dist/runtime/ssr-bridge.js.map +0 -1
  393. package/dist/ssr/index.d.ts.map +0 -1
  394. package/dist/ssr/index.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import { isPromiseLike } from "../common/promise.js";
2
2
  //#region src/router/policy.ts
3
3
  const ROUTE_AUTH_OPTIONS = Symbol.for("__ASKR_ROUTE_AUTH_OPTIONS__");
4
+ const BUILT_IN_ROUTE_POLICY = Symbol.for("__ASKR_BUILT_IN_ROUTE_POLICY__");
4
5
  function allow() {
5
6
  return { kind: "allow" };
6
7
  }
@@ -44,6 +45,17 @@ function assertRouteAuthOptions(context) {
44
45
  if (!auth?.resolve) throw new Error("Built-in auth policies require router auth configuration. Provide `auth` to registerRoutes(...), createSPA(...), hydrateSPA(...), or SSR route resolution.");
45
46
  return auth;
46
47
  }
48
+ function markBuiltInRoutePolicy(policy, metadata) {
49
+ Object.defineProperty(policy, BUILT_IN_ROUTE_POLICY, {
50
+ value: Object.freeze({ ...metadata }),
51
+ enumerable: false,
52
+ configurable: false
53
+ });
54
+ return policy;
55
+ }
56
+ function _getBuiltInRoutePolicy(policy) {
57
+ return policy[BUILT_IN_ROUTE_POLICY] ?? null;
58
+ }
47
59
  function resolvePathSetting(value, fallback, context) {
48
60
  if (!value) return fallback;
49
61
  if (typeof value === "function") return value(context);
@@ -79,36 +91,42 @@ function resolveAuthenticatedRedirect(context) {
79
91
  return redirect(target, { replace: true });
80
92
  }
81
93
  function requireAuth() {
82
- return (context) => {
94
+ return markBuiltInRoutePolicy((context) => {
83
95
  if (context.session) return allow();
84
96
  return resolveUnauthenticatedRedirect(context);
85
- };
97
+ }, { kind: "auth" });
86
98
  }
87
99
  function requireGuest() {
88
- return (context) => {
100
+ return markBuiltInRoutePolicy((context) => {
89
101
  if (!context.session) return allow();
90
102
  return resolveAuthenticatedRedirect(context);
91
- };
103
+ }, { kind: "guest" });
92
104
  }
93
105
  function requireRole(role) {
94
- return (context) => {
106
+ return markBuiltInRoutePolicy((context) => {
95
107
  if (!context.user) return resolveUnauthenticatedRedirect(context);
96
108
  const auth = assertRouteAuthOptions(context);
97
109
  const hasRole = auth.hasRole ? auth.hasRole(context.user, role, context) : defaultHasRole(context.user, role);
98
110
  if (isPromiseLike(hasRole)) return Promise.resolve(hasRole).then((next) => next ? allow() : forbidden());
99
111
  return hasRole ? allow() : forbidden();
100
- };
112
+ }, {
113
+ kind: "role",
114
+ value: role
115
+ });
101
116
  }
102
117
  function requirePermission(permission) {
103
- return (context) => {
118
+ return markBuiltInRoutePolicy((context) => {
104
119
  if (!context.user) return resolveUnauthenticatedRedirect(context);
105
120
  const auth = assertRouteAuthOptions(context);
106
121
  const hasPermission = auth.hasPermission ? auth.hasPermission(context.user, permission, context) : defaultHasPermission(context.user, permission);
107
122
  if (isPromiseLike(hasPermission)) return Promise.resolve(hasPermission).then((next) => next ? allow() : forbidden());
108
123
  return hasPermission ? allow() : forbidden();
109
- };
124
+ }, {
125
+ kind: "permission",
126
+ value: permission
127
+ });
110
128
  }
111
129
  //#endregion
112
- export { allow, deny, forbidden, notFound, redirect, requireAuth, requireGuest, requirePermission, requireRole, unauthorized, withRouteAuthOptions };
130
+ export { _getBuiltInRoutePolicy, allow, deny, forbidden, notFound, redirect, requireAuth, requireGuest, requirePermission, requireRole, unauthorized, withRouteAuthOptions };
113
131
 
114
132
  //# sourceMappingURL=policy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","names":[],"sources":["../../src/router/policy.ts"],"sourcesContent":["import type {\n AccessDecision,\n AccessAllowDecision,\n AccessDenyDecision,\n AccessDenyStatus,\n AccessRedirectDecision,\n AccessRedirectStatus,\n RouteAuthOptions,\n RouteContext,\n RoutePolicy,\n} from '../common/router';\nimport { isPromiseLike } from '../common/promise';\n\nconst ROUTE_AUTH_OPTIONS = Symbol.for('__ASKR_ROUTE_AUTH_OPTIONS__');\n\ntype InternalRouteContext = RouteContext & {\n [ROUTE_AUTH_OPTIONS]?: RouteAuthOptions;\n};\n\ntype RoutePathResolver =\n | string\n | ((context: RouteContext) => string | PromiseLike<string>);\n\nexport function allow(): AccessAllowDecision {\n return { kind: 'allow' };\n}\n\nexport function redirect(\n to: string,\n init: {\n status?: AccessRedirectStatus;\n replace?: boolean;\n } = {}\n): AccessRedirectDecision {\n return {\n kind: 'redirect',\n to,\n ...(init.status ? { status: init.status } : {}),\n ...(init.replace !== undefined ? { replace: init.replace } : {}),\n };\n}\n\nexport function deny(status: AccessDenyStatus): AccessDenyDecision {\n return { kind: 'deny', status };\n}\n\nexport function unauthorized(): AccessDenyDecision {\n return deny(401);\n}\n\nexport function forbidden(): AccessDenyDecision {\n return deny(403);\n}\n\nexport function notFound(): AccessDenyDecision {\n return deny(404);\n}\n\nexport function normalizeAccessDecision(\n result: AccessDecision\n): AccessDecision {\n return result;\n}\n\nexport function withRouteAuthOptions(\n context: RouteContext,\n auth: RouteAuthOptions | undefined\n): RouteContext {\n const internal = context as InternalRouteContext;\n\n if (!auth) {\n delete internal[ROUTE_AUTH_OPTIONS];\n return context;\n }\n\n internal[ROUTE_AUTH_OPTIONS] = auth;\n return context;\n}\n\nfunction getRouteAuthOptions(\n context: RouteContext\n): RouteAuthOptions | undefined {\n return (context as InternalRouteContext)[ROUTE_AUTH_OPTIONS];\n}\n\nfunction assertRouteAuthOptions(context: RouteContext): RouteAuthOptions {\n const auth = getRouteAuthOptions(context);\n if (!auth?.resolve) {\n throw new Error(\n 'Built-in auth policies require router auth configuration. ' +\n 'Provide `auth` to registerRoutes(...), createSPA(...), hydrateSPA(...), or SSR route resolution.'\n );\n }\n\n return auth;\n}\n\nfunction resolvePathSetting(\n value: RoutePathResolver | undefined,\n fallback: string,\n context: RouteContext\n): string | PromiseLike<string> {\n if (!value) {\n return fallback;\n }\n\n if (typeof value === 'function') {\n return value(context);\n }\n\n return value;\n}\n\nfunction appendNextTarget(path: string, href: string): string {\n const resolved = new URL(path, 'http://localhost');\n resolved.searchParams.set('next', href);\n return `${resolved.pathname}${resolved.search}${resolved.hash}`;\n}\n\nfunction collectStringValues(value: unknown): string[] {\n if (typeof value === 'string') {\n return [value];\n }\n\n if (Array.isArray(value)) {\n return value.filter((entry): entry is string => typeof entry === 'string');\n }\n\n if (value instanceof Set) {\n return Array.from(value).filter(\n (entry): entry is string => typeof entry === 'string'\n );\n }\n\n return [];\n}\n\nfunction defaultHasRole(user: unknown, role: string): boolean {\n if (!user || typeof user !== 'object') {\n return false;\n }\n\n return collectStringValues((user as { roles?: unknown }).roles).includes(\n role\n );\n}\n\nfunction defaultHasPermission(user: unknown, permission: string): boolean {\n if (!user || typeof user !== 'object') {\n return false;\n }\n\n return collectStringValues(\n (user as { permissions?: unknown }).permissions\n ).includes(permission);\n}\n\nfunction resolveUnauthenticatedRedirect(\n context: RouteContext\n): AccessDecision | Promise<AccessDecision> {\n const auth = assertRouteAuthOptions(context);\n const loginPath = resolvePathSetting(auth.loginPath, '/login', context);\n if (isPromiseLike<string>(loginPath)) {\n return Promise.resolve(loginPath).then((nextPath) =>\n redirect(appendNextTarget(nextPath, context.href), {\n replace: context.mode === 'spa',\n })\n );\n }\n\n return redirect(appendNextTarget(loginPath, context.href), {\n replace: context.mode === 'spa',\n });\n}\n\nfunction resolveAuthenticatedRedirect(\n context: RouteContext\n): AccessDecision | Promise<AccessDecision> {\n const auth = assertRouteAuthOptions(context);\n const target = resolvePathSetting(auth.guestRedirectTo, '/', context);\n if (isPromiseLike<string>(target)) {\n return Promise.resolve(target).then((nextTarget) =>\n redirect(nextTarget, {\n replace: true,\n })\n );\n }\n\n return redirect(target, {\n replace: true,\n });\n}\n\nexport function requireAuth(): RoutePolicy {\n return (context) => {\n if (context.session) {\n return allow();\n }\n\n return resolveUnauthenticatedRedirect(context);\n };\n}\n\nexport function requireGuest(): RoutePolicy {\n return (context) => {\n if (!context.session) {\n return allow();\n }\n\n return resolveAuthenticatedRedirect(context);\n };\n}\n\nexport function requireRole(role: string): RoutePolicy {\n return (context) => {\n if (!context.user) {\n return resolveUnauthenticatedRedirect(context);\n }\n\n const auth = assertRouteAuthOptions(context);\n const hasRole = auth.hasRole\n ? auth.hasRole(context.user, role, context)\n : defaultHasRole(context.user, role);\n\n if (isPromiseLike<boolean>(hasRole)) {\n return Promise.resolve(hasRole).then((next) =>\n next ? allow() : forbidden()\n );\n }\n\n return hasRole ? allow() : forbidden();\n };\n}\n\nexport function requirePermission(permission: string): RoutePolicy {\n return (context) => {\n if (!context.user) {\n return resolveUnauthenticatedRedirect(context);\n }\n\n const auth = assertRouteAuthOptions(context);\n const hasPermission = auth.hasPermission\n ? auth.hasPermission(context.user, permission, context)\n : defaultHasPermission(context.user, permission);\n\n if (isPromiseLike<boolean>(hasPermission)) {\n return Promise.resolve(hasPermission).then((next) =>\n next ? allow() : forbidden()\n );\n }\n\n return hasPermission ? allow() : forbidden();\n };\n}\n\nexport async function evaluateRoutePolicy(\n policy: RoutePolicy,\n context: RouteContext\n): Promise<AccessDecision> {\n const result = await policy(context);\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"policy.js","names":[],"sources":["../../src/router/policy.ts"],"sourcesContent":["import type {\n AccessDecision,\n AccessAllowDecision,\n AccessDenyDecision,\n AccessDenyStatus,\n AccessRedirectDecision,\n AccessRedirectStatus,\n RouteAuthOptions,\n RouteContext,\n RoutePolicy,\n} from '../common/router';\nimport { isPromiseLike } from '../common/promise';\n\nconst ROUTE_AUTH_OPTIONS = Symbol.for('__ASKR_ROUTE_AUTH_OPTIONS__');\nconst BUILT_IN_ROUTE_POLICY = Symbol.for('__ASKR_BUILT_IN_ROUTE_POLICY__');\n\ntype InternalRouteContext = RouteContext & {\n [ROUTE_AUTH_OPTIONS]?: RouteAuthOptions;\n};\n\nexport type BuiltInRoutePolicyKind = 'auth' | 'guest' | 'role' | 'permission';\n\nexport interface BuiltInRoutePolicyMetadata {\n kind: BuiltInRoutePolicyKind;\n value?: string;\n}\n\ntype InternalRoutePolicy = RoutePolicy & {\n [BUILT_IN_ROUTE_POLICY]?: BuiltInRoutePolicyMetadata;\n};\n\ntype RoutePathResolver =\n | string\n | ((context: RouteContext) => string | PromiseLike<string>);\n\nexport function allow(): AccessAllowDecision {\n return { kind: 'allow' };\n}\n\nexport function redirect(\n to: string,\n init: {\n status?: AccessRedirectStatus;\n replace?: boolean;\n } = {}\n): AccessRedirectDecision {\n return {\n kind: 'redirect',\n to,\n ...(init.status ? { status: init.status } : {}),\n ...(init.replace !== undefined ? { replace: init.replace } : {}),\n };\n}\n\nexport function deny(status: AccessDenyStatus): AccessDenyDecision {\n return { kind: 'deny', status };\n}\n\nexport function unauthorized(): AccessDenyDecision {\n return deny(401);\n}\n\nexport function forbidden(): AccessDenyDecision {\n return deny(403);\n}\n\nexport function notFound(): AccessDenyDecision {\n return deny(404);\n}\n\nexport function normalizeAccessDecision(\n result: AccessDecision\n): AccessDecision {\n return result;\n}\n\nexport function withRouteAuthOptions(\n context: RouteContext,\n auth: RouteAuthOptions | undefined\n): RouteContext {\n const internal = context as InternalRouteContext;\n\n if (!auth) {\n delete internal[ROUTE_AUTH_OPTIONS];\n return context;\n }\n\n internal[ROUTE_AUTH_OPTIONS] = auth;\n return context;\n}\n\nfunction getRouteAuthOptions(\n context: RouteContext\n): RouteAuthOptions | undefined {\n return (context as InternalRouteContext)[ROUTE_AUTH_OPTIONS];\n}\n\nfunction assertRouteAuthOptions(context: RouteContext): RouteAuthOptions {\n const auth = getRouteAuthOptions(context);\n if (!auth?.resolve) {\n throw new Error(\n 'Built-in auth policies require router auth configuration. ' +\n 'Provide `auth` to registerRoutes(...), createSPA(...), hydrateSPA(...), or SSR route resolution.'\n );\n }\n\n return auth;\n}\n\nfunction markBuiltInRoutePolicy(\n policy: RoutePolicy,\n metadata: BuiltInRoutePolicyMetadata\n): RoutePolicy {\n Object.defineProperty(policy, BUILT_IN_ROUTE_POLICY, {\n value: Object.freeze({ ...metadata }),\n enumerable: false,\n configurable: false,\n });\n return policy;\n}\n\nexport function _getBuiltInRoutePolicy(\n policy: RoutePolicy\n): BuiltInRoutePolicyMetadata | null {\n return (policy as InternalRoutePolicy)[BUILT_IN_ROUTE_POLICY] ?? null;\n}\n\nfunction resolvePathSetting(\n value: RoutePathResolver | undefined,\n fallback: string,\n context: RouteContext\n): string | PromiseLike<string> {\n if (!value) {\n return fallback;\n }\n\n if (typeof value === 'function') {\n return value(context);\n }\n\n return value;\n}\n\nfunction appendNextTarget(path: string, href: string): string {\n const resolved = new URL(path, 'http://localhost');\n resolved.searchParams.set('next', href);\n return `${resolved.pathname}${resolved.search}${resolved.hash}`;\n}\n\nfunction collectStringValues(value: unknown): string[] {\n if (typeof value === 'string') {\n return [value];\n }\n\n if (Array.isArray(value)) {\n return value.filter((entry): entry is string => typeof entry === 'string');\n }\n\n if (value instanceof Set) {\n return Array.from(value).filter(\n (entry): entry is string => typeof entry === 'string'\n );\n }\n\n return [];\n}\n\nfunction defaultHasRole(user: unknown, role: string): boolean {\n if (!user || typeof user !== 'object') {\n return false;\n }\n\n return collectStringValues((user as { roles?: unknown }).roles).includes(\n role\n );\n}\n\nfunction defaultHasPermission(user: unknown, permission: string): boolean {\n if (!user || typeof user !== 'object') {\n return false;\n }\n\n return collectStringValues(\n (user as { permissions?: unknown }).permissions\n ).includes(permission);\n}\n\nfunction resolveUnauthenticatedRedirect(\n context: RouteContext\n): AccessDecision | Promise<AccessDecision> {\n const auth = assertRouteAuthOptions(context);\n const loginPath = resolvePathSetting(auth.loginPath, '/login', context);\n if (isPromiseLike<string>(loginPath)) {\n return Promise.resolve(loginPath).then((nextPath) =>\n redirect(appendNextTarget(nextPath, context.href), {\n replace: context.mode === 'spa',\n })\n );\n }\n\n return redirect(appendNextTarget(loginPath, context.href), {\n replace: context.mode === 'spa',\n });\n}\n\nfunction resolveAuthenticatedRedirect(\n context: RouteContext\n): AccessDecision | Promise<AccessDecision> {\n const auth = assertRouteAuthOptions(context);\n const target = resolvePathSetting(auth.guestRedirectTo, '/', context);\n if (isPromiseLike<string>(target)) {\n return Promise.resolve(target).then((nextTarget) =>\n redirect(nextTarget, {\n replace: true,\n })\n );\n }\n\n return redirect(target, {\n replace: true,\n });\n}\n\nexport function requireAuth(): RoutePolicy {\n return markBuiltInRoutePolicy(\n (context) => {\n if (context.session) {\n return allow();\n }\n\n return resolveUnauthenticatedRedirect(context);\n },\n { kind: 'auth' }\n );\n}\n\nexport function requireGuest(): RoutePolicy {\n return markBuiltInRoutePolicy(\n (context) => {\n if (!context.session) {\n return allow();\n }\n\n return resolveAuthenticatedRedirect(context);\n },\n { kind: 'guest' }\n );\n}\n\nexport function requireRole(role: string): RoutePolicy {\n return markBuiltInRoutePolicy(\n (context) => {\n if (!context.user) {\n return resolveUnauthenticatedRedirect(context);\n }\n\n const auth = assertRouteAuthOptions(context);\n const hasRole = auth.hasRole\n ? auth.hasRole(context.user, role, context)\n : defaultHasRole(context.user, role);\n\n if (isPromiseLike<boolean>(hasRole)) {\n return Promise.resolve(hasRole).then((next) =>\n next ? allow() : forbidden()\n );\n }\n\n return hasRole ? allow() : forbidden();\n },\n { kind: 'role', value: role }\n );\n}\n\nexport function requirePermission(permission: string): RoutePolicy {\n return markBuiltInRoutePolicy(\n (context) => {\n if (!context.user) {\n return resolveUnauthenticatedRedirect(context);\n }\n\n const auth = assertRouteAuthOptions(context);\n const hasPermission = auth.hasPermission\n ? auth.hasPermission(context.user, permission, context)\n : defaultHasPermission(context.user, permission);\n\n if (isPromiseLike<boolean>(hasPermission)) {\n return Promise.resolve(hasPermission).then((next) =>\n next ? allow() : forbidden()\n );\n }\n\n return hasPermission ? allow() : forbidden();\n },\n { kind: 'permission', value: permission }\n );\n}\n\nexport async function evaluateRoutePolicy(\n policy: RoutePolicy,\n context: RouteContext\n): Promise<AccessDecision> {\n const result = await policy(context);\n return result;\n}\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { JSXElement } from "../common/jsx.js";
2
+ import { LayoutScopeRecord, PageScopeRecord, RouteComponent, RouteHandler, RouteRecord } from "../common/router.js";
3
+
4
+ //#region src/router/rendering.d.ts
5
+ declare function Outlet(): JSXElement;
6
+ declare function createRouteHandler(component: RouteComponent, pageChain: readonly PageScopeRecord[], layoutChain: readonly LayoutScopeRecord[], deferComponents?: boolean): RouteHandler;
7
+ declare function getRenderHandler(record: RouteRecord): RouteHandler;
8
+ //#endregion
9
+ export { Outlet };
10
+ //# sourceMappingURL=rendering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rendering.d.ts","names":[],"sources":["../../src/router/rendering.ts"],"mappings":";;;;iBAegB,MAAA,IAAU,UAAU;AAAA,iBA2CpB,kBAAA,CACd,SAAA,EAAW,cAAA,EACX,SAAA,WAAoB,eAAA,IACpB,WAAA,WAAsB,iBAAA,IACtB,eAAA,aACC,YAAA;AAAA,iBAgBa,gBAAA,CAAiB,MAAA,EAAQ,WAAA,GAAc,YAAY"}
@@ -0,0 +1,45 @@
1
+ import { ELEMENT_TYPE, Fragment } from "../common/jsx.js";
2
+ import { defineContext, readContext } from "../runtime/context.js";
3
+ import { ROUTE_ROOT_COMPONENT } from "../common/router-internal.js";
4
+ //#region src/router/rendering.ts
5
+ const outletContext = defineContext(null);
6
+ function Outlet() {
7
+ return {
8
+ $$typeof: ELEMENT_TYPE,
9
+ type: Fragment,
10
+ props: { children: readContext(outletContext) },
11
+ key: null
12
+ };
13
+ }
14
+ function applyPageChain(pageChain, params, content, deferComponents = false) {
15
+ let nextContent = content;
16
+ for (let i = pageChain.length - 1; i >= 0; i--) nextContent = outletContext.Scope({
17
+ value: nextContent,
18
+ children: deferComponents ? createRouteComponentVNode(pageChain[i].component, params) : pageChain[i].component(params)
19
+ });
20
+ return nextContent;
21
+ }
22
+ function createRouteComponentVNode(component, params, routeRoot = false) {
23
+ return {
24
+ $$typeof: ELEMENT_TYPE,
25
+ type: component,
26
+ props: params,
27
+ key: null,
28
+ ...routeRoot ? { [ROUTE_ROOT_COMPONENT]: true } : {}
29
+ };
30
+ }
31
+ function createRouteHandler(component, pageChain, layoutChain, deferComponents = false) {
32
+ return (params) => {
33
+ let content = deferComponents ? createRouteComponentVNode(component, params, true) : component(params);
34
+ content = applyPageChain(pageChain, params, content, deferComponents);
35
+ for (let i = layoutChain.length - 1; i >= 0; i--) content = layoutChain[i].component({ children: content });
36
+ return content;
37
+ };
38
+ }
39
+ function getRenderHandler(record) {
40
+ return record.renderHandler ?? createRouteHandler(record.component, record.pageChain, record.layoutChain, true);
41
+ }
42
+ //#endregion
43
+ export { Outlet, createRouteHandler, getRenderHandler };
44
+
45
+ //# sourceMappingURL=rendering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rendering.js","names":[],"sources":["../../src/router/rendering.ts"],"sourcesContent":["import { ELEMENT_TYPE, Fragment, type JSXElement } from '../common/jsx';\nimport type {\n LayoutScopeRecord,\n PageScopeRecord,\n RouteComponent,\n RouteHandler,\n RouteRecord,\n} from '../common/router';\nimport { ROUTE_ROOT_COMPONENT } from '../common/router-internal';\nimport type { RenderableChild } from '../common/vnode';\nimport { defineContext, readContext } from '../runtime/context';\nimport type { InternalRouteRecord } from './internal-types';\n\nconst outletContext = defineContext<RenderableChild>(null);\n\nexport function Outlet(): JSXElement {\n return {\n $$typeof: ELEMENT_TYPE,\n type: Fragment,\n props: { children: readContext(outletContext) },\n key: null,\n };\n}\n\nfunction applyPageChain(\n pageChain: readonly PageScopeRecord[],\n params: Record<string, string>,\n content: RenderableChild,\n deferComponents = false\n): RenderableChild {\n let nextContent = content;\n\n for (let i = pageChain.length - 1; i >= 0; i--) {\n nextContent = outletContext.Scope({\n value: nextContent,\n children: deferComponents\n ? createRouteComponentVNode(pageChain[i].component, params)\n : pageChain[i].component(params),\n });\n }\n\n return nextContent;\n}\n\nfunction createRouteComponentVNode(\n component: RouteComponent,\n params: Record<string, string>,\n routeRoot = false\n): RenderableChild {\n return {\n $$typeof: ELEMENT_TYPE,\n type: component,\n props: params,\n key: null,\n ...(routeRoot ? { [ROUTE_ROOT_COMPONENT]: true } : {}),\n };\n}\n\nexport function createRouteHandler(\n component: RouteComponent,\n pageChain: readonly PageScopeRecord[],\n layoutChain: readonly LayoutScopeRecord[],\n deferComponents = false\n): RouteHandler {\n return (params) => {\n let content = deferComponents\n ? createRouteComponentVNode(component, params, true)\n : component(params);\n\n content = applyPageChain(pageChain, params, content, deferComponents);\n\n for (let i = layoutChain.length - 1; i >= 0; i--) {\n content = layoutChain[i].component({ children: content });\n }\n\n return content;\n };\n}\n\nexport function getRenderHandler(record: RouteRecord): RouteHandler {\n const internalRecord = record as InternalRouteRecord;\n return (\n internalRecord.renderHandler ??\n createRouteHandler(\n record.component,\n record.pageChain,\n record.layoutChain,\n true\n )\n );\n}\n"],"mappings":";;;;AAaA,MAAM,gBAAgB,cAA+B,IAAI;AAEzD,SAAgB,SAAqB;CACnC,OAAO;EACL,UAAU;EACV,MAAM;EACN,OAAO,EAAE,UAAU,YAAY,aAAa,EAAE;EAC9C,KAAK;CACP;AACF;AAEA,SAAS,eACP,WACA,QACA,SACA,kBAAkB,OACD;CACjB,IAAI,cAAc;CAElB,KAAK,IAAI,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KACzC,cAAc,cAAc,MAAM;EAChC,OAAO;EACP,UAAU,kBACN,0BAA0B,UAAU,EAAE,CAAC,WAAW,MAAM,IACxD,UAAU,EAAE,CAAC,UAAU,MAAM;CACnC,CAAC;CAGH,OAAO;AACT;AAEA,SAAS,0BACP,WACA,QACA,YAAY,OACK;CACjB,OAAO;EACL,UAAU;EACV,MAAM;EACN,OAAO;EACP,KAAK;EACL,GAAI,YAAY,GAAG,uBAAuB,KAAK,IAAI,CAAC;CACtD;AACF;AAEA,SAAgB,mBACd,WACA,WACA,aACA,kBAAkB,OACJ;CACd,QAAQ,WAAW;EACjB,IAAI,UAAU,kBACV,0BAA0B,WAAW,QAAQ,IAAI,IACjD,UAAU,MAAM;EAEpB,UAAU,eAAe,WAAW,QAAQ,SAAS,eAAe;EAEpE,KAAK,IAAI,IAAI,YAAY,SAAS,GAAG,KAAK,GAAG,KAC3C,UAAU,YAAY,EAAE,CAAC,UAAU,EAAE,UAAU,QAAQ,CAAC;EAG1D,OAAO;CACT;AACF;AAEA,SAAgB,iBAAiB,QAAmC;CAElE,OACE,OAAe,iBACf,mBACE,OAAO,WACP,OAAO,WACP,OAAO,aACP,IACF;AAEJ"}
@@ -0,0 +1,17 @@
1
+ import { ResolvedRoute, Route, RouteManifest, RouteMatch, RouteRecord, RouteRequestOptions, RouteRequestResult } from "../common/router.js";
2
+
3
+ //#region src/router/resolution.d.ts
4
+ declare function computeMatchesFromRoutes(pathname: string, routesList: readonly Route[]): RouteMatch[];
5
+ declare function computeMatchesFromRouteRecords(pathname: string, routeRecords: readonly RouteRecord[]): RouteMatch[];
6
+ declare function computeRouteActivityMatches(pathname: string, options?: {
7
+ manifest?: RouteManifest;
8
+ routes?: readonly Route[];
9
+ }): RouteMatch[];
10
+ declare function resolveRoute(pathname: string): ResolvedRoute | null;
11
+ declare function resolveRouteRequest(target: string, options?: RouteRequestOptions): RouteRequestResult | Promise<RouteRequestResult>;
12
+ declare function resolveRouteFromRoutes(pathname: string, routeList: readonly Route[]): ResolvedRoute | null;
13
+ declare function _resolveRouteMatchFromRoutes(pathname: string, routeList: readonly Route[]): {
14
+ route: Route;
15
+ params: Record<string, string>;
16
+ } | null;
17
+ //# sourceMappingURL=resolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution.d.ts","names":[],"sources":["../../src/router/resolution.ts"],"mappings":";;;iBAsPgB,wBAAA,CACd,QAAA,UACA,UAAA,WAAqB,KAAA,KACpB,UAAU;AAAA,iBAyBG,8BAAA,CACd,QAAA,UACA,YAAA,WAAuB,WAAA,KACtB,UAAU;AAAA,iBAgBG,2BAAA,CACd,QAAA,UACA,OAAA;EACE,QAAA,GAAW,aAAA;EACX,MAAA,YAAkB,KAAA;AAAA,IAEnB,UAAA;AAAA,iBAYa,YAAA,CAAa,QAAA,WAAmB,aAAa;AAAA,iBA+H7C,mBAAA,CACd,MAAA,UACA,OAAA,GAAS,mBAAA,GACR,kBAAA,GAAqB,OAAA,CAAQ,kBAAA;AAAA,iBAsDhB,sBAAA,CACd,QAAA,UACA,SAAA,WAAoB,KAAA,KACnB,aAAa;AAAA,iBAOA,4BAAA,CACd,QAAA,UACA,SAAA,WAAoB,KAAA;EACjB,KAAA,EAAO,KAAA;EAAO,MAAA,EAAQ,MAAA;AAAA"}
@@ -0,0 +1,253 @@
1
+ import { isPromiseLike } from "../common/promise.js";
2
+ import { computeRank, matchSegments, parseSegments, splitPathSegments } from "./match.js";
3
+ import { compileNodePolicies } from "./access.js";
4
+ import { getRenderHandler } from "./rendering.js";
5
+ import { getActiveRenderContext } from "../common/render-context.js";
6
+ import { getActiveRouteAuthOptions, getActiveRoutes, getRouteRecords, isRouteStoreRoutes } from "./store.js";
7
+ import { buildRouteContext, buildRouteContextBase, deepFreeze, parseLocation } from "./route-context.js";
8
+ //#region src/router/resolution.ts
9
+ const routeSegsCache = /* @__PURE__ */ new WeakMap();
10
+ const routeRankCache = /* @__PURE__ */ new WeakMap();
11
+ const sortedListCache = /* @__PURE__ */ new WeakMap();
12
+ function cachedSegs(route) {
13
+ let segments = routeSegsCache.get(route);
14
+ if (!segments) {
15
+ segments = parseSegments(route.path);
16
+ routeSegsCache.set(route, segments);
17
+ }
18
+ return segments;
19
+ }
20
+ function cachedRank(route) {
21
+ let rank = routeRankCache.get(route);
22
+ if (rank === void 0) {
23
+ rank = computeRank(cachedSegs(route));
24
+ routeRankCache.set(route, rank);
25
+ }
26
+ return rank;
27
+ }
28
+ function cachedSortedList(routeList) {
29
+ let sorted = sortedListCache.get(routeList);
30
+ if (!sorted) {
31
+ sorted = [...routeList].sort((a, b) => cachedRank(b) - cachedRank(a));
32
+ sortedListCache.set(routeList, sorted);
33
+ }
34
+ return sorted;
35
+ }
36
+ function matchFallbackPrefix(pathname, fallbackPrefix) {
37
+ const normalizedPath = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
38
+ const normalizedPrefix = fallbackPrefix.endsWith("/") && fallbackPrefix !== "/" ? fallbackPrefix.slice(0, -1) : fallbackPrefix;
39
+ if (normalizedPrefix === "/") {
40
+ const urlParts = splitPathSegments(normalizedPath);
41
+ return { "*": urlParts.length === 0 ? "/" : urlParts.length === 1 ? urlParts[0] : "/" + urlParts.join("/") };
42
+ }
43
+ if (normalizedPath !== normalizedPrefix && !normalizedPath.startsWith(`${normalizedPrefix}/`)) return null;
44
+ const remainderParts = splitPathSegments(normalizedPath === normalizedPrefix ? "/" : normalizedPath.slice(normalizedPrefix.length));
45
+ return { "*": remainderParts.length === 0 ? "/" : remainderParts.length === 1 ? remainderParts[0] : "/" + remainderParts.join("/") };
46
+ }
47
+ function findBestResolvedRouteFromRoutes(pathname, routeList) {
48
+ const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
49
+ const urlParts = splitPathSegments(normalized);
50
+ const sorted = cachedSortedList(routeList);
51
+ let bestRoute = null;
52
+ let bestParams = {};
53
+ let bestRank = -Infinity;
54
+ for (const route of sorted) {
55
+ if (route.fallbackPrefix) continue;
56
+ const rank = cachedRank(route);
57
+ if (rank < bestRank) break;
58
+ if (bestRoute !== null && rank === bestRank) continue;
59
+ const params = matchSegments(urlParts, cachedSegs(route));
60
+ if (params !== null) {
61
+ bestRoute = route;
62
+ bestParams = params;
63
+ bestRank = rank;
64
+ }
65
+ }
66
+ if (bestRoute !== null) return {
67
+ route: bestRoute,
68
+ params: bestParams
69
+ };
70
+ let bestFallback = null;
71
+ let bestFallbackParams = null;
72
+ let bestPrefixLength = -1;
73
+ for (const route of routeList) {
74
+ const internalRoute = route;
75
+ if (!internalRoute.fallbackPrefix) continue;
76
+ const params = matchFallbackPrefix(normalized, internalRoute.fallbackPrefix);
77
+ if (params === null) continue;
78
+ if (internalRoute.fallbackPrefix.length > bestPrefixLength) {
79
+ bestFallback = internalRoute;
80
+ bestFallbackParams = params;
81
+ bestPrefixLength = internalRoute.fallbackPrefix.length;
82
+ }
83
+ }
84
+ return bestFallback && bestFallbackParams ? {
85
+ route: bestFallback,
86
+ params: bestFallbackParams
87
+ } : null;
88
+ }
89
+ function findBestScopedFallbackRecord(pathname, routeRecords) {
90
+ let bestRecord = null;
91
+ let bestParams = null;
92
+ let bestPrefixLength = -1;
93
+ for (const routeRecord of routeRecords) {
94
+ const record = routeRecord;
95
+ if (!record.fallbackPrefix) continue;
96
+ const params = matchFallbackPrefix(pathname, record.fallbackPrefix);
97
+ if (params === null) continue;
98
+ if (record.fallbackPrefix.length > bestPrefixLength) {
99
+ bestRecord = record;
100
+ bestParams = params;
101
+ bestPrefixLength = record.fallbackPrefix.length;
102
+ }
103
+ }
104
+ return bestRecord && bestParams ? {
105
+ record: bestRecord,
106
+ params: bestParams
107
+ } : null;
108
+ }
109
+ function getMatchingRecord(target, routeRecords) {
110
+ const location = parseLocation(target);
111
+ const normalized = location.pathname.endsWith("/") && location.pathname !== "/" ? location.pathname.slice(0, -1) : location.pathname;
112
+ const urlParts = splitPathSegments(normalized);
113
+ for (const record of routeRecords) {
114
+ if (record.fallbackPrefix) continue;
115
+ const params = matchSegments(urlParts, record.segments);
116
+ if (params !== null) return {
117
+ record,
118
+ params
119
+ };
120
+ }
121
+ return findBestScopedFallbackRecord(normalized, routeRecords);
122
+ }
123
+ function computeMatchesFromRoutes(pathname, routesList) {
124
+ const bestMatch = isRouteStoreRoutes(routesList) ? getMatchingRecord(pathname, getRouteRecords()) : findBestResolvedRouteFromRoutes(pathname, routesList);
125
+ if (!bestMatch) return [];
126
+ return [{
127
+ path: "route" in bestMatch ? bestMatch.route.path : bestMatch.record.path,
128
+ params: deepFreeze({ ...bestMatch.params }),
129
+ name: "route" in bestMatch ? bestMatch.route.name : void 0,
130
+ namespace: "route" in bestMatch ? bestMatch.route.namespace : bestMatch.record.options.namespace
131
+ }];
132
+ }
133
+ function computeMatchesFromRouteRecords(pathname, routeRecords) {
134
+ const bestMatch = getMatchingRecord(pathname, routeRecords);
135
+ if (!bestMatch) return [];
136
+ return [{
137
+ path: bestMatch.record.path,
138
+ params: deepFreeze({ ...bestMatch.params }),
139
+ namespace: bestMatch.record.options.namespace
140
+ }];
141
+ }
142
+ function computeRouteActivityMatches(pathname, options = {}) {
143
+ if (options.manifest) return computeMatchesFromRouteRecords(pathname, options.manifest.records);
144
+ if (options.routes) return computeMatchesFromRoutes(pathname, options.routes);
145
+ return computeMatchesFromRoutes(pathname, getActiveRoutes());
146
+ }
147
+ function resolveRoute(pathname) {
148
+ const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
149
+ const urlParts = splitPathSegments(normalized);
150
+ const records = getRouteRecords();
151
+ for (const record of records) {
152
+ if (record.fallbackPrefix) continue;
153
+ const params = matchSegments(urlParts, record.segments);
154
+ if (params !== null) return {
155
+ handler: record.handler,
156
+ params
157
+ };
158
+ }
159
+ const fallbackMatch = findBestScopedFallbackRecord(normalized, records);
160
+ return fallbackMatch ? {
161
+ handler: fallbackMatch.record.handler,
162
+ params: fallbackMatch.params
163
+ } : null;
164
+ }
165
+ function getRoutePolicies(options) {
166
+ if (!options) return [];
167
+ if (options.policies?.length) return options.policies;
168
+ return compileNodePolicies(options);
169
+ }
170
+ function getDefaultRouteMode() {
171
+ if (typeof window !== "undefined") return "spa";
172
+ return "ssr";
173
+ }
174
+ function createRenderDataAwareHandler(handler, data) {
175
+ return (params, context) => {
176
+ const renderContext = getActiveRenderContext();
177
+ if (renderContext) renderContext.renderData = data ?? null;
178
+ return handler(params, context);
179
+ };
180
+ }
181
+ function buildRenderResult(record, params, mode) {
182
+ const renderHandler = getRenderHandler(record);
183
+ const loader = mode === "ssr" ? record.options?.loader : void 0;
184
+ if (loader) {
185
+ const loaded = loader({ params });
186
+ const finalize = (data) => ({
187
+ kind: "render",
188
+ handler: createRenderDataAwareHandler(renderHandler, data),
189
+ params
190
+ });
191
+ if (isPromiseLike(loaded)) return Promise.resolve(loaded).then((data) => finalize(data));
192
+ return finalize(loaded);
193
+ }
194
+ return {
195
+ kind: "render",
196
+ handler: renderHandler,
197
+ params
198
+ };
199
+ }
200
+ function continueRoutePolicies(policies, context, record, params, startIndex = 0) {
201
+ for (let index = startIndex; index < policies.length; index += 1) {
202
+ const policyResult = policies[index](context);
203
+ if (isPromiseLike(policyResult)) return Promise.resolve(policyResult).then((next) => {
204
+ if (next.kind !== "allow") return next;
205
+ return continueRoutePolicies(policies, context, record, params, index + 1);
206
+ });
207
+ if (policyResult.kind !== "allow") return policyResult;
208
+ }
209
+ return buildRenderResult(record, params, context.mode);
210
+ }
211
+ function resolveRouteRequest(target, options = {}) {
212
+ const match = getMatchingRecord(target, options.manifest?.records ?? getRouteRecords());
213
+ if (!match) return null;
214
+ const { record, params } = match;
215
+ const policies = getRoutePolicies(record.options);
216
+ const mode = options.mode ?? getDefaultRouteMode();
217
+ if (policies.length === 0) return buildRenderResult(record, params, mode);
218
+ const signal = options.signal ?? getActiveRenderContext()?.signal ?? new AbortController().signal;
219
+ const auth = getActiveRouteAuthOptions(options.auth ?? options.manifest?.auth);
220
+ const baseContext = buildRouteContextBase(target, params, {
221
+ mode,
222
+ signal
223
+ });
224
+ const finalize = (authState) => continueRoutePolicies(policies, buildRouteContext(target, params, {
225
+ mode,
226
+ signal,
227
+ auth,
228
+ session: authState.session,
229
+ user: authState.user
230
+ }), record, params);
231
+ if (!auth?.resolve) return finalize({
232
+ session: null,
233
+ user: null
234
+ });
235
+ const authState = auth.resolve(baseContext);
236
+ if (isPromiseLike(authState)) return Promise.resolve(authState).then((next) => finalize(next));
237
+ return finalize(authState);
238
+ }
239
+ function resolveRouteFromRoutes(pathname, routeList) {
240
+ if (isRouteStoreRoutes(routeList)) return resolveRoute(pathname);
241
+ const match = findBestResolvedRouteFromRoutes(pathname, routeList);
242
+ return match ? {
243
+ handler: match.route.handler,
244
+ params: match.params
245
+ } : null;
246
+ }
247
+ function _resolveRouteMatchFromRoutes(pathname, routeList) {
248
+ return findBestResolvedRouteFromRoutes(pathname, routeList);
249
+ }
250
+ //#endregion
251
+ export { _resolveRouteMatchFromRoutes, computeMatchesFromRouteRecords, computeMatchesFromRoutes, computeRouteActivityMatches, resolveRoute, resolveRouteFromRoutes, resolveRouteRequest };
252
+
253
+ //# sourceMappingURL=resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution.js","names":[],"sources":["../../src/router/resolution.ts"],"sourcesContent":["import type {\n Route,\n RouteContext,\n RouteHandler,\n RouteManifest,\n RouteMatch,\n RouteOptions,\n RoutePolicy,\n RouteRecord,\n RouteRenderResult,\n RouteRequestOptions,\n RouteRequestResult,\n ResolvedRoute,\n} from '../common/router';\nimport { isPromiseLike } from '../common/promise';\nimport { getActiveRenderContext } from '../common/render-context';\nimport {\n buildRouteContext,\n buildRouteContextBase,\n deepFreeze,\n parseLocation,\n} from './route-context';\nimport { compileNodePolicies } from './access';\nimport {\n computeRank,\n matchSegments,\n parseSegments,\n splitPathSegments,\n} from './match';\nimport type { InternalRoute, InternalRouteRecord } from './internal-types';\nimport { getRenderHandler } from './rendering';\nimport {\n getActiveRouteAuthOptions,\n getActiveRoutes,\n getRouteRecords,\n isRouteStoreRoutes,\n} from './store';\n\nconst routeSegsCache = new WeakMap<Route, ReturnType<typeof parseSegments>>();\nconst routeRankCache = new WeakMap<Route, number>();\nconst sortedListCache = new WeakMap<\n ReadonlyArray<Route>,\n ReadonlyArray<Route>\n>();\n\nfunction cachedSegs(route: Route): ReturnType<typeof parseSegments> {\n let segments = routeSegsCache.get(route);\n if (!segments) {\n segments = parseSegments(route.path);\n routeSegsCache.set(route, segments);\n }\n return segments;\n}\n\nfunction cachedRank(route: Route): number {\n let rank = routeRankCache.get(route);\n if (rank === undefined) {\n rank = computeRank(cachedSegs(route));\n routeRankCache.set(route, rank);\n }\n return rank;\n}\n\nfunction cachedSortedList(\n routeList: ReadonlyArray<Route>\n): ReadonlyArray<Route> {\n let sorted = sortedListCache.get(routeList);\n if (!sorted) {\n sorted = [...routeList].sort((a, b) => cachedRank(b) - cachedRank(a));\n sortedListCache.set(routeList, sorted);\n }\n return sorted;\n}\n\nfunction matchFallbackPrefix(\n pathname: string,\n fallbackPrefix: string\n): Record<string, string> | null {\n const normalizedPath =\n pathname.endsWith('/') && pathname !== '/'\n ? pathname.slice(0, -1)\n : pathname;\n const normalizedPrefix =\n fallbackPrefix.endsWith('/') && fallbackPrefix !== '/'\n ? fallbackPrefix.slice(0, -1)\n : fallbackPrefix;\n\n if (normalizedPrefix === '/') {\n const urlParts = splitPathSegments(normalizedPath);\n return {\n '*':\n urlParts.length === 0\n ? '/'\n : urlParts.length === 1\n ? urlParts[0]\n : '/' + urlParts.join('/'),\n };\n }\n\n if (\n normalizedPath !== normalizedPrefix &&\n !normalizedPath.startsWith(`${normalizedPrefix}/`)\n ) {\n return null;\n }\n\n const remainder =\n normalizedPath === normalizedPrefix\n ? '/'\n : normalizedPath.slice(normalizedPrefix.length);\n const remainderParts = splitPathSegments(remainder);\n\n return {\n '*':\n remainderParts.length === 0\n ? '/'\n : remainderParts.length === 1\n ? remainderParts[0]\n : '/' + remainderParts.join('/'),\n };\n}\n\nfunction findBestResolvedRouteFromRoutes(\n pathname: string,\n routeList: readonly Route[]\n): { route: Route; params: Record<string, string> } | null {\n const normalized =\n pathname.endsWith('/') && pathname !== '/'\n ? pathname.slice(0, -1)\n : pathname;\n const urlParts = splitPathSegments(normalized);\n\n const sorted = cachedSortedList(routeList);\n let bestRoute: Route | null = null;\n let bestParams: Record<string, string> = {};\n let bestRank = -Infinity;\n\n for (const route of sorted) {\n const internalRoute = route as InternalRoute;\n if (internalRoute.fallbackPrefix) {\n continue;\n }\n\n const rank = cachedRank(route);\n if (rank < bestRank) break;\n if (bestRoute !== null && rank === bestRank) continue;\n\n const params = matchSegments(urlParts, cachedSegs(route));\n if (params !== null) {\n bestRoute = route;\n bestParams = params;\n bestRank = rank;\n }\n }\n\n if (bestRoute !== null) {\n return { route: bestRoute, params: bestParams };\n }\n\n let bestFallback: InternalRoute | null = null;\n let bestFallbackParams: Record<string, string> | null = null;\n let bestPrefixLength = -1;\n\n for (const route of routeList) {\n const internalRoute = route as InternalRoute;\n if (!internalRoute.fallbackPrefix) {\n continue;\n }\n\n const params = matchFallbackPrefix(\n normalized,\n internalRoute.fallbackPrefix\n );\n if (params === null) {\n continue;\n }\n\n if (internalRoute.fallbackPrefix.length > bestPrefixLength) {\n bestFallback = internalRoute;\n bestFallbackParams = params;\n bestPrefixLength = internalRoute.fallbackPrefix.length;\n }\n }\n\n return bestFallback && bestFallbackParams\n ? { route: bestFallback, params: bestFallbackParams }\n : null;\n}\n\nfunction findBestScopedFallbackRecord(\n pathname: string,\n routeRecords: readonly RouteRecord[]\n): { record: InternalRouteRecord; params: Record<string, string> } | null {\n let bestRecord: InternalRouteRecord | null = null;\n let bestParams: Record<string, string> | null = null;\n let bestPrefixLength = -1;\n\n for (const routeRecord of routeRecords) {\n const record = routeRecord as InternalRouteRecord;\n if (!record.fallbackPrefix) {\n continue;\n }\n\n const params = matchFallbackPrefix(pathname, record.fallbackPrefix);\n if (params === null) {\n continue;\n }\n\n if (record.fallbackPrefix.length > bestPrefixLength) {\n bestRecord = record;\n bestParams = params;\n bestPrefixLength = record.fallbackPrefix.length;\n }\n }\n\n return bestRecord && bestParams\n ? { record: bestRecord, params: bestParams }\n : null;\n}\n\nfunction getMatchingRecord(\n target: string,\n routeRecords: readonly RouteRecord[]\n): { record: RouteRecord; params: Record<string, string> } | null {\n const location = parseLocation(target);\n const normalized =\n location.pathname.endsWith('/') && location.pathname !== '/'\n ? location.pathname.slice(0, -1)\n : location.pathname;\n const urlParts = splitPathSegments(normalized);\n\n for (const record of routeRecords) {\n const internalRecord = record as InternalRouteRecord;\n if (internalRecord.fallbackPrefix) {\n continue;\n }\n\n const params = matchSegments(urlParts, record.segments);\n if (params !== null) {\n return { record, params };\n }\n }\n\n return findBestScopedFallbackRecord(normalized, routeRecords);\n}\n\nexport function computeMatchesFromRoutes(\n pathname: string,\n routesList: readonly Route[]\n): RouteMatch[] {\n const bestMatch = isRouteStoreRoutes(routesList)\n ? getMatchingRecord(pathname, getRouteRecords())\n : findBestResolvedRouteFromRoutes(pathname, routesList);\n\n if (!bestMatch) {\n return [];\n }\n\n return [\n {\n path: 'route' in bestMatch ? bestMatch.route.path : bestMatch.record.path,\n params: deepFreeze({ ...bestMatch.params }),\n name:\n 'route' in bestMatch\n ? (bestMatch.route as { name?: string }).name\n : undefined,\n namespace:\n 'route' in bestMatch\n ? bestMatch.route.namespace\n : bestMatch.record.options.namespace,\n },\n ];\n}\n\nexport function computeMatchesFromRouteRecords(\n pathname: string,\n routeRecords: readonly RouteRecord[]\n): RouteMatch[] {\n const bestMatch = getMatchingRecord(pathname, routeRecords);\n\n if (!bestMatch) {\n return [];\n }\n\n return [\n {\n path: bestMatch.record.path,\n params: deepFreeze({ ...bestMatch.params }),\n namespace: bestMatch.record.options.namespace,\n },\n ];\n}\n\nexport function computeRouteActivityMatches(\n pathname: string,\n options: {\n manifest?: RouteManifest;\n routes?: readonly Route[];\n } = {}\n): RouteMatch[] {\n if (options.manifest) {\n return computeMatchesFromRouteRecords(pathname, options.manifest.records);\n }\n\n if (options.routes) {\n return computeMatchesFromRoutes(pathname, options.routes);\n }\n\n return computeMatchesFromRoutes(pathname, getActiveRoutes());\n}\n\nexport function resolveRoute(pathname: string): ResolvedRoute | null {\n const normalized =\n pathname.endsWith('/') && pathname !== '/'\n ? pathname.slice(0, -1)\n : pathname;\n const urlParts = splitPathSegments(normalized);\n const records = getRouteRecords();\n\n for (const record of records) {\n if (record.fallbackPrefix) {\n continue;\n }\n\n const params = matchSegments(urlParts, record.segments);\n if (params !== null) {\n return { handler: record.handler, params };\n }\n }\n\n const fallbackMatch = findBestScopedFallbackRecord(normalized, records);\n return fallbackMatch\n ? { handler: fallbackMatch.record.handler, params: fallbackMatch.params }\n : null;\n}\n\nfunction getRoutePolicies(\n options: RouteOptions | undefined\n): readonly RoutePolicy[] {\n if (!options) {\n return [];\n }\n\n if (options.policies?.length) {\n return options.policies;\n }\n\n return compileNodePolicies(options);\n}\n\nfunction getDefaultRouteMode(): RouteContext['mode'] {\n if (typeof window !== 'undefined') {\n return 'spa';\n }\n\n return 'ssr';\n}\n\nfunction createRenderDataAwareHandler(\n handler: RouteHandler,\n data: unknown\n): RouteHandler {\n return (params, context) => {\n const renderContext = getActiveRenderContext();\n if (renderContext) {\n renderContext.renderData = (data ?? null) as Record<\n string,\n unknown\n > | null;\n }\n\n return handler(params, context);\n };\n}\n\nfunction buildRenderResult(\n record: RouteRecord,\n params: Record<string, string>,\n mode: RouteContext['mode']\n): RouteRequestResult | Promise<RouteRequestResult> {\n const renderHandler = getRenderHandler(record);\n const loader = mode === 'ssr' ? record.options?.loader : undefined;\n if (loader) {\n const loaded = loader({ params });\n const finalize = (data: unknown): RouteRenderResult => ({\n kind: 'render',\n handler: createRenderDataAwareHandler(renderHandler, data),\n params,\n });\n\n if (isPromiseLike(loaded)) {\n return Promise.resolve(loaded).then((data) => finalize(data));\n }\n\n return finalize(loaded);\n }\n\n return {\n kind: 'render',\n handler: renderHandler,\n params,\n };\n}\n\nfunction continueRoutePolicies(\n policies: readonly RoutePolicy[],\n context: RouteContext,\n record: RouteRecord,\n params: Record<string, string>,\n startIndex = 0\n): RouteRequestResult | Promise<RouteRequestResult> {\n for (let index = startIndex; index < policies.length; index += 1) {\n const policyResult = policies[index](context);\n\n if (isPromiseLike(policyResult)) {\n return Promise.resolve(policyResult).then((next) => {\n if (next.kind !== 'allow') {\n return next;\n }\n\n return continueRoutePolicies(\n policies,\n context,\n record,\n params,\n index + 1\n );\n });\n }\n\n if (policyResult.kind !== 'allow') {\n return policyResult;\n }\n }\n\n return buildRenderResult(record, params, context.mode);\n}\n\nexport function resolveRouteRequest(\n target: string,\n options: RouteRequestOptions = {}\n): RouteRequestResult | Promise<RouteRequestResult> {\n const routeRecords = options.manifest?.records ?? getRouteRecords();\n const match = getMatchingRecord(target, routeRecords);\n\n if (!match) {\n return null;\n }\n\n const { record, params } = match;\n const policies = getRoutePolicies(record.options);\n const mode = options.mode ?? getDefaultRouteMode();\n\n if (policies.length === 0) {\n return buildRenderResult(record, params, mode);\n }\n\n const signal =\n options.signal ??\n getActiveRenderContext()?.signal ??\n new AbortController().signal;\n const auth = getActiveRouteAuthOptions(\n options.auth ?? options.manifest?.auth\n );\n const baseContext = buildRouteContextBase(target, params, {\n mode,\n signal,\n });\n\n const finalize = (authState: { session: unknown; user: unknown }) =>\n continueRoutePolicies(\n policies,\n buildRouteContext(target, params, {\n mode,\n signal,\n auth,\n session: authState.session,\n user: authState.user,\n }),\n record,\n params\n );\n\n if (!auth?.resolve) {\n return finalize({ session: null, user: null });\n }\n\n const authState = auth.resolve(baseContext);\n if (isPromiseLike(authState)) {\n return Promise.resolve(authState).then((next) => finalize(next));\n }\n\n return finalize(authState);\n}\n\nexport function resolveRouteFromRoutes(\n pathname: string,\n routeList: readonly Route[]\n): ResolvedRoute | null {\n if (isRouteStoreRoutes(routeList)) return resolveRoute(pathname);\n\n const match = findBestResolvedRouteFromRoutes(pathname, routeList);\n return match ? { handler: match.route.handler, params: match.params } : null;\n}\n\nexport function _resolveRouteMatchFromRoutes(\n pathname: string,\n routeList: readonly Route[]\n): { route: Route; params: Record<string, string> } | null {\n return findBestResolvedRouteFromRoutes(pathname, routeList);\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ //#region src/router/route-query.d.ts
2
+ type RouteQueryParamValue = string | number | boolean | null | undefined;
3
+ type RouteQueryParamInput = RouteQueryParamValue | readonly RouteQueryParamValue[];
4
+ type RouteQueryUpdates = Record<string, RouteQueryParamInput>;
5
+ type RouteQueryUpdater = (searchParams: URLSearchParams) => void;
6
+ type UpdateRouteQueryOptions = {
7
+ /**
8
+ * Defaults to replace so high-frequency controls such as search inputs do not
9
+ * create one browser-history entry per character.
10
+ */
11
+ history?: 'push' | 'replace';
12
+ replace?: boolean;
13
+ };
14
+ declare function updateRouteQuery(updates: RouteQueryUpdates | RouteQueryUpdater, options?: UpdateRouteQueryOptions): void;
15
+ //#endregion
16
+ export { RouteQueryParamInput, RouteQueryParamValue, RouteQueryUpdater, RouteQueryUpdates, UpdateRouteQueryOptions, updateRouteQuery };
17
+ //# sourceMappingURL=route-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-query.d.ts","names":[],"sources":["../../src/router/route-query.ts"],"mappings":";KAWY,oBAAA;AAAA,KACA,oBAAA,GACR,oBAAA,YACS,oBAAoB;AAAA,KACrB,iBAAA,GAAoB,MAAM,SAAS,oBAAA;AAAA,KACnC,iBAAA,IAAqB,YAA6B,EAAf,eAAe;AAAA,KAElD,uBAAA;EAPoB;AAChC;;;EAWE,OAAA;EACA,OAAO;AAAA;AAAA,iBAmDO,gBAAA,CACd,OAAA,EAAS,iBAAA,GAAoB,iBAAA,EAC7B,OAAA,GAAS,uBAAA"}
@@ -0,0 +1,47 @@
1
+ import { saveScrollPosition } from "./navigation-scroll.js";
2
+ import { getCurrentHref, getRegisteredAppsSnapshot, getWindowHref, parseTargetUrl, setCurrentRouteLocation, syncAppRegistrationLocation, syncRegisteredRouteSnapshot } from "./navigation-registry.js";
3
+ //#region src/router/route-query.ts
4
+ function getRouteQueryHistoryMode(options) {
5
+ if (options.history) return options.history;
6
+ return options.replace === false ? "push" : "replace";
7
+ }
8
+ function setRouteQueryValue(searchParams, key, value) {
9
+ searchParams.delete(key);
10
+ if (Array.isArray(value)) {
11
+ for (const entry of value) {
12
+ if (entry === null || entry === void 0) continue;
13
+ searchParams.append(key, String(entry));
14
+ }
15
+ return;
16
+ }
17
+ if (value === null || value === void 0) return;
18
+ searchParams.set(key, String(value));
19
+ }
20
+ function applyRouteQueryUpdates(searchParams, updates) {
21
+ if (typeof updates === "function") {
22
+ updates(searchParams);
23
+ return;
24
+ }
25
+ for (const [key, value] of Object.entries(updates)) setRouteQueryValue(searchParams, key, value);
26
+ }
27
+ function updateRouteQuery(updates, options = {}) {
28
+ if (typeof window === "undefined") return;
29
+ const url = parseTargetUrl(getWindowHref());
30
+ applyRouteQueryUpdates(url.searchParams, updates);
31
+ const href = `${url.pathname}${url.search}${url.hash}`;
32
+ if (href === getWindowHref()) return;
33
+ const historyMode = getRouteQueryHistoryMode(options);
34
+ if (historyMode === "push") saveScrollPosition(getCurrentHref());
35
+ const state = window.history.state && typeof window.history.state === "object" ? window.history.state : {};
36
+ window.history[historyMode === "replace" ? "replaceState" : "pushState"]({
37
+ ...state,
38
+ path: href
39
+ }, "", href);
40
+ setCurrentRouteLocation(url.pathname, href);
41
+ for (const app of getRegisteredAppsSnapshot()) syncAppRegistrationLocation(app, url.pathname, href);
42
+ syncRegisteredRouteSnapshot();
43
+ }
44
+ //#endregion
45
+ export { updateRouteQuery };
46
+
47
+ //# sourceMappingURL=route-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-query.js","names":[],"sources":["../../src/router/route-query.ts"],"sourcesContent":["import { saveScrollPosition } from './navigation-scroll';\nimport {\n getCurrentHref,\n getRegisteredAppsSnapshot,\n getWindowHref,\n parseTargetUrl,\n setCurrentRouteLocation,\n syncAppRegistrationLocation,\n syncRegisteredRouteSnapshot,\n} from './navigation-registry';\n\nexport type RouteQueryParamValue = string | number | boolean | null | undefined;\nexport type RouteQueryParamInput =\n | RouteQueryParamValue\n | readonly RouteQueryParamValue[];\nexport type RouteQueryUpdates = Record<string, RouteQueryParamInput>;\nexport type RouteQueryUpdater = (searchParams: URLSearchParams) => void;\n\nexport type UpdateRouteQueryOptions = {\n /**\n * Defaults to replace so high-frequency controls such as search inputs do not\n * create one browser-history entry per character.\n */\n history?: 'push' | 'replace';\n replace?: boolean;\n};\n\nfunction getRouteQueryHistoryMode(\n options: UpdateRouteQueryOptions\n): 'push' | 'replace' {\n if (options.history) {\n return options.history;\n }\n\n return options.replace === false ? 'push' : 'replace';\n}\n\nfunction setRouteQueryValue(\n searchParams: URLSearchParams,\n key: string,\n value: RouteQueryParamInput\n): void {\n searchParams.delete(key);\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n if (entry === null || entry === undefined) {\n continue;\n }\n searchParams.append(key, String(entry));\n }\n return;\n }\n\n if (value === null || value === undefined) {\n return;\n }\n\n searchParams.set(key, String(value));\n}\n\nfunction applyRouteQueryUpdates(\n searchParams: URLSearchParams,\n updates: RouteQueryUpdates | RouteQueryUpdater\n): void {\n if (typeof updates === 'function') {\n updates(searchParams);\n return;\n }\n\n for (const [key, value] of Object.entries(updates)) {\n setRouteQueryValue(searchParams, key, value);\n }\n}\n\nexport function updateRouteQuery(\n updates: RouteQueryUpdates | RouteQueryUpdater,\n options: UpdateRouteQueryOptions = {}\n): void {\n if (typeof window === 'undefined') {\n return;\n }\n\n const url = parseTargetUrl(getWindowHref());\n applyRouteQueryUpdates(url.searchParams, updates);\n\n const href = `${url.pathname}${url.search}${url.hash}`;\n if (href === getWindowHref()) {\n return;\n }\n\n const historyMode = getRouteQueryHistoryMode(options);\n if (historyMode === 'push') {\n saveScrollPosition(getCurrentHref());\n }\n\n const state =\n window.history.state && typeof window.history.state === 'object'\n ? window.history.state\n : {};\n\n window.history[historyMode === 'replace' ? 'replaceState' : 'pushState'](\n {\n ...state,\n path: href,\n },\n '',\n href\n );\n\n setCurrentRouteLocation(url.pathname, href);\n for (const app of getRegisteredAppsSnapshot()) {\n syncAppRegistrationLocation(app, url.pathname, href);\n }\n syncRegisteredRouteSnapshot();\n}\n"],"mappings":";;;AA2BA,SAAS,yBACP,SACoB;CACpB,IAAI,QAAQ,SACV,OAAO,QAAQ;CAGjB,OAAO,QAAQ,YAAY,QAAQ,SAAS;AAC9C;AAEA,SAAS,mBACP,cACA,KACA,OACM;CACN,aAAa,OAAO,GAAG;CAEvB,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,MAAM,SAAS,OAAO;GACzB,IAAI,UAAU,QAAQ,UAAU,QAC9B;GAEF,aAAa,OAAO,KAAK,OAAO,KAAK,CAAC;EACxC;EACA;CACF;CAEA,IAAI,UAAU,QAAQ,UAAU,QAC9B;CAGF,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AACrC;AAEA,SAAS,uBACP,cACA,SACM;CACN,IAAI,OAAO,YAAY,YAAY;EACjC,QAAQ,YAAY;EACpB;CACF;CAEA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAC/C,mBAAmB,cAAc,KAAK,KAAK;AAE/C;AAEA,SAAgB,iBACd,SACA,UAAmC,CAAC,GAC9B;CACN,IAAI,OAAO,WAAW,aACpB;CAGF,MAAM,MAAM,eAAe,cAAc,CAAC;CAC1C,uBAAuB,IAAI,cAAc,OAAO;CAEhD,MAAM,OAAO,GAAG,IAAI,WAAW,IAAI,SAAS,IAAI;CAChD,IAAI,SAAS,cAAc,GACzB;CAGF,MAAM,cAAc,yBAAyB,OAAO;CACpD,IAAI,gBAAgB,QAClB,mBAAmB,eAAe,CAAC;CAGrC,MAAM,QACJ,OAAO,QAAQ,SAAS,OAAO,OAAO,QAAQ,UAAU,WACpD,OAAO,QAAQ,QACf,CAAC;CAEP,OAAO,QAAQ,gBAAgB,YAAY,iBAAiB,YAAY,CACtE;EACE,GAAG;EACH,MAAM;CACR,GACA,IACA,IACF;CAEA,wBAAwB,IAAI,UAAU,IAAI;CAC1C,KAAK,MAAM,OAAO,0BAA0B,GAC1C,4BAA4B,KAAK,IAAI,UAAU,IAAI;CAErD,4BAA4B;AAC9B"}