@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.140

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 (460) hide show
  1. package/AGENTS.md +17 -0
  2. package/README.md +432 -7
  3. package/dist/bin/rango.js +2073 -213
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +7258 -2714
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +140 -67
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +329 -0
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +487 -0
  12. package/skills/caching/SKILL.md +357 -25
  13. package/skills/comparison/SKILL.md +50 -0
  14. package/skills/comparison/agents/openai.yaml +4 -0
  15. package/skills/comparison/references/framework-comparison.md +837 -0
  16. package/skills/composability/SKILL.md +246 -0
  17. package/skills/css/SKILL.md +76 -0
  18. package/skills/debug-manifest/SKILL.md +16 -10
  19. package/skills/document-cache/SKILL.md +87 -62
  20. package/skills/fonts/SKILL.md +6 -4
  21. package/skills/handler-use/SKILL.md +364 -0
  22. package/skills/hooks/SKILL.md +557 -79
  23. package/skills/host-router/SKILL.md +320 -0
  24. package/skills/i18n/SKILL.md +276 -0
  25. package/skills/intercept/SKILL.md +207 -15
  26. package/skills/layout/SKILL.md +146 -6
  27. package/skills/links/SKILL.md +304 -25
  28. package/skills/loader/SKILL.md +616 -54
  29. package/skills/middleware/SKILL.md +217 -37
  30. package/skills/migrate-nextjs/SKILL.md +611 -0
  31. package/skills/migrate-react-router/SKILL.md +927 -0
  32. package/skills/mime-routes/SKILL.md +42 -11
  33. package/skills/observability/SKILL.md +194 -0
  34. package/skills/parallel/SKILL.md +284 -3
  35. package/skills/ppr/SKILL.md +426 -0
  36. package/skills/prerender/SKILL.md +437 -52
  37. package/skills/rango/SKILL.md +369 -22
  38. package/skills/react-compiler/SKILL.md +168 -0
  39. package/skills/response-routes/SKILL.md +263 -121
  40. package/skills/route/SKILL.md +350 -21
  41. package/skills/router-setup/SKILL.md +246 -33
  42. package/skills/scripts/SKILL.md +179 -0
  43. package/skills/server-actions/SKILL.md +775 -0
  44. package/skills/shell-manifest/SKILL.md +185 -0
  45. package/skills/streams-and-websockets/SKILL.md +283 -0
  46. package/skills/tailwind/SKILL.md +27 -3
  47. package/skills/testing/SKILL.md +126 -222
  48. package/skills/testing/bindings.md +103 -0
  49. package/skills/testing/cache-prerender.md +127 -0
  50. package/skills/testing/client-components.md +124 -0
  51. package/skills/testing/e2e-parity.md +125 -0
  52. package/skills/testing/flight.md +91 -0
  53. package/skills/testing/handles.md +131 -0
  54. package/skills/testing/loader.md +128 -0
  55. package/skills/testing/middleware.md +99 -0
  56. package/skills/testing/render-handler.md +122 -0
  57. package/skills/testing/response-routes.md +95 -0
  58. package/skills/testing/reverse-and-types.md +85 -0
  59. package/skills/testing/server-actions.md +107 -0
  60. package/skills/testing/server-tree.md +128 -0
  61. package/skills/testing/setup.md +123 -0
  62. package/skills/theme/SKILL.md +9 -8
  63. package/skills/typesafety/SKILL.md +532 -103
  64. package/skills/use-cache/SKILL.md +367 -0
  65. package/skills/vercel/SKILL.md +128 -0
  66. package/skills/view-transitions/SKILL.md +337 -0
  67. package/src/__augment-tests__/augment.ts +81 -0
  68. package/src/__augment-tests__/augmented.check.ts +116 -0
  69. package/src/__internal.ts +77 -44
  70. package/src/bin/rango.ts +312 -15
  71. package/src/browser/action-coordinator.ts +114 -0
  72. package/src/browser/action-fence.ts +47 -0
  73. package/src/browser/app-shell.ts +39 -0
  74. package/src/browser/app-version.ts +14 -0
  75. package/src/browser/connection-warmup.ts +134 -0
  76. package/src/browser/cookie-name.ts +140 -0
  77. package/src/browser/event-controller.ts +293 -202
  78. package/src/browser/history-state.ts +101 -0
  79. package/src/browser/index.ts +3 -3
  80. package/src/browser/intercept-utils.ts +52 -0
  81. package/src/browser/invalidate-client-cache.ts +52 -0
  82. package/src/browser/link-interceptor.ts +24 -4
  83. package/src/browser/logging.ts +11 -0
  84. package/src/browser/merge-segment-loaders.ts +20 -12
  85. package/src/browser/navigation-bridge.ts +385 -576
  86. package/src/browser/navigation-client.ts +245 -75
  87. package/src/browser/navigation-store-handle.ts +38 -0
  88. package/src/browser/navigation-store.ts +184 -118
  89. package/src/browser/navigation-transaction.ts +247 -0
  90. package/src/browser/network-error-handler.ts +88 -0
  91. package/src/browser/partial-update.ts +412 -364
  92. package/src/browser/prefetch/cache.ts +359 -0
  93. package/src/browser/prefetch/fetch.ts +452 -0
  94. package/src/browser/prefetch/observer.ts +65 -0
  95. package/src/browser/prefetch/policy.ts +48 -0
  96. package/src/browser/prefetch/queue.ts +209 -0
  97. package/src/browser/prefetch/resource-ready.ts +77 -0
  98. package/src/browser/rango-state.ts +194 -0
  99. package/src/browser/react/Link.tsx +275 -68
  100. package/src/browser/react/NavigationProvider.tsx +265 -109
  101. package/src/browser/react/ScrollRestoration.tsx +10 -6
  102. package/src/browser/react/context.ts +11 -0
  103. package/src/browser/react/filter-segment-order.ts +70 -0
  104. package/src/browser/react/index.ts +0 -48
  105. package/src/browser/react/location-state-shared.ts +272 -60
  106. package/src/browser/react/location-state.ts +90 -20
  107. package/src/browser/react/mount-context.ts +6 -1
  108. package/src/browser/react/nonce-context.ts +23 -0
  109. package/src/browser/react/shallow-equal.ts +27 -0
  110. package/src/browser/react/use-action.ts +35 -66
  111. package/src/browser/react/use-handle.ts +39 -126
  112. package/src/browser/react/use-href.tsx +8 -1
  113. package/src/browser/react/use-link-status.ts +39 -13
  114. package/src/browser/react/use-navigation.ts +53 -69
  115. package/src/browser/react/use-params.ts +75 -0
  116. package/src/browser/react/use-pathname.ts +47 -0
  117. package/src/browser/react/use-reverse.ts +106 -0
  118. package/src/browser/react/use-router.ts +98 -0
  119. package/src/browser/react/use-search-params.ts +51 -0
  120. package/src/browser/react/use-segments.ts +72 -99
  121. package/src/browser/response-adapter.ts +164 -0
  122. package/src/browser/rsc-router.tsx +300 -72
  123. package/src/browser/scroll-restoration.ts +138 -50
  124. package/src/browser/segment-reconciler.ts +243 -0
  125. package/src/browser/segment-structure-assert.ts +17 -1
  126. package/src/browser/server-action-bridge.ts +668 -613
  127. package/src/browser/types.ts +223 -51
  128. package/src/browser/validate-redirect-origin.ts +56 -0
  129. package/src/build/collect-fallback-refs.ts +107 -0
  130. package/src/build/generate-manifest.ts +252 -161
  131. package/src/build/generate-route-types.ts +41 -1038
  132. package/src/build/index.ts +12 -7
  133. package/src/build/prefix-tree-utils.ts +123 -0
  134. package/src/build/route-trie.ts +225 -42
  135. package/src/build/route-types/ast-helpers.ts +25 -0
  136. package/src/build/route-types/ast-route-extraction.ts +105 -0
  137. package/src/build/route-types/codegen.ts +113 -0
  138. package/src/build/route-types/include-resolution.ts +812 -0
  139. package/src/build/route-types/param-extraction.ts +51 -0
  140. package/src/build/route-types/per-module-writer.ts +144 -0
  141. package/src/build/route-types/router-processing.ts +695 -0
  142. package/src/build/route-types/scan-filter.ts +85 -0
  143. package/src/build/route-types/source-scan.ts +216 -0
  144. package/src/build/runtime-discovery.ts +223 -0
  145. package/src/cache/background-task.ts +34 -0
  146. package/src/cache/cache-error.ts +104 -0
  147. package/src/cache/cache-key-utils.ts +60 -0
  148. package/src/cache/cache-policy.ts +199 -0
  149. package/src/cache/cache-runtime.ts +525 -0
  150. package/src/cache/cache-scope.ts +298 -332
  151. package/src/cache/cache-tag.ts +103 -0
  152. package/src/cache/cf/cf-base64.ts +33 -0
  153. package/src/cache/cf/cf-cache-constants.ts +127 -0
  154. package/src/cache/cf/cf-cache-store.ts +2500 -158
  155. package/src/cache/cf/cf-cache-types.ts +349 -0
  156. package/src/cache/cf/cf-kv-utils.ts +46 -0
  157. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  158. package/src/cache/cf/index.ts +17 -17
  159. package/src/cache/document-cache.ts +199 -92
  160. package/src/cache/handle-capture.ts +81 -0
  161. package/src/cache/handle-snapshot.ts +111 -0
  162. package/src/cache/index.ts +29 -35
  163. package/src/cache/memory-segment-store.ts +363 -30
  164. package/src/cache/profile-registry.ts +88 -0
  165. package/src/cache/read-through-swr.ts +178 -0
  166. package/src/cache/segment-codec.ts +248 -0
  167. package/src/cache/shell-cache.ts +386 -0
  168. package/src/cache/tag-invalidation.ts +230 -0
  169. package/src/cache/taint.ts +153 -0
  170. package/src/cache/types.ts +156 -211
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1102 -0
  173. package/src/client.rsc.tsx +43 -21
  174. package/src/client.tsx +131 -347
  175. package/src/cloudflare/index.ts +11 -0
  176. package/src/cloudflare/tracing.ts +109 -0
  177. package/src/component-utils.ts +23 -4
  178. package/src/components/DefaultDocument.tsx +13 -3
  179. package/src/context-var.ts +168 -0
  180. package/src/debug.ts +19 -9
  181. package/src/decode-loader-results.ts +52 -0
  182. package/src/defer.ts +185 -0
  183. package/src/deps/ssr.ts +0 -1
  184. package/src/encode-kv.ts +49 -0
  185. package/src/errors.ts +106 -10
  186. package/src/escape-script.ts +52 -0
  187. package/src/handle.ts +110 -35
  188. package/src/handles/MetaTags.tsx +83 -59
  189. package/src/handles/Scripts.tsx +183 -0
  190. package/src/handles/breadcrumbs.ts +93 -0
  191. package/src/handles/deferred-resolution.ts +127 -0
  192. package/src/handles/is-thenable.ts +18 -0
  193. package/src/handles/meta.ts +44 -53
  194. package/src/handles/script.ts +244 -0
  195. package/src/host/cookie-handler.ts +20 -65
  196. package/src/host/errors.ts +21 -30
  197. package/src/host/index.ts +13 -9
  198. package/src/host/pattern-matcher.ts +50 -79
  199. package/src/host/router.ts +151 -121
  200. package/src/host/testing.ts +45 -32
  201. package/src/host/types.ts +52 -11
  202. package/src/host/utils.ts +2 -2
  203. package/src/href-client.ts +192 -57
  204. package/src/index.rsc.ts +177 -35
  205. package/src/index.ts +255 -71
  206. package/src/internal-debug.ts +9 -2
  207. package/src/loader-store.ts +500 -0
  208. package/src/loader.rsc.ts +31 -99
  209. package/src/loader.ts +30 -12
  210. package/src/missing-id-error.ts +68 -0
  211. package/src/outlet-context.ts +1 -1
  212. package/src/outlet-provider.tsx +41 -0
  213. package/src/prerender/param-hash.ts +16 -14
  214. package/src/prerender/store.ts +121 -21
  215. package/src/prerender.ts +460 -26
  216. package/src/redirect-origin.ts +100 -0
  217. package/src/regex-escape.ts +8 -0
  218. package/src/render-error-thrower.tsx +20 -0
  219. package/src/response-utils.ts +62 -0
  220. package/src/reverse.ts +198 -128
  221. package/src/root-error-boundary.tsx +42 -48
  222. package/src/route-content-wrapper.tsx +22 -77
  223. package/src/route-definition/dsl-helpers.ts +1116 -0
  224. package/src/route-definition/helper-factories.ts +88 -0
  225. package/src/route-definition/helpers-types.ts +505 -0
  226. package/src/route-definition/index.ts +54 -0
  227. package/src/route-definition/redirect.ts +134 -0
  228. package/src/route-definition/resolve-handler-use.ts +160 -0
  229. package/src/route-definition/use-item-types.ts +29 -0
  230. package/src/route-definition.ts +1 -1481
  231. package/src/route-map-builder.ts +82 -144
  232. package/src/route-name.ts +53 -0
  233. package/src/route-types.ts +71 -45
  234. package/src/router/basename.ts +14 -0
  235. package/src/router/content-negotiation.ts +263 -0
  236. package/src/router/debug-manifest.ts +72 -0
  237. package/src/router/error-handling.ts +54 -27
  238. package/src/router/find-match.ts +245 -0
  239. package/src/router/handler-context.ts +377 -125
  240. package/src/router/instrument.ts +350 -0
  241. package/src/router/intercept-resolution.ts +59 -28
  242. package/src/router/lazy-includes.ts +254 -0
  243. package/src/router/loader-resolution.ts +421 -157
  244. package/src/router/logging.ts +106 -6
  245. package/src/router/manifest.ts +131 -57
  246. package/src/router/match-api.ts +167 -246
  247. package/src/router/match-context.ts +4 -24
  248. package/src/router/match-handlers.ts +440 -0
  249. package/src/router/match-middleware/background-revalidation.ts +117 -93
  250. package/src/router/match-middleware/cache-lookup.ts +297 -150
  251. package/src/router/match-middleware/cache-store.ts +123 -51
  252. package/src/router/match-middleware/intercept-resolution.ts +44 -43
  253. package/src/router/match-middleware/segment-resolution.ts +64 -22
  254. package/src/router/match-pipelines.ts +11 -87
  255. package/src/router/match-result.ts +121 -50
  256. package/src/router/metrics.ts +219 -28
  257. package/src/router/middleware-types.ts +93 -0
  258. package/src/router/middleware.ts +505 -441
  259. package/src/router/navigation-snapshot.ts +133 -0
  260. package/src/router/params-util.ts +23 -0
  261. package/src/router/parse-pattern.ts +115 -0
  262. package/src/router/pattern-matching.ts +311 -142
  263. package/src/router/prefetch-cache-ttl.ts +51 -0
  264. package/src/router/prefetch-limits.ts +37 -0
  265. package/src/router/prerender-match.ts +547 -0
  266. package/src/router/preview-match.ts +102 -0
  267. package/src/router/request-classification.ts +278 -0
  268. package/src/router/revalidation.ts +203 -62
  269. package/src/router/route-snapshot.ts +246 -0
  270. package/src/router/router-context.ts +45 -48
  271. package/src/router/router-interfaces.ts +554 -0
  272. package/src/router/router-options.ts +779 -0
  273. package/src/router/router-registry.ts +21 -0
  274. package/src/router/segment-resolution/fresh.ts +772 -0
  275. package/src/router/segment-resolution/helpers.ts +348 -0
  276. package/src/router/segment-resolution/loader-cache.ts +250 -0
  277. package/src/router/segment-resolution/loader-mask.ts +44 -0
  278. package/src/router/segment-resolution/revalidation.ts +1331 -0
  279. package/src/router/segment-resolution/static-store.ts +81 -0
  280. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  281. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  282. package/src/router/segment-resolution.ts +25 -1354
  283. package/src/router/segment-wrappers.ts +292 -0
  284. package/src/router/state-cookie-name.ts +33 -0
  285. package/src/router/substitute-pattern-params.ts +75 -0
  286. package/src/router/telemetry-otel.ts +261 -0
  287. package/src/router/telemetry.ts +377 -0
  288. package/src/router/timeout.ts +128 -0
  289. package/src/router/tracing.ts +206 -0
  290. package/src/router/trie-matching.ts +240 -61
  291. package/src/router/types.ts +23 -70
  292. package/src/router/url-params.ts +57 -0
  293. package/src/router.ts +781 -2378
  294. package/src/rsc/full-payload.ts +70 -0
  295. package/src/rsc/handler-context.ts +46 -0
  296. package/src/rsc/handler.ts +905 -1142
  297. package/src/rsc/helpers.ts +275 -19
  298. package/src/rsc/index.ts +2 -25
  299. package/src/rsc/json-route-result.ts +38 -0
  300. package/src/rsc/loader-fetch.ts +305 -0
  301. package/src/rsc/manifest-init.ts +77 -0
  302. package/src/rsc/nonce.ts +14 -0
  303. package/src/rsc/origin-guard.ts +155 -0
  304. package/src/rsc/progressive-enhancement.ts +502 -0
  305. package/src/rsc/redirect-guard.ts +99 -0
  306. package/src/rsc/response-cache-serve.ts +238 -0
  307. package/src/rsc/response-error.ts +104 -0
  308. package/src/rsc/response-route-handler.ts +257 -0
  309. package/src/rsc/rsc-rendering.ts +337 -0
  310. package/src/rsc/runtime-warnings.ts +55 -0
  311. package/src/rsc/server-action.ts +522 -0
  312. package/src/rsc/shell-capture.ts +439 -0
  313. package/src/rsc/ssr-setup.ts +144 -0
  314. package/src/rsc/transition-gate.ts +89 -0
  315. package/src/rsc/types.ts +95 -12
  316. package/src/runtime-env.ts +18 -0
  317. package/src/search-params.ts +99 -82
  318. package/src/segment-content-promise.ts +67 -0
  319. package/src/segment-loader-promise.ts +149 -0
  320. package/src/segment-system.tsx +349 -134
  321. package/src/serialize.ts +243 -0
  322. package/src/server/context.ts +452 -85
  323. package/src/server/cookie-parse.ts +32 -0
  324. package/src/server/cookie-store.ts +310 -0
  325. package/src/server/fetchable-loader-store.ts +11 -6
  326. package/src/server/handle-store.ts +123 -42
  327. package/src/server/live.ts +130 -0
  328. package/src/server/loader-registry.ts +51 -100
  329. package/src/server/request-context.ts +842 -157
  330. package/src/server.ts +15 -8
  331. package/src/ssr/index.tsx +412 -136
  332. package/src/ssr/ssr-root.tsx +228 -0
  333. package/src/static-handler.ts +45 -18
  334. package/src/testing/cache-status.ts +162 -0
  335. package/src/testing/collect-handle.ts +46 -0
  336. package/src/testing/dispatch.ts +701 -0
  337. package/src/testing/dom.entry.ts +22 -0
  338. package/src/testing/e2e/fixture.ts +188 -0
  339. package/src/testing/e2e/index.ts +128 -0
  340. package/src/testing/e2e/matchers.ts +35 -0
  341. package/src/testing/e2e/page-helpers.ts +272 -0
  342. package/src/testing/e2e/parity.ts +387 -0
  343. package/src/testing/e2e/server.ts +195 -0
  344. package/src/testing/flight-matchers.ts +97 -0
  345. package/src/testing/flight-normalize.ts +11 -0
  346. package/src/testing/flight-runtime.d.ts +57 -0
  347. package/src/testing/flight-tree.ts +682 -0
  348. package/src/testing/flight.entry.ts +52 -0
  349. package/src/testing/flight.ts +257 -0
  350. package/src/testing/generated-routes.ts +199 -0
  351. package/src/testing/index.ts +105 -0
  352. package/src/testing/internal/context.ts +371 -0
  353. package/src/testing/internal/flight-client-globals.ts +30 -0
  354. package/src/testing/internal/seed-vars.ts +54 -0
  355. package/src/testing/render-handler.ts +357 -0
  356. package/src/testing/render-route.tsx +584 -0
  357. package/src/testing/run-loader.ts +385 -0
  358. package/src/testing/run-middleware.ts +205 -0
  359. package/src/testing/run-transition-when.ts +164 -0
  360. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  361. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  362. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  363. package/src/testing/vitest-stubs/version.ts +5 -0
  364. package/src/testing/vitest.ts +305 -0
  365. package/src/theme/ThemeProvider.tsx +40 -72
  366. package/src/theme/ThemeScript.tsx +12 -14
  367. package/src/theme/constants.ts +57 -15
  368. package/src/theme/index.ts +3 -20
  369. package/src/theme/theme-context.ts +5 -35
  370. package/src/theme/theme-script.ts +43 -39
  371. package/src/theme/use-theme.ts +0 -3
  372. package/src/types/boundaries.ts +123 -0
  373. package/src/types/cache-types.ts +207 -0
  374. package/src/types/error-types.ts +132 -0
  375. package/src/types/global-namespace.ts +113 -0
  376. package/src/types/handler-context.ts +839 -0
  377. package/src/types/index.ts +81 -0
  378. package/src/types/loader-types.ts +212 -0
  379. package/src/types/request-scope.ts +112 -0
  380. package/src/types/route-config.ts +138 -0
  381. package/src/types/route-entry.ts +114 -0
  382. package/src/types/segments.ts +271 -0
  383. package/src/types.ts +1 -1795
  384. package/src/urls/include-helper.ts +162 -0
  385. package/src/urls/include-provider.ts +71 -0
  386. package/src/urls/index.ts +43 -0
  387. package/src/urls/path-helper-types.ts +413 -0
  388. package/src/urls/path-helper.ts +275 -0
  389. package/src/urls/pattern-types.ts +124 -0
  390. package/src/urls/response-types.ts +109 -0
  391. package/src/urls/type-extraction.ts +316 -0
  392. package/src/urls/urls-function.ts +80 -0
  393. package/src/urls.ts +1 -1341
  394. package/src/use-loader.tsx +406 -141
  395. package/src/vercel/index.ts +11 -0
  396. package/src/vercel/tracing.ts +88 -0
  397. package/src/vite/debug.ts +185 -0
  398. package/src/vite/discovery/bundle-postprocess.ts +182 -0
  399. package/src/vite/discovery/discover-routers.ts +389 -0
  400. package/src/vite/discovery/discovery-errors.ts +255 -0
  401. package/src/vite/discovery/gate-state.ts +171 -0
  402. package/src/vite/discovery/prerender-collection.ts +467 -0
  403. package/src/vite/discovery/route-types-writer.ts +214 -0
  404. package/src/vite/discovery/self-gen-tracking.ts +73 -0
  405. package/src/vite/discovery/state.ts +161 -0
  406. package/src/vite/discovery/virtual-module-codegen.ts +183 -0
  407. package/src/vite/index.ts +23 -2255
  408. package/src/vite/inject-client-debug.ts +36 -0
  409. package/src/vite/plugin-types.ts +303 -0
  410. package/src/vite/plugins/cjs-to-esm.ts +90 -0
  411. package/src/vite/plugins/client-ref-dedup.ts +120 -0
  412. package/src/vite/plugins/client-ref-hashing.ts +118 -0
  413. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  414. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  415. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  416. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
  417. package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
  418. package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
  419. package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
  420. package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
  421. package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
  422. package/src/vite/plugins/expose-ids/types.ts +45 -0
  423. package/src/vite/plugins/expose-internal-ids.ts +805 -0
  424. package/src/vite/plugins/performance-tracks.ts +89 -0
  425. package/src/vite/plugins/refresh-cmd.ts +127 -0
  426. package/src/vite/plugins/use-cache-transform.ts +313 -0
  427. package/src/vite/plugins/vercel-output.ts +384 -0
  428. package/src/vite/plugins/version-injector.ts +94 -0
  429. package/src/vite/plugins/version-plugin.ts +263 -0
  430. package/src/vite/plugins/virtual-entries.ts +234 -0
  431. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  432. package/src/vite/rango.ts +560 -0
  433. package/src/vite/router-discovery.ts +1638 -0
  434. package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
  435. package/src/vite/utils/banner.ts +36 -0
  436. package/src/vite/utils/bundle-analysis.ts +132 -0
  437. package/src/vite/utils/client-chunks.ts +184 -0
  438. package/src/vite/utils/directive-prologue.ts +40 -0
  439. package/src/vite/utils/forward-user-plugins.ts +171 -0
  440. package/src/vite/utils/manifest-utils.ts +15 -0
  441. package/src/vite/utils/package-resolution.ts +89 -0
  442. package/src/vite/utils/prerender-utils.ts +249 -0
  443. package/src/vite/utils/shared-utils.ts +269 -0
  444. package/CLAUDE.md +0 -43
  445. package/dist/vite/index.named-routes.gen.ts +0 -103
  446. package/src/browser/lru-cache.ts +0 -69
  447. package/src/browser/react/use-client-cache.ts +0 -56
  448. package/src/browser/request-controller.ts +0 -164
  449. package/src/browser/shallow.ts +0 -35
  450. package/src/cache/memory-store.ts +0 -253
  451. package/src/handles/index.ts +0 -6
  452. package/src/href-context.ts +0 -33
  453. package/src/network-error-thrower.tsx +0 -21
  454. package/src/router.gen.ts +0 -6
  455. package/src/static-handler.gen.ts +0 -5
  456. package/src/urls.gen.ts +0 -8
  457. package/src/vite/expose-internal-ids.ts +0 -1167
  458. package/src/vite/package-resolution.ts +0 -125
  459. package/src/vite/virtual-entries.ts +0 -114
  460. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -11,7 +11,13 @@
