@benjavicente/router-core 1.168.9

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 (380) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/bin/intent.js +25 -0
  4. package/dist/cjs/Matches.cjs +17 -0
  5. package/dist/cjs/Matches.cjs.map +1 -0
  6. package/dist/cjs/Matches.d.cts +139 -0
  7. package/dist/cjs/RouterProvider.d.cts +27 -0
  8. package/dist/cjs/config.cjs +11 -0
  9. package/dist/cjs/config.cjs.map +1 -0
  10. package/dist/cjs/config.d.cts +17 -0
  11. package/dist/cjs/defer.cjs +41 -0
  12. package/dist/cjs/defer.cjs.map +1 -0
  13. package/dist/cjs/defer.d.cts +37 -0
  14. package/dist/cjs/fileRoute.d.cts +24 -0
  15. package/dist/cjs/global.d.cts +7 -0
  16. package/dist/cjs/hash-scroll.cjs +20 -0
  17. package/dist/cjs/hash-scroll.cjs.map +1 -0
  18. package/dist/cjs/hash-scroll.d.cts +7 -0
  19. package/dist/cjs/history.d.cts +8 -0
  20. package/dist/cjs/index.cjs +96 -0
  21. package/dist/cjs/index.d.cts +53 -0
  22. package/dist/cjs/invariant.cjs +8 -0
  23. package/dist/cjs/invariant.cjs.map +1 -0
  24. package/dist/cjs/invariant.d.cts +1 -0
  25. package/dist/cjs/isServer/client.cjs +7 -0
  26. package/dist/cjs/isServer/client.cjs.map +1 -0
  27. package/dist/cjs/isServer/client.d.cts +1 -0
  28. package/dist/cjs/isServer/development.cjs +7 -0
  29. package/dist/cjs/isServer/development.cjs.map +1 -0
  30. package/dist/cjs/isServer/development.d.cts +1 -0
  31. package/dist/cjs/isServer/server.cjs +7 -0
  32. package/dist/cjs/isServer/server.cjs.map +1 -0
  33. package/dist/cjs/isServer/server.d.cts +1 -0
  34. package/dist/cjs/link.cjs +6 -0
  35. package/dist/cjs/link.cjs.map +1 -0
  36. package/dist/cjs/link.d.cts +221 -0
  37. package/dist/cjs/load-matches.cjs +659 -0
  38. package/dist/cjs/load-matches.cjs.map +1 -0
  39. package/dist/cjs/load-matches.d.cts +18 -0
  40. package/dist/cjs/location.d.cts +50 -0
  41. package/dist/cjs/lru-cache.cjs +70 -0
  42. package/dist/cjs/lru-cache.cjs.map +1 -0
  43. package/dist/cjs/lru-cache.d.cts +6 -0
  44. package/dist/cjs/manifest.cjs +18 -0
  45. package/dist/cjs/manifest.cjs.map +1 -0
  46. package/dist/cjs/manifest.d.cts +35 -0
  47. package/dist/cjs/new-process-route-tree.cjs +754 -0
  48. package/dist/cjs/new-process-route-tree.cjs.map +1 -0
  49. package/dist/cjs/new-process-route-tree.d.cts +236 -0
  50. package/dist/cjs/not-found.cjs +26 -0
  51. package/dist/cjs/not-found.cjs.map +1 -0
  52. package/dist/cjs/not-found.d.cts +32 -0
  53. package/dist/cjs/path.cjs +252 -0
  54. package/dist/cjs/path.cjs.map +1 -0
  55. package/dist/cjs/path.d.cts +56 -0
  56. package/dist/cjs/qss.cjs +70 -0
  57. package/dist/cjs/qss.cjs.map +1 -0
  58. package/dist/cjs/qss.d.cts +33 -0
  59. package/dist/cjs/redirect.cjs +56 -0
  60. package/dist/cjs/redirect.cjs.map +1 -0
  61. package/dist/cjs/redirect.d.cts +77 -0
  62. package/dist/cjs/rewrite.cjs +68 -0
  63. package/dist/cjs/rewrite.cjs.map +1 -0
  64. package/dist/cjs/rewrite.d.cts +30 -0
  65. package/dist/cjs/root.cjs +7 -0
  66. package/dist/cjs/root.cjs.map +1 -0
  67. package/dist/cjs/root.d.cts +3 -0
  68. package/dist/cjs/route.cjs +100 -0
  69. package/dist/cjs/route.cjs.map +1 -0
  70. package/dist/cjs/route.d.cts +552 -0
  71. package/dist/cjs/routeInfo.d.cts +54 -0
  72. package/dist/cjs/router.cjs +1173 -0
  73. package/dist/cjs/router.cjs.map +1 -0
  74. package/dist/cjs/router.d.cts +734 -0
  75. package/dist/cjs/scroll-restoration-inline.cjs +6 -0
  76. package/dist/cjs/scroll-restoration-inline.cjs.map +1 -0
  77. package/dist/cjs/scroll-restoration-inline.d.cts +6 -0
  78. package/dist/cjs/scroll-restoration-script/client.cjs +9 -0
  79. package/dist/cjs/scroll-restoration-script/client.cjs.map +1 -0
  80. package/dist/cjs/scroll-restoration-script/client.d.cts +2 -0
  81. package/dist/cjs/scroll-restoration-script/server.cjs +30 -0
  82. package/dist/cjs/scroll-restoration-script/server.cjs.map +1 -0
  83. package/dist/cjs/scroll-restoration-script/server.d.cts +2 -0
  84. package/dist/cjs/scroll-restoration.cjs +191 -0
  85. package/dist/cjs/scroll-restoration.cjs.map +1 -0
  86. package/dist/cjs/scroll-restoration.d.cts +38 -0
  87. package/dist/cjs/searchMiddleware.cjs +55 -0
  88. package/dist/cjs/searchMiddleware.cjs.map +1 -0
  89. package/dist/cjs/searchMiddleware.d.cts +25 -0
  90. package/dist/cjs/searchParams.cjs +65 -0
  91. package/dist/cjs/searchParams.cjs.map +1 -0
  92. package/dist/cjs/searchParams.d.cts +31 -0
  93. package/dist/cjs/ssr/client.cjs +7 -0
  94. package/dist/cjs/ssr/client.d.cts +6 -0
  95. package/dist/cjs/ssr/constants.cjs +8 -0
  96. package/dist/cjs/ssr/constants.cjs.map +1 -0
  97. package/dist/cjs/ssr/constants.d.cts +3 -0
  98. package/dist/cjs/ssr/createRequestHandler.cjs +44 -0
  99. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -0
  100. package/dist/cjs/ssr/createRequestHandler.d.cts +9 -0
  101. package/dist/cjs/ssr/handlerCallback.cjs +8 -0
  102. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -0
  103. package/dist/cjs/ssr/handlerCallback.d.cts +9 -0
  104. package/dist/cjs/ssr/headers.cjs +21 -0
  105. package/dist/cjs/ssr/headers.cjs.map +1 -0
  106. package/dist/cjs/ssr/headers.d.cts +3 -0
  107. package/dist/cjs/ssr/json.cjs +11 -0
  108. package/dist/cjs/ssr/json.cjs.map +1 -0
  109. package/dist/cjs/ssr/json.d.cts +10 -0
  110. package/dist/cjs/ssr/serializer/RawStream.cjs +287 -0
  111. package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -0
  112. package/dist/cjs/ssr/serializer/RawStream.d.cts +64 -0
  113. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs +32 -0
  114. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -0
  115. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.d.cts +9 -0
  116. package/dist/cjs/ssr/serializer/seroval-plugins.cjs +13 -0
  117. package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -0
  118. package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -0
  119. package/dist/cjs/ssr/serializer/transformer.cjs +53 -0
  120. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -0
  121. package/dist/cjs/ssr/serializer/transformer.d.cts +91 -0
  122. package/dist/cjs/ssr/server.cjs +13 -0
  123. package/dist/cjs/ssr/server.d.cts +6 -0
  124. package/dist/cjs/ssr/ssr-client.cjs +183 -0
  125. package/dist/cjs/ssr/ssr-client.cjs.map +1 -0
  126. package/dist/cjs/ssr/ssr-client.d.cts +10 -0
  127. package/dist/cjs/ssr/ssr-match-id.cjs +12 -0
  128. package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -0
  129. package/dist/cjs/ssr/ssr-match-id.d.cts +2 -0
  130. package/dist/cjs/ssr/ssr-server.cjs +279 -0
  131. package/dist/cjs/ssr/ssr-server.cjs.map +1 -0
  132. package/dist/cjs/ssr/ssr-server.d.cts +42 -0
  133. package/dist/cjs/ssr/transformStreamWithRouter.cjs +327 -0
  134. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -0
  135. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +11 -0
  136. package/dist/cjs/ssr/tsrScript.cjs +6 -0
  137. package/dist/cjs/ssr/tsrScript.cjs.map +1 -0
  138. package/dist/cjs/ssr/tsrScript.d.cts +1 -0
  139. package/dist/cjs/ssr/types.d.cts +30 -0
  140. package/dist/cjs/stores.cjs +148 -0
  141. package/dist/cjs/stores.cjs.map +1 -0
  142. package/dist/cjs/stores.d.cts +70 -0
  143. package/dist/cjs/structuralSharing.d.cts +4 -0
  144. package/dist/cjs/typePrimitives.d.cts +65 -0
  145. package/dist/cjs/useLoaderData.d.cts +5 -0
  146. package/dist/cjs/useLoaderDeps.d.cts +5 -0
  147. package/dist/cjs/useNavigate.d.cts +3 -0
  148. package/dist/cjs/useParams.d.cts +5 -0
  149. package/dist/cjs/useRouteContext.d.cts +9 -0
  150. package/dist/cjs/useSearch.d.cts +5 -0
  151. package/dist/cjs/utils.cjs +339 -0
  152. package/dist/cjs/utils.cjs.map +1 -0
  153. package/dist/cjs/utils.d.cts +178 -0
  154. package/dist/cjs/validators.d.cts +51 -0
  155. package/dist/esm/Matches.d.ts +139 -0
  156. package/dist/esm/Matches.js +17 -0
  157. package/dist/esm/Matches.js.map +1 -0
  158. package/dist/esm/RouterProvider.d.ts +27 -0
  159. package/dist/esm/config.d.ts +17 -0
  160. package/dist/esm/config.js +11 -0
  161. package/dist/esm/config.js.map +1 -0
  162. package/dist/esm/defer.d.ts +37 -0
  163. package/dist/esm/defer.js +40 -0
  164. package/dist/esm/defer.js.map +1 -0
  165. package/dist/esm/fileRoute.d.ts +24 -0
  166. package/dist/esm/global.d.ts +7 -0
  167. package/dist/esm/hash-scroll.d.ts +7 -0
  168. package/dist/esm/hash-scroll.js +20 -0
  169. package/dist/esm/hash-scroll.js.map +1 -0
  170. package/dist/esm/history.d.ts +8 -0
  171. package/dist/esm/index.d.ts +53 -0
  172. package/dist/esm/index.js +24 -0
  173. package/dist/esm/invariant.d.ts +1 -0
  174. package/dist/esm/invariant.js +8 -0
  175. package/dist/esm/invariant.js.map +1 -0
  176. package/dist/esm/isServer/client.d.ts +1 -0
  177. package/dist/esm/isServer/client.js +6 -0
  178. package/dist/esm/isServer/client.js.map +1 -0
  179. package/dist/esm/isServer/development.d.ts +1 -0
  180. package/dist/esm/isServer/development.js +6 -0
  181. package/dist/esm/isServer/development.js.map +1 -0
  182. package/dist/esm/isServer/server.d.ts +1 -0
  183. package/dist/esm/isServer/server.js +6 -0
  184. package/dist/esm/isServer/server.js.map +1 -0
  185. package/dist/esm/link.d.ts +221 -0
  186. package/dist/esm/link.js +6 -0
  187. package/dist/esm/link.js.map +1 -0
  188. package/dist/esm/load-matches.d.ts +18 -0
  189. package/dist/esm/load-matches.js +657 -0
  190. package/dist/esm/load-matches.js.map +1 -0
  191. package/dist/esm/location.d.ts +50 -0
  192. package/dist/esm/lru-cache.d.ts +6 -0
  193. package/dist/esm/lru-cache.js +70 -0
  194. package/dist/esm/lru-cache.js.map +1 -0
  195. package/dist/esm/manifest.d.ts +35 -0
  196. package/dist/esm/manifest.js +17 -0
  197. package/dist/esm/manifest.js.map +1 -0
  198. package/dist/esm/new-process-route-tree.d.ts +236 -0
  199. package/dist/esm/new-process-route-tree.js +749 -0
  200. package/dist/esm/new-process-route-tree.js.map +1 -0
  201. package/dist/esm/not-found.d.ts +32 -0
  202. package/dist/esm/not-found.js +25 -0
  203. package/dist/esm/not-found.js.map +1 -0
  204. package/dist/esm/path.d.ts +56 -0
  205. package/dist/esm/path.js +243 -0
  206. package/dist/esm/path.js.map +1 -0
  207. package/dist/esm/qss.d.ts +33 -0
  208. package/dist/esm/qss.js +69 -0
  209. package/dist/esm/qss.js.map +1 -0
  210. package/dist/esm/redirect.d.ts +77 -0
  211. package/dist/esm/redirect.js +53 -0
  212. package/dist/esm/redirect.js.map +1 -0
  213. package/dist/esm/rewrite.d.ts +30 -0
  214. package/dist/esm/rewrite.js +65 -0
  215. package/dist/esm/rewrite.js.map +1 -0
  216. package/dist/esm/root.d.ts +3 -0
  217. package/dist/esm/root.js +7 -0
  218. package/dist/esm/root.js.map +1 -0
  219. package/dist/esm/route.d.ts +552 -0
  220. package/dist/esm/route.js +98 -0
  221. package/dist/esm/route.js.map +1 -0
  222. package/dist/esm/routeInfo.d.ts +54 -0
  223. package/dist/esm/router.d.ts +734 -0
  224. package/dist/esm/router.js +1165 -0
  225. package/dist/esm/router.js.map +1 -0
  226. package/dist/esm/scroll-restoration-inline.d.ts +6 -0
  227. package/dist/esm/scroll-restoration-inline.js +6 -0
  228. package/dist/esm/scroll-restoration-inline.js.map +1 -0
  229. package/dist/esm/scroll-restoration-script/client.d.ts +2 -0
  230. package/dist/esm/scroll-restoration-script/client.js +8 -0
  231. package/dist/esm/scroll-restoration-script/client.js.map +1 -0
  232. package/dist/esm/scroll-restoration-script/server.d.ts +2 -0
  233. package/dist/esm/scroll-restoration-script/server.js +29 -0
  234. package/dist/esm/scroll-restoration-script/server.js.map +1 -0
  235. package/dist/esm/scroll-restoration.d.ts +38 -0
  236. package/dist/esm/scroll-restoration.js +187 -0
  237. package/dist/esm/scroll-restoration.js.map +1 -0
  238. package/dist/esm/searchMiddleware.d.ts +25 -0
  239. package/dist/esm/searchMiddleware.js +54 -0
  240. package/dist/esm/searchMiddleware.js.map +1 -0
  241. package/dist/esm/searchParams.d.ts +31 -0
  242. package/dist/esm/searchParams.js +62 -0
  243. package/dist/esm/searchParams.js.map +1 -0
  244. package/dist/esm/ssr/client.d.ts +6 -0
  245. package/dist/esm/ssr/client.js +4 -0
  246. package/dist/esm/ssr/constants.d.ts +3 -0
  247. package/dist/esm/ssr/constants.js +7 -0
  248. package/dist/esm/ssr/constants.js.map +1 -0
  249. package/dist/esm/ssr/createRequestHandler.d.ts +9 -0
  250. package/dist/esm/ssr/createRequestHandler.js +44 -0
  251. package/dist/esm/ssr/createRequestHandler.js.map +1 -0
  252. package/dist/esm/ssr/handlerCallback.d.ts +9 -0
  253. package/dist/esm/ssr/handlerCallback.js +8 -0
  254. package/dist/esm/ssr/handlerCallback.js.map +1 -0
  255. package/dist/esm/ssr/headers.d.ts +3 -0
  256. package/dist/esm/ssr/headers.js +21 -0
  257. package/dist/esm/ssr/headers.js.map +1 -0
  258. package/dist/esm/ssr/json.d.ts +10 -0
  259. package/dist/esm/ssr/json.js +11 -0
  260. package/dist/esm/ssr/json.js.map +1 -0
  261. package/dist/esm/ssr/serializer/RawStream.d.ts +64 -0
  262. package/dist/esm/ssr/serializer/RawStream.js +282 -0
  263. package/dist/esm/ssr/serializer/RawStream.js.map +1 -0
  264. package/dist/esm/ssr/serializer/ShallowErrorPlugin.d.ts +9 -0
  265. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js +33 -0
  266. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -0
  267. package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -0
  268. package/dist/esm/ssr/serializer/seroval-plugins.js +13 -0
  269. package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -0
  270. package/dist/esm/ssr/serializer/transformer.d.ts +91 -0
  271. package/dist/esm/ssr/serializer/transformer.js +51 -0
  272. package/dist/esm/ssr/serializer/transformer.js.map +1 -0
  273. package/dist/esm/ssr/server.d.ts +6 -0
  274. package/dist/esm/ssr/server.js +5 -0
  275. package/dist/esm/ssr/ssr-client.d.ts +10 -0
  276. package/dist/esm/ssr/ssr-client.js +183 -0
  277. package/dist/esm/ssr/ssr-client.js.map +1 -0
  278. package/dist/esm/ssr/ssr-match-id.d.ts +2 -0
  279. package/dist/esm/ssr/ssr-match-id.js +11 -0
  280. package/dist/esm/ssr/ssr-match-id.js.map +1 -0
  281. package/dist/esm/ssr/ssr-server.d.ts +42 -0
  282. package/dist/esm/ssr/ssr-server.js +277 -0
  283. package/dist/esm/ssr/ssr-server.js.map +1 -0
  284. package/dist/esm/ssr/transformStreamWithRouter.d.ts +11 -0
  285. package/dist/esm/ssr/transformStreamWithRouter.js +325 -0
  286. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -0
  287. package/dist/esm/ssr/tsrScript.d.ts +0 -0
  288. package/dist/esm/ssr/tsrScript.js +6 -0
  289. package/dist/esm/ssr/tsrScript.js.map +1 -0
  290. package/dist/esm/ssr/types.d.ts +30 -0
  291. package/dist/esm/stores.d.ts +70 -0
  292. package/dist/esm/stores.js +146 -0
  293. package/dist/esm/stores.js.map +1 -0
  294. package/dist/esm/structuralSharing.d.ts +4 -0
  295. package/dist/esm/typePrimitives.d.ts +65 -0
  296. package/dist/esm/useLoaderData.d.ts +5 -0
  297. package/dist/esm/useLoaderDeps.d.ts +5 -0
  298. package/dist/esm/useNavigate.d.ts +3 -0
  299. package/dist/esm/useParams.d.ts +5 -0
  300. package/dist/esm/useRouteContext.d.ts +9 -0
  301. package/dist/esm/useSearch.d.ts +5 -0
  302. package/dist/esm/utils.d.ts +178 -0
  303. package/dist/esm/utils.js +322 -0
  304. package/dist/esm/utils.js.map +1 -0
  305. package/dist/esm/validators.d.ts +51 -0
  306. package/package.json +200 -0
  307. package/skills/router-core/SKILL.md +139 -0
  308. package/skills/router-core/auth-and-guards/SKILL.md +458 -0
  309. package/skills/router-core/code-splitting/SKILL.md +322 -0
  310. package/skills/router-core/data-loading/SKILL.md +485 -0
  311. package/skills/router-core/navigation/SKILL.md +448 -0
  312. package/skills/router-core/not-found-and-errors/SKILL.md +435 -0
  313. package/skills/router-core/path-params/SKILL.md +382 -0
  314. package/skills/router-core/search-params/SKILL.md +349 -0
  315. package/skills/router-core/search-params/references/validation-patterns.md +379 -0
  316. package/skills/router-core/ssr/SKILL.md +437 -0
  317. package/skills/router-core/type-safety/SKILL.md +497 -0
  318. package/src/Matches.ts +291 -0
  319. package/src/RouterProvider.ts +47 -0
  320. package/src/config.ts +42 -0
  321. package/src/defer.ts +69 -0
  322. package/src/fileRoute.ts +164 -0
  323. package/src/global.ts +9 -0
  324. package/src/hash-scroll.ts +21 -0
  325. package/src/history.ts +9 -0
  326. package/src/index.ts +471 -0
  327. package/src/invariant.ts +3 -0
  328. package/src/isServer/client.ts +1 -0
  329. package/src/isServer/development.ts +2 -0
  330. package/src/isServer/server.ts +1 -0
  331. package/src/link.ts +704 -0
  332. package/src/load-matches.ts +1281 -0
  333. package/src/location.ts +51 -0
  334. package/src/lru-cache.ts +74 -0
  335. package/src/manifest.ts +68 -0
  336. package/src/new-process-route-tree.ts +1387 -0
  337. package/src/not-found.ts +41 -0
  338. package/src/path.ts +436 -0
  339. package/src/qss.ts +81 -0
  340. package/src/redirect.ts +179 -0
  341. package/src/rewrite.ts +93 -0
  342. package/src/root.ts +3 -0
  343. package/src/route.ts +2235 -0
  344. package/src/routeInfo.ts +235 -0
  345. package/src/router.ts +3207 -0
  346. package/src/scroll-restoration-inline.ts +81 -0
  347. package/src/scroll-restoration-script/client.ts +5 -0
  348. package/src/scroll-restoration-script/server.ts +64 -0
  349. package/src/scroll-restoration.ts +357 -0
  350. package/src/searchMiddleware.ts +76 -0
  351. package/src/searchParams.ts +90 -0
  352. package/src/ssr/client.ts +6 -0
  353. package/src/ssr/constants.ts +3 -0
  354. package/src/ssr/createRequestHandler.ts +98 -0
  355. package/src/ssr/handlerCallback.ts +15 -0
  356. package/src/ssr/headers.ts +40 -0
  357. package/src/ssr/json.ts +16 -0
  358. package/src/ssr/serializer/RawStream.ts +464 -0
  359. package/src/ssr/serializer/ShallowErrorPlugin.ts +43 -0
  360. package/src/ssr/serializer/seroval-plugins.ts +12 -0
  361. package/src/ssr/serializer/transformer.ts +312 -0
  362. package/src/ssr/server.ts +14 -0
  363. package/src/ssr/ssr-client.ts +313 -0
  364. package/src/ssr/ssr-match-id.ts +7 -0
  365. package/src/ssr/ssr-server.ts +425 -0
  366. package/src/ssr/transformStreamWithRouter.ts +493 -0
  367. package/src/ssr/tsrScript.ts +20 -0
  368. package/src/ssr/types.ts +41 -0
  369. package/src/stores.ts +342 -0
  370. package/src/structuralSharing.ts +7 -0
  371. package/src/typePrimitives.ts +181 -0
  372. package/src/useLoaderData.ts +20 -0
  373. package/src/useLoaderDeps.ts +13 -0
  374. package/src/useNavigate.ts +13 -0
  375. package/src/useParams.ts +20 -0
  376. package/src/useRouteContext.ts +39 -0
  377. package/src/useSearch.ts +20 -0
  378. package/src/utils.ts +708 -0
  379. package/src/validators.ts +121 -0
  380. package/src/vite-env.d.ts +4 -0
