@tonyclaw/llm-inspector 1.6.0

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 (286) hide show
  1. package/.output/nitro.json +17 -0
  2. package/.output/public/assets/alibaba-TTwafVwX.svg +1 -0
  3. package/.output/public/assets/index-B3RwBPLW.css +1 -0
  4. package/.output/public/assets/index-s4lwsWvq.js +97 -0
  5. package/.output/public/assets/main-Cp8AM0Pa.js +17 -0
  6. package/.output/public/assets/minimax-BPMzvuL-.jpeg +0 -0
  7. package/.output/public/assets/qwen-CONDcHqt.png +0 -0
  8. package/.output/public/assets/zhipuai-BPNAnxo-.svg +219 -0
  9. package/.output/server/_chunks/ssr-renderer.mjs +17 -0
  10. package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +1 -0
  11. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +210 -0
  12. package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +1 -0
  13. package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +1 -0
  14. package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +1 -0
  15. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +11 -0
  16. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +69 -0
  17. package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +1 -0
  18. package/.output/server/_libs/@radix-ui/react-use-escape-keydown+[...].mjs +17 -0
  19. package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +1 -0
  20. package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +6 -0
  21. package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +34 -0
  22. package/.output/server/_libs/ajv-formats.mjs +330 -0
  23. package/.output/server/_libs/ajv.mjs +11444 -0
  24. package/.output/server/_libs/aria-hidden.mjs +122 -0
  25. package/.output/server/_libs/atomically.mjs +152 -0
  26. package/.output/server/_libs/bail.mjs +8 -0
  27. package/.output/server/_libs/character-entities.mjs +2130 -0
  28. package/.output/server/_libs/class-variance-authority.mjs +44 -0
  29. package/.output/server/_libs/clsx.mjs +16 -0
  30. package/.output/server/_libs/comma-separated-tokens.mjs +10 -0
  31. package/.output/server/_libs/conf.mjs +635 -0
  32. package/.output/server/_libs/cookie-es.mjs +58 -0
  33. package/.output/server/_libs/core-util-is.mjs +75 -0
  34. package/.output/server/_libs/croner.mjs +1 -0
  35. package/.output/server/_libs/crossws.mjs +1 -0
  36. package/.output/server/_libs/debounce-fn.mjs +69 -0
  37. package/.output/server/_libs/decode-named-character-reference+[...].mjs +8 -0
  38. package/.output/server/_libs/detect-node-es.mjs +1 -0
  39. package/.output/server/_libs/devlop.mjs +8 -0
  40. package/.output/server/_libs/dot-prop.mjs +265 -0
  41. package/.output/server/_libs/env-paths.mjs +57 -0
  42. package/.output/server/_libs/estree-util-is-identifier-name.mjs +11 -0
  43. package/.output/server/_libs/extend.mjs +97 -0
  44. package/.output/server/_libs/fast-deep-equal.mjs +38 -0
  45. package/.output/server/_libs/fast-uri.mjs +812 -0
  46. package/.output/server/_libs/floating-ui__core.mjs +725 -0
  47. package/.output/server/_libs/floating-ui__dom.mjs +622 -0
  48. package/.output/server/_libs/floating-ui__react-dom.mjs +292 -0
  49. package/.output/server/_libs/floating-ui__utils.mjs +320 -0
  50. package/.output/server/_libs/get-nonce.mjs +9 -0
  51. package/.output/server/_libs/h3-v2.mjs +276 -0
  52. package/.output/server/_libs/h3.mjs +400 -0
  53. package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +388 -0
  54. package/.output/server/_libs/hast-util-whitespace.mjs +10 -0
  55. package/.output/server/_libs/hookable.mjs +1 -0
  56. package/.output/server/_libs/html-url-attributes.mjs +26 -0
  57. package/.output/server/_libs/immediate.mjs +74 -0
  58. package/.output/server/_libs/inherits.mjs +50 -0
  59. package/.output/server/_libs/inline-style-parser.mjs +142 -0
  60. package/.output/server/_libs/is-plain-obj.mjs +10 -0
  61. package/.output/server/_libs/isarray.mjs +14 -0
  62. package/.output/server/_libs/isbot.mjs +20 -0
  63. package/.output/server/_libs/json-schema-traverse.mjs +180 -0
  64. package/.output/server/_libs/jszip.mjs +3049 -0
  65. package/.output/server/_libs/lie.mjs +273 -0
  66. package/.output/server/_libs/lucide-react.mjs +368 -0
  67. package/.output/server/_libs/mdast-util-from-markdown.mjs +717 -0
  68. package/.output/server/_libs/mdast-util-to-hast.mjs +710 -0
  69. package/.output/server/_libs/mdast-util-to-string.mjs +38 -0
  70. package/.output/server/_libs/micromark-core-commonmark.mjs +2259 -0
  71. package/.output/server/_libs/micromark-factory-destination.mjs +94 -0
  72. package/.output/server/_libs/micromark-factory-label.mjs +63 -0
  73. package/.output/server/_libs/micromark-factory-space.mjs +24 -0
  74. package/.output/server/_libs/micromark-factory-title.mjs +65 -0
  75. package/.output/server/_libs/micromark-factory-whitespace.mjs +22 -0
  76. package/.output/server/_libs/micromark-util-character.mjs +44 -0
  77. package/.output/server/_libs/micromark-util-chunked.mjs +36 -0
  78. package/.output/server/_libs/micromark-util-classify-character+[...].mjs +12 -0
  79. package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +41 -0
  80. package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +19 -0
  81. package/.output/server/_libs/micromark-util-decode-string.mjs +21 -0
  82. package/.output/server/_libs/micromark-util-encode.mjs +1 -0
  83. package/.output/server/_libs/micromark-util-html-tag-name.mjs +69 -0
  84. package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +6 -0
  85. package/.output/server/_libs/micromark-util-resolve-all.mjs +15 -0
  86. package/.output/server/_libs/micromark-util-sanitize-uri.mjs +41 -0
  87. package/.output/server/_libs/micromark-util-subtokenize.mjs +346 -0
  88. package/.output/server/_libs/micromark.mjs +906 -0
  89. package/.output/server/_libs/mimic-function.mjs +47 -0
  90. package/.output/server/_libs/ohash.mjs +1 -0
  91. package/.output/server/_libs/pako.mjs +4223 -0
  92. package/.output/server/_libs/process-nextick-args.mjs +48 -0
  93. package/.output/server/_libs/property-information.mjs +1209 -0
  94. package/.output/server/_libs/radix-ui.mjs +1 -0
  95. package/.output/server/_libs/radix-ui__number.mjs +6 -0
  96. package/.output/server/_libs/radix-ui__primitive.mjs +11 -0
  97. package/.output/server/_libs/radix-ui__react-accordion.mjs +1 -0
  98. package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +1 -0
  99. package/.output/server/_libs/radix-ui__react-arrow.mjs +23 -0
  100. package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +1 -0
  101. package/.output/server/_libs/radix-ui__react-avatar.mjs +1 -0
  102. package/.output/server/_libs/radix-ui__react-checkbox.mjs +1 -0
  103. package/.output/server/_libs/radix-ui__react-collapsible.mjs +144 -0
  104. package/.output/server/_libs/radix-ui__react-collection.mjs +69 -0
  105. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +39 -0
  106. package/.output/server/_libs/radix-ui__react-context-menu.mjs +1 -0
  107. package/.output/server/_libs/radix-ui__react-context.mjs +78 -0
  108. package/.output/server/_libs/radix-ui__react-dialog.mjs +325 -0
  109. package/.output/server/_libs/radix-ui__react-direction.mjs +9 -0
  110. package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +1 -0
  111. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +29 -0
  112. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +206 -0
  113. package/.output/server/_libs/radix-ui__react-form.mjs +1 -0
  114. package/.output/server/_libs/radix-ui__react-hover-card.mjs +1 -0
  115. package/.output/server/_libs/radix-ui__react-id.mjs +14 -0
  116. package/.output/server/_libs/radix-ui__react-label.mjs +1 -0
  117. package/.output/server/_libs/radix-ui__react-menu.mjs +1 -0
  118. package/.output/server/_libs/radix-ui__react-menubar.mjs +1 -0
  119. package/.output/server/_libs/radix-ui__react-popover.mjs +1 -0
  120. package/.output/server/_libs/radix-ui__react-popper.mjs +286 -0
  121. package/.output/server/_libs/radix-ui__react-portal.mjs +16 -0
  122. package/.output/server/_libs/radix-ui__react-presence.mjs +128 -0
  123. package/.output/server/_libs/radix-ui__react-primitive.mjs +42 -0
  124. package/.output/server/_libs/radix-ui__react-progress.mjs +1 -0
  125. package/.output/server/_libs/radix-ui__react-radio-group.mjs +1 -0
  126. package/.output/server/_libs/radix-ui__react-roving-focus.mjs +224 -0
  127. package/.output/server/_libs/radix-ui__react-scroll-area.mjs +721 -0
  128. package/.output/server/_libs/radix-ui__react-select.mjs +1163 -0
  129. package/.output/server/_libs/radix-ui__react-separator.mjs +28 -0
  130. package/.output/server/_libs/radix-ui__react-slider.mjs +1 -0
  131. package/.output/server/_libs/radix-ui__react-slot.mjs +99 -0
  132. package/.output/server/_libs/radix-ui__react-switch.mjs +1 -0
  133. package/.output/server/_libs/radix-ui__react-tabs.mjs +189 -0
  134. package/.output/server/_libs/radix-ui__react-toast.mjs +1 -0
  135. package/.output/server/_libs/radix-ui__react-toggle-group.mjs +1 -0
  136. package/.output/server/_libs/radix-ui__react-toggle.mjs +1 -0
  137. package/.output/server/_libs/radix-ui__react-toolbar.mjs +1 -0
  138. package/.output/server/_libs/radix-ui__react-tooltip.mjs +495 -0
  139. package/.output/server/_libs/radix-ui__react-use-previous.mjs +14 -0
  140. package/.output/server/_libs/radix-ui__react-use-size.mjs +39 -0
  141. package/.output/server/_libs/react-dom.mjs +9935 -0
  142. package/.output/server/_libs/react-markdown.mjs +147 -0
  143. package/.output/server/_libs/react-remove-scroll-bar.mjs +82 -0
  144. package/.output/server/_libs/react-remove-scroll.mjs +328 -0
  145. package/.output/server/_libs/react-style-singleton.mjs +69 -0
  146. package/.output/server/_libs/react.mjs +515 -0
  147. package/.output/server/_libs/readable-stream.mjs +1518 -0
  148. package/.output/server/_libs/remark-parse.mjs +19 -0
  149. package/.output/server/_libs/remark-rehype.mjs +21 -0
  150. package/.output/server/_libs/rou3.mjs +8 -0
  151. package/.output/server/_libs/safe-buffer.mjs +64 -0
  152. package/.output/server/_libs/semver.mjs +1984 -0
  153. package/.output/server/_libs/seroval-plugins.mjs +58 -0
  154. package/.output/server/_libs/seroval.mjs +1765 -0
  155. package/.output/server/_libs/setimmediate.mjs +1 -0
  156. package/.output/server/_libs/space-separated-tokens.mjs +6 -0
  157. package/.output/server/_libs/srvx.mjs +334 -0
  158. package/.output/server/_libs/stubborn-fs.mjs +91 -0
  159. package/.output/server/_libs/stubborn-utils.mjs +66 -0
  160. package/.output/server/_libs/style-to-js.mjs +72 -0
  161. package/.output/server/_libs/style-to-object.mjs +38 -0
  162. package/.output/server/_libs/tailwind-merge.mjs +3010 -0
  163. package/.output/server/_libs/tanstack__history.mjs +217 -0
  164. package/.output/server/_libs/tanstack__react-router.mjs +1480 -0
  165. package/.output/server/_libs/tanstack__react-store.mjs +1 -0
  166. package/.output/server/_libs/tanstack__react-virtual.mjs +44 -0
  167. package/.output/server/_libs/tanstack__router-core.mjs +4827 -0
  168. package/.output/server/_libs/tanstack__store.mjs +1 -0
  169. package/.output/server/_libs/tanstack__virtual-core.mjs +1225 -0
  170. package/.output/server/_libs/tiny-invariant.mjs +12 -0
  171. package/.output/server/_libs/tiny-warning.mjs +5 -0
  172. package/.output/server/_libs/trim-lines.mjs +41 -0
  173. package/.output/server/_libs/trough.mjs +85 -0
  174. package/.output/server/_libs/tslib.mjs +576 -0
  175. package/.output/server/_libs/ufo.mjs +54 -0
  176. package/.output/server/_libs/uint8array-extras.mjs +69 -0
  177. package/.output/server/_libs/unctx.mjs +1 -0
  178. package/.output/server/_libs/ungap__structured-clone.mjs +212 -0
  179. package/.output/server/_libs/unified.mjs +661 -0
  180. package/.output/server/_libs/unist-util-is.mjs +100 -0
  181. package/.output/server/_libs/unist-util-position.mjs +27 -0
  182. package/.output/server/_libs/unist-util-stringify-position.mjs +27 -0
  183. package/.output/server/_libs/unist-util-visit-parents.mjs +82 -0
  184. package/.output/server/_libs/unist-util-visit.mjs +24 -0
  185. package/.output/server/_libs/unstorage.mjs +1 -0
  186. package/.output/server/_libs/use-callback-ref.mjs +66 -0
  187. package/.output/server/_libs/use-sidecar.mjs +106 -0
  188. package/.output/server/_libs/use-sync-external-store.mjs +1 -0
  189. package/.output/server/_libs/util-deprecate.mjs +12 -0
  190. package/.output/server/_libs/vfile-message.mjs +138 -0
  191. package/.output/server/_libs/vfile.mjs +467 -0
  192. package/.output/server/_libs/when-exit.mjs +53 -0
  193. package/.output/server/_libs/zod.mjs +4460 -0
  194. package/.output/server/_ssr/index-ByCLZu7J.mjs +3061 -0
  195. package/.output/server/_ssr/index.mjs +1176 -0
  196. package/.output/server/_ssr/router-Bq_mxeNz.mjs +2872 -0
  197. package/.output/server/_ssr/start-HYkvq4Ni.mjs +4 -0
  198. package/.output/server/_tanstack-start-manifest_v-C4E0e9my.mjs +4 -0
  199. package/.output/server/index.mjs +393 -0
  200. package/README.md +196 -0
  201. package/package.json +91 -0
  202. package/src/assets/logos/alibaba.svg +1 -0
  203. package/src/assets/logos/anthropic.svg +1 -0
  204. package/src/assets/logos/deepseek.svg +1 -0
  205. package/src/assets/logos/minimax.jpeg +0 -0
  206. package/src/assets/logos/openai.svg +1 -0
  207. package/src/assets/logos/qwen.png +0 -0
  208. package/src/assets/logos/zhipuai.svg +219 -0
  209. package/src/cli.ts +68 -0
  210. package/src/components/ProxyViewer.tsx +325 -0
  211. package/src/components/ProxyViewerContainer.tsx +211 -0
  212. package/src/components/providers/ProviderCard.tsx +186 -0
  213. package/src/components/providers/ProviderForm.tsx +259 -0
  214. package/src/components/providers/ProviderLogo.tsx +111 -0
  215. package/src/components/providers/ProvidersPanel.tsx +259 -0
  216. package/src/components/providers/SettingsDialog.tsx +39 -0
  217. package/src/components/proxy-viewer/ConversationGroup.tsx +68 -0
  218. package/src/components/proxy-viewer/ConversationHeader.tsx +141 -0
  219. package/src/components/proxy-viewer/LogEntry.tsx +225 -0
  220. package/src/components/proxy-viewer/LogEntryHeader.tsx +250 -0
  221. package/src/components/proxy-viewer/ReplayDialog.tsx +208 -0
  222. package/src/components/proxy-viewer/ResponseView.tsx +161 -0
  223. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +171 -0
  224. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +139 -0
  225. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +64 -0
  226. package/src/components/proxy-viewer/formats/index.tsx +24 -0
  227. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +80 -0
  228. package/src/components/proxy-viewer/index.ts +8 -0
  229. package/src/components/ui/badge.tsx +47 -0
  230. package/src/components/ui/button.tsx +47 -0
  231. package/src/components/ui/collapsible.tsx +21 -0
  232. package/src/components/ui/dialog.tsx +129 -0
  233. package/src/components/ui/json-viewer.tsx +464 -0
  234. package/src/components/ui/scroll-area.tsx +54 -0
  235. package/src/components/ui/select.tsx +178 -0
  236. package/src/components/ui/separator.tsx +28 -0
  237. package/src/components/ui/tabs.tsx +88 -0
  238. package/src/components/ui/tooltip.tsx +51 -0
  239. package/src/index.css +11 -0
  240. package/src/lib/export-logs.ts +51 -0
  241. package/src/lib/utils.ts +22 -0
  242. package/src/proxy/chunkStorage.ts +118 -0
  243. package/src/proxy/constants.ts +36 -0
  244. package/src/proxy/formats/anthropic/anthropicProvider.ts +75 -0
  245. package/src/proxy/formats/anthropic/handler.ts +74 -0
  246. package/src/proxy/formats/anthropic/index.ts +14 -0
  247. package/src/proxy/formats/anthropic/register.ts +4 -0
  248. package/src/proxy/formats/anthropic/schemas.ts +217 -0
  249. package/src/proxy/formats/anthropic/stream.ts +167 -0
  250. package/src/proxy/formats/handler.ts +46 -0
  251. package/src/proxy/formats/index.ts +12 -0
  252. package/src/proxy/formats/jsonSchema.ts +24 -0
  253. package/src/proxy/formats/openai/alibabaProvider.ts +38 -0
  254. package/src/proxy/formats/openai/handler.ts +70 -0
  255. package/src/proxy/formats/openai/index.ts +25 -0
  256. package/src/proxy/formats/openai/provider.ts +50 -0
  257. package/src/proxy/formats/openai/register.ts +4 -0
  258. package/src/proxy/formats/openai/schemas.ts +150 -0
  259. package/src/proxy/formats/openai/stream.ts +153 -0
  260. package/src/proxy/formats/protocol.ts +50 -0
  261. package/src/proxy/formats/providerRegistry.ts +51 -0
  262. package/src/proxy/formats/providers/index.ts +3 -0
  263. package/src/proxy/formats/registry.ts +61 -0
  264. package/src/proxy/handler.ts +389 -0
  265. package/src/proxy/logIndex.ts +187 -0
  266. package/src/proxy/logger.ts +99 -0
  267. package/src/proxy/providers.ts +234 -0
  268. package/src/proxy/schemas.ts +160 -0
  269. package/src/proxy/socketTracker.ts +158 -0
  270. package/src/proxy/store.ts +386 -0
  271. package/src/router.tsx +16 -0
  272. package/src/routes/__root.tsx +38 -0
  273. package/src/routes/api/config.paths.ts +14 -0
  274. package/src/routes/api/health.ts +11 -0
  275. package/src/routes/api/logs.$id.chunks.ts +36 -0
  276. package/src/routes/api/logs.$id.replay.ts +262 -0
  277. package/src/routes/api/logs.$id.ts +22 -0
  278. package/src/routes/api/logs.stream.ts +64 -0
  279. package/src/routes/api/logs.ts +30 -0
  280. package/src/routes/api/models.ts +10 -0
  281. package/src/routes/api/providers.$providerId.ts +45 -0
  282. package/src/routes/api/providers.ts +37 -0
  283. package/src/routes/api/sessions.ts +10 -0
  284. package/src/routes/index.tsx +6 -0
  285. package/src/routes/proxy/$.ts +15 -0
  286. package/styles/globals.css +121 -0