11
11
  * - Handles SSR hydration by deferring system theme detection
12
12
  */
13
13
 
14
- import React, { useCallback, useEffect, useMemo, useState, useRef } from "react";
14
+ import React, {
15
+ useCallback,
16
+ useEffect,
17
+ useMemo,
18
+ useState,
19
+ useRef,
20
+ } from "react";
15
21
  import { ThemeContext } from "./theme-context.js";
16
22
  import type {
17
23
  ResolvedTheme,
@@ -20,11 +26,8 @@ import type {
20
26
  ThemeContextValue,
21
27
  ThemeProviderProps,
22
28
  } from "./types.js";
23
- import { THEME_COOKIE } from "./constants.js";
29
+ import { THEME_COOKIE, isValidTheme, warnInvalidTheme } from "./constants.js";
24
30
 
25
- /**
26
- * Get system preference for color scheme
27
- */
28
31
  function getSystemTheme(): ResolvedTheme {
29
32
  if (typeof window !== "undefined" && window.matchMedia) {
30
33
  return window.matchMedia("(prefers-color-scheme: dark)").matches
@@ -34,9 +37,6 @@ function getSystemTheme(): ResolvedTheme {
34
37
  return "light";
35
38
  }
36
39
 
37
- /**
38
- * Read theme from cookie
39
- */
40
40
  function readThemeFromCookie(storageKey: string): string | null {
41
41
  if (typeof document === "undefined") return null;
42
42
 
@@ -44,15 +44,17 @@ function readThemeFromCookie(storageKey: string): string | null {
44
44
  for (const cookie of cookies) {
45
45
  const [name, ...rest] = cookie.trim().split("=");
46
46
  if (name === storageKey) {
47
- return decodeURIComponent(rest.join("="));
47
+ const raw = rest.join("=");
48
+ try {
49
+ return decodeURIComponent(raw);
50
+ } catch {
51
+ return raw;
52
+ }
48
53
  }
49
54
  }
50
55
  return null;
51
56
  }
52
57
 
53
- /**
54
- * Read theme from localStorage
55
- */
56
58
  function readThemeFromStorage(storageKey: string): string | null {
57
59
  if (typeof localStorage === "undefined") return null;
58
60
 
@@ -63,9 +65,6 @@ function readThemeFromStorage(storageKey: string): string | null {
63
65
  }
64
66
  }
65
67
 
66
- /**
67
- * Write theme to cookie
68
- */
69
68
  function writeThemeToCookie(storageKey: string, theme: Theme): void {
70
69
  if (typeof document === "undefined") return;
71
70
 
@@ -74,9 +73,6 @@ function writeThemeToCookie(storageKey: string, theme: Theme): void {
74
73
  document.cookie = cookie;
75
74
  }
76
75
 
77
- /**
78
- * Write theme to localStorage
79
- */
80
76
  function writeThemeToStorage(storageKey: string, theme: Theme): void {
81
77
  if (typeof localStorage === "undefined") return;
82
78
 
@@ -87,56 +83,41 @@ function writeThemeToStorage(storageKey: string, theme: Theme): void {
87
83
  }
88
84
  }
89
85
 
90
- /**
91
- * Apply theme to HTML element
92
- */
93
- function applyThemeToDocument(
94
- theme: Theme,
95
- config: ResolvedThemeConfig
96
- ): void {
86
+ function applyThemeToDocument(theme: Theme, config: ResolvedThemeConfig): void {
97
87
  if (typeof document === "undefined") return;
98
88
 
99
- const resolved = theme === "system" && config.enableSystem
100
- ? getSystemTheme()
101
- : (theme as ResolvedTheme);
89
+ const resolved =
90
+ theme === "system" && config.enableSystem
91
+ ? getSystemTheme()
92
+ : (theme as ResolvedTheme);
102
93
 
103
94
  const value = config.value[resolved] || resolved;
104
95
  const el = document.documentElement;
105
96
 
106
- // Apply attribute
107
97
  if (config.attribute === "class") {
108
- // Remove all theme classes
109
98
  for (const t of config.themes) {
110
99
  const v = config.value[t] || t;
111
100
  el.classList.remove(v);
112
101
  }
113
- // Add current theme class
114
102
  el.classList.add(value);
115
103
  } else {
116
104
  el.setAttribute(config.attribute, value);
117
105
  }
118
106
 
119
- // Set color-scheme for native dark mode support
120
107
  if (config.enableColorScheme) {
121
108
  el.style.colorScheme = resolved;
122
109
  }
123
110
  }
124
111
 
125
- /**
126
- * Get the resolved stored theme (validated against available themes)
127
- */
128
112
  function getStoredTheme(config: ResolvedThemeConfig): Theme {
129
113
  const { storageKey, themes, defaultTheme, enableSystem } = config;
130
114
 
131
- // Try cookie first (for SSR consistency)
132
115
  let stored = readThemeFromCookie(storageKey);
133
116
 
134
- // Fall back to localStorage
135
117
  if (!stored) {
136
118
  stored = readThemeFromStorage(storageKey);
137
119
  }
138
120
 
139
- // Validate stored value
140
121
  if (stored) {
141
122
  if (stored === "system" && enableSystem) {
142
123
  return "system";
@@ -149,49 +130,45 @@ function getStoredTheme(config: ResolvedThemeConfig): Theme {
149
130
  return defaultTheme;
150
131
  }
151
132
 
152
- /**
153
- * ThemeProvider component
154
- *
155
- * Provides theme state to the component tree via context.
156
- * Handles theme persistence, system preference detection, and cross-tab sync.
157
- */
158
133
  export function ThemeProvider({
159
134
  config,
160
135
  initialTheme,
161
136
  children,
162
137
  }: ThemeProviderProps): React.ReactNode {
163
- // Track mount state to avoid hydration mismatches
164
- // During SSR and initial hydration, mounted is false
165
138
  const [mounted, setMounted] = useState(false);
166
139
 
167
- // Initialize theme from prop, storage, or default
168
140
  const [theme, setThemeState] = useState<Theme>(() => {
169
141
  if (initialTheme) return initialTheme;
170
142
  if (typeof window === "undefined") return config.defaultTheme;
171
143
  return getStoredTheme(config);
172
144
  });
173
145
 
174
- // Track system preference - use stable default during SSR
175
146
  const [systemTheme, setSystemTheme] = useState<ResolvedTheme>("light");
176
147
 
177
- // Set mounted after hydration and detect actual system theme
178
148
  useEffect(() => {
179
149
  setMounted(true);
180
150
  setSystemTheme(getSystemTheme());
181
151
  }, []);
182
152
 
183
- // Set theme and persist to storage
184
153
  const setTheme = useCallback(
185
154
  (newTheme: Theme) => {
155
+ // Shared guard (isValidTheme) used by the server ctx.setTheme too: reject
156
+ // any value not in the configured theme set, AND reject "system" when
157
+ // system detection is off (applyThemeToDocument would write a bogus
158
+ // class="system"). Keeps the cookie from holding a value the server would
159
+ // reinterpret as defaultTheme on the next SSR (desyncing markup).
160
+ if (!isValidTheme(newTheme, config)) {
161
+ warnInvalidTheme(newTheme, config);
162
+ return;
163
+ }
186
164
  setThemeState(newTheme);
187
165
  writeThemeToCookie(config.storageKey, newTheme);
188
166
  writeThemeToStorage(config.storageKey, newTheme);
189
167
  applyThemeToDocument(newTheme, config);
190
168
  },
191
- [config]
169
+ [config],
192
170
  );
193
171
 
194
- // Listen for system preference changes
195
172
  useEffect(() => {
196
173
  if (!config.enableSystem) return;
197
174
  if (typeof window === "undefined" || !window.matchMedia) return;
@@ -202,13 +179,11 @@ export function ThemeProvider({
202
179
  const newSystemTheme = e.matches ? "dark" : "light";
203
180
  setSystemTheme(newSystemTheme);
204
181
 
205
- // If current theme is "system", re-apply to update document
206
182
  if (theme === "system") {
207
183
  applyThemeToDocument("system", config);
208
184
  }
209
185
  };
210
186
 
211
- // Modern browsers
212
187
  mediaQuery.addEventListener("change", handleChange);
213
188
 
214
189
  return () => {
@@ -216,7 +191,6 @@ export function ThemeProvider({
216
191
  };
217
192
  }, [config, theme]);
218
193
 
219
- // Cross-tab synchronization via localStorage storage event
220
194
  useEffect(() => {
221
195
  if (typeof window === "undefined") return;
222
196
 
@@ -226,14 +200,16 @@ export function ThemeProvider({
226
200
  const newTheme = e.newValue;
227
201
  if (!newTheme) return;
228
202
 
229
- // Validate and apply
230
- if (
231
- newTheme === "system" ||
232
- config.themes.includes(newTheme)
233
- ) {
234
- setThemeState(newTheme as Theme);
235
- applyThemeToDocument(newTheme as Theme, config);
236
- }
203
+ // A cross-tab storage event can carry any value (another tab, or stale
204
+ // localStorage). Reuse the shared validity rule: reject anything not a
205
+ // configured theme, AND reject "system" when system detection is off (it
206
+ // would apply a bogus class="system"). An invalid received value falls back
207
+ // to defaultTheme rather than applying as-is.
208
+ const applied: Theme = isValidTheme(newTheme, config)
209
+ ? (newTheme as Theme)
210
+ : config.defaultTheme;
211
+ setThemeState(applied);
212
+ applyThemeToDocument(applied, config);
237
213
  };
238
214
 
239
215
  window.addEventListener("storage", handleStorageChange);
@@ -243,12 +219,8 @@ export function ThemeProvider({
243
219
  };
244
220
  }, [config]);
245
221
 
246
- // Compute resolved theme
247
- // During SSR (not mounted), use the initial theme or default to avoid hydration mismatch
248
222
  const resolvedTheme: ResolvedTheme = useMemo(() => {
249
223
  if (!mounted) {
250
- // During SSR, return the initial theme if it's not "system", otherwise "light"
251
- // The inline script will apply the correct class before hydration
252
224
  if (initialTheme && initialTheme !== "system") {
253
225
  return initialTheme as ResolvedTheme;
254
226
  }
@@ -260,7 +232,6 @@ export function ThemeProvider({
260
232
  return theme as ResolvedTheme;
261
233
  }, [theme, systemTheme, config.enableSystem, mounted, initialTheme]);
262
234
 
263
- // Build themes list (include "system" if enabled)
264
235
  const themes = useMemo(() => {
265
236
  if (config.enableSystem) {
266
237
  return ["system", ...config.themes.filter((t) => t !== "system")];
@@ -268,19 +239,16 @@ export function ThemeProvider({
268
239
  return config.themes;
269
240
  }, [config.themes, config.enableSystem]);
270
241
 
271
- // Context value
272
- // During SSR (not mounted), return stable values to avoid hydration mismatch
273
242
  const contextValue: ThemeContextValue = useMemo(
274
243
  () => ({
275
244
  theme,
276
245
  setTheme,
277
246
  resolvedTheme,
278
- // Return stable "light" for systemTheme during SSR - actual value updates after mount
279
247
  systemTheme: mounted ? systemTheme : "light",
280
248
  themes,
281
249
  config,
282
250
  }),
283
- [theme, setTheme, resolvedTheme, systemTheme, themes, config, mounted]
251
+ [theme, setTheme, resolvedTheme, systemTheme, themes, config, mounted],
284
252
  );
285
253
 
286
254
  return (
@@ -8,17 +8,21 @@
8
8
  *
9
9
  * Must be placed in the <head> element of your document, before any stylesheets.
10
10
  *
11
+ * Note: when theme is enabled in the router config, `<MetaTags />` ALREADY
12
+ * renders this FOUC script. Use `<ThemeScript />` only if you do NOT render
13
+ * `<MetaTags />`. Rendering both is safe — the inline script guards the
14
+ * matchMedia listener registration against double-running — but it is redundant.
15
+ *
11
16
  * @example
12
17
  * ```tsx
13
- * // In your document component
18
+ * // In your document component. Use ThemeScript only when you do not render MetaTags.
14
19
  * import { ThemeScript } from "@rangojs/router/theme";
15
20
  *
16
21
  * export function Document({ children }) {
17
22
  * return (
18
23
  * <html lang="en" suppressHydrationWarning>
19
24
  * <head>
20
- * <ThemeScript />
21
- * <MetaTags />
25
+ * <ThemeScript config={config} />
22
26
  * </head>
23
27
  * <body>{children}</body>
24
28
  * </html>
@@ -43,19 +47,13 @@ export interface ThemeScriptProps {
43
47
  nonce?: string;
44
48
  }
45
49
 
46
- /**
47
- * Server component that renders the theme initialization script.
48
- *
49
- * This renders a synchronous inline script that applies the theme
50
- * to the HTML element before React hydration, preventing FOUC.
51
- */
52
- export function ThemeScript({ config, nonce }: ThemeScriptProps): React.ReactNode {
50
+ export function ThemeScript({
51
+ config,
52
+ nonce,
53
+ }: ThemeScriptProps): React.ReactNode {
53
54
  const scriptContent = generateThemeScript(config);
54
55
 
55
56
  return (
56
- <script
57
- nonce={nonce}
58
- dangerouslySetInnerHTML={{ __html: scriptContent }}
59
- />
57
+ <script nonce={nonce} dangerouslySetInnerHTML={{ __html: scriptContent }} />
60
58
  );
61
59
  }
@@ -2,11 +2,8 @@
2
2
  * Default values for theme configuration
3
3
  */
4
4
 
5
- import type { ResolvedThemeConfig, ThemeConfig } from "./types.js";
5
+ import type { ResolvedThemeConfig, Theme, ThemeConfig } from "./types.js";
6
6
 
7
- /**
8
- * Default theme configuration values
9
- */
10
7
  export const THEME_DEFAULTS = {
11
8
  defaultTheme: "system",
12
9
  themes: ["light", "dark"],
@@ -16,9 +13,6 @@ export const THEME_DEFAULTS = {
16
13
  enableColorScheme: true,
17
14
  } as const;
18
15
 
19
- /**
20
- * Cookie configuration for theme persistence
21
- */
22
16
  export const THEME_COOKIE: {
23
17
  readonly maxAge: number;
24
18
  readonly path: string;
@@ -30,30 +24,78 @@ export const THEME_COOKIE: {
30
24
  };
31
25
 
32
26
  /**
33
- * Resolve theme config by applying defaults.
34
- * Accepts `true` to enable with all defaults, or a config object.
27
+ * Single owner of the setTheme validity rule, shared by the client
28
+ * (ThemeProvider) and server (ctx.setTheme) guards so they cannot drift.
29
+ *
30
+ * A theme is valid when it is one of the configured concrete themes, OR
31
+ * "system" but only while system detection is enabled. Rejecting "system" when
32
+ * `enableSystem` is false is load-bearing: applyThemeToDocument would otherwise
33
+ * leave "system" unresolved and write a bogus class="system" / colorScheme
34
+ * ="system" on <html> (the same bogus value resolveThemeConfig coerces away for
35
+ * the default).
36
+ */
37
+ export function isValidTheme(
38
+ theme: string,
39
+ config: Pick<ResolvedThemeConfig, "themes" | "enableSystem">,
40
+ ): boolean {
41
+ if (theme === "system") return config.enableSystem;
42
+ return config.themes.includes(theme);
43
+ }
44
+
45
+ /**
46
+ * Emit the shared "[Theme] Invalid theme value" warning. One owner of the
47
+ * message string so the client and server guards stay byte-identical.
48
+ *
49
+ * The valid-values list mirrors isValidTheme: "system" is only listed when
50
+ * enableSystem is true, otherwise the message would advertise a value the guard
51
+ * itself rejects.
35
52
  */
36
- export function resolveThemeConfig(config: ThemeConfig | true): ResolvedThemeConfig {
37
- // Handle `theme: true` shorthand
53
+ export function warnInvalidTheme(
54
+ theme: string,
55
+ config: Pick<ResolvedThemeConfig, "themes" | "enableSystem">,
56
+ ): void {
57
+ const validValues = config.enableSystem
58
+ ? ["system", ...config.themes]
59
+ : config.themes;
60
+ console.warn(
61
+ `[Theme] Invalid theme value: "${theme}". Valid values: ${validValues.join(", ")}`,
62
+ );
63
+ }
64
+
65
+ export function resolveThemeConfig(
66
+ config: ThemeConfig | true,
67
+ ): ResolvedThemeConfig {
38
68
  if (config === true) {
39
69
  config = {};
40
70
  }
41
71
 
42
72
  const themes = config.themes ?? [...THEME_DEFAULTS.themes];
43
73
 
44
- // Build value mapping - default to identity mapping
45
74
  const value: Record<string, string> = {};
46
75
  for (const theme of themes) {
47
76
  value[theme] = config.value?.[theme] ?? theme;
48
77
  }
49
78
 
79
+ const enableSystem = config.enableSystem ?? THEME_DEFAULTS.enableSystem;
80
+
81
+ // When system detection is disabled, "system" is not a valid resolved theme.
82
+ // Coerce both the unset default and an explicit defaultTheme:"system" to the
83
+ // first concrete theme, so the FOUC script / ThemeProvider never apply a bogus
84
+ // class="system" / colorScheme="system" on <html>.
85
+ const requestedDefault = config.defaultTheme ?? THEME_DEFAULTS.defaultTheme;
86
+ const defaultTheme =
87
+ !enableSystem && requestedDefault === "system"
88
+ ? (themes[0] as Theme)
89
+ : requestedDefault;
90
+
50
91
  return {
51
- defaultTheme: config.defaultTheme ?? THEME_DEFAULTS.defaultTheme,
92
+ defaultTheme,
52
93
  themes,
53
94
  attribute: config.attribute ?? THEME_DEFAULTS.attribute,
54
95
  storageKey: config.storageKey ?? THEME_DEFAULTS.storageKey,
55
- enableSystem: config.enableSystem ?? THEME_DEFAULTS.enableSystem,
56
- enableColorScheme: config.enableColorScheme ?? THEME_DEFAULTS.enableColorScheme,
96
+ enableSystem,
97
+ enableColorScheme:
98
+ config.enableColorScheme ?? THEME_DEFAULTS.enableColorScheme,
57
99
  value,
58
100
  };
59
101
  }
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Theme module exports for @rangojs/router/theme
3
3
  *
4
- * This module provides theme management for rsc-router:
4
+ * This module provides the public theme API:
5
5
  * - useTheme: Hook for accessing theme state in client components
6
6
  * - ThemeProvider: Component for manual theme provider setup (typically not needed)
7
+ * - ThemeScript: FOUC-prevention script component for document/head usage
7
8
  * - Types for theme configuration
8
9
  *
9
10
  * @example
@@ -22,16 +23,10 @@
22
23
  * ```
23
24
  */
24
25
 
25
- // Main hook for accessing theme
26
26
  export { useTheme } from "./use-theme.js";
27
-
28
- // Provider (typically auto-included via NavigationProvider when theme is enabled)
29
27
  export { ThemeProvider } from "./ThemeProvider.js";
30
-
31
- // Script component for FOUC prevention (use in document head)
32
28
  export { ThemeScript, type ThemeScriptProps } from "./ThemeScript.js";
33
29
 
34
- // Types
35
30
  export type {
36
31
  Theme,
37
32
  ResolvedTheme,
@@ -43,16 +38,4 @@ export type {
43
38
  ThemeContextValue,
44
39
  } from "./types.js";
45
40
 
46
- // Constants (for advanced use cases)
47
- export { THEME_DEFAULTS, THEME_COOKIE, resolveThemeConfig } from "./constants.js";
48
-
49
- // Script generation (for advanced SSR use cases)
50
- export { generateThemeScript, getNonceAttribute } from "./theme-script.js";
51
-
52
- // Context (for advanced use cases)
53
- export {
54
- ThemeContext,
55
- useThemeContext,
56
- initThemeConfigSync,
57
- getSSRThemeConfig,
58
- } from "./theme-context.js";
41
+ export { THEME_DEFAULTS, THEME_COOKIE } from "./constants.js";
@@ -10,52 +10,22 @@
10
10
  */
11
11
 
12
12
  import { createContext, useContext, type Context } from "react";
13
- import type { ResolvedThemeConfig, ThemeContextValue } from "./types.js";
13
+ import type { ThemeContextValue } from "./types.js";
14
14
 
15
15
  /**
16
16
  * React context for theme state
17
17
  * null when theme is not enabled in router config
18
18
  */
19
- export const ThemeContext: Context<ThemeContextValue | null> = createContext<ThemeContextValue | null>(null);
19
+ export const ThemeContext: Context<ThemeContextValue | null> =
20
+ createContext<ThemeContextValue | null>(null);
20
21
 
21
- /**
22
- * SSR module-level state for theme config.
23
- * Populated by initThemeConfigSync before React renders.
24
- * Used by MetaTags during SSR to render the theme script.
25
- */
26
- let ssrThemeConfig: ResolvedThemeConfig | null = null;
27
-
28
- /**
29
- * Initialize theme config synchronously for SSR.
30
- * Called before rendering to populate state for MetaTags.
31
- *
32
- * @param config - Theme config from router, or null if theme is disabled
33
- */
34
- export function initThemeConfigSync(config: ResolvedThemeConfig | null): void {
35
- ssrThemeConfig = config;
36
- }
37
-
38
- /**
39
- * Get theme config for SSR/hydration.
40
- * Used by MetaTags to render the theme script.
41
- *
42
- * @returns Theme config if available, null otherwise
43
- */
44
- export function getSSRThemeConfig(): ResolvedThemeConfig | null {
45
- return ssrThemeConfig;
46
- }
47
-
48
- /**
49
- * Get theme context (internal use)
50
- * Returns null if theme is not enabled
51
- */
52
22
  export function useThemeContext(): ThemeContextValue | null {
53
23
  return useContext(ThemeContext);
54
24
  }
55
25
 
56
26
  /**
57
27
  * Get theme context, throwing if not available
58
- * Use this in useTheme hook
28
+ * Used by useTheme hook
59
29
  */
60
30
  export function requireThemeContext(): ThemeContextValue {
61
31
  const ctx = useContext(ThemeContext);
@@ -63,7 +33,7 @@ export function requireThemeContext(): ThemeContextValue {
63
33
  throw new Error(
64
34
  "useTheme must be used within a ThemeProvider. " +
65
35
  "Make sure theme is enabled in your router config: " +
66
- "createRouter({ theme: { ... } })"
36
+ "createRouter({ theme: { ... } })",
67
37
  );
68
38
  }
69
39
  return ctx;