@@ -0,0 +1,458 @@
1
+ ---
2
+ name: router-core/auth-and-guards
3
+ description: >-
4
+ Route protection with beforeLoad, redirect()/throw redirect(),
5
+ isRedirect helper, authenticated layout routes (_authenticated),
6
+ non-redirect auth (inline login), RBAC with roles and permissions,
7
+ auth provider integration (Auth0, Clerk, Supabase), router context
8
+ for auth state.
9
+ type: sub-skill
10
+ library: tanstack-router
11
+ library_version: '1.166.2'
12
+ requires:
13
+ - router-core
14
+ - router-core/data-loading
15
+ sources:
16
+ - TanStack/router:docs/router/guide/authenticated-routes.md
17
+ - TanStack/router:docs/router/how-to/setup-authentication.md
18
+ - TanStack/router:docs/router/how-to/setup-auth-providers.md
19
+ - TanStack/router:docs/router/how-to/setup-rbac.md
20
+ ---
21
+
22
+ # Auth and Guards
23
+
24
+ ## Setup
25
+
26
+ Protect routes with `beforeLoad` + `redirect()` in a pathless layout route (`_authenticated`):
27
+
28
+ ```tsx
29
+ // src/routes/_authenticated.tsx
30
+ import { createFileRoute, redirect } from '@benjavicente/react-router'
31
+
32
+ export const Route = createFileRoute('/_authenticated')({
33
+ beforeLoad: ({ context, location }) => {
34
+ if (!context.auth.isAuthenticated) {
35
+ throw redirect({
36
+ to: '/login',
37
+ search: {
38
+ redirect: location.href,
39
+ },
40
+ })
41
+ }
42
+ },
43
+ // component defaults to Outlet — no need to declare it
44
+ })
45
+ ```
46
+
47
+ Any route file placed under `src/routes/_authenticated/` is automatically protected:
48
+
49
+ ```tsx
50
+ // src/routes/_authenticated/dashboard.tsx
51
+ import { createFileRoute } from '@benjavicente/react-router'
52
+
53
+ export const Route = createFileRoute('/_authenticated/dashboard')({
54
+ component: DashboardComponent,
55
+ })
56
+
57
+ function DashboardComponent() {
58
+ const { auth } = Route.useRouteContext()
59
+ return <div>Welcome, {auth.user?.username}</div>
60
+ }
61
+ ```
62
+
63
+ ## Core Patterns
64
+
65
+ ### Router Context for Auth State
66
+
67
+ Auth state flows into the router via `createRootRouteWithContext` and `RouterProvider`'s `context` prop:
68
+
69
+ ```tsx
70
+ // src/routes/__root.tsx
71
+ import { createRootRouteWithContext, Outlet } from '@benjavicente/react-router'
72
+
73
+ interface AuthState {
74
+ isAuthenticated: boolean
75
+ user: { id: string; username: string; email: string } | null
76
+ login: (username: string, password: string) => Promise<void>
77
+ logout: () => void
78
+ }
79
+
80
+ interface MyRouterContext {
81
+ auth: AuthState
82
+ }
83
+
84
+ export const Route = createRootRouteWithContext<MyRouterContext>()({
85
+ component: () => <Outlet />,
86
+ })
87
+ ```
88
+
89
+ ```tsx
90
+ // src/router.tsx
91
+ import { createRouter } from '@benjavicente/react-router'
92
+ import { routeTree } from './routeTree.gen'
93
+
94
+ export const router = createRouter({
95
+ routeTree,
96
+ context: {
97
+ auth: undefined!, // placeholder — filled by RouterProvider context prop
98
+ },
99
+ })
100
+
101
+ declare module '@benjavicente/react-router' {
102
+ interface Register {
103
+ router: typeof router
104
+ }
105
+ }
106
+ ```
107
+
108
+ ```tsx
109
+ // src/App.tsx
110
+ import { RouterProvider } from '@benjavicente/react-router'
111
+ import { AuthProvider, useAuth } from './auth'
112
+ import { router } from './router'
113
+
114
+ function InnerApp() {
115
+ const auth = useAuth()
116
+ // context prop injects live auth state WITHOUT recreating the router
117
+ return <RouterProvider router={router} context={{ auth }} />
118
+ }
119
+
120
+ function App() {
121
+ return (
122
+ <AuthProvider>
123
+ <InnerApp />
124
+ </AuthProvider>
125
+ )
126
+ }
127
+ ```
128
+
129
+ The router is created once with a placeholder. `RouterProvider`'s `context` prop injects the live auth state on each render — this avoids recreating the router on auth changes (which would reset caches and rebuild the route tree).
130
+
131
+ ### Redirect-Based Auth with Redirect-Back
132
+
133
+ Save the current location in search params so you can redirect back after login:
134
+
135
+ ```tsx
136
+ // src/routes/_authenticated.tsx
137
+ import { createFileRoute, redirect } from '@benjavicente/react-router'
138
+
139
+ export const Route = createFileRoute('/_authenticated')({
140
+ beforeLoad: ({ context, location }) => {
141
+ if (!context.auth.isAuthenticated) {
142
+ throw redirect({
143
+ to: '/login',
144
+ search: { redirect: location.href },
145
+ })
146
+ }
147
+ },
148
+ })
149
+ ```
150
+
151
+ ```tsx
152
+ // src/routes/login.tsx
153
+ import { createFileRoute, redirect } from '@benjavicente/react-router'
154
+ import { useState, type FormEvent } from 'react'
155
+
156
+ // Validate redirect target to prevent open redirect attacks
157
+ function sanitizeRedirect(url: unknown): string {
158
+ if (typeof url !== 'string' || !url.startsWith('/') || url.startsWith('//')) {
159
+ return '/'
160
+ }
161
+ return url
162
+ }
163
+
164
+ export const Route = createFileRoute('/login')({
165
+ validateSearch: (search) => ({
166
+ redirect: sanitizeRedirect(search.redirect),
167
+ }),
168
+ beforeLoad: ({ context, search }) => {
169
+ if (context.auth.isAuthenticated) {
170
+ throw redirect({ to: search.redirect })
171
+ }
172
+ },
173
+ component: LoginComponent,
174
+ })
175
+
176
+ function LoginComponent() {
177
+ const { auth } = Route.useRouteContext()
178
+ const search = Route.useSearch()
179
+ const navigate = Route.useNavigate()
180
+ const [username, setUsername] = useState('')
181
+ const [password, setPassword] = useState('')
182
+ const [error, setError] = useState('')
183
+
184
+ const handleSubmit = async (e: FormEvent) => {
185
+ e.preventDefault()
186
+ try {
187
+ await auth.login(username, password)
188
+ navigate({ to: search.redirect })
189
+ } catch {
190
+ setError('Invalid credentials')
191
+ }
192
+ }
193
+
194
+ return (
195
+ <form onSubmit={handleSubmit}>
196
+ {error && <div>{error}</div>}
197
+ <input value={username} onChange={(e) => setUsername(e.target.value)} />
198
+ <input
199
+ type="password"
200
+ value={password}
201
+ onChange={(e) => setPassword(e.target.value)}
202
+ />
203
+ <button type="submit">Sign In</button>
204
+ </form>
205
+ )
206
+ }
207
+ ```
208
+
209
+ ### Non-Redirect Auth (Inline Login)
210
+
211
+ Instead of redirecting, show a login form in place of the `Outlet`:
212
+
213
+ ```tsx
214
+ // src/routes/_authenticated.tsx
215
+ import { createFileRoute, Outlet } from '@benjavicente/react-router'
216
+
217
+ export const Route = createFileRoute('/_authenticated')({
218
+ component: AuthenticatedLayout,
219
+ })
220
+
221
+ function AuthenticatedLayout() {
222
+ const { auth } = Route.useRouteContext()
223
+
224
+ if (!auth.isAuthenticated) {
225
+ return <LoginForm />
226
+ }
227
+
228
+ return <Outlet />
229
+ }
230
+ ```
231
+
232
+ This keeps the URL unchanged — the user stays on the same page and sees a login form instead of protected content. After authentication, `<Outlet />` renders and child routes appear.
233
+
234
+ ### RBAC with Roles and Permissions
235
+
236
+ Extend auth state with role/permission helpers, then check in `beforeLoad`:
237
+
238
+ ```tsx
239
+ // src/auth.tsx
240
+ interface User {
241
+ id: string
242
+ username: string
243
+ email: string
244
+ roles: string[]
245
+ permissions: string[]
246
+ }
247
+
248
+ interface AuthState {
249
+ isAuthenticated: boolean
250
+ user: User | null
251
+ hasRole: (role: string) => boolean
252
+ hasAnyRole: (roles: string[]) => boolean
253
+ hasPermission: (permission: string) => boolean
254
+ hasAnyPermission: (permissions: string[]) => boolean
255
+ login: (username: string, password: string) => Promise<void>
256
+ logout: () => void
257
+ }
258
+ ```
259
+
260
+ Admin-only layout route:
261
+
262
+ ```tsx
263
+ // src/routes/_authenticated/_admin.tsx
264
+ import { createFileRoute, redirect } from '@benjavicente/react-router'
265
+
266
+ export const Route = createFileRoute('/_authenticated/_admin')({
267
+ beforeLoad: ({ context, location }) => {
268
+ if (!context.auth.hasRole('admin')) {
269
+ throw redirect({
270
+ to: '/unauthorized',
271
+ search: { redirect: location.href },
272
+ })
273
+ }
274
+ },
275
+ })
276
+ ```
277
+
278
+ Multi-role access:
279
+
280
+ ```tsx
281
+ // src/routes/_authenticated/_moderator.tsx
282
+ import { createFileRoute, redirect } from '@benjavicente/react-router'
283
+
284
+ export const Route = createFileRoute('/_authenticated/_moderator')({
285
+ beforeLoad: ({ context, location }) => {
286
+ if (!context.auth.hasAnyRole(['admin', 'moderator'])) {
287
+ throw redirect({
288
+ to: '/unauthorized',
289
+ search: { redirect: location.href },
290
+ })
291
+ }
292
+ },
293
+ })
294
+ ```
295
+
296
+ Permission-based:
297
+
298
+ ```tsx
299
+ // src/routes/_authenticated/_users.tsx
300
+ import { createFileRoute, redirect } from '@benjavicente/react-router'
301
+
302
+ export const Route = createFileRoute('/_authenticated/_users')({
303
+ beforeLoad: ({ context, location }) => {
304
+ if (!context.auth.hasAnyPermission(['users:read', 'users:write'])) {
305
+ throw redirect({
306
+ to: '/unauthorized',
307
+ search: { redirect: location.href },
308
+ })
309
+ }
310
+ },
311
+ })
312
+ ```
313
+
314
+ Page-level permission check (nested under an already-role-protected layout):
315
+
316
+ ```tsx
317
+ // src/routes/_authenticated/_users/manage.tsx
318
+ import { createFileRoute } from '@benjavicente/react-router'
319
+
320
+ export const Route = createFileRoute('/_authenticated/_users/manage')({
321
+ beforeLoad: ({ context }) => {
322
+ if (!context.auth.hasPermission('users:write')) {
323
+ throw new Error('Write permission required')
324
+ }
325
+ },
326
+ component: UserManagement,
327
+ })
328
+
329
+ function UserManagement() {
330
+ const { auth } = Route.useRouteContext()
331
+ const canDelete = auth.hasPermission('users:delete')
332
+
333
+ return (
334
+ <div>
335
+ <h1>User Management</h1>
336
+ {canDelete && <button>Delete User</button>}
337
+ </div>
338
+ )
339
+ }
340
+ ```
341
+
342
+ ### Handling Auth Check Failures (isRedirect)
343
+
344
+ When `beforeLoad` has a try/catch, redirects (which work by throwing) can get swallowed. Use `isRedirect` to re-throw:
345
+
346
+ ```tsx
347
+ import { createFileRoute, redirect, isRedirect } from '@benjavicente/react-router'
348
+
349
+ export const Route = createFileRoute('/_authenticated')({
350
+ beforeLoad: async ({ context, location }) => {
351
+ try {
352
+ const user = await verifySession(context.auth)
353
+ if (!user) {
354
+ throw redirect({
355
+ to: '/login',
356
+ search: { redirect: location.href },
357
+ })
358
+ }
359
+ return { user }
360
+ } catch (error) {
361
+ if (isRedirect(error)) throw error // re-throw redirect, don't swallow it
362
+ // Actual error — redirect to login
363
+ throw redirect({
364
+ to: '/login',
365
+ search: { redirect: location.href },
366
+ })
367
+ }
368
+ },
369
+ })
370
+ ```
371
+
372
+ ## Common Mistakes
373
+
374
+ ### HIGH: Auth check in component instead of beforeLoad
375
+
376
+ Component-level auth checks cause a **flash of protected content** before the redirect:
377
+
378
+ ```tsx
379
+ // WRONG — protected content renders briefly before redirect
380
+ export const Route = createFileRoute('/_authenticated/dashboard')({
381
+ component: () => {
382
+ const auth = useAuth()
383
+ if (!auth.isAuthenticated) return <Navigate to="/login" />
384
+ return <Dashboard />
385
+ },
386
+ })
387
+
388
+ // CORRECT — beforeLoad runs before any rendering
389
+ export const Route = createFileRoute('/_authenticated/dashboard')({
390
+ beforeLoad: ({ context }) => {
391
+ if (!context.auth.isAuthenticated) {
392
+ throw redirect({ to: '/login' })
393
+ }
394
+ },
395
+ component: Dashboard,
396
+ })
397
+ ```
398
+
399
+ `beforeLoad` runs before any component rendering and before the loader. It completely prevents the flash.
400
+
401
+ ### HIGH: Not re-throwing redirects in try/catch
402
+
403
+ `redirect()` works by throwing. If `beforeLoad` has a try/catch, the redirect gets swallowed:
404
+
405
+ ```tsx
406
+ // WRONG — redirect is caught and swallowed
407
+ beforeLoad: async ({ context }) => {
408
+ try {
409
+ await validateSession(context.auth)
410
+ } catch (e) {
411
+ console.error(e) // swallows the redirect!
412
+ }
413
+ }
414
+
415
+ // CORRECT — use isRedirect to distinguish intentional redirects from errors
416
+ import { isRedirect } from '@benjavicente/react-router'
417
+
418
+ beforeLoad: async ({ context }) => {
419
+ try {
420
+ await validateSession(context.auth)
421
+ } catch (e) {
422
+ if (isRedirect(e)) throw e
423
+ console.error(e)
424
+ }
425
+ }
426
+ ```
427
+
428
+ ### MEDIUM: Conditionally rendering root route component
429
+
430
+ The root route always renders regardless of auth state. You cannot conditionally render its component:
431
+
432
+ ```tsx
433
+ // WRONG — root route always renders, this doesn't protect anything
434
+ export const Route = createRootRoute({
435
+ component: () => {
436
+ if (!isAuthenticated()) return <Login />
437
+ return <Outlet />
438
+ },
439
+ })
440
+
441
+ // CORRECT — use a pathless layout route for auth boundaries
442
+ // src/routes/_authenticated.tsx
443
+ export const Route = createFileRoute('/_authenticated')({
444
+ beforeLoad: ({ context }) => {
445
+ if (!context.auth.isAuthenticated) {
446
+ throw redirect({ to: '/login' })
447
+ }
448
+ },
449
+ })
450
+ ```
451
+
452
+ Place protected routes as children of the `_authenticated` layout route. Public routes (login, home, etc.) live outside it.
453
+
454
+ ---
455
+
456
+ ## Cross-References
457
+
458
+ - See also: **router-core/data-loading/SKILL.md** — `beforeLoad` runs before `loader`; auth context flows into loader via route context