@@ -0,0 +1,4827 @@
1
+ import { s as splitSetCookieString } from "./cookie-es.mjs";
2
+ import { p as parseHref } from "./tanstack__history.mjs";
3
+ import { i as invariant } from "./tiny-invariant.mjs";
4
+ import { n as ni, t as te, c as cn, m as mn } from "./seroval.mjs";
5
+ import { p } from "./seroval-plugins.mjs";
6
+ import { ReadableStream as ReadableStream$1 } from "node:stream/web";
7
+ import { Readable } from "node:stream";
8
+ function toHeadersInstance(init) {
9
+ if (init instanceof Headers) {
10
+ return init;
11
+ } else if (Array.isArray(init)) {
12
+ return new Headers(init);
13
+ } else if (typeof init === "object") {
14
+ return new Headers(init);
15
+ } else {
16
+ return null;
17
+ }
18
+ }
19
+ function mergeHeaders(...headers) {
20
+ return headers.reduce((acc, header) => {
21
+ const headersInstance = toHeadersInstance(header);
22
+ if (!headersInstance) return acc;
23
+ for (const [key, value] of headersInstance.entries()) {
24
+ if (key === "set-cookie") {
25
+ const splitCookies = splitSetCookieString(value);
26
+ splitCookies.forEach((cookie) => acc.append("set-cookie", cookie));
27
+ } else {
28
+ acc.set(key, value);
29
+ }
30
+ }
31
+ return acc;
32
+ }, new Headers());
33
+ }
34
+ const isServer = true;
35
+ function batch(fn) {
36
+ {
37
+ return fn();
38
+ }
39
+ }
40
+ function isNotFound(obj) {
41
+ return !!obj?.isNotFound;
42
+ }
43
+ function last(arr) {
44
+ return arr[arr.length - 1];
45
+ }
46
+ function isFunction(d) {
47
+ return typeof d === "function";
48
+ }
49
+ function functionalUpdate(updater, previous) {
50
+ if (isFunction(updater)) {
51
+ return updater(previous);
52
+ }
53
+ return updater;
54
+ }
55
+ function replaceEqualDeep(prev, _next, _depth = 0) {
56
+ {
57
+ return _next;
58
+ }
59
+ }
60
+ function isPlainObject(o) {
61
+ if (!hasObjectPrototype(o)) {
62
+ return false;
63
+ }
64
+ const ctor = o.constructor;
65
+ if (typeof ctor === "undefined") {
66
+ return true;
67
+ }
68
+ const prot = ctor.prototype;
69
+ if (!hasObjectPrototype(prot)) {
70
+ return false;
71
+ }
72
+ if (!prot.hasOwnProperty("isPrototypeOf")) {
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ function hasObjectPrototype(o) {
78
+ return Object.prototype.toString.call(o) === "[object Object]";
79
+ }
80
+ function deepEqual(a, b, opts) {
81
+ if (a === b) {
82
+ return true;
83
+ }
84
+ if (typeof a !== typeof b) {
85
+ return false;
86
+ }
87
+ if (Array.isArray(a) && Array.isArray(b)) {
88
+ if (a.length !== b.length) return false;
89
+ for (let i = 0, l = a.length; i < l; i++) {
90
+ if (!deepEqual(a[i], b[i], opts)) return false;
91
+ }
92
+ return true;
93
+ }
94
+ if (isPlainObject(a) && isPlainObject(b)) {
95
+ const ignoreUndefined = opts?.ignoreUndefined ?? true;
96
+ if (opts?.partial) {
97
+ for (const k in b) {
98
+ if (!ignoreUndefined || b[k] !== void 0) {
99
+ if (!deepEqual(a[k], b[k], opts)) return false;
100
+ }
101
+ }
102
+ return true;
103
+ }
104
+ let aCount = 0;
105
+ if (!ignoreUndefined) {
106
+ aCount = Object.keys(a).length;
107
+ } else {
108
+ for (const k in a) {
109
+ if (a[k] !== void 0) aCount++;
110
+ }
111
+ }
112
+ let bCount = 0;
113
+ for (const k in b) {
114
+ if (!ignoreUndefined || b[k] !== void 0) {
115
+ bCount++;
116
+ if (bCount > aCount || !deepEqual(a[k], b[k], opts)) return false;
117
+ }
118
+ }
119
+ return aCount === bCount;
120
+ }
121
+ return false;
122
+ }
123
+ function createControlledPromise(onResolve) {
124
+ let resolveLoadPromise;
125
+ let rejectLoadPromise;
126
+ const controlledPromise = new Promise((resolve, reject) => {
127
+ resolveLoadPromise = resolve;
128
+ rejectLoadPromise = reject;
129
+ });
130
+ controlledPromise.status = "pending";
131
+ controlledPromise.resolve = (value) => {
132
+ controlledPromise.status = "resolved";
133
+ controlledPromise.value = value;
134
+ resolveLoadPromise(value);
135
+ onResolve?.(value);
136
+ };
137
+ controlledPromise.reject = (e) => {
138
+ controlledPromise.status = "rejected";
139
+ rejectLoadPromise(e);
140
+ };
141
+ return controlledPromise;
142
+ }
143
+ function isModuleNotFoundError(error) {
144
+ if (typeof error?.message !== "string") return false;
145
+ return error.message.startsWith("Failed to fetch dynamically imported module") || error.message.startsWith("error loading dynamically imported module") || error.message.startsWith("Importing a module script failed");
146
+ }
147
+ function isPromise(value) {
148
+ return Boolean(
149
+ value && typeof value === "object" && typeof value.then === "function"
150
+ );
151
+ }
152
+ function sanitizePathSegment(segment) {
153
+ return segment.replace(/[\x00-\x1f\x7f]/g, "");
154
+ }
155
+ function decodeSegment(segment) {
156
+ let decoded;
157
+ try {
158
+ decoded = decodeURI(segment);
159
+ } catch {
160
+ decoded = segment.replaceAll(/%[0-9A-F]{2}/gi, (match) => {
161
+ try {
162
+ return decodeURI(match);
163
+ } catch {
164
+ return match;
165
+ }
166
+ });
167
+ }
168
+ return sanitizePathSegment(decoded);
169
+ }
170
+ const DEFAULT_PROTOCOL_ALLOWLIST = [
171
+ // Standard web navigation
172
+ "http:",
173
+ "https:",
174
+ // Common browser-safe actions
175
+ "mailto:",
176
+ "tel:"
177
+ ];
178
+ function isDangerousProtocol(url, allowlist) {
179
+ if (!url) return false;
180
+ try {
181
+ const parsed = new URL(url);
182
+ return !allowlist.has(parsed.protocol);
183
+ } catch {
184
+ return false;
185
+ }
186
+ }
187
+ const HTML_ESCAPE_LOOKUP = {
188
+ "&": "\\u0026",
189
+ ">": "\\u003e",
190
+ "<": "\\u003c",
191
+ "\u2028": "\\u2028",
192
+ "\u2029": "\\u2029"
193
+ };
194
+ const HTML_ESCAPE_REGEX = /[&><\u2028\u2029]/g;
195
+ function escapeHtml(str) {
196
+ return str.replace(HTML_ESCAPE_REGEX, (match) => HTML_ESCAPE_LOOKUP[match]);
197
+ }
198
+ function decodePath(path) {
199
+ if (!path) return { path, handledProtocolRelativeURL: false };
200
+ if (!/[%\\\x00-\x1f\x7f]/.test(path) && !path.startsWith("//")) {
201
+ return { path, handledProtocolRelativeURL: false };
202
+ }
203
+ const re = /%25|%5C/gi;
204
+ let cursor = 0;
205
+ let result = "";
206
+ let match;
207
+ while (null !== (match = re.exec(path))) {
208
+ result += decodeSegment(path.slice(cursor, match.index)) + match[0];
209
+ cursor = re.lastIndex;
210
+ }
211
+ result = result + decodeSegment(cursor ? path.slice(cursor) : path);
212
+ let handledProtocolRelativeURL = false;
213
+ if (result.startsWith("//")) {
214
+ handledProtocolRelativeURL = true;
215
+ result = "/" + result.replace(/^\/+/, "");
216
+ }
217
+ return { path: result, handledProtocolRelativeURL };
218
+ }
219
+ function encodePathLikeUrl(path) {
220
+ if (!/\s|[^\u0000-\u007F]/.test(path)) return path;
221
+ return path.replace(/\s|[^\u0000-\u007F]/gu, encodeURIComponent);
222
+ }
223
+ function createLRUCache(max) {
224
+ const cache = /* @__PURE__ */ new Map();
225
+ let oldest;
226
+ let newest;
227
+ const touch = (entry) => {
228
+ if (!entry.next) return;
229
+ if (!entry.prev) {
230
+ entry.next.prev = void 0;
231
+ oldest = entry.next;
232
+ entry.next = void 0;
233
+ if (newest) {
234
+ entry.prev = newest;
235
+ newest.next = entry;
236
+ }
237
+ } else {
238
+ entry.prev.next = entry.next;
239
+ entry.next.prev = entry.prev;
240
+ entry.next = void 0;
241
+ if (newest) {
242
+ newest.next = entry;
243
+ entry.prev = newest;
244
+ }
245
+ }
246
+ newest = entry;
247
+ };
248
+ return {
249
+ get(key) {
250
+ const entry = cache.get(key);
251
+ if (!entry) return void 0;
252
+ touch(entry);
253
+ return entry.value;
254
+ },
255
+ set(key, value) {
256
+ if (cache.size >= max && oldest) {
257
+ const toDelete = oldest;
258
+ cache.delete(toDelete.key);
259
+ if (toDelete.next) {
260
+ oldest = toDelete.next;
261
+ toDelete.next.prev = void 0;
262
+ }
263
+ if (toDelete === newest) {
264
+ newest = void 0;
265
+ }
266
+ }
267
+ const existing = cache.get(key);
268
+ if (existing) {
269
+ existing.value = value;
270
+ touch(existing);
271
+ } else {
272
+ const entry = { key, value, prev: newest };
273
+ if (newest) newest.next = entry;
274
+ newest = entry;
275
+ if (!oldest) oldest = entry;
276
+ cache.set(key, entry);
277
+ }
278
+ },
279
+ clear() {
280
+ cache.clear();
281
+ oldest = void 0;
282
+ newest = void 0;
283
+ }
284
+ };
285
+ }
286
+ const SEGMENT_TYPE_PATHNAME = 0;
287
+ const SEGMENT_TYPE_PARAM = 1;
288
+ const SEGMENT_TYPE_WILDCARD = 2;
289
+ const SEGMENT_TYPE_OPTIONAL_PARAM = 3;
290
+ const SEGMENT_TYPE_INDEX = 4;
291
+ const SEGMENT_TYPE_PATHLESS = 5;
292
+ function getOpenAndCloseBraces(part) {
293
+ const openBrace = part.indexOf("{");
294
+ if (openBrace === -1) return null;
295
+ const closeBrace = part.indexOf("}", openBrace);
296
+ if (closeBrace === -1) return null;
297
+ const afterOpen = openBrace + 1;
298
+ if (afterOpen >= part.length) return null;
299
+ return [openBrace, closeBrace];
300
+ }
301
+ function parseSegment(path, start, output = new Uint16Array(6)) {
302
+ const next = path.indexOf("/", start);
303
+ const end = next === -1 ? path.length : next;
304
+ const part = path.substring(start, end);
305
+ if (!part || !part.includes("$")) {
306
+ output[0] = SEGMENT_TYPE_PATHNAME;
307
+ output[1] = start;
308
+ output[2] = start;
309
+ output[3] = end;
310
+ output[4] = end;
311
+ output[5] = end;
312
+ return output;
313
+ }
314
+ if (part === "$") {
315
+ const total = path.length;
316
+ output[0] = SEGMENT_TYPE_WILDCARD;
317
+ output[1] = start;
318
+ output[2] = start;
319
+ output[3] = total;
320
+ output[4] = total;
321
+ output[5] = total;
322
+ return output;
323
+ }
324
+ if (part.charCodeAt(0) === 36) {
325
+ output[0] = SEGMENT_TYPE_PARAM;
326
+ output[1] = start;
327
+ output[2] = start + 1;
328
+ output[3] = end;
329
+ output[4] = end;
330
+ output[5] = end;
331
+ return output;
332
+ }
333
+ const braces = getOpenAndCloseBraces(part);
334
+ if (braces) {
335
+ const [openBrace, closeBrace] = braces;
336
+ const firstChar = part.charCodeAt(openBrace + 1);
337
+ if (firstChar === 45) {
338
+ if (openBrace + 2 < part.length && part.charCodeAt(openBrace + 2) === 36) {
339
+ const paramStart = openBrace + 3;
340
+ const paramEnd = closeBrace;
341
+ if (paramStart < paramEnd) {
342
+ output[0] = SEGMENT_TYPE_OPTIONAL_PARAM;
343
+ output[1] = start + openBrace;
344
+ output[2] = start + paramStart;
345
+ output[3] = start + paramEnd;
346
+ output[4] = start + closeBrace + 1;
347
+ output[5] = end;
348
+ return output;
349
+ }
350
+ }
351
+ } else if (firstChar === 36) {
352
+ const dollarPos = openBrace + 1;
353
+ const afterDollar = openBrace + 2;
354
+ if (afterDollar === closeBrace) {
355
+ output[0] = SEGMENT_TYPE_WILDCARD;
356
+ output[1] = start + openBrace;
357
+ output[2] = start + dollarPos;
358
+ output[3] = start + afterDollar;
359
+ output[4] = start + closeBrace + 1;
360
+ output[5] = path.length;
361
+ return output;
362
+ }
363
+ output[0] = SEGMENT_TYPE_PARAM;
364
+ output[1] = start + openBrace;
365
+ output[2] = start + afterDollar;
366
+ output[3] = start + closeBrace;
367
+ output[4] = start + closeBrace + 1;
368
+ output[5] = end;
369
+ return output;
370
+ }
371
+ }
372
+ output[0] = SEGMENT_TYPE_PATHNAME;
373
+ output[1] = start;
374
+ output[2] = start;
375
+ output[3] = end;
376
+ output[4] = end;
377
+ output[5] = end;
378
+ return output;
379
+ }
380
+ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, onRoute) {
381
+ onRoute?.(route);
382
+ let cursor = start;
383
+ {
384
+ const path = route.fullPath ?? route.from;
385
+ const length = path.length;
386
+ const caseSensitive = route.options?.caseSensitive ?? defaultCaseSensitive;
387
+ const skipOnParamError = !!(route.options?.params?.parse && route.options?.skipRouteOnParseError?.params);
388
+ while (cursor < length) {
389
+ const segment = parseSegment(path, cursor, data);
390
+ let nextNode;
391
+ const start2 = cursor;
392
+ const end = segment[5];
393
+ cursor = end + 1;
394
+ depth++;
395
+ const kind = segment[0];
396
+ switch (kind) {
397
+ case SEGMENT_TYPE_PATHNAME: {
398
+ const value = path.substring(segment[2], segment[3]);
399
+ if (caseSensitive) {
400
+ const existingNode = node.static?.get(value);
401
+ if (existingNode) {
402
+ nextNode = existingNode;
403
+ } else {
404
+ node.static ??= /* @__PURE__ */ new Map();
405
+ const next = createStaticNode(
406
+ route.fullPath ?? route.from
407
+ );
408
+ next.parent = node;
409
+ next.depth = depth;
410
+ nextNode = next;
411
+ node.static.set(value, next);
412
+ }
413
+ } else {
414
+ const name = value.toLowerCase();
415
+ const existingNode = node.staticInsensitive?.get(name);
416
+ if (existingNode) {
417
+ nextNode = existingNode;
418
+ } else {
419
+ node.staticInsensitive ??= /* @__PURE__ */ new Map();
420
+ const next = createStaticNode(
421
+ route.fullPath ?? route.from
422
+ );
423
+ next.parent = node;
424
+ next.depth = depth;
425
+ nextNode = next;
426
+ node.staticInsensitive.set(name, next);
427
+ }
428
+ }
429
+ break;
430
+ }
431
+ case SEGMENT_TYPE_PARAM: {
432
+ const prefix_raw = path.substring(start2, segment[1]);
433
+ const suffix_raw = path.substring(segment[4], end);
434
+ const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
435
+ const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
436
+ const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
437
+ const existingNode = !skipOnParamError && node.dynamic?.find(
438
+ (s) => !s.skipOnParamError && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix
439
+ );
440
+ if (existingNode) {
441
+ nextNode = existingNode;
442
+ } else {
443
+ const next = createDynamicNode(
444
+ SEGMENT_TYPE_PARAM,
445
+ route.fullPath ?? route.from,
446
+ actuallyCaseSensitive,
447
+ prefix,
448
+ suffix
449
+ );
450
+ nextNode = next;
451
+ next.depth = depth;
452
+ next.parent = node;
453
+ node.dynamic ??= [];
454
+ node.dynamic.push(next);
455
+ }
456
+ break;
457
+ }
458
+ case SEGMENT_TYPE_OPTIONAL_PARAM: {
459
+ const prefix_raw = path.substring(start2, segment[1]);
460
+ const suffix_raw = path.substring(segment[4], end);
461
+ const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
462
+ const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
463
+ const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
464
+ const existingNode = !skipOnParamError && node.optional?.find(
465
+ (s) => !s.skipOnParamError && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix
466
+ );
467
+ if (existingNode) {
468
+ nextNode = existingNode;
469
+ } else {
470
+ const next = createDynamicNode(
471
+ SEGMENT_TYPE_OPTIONAL_PARAM,
472
+ route.fullPath ?? route.from,
473
+ actuallyCaseSensitive,
474
+ prefix,
475
+ suffix
476
+ );
477
+ nextNode = next;
478
+ next.parent = node;
479
+ next.depth = depth;
480
+ node.optional ??= [];
481
+ node.optional.push(next);
482
+ }
483
+ break;
484
+ }
485
+ case SEGMENT_TYPE_WILDCARD: {
486
+ const prefix_raw = path.substring(start2, segment[1]);
487
+ const suffix_raw = path.substring(segment[4], end);
488
+ const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
489
+ const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
490
+ const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
491
+ const next = createDynamicNode(
492
+ SEGMENT_TYPE_WILDCARD,
493
+ route.fullPath ?? route.from,
494
+ actuallyCaseSensitive,
495
+ prefix,
496
+ suffix
497
+ );
498
+ nextNode = next;
499
+ next.parent = node;
500
+ next.depth = depth;
501
+ node.wildcard ??= [];
502
+ node.wildcard.push(next);
503
+ }
504
+ }
505
+ node = nextNode;
506
+ }
507
+ if (skipOnParamError && route.children && !route.isRoot && route.id && route.id.charCodeAt(route.id.lastIndexOf("/") + 1) === 95) {
508
+ const pathlessNode = createStaticNode(
509
+ route.fullPath ?? route.from
510
+ );
511
+ pathlessNode.kind = SEGMENT_TYPE_PATHLESS;
512
+ pathlessNode.parent = node;
513
+ depth++;
514
+ pathlessNode.depth = depth;
515
+ node.pathless ??= [];
516
+ node.pathless.push(pathlessNode);
517
+ node = pathlessNode;
518
+ }
519
+ const isLeaf = (route.path || !route.children) && !route.isRoot;
520
+ if (isLeaf && path.endsWith("/")) {
521
+ const indexNode = createStaticNode(
522
+ route.fullPath ?? route.from
523
+ );
524
+ indexNode.kind = SEGMENT_TYPE_INDEX;
525
+ indexNode.parent = node;
526
+ depth++;
527
+ indexNode.depth = depth;
528
+ node.index = indexNode;
529
+ node = indexNode;
530
+ }
531
+ node.parse = route.options?.params?.parse ?? null;
532
+ node.skipOnParamError = skipOnParamError;
533
+ node.parsingPriority = route.options?.skipRouteOnParseError?.priority ?? 0;
534
+ if (isLeaf && !node.route) {
535
+ node.route = route;
536
+ node.fullPath = route.fullPath ?? route.from;
537
+ }
538
+ }
539
+ if (route.children)
540
+ for (const child of route.children) {
541
+ parseSegments(
542
+ defaultCaseSensitive,
543
+ data,
544
+ child,
545
+ cursor,
546
+ node,
547
+ depth,
548
+ onRoute
549
+ );
550
+ }
551
+ }
552
+ function sortDynamic(a, b) {
553
+ if (a.skipOnParamError && !b.skipOnParamError) return -1;
554
+ if (!a.skipOnParamError && b.skipOnParamError) return 1;
555
+ if (a.skipOnParamError && b.skipOnParamError && (a.parsingPriority || b.parsingPriority))
556
+ return b.parsingPriority - a.parsingPriority;
557
+ if (a.prefix && b.prefix && a.prefix !== b.prefix) {
558
+ if (a.prefix.startsWith(b.prefix)) return -1;
559
+ if (b.prefix.startsWith(a.prefix)) return 1;
560
+ }
561
+ if (a.suffix && b.suffix && a.suffix !== b.suffix) {
562
+ if (a.suffix.endsWith(b.suffix)) return -1;
563
+ if (b.suffix.endsWith(a.suffix)) return 1;
564
+ }
565
+ if (a.prefix && !b.prefix) return -1;
566
+ if (!a.prefix && b.prefix) return 1;
567
+ if (a.suffix && !b.suffix) return -1;
568
+ if (!a.suffix && b.suffix) return 1;
569
+ if (a.caseSensitive && !b.caseSensitive) return -1;
570
+ if (!a.caseSensitive && b.caseSensitive) return 1;
571
+ return 0;
572
+ }
573
+ function sortTreeNodes(node) {
574
+ if (node.pathless) {
575
+ for (const child of node.pathless) {
576
+ sortTreeNodes(child);
577
+ }
578
+ }
579
+ if (node.static) {
580
+ for (const child of node.static.values()) {
581
+ sortTreeNodes(child);
582
+ }
583
+ }
584
+ if (node.staticInsensitive) {
585
+ for (const child of node.staticInsensitive.values()) {
586
+ sortTreeNodes(child);
587
+ }
588
+ }
589
+ if (node.dynamic?.length) {
590
+ node.dynamic.sort(sortDynamic);
591
+ for (const child of node.dynamic) {
592
+ sortTreeNodes(child);
593
+ }
594
+ }
595
+ if (node.optional?.length) {
596
+ node.optional.sort(sortDynamic);
597
+ for (const child of node.optional) {
598
+ sortTreeNodes(child);
599
+ }
600
+ }
601
+ if (node.wildcard?.length) {
602
+ node.wildcard.sort(sortDynamic);
603
+ for (const child of node.wildcard) {
604
+ sortTreeNodes(child);
605
+ }
606
+ }
607
+ }
608
+ function createStaticNode(fullPath) {
609
+ return {
610
+ kind: SEGMENT_TYPE_PATHNAME,
611
+ depth: 0,
612
+ pathless: null,
613
+ index: null,
614
+ static: null,
615
+ staticInsensitive: null,
616
+ dynamic: null,
617
+ optional: null,
618
+ wildcard: null,
619
+ route: null,
620
+ fullPath,
621
+ parent: null,
622
+ parse: null,
623
+ skipOnParamError: false,
624
+ parsingPriority: 0
625
+ };
626
+ }
627
+ function createDynamicNode(kind, fullPath, caseSensitive, prefix, suffix) {
628
+ return {
629
+ kind,
630
+ depth: 0,
631
+ pathless: null,
632
+ index: null,
633
+ static: null,
634
+ staticInsensitive: null,
635
+ dynamic: null,
636
+ optional: null,
637
+ wildcard: null,
638
+ route: null,
639
+ fullPath,
640
+ parent: null,
641
+ parse: null,
642
+ skipOnParamError: false,
643
+ parsingPriority: 0,
644
+ caseSensitive,
645
+ prefix,
646
+ suffix
647
+ };
648
+ }
649
+ function processRouteMasks(routeList, processedTree) {
650
+ const segmentTree = createStaticNode("/");
651
+ const data = new Uint16Array(6);
652
+ for (const route of routeList) {
653
+ parseSegments(false, data, route, 1, segmentTree, 0);
654
+ }
655
+ sortTreeNodes(segmentTree);
656
+ processedTree.masksTree = segmentTree;
657
+ processedTree.flatCache = createLRUCache(1e3);
658
+ }
659
+ function findFlatMatch(path, processedTree) {
660
+ path ||= "/";
661
+ const cached = processedTree.flatCache.get(path);
662
+ if (cached) return cached;
663
+ const result = findMatch(path, processedTree.masksTree);
664
+ processedTree.flatCache.set(path, result);
665
+ return result;
666
+ }
667
+ function findSingleMatch(from, caseSensitive, fuzzy, path, processedTree) {
668
+ from ||= "/";
669
+ path ||= "/";
670
+ const key = caseSensitive ? `case\0${from}` : from;
671
+ let tree = processedTree.singleCache.get(key);
672
+ if (!tree) {
673
+ tree = createStaticNode("/");
674
+ const data = new Uint16Array(6);
675
+ parseSegments(caseSensitive, data, { from }, 1, tree, 0);
676
+ processedTree.singleCache.set(key, tree);
677
+ }
678
+ return findMatch(path, tree, fuzzy);
679
+ }
680
+ function findRouteMatch(path, processedTree, fuzzy = false) {
681
+ const key = fuzzy ? path : `nofuzz\0${path}`;
682
+ const cached = processedTree.matchCache.get(key);
683
+ if (cached !== void 0) return cached;
684
+ path ||= "/";
685
+ let result;
686
+ try {
687
+ result = findMatch(
688
+ path,
689
+ processedTree.segmentTree,
690
+ fuzzy
691
+ );
692
+ } catch (err) {
693
+ if (err instanceof URIError) {
694
+ result = null;
695
+ } else {
696
+ throw err;
697
+ }
698
+ }
699
+ if (result) result.branch = buildRouteBranch(result.route);
700
+ processedTree.matchCache.set(key, result);
701
+ return result;
702
+ }
703
+ function trimPathRight$1(path) {
704
+ return path === "/" ? path : path.replace(/\/{1,}$/, "");
705
+ }
706
+ function processRouteTree(routeTree, caseSensitive = false, initRoute) {
707
+ const segmentTree = createStaticNode(routeTree.fullPath);
708
+ const data = new Uint16Array(6);
709
+ const routesById = {};
710
+ const routesByPath = {};
711
+ let index = 0;
712
+ parseSegments(caseSensitive, data, routeTree, 1, segmentTree, 0, (route) => {
713
+ initRoute?.(route, index);
714
+ invariant(
715
+ !(route.id in routesById),
716
+ `Duplicate routes found with id: ${String(route.id)}`
717
+ );
718
+ routesById[route.id] = route;
719
+ if (index !== 0 && route.path) {
720
+ const trimmedFullPath = trimPathRight$1(route.fullPath);
721
+ if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith("/")) {
722
+ routesByPath[trimmedFullPath] = route;
723
+ }
724
+ }
725
+ index++;
726
+ });
727
+ sortTreeNodes(segmentTree);
728
+ const processedTree = {
729
+ segmentTree,
730
+ singleCache: createLRUCache(1e3),
731
+ matchCache: createLRUCache(1e3),
732
+ flatCache: null,
733
+ masksTree: null
734
+ };
735
+ return {
736
+ processedTree,
737
+ routesById,
738
+ routesByPath
739
+ };
740
+ }
741
+ function findMatch(path, segmentTree, fuzzy = false) {
742
+ const parts = path.split("/");
743
+ const leaf = getNodeMatch(path, parts, segmentTree, fuzzy);
744
+ if (!leaf) return null;
745
+ const [rawParams] = extractParams(path, parts, leaf);
746
+ return {
747
+ route: leaf.node.route,
748
+ rawParams,
749
+ parsedParams: leaf.parsedParams
750
+ };
751
+ }
752
+ function extractParams(path, parts, leaf) {
753
+ const list = buildBranch(leaf.node);
754
+ let nodeParts = null;
755
+ const rawParams = {};
756
+ let partIndex = leaf.extract?.part ?? 0;
757
+ let nodeIndex = leaf.extract?.node ?? 0;
758
+ let pathIndex = leaf.extract?.path ?? 0;
759
+ let segmentCount = leaf.extract?.segment ?? 0;
760
+ for (; nodeIndex < list.length; partIndex++, nodeIndex++, pathIndex++, segmentCount++) {
761
+ const node = list[nodeIndex];
762
+ if (node.kind === SEGMENT_TYPE_INDEX) break;
763
+ if (node.kind === SEGMENT_TYPE_PATHLESS) {
764
+ segmentCount--;
765
+ partIndex--;
766
+ pathIndex--;
767
+ continue;
768
+ }
769
+ const part = parts[partIndex];
770
+ const currentPathIndex = pathIndex;
771
+ if (part) pathIndex += part.length;
772
+ if (node.kind === SEGMENT_TYPE_PARAM) {
773
+ nodeParts ??= leaf.node.fullPath.split("/");
774
+ const nodePart = nodeParts[segmentCount];
775
+ const preLength = node.prefix?.length ?? 0;
776
+ const isCurlyBraced = nodePart.charCodeAt(preLength) === 123;
777
+ if (isCurlyBraced) {
778
+ const sufLength = node.suffix?.length ?? 0;
779
+ const name = nodePart.substring(
780
+ preLength + 2,
781
+ nodePart.length - sufLength - 1
782
+ );
783
+ const value = part.substring(preLength, part.length - sufLength);
784
+ rawParams[name] = decodeURIComponent(value);
785
+ } else {
786
+ const name = nodePart.substring(1);
787
+ rawParams[name] = decodeURIComponent(part);
788
+ }
789
+ } else if (node.kind === SEGMENT_TYPE_OPTIONAL_PARAM) {
790
+ if (leaf.skipped & 1 << nodeIndex) {
791
+ partIndex--;
792
+ pathIndex = currentPathIndex - 1;
793
+ continue;
794
+ }
795
+ nodeParts ??= leaf.node.fullPath.split("/");
796
+ const nodePart = nodeParts[segmentCount];
797
+ const preLength = node.prefix?.length ?? 0;
798
+ const sufLength = node.suffix?.length ?? 0;
799
+ const name = nodePart.substring(
800
+ preLength + 3,
801
+ nodePart.length - sufLength - 1
802
+ );
803
+ const value = node.suffix || node.prefix ? part.substring(preLength, part.length - sufLength) : part;
804
+ if (value) rawParams[name] = decodeURIComponent(value);
805
+ } else if (node.kind === SEGMENT_TYPE_WILDCARD) {
806
+ const n = node;
807
+ const value = path.substring(
808
+ currentPathIndex + (n.prefix?.length ?? 0),
809
+ path.length - (n.suffix?.length ?? 0)
810
+ );
811
+ const splat = decodeURIComponent(value);
812
+ rawParams["*"] = splat;
813
+ rawParams._splat = splat;
814
+ break;
815
+ }
816
+ }
817
+ if (leaf.rawParams) Object.assign(rawParams, leaf.rawParams);
818
+ return [
819
+ rawParams,
820
+ {
821
+ part: partIndex,
822
+ node: nodeIndex,
823
+ path: pathIndex,
824
+ segment: segmentCount
825
+ }
826
+ ];
827
+ }
828
+ function buildRouteBranch(route) {
829
+ const list = [route];
830
+ while (route.parentRoute) {
831
+ route = route.parentRoute;
832
+ list.push(route);
833
+ }
834
+ list.reverse();
835
+ return list;
836
+ }
837
+ function buildBranch(node) {
838
+ const list = Array(node.depth + 1);
839
+ do {
840
+ list[node.depth] = node;
841
+ node = node.parent;
842
+ } while (node);
843
+ return list;
844
+ }
845
+ function getNodeMatch(path, parts, segmentTree, fuzzy) {
846
+ if (path === "/" && segmentTree.index)
847
+ return { node: segmentTree.index, skipped: 0 };
848
+ const trailingSlash = !last(parts);
849
+ const pathIsIndex = trailingSlash && path !== "/";
850
+ const partsLength = parts.length - (trailingSlash ? 1 : 0);
851
+ const stack = [
852
+ {
853
+ node: segmentTree,
854
+ index: 1,
855
+ skipped: 0,
856
+ depth: 1,
857
+ statics: 1,
858
+ dynamics: 0,
859
+ optionals: 0
860
+ }
861
+ ];
862
+ let wildcardMatch = null;
863
+ let bestFuzzy = null;
864
+ let bestMatch = null;
865
+ while (stack.length) {
866
+ const frame = stack.pop();
867
+ const { node, index, skipped, depth, statics, dynamics, optionals } = frame;
868
+ let { extract, rawParams, parsedParams } = frame;
869
+ if (node.skipOnParamError) {
870
+ const result = validateMatchParams(path, parts, frame);
871
+ if (!result) continue;
872
+ rawParams = frame.rawParams;
873
+ extract = frame.extract;
874
+ parsedParams = frame.parsedParams;
875
+ }
876
+ if (fuzzy && node.route && node.kind !== SEGMENT_TYPE_INDEX && isFrameMoreSpecific(bestFuzzy, frame)) {
877
+ bestFuzzy = frame;
878
+ }
879
+ const isBeyondPath = index === partsLength;
880
+ if (isBeyondPath) {
881
+ if (node.route && !pathIsIndex && isFrameMoreSpecific(bestMatch, frame)) {
882
+ bestMatch = frame;
883
+ }
884
+ if (!node.optional && !node.wildcard && !node.index && !node.pathless)
885
+ continue;
886
+ }
887
+ const part = isBeyondPath ? void 0 : parts[index];
888
+ let lowerPart;
889
+ if (isBeyondPath && node.index) {
890
+ const indexFrame = {
891
+ node: node.index,
892
+ index,
893
+ skipped,
894
+ depth: depth + 1,
895
+ statics,
896
+ dynamics,
897
+ optionals,
898
+ extract,
899
+ rawParams,
900
+ parsedParams
901
+ };
902
+ let indexValid = true;
903
+ if (node.index.skipOnParamError) {
904
+ const result = validateMatchParams(path, parts, indexFrame);
905
+ if (!result) indexValid = false;
906
+ }
907
+ if (indexValid) {
908
+ if (statics === partsLength && !dynamics && !optionals && !skipped) {
909
+ return indexFrame;
910
+ }
911
+ if (isFrameMoreSpecific(bestMatch, indexFrame)) {
912
+ bestMatch = indexFrame;
913
+ }
914
+ }
915
+ }
916
+ if (node.wildcard && isFrameMoreSpecific(wildcardMatch, frame)) {
917
+ for (const segment of node.wildcard) {
918
+ const { prefix, suffix } = segment;
919
+ if (prefix) {
920
+ if (isBeyondPath) continue;
921
+ const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
922
+ if (!casePart.startsWith(prefix)) continue;
923
+ }
924
+ if (suffix) {
925
+ if (isBeyondPath) continue;
926
+ const end = parts.slice(index).join("/").slice(-suffix.length);
927
+ const casePart = segment.caseSensitive ? end : end.toLowerCase();
928
+ if (casePart !== suffix) continue;
929
+ }
930
+ const frame2 = {
931
+ node: segment,
932
+ index: partsLength,
933
+ skipped,
934
+ depth,
935
+ statics,
936
+ dynamics,
937
+ optionals,
938
+ extract,
939
+ rawParams,
940
+ parsedParams
941
+ };
942
+ if (segment.skipOnParamError) {
943
+ const result = validateMatchParams(path, parts, frame2);
944
+ if (!result) continue;
945
+ }
946
+ wildcardMatch = frame2;
947
+ break;
948
+ }
949
+ }
950
+ if (node.optional) {
951
+ const nextSkipped = skipped | 1 << depth;
952
+ const nextDepth = depth + 1;
953
+ for (let i = node.optional.length - 1; i >= 0; i--) {
954
+ const segment = node.optional[i];
955
+ stack.push({
956
+ node: segment,
957
+ index,
958
+ skipped: nextSkipped,
959
+ depth: nextDepth,
960
+ statics,
961
+ dynamics,
962
+ optionals,
963
+ extract,
964
+ rawParams,
965
+ parsedParams
966
+ });
967
+ }
968
+ if (!isBeyondPath) {
969
+ for (let i = node.optional.length - 1; i >= 0; i--) {
970
+ const segment = node.optional[i];
971
+ const { prefix, suffix } = segment;
972
+ if (prefix || suffix) {
973
+ const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
974
+ if (prefix && !casePart.startsWith(prefix)) continue;
975
+ if (suffix && !casePart.endsWith(suffix)) continue;
976
+ }
977
+ stack.push({
978
+ node: segment,
979
+ index: index + 1,
980
+ skipped,
981
+ depth: nextDepth,
982
+ statics,
983
+ dynamics,
984
+ optionals: optionals + 1,
985
+ extract,
986
+ rawParams,
987
+ parsedParams
988
+ });
989
+ }
990
+ }
991
+ }
992
+ if (!isBeyondPath && node.dynamic && part) {
993
+ for (let i = node.dynamic.length - 1; i >= 0; i--) {
994
+ const segment = node.dynamic[i];
995
+ const { prefix, suffix } = segment;
996
+ if (prefix || suffix) {
997
+ const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
998
+ if (prefix && !casePart.startsWith(prefix)) continue;
999
+ if (suffix && !casePart.endsWith(suffix)) continue;
1000
+ }
1001
+ stack.push({
1002
+ node: segment,
1003
+ index: index + 1,
1004
+ skipped,
1005
+ depth: depth + 1,
1006
+ statics,
1007
+ dynamics: dynamics + 1,
1008
+ optionals,
1009
+ extract,
1010
+ rawParams,
1011
+ parsedParams
1012
+ });
1013
+ }
1014
+ }
1015
+ if (!isBeyondPath && node.staticInsensitive) {
1016
+ const match = node.staticInsensitive.get(
1017
+ lowerPart ??= part.toLowerCase()
1018
+ );
1019
+ if (match) {
1020
+ stack.push({
1021
+ node: match,
1022
+ index: index + 1,
1023
+ skipped,
1024
+ depth: depth + 1,
1025
+ statics: statics + 1,
1026
+ dynamics,
1027
+ optionals,
1028
+ extract,
1029
+ rawParams,
1030
+ parsedParams
1031
+ });
1032
+ }
1033
+ }
1034
+ if (!isBeyondPath && node.static) {
1035
+ const match = node.static.get(part);
1036
+ if (match) {
1037
+ stack.push({
1038
+ node: match,
1039
+ index: index + 1,
1040
+ skipped,
1041
+ depth: depth + 1,
1042
+ statics: statics + 1,
1043
+ dynamics,
1044
+ optionals,
1045
+ extract,
1046
+ rawParams,
1047
+ parsedParams
1048
+ });
1049
+ }
1050
+ }
1051
+ if (node.pathless) {
1052
+ const nextDepth = depth + 1;
1053
+ for (let i = node.pathless.length - 1; i >= 0; i--) {
1054
+ const segment = node.pathless[i];
1055
+ stack.push({
1056
+ node: segment,
1057
+ index,
1058
+ skipped,
1059
+ depth: nextDepth,
1060
+ statics,
1061
+ dynamics,
1062
+ optionals,
1063
+ extract,
1064
+ rawParams,
1065
+ parsedParams
1066
+ });
1067
+ }
1068
+ }
1069
+ }
1070
+ if (bestMatch && wildcardMatch) {
1071
+ return isFrameMoreSpecific(wildcardMatch, bestMatch) ? bestMatch : wildcardMatch;
1072
+ }
1073
+ if (bestMatch) return bestMatch;
1074
+ if (wildcardMatch) return wildcardMatch;
1075
+ if (fuzzy && bestFuzzy) {
1076
+ let sliceIndex = bestFuzzy.index;
1077
+ for (let i = 0; i < bestFuzzy.index; i++) {
1078
+ sliceIndex += parts[i].length;
1079
+ }
1080
+ const splat = sliceIndex === path.length ? "/" : path.slice(sliceIndex);
1081
+ bestFuzzy.rawParams ??= {};
1082
+ bestFuzzy.rawParams["**"] = decodeURIComponent(splat);
1083
+ return bestFuzzy;
1084
+ }
1085
+ return null;
1086
+ }
1087
+ function validateMatchParams(path, parts, frame) {
1088
+ try {
1089
+ const [rawParams, state] = extractParams(path, parts, frame);
1090
+ frame.rawParams = rawParams;
1091
+ frame.extract = state;
1092
+ const parsed = frame.node.parse(rawParams);
1093
+ frame.parsedParams = Object.assign({}, frame.parsedParams, parsed);
1094
+ return true;
1095
+ } catch {
1096
+ return null;
1097
+ }
1098
+ }
1099
+ function isFrameMoreSpecific(prev, next) {
1100
+ if (!prev) return true;
1101
+ return next.statics > prev.statics || next.statics === prev.statics && (next.dynamics > prev.dynamics || next.dynamics === prev.dynamics && (next.optionals > prev.optionals || next.optionals === prev.optionals && ((next.node.kind === SEGMENT_TYPE_INDEX) > (prev.node.kind === SEGMENT_TYPE_INDEX) || next.node.kind === SEGMENT_TYPE_INDEX === (prev.node.kind === SEGMENT_TYPE_INDEX) && next.depth > prev.depth)));
1102
+ }
1103
+ function joinPaths(paths) {
1104
+ return cleanPath(
1105
+ paths.filter((val) => {
1106
+ return val !== void 0;
1107
+ }).join("/")
1108
+ );
1109
+ }
1110
+ function cleanPath(path) {
1111
+ return path.replace(/\/{2,}/g, "/");
1112
+ }
1113
+ function trimPathLeft(path) {
1114
+ return path === "/" ? path : path.replace(/^\/{1,}/, "");
1115
+ }
1116
+ function trimPathRight(path) {
1117
+ const len = path.length;
1118
+ return len > 1 && path[len - 1] === "/" ? path.replace(/\/{1,}$/, "") : path;
1119
+ }
1120
+ function trimPath(path) {
1121
+ return trimPathRight(trimPathLeft(path));
1122
+ }
1123
+ function removeTrailingSlash(value, basepath) {
1124
+ if (value?.endsWith("/") && value !== "/" && value !== `${basepath}/`) {
1125
+ return value.slice(0, -1);
1126
+ }
1127
+ return value;
1128
+ }
1129
+ function exactPathTest(pathName1, pathName2, basepath) {
1130
+ return removeTrailingSlash(pathName1, basepath) === removeTrailingSlash(pathName2, basepath);
1131
+ }
1132
+ function resolvePath({
1133
+ base,
1134
+ to,
1135
+ trailingSlash = "never",
1136
+ cache
1137
+ }) {
1138
+ const isAbsolute = to.startsWith("/");
1139
+ const isBase = !isAbsolute && to === ".";
1140
+ let key;
1141
+ if (cache) {
1142
+ key = isAbsolute ? to : isBase ? base : base + "\0" + to;
1143
+ const cached = cache.get(key);
1144
+ if (cached) return cached;
1145
+ }
1146
+ let baseSegments;
1147
+ if (isBase) {
1148
+ baseSegments = base.split("/");
1149
+ } else if (isAbsolute) {
1150
+ baseSegments = to.split("/");
1151
+ } else {
1152
+ baseSegments = base.split("/");
1153
+ while (baseSegments.length > 1 && last(baseSegments) === "") {
1154
+ baseSegments.pop();
1155
+ }
1156
+ const toSegments = to.split("/");
1157
+ for (let index = 0, length = toSegments.length; index < length; index++) {
1158
+ const value = toSegments[index];
1159
+ if (value === "") {
1160
+ if (!index) {
1161
+ baseSegments = [value];
1162
+ } else if (index === length - 1) {
1163
+ baseSegments.push(value);
1164
+ } else ;
1165
+ } else if (value === "..") {
1166
+ baseSegments.pop();
1167
+ } else if (value === ".") ;
1168
+ else {
1169
+ baseSegments.push(value);
1170
+ }
1171
+ }
1172
+ }
1173
+ if (baseSegments.length > 1) {
1174
+ if (last(baseSegments) === "") {
1175
+ if (trailingSlash === "never") {
1176
+ baseSegments.pop();
1177
+ }
1178
+ } else if (trailingSlash === "always") {
1179
+ baseSegments.push("");
1180
+ }
1181
+ }
1182
+ let segment;
1183
+ let joined = "";
1184
+ for (let i = 0; i < baseSegments.length; i++) {
1185
+ if (i > 0) joined += "/";
1186
+ const part = baseSegments[i];
1187
+ if (!part) continue;
1188
+ segment = parseSegment(part, 0, segment);
1189
+ const kind = segment[0];
1190
+ if (kind === SEGMENT_TYPE_PATHNAME) {
1191
+ joined += part;
1192
+ continue;
1193
+ }
1194
+ const end = segment[5];
1195
+ const prefix = part.substring(0, segment[1]);
1196
+ const suffix = part.substring(segment[4], end);
1197
+ const value = part.substring(segment[2], segment[3]);
1198
+ if (kind === SEGMENT_TYPE_PARAM) {
1199
+ joined += prefix || suffix ? `${prefix}{$${value}}${suffix}` : `$${value}`;
1200
+ } else if (kind === SEGMENT_TYPE_WILDCARD) {
1201
+ joined += prefix || suffix ? `${prefix}{$}${suffix}` : "$";
1202
+ } else {
1203
+ joined += `${prefix}{-$${value}}${suffix}`;
1204
+ }
1205
+ }
1206
+ joined = cleanPath(joined);
1207
+ const result = joined || "/";
1208
+ if (key && cache) cache.set(key, result);
1209
+ return result;
1210
+ }
1211
+ function compileDecodeCharMap(pathParamsAllowedCharacters) {
1212
+ const charMap = new Map(
1213
+ pathParamsAllowedCharacters.map((char) => [encodeURIComponent(char), char])
1214
+ );
1215
+ const pattern = Array.from(charMap.keys()).map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
1216
+ const regex = new RegExp(pattern, "g");
1217
+ return (encoded) => encoded.replace(regex, (match) => charMap.get(match) ?? match);
1218
+ }
1219
+ function encodeParam(key, params, decoder) {
1220
+ const value = params[key];
1221
+ if (typeof value !== "string") return value;
1222
+ if (key === "_splat") {
1223
+ if (/^[a-zA-Z0-9\-._~!/]*$/.test(value)) return value;
1224
+ return value.split("/").map((segment) => encodePathParam(segment, decoder)).join("/");
1225
+ } else {
1226
+ return encodePathParam(value, decoder);
1227
+ }
1228
+ }
1229
+ function interpolatePath({
1230
+ path,
1231
+ params,
1232
+ decoder,
1233
+ // `server` is marked @internal and stripped from .d.ts by `stripInternal`.
1234
+ // We avoid destructuring it in the function signature so the emitted
1235
+ // declaration doesn't reference a property that no longer exists.
1236
+ ...rest
1237
+ }) {
1238
+ let isMissingParams = false;
1239
+ const usedParams = {};
1240
+ if (!path || path === "/")
1241
+ return { interpolatedPath: "/", usedParams, isMissingParams };
1242
+ if (!path.includes("$"))
1243
+ return { interpolatedPath: path, usedParams, isMissingParams };
1244
+ {
1245
+ if (path.indexOf("{") === -1) {
1246
+ const length2 = path.length;
1247
+ let cursor2 = 0;
1248
+ let joined2 = "";
1249
+ while (cursor2 < length2) {
1250
+ while (cursor2 < length2 && path.charCodeAt(cursor2) === 47) cursor2++;
1251
+ if (cursor2 >= length2) break;
1252
+ const start = cursor2;
1253
+ let end = path.indexOf("/", cursor2);
1254
+ if (end === -1) end = length2;
1255
+ cursor2 = end;
1256
+ const part = path.substring(start, end);
1257
+ if (!part) continue;
1258
+ if (part.charCodeAt(0) === 36) {
1259
+ if (part.length === 1) {
1260
+ const splat = params._splat;
1261
+ usedParams._splat = splat;
1262
+ usedParams["*"] = splat;
1263
+ if (!splat) {
1264
+ isMissingParams = true;
1265
+ continue;
1266
+ }
1267
+ const value = encodeParam("_splat", params, decoder);
1268
+ joined2 += "/" + value;
1269
+ } else {
1270
+ const key = part.substring(1);
1271
+ if (!isMissingParams && !(key in params)) {
1272
+ isMissingParams = true;
1273
+ }
1274
+ usedParams[key] = params[key];
1275
+ const value = encodeParam(key, params, decoder) ?? "undefined";
1276
+ joined2 += "/" + value;
1277
+ }
1278
+ } else {
1279
+ joined2 += "/" + part;
1280
+ }
1281
+ }
1282
+ if (path.endsWith("/")) joined2 += "/";
1283
+ const interpolatedPath2 = joined2 || "/";
1284
+ return { usedParams, interpolatedPath: interpolatedPath2, isMissingParams };
1285
+ }
1286
+ }
1287
+ const length = path.length;
1288
+ let cursor = 0;
1289
+ let segment;
1290
+ let joined = "";
1291
+ while (cursor < length) {
1292
+ const start = cursor;
1293
+ segment = parseSegment(path, start, segment);
1294
+ const end = segment[5];
1295
+ cursor = end + 1;
1296
+ if (start === end) continue;
1297
+ const kind = segment[0];
1298
+ if (kind === SEGMENT_TYPE_PATHNAME) {
1299
+ joined += "/" + path.substring(start, end);
1300
+ continue;
1301
+ }
1302
+ if (kind === SEGMENT_TYPE_WILDCARD) {
1303
+ const splat = params._splat;
1304
+ usedParams._splat = splat;
1305
+ usedParams["*"] = splat;
1306
+ const prefix = path.substring(start, segment[1]);
1307
+ const suffix = path.substring(segment[4], end);
1308
+ if (!splat) {
1309
+ isMissingParams = true;
1310
+ if (prefix || suffix) {
1311
+ joined += "/" + prefix + suffix;
1312
+ }
1313
+ continue;
1314
+ }
1315
+ const value = encodeParam("_splat", params, decoder);
1316
+ joined += "/" + prefix + value + suffix;
1317
+ continue;
1318
+ }
1319
+ if (kind === SEGMENT_TYPE_PARAM) {
1320
+ const key = path.substring(segment[2], segment[3]);
1321
+ if (!isMissingParams && !(key in params)) {
1322
+ isMissingParams = true;
1323
+ }
1324
+ usedParams[key] = params[key];
1325
+ const prefix = path.substring(start, segment[1]);
1326
+ const suffix = path.substring(segment[4], end);
1327
+ const value = encodeParam(key, params, decoder) ?? "undefined";
1328
+ joined += "/" + prefix + value + suffix;
1329
+ continue;
1330
+ }
1331
+ if (kind === SEGMENT_TYPE_OPTIONAL_PARAM) {
1332
+ const key = path.substring(segment[2], segment[3]);
1333
+ const valueRaw = params[key];
1334
+ if (valueRaw == null) continue;
1335
+ usedParams[key] = valueRaw;
1336
+ const prefix = path.substring(start, segment[1]);
1337
+ const suffix = path.substring(segment[4], end);
1338
+ const value = encodeParam(key, params, decoder) ?? "";
1339
+ joined += "/" + prefix + value + suffix;
1340
+ continue;
1341
+ }
1342
+ }
1343
+ if (path.endsWith("/")) joined += "/";
1344
+ const interpolatedPath = joined || "/";
1345
+ return { usedParams, interpolatedPath, isMissingParams };
1346
+ }
1347
+ function encodePathParam(value, decoder) {
1348
+ const encoded = encodeURIComponent(value);
1349
+ return decoder?.(encoded) ?? encoded;
1350
+ }
1351
+ function getSafeSessionStorage() {
1352
+ try {
1353
+ if (typeof window !== "undefined" && typeof window.sessionStorage === "object") {
1354
+ return window.sessionStorage;
1355
+ }
1356
+ } catch {
1357
+ }
1358
+ return void 0;
1359
+ }
1360
+ const storageKey = "tsr-scroll-restoration-v1_3";
1361
+ function createScrollRestorationCache() {
1362
+ const safeSessionStorage = getSafeSessionStorage();
1363
+ if (!safeSessionStorage) {
1364
+ return null;
1365
+ }
1366
+ const persistedState = safeSessionStorage.getItem(storageKey);
1367
+ let state = persistedState ? JSON.parse(persistedState) : {};
1368
+ return {
1369
+ state,
1370
+ // This setter is simply to make sure that we set the sessionStorage right
1371
+ // after the state is updated. It doesn't necessarily need to be a functional
1372
+ // update.
1373
+ set: (updater) => {
1374
+ state = functionalUpdate(updater, state) || state;
1375
+ try {
1376
+ safeSessionStorage.setItem(storageKey, JSON.stringify(state));
1377
+ } catch {
1378
+ console.warn(
1379
+ "[ts-router] Could not persist scroll restoration state to sessionStorage."
1380
+ );
1381
+ }
1382
+ }
1383
+ };
1384
+ }
1385
+ createScrollRestorationCache();
1386
+ const defaultGetScrollRestorationKey = (location) => {
1387
+ return location.state.__TSR_key || location.href;
1388
+ };
1389
+ function restoreScroll({
1390
+ storageKey: storageKey2,
1391
+ key,
1392
+ behavior,
1393
+ shouldScrollRestoration,
1394
+ scrollToTopSelectors,
1395
+ location
1396
+ }) {
1397
+ let byKey;
1398
+ try {
1399
+ byKey = JSON.parse(sessionStorage.getItem(storageKey2) || "{}");
1400
+ } catch (error) {
1401
+ console.error(error);
1402
+ return;
1403
+ }
1404
+ const resolvedKey = key || window.history.state?.__TSR_key;
1405
+ const elementEntries = byKey[resolvedKey];
1406
+ scroll: {
1407
+ if (shouldScrollRestoration && elementEntries && Object.keys(elementEntries).length > 0) {
1408
+ for (const elementSelector in elementEntries) {
1409
+ const entry = elementEntries[elementSelector];
1410
+ if (elementSelector === "window") {
1411
+ window.scrollTo({
1412
+ top: entry.scrollY,
1413
+ left: entry.scrollX,
1414
+ behavior
1415
+ });
1416
+ } else if (elementSelector) {
1417
+ const element = document.querySelector(elementSelector);
1418
+ if (element) {
1419
+ element.scrollLeft = entry.scrollX;
1420
+ element.scrollTop = entry.scrollY;
1421
+ }
1422
+ }
1423
+ }
1424
+ break scroll;
1425
+ }
1426
+ const hash = (location ?? window.location).hash.split("#", 2)[1];
1427
+ if (hash) {
1428
+ const hashScrollIntoViewOptions = window.history.state?.__hashScrollIntoViewOptions ?? true;
1429
+ if (hashScrollIntoViewOptions) {
1430
+ const el = document.getElementById(hash);
1431
+ if (el) {
1432
+ el.scrollIntoView(hashScrollIntoViewOptions);
1433
+ }
1434
+ }
1435
+ break scroll;
1436
+ }
1437
+ const scrollOptions = { top: 0, left: 0, behavior };
1438
+ window.scrollTo(scrollOptions);
1439
+ if (scrollToTopSelectors) {
1440
+ for (const selector of scrollToTopSelectors) {
1441
+ if (selector === "window") continue;
1442
+ const element = typeof selector === "function" ? selector() : document.querySelector(selector);
1443
+ if (element) element.scrollTo(scrollOptions);
1444
+ }
1445
+ }
1446
+ }
1447
+ }
1448
+ function encode(obj, stringify = String) {
1449
+ const result = new URLSearchParams();
1450
+ for (const key in obj) {
1451
+ const val = obj[key];
1452
+ if (val !== void 0) {
1453
+ result.set(key, stringify(val));
1454
+ }
1455
+ }
1456
+ return result.toString();
1457
+ }
1458
+ function toValue(str) {
1459
+ if (!str) return "";
1460
+ if (str === "false") return false;
1461
+ if (str === "true") return true;
1462
+ return +str * 0 === 0 && +str + "" === str ? +str : str;
1463
+ }
1464
+ function decode(str) {
1465
+ const searchParams = new URLSearchParams(str);
1466
+ const result = {};
1467
+ for (const [key, value] of searchParams.entries()) {
1468
+ const previousValue = result[key];
1469
+ if (previousValue == null) {
1470
+ result[key] = toValue(value);
1471
+ } else if (Array.isArray(previousValue)) {
1472
+ previousValue.push(toValue(value));
1473
+ } else {
1474
+ result[key] = [previousValue, toValue(value)];
1475
+ }
1476
+ }
1477
+ return result;
1478
+ }
1479
+ const defaultParseSearch = parseSearchWith(JSON.parse);
1480
+ const defaultStringifySearch = stringifySearchWith(
1481
+ JSON.stringify,
1482
+ JSON.parse
1483
+ );
1484
+ function parseSearchWith(parser) {
1485
+ return (searchStr) => {
1486
+ if (searchStr[0] === "?") {
1487
+ searchStr = searchStr.substring(1);
1488
+ }
1489
+ const query = decode(searchStr);
1490
+ for (const key in query) {
1491
+ const value = query[key];
1492
+ if (typeof value === "string") {
1493
+ try {
1494
+ query[key] = parser(value);
1495
+ } catch (_err) {
1496
+ }
1497
+ }
1498
+ }
1499
+ return query;
1500
+ };
1501
+ }
1502
+ function stringifySearchWith(stringify, parser) {
1503
+ const hasParser = typeof parser === "function";
1504
+ function stringifyValue(val) {
1505
+ if (typeof val === "object" && val !== null) {
1506
+ try {
1507
+ return stringify(val);
1508
+ } catch (_err) {
1509
+ }
1510
+ } else if (hasParser && typeof val === "string") {
1511
+ try {
1512
+ parser(val);
1513
+ return stringify(val);
1514
+ } catch (_err) {
1515
+ }
1516
+ }
1517
+ return val;
1518
+ }
1519
+ return (search) => {
1520
+ const searchStr = encode(search, stringifyValue);
1521
+ return searchStr ? `?${searchStr}` : "";
1522
+ };
1523
+ }
1524
+ const rootRouteId = "__root__";
1525
+ function redirect(opts) {
1526
+ opts.statusCode = opts.statusCode || opts.code || 307;
1527
+ if (!opts._builtLocation && !opts.reloadDocument && typeof opts.href === "string") {
1528
+ try {
1529
+ new URL(opts.href);
1530
+ opts.reloadDocument = true;
1531
+ } catch {
1532
+ }
1533
+ }
1534
+ const headers = new Headers(opts.headers);
1535
+ if (opts.href && headers.get("Location") === null) {
1536
+ headers.set("Location", opts.href);
1537
+ }
1538
+ const response = new Response(null, {
1539
+ status: opts.statusCode,
1540
+ headers
1541
+ });
1542
+ response.options = opts;
1543
+ if (opts.throw) {
1544
+ throw response;
1545
+ }
1546
+ return response;
1547
+ }
1548
+ function isRedirect(obj) {
1549
+ return obj instanceof Response && !!obj.options;
1550
+ }
1551
+ function isResolvedRedirect(obj) {
1552
+ return isRedirect(obj) && !!obj.options.href;
1553
+ }
1554
+ const triggerOnReady = (inner) => {
1555
+ if (!inner.rendered) {
1556
+ inner.rendered = true;
1557
+ return inner.onReady?.();
1558
+ }
1559
+ };
1560
+ const resolvePreload = (inner, matchId) => {
1561
+ return !!(inner.preload && !inner.router.state.matches.some((d) => d.id === matchId));
1562
+ };
1563
+ const buildMatchContext = (inner, index, includeCurrentMatch = true) => {
1564
+ const context = {
1565
+ ...inner.router.options.context ?? {}
1566
+ };
1567
+ const end = includeCurrentMatch ? index : index - 1;
1568
+ for (let i = 0; i <= end; i++) {
1569
+ const innerMatch = inner.matches[i];
1570
+ if (!innerMatch) continue;
1571
+ const m = inner.router.getMatch(innerMatch.id);
1572
+ if (!m) continue;
1573
+ Object.assign(context, m.__routeContext, m.__beforeLoadContext);
1574
+ }
1575
+ return context;
1576
+ };
1577
+ const _handleNotFound = (inner, err, routerCode) => {
1578
+ const routeCursor = inner.router.routesById[err.routeId ?? ""] ?? inner.router.routeTree;
1579
+ if (!routeCursor.options.notFoundComponent && inner.router.options?.defaultNotFoundComponent) {
1580
+ routeCursor.options.notFoundComponent = inner.router.options.defaultNotFoundComponent;
1581
+ }
1582
+ const willWalkUp = routerCode === "BEFORE_LOAD" && routeCursor.parentRoute;
1583
+ if (!willWalkUp) {
1584
+ invariant(
1585
+ routeCursor.options.notFoundComponent
1586
+ );
1587
+ }
1588
+ const matchForRoute = inner.matches.find((m) => m.routeId === routeCursor.id);
1589
+ invariant(matchForRoute, "Could not find match for route: " + routeCursor.id);
1590
+ inner.updateMatch(matchForRoute.id, (prev) => ({
1591
+ ...prev,
1592
+ status: "notFound",
1593
+ error: err,
1594
+ isFetching: false
1595
+ }));
1596
+ if (willWalkUp) {
1597
+ err.routeId = routeCursor.parentRoute.id;
1598
+ _handleNotFound(inner, err, routerCode);
1599
+ }
1600
+ };
1601
+ const handleRedirectAndNotFound = (inner, match, err, routerCode) => {
1602
+ if (!isRedirect(err) && !isNotFound(err)) return;
1603
+ if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) {
1604
+ throw err;
1605
+ }
1606
+ if (match) {
1607
+ match._nonReactive.beforeLoadPromise?.resolve();
1608
+ match._nonReactive.loaderPromise?.resolve();
1609
+ match._nonReactive.beforeLoadPromise = void 0;
1610
+ match._nonReactive.loaderPromise = void 0;
1611
+ const status = isRedirect(err) ? "redirected" : "notFound";
1612
+ match._nonReactive.error = err;
1613
+ inner.updateMatch(match.id, (prev) => ({
1614
+ ...prev,
1615
+ status,
1616
+ context: buildMatchContext(inner, match.index),
1617
+ isFetching: false,
1618
+ error: err
1619
+ }));
1620
+ if (isNotFound(err) && !err.routeId) {
1621
+ err.routeId = match.routeId;
1622
+ }
1623
+ match._nonReactive.loadPromise?.resolve();
1624
+ }
1625
+ if (isRedirect(err)) {
1626
+ inner.rendered = true;
1627
+ err.options._fromLocation = inner.location;
1628
+ err.redirectHandled = true;
1629
+ err = inner.router.resolveRedirect(err);
1630
+ throw err;
1631
+ } else {
1632
+ _handleNotFound(inner, err, routerCode);
1633
+ throw err;
1634
+ }
1635
+ };
1636
+ const shouldSkipLoader = (inner, matchId) => {
1637
+ const match = inner.router.getMatch(matchId);
1638
+ if (match.ssr === false) {
1639
+ return true;
1640
+ }
1641
+ return false;
1642
+ };
1643
+ const handleSerialError = (inner, index, err, routerCode) => {
1644
+ const { id: matchId, routeId } = inner.matches[index];
1645
+ const route = inner.router.looseRoutesById[routeId];
1646
+ if (err instanceof Promise) {
1647
+ throw err;
1648
+ }
1649
+ err.routerCode = routerCode;
1650
+ inner.firstBadMatchIndex ??= index;
1651
+ handleRedirectAndNotFound(
1652
+ inner,
1653
+ inner.router.getMatch(matchId),
1654
+ err,
1655
+ routerCode
1656
+ );
1657
+ try {
1658
+ route.options.onError?.(err);
1659
+ } catch (errorHandlerErr) {
1660
+ err = errorHandlerErr;
1661
+ handleRedirectAndNotFound(
1662
+ inner,
1663
+ inner.router.getMatch(matchId),
1664
+ err,
1665
+ routerCode
1666
+ );
1667
+ }
1668
+ inner.updateMatch(matchId, (prev) => {
1669
+ prev._nonReactive.beforeLoadPromise?.resolve();
1670
+ prev._nonReactive.beforeLoadPromise = void 0;
1671
+ prev._nonReactive.loadPromise?.resolve();
1672
+ return {
1673
+ ...prev,
1674
+ error: err,
1675
+ status: "error",
1676
+ isFetching: false,
1677
+ updatedAt: Date.now(),
1678
+ abortController: new AbortController()
1679
+ };
1680
+ });
1681
+ };
1682
+ const isBeforeLoadSsr = (inner, matchId, index, route) => {
1683
+ const existingMatch = inner.router.getMatch(matchId);
1684
+ const parentMatchId = inner.matches[index - 1]?.id;
1685
+ const parentMatch = parentMatchId ? inner.router.getMatch(parentMatchId) : void 0;
1686
+ if (inner.router.isShell()) {
1687
+ existingMatch.ssr = route.id === rootRouteId;
1688
+ return;
1689
+ }
1690
+ if (parentMatch?.ssr === false) {
1691
+ existingMatch.ssr = false;
1692
+ return;
1693
+ }
1694
+ const parentOverride = (tempSsr2) => {
1695
+ if (tempSsr2 === true && parentMatch?.ssr === "data-only") {
1696
+ return "data-only";
1697
+ }
1698
+ return tempSsr2;
1699
+ };
1700
+ const defaultSsr = inner.router.options.defaultSsr ?? true;
1701
+ if (route.options.ssr === void 0) {
1702
+ existingMatch.ssr = parentOverride(defaultSsr);
1703
+ return;
1704
+ }
1705
+ if (typeof route.options.ssr !== "function") {
1706
+ existingMatch.ssr = parentOverride(route.options.ssr);
1707
+ return;
1708
+ }
1709
+ const { search, params } = existingMatch;
1710
+ const ssrFnContext = {
1711
+ search: makeMaybe(search, existingMatch.searchError),
1712
+ params: makeMaybe(params, existingMatch.paramsError),
1713
+ location: inner.location,
1714
+ matches: inner.matches.map((match) => ({
1715
+ index: match.index,
1716
+ pathname: match.pathname,
1717
+ fullPath: match.fullPath,
1718
+ staticData: match.staticData,
1719
+ id: match.id,
1720
+ routeId: match.routeId,
1721
+ search: makeMaybe(match.search, match.searchError),
1722
+ params: makeMaybe(match.params, match.paramsError),
1723
+ ssr: match.ssr
1724
+ }))
1725
+ };
1726
+ const tempSsr = route.options.ssr(ssrFnContext);
1727
+ if (isPromise(tempSsr)) {
1728
+ return tempSsr.then((ssr) => {
1729
+ existingMatch.ssr = parentOverride(ssr ?? defaultSsr);
1730
+ });
1731
+ }
1732
+ existingMatch.ssr = parentOverride(tempSsr ?? defaultSsr);
1733
+ return;
1734
+ };
1735
+ const setupPendingTimeout = (inner, matchId, route, match) => {
1736
+ if (match._nonReactive.pendingTimeout !== void 0) return;
1737
+ const pendingMs = route.options.pendingMs ?? inner.router.options.defaultPendingMs;
1738
+ const shouldPending = !!(inner.onReady && false);
1739
+ if (shouldPending) {
1740
+ const pendingTimeout = setTimeout(() => {
1741
+ triggerOnReady(inner);
1742
+ }, pendingMs);
1743
+ match._nonReactive.pendingTimeout = pendingTimeout;
1744
+ }
1745
+ };
1746
+ const preBeforeLoadSetup = (inner, matchId, route) => {
1747
+ const existingMatch = inner.router.getMatch(matchId);
1748
+ if (!existingMatch._nonReactive.beforeLoadPromise && !existingMatch._nonReactive.loaderPromise)
1749
+ return;
1750
+ setupPendingTimeout(inner, matchId, route, existingMatch);
1751
+ const then = () => {
1752
+ const match = inner.router.getMatch(matchId);
1753
+ if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
1754
+ handleRedirectAndNotFound(inner, match, match.error);
1755
+ }
1756
+ };
1757
+ return existingMatch._nonReactive.beforeLoadPromise ? existingMatch._nonReactive.beforeLoadPromise.then(then) : then();
1758
+ };
1759
+ const executeBeforeLoad = (inner, matchId, index, route) => {
1760
+ const match = inner.router.getMatch(matchId);
1761
+ const prevLoadPromise = match._nonReactive.loadPromise;
1762
+ match._nonReactive.loadPromise = createControlledPromise(() => {
1763
+ prevLoadPromise?.resolve();
1764
+ });
1765
+ const { paramsError, searchError } = match;
1766
+ if (paramsError) {
1767
+ handleSerialError(inner, index, paramsError, "PARSE_PARAMS");
1768
+ }
1769
+ if (searchError) {
1770
+ handleSerialError(inner, index, searchError, "VALIDATE_SEARCH");
1771
+ }
1772
+ setupPendingTimeout(inner, matchId, route, match);
1773
+ const abortController = new AbortController();
1774
+ let isPending = false;
1775
+ const pending = () => {
1776
+ if (isPending) return;
1777
+ isPending = true;
1778
+ inner.updateMatch(matchId, (prev) => ({
1779
+ ...prev,
1780
+ isFetching: "beforeLoad",
1781
+ fetchCount: prev.fetchCount + 1,
1782
+ abortController
1783
+ // Note: We intentionally don't update context here.
1784
+ // Context should only be updated after beforeLoad resolves to avoid
1785
+ // components seeing incomplete context during async beforeLoad execution.
1786
+ }));
1787
+ };
1788
+ const resolve = () => {
1789
+ match._nonReactive.beforeLoadPromise?.resolve();
1790
+ match._nonReactive.beforeLoadPromise = void 0;
1791
+ inner.updateMatch(matchId, (prev) => ({
1792
+ ...prev,
1793
+ isFetching: false
1794
+ }));
1795
+ };
1796
+ if (!route.options.beforeLoad) {
1797
+ batch(() => {
1798
+ pending();
1799
+ resolve();
1800
+ });
1801
+ return;
1802
+ }
1803
+ match._nonReactive.beforeLoadPromise = createControlledPromise();
1804
+ const context = {
1805
+ ...buildMatchContext(inner, index, false),
1806
+ ...match.__routeContext
1807
+ };
1808
+ const { search, params, cause } = match;
1809
+ const preload = resolvePreload(inner, matchId);
1810
+ const beforeLoadFnContext = {
1811
+ search,
1812
+ abortController,
1813
+ params,
1814
+ preload,
1815
+ context,
1816
+ location: inner.location,
1817
+ navigate: (opts) => inner.router.navigate({
1818
+ ...opts,
1819
+ _fromLocation: inner.location
1820
+ }),
1821
+ buildLocation: inner.router.buildLocation,
1822
+ cause: preload ? "preload" : cause,
1823
+ matches: inner.matches,
1824
+ routeId: route.id,
1825
+ ...inner.router.options.additionalContext
1826
+ };
1827
+ const updateContext = (beforeLoadContext2) => {
1828
+ if (beforeLoadContext2 === void 0) {
1829
+ batch(() => {
1830
+ pending();
1831
+ resolve();
1832
+ });
1833
+ return;
1834
+ }
1835
+ if (isRedirect(beforeLoadContext2) || isNotFound(beforeLoadContext2)) {
1836
+ pending();
1837
+ handleSerialError(inner, index, beforeLoadContext2, "BEFORE_LOAD");
1838
+ }
1839
+ batch(() => {
1840
+ pending();
1841
+ inner.updateMatch(matchId, (prev) => ({
1842
+ ...prev,
1843
+ __beforeLoadContext: beforeLoadContext2
1844
+ }));
1845
+ resolve();
1846
+ });
1847
+ };
1848
+ let beforeLoadContext;
1849
+ try {
1850
+ beforeLoadContext = route.options.beforeLoad(beforeLoadFnContext);
1851
+ if (isPromise(beforeLoadContext)) {
1852
+ pending();
1853
+ return beforeLoadContext.catch((err) => {
1854
+ handleSerialError(inner, index, err, "BEFORE_LOAD");
1855
+ }).then(updateContext);
1856
+ }
1857
+ } catch (err) {
1858
+ pending();
1859
+ handleSerialError(inner, index, err, "BEFORE_LOAD");
1860
+ }
1861
+ updateContext(beforeLoadContext);
1862
+ return;
1863
+ };
1864
+ const handleBeforeLoad = (inner, index) => {
1865
+ const { id: matchId, routeId } = inner.matches[index];
1866
+ const route = inner.router.looseRoutesById[routeId];
1867
+ const serverSsr = () => {
1868
+ {
1869
+ const maybePromise = isBeforeLoadSsr(inner, matchId, index, route);
1870
+ if (isPromise(maybePromise)) return maybePromise.then(queueExecution);
1871
+ }
1872
+ return queueExecution();
1873
+ };
1874
+ const execute = () => executeBeforeLoad(inner, matchId, index, route);
1875
+ const queueExecution = () => {
1876
+ if (shouldSkipLoader(inner, matchId)) return;
1877
+ const result = preBeforeLoadSetup(inner, matchId, route);
1878
+ return isPromise(result) ? result.then(execute) : execute();
1879
+ };
1880
+ return serverSsr();
1881
+ };
1882
+ const executeHead = (inner, matchId, route) => {
1883
+ const match = inner.router.getMatch(matchId);
1884
+ if (!match) {
1885
+ return;
1886
+ }
1887
+ if (!route.options.head && !route.options.scripts && !route.options.headers) {
1888
+ return;
1889
+ }
1890
+ const assetContext = {
1891
+ ssr: inner.router.options.ssr,
1892
+ matches: inner.matches,
1893
+ match,
1894
+ params: match.params,
1895
+ loaderData: match.loaderData
1896
+ };
1897
+ return Promise.all([
1898
+ route.options.head?.(assetContext),
1899
+ route.options.scripts?.(assetContext),
1900
+ route.options.headers?.(assetContext)
1901
+ ]).then(([headFnContent, scripts, headers]) => {
1902
+ const meta = headFnContent?.meta;
1903
+ const links = headFnContent?.links;
1904
+ const headScripts = headFnContent?.scripts;
1905
+ const styles = headFnContent?.styles;
1906
+ return {
1907
+ meta,
1908
+ links,
1909
+ headScripts,
1910
+ headers,
1911
+ scripts,
1912
+ styles
1913
+ };
1914
+ });
1915
+ };
1916
+ const getLoaderContext = (inner, matchId, index, route) => {
1917
+ const parentMatchPromise = inner.matchPromises[index - 1];
1918
+ const { params, loaderDeps, abortController, cause } = inner.router.getMatch(matchId);
1919
+ const context = buildMatchContext(inner, index);
1920
+ const preload = resolvePreload(inner, matchId);
1921
+ return {
1922
+ params,
1923
+ deps: loaderDeps,
1924
+ preload: !!preload,
1925
+ parentMatchPromise,
1926
+ abortController,
1927
+ context,
1928
+ location: inner.location,
1929
+ navigate: (opts) => inner.router.navigate({
1930
+ ...opts,
1931
+ _fromLocation: inner.location
1932
+ }),
1933
+ cause: preload ? "preload" : cause,
1934
+ route,
1935
+ ...inner.router.options.additionalContext
1936
+ };
1937
+ };
1938
+ const runLoader = async (inner, matchId, index, route) => {
1939
+ try {
1940
+ const match = inner.router.getMatch(matchId);
1941
+ try {
1942
+ if (!(isServer ?? inner.router.isServer) || match.ssr === true) {
1943
+ loadRouteChunk(route);
1944
+ }
1945
+ const loaderResult = route.options.loader?.(
1946
+ getLoaderContext(inner, matchId, index, route)
1947
+ );
1948
+ const loaderResultIsPromise = route.options.loader && isPromise(loaderResult);
1949
+ const willLoadSomething = !!(loaderResultIsPromise || route._lazyPromise || route._componentsPromise || route.options.head || route.options.scripts || route.options.headers || match._nonReactive.minPendingPromise);
1950
+ if (willLoadSomething) {
1951
+ inner.updateMatch(matchId, (prev) => ({
1952
+ ...prev,
1953
+ isFetching: "loader"
1954
+ }));
1955
+ }
1956
+ if (route.options.loader) {
1957
+ const loaderData = loaderResultIsPromise ? await loaderResult : loaderResult;
1958
+ handleRedirectAndNotFound(
1959
+ inner,
1960
+ inner.router.getMatch(matchId),
1961
+ loaderData
1962
+ );
1963
+ if (loaderData !== void 0) {
1964
+ inner.updateMatch(matchId, (prev) => ({
1965
+ ...prev,
1966
+ loaderData
1967
+ }));
1968
+ }
1969
+ }
1970
+ if (route._lazyPromise) await route._lazyPromise;
1971
+ const pendingPromise = match._nonReactive.minPendingPromise;
1972
+ if (pendingPromise) await pendingPromise;
1973
+ if (route._componentsPromise) await route._componentsPromise;
1974
+ inner.updateMatch(matchId, (prev) => ({
1975
+ ...prev,
1976
+ error: void 0,
1977
+ context: buildMatchContext(inner, index),
1978
+ status: "success",
1979
+ isFetching: false,
1980
+ updatedAt: Date.now()
1981
+ }));
1982
+ } catch (e) {
1983
+ let error = e;
1984
+ if (error?.name === "AbortError") {
1985
+ if (match.abortController.signal.aborted) {
1986
+ match._nonReactive.loaderPromise?.resolve();
1987
+ match._nonReactive.loaderPromise = void 0;
1988
+ return;
1989
+ }
1990
+ inner.updateMatch(matchId, (prev) => ({
1991
+ ...prev,
1992
+ status: prev.status === "pending" ? "success" : prev.status,
1993
+ isFetching: false,
1994
+ context: buildMatchContext(inner, index)
1995
+ }));
1996
+ return;
1997
+ }
1998
+ const pendingPromise = match._nonReactive.minPendingPromise;
1999
+ if (pendingPromise) await pendingPromise;
2000
+ if (isNotFound(e)) {
2001
+ await route.options.notFoundComponent?.preload?.();
2002
+ }
2003
+ handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), e);
2004
+ try {
2005
+ route.options.onError?.(e);
2006
+ } catch (onErrorError) {
2007
+ error = onErrorError;
2008
+ handleRedirectAndNotFound(
2009
+ inner,
2010
+ inner.router.getMatch(matchId),
2011
+ onErrorError
2012
+ );
2013
+ }
2014
+ inner.updateMatch(matchId, (prev) => ({
2015
+ ...prev,
2016
+ error,
2017
+ context: buildMatchContext(inner, index),
2018
+ status: "error",
2019
+ isFetching: false
2020
+ }));
2021
+ }
2022
+ } catch (err) {
2023
+ const match = inner.router.getMatch(matchId);
2024
+ if (match) {
2025
+ match._nonReactive.loaderPromise = void 0;
2026
+ }
2027
+ handleRedirectAndNotFound(inner, match, err);
2028
+ }
2029
+ };
2030
+ const loadRouteMatch = async (inner, index) => {
2031
+ async function handleLoader(preload, prevMatch, match2, route2) {
2032
+ const age = Date.now() - prevMatch.updatedAt;
2033
+ const staleAge = preload ? route2.options.preloadStaleTime ?? inner.router.options.defaultPreloadStaleTime ?? 3e4 : route2.options.staleTime ?? inner.router.options.defaultStaleTime ?? 0;
2034
+ const shouldReloadOption = route2.options.shouldReload;
2035
+ const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext(inner, matchId, index, route2)) : shouldReloadOption;
2036
+ const { status, invalid } = match2;
2037
+ loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
2038
+ if (preload && route2.options.preload === false) ;
2039
+ else if (loaderShouldRunAsync && !inner.sync) {
2040
+ loaderIsRunningAsync = true;
2041
+ (async () => {
2042
+ try {
2043
+ await runLoader(inner, matchId, index, route2);
2044
+ const match3 = inner.router.getMatch(matchId);
2045
+ match3._nonReactive.loaderPromise?.resolve();
2046
+ match3._nonReactive.loadPromise?.resolve();
2047
+ match3._nonReactive.loaderPromise = void 0;
2048
+ } catch (err) {
2049
+ if (isRedirect(err)) {
2050
+ await inner.router.navigate(err.options);
2051
+ }
2052
+ }
2053
+ })();
2054
+ } else if (status !== "success" || loaderShouldRunAsync && inner.sync) {
2055
+ await runLoader(inner, matchId, index, route2);
2056
+ }
2057
+ }
2058
+ const { id: matchId, routeId } = inner.matches[index];
2059
+ let loaderShouldRunAsync = false;
2060
+ let loaderIsRunningAsync = false;
2061
+ const route = inner.router.looseRoutesById[routeId];
2062
+ if (shouldSkipLoader(inner, matchId)) {
2063
+ {
2064
+ return inner.router.getMatch(matchId);
2065
+ }
2066
+ } else {
2067
+ const prevMatch = inner.router.getMatch(matchId);
2068
+ const preload = resolvePreload(inner, matchId);
2069
+ if (prevMatch._nonReactive.loaderPromise) {
2070
+ if (prevMatch.status === "success" && !inner.sync && !prevMatch.preload) {
2071
+ return prevMatch;
2072
+ }
2073
+ await prevMatch._nonReactive.loaderPromise;
2074
+ const match2 = inner.router.getMatch(matchId);
2075
+ const error = match2._nonReactive.error || match2.error;
2076
+ if (error) {
2077
+ handleRedirectAndNotFound(inner, match2, error);
2078
+ }
2079
+ if (match2.status === "pending") {
2080
+ await handleLoader(preload, prevMatch, match2, route);
2081
+ }
2082
+ } else {
2083
+ const nextPreload = preload && !inner.router.state.matches.some((d) => d.id === matchId);
2084
+ const match2 = inner.router.getMatch(matchId);
2085
+ match2._nonReactive.loaderPromise = createControlledPromise();
2086
+ if (nextPreload !== match2.preload) {
2087
+ inner.updateMatch(matchId, (prev) => ({
2088
+ ...prev,
2089
+ preload: nextPreload
2090
+ }));
2091
+ }
2092
+ await handleLoader(preload, prevMatch, match2, route);
2093
+ }
2094
+ }
2095
+ const match = inner.router.getMatch(matchId);
2096
+ if (!loaderIsRunningAsync) {
2097
+ match._nonReactive.loaderPromise?.resolve();
2098
+ match._nonReactive.loadPromise?.resolve();
2099
+ }
2100
+ clearTimeout(match._nonReactive.pendingTimeout);
2101
+ match._nonReactive.pendingTimeout = void 0;
2102
+ if (!loaderIsRunningAsync) match._nonReactive.loaderPromise = void 0;
2103
+ match._nonReactive.dehydrated = void 0;
2104
+ const nextIsFetching = loaderIsRunningAsync ? match.isFetching : false;
2105
+ if (nextIsFetching !== match.isFetching || match.invalid !== false) {
2106
+ inner.updateMatch(matchId, (prev) => ({
2107
+ ...prev,
2108
+ isFetching: nextIsFetching,
2109
+ invalid: false
2110
+ }));
2111
+ return inner.router.getMatch(matchId);
2112
+ } else {
2113
+ return match;
2114
+ }
2115
+ };
2116
+ async function loadMatches(arg) {
2117
+ const inner = Object.assign(arg, {
2118
+ matchPromises: []
2119
+ });
2120
+ try {
2121
+ for (let i = 0; i < inner.matches.length; i++) {
2122
+ const beforeLoad = handleBeforeLoad(inner, i);
2123
+ if (isPromise(beforeLoad)) await beforeLoad;
2124
+ }
2125
+ const max = inner.firstBadMatchIndex ?? inner.matches.length;
2126
+ for (let i = 0; i < max; i++) {
2127
+ inner.matchPromises.push(loadRouteMatch(inner, i));
2128
+ }
2129
+ const results = await Promise.allSettled(inner.matchPromises);
2130
+ const failures = results.filter(
2131
+ (result) => result.status === "rejected"
2132
+ ).map((result) => result.reason);
2133
+ let firstNotFound;
2134
+ for (const err of failures) {
2135
+ if (isRedirect(err)) {
2136
+ throw err;
2137
+ }
2138
+ if (!firstNotFound && isNotFound(err)) {
2139
+ firstNotFound = err;
2140
+ }
2141
+ }
2142
+ for (const match of inner.matches) {
2143
+ const { id: matchId, routeId } = match;
2144
+ const route = inner.router.looseRoutesById[routeId];
2145
+ try {
2146
+ const headResult = executeHead(inner, matchId, route);
2147
+ if (headResult) {
2148
+ const head = await headResult;
2149
+ inner.updateMatch(matchId, (prev) => ({
2150
+ ...prev,
2151
+ ...head
2152
+ }));
2153
+ }
2154
+ } catch (err) {
2155
+ console.error(`Error executing head for route ${routeId}:`, err);
2156
+ }
2157
+ }
2158
+ if (firstNotFound) {
2159
+ throw firstNotFound;
2160
+ }
2161
+ const readyPromise = triggerOnReady(inner);
2162
+ if (isPromise(readyPromise)) await readyPromise;
2163
+ } catch (err) {
2164
+ if (isNotFound(err) && !inner.preload) {
2165
+ const readyPromise = triggerOnReady(inner);
2166
+ if (isPromise(readyPromise)) await readyPromise;
2167
+ throw err;
2168
+ }
2169
+ if (isRedirect(err)) {
2170
+ throw err;
2171
+ }
2172
+ }
2173
+ return inner.matches;
2174
+ }
2175
+ async function loadRouteChunk(route) {
2176
+ if (!route._lazyLoaded && route._lazyPromise === void 0) {
2177
+ if (route.lazyFn) {
2178
+ route._lazyPromise = route.lazyFn().then((lazyRoute) => {
2179
+ const { id: _id, ...options } = lazyRoute.options;
2180
+ Object.assign(route.options, options);
2181
+ route._lazyLoaded = true;
2182
+ route._lazyPromise = void 0;
2183
+ });
2184
+ } else {
2185
+ route._lazyLoaded = true;
2186
+ }
2187
+ }
2188
+ if (!route._componentsLoaded && route._componentsPromise === void 0) {
2189
+ const loadComponents = () => {
2190
+ const preloads = [];
2191
+ for (const type of componentTypes) {
2192
+ const preload = route.options[type]?.preload;
2193
+ if (preload) preloads.push(preload());
2194
+ }
2195
+ if (preloads.length)
2196
+ return Promise.all(preloads).then(() => {
2197
+ route._componentsLoaded = true;
2198
+ route._componentsPromise = void 0;
2199
+ });
2200
+ route._componentsLoaded = true;
2201
+ route._componentsPromise = void 0;
2202
+ return;
2203
+ };
2204
+ route._componentsPromise = route._lazyPromise ? route._lazyPromise.then(loadComponents) : loadComponents();
2205
+ }
2206
+ return route._componentsPromise;
2207
+ }
2208
+ function makeMaybe(value, error) {
2209
+ if (error) {
2210
+ return { status: "error", error };
2211
+ }
2212
+ return { status: "success", value };
2213
+ }
2214
+ function routeNeedsPreload(route) {
2215
+ for (const componentType of componentTypes) {
2216
+ if (route.options[componentType]?.preload) {
2217
+ return true;
2218
+ }
2219
+ }
2220
+ return false;
2221
+ }
2222
+ const componentTypes = [
2223
+ "component",
2224
+ "errorComponent",
2225
+ "pendingComponent",
2226
+ "notFoundComponent"
2227
+ ];
2228
+ function composeRewrites(rewrites) {
2229
+ return {
2230
+ input: ({ url }) => {
2231
+ for (const rewrite of rewrites) {
2232
+ url = executeRewriteInput(rewrite, url);
2233
+ }
2234
+ return url;
2235
+ },
2236
+ output: ({ url }) => {
2237
+ for (let i = rewrites.length - 1; i >= 0; i--) {
2238
+ url = executeRewriteOutput(rewrites[i], url);
2239
+ }
2240
+ return url;
2241
+ }
2242
+ };
2243
+ }
2244
+ function rewriteBasepath(opts) {
2245
+ const trimmedBasepath = trimPath(opts.basepath);
2246
+ const normalizedBasepath = `/${trimmedBasepath}`;
2247
+ const normalizedBasepathWithSlash = `${normalizedBasepath}/`;
2248
+ const checkBasepath = opts.caseSensitive ? normalizedBasepath : normalizedBasepath.toLowerCase();
2249
+ const checkBasepathWithSlash = opts.caseSensitive ? normalizedBasepathWithSlash : normalizedBasepathWithSlash.toLowerCase();
2250
+ return {
2251
+ input: ({ url }) => {
2252
+ const pathname = opts.caseSensitive ? url.pathname : url.pathname.toLowerCase();
2253
+ if (pathname === checkBasepath) {
2254
+ url.pathname = "/";
2255
+ } else if (pathname.startsWith(checkBasepathWithSlash)) {
2256
+ url.pathname = url.pathname.slice(normalizedBasepath.length);
2257
+ }
2258
+ return url;
2259
+ },
2260
+ output: ({ url }) => {
2261
+ url.pathname = joinPaths(["/", trimmedBasepath, url.pathname]);
2262
+ return url;
2263
+ }
2264
+ };
2265
+ }
2266
+ function executeRewriteInput(rewrite, url) {
2267
+ const res = rewrite?.input?.({ url });
2268
+ if (res) {
2269
+ if (typeof res === "string") {
2270
+ return new URL(res);
2271
+ } else if (res instanceof URL) {
2272
+ return res;
2273
+ }
2274
+ }
2275
+ return url;
2276
+ }
2277
+ function executeRewriteOutput(rewrite, url) {
2278
+ const res = rewrite?.output?.({ url });
2279
+ if (res) {
2280
+ if (typeof res === "string") {
2281
+ return new URL(res);
2282
+ } else if (res instanceof URL) {
2283
+ return res;
2284
+ }
2285
+ }
2286
+ return url;
2287
+ }
2288
+ function getLocationChangeInfo(routerState) {
2289
+ const fromLocation = routerState.resolvedLocation;
2290
+ const toLocation = routerState.location;
2291
+ const pathChanged = fromLocation?.pathname !== toLocation.pathname;
2292
+ const hrefChanged = fromLocation?.href !== toLocation.href;
2293
+ const hashChanged = fromLocation?.hash !== toLocation.hash;
2294
+ return { fromLocation, toLocation, pathChanged, hrefChanged, hashChanged };
2295
+ }
2296
+ function createServerStore(initialState) {
2297
+ const store = {
2298
+ state: initialState,
2299
+ setState: (updater) => {
2300
+ store.state = updater(store.state);
2301
+ }
2302
+ };
2303
+ return store;
2304
+ }
2305
+ class RouterCore {
2306
+ /**
2307
+ * @deprecated Use the `createRouter` function instead
2308
+ */
2309
+ constructor(options) {
2310
+ this.tempLocationKey = `${Math.round(
2311
+ Math.random() * 1e7
2312
+ )}`;
2313
+ this.resetNextScroll = true;
2314
+ this.shouldViewTransition = void 0;
2315
+ this.isViewTransitionTypesSupported = void 0;
2316
+ this.subscribers = /* @__PURE__ */ new Set();
2317
+ this.isScrollRestoring = false;
2318
+ this.isScrollRestorationSetup = false;
2319
+ this.startTransition = (fn) => fn();
2320
+ this.update = (newOptions) => {
2321
+ if (newOptions.notFoundRoute) {
2322
+ console.warn(
2323
+ "The notFoundRoute API is deprecated and will be removed in the next major version. See https://tanstack.com/router/v1/docs/framework/react/guide/not-found-errors#migrating-from-notfoundroute for more info."
2324
+ );
2325
+ }
2326
+ const prevOptions = this.options;
2327
+ const prevBasepath = this.basepath ?? prevOptions?.basepath ?? "/";
2328
+ const basepathWasUnset = this.basepath === void 0;
2329
+ const prevRewriteOption = prevOptions?.rewrite;
2330
+ this.options = {
2331
+ ...prevOptions,
2332
+ ...newOptions
2333
+ };
2334
+ this.isServer = this.options.isServer ?? typeof document === "undefined";
2335
+ this.protocolAllowlist = new Set(this.options.protocolAllowlist);
2336
+ if (this.options.pathParamsAllowedCharacters)
2337
+ this.pathParamsDecoder = compileDecodeCharMap(
2338
+ this.options.pathParamsAllowedCharacters
2339
+ );
2340
+ if (!this.history || this.options.history && this.options.history !== this.history) {
2341
+ if (!this.options.history) ;
2342
+ else {
2343
+ this.history = this.options.history;
2344
+ }
2345
+ }
2346
+ this.origin = this.options.origin;
2347
+ if (!this.origin) {
2348
+ {
2349
+ this.origin = "http://localhost";
2350
+ }
2351
+ }
2352
+ if (this.history) {
2353
+ this.updateLatestLocation();
2354
+ }
2355
+ if (this.options.routeTree !== this.routeTree) {
2356
+ this.routeTree = this.options.routeTree;
2357
+ let processRouteTreeResult;
2358
+ if (globalThis.__TSR_CACHE__ && globalThis.__TSR_CACHE__.routeTree === this.routeTree) {
2359
+ const cached = globalThis.__TSR_CACHE__;
2360
+ this.resolvePathCache = cached.resolvePathCache;
2361
+ processRouteTreeResult = cached.processRouteTreeResult;
2362
+ } else {
2363
+ this.resolvePathCache = createLRUCache(1e3);
2364
+ processRouteTreeResult = this.buildRouteTree();
2365
+ if (globalThis.__TSR_CACHE__ === void 0) {
2366
+ globalThis.__TSR_CACHE__ = {
2367
+ routeTree: this.routeTree,
2368
+ processRouteTreeResult,
2369
+ resolvePathCache: this.resolvePathCache
2370
+ };
2371
+ }
2372
+ }
2373
+ this.setRoutes(processRouteTreeResult);
2374
+ }
2375
+ if (!this.__store && this.latestLocation) {
2376
+ {
2377
+ this.__store = createServerStore(
2378
+ getInitialRouterState(this.latestLocation)
2379
+ );
2380
+ }
2381
+ }
2382
+ let needsLocationUpdate = false;
2383
+ const nextBasepath = this.options.basepath ?? "/";
2384
+ const nextRewriteOption = this.options.rewrite;
2385
+ const basepathChanged = basepathWasUnset || prevBasepath !== nextBasepath;
2386
+ const rewriteChanged = prevRewriteOption !== nextRewriteOption;
2387
+ if (basepathChanged || rewriteChanged) {
2388
+ this.basepath = nextBasepath;
2389
+ const rewrites = [];
2390
+ const trimmed = trimPath(nextBasepath);
2391
+ if (trimmed && trimmed !== "/") {
2392
+ rewrites.push(
2393
+ rewriteBasepath({
2394
+ basepath: nextBasepath
2395
+ })
2396
+ );
2397
+ }
2398
+ if (nextRewriteOption) {
2399
+ rewrites.push(nextRewriteOption);
2400
+ }
2401
+ this.rewrite = rewrites.length === 0 ? void 0 : rewrites.length === 1 ? rewrites[0] : composeRewrites(rewrites);
2402
+ if (this.history) {
2403
+ this.updateLatestLocation();
2404
+ }
2405
+ needsLocationUpdate = true;
2406
+ }
2407
+ if (needsLocationUpdate && this.__store) {
2408
+ this.__store.state = {
2409
+ ...this.state,
2410
+ location: this.latestLocation
2411
+ };
2412
+ }
2413
+ if (typeof window !== "undefined" && "CSS" in window && typeof window.CSS?.supports === "function") {
2414
+ this.isViewTransitionTypesSupported = window.CSS.supports(
2415
+ "selector(:active-view-transition-type(a)"
2416
+ );
2417
+ }
2418
+ };
2419
+ this.updateLatestLocation = () => {
2420
+ this.latestLocation = this.parseLocation(
2421
+ this.history.location,
2422
+ this.latestLocation
2423
+ );
2424
+ };
2425
+ this.buildRouteTree = () => {
2426
+ const result = processRouteTree(
2427
+ this.routeTree,
2428
+ this.options.caseSensitive,
2429
+ (route, i) => {
2430
+ route.init({
2431
+ originalIndex: i
2432
+ });
2433
+ }
2434
+ );
2435
+ if (this.options.routeMasks) {
2436
+ processRouteMasks(this.options.routeMasks, result.processedTree);
2437
+ }
2438
+ return result;
2439
+ };
2440
+ this.subscribe = (eventType, fn) => {
2441
+ const listener = {
2442
+ eventType,
2443
+ fn
2444
+ };
2445
+ this.subscribers.add(listener);
2446
+ return () => {
2447
+ this.subscribers.delete(listener);
2448
+ };
2449
+ };
2450
+ this.emit = (routerEvent) => {
2451
+ this.subscribers.forEach((listener) => {
2452
+ if (listener.eventType === routerEvent.type) {
2453
+ listener.fn(routerEvent);
2454
+ }
2455
+ });
2456
+ };
2457
+ this.parseLocation = (locationToParse, previousLocation) => {
2458
+ const parse = ({
2459
+ pathname,
2460
+ search,
2461
+ hash,
2462
+ href,
2463
+ state
2464
+ }) => {
2465
+ if (!this.rewrite && !/[ \x00-\x1f\x7f\u0080-\uffff]/.test(pathname)) {
2466
+ const parsedSearch2 = this.options.parseSearch(search);
2467
+ const searchStr2 = this.options.stringifySearch(parsedSearch2);
2468
+ return {
2469
+ href: pathname + searchStr2 + hash,
2470
+ publicHref: href,
2471
+ pathname: decodePath(pathname).path,
2472
+ external: false,
2473
+ searchStr: searchStr2,
2474
+ search: replaceEqualDeep(
2475
+ previousLocation?.search,
2476
+ parsedSearch2
2477
+ ),
2478
+ hash: decodePath(hash.slice(1)).path,
2479
+ state: replaceEqualDeep(previousLocation?.state, state)
2480
+ };
2481
+ }
2482
+ const fullUrl = new URL(href, this.origin);
2483
+ const url = executeRewriteInput(this.rewrite, fullUrl);
2484
+ const parsedSearch = this.options.parseSearch(url.search);
2485
+ const searchStr = this.options.stringifySearch(parsedSearch);
2486
+ url.search = searchStr;
2487
+ const fullPath = url.href.replace(url.origin, "");
2488
+ return {
2489
+ href: fullPath,
2490
+ publicHref: href,
2491
+ pathname: decodePath(url.pathname).path,
2492
+ external: !!this.rewrite && url.origin !== this.origin,
2493
+ searchStr,
2494
+ search: replaceEqualDeep(previousLocation?.search, parsedSearch),
2495
+ hash: decodePath(url.hash.slice(1)).path,
2496
+ state: replaceEqualDeep(previousLocation?.state, state)
2497
+ };
2498
+ };
2499
+ const location = parse(locationToParse);
2500
+ const { __tempLocation, __tempKey } = location.state;
2501
+ if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
2502
+ const parsedTempLocation = parse(__tempLocation);
2503
+ parsedTempLocation.state.key = location.state.key;
2504
+ parsedTempLocation.state.__TSR_key = location.state.__TSR_key;
2505
+ delete parsedTempLocation.state.__tempLocation;
2506
+ return {
2507
+ ...parsedTempLocation,
2508
+ maskedLocation: location
2509
+ };
2510
+ }
2511
+ return location;
2512
+ };
2513
+ this.resolvePathWithBase = (from, path) => {
2514
+ const resolvedPath = resolvePath({
2515
+ base: from,
2516
+ to: cleanPath(path),
2517
+ trailingSlash: this.options.trailingSlash,
2518
+ cache: this.resolvePathCache
2519
+ });
2520
+ return resolvedPath;
2521
+ };
2522
+ this.matchRoutes = (pathnameOrNext, locationSearchOrOpts, opts) => {
2523
+ if (typeof pathnameOrNext === "string") {
2524
+ return this.matchRoutesInternal(
2525
+ {
2526
+ pathname: pathnameOrNext,
2527
+ search: locationSearchOrOpts
2528
+ },
2529
+ opts
2530
+ );
2531
+ }
2532
+ return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
2533
+ };
2534
+ this.getMatchedRoutes = (pathname) => {
2535
+ return getMatchedRoutes({
2536
+ pathname,
2537
+ routesById: this.routesById,
2538
+ processedTree: this.processedTree
2539
+ });
2540
+ };
2541
+ this.cancelMatch = (id) => {
2542
+ const match = this.getMatch(id);
2543
+ if (!match) return;
2544
+ match.abortController.abort();
2545
+ clearTimeout(match._nonReactive.pendingTimeout);
2546
+ match._nonReactive.pendingTimeout = void 0;
2547
+ };
2548
+ this.cancelMatches = () => {
2549
+ const currentPendingMatches = this.state.matches.filter(
2550
+ (match) => match.status === "pending"
2551
+ );
2552
+ const currentLoadingMatches = this.state.matches.filter(
2553
+ (match) => match.isFetching === "loader"
2554
+ );
2555
+ const matchesToCancelArray = /* @__PURE__ */ new Set([
2556
+ ...this.state.pendingMatches ?? [],
2557
+ ...currentPendingMatches,
2558
+ ...currentLoadingMatches
2559
+ ]);
2560
+ matchesToCancelArray.forEach((match) => {
2561
+ this.cancelMatch(match.id);
2562
+ });
2563
+ };
2564
+ this.buildLocation = (opts) => {
2565
+ const build = (dest = {}) => {
2566
+ const currentLocation = dest._fromLocation || this.pendingBuiltLocation || this.latestLocation;
2567
+ const lightweightResult = this.matchRoutesLightweight(currentLocation);
2568
+ if (dest.from && false) ;
2569
+ const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ?? lightweightResult.fullPath;
2570
+ const fromPath = this.resolvePathWithBase(defaultedFromPath, ".");
2571
+ const fromSearch = lightweightResult.search;
2572
+ const fromParams = { ...lightweightResult.params };
2573
+ const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
2574
+ const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
2575
+ fromParams,
2576
+ functionalUpdate(dest.params, fromParams)
2577
+ );
2578
+ const interpolatedNextTo = interpolatePath({
2579
+ path: nextTo,
2580
+ params: nextParams,
2581
+ decoder: this.pathParamsDecoder,
2582
+ server: this.isServer
2583
+ }).interpolatedPath;
2584
+ const destMatchResult = this.getMatchedRoutes(interpolatedNextTo);
2585
+ let destRoutes = destMatchResult.matchedRoutes;
2586
+ const isGlobalNotFound = destMatchResult.foundRoute ? destMatchResult.foundRoute.path !== "/" && destMatchResult.routeParams["**"] : trimPathRight(interpolatedNextTo);
2587
+ if (isGlobalNotFound && this.options.notFoundRoute) {
2588
+ destRoutes = [...destRoutes, this.options.notFoundRoute];
2589
+ }
2590
+ let changedParams = false;
2591
+ if (Object.keys(nextParams).length > 0) {
2592
+ for (const route of destRoutes) {
2593
+ const fn = route.options.params?.stringify ?? route.options.stringifyParams;
2594
+ if (fn) {
2595
+ changedParams = true;
2596
+ Object.assign(nextParams, fn(nextParams));
2597
+ }
2598
+ }
2599
+ }
2600
+ const nextPathname = opts.leaveParams ? (
2601
+ // Use the original template path for interpolation
2602
+ // This preserves the original parameter syntax including optional parameters
2603
+ nextTo
2604
+ ) : decodePath(
2605
+ !changedParams ? interpolatedNextTo : interpolatePath({
2606
+ path: nextTo,
2607
+ params: nextParams,
2608
+ decoder: this.pathParamsDecoder,
2609
+ server: this.isServer
2610
+ }).interpolatedPath
2611
+ ).path;
2612
+ let nextSearch = fromSearch;
2613
+ if (opts._includeValidateSearch && this.options.search?.strict) {
2614
+ const validatedSearch = {};
2615
+ destRoutes.forEach((route) => {
2616
+ if (route.options.validateSearch) {
2617
+ try {
2618
+ Object.assign(
2619
+ validatedSearch,
2620
+ validateSearch(route.options.validateSearch, {
2621
+ ...validatedSearch,
2622
+ ...nextSearch
2623
+ })
2624
+ );
2625
+ } catch {
2626
+ }
2627
+ }
2628
+ });
2629
+ nextSearch = validatedSearch;
2630
+ }
2631
+ nextSearch = applySearchMiddleware({
2632
+ search: nextSearch,
2633
+ dest,
2634
+ destRoutes,
2635
+ _includeValidateSearch: opts._includeValidateSearch
2636
+ });
2637
+ nextSearch = replaceEqualDeep(fromSearch, nextSearch);
2638
+ const searchStr = this.options.stringifySearch(nextSearch);
2639
+ const hash = dest.hash === true ? currentLocation.hash : dest.hash ? functionalUpdate(dest.hash, currentLocation.hash) : void 0;
2640
+ const hashStr = hash ? `#${hash}` : "";
2641
+ let nextState = dest.state === true ? currentLocation.state : dest.state ? functionalUpdate(dest.state, currentLocation.state) : {};
2642
+ nextState = replaceEqualDeep(currentLocation.state, nextState);
2643
+ const fullPath = `${nextPathname}${searchStr}${hashStr}`;
2644
+ let href;
2645
+ let publicHref;
2646
+ let external = false;
2647
+ if (this.rewrite) {
2648
+ const url = new URL(fullPath, this.origin);
2649
+ const rewrittenUrl = executeRewriteOutput(this.rewrite, url);
2650
+ href = url.href.replace(url.origin, "");
2651
+ if (rewrittenUrl.origin !== this.origin) {
2652
+ publicHref = rewrittenUrl.href;
2653
+ external = true;
2654
+ } else {
2655
+ publicHref = rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash;
2656
+ }
2657
+ } else {
2658
+ href = encodePathLikeUrl(fullPath);
2659
+ publicHref = href;
2660
+ }
2661
+ return {
2662
+ publicHref,
2663
+ href,
2664
+ pathname: nextPathname,
2665
+ search: nextSearch,
2666
+ searchStr,
2667
+ state: nextState,
2668
+ hash: hash ?? "",
2669
+ external,
2670
+ unmaskOnReload: dest.unmaskOnReload
2671
+ };
2672
+ };
2673
+ const buildWithMatches = (dest = {}, maskedDest) => {
2674
+ const next = build(dest);
2675
+ let maskedNext = maskedDest ? build(maskedDest) : void 0;
2676
+ if (!maskedNext) {
2677
+ const params = {};
2678
+ if (this.options.routeMasks) {
2679
+ const match = findFlatMatch(
2680
+ next.pathname,
2681
+ this.processedTree
2682
+ );
2683
+ if (match) {
2684
+ Object.assign(params, match.rawParams);
2685
+ const {
2686
+ from: _from,
2687
+ params: maskParams,
2688
+ ...maskProps
2689
+ } = match.route;
2690
+ const nextParams = maskParams === false || maskParams === null ? {} : (maskParams ?? true) === true ? params : Object.assign(params, functionalUpdate(maskParams, params));
2691
+ maskedDest = {
2692
+ from: opts.from,
2693
+ ...maskProps,
2694
+ params: nextParams
2695
+ };
2696
+ maskedNext = build(maskedDest);
2697
+ }
2698
+ }
2699
+ }
2700
+ if (maskedNext) {
2701
+ next.maskedLocation = maskedNext;
2702
+ }
2703
+ return next;
2704
+ };
2705
+ if (opts.mask) {
2706
+ return buildWithMatches(opts, {
2707
+ from: opts.from,
2708
+ ...opts.mask
2709
+ });
2710
+ }
2711
+ return buildWithMatches(opts);
2712
+ };
2713
+ this.commitLocation = async ({
2714
+ viewTransition,
2715
+ ignoreBlocker,
2716
+ ...next
2717
+ }) => {
2718
+ const isSameState = () => {
2719
+ const ignoredProps = [
2720
+ "key",
2721
+ // TODO: Remove in v2 - use __TSR_key instead
2722
+ "__TSR_key",
2723
+ "__TSR_index",
2724
+ "__hashScrollIntoViewOptions"
2725
+ ];
2726
+ ignoredProps.forEach((prop) => {
2727
+ next.state[prop] = this.latestLocation.state[prop];
2728
+ });
2729
+ const isEqual = deepEqual(next.state, this.latestLocation.state);
2730
+ ignoredProps.forEach((prop) => {
2731
+ delete next.state[prop];
2732
+ });
2733
+ return isEqual;
2734
+ };
2735
+ const isSameUrl = trimPathRight(this.latestLocation.href) === trimPathRight(next.href);
2736
+ const previousCommitPromise = this.commitLocationPromise;
2737
+ this.commitLocationPromise = createControlledPromise(() => {
2738
+ previousCommitPromise?.resolve();
2739
+ });
2740
+ if (isSameUrl && isSameState()) {
2741
+ this.load();
2742
+ } else {
2743
+ let {
2744
+ // eslint-disable-next-line prefer-const
2745
+ maskedLocation,
2746
+ // eslint-disable-next-line prefer-const
2747
+ hashScrollIntoView,
2748
+ ...nextHistory
2749
+ } = next;
2750
+ if (maskedLocation) {
2751
+ nextHistory = {
2752
+ ...maskedLocation,
2753
+ state: {
2754
+ ...maskedLocation.state,
2755
+ __tempKey: void 0,
2756
+ __tempLocation: {
2757
+ ...nextHistory,
2758
+ search: nextHistory.searchStr,
2759
+ state: {
2760
+ ...nextHistory.state,
2761
+ __tempKey: void 0,
2762
+ __tempLocation: void 0,
2763
+ __TSR_key: void 0,
2764
+ key: void 0
2765
+ // TODO: Remove in v2 - use __TSR_key instead
2766
+ }
2767
+ }
2768
+ }
2769
+ };
2770
+ if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
2771
+ nextHistory.state.__tempKey = this.tempLocationKey;
2772
+ }
2773
+ }
2774
+ nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
2775
+ this.shouldViewTransition = viewTransition;
2776
+ this.history[next.replace ? "replace" : "push"](
2777
+ nextHistory.publicHref,
2778
+ nextHistory.state,
2779
+ { ignoreBlocker }
2780
+ );
2781
+ }
2782
+ this.resetNextScroll = next.resetScroll ?? true;
2783
+ if (!this.history.subscribers.size) {
2784
+ this.load();
2785
+ }
2786
+ return this.commitLocationPromise;
2787
+ };
2788
+ this.buildAndCommitLocation = ({
2789
+ replace,
2790
+ resetScroll,
2791
+ hashScrollIntoView,
2792
+ viewTransition,
2793
+ ignoreBlocker,
2794
+ href,
2795
+ ...rest
2796
+ } = {}) => {
2797
+ if (href) {
2798
+ const currentIndex = this.history.location.state.__TSR_index;
2799
+ const parsed = parseHref(href, {
2800
+ __TSR_index: replace ? currentIndex : currentIndex + 1
2801
+ });
2802
+ const hrefUrl = new URL(parsed.pathname, this.origin);
2803
+ const rewrittenUrl = executeRewriteInput(this.rewrite, hrefUrl);
2804
+ rest.to = rewrittenUrl.pathname;
2805
+ rest.search = this.options.parseSearch(parsed.search);
2806
+ rest.hash = parsed.hash.slice(1);
2807
+ }
2808
+ const location = this.buildLocation({
2809
+ ...rest,
2810
+ _includeValidateSearch: true
2811
+ });
2812
+ this.pendingBuiltLocation = location;
2813
+ const commitPromise = this.commitLocation({
2814
+ ...location,
2815
+ viewTransition,
2816
+ replace,
2817
+ resetScroll,
2818
+ hashScrollIntoView,
2819
+ ignoreBlocker
2820
+ });
2821
+ Promise.resolve().then(() => {
2822
+ if (this.pendingBuiltLocation === location) {
2823
+ this.pendingBuiltLocation = void 0;
2824
+ }
2825
+ });
2826
+ return commitPromise;
2827
+ };
2828
+ this.navigate = async ({
2829
+ to,
2830
+ reloadDocument,
2831
+ href,
2832
+ publicHref,
2833
+ ...rest
2834
+ }) => {
2835
+ let hrefIsUrl = false;
2836
+ if (href) {
2837
+ try {
2838
+ new URL(`${href}`);
2839
+ hrefIsUrl = true;
2840
+ } catch {
2841
+ }
2842
+ }
2843
+ if (hrefIsUrl && !reloadDocument) {
2844
+ reloadDocument = true;
2845
+ }
2846
+ if (reloadDocument) {
2847
+ if (to !== void 0 || !href) {
2848
+ const location = this.buildLocation({ to, ...rest });
2849
+ href = href ?? location.publicHref;
2850
+ publicHref = publicHref ?? location.publicHref;
2851
+ }
2852
+ const reloadHref = !hrefIsUrl && publicHref ? publicHref : href;
2853
+ if (isDangerousProtocol(reloadHref, this.protocolAllowlist)) {
2854
+ return Promise.resolve();
2855
+ }
2856
+ if (!rest.ignoreBlocker) {
2857
+ const historyWithBlockers = this.history;
2858
+ const blockers = historyWithBlockers.getBlockers?.() ?? [];
2859
+ for (const blocker of blockers) {
2860
+ if (blocker?.blockerFn) {
2861
+ const shouldBlock = await blocker.blockerFn({
2862
+ currentLocation: this.latestLocation,
2863
+ nextLocation: this.latestLocation,
2864
+ // External URLs don't have a next location in our router
2865
+ action: "PUSH"
2866
+ });
2867
+ if (shouldBlock) {
2868
+ return Promise.resolve();
2869
+ }
2870
+ }
2871
+ }
2872
+ }
2873
+ if (rest.replace) {
2874
+ window.location.replace(reloadHref);
2875
+ } else {
2876
+ window.location.href = reloadHref;
2877
+ }
2878
+ return Promise.resolve();
2879
+ }
2880
+ return this.buildAndCommitLocation({
2881
+ ...rest,
2882
+ href,
2883
+ to,
2884
+ _isNavigate: true
2885
+ });
2886
+ };
2887
+ this.beforeLoad = () => {
2888
+ this.cancelMatches();
2889
+ this.updateLatestLocation();
2890
+ {
2891
+ const nextLocation = this.buildLocation({
2892
+ to: this.latestLocation.pathname,
2893
+ search: true,
2894
+ params: true,
2895
+ hash: true,
2896
+ state: true,
2897
+ _includeValidateSearch: true
2898
+ });
2899
+ if (this.latestLocation.publicHref !== nextLocation.publicHref) {
2900
+ const href = this.getParsedLocationHref(nextLocation);
2901
+ if (nextLocation.external) {
2902
+ throw redirect({ href });
2903
+ } else {
2904
+ throw redirect({ href, _builtLocation: nextLocation });
2905
+ }
2906
+ }
2907
+ }
2908
+ const pendingMatches = this.matchRoutes(this.latestLocation);
2909
+ this.__store.setState((s) => ({
2910
+ ...s,
2911
+ status: "pending",
2912
+ statusCode: 200,
2913
+ isLoading: true,
2914
+ location: this.latestLocation,
2915
+ pendingMatches,
2916
+ // If a cached moved to pendingMatches, remove it from cachedMatches
2917
+ cachedMatches: s.cachedMatches.filter(
2918
+ (d) => !pendingMatches.some((e) => e.id === d.id)
2919
+ )
2920
+ }));
2921
+ };
2922
+ this.load = async (opts) => {
2923
+ let redirect2;
2924
+ let notFound;
2925
+ let loadPromise;
2926
+ loadPromise = new Promise((resolve) => {
2927
+ this.startTransition(async () => {
2928
+ try {
2929
+ this.beforeLoad();
2930
+ const next = this.latestLocation;
2931
+ const prevLocation = this.state.resolvedLocation;
2932
+ if (!this.state.redirect) {
2933
+ this.emit({
2934
+ type: "onBeforeNavigate",
2935
+ ...getLocationChangeInfo({
2936
+ resolvedLocation: prevLocation,
2937
+ location: next
2938
+ })
2939
+ });
2940
+ }
2941
+ this.emit({
2942
+ type: "onBeforeLoad",
2943
+ ...getLocationChangeInfo({
2944
+ resolvedLocation: prevLocation,
2945
+ location: next
2946
+ })
2947
+ });
2948
+ await loadMatches({
2949
+ router: this,
2950
+ sync: opts?.sync,
2951
+ matches: this.state.pendingMatches,
2952
+ location: next,
2953
+ updateMatch: this.updateMatch,
2954
+ // eslint-disable-next-line @typescript-eslint/require-await
2955
+ onReady: async () => {
2956
+ this.startTransition(() => {
2957
+ this.startViewTransition(async () => {
2958
+ let exitingMatches = [];
2959
+ let enteringMatches = [];
2960
+ let stayingMatches = [];
2961
+ batch(() => {
2962
+ this.__store.setState((s) => {
2963
+ const previousMatches = s.matches;
2964
+ const newMatches = s.pendingMatches || s.matches;
2965
+ exitingMatches = previousMatches.filter(
2966
+ (match) => !newMatches.some((d) => d.id === match.id)
2967
+ );
2968
+ enteringMatches = newMatches.filter(
2969
+ (match) => !previousMatches.some((d) => d.id === match.id)
2970
+ );
2971
+ stayingMatches = newMatches.filter(
2972
+ (match) => previousMatches.some((d) => d.id === match.id)
2973
+ );
2974
+ return {
2975
+ ...s,
2976
+ isLoading: false,
2977
+ loadedAt: Date.now(),
2978
+ matches: newMatches,
2979
+ pendingMatches: void 0,
2980
+ /**
2981
+ * When committing new matches, cache any exiting matches that are still usable.
2982
+ * Routes that resolved with `status: 'error'` or `status: 'notFound'` are
2983
+ * deliberately excluded from `cachedMatches` so that subsequent invalidations
2984
+ * or reloads re-run their loaders instead of reusing the failed/not-found data.
2985
+ */
2986
+ cachedMatches: [
2987
+ ...s.cachedMatches,
2988
+ ...exitingMatches.filter(
2989
+ (d) => d.status !== "error" && d.status !== "notFound"
2990
+ )
2991
+ ]
2992
+ };
2993
+ });
2994
+ this.clearExpiredCache();
2995
+ });
2996
+ [
2997
+ [exitingMatches, "onLeave"],
2998
+ [enteringMatches, "onEnter"],
2999
+ [stayingMatches, "onStay"]
3000
+ ].forEach(([matches, hook]) => {
3001
+ matches.forEach((match) => {
3002
+ this.looseRoutesById[match.routeId].options[hook]?.(
3003
+ match
3004
+ );
3005
+ });
3006
+ });
3007
+ });
3008
+ });
3009
+ }
3010
+ });
3011
+ } catch (err) {
3012
+ if (isRedirect(err)) {
3013
+ redirect2 = err;
3014
+ } else if (isNotFound(err)) {
3015
+ notFound = err;
3016
+ }
3017
+ this.__store.setState((s) => ({
3018
+ ...s,
3019
+ statusCode: redirect2 ? redirect2.status : notFound ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
3020
+ redirect: redirect2
3021
+ }));
3022
+ }
3023
+ if (this.latestLoadPromise === loadPromise) {
3024
+ this.commitLocationPromise?.resolve();
3025
+ this.latestLoadPromise = void 0;
3026
+ this.commitLocationPromise = void 0;
3027
+ }
3028
+ resolve();
3029
+ });
3030
+ });
3031
+ this.latestLoadPromise = loadPromise;
3032
+ await loadPromise;
3033
+ while (this.latestLoadPromise && loadPromise !== this.latestLoadPromise) {
3034
+ await this.latestLoadPromise;
3035
+ }
3036
+ let newStatusCode = void 0;
3037
+ if (this.hasNotFoundMatch()) {
3038
+ newStatusCode = 404;
3039
+ } else if (this.__store.state.matches.some((d) => d.status === "error")) {
3040
+ newStatusCode = 500;
3041
+ }
3042
+ if (newStatusCode !== void 0) {
3043
+ this.__store.setState((s) => ({
3044
+ ...s,
3045
+ statusCode: newStatusCode
3046
+ }));
3047
+ }
3048
+ };
3049
+ this.startViewTransition = (fn) => {
3050
+ const shouldViewTransition = this.shouldViewTransition ?? this.options.defaultViewTransition;
3051
+ this.shouldViewTransition = void 0;
3052
+ if (shouldViewTransition && typeof document !== "undefined" && "startViewTransition" in document && typeof document.startViewTransition === "function") {
3053
+ let startViewTransitionParams;
3054
+ if (typeof shouldViewTransition === "object" && this.isViewTransitionTypesSupported) {
3055
+ const next = this.latestLocation;
3056
+ const prevLocation = this.state.resolvedLocation;
3057
+ const resolvedViewTransitionTypes = typeof shouldViewTransition.types === "function" ? shouldViewTransition.types(
3058
+ getLocationChangeInfo({
3059
+ resolvedLocation: prevLocation,
3060
+ location: next
3061
+ })
3062
+ ) : shouldViewTransition.types;
3063
+ if (resolvedViewTransitionTypes === false) {
3064
+ fn();
3065
+ return;
3066
+ }
3067
+ startViewTransitionParams = {
3068
+ update: fn,
3069
+ types: resolvedViewTransitionTypes
3070
+ };
3071
+ } else {
3072
+ startViewTransitionParams = fn;
3073
+ }
3074
+ document.startViewTransition(startViewTransitionParams);
3075
+ } else {
3076
+ fn();
3077
+ }
3078
+ };
3079
+ this.updateMatch = (id, updater) => {
3080
+ this.startTransition(() => {
3081
+ const matchesKey = this.state.pendingMatches?.some((d) => d.id === id) ? "pendingMatches" : this.state.matches.some((d) => d.id === id) ? "matches" : this.state.cachedMatches.some((d) => d.id === id) ? "cachedMatches" : "";
3082
+ if (matchesKey) {
3083
+ this.__store.setState((s) => ({
3084
+ ...s,
3085
+ [matchesKey]: s[matchesKey]?.map(
3086
+ (d) => d.id === id ? updater(d) : d
3087
+ )
3088
+ }));
3089
+ }
3090
+ });
3091
+ };
3092
+ this.getMatch = (matchId) => {
3093
+ const findFn = (d) => d.id === matchId;
3094
+ return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
3095
+ };
3096
+ this.invalidate = (opts) => {
3097
+ const invalidate = (d) => {
3098
+ if (opts?.filter?.(d) ?? true) {
3099
+ return {
3100
+ ...d,
3101
+ invalid: true,
3102
+ ...opts?.forcePending || d.status === "error" || d.status === "notFound" ? { status: "pending", error: void 0 } : void 0
3103
+ };
3104
+ }
3105
+ return d;
3106
+ };
3107
+ this.__store.setState((s) => ({
3108
+ ...s,
3109
+ matches: s.matches.map(invalidate),
3110
+ cachedMatches: s.cachedMatches.map(invalidate),
3111
+ pendingMatches: s.pendingMatches?.map(invalidate)
3112
+ }));
3113
+ this.shouldViewTransition = false;
3114
+ return this.load({ sync: opts?.sync });
3115
+ };
3116
+ this.getParsedLocationHref = (location) => {
3117
+ return location.publicHref || "/";
3118
+ };
3119
+ this.resolveRedirect = (redirect2) => {
3120
+ const locationHeader = redirect2.headers.get("Location");
3121
+ if (!redirect2.options.href || redirect2.options._builtLocation) {
3122
+ const location = redirect2.options._builtLocation ?? this.buildLocation(redirect2.options);
3123
+ const href = this.getParsedLocationHref(location);
3124
+ redirect2.options.href = href;
3125
+ redirect2.headers.set("Location", href);
3126
+ } else if (locationHeader) {
3127
+ try {
3128
+ const url = new URL(locationHeader);
3129
+ if (this.origin && url.origin === this.origin) {
3130
+ const href = url.pathname + url.search + url.hash;
3131
+ redirect2.options.href = href;
3132
+ redirect2.headers.set("Location", href);
3133
+ }
3134
+ } catch {
3135
+ }
3136
+ }
3137
+ if (redirect2.options.href && !redirect2.options._builtLocation && // Check for dangerous protocols before processing the redirect
3138
+ isDangerousProtocol(redirect2.options.href, this.protocolAllowlist)) {
3139
+ throw new Error(
3140
+ `Redirect blocked: unsafe protocol in href "${redirect2.options.href}". Allowed protocols: ${Array.from(this.protocolAllowlist).join(", ")}.`
3141
+ );
3142
+ }
3143
+ if (!redirect2.headers.get("Location")) {
3144
+ redirect2.headers.set("Location", redirect2.options.href);
3145
+ }
3146
+ return redirect2;
3147
+ };
3148
+ this.clearCache = (opts) => {
3149
+ const filter = opts?.filter;
3150
+ if (filter !== void 0) {
3151
+ this.__store.setState((s) => {
3152
+ return {
3153
+ ...s,
3154
+ cachedMatches: s.cachedMatches.filter(
3155
+ (m) => !filter(m)
3156
+ )
3157
+ };
3158
+ });
3159
+ } else {
3160
+ this.__store.setState((s) => {
3161
+ return {
3162
+ ...s,
3163
+ cachedMatches: []
3164
+ };
3165
+ });
3166
+ }
3167
+ };
3168
+ this.clearExpiredCache = () => {
3169
+ const filter = (d) => {
3170
+ const route = this.looseRoutesById[d.routeId];
3171
+ if (!route.options.loader) {
3172
+ return true;
3173
+ }
3174
+ const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 5 * 60 * 1e3;
3175
+ const isError = d.status === "error";
3176
+ if (isError) return true;
3177
+ const gcEligible = Date.now() - d.updatedAt >= gcTime;
3178
+ return gcEligible;
3179
+ };
3180
+ this.clearCache({ filter });
3181
+ };
3182
+ this.loadRouteChunk = loadRouteChunk;
3183
+ this.preloadRoute = async (opts) => {
3184
+ const next = this.buildLocation(opts);
3185
+ let matches = this.matchRoutes(next, {
3186
+ throwOnError: true,
3187
+ preload: true,
3188
+ dest: opts
3189
+ });
3190
+ const activeMatchIds = new Set(
3191
+ [...this.state.matches, ...this.state.pendingMatches ?? []].map(
3192
+ (d) => d.id
3193
+ )
3194
+ );
3195
+ const loadedMatchIds = /* @__PURE__ */ new Set([
3196
+ ...activeMatchIds,
3197
+ ...this.state.cachedMatches.map((d) => d.id)
3198
+ ]);
3199
+ batch(() => {
3200
+ matches.forEach((match) => {
3201
+ if (!loadedMatchIds.has(match.id)) {
3202
+ this.__store.setState((s) => ({
3203
+ ...s,
3204
+ cachedMatches: [...s.cachedMatches, match]
3205
+ }));
3206
+ }
3207
+ });
3208
+ });
3209
+ try {
3210
+ matches = await loadMatches({
3211
+ router: this,
3212
+ matches,
3213
+ location: next,
3214
+ preload: true,
3215
+ updateMatch: (id, updater) => {
3216
+ if (activeMatchIds.has(id)) {
3217
+ matches = matches.map((d) => d.id === id ? updater(d) : d);
3218
+ } else {
3219
+ this.updateMatch(id, updater);
3220
+ }
3221
+ }
3222
+ });
3223
+ return matches;
3224
+ } catch (err) {
3225
+ if (isRedirect(err)) {
3226
+ if (err.options.reloadDocument) {
3227
+ return void 0;
3228
+ }
3229
+ return await this.preloadRoute({
3230
+ ...err.options,
3231
+ _fromLocation: next
3232
+ });
3233
+ }
3234
+ if (!isNotFound(err)) {
3235
+ console.error(err);
3236
+ }
3237
+ return void 0;
3238
+ }
3239
+ };
3240
+ this.matchRoute = (location, opts) => {
3241
+ const matchLocation = {
3242
+ ...location,
3243
+ to: location.to ? this.resolvePathWithBase(
3244
+ location.from || "",
3245
+ location.to
3246
+ ) : void 0,
3247
+ params: location.params || {},
3248
+ leaveParams: true
3249
+ };
3250
+ const next = this.buildLocation(matchLocation);
3251
+ if (opts?.pending && this.state.status !== "pending") {
3252
+ return false;
3253
+ }
3254
+ const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
3255
+ const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
3256
+ const match = findSingleMatch(
3257
+ next.pathname,
3258
+ opts?.caseSensitive ?? false,
3259
+ opts?.fuzzy ?? false,
3260
+ baseLocation.pathname,
3261
+ this.processedTree
3262
+ );
3263
+ if (!match) {
3264
+ return false;
3265
+ }
3266
+ if (location.params) {
3267
+ if (!deepEqual(match.rawParams, location.params, { partial: true })) {
3268
+ return false;
3269
+ }
3270
+ }
3271
+ if (opts?.includeSearch ?? true) {
3272
+ return deepEqual(baseLocation.search, next.search, { partial: true }) ? match.rawParams : false;
3273
+ }
3274
+ return match.rawParams;
3275
+ };
3276
+ this.hasNotFoundMatch = () => {
3277
+ return this.__store.state.matches.some(
3278
+ (d) => d.status === "notFound" || d.globalNotFound
3279
+ );
3280
+ };
3281
+ this.update({
3282
+ defaultPreloadDelay: 50,
3283
+ defaultPendingMs: 1e3,
3284
+ defaultPendingMinMs: 500,
3285
+ context: void 0,
3286
+ ...options,
3287
+ caseSensitive: options.caseSensitive ?? false,
3288
+ notFoundMode: options.notFoundMode ?? "fuzzy",
3289
+ stringifySearch: options.stringifySearch ?? defaultStringifySearch,
3290
+ parseSearch: options.parseSearch ?? defaultParseSearch,
3291
+ protocolAllowlist: options.protocolAllowlist ?? DEFAULT_PROTOCOL_ALLOWLIST
3292
+ });
3293
+ if (typeof document !== "undefined") {
3294
+ self.__TSR_ROUTER__ = this;
3295
+ }
3296
+ }
3297
+ isShell() {
3298
+ return !!this.options.isShell;
3299
+ }
3300
+ isPrerendering() {
3301
+ return !!this.options.isPrerendering;
3302
+ }
3303
+ get state() {
3304
+ return this.__store.state;
3305
+ }
3306
+ setRoutes({
3307
+ routesById,
3308
+ routesByPath,
3309
+ processedTree
3310
+ }) {
3311
+ this.routesById = routesById;
3312
+ this.routesByPath = routesByPath;
3313
+ this.processedTree = processedTree;
3314
+ const notFoundRoute = this.options.notFoundRoute;
3315
+ if (notFoundRoute) {
3316
+ notFoundRoute.init({
3317
+ originalIndex: 99999999999
3318
+ });
3319
+ this.routesById[notFoundRoute.id] = notFoundRoute;
3320
+ }
3321
+ }
3322
+ get looseRoutesById() {
3323
+ return this.routesById;
3324
+ }
3325
+ getParentContext(parentMatch) {
3326
+ const parentMatchId = parentMatch?.id;
3327
+ const parentContext = !parentMatchId ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
3328
+ return parentContext;
3329
+ }
3330
+ matchRoutesInternal(next, opts) {
3331
+ const matchedRoutesResult = this.getMatchedRoutes(next.pathname);
3332
+ const { foundRoute, routeParams, parsedParams } = matchedRoutesResult;
3333
+ let { matchedRoutes } = matchedRoutesResult;
3334
+ let isGlobalNotFound = false;
3335
+ if (
3336
+ // If we found a route, and it's not an index route and we have left over path
3337
+ foundRoute ? foundRoute.path !== "/" && routeParams["**"] : (
3338
+ // Or if we didn't find a route and we have left over path
3339
+ trimPathRight(next.pathname)
3340
+ )
3341
+ ) {
3342
+ if (this.options.notFoundRoute) {
3343
+ matchedRoutes = [...matchedRoutes, this.options.notFoundRoute];
3344
+ } else {
3345
+ isGlobalNotFound = true;
3346
+ }
3347
+ }
3348
+ const globalNotFoundRouteId = isGlobalNotFound ? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes) : void 0;
3349
+ const matches = new Array(matchedRoutes.length);
3350
+ const previousMatchesByRouteId = new Map(
3351
+ this.state.matches.map((match) => [match.routeId, match])
3352
+ );
3353
+ for (let index = 0; index < matchedRoutes.length; index++) {
3354
+ const route = matchedRoutes[index];
3355
+ const parentMatch = matches[index - 1];
3356
+ let preMatchSearch;
3357
+ let strictMatchSearch;
3358
+ let searchError;
3359
+ {
3360
+ const parentSearch = parentMatch?.search ?? next.search;
3361
+ const parentStrictSearch = parentMatch?._strictSearch ?? void 0;
3362
+ try {
3363
+ const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? void 0;
3364
+ preMatchSearch = {
3365
+ ...parentSearch,
3366
+ ...strictSearch
3367
+ };
3368
+ strictMatchSearch = { ...parentStrictSearch, ...strictSearch };
3369
+ searchError = void 0;
3370
+ } catch (err) {
3371
+ let searchParamError = err;
3372
+ if (!(err instanceof SearchParamError)) {
3373
+ searchParamError = new SearchParamError(err.message, {
3374
+ cause: err
3375
+ });
3376
+ }
3377
+ if (opts?.throwOnError) {
3378
+ throw searchParamError;
3379
+ }
3380
+ preMatchSearch = parentSearch;
3381
+ strictMatchSearch = {};
3382
+ searchError = searchParamError;
3383
+ }
3384
+ }
3385
+ const loaderDeps = route.options.loaderDeps?.({
3386
+ search: preMatchSearch
3387
+ }) ?? "";
3388
+ const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
3389
+ const { interpolatedPath, usedParams } = interpolatePath({
3390
+ path: route.fullPath,
3391
+ params: routeParams,
3392
+ decoder: this.pathParamsDecoder,
3393
+ server: this.isServer
3394
+ });
3395
+ const matchId = (
3396
+ // route.id for disambiguation
3397
+ route.id + // interpolatedPath for param changes
3398
+ interpolatedPath + // explicit deps
3399
+ loaderDepsHash
3400
+ );
3401
+ const existingMatch = this.getMatch(matchId);
3402
+ const previousMatch = previousMatchesByRouteId.get(route.id);
3403
+ const strictParams = existingMatch?._strictParams ?? usedParams;
3404
+ let paramsError = void 0;
3405
+ if (!existingMatch) {
3406
+ try {
3407
+ extractStrictParams(route, usedParams, parsedParams, strictParams);
3408
+ } catch (err) {
3409
+ if (isNotFound(err) || isRedirect(err)) {
3410
+ paramsError = err;
3411
+ } else {
3412
+ paramsError = new PathParamError(err.message, {
3413
+ cause: err
3414
+ });
3415
+ }
3416
+ if (opts?.throwOnError) {
3417
+ throw paramsError;
3418
+ }
3419
+ }
3420
+ }
3421
+ Object.assign(routeParams, strictParams);
3422
+ const cause = previousMatch ? "stay" : "enter";
3423
+ let match;
3424
+ if (existingMatch) {
3425
+ match = {
3426
+ ...existingMatch,
3427
+ cause,
3428
+ params: previousMatch?.params ?? routeParams,
3429
+ _strictParams: strictParams,
3430
+ search: previousMatch ? replaceEqualDeep(previousMatch.search, preMatchSearch) : replaceEqualDeep(existingMatch.search, preMatchSearch),
3431
+ _strictSearch: strictMatchSearch
3432
+ };
3433
+ } else {
3434
+ const status = route.options.loader || route.options.beforeLoad || route.lazyFn || routeNeedsPreload(route) ? "pending" : "success";
3435
+ match = {
3436
+ id: matchId,
3437
+ ssr: void 0,
3438
+ index,
3439
+ routeId: route.id,
3440
+ params: previousMatch?.params ?? routeParams,
3441
+ _strictParams: strictParams,
3442
+ pathname: interpolatedPath,
3443
+ updatedAt: Date.now(),
3444
+ search: previousMatch ? replaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
3445
+ _strictSearch: strictMatchSearch,
3446
+ searchError: void 0,
3447
+ status,
3448
+ isFetching: false,
3449
+ error: void 0,
3450
+ paramsError,
3451
+ __routeContext: void 0,
3452
+ _nonReactive: {
3453
+ loadPromise: createControlledPromise()
3454
+ },
3455
+ __beforeLoadContext: void 0,
3456
+ context: {},
3457
+ abortController: new AbortController(),
3458
+ fetchCount: 0,
3459
+ cause,
3460
+ loaderDeps: previousMatch ? replaceEqualDeep(previousMatch.loaderDeps, loaderDeps) : loaderDeps,
3461
+ invalid: false,
3462
+ preload: false,
3463
+ links: void 0,
3464
+ scripts: void 0,
3465
+ headScripts: void 0,
3466
+ meta: void 0,
3467
+ staticData: route.options.staticData || {},
3468
+ fullPath: route.fullPath
3469
+ };
3470
+ }
3471
+ if (!opts?.preload) {
3472
+ match.globalNotFound = globalNotFoundRouteId === route.id;
3473
+ }
3474
+ match.searchError = searchError;
3475
+ const parentContext = this.getParentContext(parentMatch);
3476
+ match.context = {
3477
+ ...parentContext,
3478
+ ...match.__routeContext,
3479
+ ...match.__beforeLoadContext
3480
+ };
3481
+ matches[index] = match;
3482
+ }
3483
+ for (let index = 0; index < matches.length; index++) {
3484
+ const match = matches[index];
3485
+ const route = this.looseRoutesById[match.routeId];
3486
+ const existingMatch = this.getMatch(match.id);
3487
+ const previousMatch = previousMatchesByRouteId.get(match.routeId);
3488
+ match.params = previousMatch ? replaceEqualDeep(previousMatch.params, routeParams) : routeParams;
3489
+ if (!existingMatch) {
3490
+ const parentMatch = matches[index - 1];
3491
+ const parentContext = this.getParentContext(parentMatch);
3492
+ if (route.options.context) {
3493
+ const contextFnContext = {
3494
+ deps: match.loaderDeps,
3495
+ params: match.params,
3496
+ context: parentContext ?? {},
3497
+ location: next,
3498
+ navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
3499
+ buildLocation: this.buildLocation,
3500
+ cause: match.cause,
3501
+ abortController: match.abortController,
3502
+ preload: !!match.preload,
3503
+ matches,
3504
+ routeId: route.id
3505
+ };
3506
+ match.__routeContext = route.options.context(contextFnContext) ?? void 0;
3507
+ }
3508
+ match.context = {
3509
+ ...parentContext,
3510
+ ...match.__routeContext,
3511
+ ...match.__beforeLoadContext
3512
+ };
3513
+ }
3514
+ }
3515
+ return matches;
3516
+ }
3517
+ /**
3518
+ * Lightweight route matching for buildLocation.
3519
+ * Only computes fullPath, accumulated search, and params - skipping expensive
3520
+ * operations like AbortController, ControlledPromise, loaderDeps, and full match objects.
3521
+ */
3522
+ matchRoutesLightweight(location) {
3523
+ const { matchedRoutes, routeParams, parsedParams } = this.getMatchedRoutes(
3524
+ location.pathname
3525
+ );
3526
+ const lastRoute = last(matchedRoutes);
3527
+ const accumulatedSearch = { ...location.search };
3528
+ for (const route of matchedRoutes) {
3529
+ try {
3530
+ Object.assign(
3531
+ accumulatedSearch,
3532
+ validateSearch(route.options.validateSearch, accumulatedSearch)
3533
+ );
3534
+ } catch {
3535
+ }
3536
+ }
3537
+ const lastStateMatch = last(this.state.matches);
3538
+ const canReuseParams = lastStateMatch && lastStateMatch.routeId === lastRoute.id && location.pathname === this.state.location.pathname;
3539
+ let params;
3540
+ if (canReuseParams) {
3541
+ params = lastStateMatch.params;
3542
+ } else {
3543
+ const strictParams = { ...routeParams };
3544
+ for (const route of matchedRoutes) {
3545
+ try {
3546
+ extractStrictParams(
3547
+ route,
3548
+ routeParams,
3549
+ parsedParams ?? {},
3550
+ strictParams
3551
+ );
3552
+ } catch {
3553
+ }
3554
+ }
3555
+ params = strictParams;
3556
+ }
3557
+ return {
3558
+ matchedRoutes,
3559
+ fullPath: lastRoute.fullPath,
3560
+ search: accumulatedSearch,
3561
+ params
3562
+ };
3563
+ }
3564
+ }
3565
+ class SearchParamError extends Error {
3566
+ }
3567
+ class PathParamError extends Error {
3568
+ }
3569
+ function getInitialRouterState(location) {
3570
+ return {
3571
+ loadedAt: 0,
3572
+ isLoading: false,
3573
+ isTransitioning: false,
3574
+ status: "idle",
3575
+ resolvedLocation: void 0,
3576
+ location,
3577
+ matches: [],
3578
+ pendingMatches: [],
3579
+ cachedMatches: [],
3580
+ statusCode: 200
3581
+ };
3582
+ }
3583
+ function validateSearch(validateSearch2, input) {
3584
+ if (validateSearch2 == null) return {};
3585
+ if ("~standard" in validateSearch2) {
3586
+ const result = validateSearch2["~standard"].validate(input);
3587
+ if (result instanceof Promise)
3588
+ throw new SearchParamError("Async validation not supported");
3589
+ if (result.issues)
3590
+ throw new SearchParamError(JSON.stringify(result.issues, void 0, 2), {
3591
+ cause: result
3592
+ });
3593
+ return result.value;
3594
+ }
3595
+ if ("parse" in validateSearch2) {
3596
+ return validateSearch2.parse(input);
3597
+ }
3598
+ if (typeof validateSearch2 === "function") {
3599
+ return validateSearch2(input);
3600
+ }
3601
+ return {};
3602
+ }
3603
+ function getMatchedRoutes({
3604
+ pathname,
3605
+ routesById,
3606
+ processedTree
3607
+ }) {
3608
+ const routeParams = {};
3609
+ const trimmedPath = trimPathRight(pathname);
3610
+ let foundRoute = void 0;
3611
+ let parsedParams = void 0;
3612
+ const match = findRouteMatch(trimmedPath, processedTree, true);
3613
+ if (match) {
3614
+ foundRoute = match.route;
3615
+ Object.assign(routeParams, match.rawParams);
3616
+ parsedParams = Object.assign({}, match.parsedParams);
3617
+ }
3618
+ const matchedRoutes = match?.branch || [routesById[rootRouteId]];
3619
+ return { matchedRoutes, routeParams, foundRoute, parsedParams };
3620
+ }
3621
+ function applySearchMiddleware({
3622
+ search,
3623
+ dest,
3624
+ destRoutes,
3625
+ _includeValidateSearch
3626
+ }) {
3627
+ const middleware = buildMiddlewareChain(destRoutes);
3628
+ return middleware(search, dest, _includeValidateSearch ?? false);
3629
+ }
3630
+ function buildMiddlewareChain(destRoutes) {
3631
+ const context = {
3632
+ dest: null,
3633
+ _includeValidateSearch: false,
3634
+ middlewares: []
3635
+ };
3636
+ for (const route of destRoutes) {
3637
+ if ("search" in route.options) {
3638
+ if (route.options.search?.middlewares) {
3639
+ context.middlewares.push(...route.options.search.middlewares);
3640
+ }
3641
+ } else if (route.options.preSearchFilters || route.options.postSearchFilters) {
3642
+ const legacyMiddleware = ({ search, next }) => {
3643
+ let nextSearch = search;
3644
+ if ("preSearchFilters" in route.options && route.options.preSearchFilters) {
3645
+ nextSearch = route.options.preSearchFilters.reduce(
3646
+ (prev, next2) => next2(prev),
3647
+ search
3648
+ );
3649
+ }
3650
+ const result = next(nextSearch);
3651
+ if ("postSearchFilters" in route.options && route.options.postSearchFilters) {
3652
+ return route.options.postSearchFilters.reduce(
3653
+ (prev, next2) => next2(prev),
3654
+ result
3655
+ );
3656
+ }
3657
+ return result;
3658
+ };
3659
+ context.middlewares.push(legacyMiddleware);
3660
+ }
3661
+ if (route.options.validateSearch) {
3662
+ const validate = ({ search, next }) => {
3663
+ const result = next(search);
3664
+ if (!context._includeValidateSearch) return result;
3665
+ try {
3666
+ const validatedSearch = {
3667
+ ...result,
3668
+ ...validateSearch(route.options.validateSearch, result) ?? void 0
3669
+ };
3670
+ return validatedSearch;
3671
+ } catch {
3672
+ return result;
3673
+ }
3674
+ };
3675
+ context.middlewares.push(validate);
3676
+ }
3677
+ }
3678
+ const final = ({ search }) => {
3679
+ const dest = context.dest;
3680
+ if (!dest.search) {
3681
+ return {};
3682
+ }
3683
+ if (dest.search === true) {
3684
+ return search;
3685
+ }
3686
+ return functionalUpdate(dest.search, search);
3687
+ };
3688
+ context.middlewares.push(final);
3689
+ const applyNext = (index, currentSearch, middlewares) => {
3690
+ if (index >= middlewares.length) {
3691
+ return currentSearch;
3692
+ }
3693
+ const middleware = middlewares[index];
3694
+ const next = (newSearch) => {
3695
+ return applyNext(index + 1, newSearch, middlewares);
3696
+ };
3697
+ return middleware({ search: currentSearch, next });
3698
+ };
3699
+ return function middleware(search, dest, _includeValidateSearch) {
3700
+ context.dest = dest;
3701
+ context._includeValidateSearch = _includeValidateSearch;
3702
+ return applyNext(0, search, context.middlewares);
3703
+ };
3704
+ }
3705
+ function findGlobalNotFoundRouteId(notFoundMode, routes) {
3706
+ if (notFoundMode !== "root") {
3707
+ for (let i = routes.length - 1; i >= 0; i--) {
3708
+ const route = routes[i];
3709
+ if (route.children) {
3710
+ return route.id;
3711
+ }
3712
+ }
3713
+ }
3714
+ return rootRouteId;
3715
+ }
3716
+ function extractStrictParams(route, referenceParams, parsedParams, accumulatedParams) {
3717
+ const parseParams = route.options.params?.parse ?? route.options.parseParams;
3718
+ if (parseParams) {
3719
+ if (route.options.skipRouteOnParseError) {
3720
+ for (const key in referenceParams) {
3721
+ if (key in parsedParams) {
3722
+ accumulatedParams[key] = parsedParams[key];
3723
+ }
3724
+ }
3725
+ } else {
3726
+ const result = parseParams(accumulatedParams);
3727
+ Object.assign(accumulatedParams, result);
3728
+ }
3729
+ }
3730
+ }
3731
+ class BaseRoute {
3732
+ constructor(options) {
3733
+ this.init = (opts) => {
3734
+ this.originalIndex = opts.originalIndex;
3735
+ const options2 = this.options;
3736
+ const isRoot = !options2?.path && !options2?.id;
3737
+ this.parentRoute = this.options.getParentRoute?.();
3738
+ if (isRoot) {
3739
+ this._path = rootRouteId;
3740
+ } else if (!this.parentRoute) {
3741
+ invariant(
3742
+ false
3743
+ );
3744
+ }
3745
+ let path = isRoot ? rootRouteId : options2?.path;
3746
+ if (path && path !== "/") {
3747
+ path = trimPathLeft(path);
3748
+ }
3749
+ const customId = options2?.id || path;
3750
+ let id = isRoot ? rootRouteId : joinPaths([
3751
+ this.parentRoute.id === rootRouteId ? "" : this.parentRoute.id,
3752
+ customId
3753
+ ]);
3754
+ if (path === rootRouteId) {
3755
+ path = "/";
3756
+ }
3757
+ if (id !== rootRouteId) {
3758
+ id = joinPaths(["/", id]);
3759
+ }
3760
+ const fullPath = id === rootRouteId ? "/" : joinPaths([this.parentRoute.fullPath, path]);
3761
+ this._path = path;
3762
+ this._id = id;
3763
+ this._fullPath = fullPath;
3764
+ this._to = trimPathRight(fullPath);
3765
+ };
3766
+ this.addChildren = (children) => {
3767
+ return this._addFileChildren(children);
3768
+ };
3769
+ this._addFileChildren = (children) => {
3770
+ if (Array.isArray(children)) {
3771
+ this.children = children;
3772
+ }
3773
+ if (typeof children === "object" && children !== null) {
3774
+ this.children = Object.values(children);
3775
+ }
3776
+ return this;
3777
+ };
3778
+ this._addFileTypes = () => {
3779
+ return this;
3780
+ };
3781
+ this.updateLoader = (options2) => {
3782
+ Object.assign(this.options, options2);
3783
+ return this;
3784
+ };
3785
+ this.update = (options2) => {
3786
+ Object.assign(this.options, options2);
3787
+ return this;
3788
+ };
3789
+ this.lazy = (lazyFn) => {
3790
+ this.lazyFn = lazyFn;
3791
+ return this;
3792
+ };
3793
+ this.redirect = (opts) => redirect({ from: this.fullPath, ...opts });
3794
+ this.options = options || {};
3795
+ this.isRoot = !options?.getParentRoute;
3796
+ if (options?.id && options?.path) {
3797
+ throw new Error(`Route cannot have both an 'id' and a 'path' option.`);
3798
+ }
3799
+ }
3800
+ get to() {
3801
+ return this._to;
3802
+ }
3803
+ get id() {
3804
+ return this._id;
3805
+ }
3806
+ get path() {
3807
+ return this._path;
3808
+ }
3809
+ get fullPath() {
3810
+ return this._fullPath;
3811
+ }
3812
+ }
3813
+ class BaseRootRoute extends BaseRoute {
3814
+ constructor(options) {
3815
+ super(options);
3816
+ }
3817
+ }
3818
+ const GLOBAL_TSR = "$_TSR";
3819
+ const TSR_SCRIPT_BARRIER_ID = "$tsr-stream-barrier";
3820
+ function createSerializationAdapter(opts) {
3821
+ return opts;
3822
+ }
3823
+ function makeSsrSerovalPlugin(serializationAdapter, options) {
3824
+ return ni({
3825
+ tag: "$TSR/t/" + serializationAdapter.key,
3826
+ test: serializationAdapter.test,
3827
+ parse: {
3828
+ stream(value, ctx) {
3829
+ return ctx.parse(serializationAdapter.toSerializable(value));
3830
+ }
3831
+ },
3832
+ serialize(node, ctx) {
3833
+ options.didRun = true;
3834
+ return GLOBAL_TSR + '.t.get("' + serializationAdapter.key + '")(' + ctx.serialize(node) + ")";
3835
+ },
3836
+ // we never deserialize on the server during SSR
3837
+ deserialize: void 0
3838
+ });
3839
+ }
3840
+ function makeSerovalPlugin(serializationAdapter) {
3841
+ return ni({
3842
+ tag: "$TSR/t/" + serializationAdapter.key,
3843
+ test: serializationAdapter.test,
3844
+ parse: {
3845
+ sync(value, ctx) {
3846
+ return ctx.parse(serializationAdapter.toSerializable(value));
3847
+ },
3848
+ async async(value, ctx) {
3849
+ return await ctx.parse(serializationAdapter.toSerializable(value));
3850
+ },
3851
+ stream(value, ctx) {
3852
+ return ctx.parse(serializationAdapter.toSerializable(value));
3853
+ }
3854
+ },
3855
+ // we don't generate JS code outside of SSR (for now)
3856
+ serialize: void 0,
3857
+ deserialize(node, ctx) {
3858
+ return serializationAdapter.fromSerializable(ctx.deserialize(node));
3859
+ }
3860
+ });
3861
+ }
3862
+ const ShallowErrorPlugin = /* @__PURE__ */ ni({
3863
+ tag: "$TSR/Error",
3864
+ test(value) {
3865
+ return value instanceof Error;
3866
+ },
3867
+ parse: {
3868
+ sync(value, ctx) {
3869
+ return {
3870
+ message: ctx.parse(value.message)
3871
+ };
3872
+ },
3873
+ async async(value, ctx) {
3874
+ return {
3875
+ message: await ctx.parse(value.message)
3876
+ };
3877
+ },
3878
+ stream(value, ctx) {
3879
+ return {
3880
+ message: ctx.parse(value.message)
3881
+ };
3882
+ }
3883
+ },
3884
+ serialize(node, ctx) {
3885
+ return "new Error(" + ctx.serialize(node.message) + ")";
3886
+ },
3887
+ deserialize(node, ctx) {
3888
+ return new Error(ctx.deserialize(node.message));
3889
+ }
3890
+ });
3891
+ class RawStream {
3892
+ constructor(stream, options) {
3893
+ this.stream = stream;
3894
+ this.hint = options?.hint ?? "binary";
3895
+ }
3896
+ }
3897
+ const BufferCtor = globalThis.Buffer;
3898
+ const hasNodeBuffer = !!BufferCtor && typeof BufferCtor.from === "function";
3899
+ function uint8ArrayToBase64(bytes) {
3900
+ if (bytes.length === 0) return "";
3901
+ if (hasNodeBuffer) {
3902
+ return BufferCtor.from(bytes).toString("base64");
3903
+ }
3904
+ const CHUNK_SIZE = 32768;
3905
+ const chunks = [];
3906
+ for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {
3907
+ const chunk = bytes.subarray(i, i + CHUNK_SIZE);
3908
+ chunks.push(String.fromCharCode.apply(null, chunk));
3909
+ }
3910
+ return btoa(chunks.join(""));
3911
+ }
3912
+ function base64ToUint8Array(base64) {
3913
+ if (base64.length === 0) return new Uint8Array(0);
3914
+ if (hasNodeBuffer) {
3915
+ const buf = BufferCtor.from(base64, "base64");
3916
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
3917
+ }
3918
+ const binary = atob(base64);
3919
+ const bytes = new Uint8Array(binary.length);
3920
+ for (let i = 0; i < binary.length; i++) {
3921
+ bytes[i] = binary.charCodeAt(i);
3922
+ }
3923
+ return bytes;
3924
+ }
3925
+ const RAW_STREAM_FACTORY_BINARY = /* @__PURE__ */ Object.create(null);
3926
+ const RAW_STREAM_FACTORY_TEXT = /* @__PURE__ */ Object.create(null);
3927
+ const RAW_STREAM_FACTORY_CONSTRUCTOR_BINARY = (stream) => new ReadableStream({
3928
+ start(controller) {
3929
+ stream.on({
3930
+ next(base64) {
3931
+ try {
3932
+ controller.enqueue(base64ToUint8Array(base64));
3933
+ } catch {
3934
+ }
3935
+ },
3936
+ throw(error) {
3937
+ controller.error(error);
3938
+ },
3939
+ return() {
3940
+ try {
3941
+ controller.close();
3942
+ } catch {
3943
+ }
3944
+ }
3945
+ });
3946
+ }
3947
+ });
3948
+ const textEncoderForFactory = new TextEncoder();
3949
+ const RAW_STREAM_FACTORY_CONSTRUCTOR_TEXT = (stream) => {
3950
+ return new ReadableStream({
3951
+ start(controller) {
3952
+ stream.on({
3953
+ next(value) {
3954
+ try {
3955
+ if (typeof value === "string") {
3956
+ controller.enqueue(textEncoderForFactory.encode(value));
3957
+ } else {
3958
+ controller.enqueue(base64ToUint8Array(value.$b64));
3959
+ }
3960
+ } catch {
3961
+ }
3962
+ },
3963
+ throw(error) {
3964
+ controller.error(error);
3965
+ },
3966
+ return() {
3967
+ try {
3968
+ controller.close();
3969
+ } catch {
3970
+ }
3971
+ }
3972
+ });
3973
+ }
3974
+ });
3975
+ };
3976
+ const FACTORY_BINARY = `(s=>new ReadableStream({start(c){s.on({next(b){try{const d=atob(b),a=new Uint8Array(d.length);for(let i=0;i<d.length;i++)a[i]=d.charCodeAt(i);c.enqueue(a)}catch(_){}},throw(e){c.error(e)},return(){try{c.close()}catch(_){}}})}}))`;
3977
+ const FACTORY_TEXT = `(s=>{const e=new TextEncoder();return new ReadableStream({start(c){s.on({next(v){try{if(typeof v==='string'){c.enqueue(e.encode(v))}else{const d=atob(v.$b64),a=new Uint8Array(d.length);for(let i=0;i<d.length;i++)a[i]=d.charCodeAt(i);c.enqueue(a)}}catch(_){}},throw(x){c.error(x)},return(){try{c.close()}catch(_){}}})}})})`;
3978
+ function toBinaryStream(readable) {
3979
+ const stream = te();
3980
+ const reader = readable.getReader();
3981
+ (async () => {
3982
+ try {
3983
+ while (true) {
3984
+ const { done, value } = await reader.read();
3985
+ if (done) {
3986
+ stream.return(void 0);
3987
+ break;
3988
+ }
3989
+ stream.next(uint8ArrayToBase64(value));
3990
+ }
3991
+ } catch (error) {
3992
+ stream.throw(error);
3993
+ } finally {
3994
+ reader.releaseLock();
3995
+ }
3996
+ })();
3997
+ return stream;
3998
+ }
3999
+ function toTextStream(readable) {
4000
+ const stream = te();
4001
+ const reader = readable.getReader();
4002
+ const decoder = new TextDecoder("utf-8", { fatal: true });
4003
+ (async () => {
4004
+ try {
4005
+ while (true) {
4006
+ const { done, value } = await reader.read();
4007
+ if (done) {
4008
+ try {
4009
+ const remaining = decoder.decode();
4010
+ if (remaining.length > 0) {
4011
+ stream.next(remaining);
4012
+ }
4013
+ } catch {
4014
+ }
4015
+ stream.return(void 0);
4016
+ break;
4017
+ }
4018
+ try {
4019
+ const text = decoder.decode(value, { stream: true });
4020
+ if (text.length > 0) {
4021
+ stream.next(text);
4022
+ }
4023
+ } catch {
4024
+ stream.next({ $b64: uint8ArrayToBase64(value) });
4025
+ }
4026
+ }
4027
+ } catch (error) {
4028
+ stream.throw(error);
4029
+ } finally {
4030
+ reader.releaseLock();
4031
+ }
4032
+ })();
4033
+ return stream;
4034
+ }
4035
+ const RawStreamFactoryBinaryPlugin = ni({
4036
+ tag: "tss/RawStreamFactory",
4037
+ test(value) {
4038
+ return value === RAW_STREAM_FACTORY_BINARY;
4039
+ },
4040
+ parse: {
4041
+ sync() {
4042
+ return void 0;
4043
+ },
4044
+ async() {
4045
+ return Promise.resolve(void 0);
4046
+ },
4047
+ stream() {
4048
+ return void 0;
4049
+ }
4050
+ },
4051
+ serialize() {
4052
+ return FACTORY_BINARY;
4053
+ },
4054
+ deserialize() {
4055
+ return RAW_STREAM_FACTORY_BINARY;
4056
+ }
4057
+ });
4058
+ const RawStreamFactoryTextPlugin = ni({
4059
+ tag: "tss/RawStreamFactoryText",
4060
+ test(value) {
4061
+ return value === RAW_STREAM_FACTORY_TEXT;
4062
+ },
4063
+ parse: {
4064
+ sync() {
4065
+ return void 0;
4066
+ },
4067
+ async() {
4068
+ return Promise.resolve(void 0);
4069
+ },
4070
+ stream() {
4071
+ return void 0;
4072
+ }
4073
+ },
4074
+ serialize() {
4075
+ return FACTORY_TEXT;
4076
+ },
4077
+ deserialize() {
4078
+ return RAW_STREAM_FACTORY_TEXT;
4079
+ }
4080
+ });
4081
+ const RawStreamSSRPlugin = ni({
4082
+ tag: "tss/RawStream",
4083
+ extends: [RawStreamFactoryBinaryPlugin, RawStreamFactoryTextPlugin],
4084
+ test(value) {
4085
+ return value instanceof RawStream;
4086
+ },
4087
+ parse: {
4088
+ sync(value, ctx) {
4089
+ const factory = value.hint === "text" ? RAW_STREAM_FACTORY_TEXT : RAW_STREAM_FACTORY_BINARY;
4090
+ return {
4091
+ hint: value.hint,
4092
+ factory: ctx.parse(factory),
4093
+ stream: ctx.parse(te())
4094
+ };
4095
+ },
4096
+ async async(value, ctx) {
4097
+ const factory = value.hint === "text" ? RAW_STREAM_FACTORY_TEXT : RAW_STREAM_FACTORY_BINARY;
4098
+ const encodedStream = value.hint === "text" ? toTextStream(value.stream) : toBinaryStream(value.stream);
4099
+ return {
4100
+ hint: value.hint,
4101
+ factory: await ctx.parse(factory),
4102
+ stream: await ctx.parse(encodedStream)
4103
+ };
4104
+ },
4105
+ stream(value, ctx) {
4106
+ const factory = value.hint === "text" ? RAW_STREAM_FACTORY_TEXT : RAW_STREAM_FACTORY_BINARY;
4107
+ const encodedStream = value.hint === "text" ? toTextStream(value.stream) : toBinaryStream(value.stream);
4108
+ return {
4109
+ hint: value.hint,
4110
+ factory: ctx.parse(factory),
4111
+ stream: ctx.parse(encodedStream)
4112
+ };
4113
+ }
4114
+ },
4115
+ serialize(node, ctx) {
4116
+ return "(" + ctx.serialize(node.factory) + ")(" + ctx.serialize(node.stream) + ")";
4117
+ },
4118
+ deserialize(node, ctx) {
4119
+ const stream = ctx.deserialize(node.stream);
4120
+ return node.hint === "text" ? RAW_STREAM_FACTORY_CONSTRUCTOR_TEXT(stream) : RAW_STREAM_FACTORY_CONSTRUCTOR_BINARY(stream);
4121
+ }
4122
+ });
4123
+ function createRawStreamRPCPlugin(onRawStream) {
4124
+ let nextStreamId = 1;
4125
+ return ni({
4126
+ tag: "tss/RawStream",
4127
+ test(value) {
4128
+ return value instanceof RawStream;
4129
+ },
4130
+ parse: {
4131
+ async(value) {
4132
+ const streamId = nextStreamId++;
4133
+ onRawStream(streamId, value.stream);
4134
+ return Promise.resolve({ streamId });
4135
+ },
4136
+ stream(value) {
4137
+ const streamId = nextStreamId++;
4138
+ onRawStream(streamId, value.stream);
4139
+ return { streamId };
4140
+ }
4141
+ },
4142
+ serialize() {
4143
+ throw new Error(
4144
+ "RawStreamRPCPlugin.serialize should not be called. RPC uses JSON serialization, not JS code generation."
4145
+ );
4146
+ },
4147
+ deserialize() {
4148
+ throw new Error(
4149
+ "RawStreamRPCPlugin.deserialize should not be called. Use createRawStreamDeserializePlugin on client."
4150
+ );
4151
+ }
4152
+ });
4153
+ }
4154
+ const defaultSerovalPlugins = [
4155
+ ShallowErrorPlugin,
4156
+ // RawStreamSSRPlugin must come before ReadableStreamPlugin to match first
4157
+ RawStreamSSRPlugin,
4158
+ // ReadableStreamNode is not exported by seroval
4159
+ p
4160
+ ];
4161
+ const minifiedTsrBootStrapScript = "self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]};\n";
4162
+ const SCOPE_ID = "tsr";
4163
+ const TSR_PREFIX = GLOBAL_TSR + ".router=";
4164
+ const P_PREFIX = GLOBAL_TSR + ".p(()=>";
4165
+ const P_SUFFIX = ")";
4166
+ function dehydrateMatch(match) {
4167
+ const dehydratedMatch = {
4168
+ i: match.id,
4169
+ u: match.updatedAt,
4170
+ s: match.status
4171
+ };
4172
+ const properties = [
4173
+ ["__beforeLoadContext", "b"],
4174
+ ["loaderData", "l"],
4175
+ ["error", "e"],
4176
+ ["ssr", "ssr"]
4177
+ ];
4178
+ for (const [key, shorthand] of properties) {
4179
+ if (match[key] !== void 0) {
4180
+ dehydratedMatch[shorthand] = match[key];
4181
+ }
4182
+ }
4183
+ return dehydratedMatch;
4184
+ }
4185
+ const INITIAL_SCRIPTS = [
4186
+ mn(SCOPE_ID),
4187
+ minifiedTsrBootStrapScript
4188
+ ];
4189
+ class ScriptBuffer {
4190
+ constructor(router) {
4191
+ this._scriptBarrierLifted = false;
4192
+ this._cleanedUp = false;
4193
+ this._pendingMicrotask = false;
4194
+ this.router = router;
4195
+ this._queue = INITIAL_SCRIPTS.slice();
4196
+ }
4197
+ enqueue(script) {
4198
+ if (this._cleanedUp) return;
4199
+ this._queue.push(script);
4200
+ if (this._scriptBarrierLifted && !this._pendingMicrotask) {
4201
+ this._pendingMicrotask = true;
4202
+ queueMicrotask(() => {
4203
+ this._pendingMicrotask = false;
4204
+ this.injectBufferedScripts();
4205
+ });
4206
+ }
4207
+ }
4208
+ liftBarrier() {
4209
+ if (this._scriptBarrierLifted || this._cleanedUp) return;
4210
+ this._scriptBarrierLifted = true;
4211
+ if (this._queue.length > 0 && !this._pendingMicrotask) {
4212
+ this._pendingMicrotask = true;
4213
+ queueMicrotask(() => {
4214
+ this._pendingMicrotask = false;
4215
+ this.injectBufferedScripts();
4216
+ });
4217
+ }
4218
+ }
4219
+ /**
4220
+ * Flushes any pending scripts synchronously.
4221
+ * Call this before emitting onSerializationFinished to ensure all scripts are injected.
4222
+ *
4223
+ * IMPORTANT: Only injects if the barrier has been lifted. Before the barrier is lifted,
4224
+ * scripts should remain in the queue so takeBufferedScripts() can retrieve them
4225
+ */
4226
+ flush() {
4227
+ if (!this._scriptBarrierLifted) return;
4228
+ if (this._cleanedUp) return;
4229
+ this._pendingMicrotask = false;
4230
+ const scriptsToInject = this.takeAll();
4231
+ if (scriptsToInject && this.router?.serverSsr) {
4232
+ this.router.serverSsr.injectScript(scriptsToInject);
4233
+ }
4234
+ }
4235
+ takeAll() {
4236
+ const bufferedScripts = this._queue;
4237
+ this._queue = [];
4238
+ if (bufferedScripts.length === 0) {
4239
+ return void 0;
4240
+ }
4241
+ if (bufferedScripts.length === 1) {
4242
+ return bufferedScripts[0] + ";document.currentScript.remove()";
4243
+ }
4244
+ return bufferedScripts.join(";") + ";document.currentScript.remove()";
4245
+ }
4246
+ injectBufferedScripts() {
4247
+ if (this._cleanedUp) return;
4248
+ if (this._queue.length === 0) return;
4249
+ const scriptsToInject = this.takeAll();
4250
+ if (scriptsToInject && this.router?.serverSsr) {
4251
+ this.router.serverSsr.injectScript(scriptsToInject);
4252
+ }
4253
+ }
4254
+ cleanup() {
4255
+ this._cleanedUp = true;
4256
+ this._queue = [];
4257
+ this.router = void 0;
4258
+ }
4259
+ }
4260
+ const MANIFEST_CACHE_SIZE = 100;
4261
+ const manifestCaches = /* @__PURE__ */ new WeakMap();
4262
+ function getManifestCache(manifest) {
4263
+ const cache = manifestCaches.get(manifest);
4264
+ if (cache) return cache;
4265
+ const newCache = createLRUCache(MANIFEST_CACHE_SIZE);
4266
+ manifestCaches.set(manifest, newCache);
4267
+ return newCache;
4268
+ }
4269
+ function attachRouterServerSsrUtils({
4270
+ router,
4271
+ manifest
4272
+ }) {
4273
+ router.ssr = {
4274
+ manifest
4275
+ };
4276
+ let _dehydrated = false;
4277
+ let _serializationFinished = false;
4278
+ const renderFinishedListeners = [];
4279
+ const serializationFinishedListeners = [];
4280
+ const scriptBuffer = new ScriptBuffer(router);
4281
+ let injectedHtmlBuffer = "";
4282
+ router.serverSsr = {
4283
+ injectHtml: (html) => {
4284
+ if (!html) return;
4285
+ injectedHtmlBuffer += html;
4286
+ router.emit({
4287
+ type: "onInjectedHtml"
4288
+ });
4289
+ },
4290
+ injectScript: (script) => {
4291
+ if (!script) return;
4292
+ const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ""}>${script}<\/script>`;
4293
+ router.serverSsr.injectHtml(html);
4294
+ },
4295
+ dehydrate: async () => {
4296
+ invariant(!_dehydrated);
4297
+ let matchesToDehydrate = router.state.matches;
4298
+ if (router.isShell()) {
4299
+ matchesToDehydrate = matchesToDehydrate.slice(0, 1);
4300
+ }
4301
+ const matches = matchesToDehydrate.map(dehydrateMatch);
4302
+ let manifestToDehydrate = void 0;
4303
+ if (manifest) {
4304
+ const currentRouteIdsList = matchesToDehydrate.map((m) => m.routeId);
4305
+ const manifestCacheKey = currentRouteIdsList.join("\0");
4306
+ let filteredRoutes;
4307
+ {
4308
+ filteredRoutes = getManifestCache(manifest).get(manifestCacheKey);
4309
+ }
4310
+ if (!filteredRoutes) {
4311
+ const currentRouteIds = new Set(currentRouteIdsList);
4312
+ const nextFilteredRoutes = {};
4313
+ for (const routeId in manifest.routes) {
4314
+ const routeManifest = manifest.routes[routeId];
4315
+ if (currentRouteIds.has(routeId)) {
4316
+ nextFilteredRoutes[routeId] = routeManifest;
4317
+ } else if (routeManifest.assets && routeManifest.assets.length > 0) {
4318
+ nextFilteredRoutes[routeId] = {
4319
+ assets: routeManifest.assets
4320
+ };
4321
+ }
4322
+ }
4323
+ {
4324
+ getManifestCache(manifest).set(manifestCacheKey, nextFilteredRoutes);
4325
+ }
4326
+ filteredRoutes = nextFilteredRoutes;
4327
+ }
4328
+ manifestToDehydrate = {
4329
+ routes: filteredRoutes
4330
+ };
4331
+ }
4332
+ const dehydratedRouter = {
4333
+ manifest: manifestToDehydrate,
4334
+ matches
4335
+ };
4336
+ const lastMatchId = matchesToDehydrate[matchesToDehydrate.length - 1]?.id;
4337
+ if (lastMatchId) {
4338
+ dehydratedRouter.lastMatchId = lastMatchId;
4339
+ }
4340
+ const dehydratedData = await router.options.dehydrate?.();
4341
+ if (dehydratedData) {
4342
+ dehydratedRouter.dehydratedData = dehydratedData;
4343
+ }
4344
+ _dehydrated = true;
4345
+ const trackPlugins = { didRun: false };
4346
+ const serializationAdapters = router.options.serializationAdapters;
4347
+ const plugins = serializationAdapters ? serializationAdapters.map((t) => makeSsrSerovalPlugin(t, trackPlugins)).concat(defaultSerovalPlugins) : defaultSerovalPlugins;
4348
+ const signalSerializationComplete = () => {
4349
+ _serializationFinished = true;
4350
+ try {
4351
+ serializationFinishedListeners.forEach((l) => l());
4352
+ router.emit({ type: "onSerializationFinished" });
4353
+ } catch (err) {
4354
+ console.error("Serialization listener error:", err);
4355
+ } finally {
4356
+ serializationFinishedListeners.length = 0;
4357
+ renderFinishedListeners.length = 0;
4358
+ }
4359
+ };
4360
+ cn(dehydratedRouter, {
4361
+ refs: /* @__PURE__ */ new Map(),
4362
+ plugins,
4363
+ onSerialize: (data, initial) => {
4364
+ let serialized = initial ? TSR_PREFIX + data : data;
4365
+ if (trackPlugins.didRun) {
4366
+ serialized = P_PREFIX + serialized + P_SUFFIX;
4367
+ }
4368
+ scriptBuffer.enqueue(serialized);
4369
+ },
4370
+ scopeId: SCOPE_ID,
4371
+ onDone: () => {
4372
+ scriptBuffer.enqueue(GLOBAL_TSR + ".e()");
4373
+ scriptBuffer.flush();
4374
+ signalSerializationComplete();
4375
+ },
4376
+ onError: (err) => {
4377
+ console.error("Serialization error:", err);
4378
+ signalSerializationComplete();
4379
+ }
4380
+ });
4381
+ },
4382
+ isDehydrated() {
4383
+ return _dehydrated;
4384
+ },
4385
+ isSerializationFinished() {
4386
+ return _serializationFinished;
4387
+ },
4388
+ onRenderFinished: (listener) => renderFinishedListeners.push(listener),
4389
+ onSerializationFinished: (listener) => serializationFinishedListeners.push(listener),
4390
+ setRenderFinished: () => {
4391
+ try {
4392
+ renderFinishedListeners.forEach((l) => l());
4393
+ } catch (err) {
4394
+ console.error("Error in render finished listener:", err);
4395
+ } finally {
4396
+ renderFinishedListeners.length = 0;
4397
+ }
4398
+ scriptBuffer.liftBarrier();
4399
+ },
4400
+ takeBufferedScripts() {
4401
+ const scripts = scriptBuffer.takeAll();
4402
+ const serverBufferedScript = {
4403
+ tag: "script",
4404
+ attrs: {
4405
+ nonce: router.options.ssr?.nonce,
4406
+ className: "$tsr",
4407
+ id: TSR_SCRIPT_BARRIER_ID
4408
+ },
4409
+ children: scripts
4410
+ };
4411
+ return serverBufferedScript;
4412
+ },
4413
+ liftScriptBarrier() {
4414
+ scriptBuffer.liftBarrier();
4415
+ },
4416
+ takeBufferedHtml() {
4417
+ if (!injectedHtmlBuffer) {
4418
+ return void 0;
4419
+ }
4420
+ const buffered = injectedHtmlBuffer;
4421
+ injectedHtmlBuffer = "";
4422
+ return buffered;
4423
+ },
4424
+ cleanup() {
4425
+ if (!router.serverSsr) return;
4426
+ renderFinishedListeners.length = 0;
4427
+ serializationFinishedListeners.length = 0;
4428
+ injectedHtmlBuffer = "";
4429
+ scriptBuffer.cleanup();
4430
+ router.serverSsr = void 0;
4431
+ }
4432
+ };
4433
+ }
4434
+ function getOrigin(request) {
4435
+ try {
4436
+ return new URL(request.url).origin;
4437
+ } catch {
4438
+ }
4439
+ return "http://localhost";
4440
+ }
4441
+ function getNormalizedURL(url, base) {
4442
+ if (typeof url === "string") url = url.replace("\\", "%5C");
4443
+ const rawUrl = new URL(url, base);
4444
+ const { path: decodedPathname, handledProtocolRelativeURL } = decodePath(
4445
+ rawUrl.pathname
4446
+ );
4447
+ const searchParams = new URLSearchParams(rawUrl.search);
4448
+ const normalizedHref = decodedPathname + (searchParams.size > 0 ? "?" : "") + searchParams.toString() + rawUrl.hash;
4449
+ return {
4450
+ url: new URL(normalizedHref, rawUrl.origin),
4451
+ handledProtocolRelativeURL
4452
+ };
4453
+ }
4454
+ function defineHandlerCallback(handler) {
4455
+ return handler;
4456
+ }
4457
+ function transformReadableStreamWithRouter(router, routerStream) {
4458
+ return transformStreamWithRouter(router, routerStream);
4459
+ }
4460
+ function transformPipeableStreamWithRouter(router, routerStream) {
4461
+ return Readable.fromWeb(
4462
+ transformStreamWithRouter(router, Readable.toWeb(routerStream))
4463
+ );
4464
+ }
4465
+ const BODY_END_TAG = "</body>";
4466
+ const HTML_END_TAG = "</html>";
4467
+ const MIN_CLOSING_TAG_LENGTH = 4;
4468
+ const DEFAULT_SERIALIZATION_TIMEOUT_MS = 6e4;
4469
+ const DEFAULT_LIFETIME_TIMEOUT_MS = 6e4;
4470
+ const textEncoder = new TextEncoder();
4471
+ function findLastClosingTagEnd(str) {
4472
+ const len = str.length;
4473
+ if (len < MIN_CLOSING_TAG_LENGTH) return -1;
4474
+ let i = len - 1;
4475
+ while (i >= MIN_CLOSING_TAG_LENGTH - 1) {
4476
+ if (str.charCodeAt(i) === 62) {
4477
+ let j = i - 1;
4478
+ while (j >= 1) {
4479
+ const code = str.charCodeAt(j);
4480
+ if (code >= 97 && code <= 122 || // a-z
4481
+ code >= 65 && code <= 90 || // A-Z
4482
+ code >= 48 && code <= 57 || // 0-9
4483
+ code === 95 || // _
4484
+ code === 58 || // :
4485
+ code === 46 || // .
4486
+ code === 45) {
4487
+ j--;
4488
+ } else {
4489
+ break;
4490
+ }
4491
+ }
4492
+ const tagNameStart = j + 1;
4493
+ if (tagNameStart < i) {
4494
+ const startCode = str.charCodeAt(tagNameStart);
4495
+ if (startCode >= 97 && startCode <= 122 || startCode >= 65 && startCode <= 90) {
4496
+ if (j >= 1 && str.charCodeAt(j) === 47 && str.charCodeAt(j - 1) === 60) {
4497
+ return i + 1;
4498
+ }
4499
+ }
4500
+ }
4501
+ }
4502
+ i--;
4503
+ }
4504
+ return -1;
4505
+ }
4506
+ function transformStreamWithRouter(router, appStream, opts) {
4507
+ const serializationAlreadyFinished = router.serverSsr?.isSerializationFinished() ?? false;
4508
+ const initialBufferedHtml = router.serverSsr?.takeBufferedHtml();
4509
+ if (serializationAlreadyFinished && !initialBufferedHtml) {
4510
+ let cleanedUp2 = false;
4511
+ let controller2;
4512
+ let isStreamClosed2 = false;
4513
+ let lifetimeTimeoutHandle2;
4514
+ const cleanup2 = () => {
4515
+ if (cleanedUp2) return;
4516
+ cleanedUp2 = true;
4517
+ if (lifetimeTimeoutHandle2 !== void 0) {
4518
+ clearTimeout(lifetimeTimeoutHandle2);
4519
+ lifetimeTimeoutHandle2 = void 0;
4520
+ }
4521
+ router.serverSsr?.cleanup();
4522
+ };
4523
+ const safeClose2 = () => {
4524
+ if (isStreamClosed2) return;
4525
+ isStreamClosed2 = true;
4526
+ try {
4527
+ controller2?.close();
4528
+ } catch {
4529
+ }
4530
+ };
4531
+ const safeError2 = (error) => {
4532
+ if (isStreamClosed2) return;
4533
+ isStreamClosed2 = true;
4534
+ try {
4535
+ controller2?.error(error);
4536
+ } catch {
4537
+ }
4538
+ };
4539
+ const lifetimeMs2 = DEFAULT_LIFETIME_TIMEOUT_MS;
4540
+ lifetimeTimeoutHandle2 = setTimeout(() => {
4541
+ if (!cleanedUp2 && !isStreamClosed2) {
4542
+ console.warn(
4543
+ `SSR stream transform exceeded maximum lifetime (${lifetimeMs2}ms), forcing cleanup`
4544
+ );
4545
+ safeError2(new Error("Stream lifetime exceeded"));
4546
+ cleanup2();
4547
+ }
4548
+ }, lifetimeMs2);
4549
+ const stream2 = new ReadableStream$1({
4550
+ start(c) {
4551
+ controller2 = c;
4552
+ },
4553
+ cancel() {
4554
+ isStreamClosed2 = true;
4555
+ cleanup2();
4556
+ }
4557
+ });
4558
+ (async () => {
4559
+ const reader = appStream.getReader();
4560
+ try {
4561
+ while (true) {
4562
+ const { done, value } = await reader.read();
4563
+ if (done) break;
4564
+ if (cleanedUp2 || isStreamClosed2) return;
4565
+ controller2?.enqueue(value);
4566
+ }
4567
+ if (cleanedUp2 || isStreamClosed2) return;
4568
+ router.serverSsr?.setRenderFinished();
4569
+ safeClose2();
4570
+ cleanup2();
4571
+ } catch (error) {
4572
+ if (cleanedUp2) return;
4573
+ console.error("Error reading appStream:", error);
4574
+ router.serverSsr?.setRenderFinished();
4575
+ safeError2(error);
4576
+ cleanup2();
4577
+ } finally {
4578
+ reader.releaseLock();
4579
+ }
4580
+ })().catch((error) => {
4581
+ if (cleanedUp2) return;
4582
+ console.error("Error in stream transform:", error);
4583
+ safeError2(error);
4584
+ cleanup2();
4585
+ });
4586
+ return stream2;
4587
+ }
4588
+ let stopListeningToInjectedHtml;
4589
+ let stopListeningToSerializationFinished;
4590
+ let serializationTimeoutHandle;
4591
+ let lifetimeTimeoutHandle;
4592
+ let cleanedUp = false;
4593
+ let controller;
4594
+ let isStreamClosed = false;
4595
+ const textDecoder = new TextDecoder();
4596
+ let pendingRouterHtml = initialBufferedHtml ?? "";
4597
+ let leftover = "";
4598
+ let pendingClosingTags = "";
4599
+ const MAX_LEFTOVER_CHARS = 2048;
4600
+ let isAppRendering = true;
4601
+ let streamBarrierLifted = false;
4602
+ let serializationFinished = serializationAlreadyFinished;
4603
+ function safeEnqueue(chunk) {
4604
+ if (isStreamClosed) return;
4605
+ if (typeof chunk === "string") {
4606
+ controller.enqueue(textEncoder.encode(chunk));
4607
+ } else {
4608
+ controller.enqueue(chunk);
4609
+ }
4610
+ }
4611
+ function safeClose() {
4612
+ if (isStreamClosed) return;
4613
+ isStreamClosed = true;
4614
+ try {
4615
+ controller.close();
4616
+ } catch {
4617
+ }
4618
+ }
4619
+ function safeError(error) {
4620
+ if (isStreamClosed) return;
4621
+ isStreamClosed = true;
4622
+ try {
4623
+ controller.error(error);
4624
+ } catch {
4625
+ }
4626
+ }
4627
+ function cleanup() {
4628
+ if (cleanedUp) return;
4629
+ cleanedUp = true;
4630
+ try {
4631
+ stopListeningToInjectedHtml?.();
4632
+ stopListeningToSerializationFinished?.();
4633
+ } catch {
4634
+ }
4635
+ stopListeningToInjectedHtml = void 0;
4636
+ stopListeningToSerializationFinished = void 0;
4637
+ if (serializationTimeoutHandle !== void 0) {
4638
+ clearTimeout(serializationTimeoutHandle);
4639
+ serializationTimeoutHandle = void 0;
4640
+ }
4641
+ if (lifetimeTimeoutHandle !== void 0) {
4642
+ clearTimeout(lifetimeTimeoutHandle);
4643
+ lifetimeTimeoutHandle = void 0;
4644
+ }
4645
+ pendingRouterHtml = "";
4646
+ leftover = "";
4647
+ pendingClosingTags = "";
4648
+ router.serverSsr?.cleanup();
4649
+ }
4650
+ const stream = new ReadableStream$1({
4651
+ start(c) {
4652
+ controller = c;
4653
+ },
4654
+ cancel() {
4655
+ isStreamClosed = true;
4656
+ cleanup();
4657
+ }
4658
+ });
4659
+ function flushPendingRouterHtml() {
4660
+ if (!pendingRouterHtml) return;
4661
+ safeEnqueue(pendingRouterHtml);
4662
+ pendingRouterHtml = "";
4663
+ }
4664
+ function appendRouterHtml(html) {
4665
+ if (!html) return;
4666
+ pendingRouterHtml += html;
4667
+ }
4668
+ function tryFinish() {
4669
+ if (isAppRendering || !serializationFinished) return;
4670
+ if (cleanedUp || isStreamClosed) return;
4671
+ if (serializationTimeoutHandle !== void 0) {
4672
+ clearTimeout(serializationTimeoutHandle);
4673
+ serializationTimeoutHandle = void 0;
4674
+ }
4675
+ const decoderRemainder = textDecoder.decode();
4676
+ if (leftover) safeEnqueue(leftover);
4677
+ if (decoderRemainder) safeEnqueue(decoderRemainder);
4678
+ flushPendingRouterHtml();
4679
+ if (pendingClosingTags) safeEnqueue(pendingClosingTags);
4680
+ safeClose();
4681
+ cleanup();
4682
+ }
4683
+ const lifetimeMs = DEFAULT_LIFETIME_TIMEOUT_MS;
4684
+ lifetimeTimeoutHandle = setTimeout(() => {
4685
+ if (!cleanedUp && !isStreamClosed) {
4686
+ console.warn(
4687
+ `SSR stream transform exceeded maximum lifetime (${lifetimeMs}ms), forcing cleanup`
4688
+ );
4689
+ safeError(new Error("Stream lifetime exceeded"));
4690
+ cleanup();
4691
+ }
4692
+ }, lifetimeMs);
4693
+ if (!serializationAlreadyFinished) {
4694
+ stopListeningToInjectedHtml = router.subscribe("onInjectedHtml", () => {
4695
+ if (cleanedUp || isStreamClosed) return;
4696
+ const html = router.serverSsr?.takeBufferedHtml();
4697
+ if (!html) return;
4698
+ if (isAppRendering || leftover || pendingClosingTags) {
4699
+ appendRouterHtml(html);
4700
+ } else {
4701
+ safeEnqueue(html);
4702
+ }
4703
+ });
4704
+ stopListeningToSerializationFinished = router.subscribe(
4705
+ "onSerializationFinished",
4706
+ () => {
4707
+ serializationFinished = true;
4708
+ tryFinish();
4709
+ }
4710
+ );
4711
+ }
4712
+ (async () => {
4713
+ const reader = appStream.getReader();
4714
+ try {
4715
+ while (true) {
4716
+ const { done, value } = await reader.read();
4717
+ if (done) break;
4718
+ if (cleanedUp || isStreamClosed) return;
4719
+ const text = value instanceof Uint8Array ? textDecoder.decode(value, { stream: true }) : String(value);
4720
+ const chunkString = leftover ? leftover + text : text;
4721
+ if (!streamBarrierLifted) {
4722
+ if (chunkString.includes(TSR_SCRIPT_BARRIER_ID)) {
4723
+ streamBarrierLifted = true;
4724
+ router.serverSsr?.liftScriptBarrier();
4725
+ }
4726
+ }
4727
+ if (pendingClosingTags) {
4728
+ pendingClosingTags += chunkString;
4729
+ leftover = "";
4730
+ continue;
4731
+ }
4732
+ const bodyEndIndex = chunkString.indexOf(BODY_END_TAG);
4733
+ const htmlEndIndex = chunkString.indexOf(HTML_END_TAG);
4734
+ if (bodyEndIndex !== -1 && htmlEndIndex !== -1 && bodyEndIndex < htmlEndIndex) {
4735
+ pendingClosingTags = chunkString.slice(bodyEndIndex);
4736
+ safeEnqueue(chunkString.slice(0, bodyEndIndex));
4737
+ flushPendingRouterHtml();
4738
+ leftover = "";
4739
+ continue;
4740
+ }
4741
+ const lastClosingTagEnd = findLastClosingTagEnd(chunkString);
4742
+ if (lastClosingTagEnd > 0) {
4743
+ safeEnqueue(chunkString.slice(0, lastClosingTagEnd));
4744
+ flushPendingRouterHtml();
4745
+ leftover = chunkString.slice(lastClosingTagEnd);
4746
+ if (leftover.length > MAX_LEFTOVER_CHARS) {
4747
+ safeEnqueue(leftover.slice(0, leftover.length - MAX_LEFTOVER_CHARS));
4748
+ leftover = leftover.slice(-MAX_LEFTOVER_CHARS);
4749
+ }
4750
+ } else {
4751
+ const combined = chunkString;
4752
+ if (combined.length > MAX_LEFTOVER_CHARS) {
4753
+ const flushUpto = combined.length - MAX_LEFTOVER_CHARS;
4754
+ safeEnqueue(combined.slice(0, flushUpto));
4755
+ leftover = combined.slice(flushUpto);
4756
+ } else {
4757
+ leftover = combined;
4758
+ }
4759
+ }
4760
+ }
4761
+ if (cleanedUp || isStreamClosed) return;
4762
+ isAppRendering = false;
4763
+ router.serverSsr?.setRenderFinished();
4764
+ if (serializationFinished) {
4765
+ tryFinish();
4766
+ } else {
4767
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_SERIALIZATION_TIMEOUT_MS;
4768
+ serializationTimeoutHandle = setTimeout(() => {
4769
+ if (!cleanedUp && !isStreamClosed) {
4770
+ console.error("Serialization timeout after app render finished");
4771
+ safeError(
4772
+ new Error("Serialization timeout after app render finished")
4773
+ );
4774
+ cleanup();
4775
+ }
4776
+ }, timeoutMs);
4777
+ }
4778
+ } catch (error) {
4779
+ if (cleanedUp) return;
4780
+ console.error("Error reading appStream:", error);
4781
+ isAppRendering = false;
4782
+ router.serverSsr?.setRenderFinished();
4783
+ safeError(error);
4784
+ cleanup();
4785
+ } finally {
4786
+ reader.releaseLock();
4787
+ }
4788
+ })().catch((error) => {
4789
+ if (cleanedUp) return;
4790
+ console.error("Error in stream transform:", error);
4791
+ safeError(error);
4792
+ cleanup();
4793
+ });
4794
+ return stream;
4795
+ }
4796
+ export {
4797
+ defaultSerovalPlugins as A,
4798
+ BaseRootRoute as B,
4799
+ makeSerovalPlugin as C,
4800
+ RouterCore as R,
4801
+ rootRouteId as a,
4802
+ isRedirect as b,
4803
+ transformPipeableStreamWithRouter as c,
4804
+ defaultGetScrollRestorationKey as d,
4805
+ escapeHtml as e,
4806
+ isDangerousProtocol as f,
4807
+ getLocationChangeInfo as g,
4808
+ exactPathTest as h,
4809
+ isNotFound as i,
4810
+ removeTrailingSlash as j,
4811
+ deepEqual as k,
4812
+ functionalUpdate as l,
4813
+ BaseRoute as m,
4814
+ isModuleNotFoundError as n,
4815
+ getNormalizedURL as o,
4816
+ getOrigin as p,
4817
+ attachRouterServerSsrUtils as q,
4818
+ restoreScroll as r,
4819
+ storageKey as s,
4820
+ transformReadableStreamWithRouter as t,
4821
+ defineHandlerCallback as u,
4822
+ createSerializationAdapter as v,
4823
+ createRawStreamRPCPlugin as w,
4824
+ isResolvedRedirect as x,
4825
+ mergeHeaders as y,
4826
+ executeRewriteInput as z
4827
+ };