@tanstack/router-core 1.157.0 → 1.157.3

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 (57) hide show
  1. package/dist/cjs/index.cjs +0 -5
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +0 -1
  4. package/dist/cjs/isServer/client.cjs +5 -0
  5. package/dist/cjs/isServer/client.cjs.map +1 -0
  6. package/dist/cjs/isServer/client.d.cts +1 -0
  7. package/dist/cjs/isServer/development.cjs +5 -0
  8. package/dist/cjs/isServer/development.cjs.map +1 -0
  9. package/dist/cjs/isServer/development.d.cts +1 -0
  10. package/dist/cjs/isServer/server.cjs +5 -0
  11. package/dist/cjs/isServer/server.cjs.map +1 -0
  12. package/dist/cjs/isServer/server.d.cts +1 -0
  13. package/dist/cjs/load-matches.cjs +8 -8
  14. package/dist/cjs/load-matches.cjs.map +1 -1
  15. package/dist/cjs/location.d.cts +2 -3
  16. package/dist/cjs/router.cjs +35 -26
  17. package/dist/cjs/router.cjs.map +1 -1
  18. package/dist/cjs/scroll-restoration.cjs +3 -3
  19. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  20. package/dist/cjs/utils.cjs +5 -0
  21. package/dist/cjs/utils.cjs.map +1 -1
  22. package/dist/cjs/utils.d.cts +9 -0
  23. package/dist/esm/index.d.ts +0 -1
  24. package/dist/esm/index.js +0 -2
  25. package/dist/esm/index.js.map +1 -1
  26. package/dist/esm/isServer/client.d.ts +1 -0
  27. package/dist/esm/isServer/client.js +5 -0
  28. package/dist/esm/isServer/client.js.map +1 -0
  29. package/dist/esm/isServer/development.d.ts +1 -0
  30. package/dist/esm/isServer/development.js +5 -0
  31. package/dist/esm/isServer/development.js.map +1 -0
  32. package/dist/esm/isServer/server.d.ts +1 -0
  33. package/dist/esm/isServer/server.js +5 -0
  34. package/dist/esm/isServer/server.js.map +1 -0
  35. package/dist/esm/load-matches.js +1 -1
  36. package/dist/esm/load-matches.js.map +1 -1
  37. package/dist/esm/location.d.ts +2 -3
  38. package/dist/esm/router.js +29 -20
  39. package/dist/esm/router.js.map +1 -1
  40. package/dist/esm/scroll-restoration.js +1 -1
  41. package/dist/esm/scroll-restoration.js.map +1 -1
  42. package/dist/esm/utils.d.ts +9 -0
  43. package/dist/esm/utils.js +5 -0
  44. package/dist/esm/utils.js.map +1 -1
  45. package/package.json +82 -3
  46. package/src/index.ts +0 -1
  47. package/src/isServer/client.ts +1 -0
  48. package/src/isServer/development.ts +2 -0
  49. package/src/isServer/server.ts +1 -0
  50. package/src/load-matches.ts +1 -1
  51. package/src/location.ts +2 -3
  52. package/src/router.ts +44 -26
  53. package/src/scroll-restoration.ts +1 -1
  54. package/src/utils.ts +15 -0
  55. package/dist/cjs/isServer.d.cts +0 -24
  56. package/dist/esm/isServer.d.ts +0 -24
  57. package/src/isServer.ts +0 -24
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const isServer = require("@tanstack/router-core/isServer");
3
4
  const utils = require("./utils.cjs");
4
- const routerIsServer = require("@tanstack/router-is-server");
5
5
  function getSafeSessionStorage() {
6
6
  try {
7
7
  if (typeof window !== "undefined" && typeof window.sessionStorage === "object") {
@@ -125,14 +125,14 @@ function restoreScroll({
125
125
  ignoreScroll = false;
126
126
  }
127
127
  function setupScrollRestoration(router, force) {
128
- if (!scrollRestorationCache && !(routerIsServer.isServer ?? router.isServer)) {
128
+ if (!scrollRestorationCache && !(isServer.isServer ?? router.isServer)) {
129
129
  return;
130
130
  }
131
131
  const shouldScrollRestoration = force ?? router.options.scrollRestoration ?? false;
132
132
  if (shouldScrollRestoration) {
133
133
  router.isScrollRestoring = true;
134
134
  }
135
- if ((routerIsServer.isServer ?? router.isServer) || router.isScrollRestorationSetup || !scrollRestorationCache) {
135
+ if ((isServer.isServer ?? router.isServer) || router.isScrollRestorationSetup || !scrollRestorationCache) {
136
136
  return;
137
137
  }
138
138
  router.isScrollRestorationSetup = true;
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-restoration.cjs","sources":["../../src/scroll-restoration.ts"],"sourcesContent":["import { functionalUpdate } from './utils'\nimport { isServer } from './isServer'\nimport type { AnyRouter } from './router'\nimport type { ParsedLocation } from './location'\nimport type { NonNullableUpdater } from './utils'\nimport type { HistoryLocation } from '@tanstack/history'\n\nexport type ScrollRestorationEntry = { scrollX: number; scrollY: number }\n\nexport type ScrollRestorationByElement = Record<string, ScrollRestorationEntry>\n\nexport type ScrollRestorationByKey = Record<string, ScrollRestorationByElement>\n\nexport type ScrollRestorationCache = {\n state: ScrollRestorationByKey\n set: (updater: NonNullableUpdater<ScrollRestorationByKey>) => void\n}\nexport type ScrollRestorationOptions = {\n getKey?: (location: ParsedLocation) => string\n scrollBehavior?: ScrollToOptions['behavior']\n}\n\nfunction getSafeSessionStorage() {\n try {\n if (\n typeof window !== 'undefined' &&\n typeof window.sessionStorage === 'object'\n ) {\n return window.sessionStorage\n }\n } catch {\n // silent\n }\n return undefined\n}\n\n/** SessionStorage key used to persist scroll restoration state. */\n/** SessionStorage key used to store scroll positions across navigations. */\n/** SessionStorage key used to store scroll positions across navigations. */\nexport const storageKey = 'tsr-scroll-restoration-v1_3'\n\nconst throttle = (fn: (...args: Array<any>) => void, wait: number) => {\n let timeout: any\n return (...args: Array<any>) => {\n if (!timeout) {\n timeout = setTimeout(() => {\n fn(...args)\n timeout = null\n }, wait)\n }\n }\n}\n\nfunction createScrollRestorationCache(): ScrollRestorationCache | null {\n const safeSessionStorage = getSafeSessionStorage()\n if (!safeSessionStorage) {\n return null\n }\n\n const persistedState = safeSessionStorage.getItem(storageKey)\n let state: ScrollRestorationByKey = persistedState\n ? JSON.parse(persistedState)\n : {}\n\n return {\n state,\n // This setter is simply to make sure that we set the sessionStorage right\n // after the state is updated. It doesn't necessarily need to be a functional\n // update.\n set: (updater) => {\n state = functionalUpdate(updater, state) || state\n try {\n safeSessionStorage.setItem(storageKey, JSON.stringify(state))\n } catch {\n console.warn(\n '[ts-router] Could not persist scroll restoration state to sessionStorage.',\n )\n }\n },\n }\n}\n\n/** In-memory handle to the persisted scroll restoration cache. */\nexport const scrollRestorationCache = createScrollRestorationCache()\n\n/**\n * The default `getKey` function for `useScrollRestoration`.\n * It returns the `key` from the location state or the `href` of the location.\n *\n * The `location.href` is used as a fallback to support the use case where the location state is not available like the initial render.\n */\n\n/**\n * Default scroll restoration cache key: location state key or full href.\n */\nexport const defaultGetScrollRestorationKey = (location: ParsedLocation) => {\n return location.state.__TSR_key! || location.href\n}\n\n/** Best-effort nth-child CSS selector for a given element. */\nexport function getCssSelector(el: any): string {\n const path = []\n let parent: HTMLElement\n while ((parent = el.parentNode)) {\n path.push(\n `${el.tagName}:nth-child(${Array.prototype.indexOf.call(parent.children, el) + 1})`,\n )\n el = parent\n }\n return `${path.reverse().join(' > ')}`.toLowerCase()\n}\n\nlet ignoreScroll = false\n\n// NOTE: This function must remain pure and not use any outside variables\n// unless they are passed in as arguments. Why? Because we need to be able to\n// toString() it into a script tag to execute as early as possible in the browser\n// during SSR. Additionally, we also call it from within the router lifecycle\nexport function restoreScroll({\n storageKey,\n key,\n behavior,\n shouldScrollRestoration,\n scrollToTopSelectors,\n location,\n}: {\n storageKey: string\n key?: string\n behavior?: ScrollToOptions['behavior']\n shouldScrollRestoration?: boolean\n scrollToTopSelectors?: Array<string | (() => Element | null | undefined)>\n location?: HistoryLocation\n}) {\n let byKey: ScrollRestorationByKey\n\n try {\n byKey = JSON.parse(sessionStorage.getItem(storageKey) || '{}')\n } catch (error) {\n console.error(error)\n return\n }\n\n const resolvedKey = key || window.history.state?.__TSR_key\n const elementEntries = byKey[resolvedKey]\n\n //\n ignoreScroll = true\n\n //\n scroll: {\n // If we have a cached entry for this location state,\n // we always need to prefer that over the hash scroll.\n if (\n shouldScrollRestoration &&\n elementEntries &&\n Object.keys(elementEntries).length > 0\n ) {\n for (const elementSelector in elementEntries) {\n const entry = elementEntries[elementSelector]!\n if (elementSelector === 'window') {\n window.scrollTo({\n top: entry.scrollY,\n left: entry.scrollX,\n behavior,\n })\n } else if (elementSelector) {\n const element = document.querySelector(elementSelector)\n if (element) {\n element.scrollLeft = entry.scrollX\n element.scrollTop = entry.scrollY\n }\n }\n }\n\n break scroll\n }\n\n // If we don't have a cached entry for the hash,\n // Which means we've never seen this location before,\n // we need to check if there is a hash in the URL.\n // If there is, we need to scroll it's ID into view.\n const hash = (location ?? window.location).hash.split('#', 2)[1]\n\n if (hash) {\n const hashScrollIntoViewOptions =\n window.history.state?.__hashScrollIntoViewOptions ?? true\n\n if (hashScrollIntoViewOptions) {\n const el = document.getElementById(hash)\n if (el) {\n el.scrollIntoView(hashScrollIntoViewOptions)\n }\n }\n\n break scroll\n }\n\n // If there is no cached entry for the hash and there is no hash in the URL,\n // we need to scroll to the top of the page for every scrollToTop element\n const scrollOptions = { top: 0, left: 0, behavior }\n window.scrollTo(scrollOptions)\n if (scrollToTopSelectors) {\n for (const selector of scrollToTopSelectors) {\n if (selector === 'window') continue\n const element =\n typeof selector === 'function'\n ? selector()\n : document.querySelector(selector)\n if (element) element.scrollTo(scrollOptions)\n }\n }\n }\n\n //\n ignoreScroll = false\n}\n\n/** Setup global listeners and hooks to support scroll restoration. */\n/** Setup global listeners and hooks to support scroll restoration. */\nexport function setupScrollRestoration(router: AnyRouter, force?: boolean) {\n if (!scrollRestorationCache && !(isServer ?? router.isServer)) {\n return\n }\n const shouldScrollRestoration =\n force ?? router.options.scrollRestoration ?? false\n\n if (shouldScrollRestoration) {\n router.isScrollRestoring = true\n }\n\n if (\n (isServer ?? router.isServer) ||\n router.isScrollRestorationSetup ||\n !scrollRestorationCache\n ) {\n return\n }\n\n router.isScrollRestorationSetup = true\n\n //\n ignoreScroll = false\n\n const getKey =\n router.options.getScrollRestorationKey || defaultGetScrollRestorationKey\n\n window.history.scrollRestoration = 'manual'\n\n // // Create a MutationObserver to monitor DOM changes\n // const mutationObserver = new MutationObserver(() => {\n // ;ignoreScroll = true\n // requestAnimationFrame(() => {\n // ;ignoreScroll = false\n\n // // Attempt to restore scroll position on each dom\n // // mutation until the user scrolls. We do this\n // // because dynamic content may come in at different\n // // ticks after the initial render and we want to\n // // keep up with that content as much as possible.\n // // As soon as the user scrolls, we no longer need\n // // to attempt router.\n // // console.log('mutation observer restoreScroll')\n // restoreScroll(\n // storageKey,\n // getKey(router.state.location),\n // router.options.scrollRestorationBehavior,\n // )\n // })\n // })\n\n // const observeDom = () => {\n // // Observe changes to the entire document\n // mutationObserver.observe(document, {\n // childList: true, // Detect added or removed child nodes\n // subtree: true, // Monitor all descendants\n // characterData: true, // Detect text content changes\n // })\n // }\n\n // const unobserveDom = () => {\n // mutationObserver.disconnect()\n // }\n\n // observeDom()\n\n const onScroll = (event: Event) => {\n // unobserveDom()\n\n if (ignoreScroll || !router.isScrollRestoring) {\n return\n }\n\n let elementSelector = ''\n\n if (event.target === document || event.target === window) {\n elementSelector = 'window'\n } else {\n const attrId = (event.target as Element).getAttribute(\n 'data-scroll-restoration-id',\n )\n\n if (attrId) {\n elementSelector = `[data-scroll-restoration-id=\"${attrId}\"]`\n } else {\n elementSelector = getCssSelector(event.target)\n }\n }\n\n const restoreKey = getKey(router.state.location)\n\n scrollRestorationCache.set((state) => {\n const keyEntry = (state[restoreKey] ||= {} as ScrollRestorationByElement)\n\n const elementEntry = (keyEntry[elementSelector] ||=\n {} as ScrollRestorationEntry)\n\n if (elementSelector === 'window') {\n elementEntry.scrollX = window.scrollX || 0\n elementEntry.scrollY = window.scrollY || 0\n } else if (elementSelector) {\n const element = document.querySelector(elementSelector)\n if (element) {\n elementEntry.scrollX = element.scrollLeft || 0\n elementEntry.scrollY = element.scrollTop || 0\n }\n }\n\n return state\n })\n }\n\n // Throttle the scroll event to avoid excessive updates\n if (typeof document !== 'undefined') {\n document.addEventListener('scroll', throttle(onScroll, 100), true)\n }\n\n router.subscribe('onRendered', (event) => {\n // unobserveDom()\n\n const cacheKey = getKey(event.toLocation)\n\n // If the user doesn't want to restore the scroll position,\n // we don't need to do anything.\n if (!router.resetNextScroll) {\n router.resetNextScroll = true\n return\n }\n if (typeof router.options.scrollRestoration === 'function') {\n const shouldRestore = router.options.scrollRestoration({\n location: router.latestLocation,\n })\n if (!shouldRestore) {\n return\n }\n }\n\n restoreScroll({\n storageKey,\n key: cacheKey,\n behavior: router.options.scrollRestorationBehavior,\n shouldScrollRestoration: router.isScrollRestoring,\n scrollToTopSelectors: router.options.scrollToTopSelectors,\n location: router.history.location,\n })\n\n if (router.isScrollRestoring) {\n // Mark the location as having been seen\n scrollRestorationCache.set((state) => {\n state[cacheKey] ||= {} as ScrollRestorationByElement\n\n return state\n })\n }\n })\n}\n\n/**\n * @private\n * Handles hash-based scrolling after navigation completes.\n * To be used in framework-specific <Transitioner> components during the onResolved event.\n *\n * Provides hash scrolling for programmatic navigation when default browser handling is prevented.\n * @param router The router instance containing current location and state\n */\n/**\n * @private\n * Handles hash-based scrolling after navigation completes.\n * To be used in framework-specific Transitioners.\n */\nexport function handleHashScroll(router: AnyRouter) {\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n const hashScrollIntoViewOptions =\n router.state.location.state.__hashScrollIntoViewOptions ?? true\n\n if (hashScrollIntoViewOptions && router.state.location.hash !== '') {\n const el = document.getElementById(router.state.location.hash)\n if (el) {\n el.scrollIntoView(hashScrollIntoViewOptions)\n }\n }\n }\n}\n"],"names":["functionalUpdate","storageKey","isServer"],"mappings":"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"}
1
+ {"version":3,"file":"scroll-restoration.cjs","sources":["../../src/scroll-restoration.ts"],"sourcesContent":["import { isServer } from '@tanstack/router-core/isServer'\nimport { functionalUpdate } from './utils'\nimport type { AnyRouter } from './router'\nimport type { ParsedLocation } from './location'\nimport type { NonNullableUpdater } from './utils'\nimport type { HistoryLocation } from '@tanstack/history'\n\nexport type ScrollRestorationEntry = { scrollX: number; scrollY: number }\n\nexport type ScrollRestorationByElement = Record<string, ScrollRestorationEntry>\n\nexport type ScrollRestorationByKey = Record<string, ScrollRestorationByElement>\n\nexport type ScrollRestorationCache = {\n state: ScrollRestorationByKey\n set: (updater: NonNullableUpdater<ScrollRestorationByKey>) => void\n}\nexport type ScrollRestorationOptions = {\n getKey?: (location: ParsedLocation) => string\n scrollBehavior?: ScrollToOptions['behavior']\n}\n\nfunction getSafeSessionStorage() {\n try {\n if (\n typeof window !== 'undefined' &&\n typeof window.sessionStorage === 'object'\n ) {\n return window.sessionStorage\n }\n } catch {\n // silent\n }\n return undefined\n}\n\n/** SessionStorage key used to persist scroll restoration state. */\n/** SessionStorage key used to store scroll positions across navigations. */\n/** SessionStorage key used to store scroll positions across navigations. */\nexport const storageKey = 'tsr-scroll-restoration-v1_3'\n\nconst throttle = (fn: (...args: Array<any>) => void, wait: number) => {\n let timeout: any\n return (...args: Array<any>) => {\n if (!timeout) {\n timeout = setTimeout(() => {\n fn(...args)\n timeout = null\n }, wait)\n }\n }\n}\n\nfunction createScrollRestorationCache(): ScrollRestorationCache | null {\n const safeSessionStorage = getSafeSessionStorage()\n if (!safeSessionStorage) {\n return null\n }\n\n const persistedState = safeSessionStorage.getItem(storageKey)\n let state: ScrollRestorationByKey = persistedState\n ? JSON.parse(persistedState)\n : {}\n\n return {\n state,\n // This setter is simply to make sure that we set the sessionStorage right\n // after the state is updated. It doesn't necessarily need to be a functional\n // update.\n set: (updater) => {\n state = functionalUpdate(updater, state) || state\n try {\n safeSessionStorage.setItem(storageKey, JSON.stringify(state))\n } catch {\n console.warn(\n '[ts-router] Could not persist scroll restoration state to sessionStorage.',\n )\n }\n },\n }\n}\n\n/** In-memory handle to the persisted scroll restoration cache. */\nexport const scrollRestorationCache = createScrollRestorationCache()\n\n/**\n * The default `getKey` function for `useScrollRestoration`.\n * It returns the `key` from the location state or the `href` of the location.\n *\n * The `location.href` is used as a fallback to support the use case where the location state is not available like the initial render.\n */\n\n/**\n * Default scroll restoration cache key: location state key or full href.\n */\nexport const defaultGetScrollRestorationKey = (location: ParsedLocation) => {\n return location.state.__TSR_key! || location.href\n}\n\n/** Best-effort nth-child CSS selector for a given element. */\nexport function getCssSelector(el: any): string {\n const path = []\n let parent: HTMLElement\n while ((parent = el.parentNode)) {\n path.push(\n `${el.tagName}:nth-child(${Array.prototype.indexOf.call(parent.children, el) + 1})`,\n )\n el = parent\n }\n return `${path.reverse().join(' > ')}`.toLowerCase()\n}\n\nlet ignoreScroll = false\n\n// NOTE: This function must remain pure and not use any outside variables\n// unless they are passed in as arguments. Why? Because we need to be able to\n// toString() it into a script tag to execute as early as possible in the browser\n// during SSR. Additionally, we also call it from within the router lifecycle\nexport function restoreScroll({\n storageKey,\n key,\n behavior,\n shouldScrollRestoration,\n scrollToTopSelectors,\n location,\n}: {\n storageKey: string\n key?: string\n behavior?: ScrollToOptions['behavior']\n shouldScrollRestoration?: boolean\n scrollToTopSelectors?: Array<string | (() => Element | null | undefined)>\n location?: HistoryLocation\n}) {\n let byKey: ScrollRestorationByKey\n\n try {\n byKey = JSON.parse(sessionStorage.getItem(storageKey) || '{}')\n } catch (error) {\n console.error(error)\n return\n }\n\n const resolvedKey = key || window.history.state?.__TSR_key\n const elementEntries = byKey[resolvedKey]\n\n //\n ignoreScroll = true\n\n //\n scroll: {\n // If we have a cached entry for this location state,\n // we always need to prefer that over the hash scroll.\n if (\n shouldScrollRestoration &&\n elementEntries &&\n Object.keys(elementEntries).length > 0\n ) {\n for (const elementSelector in elementEntries) {\n const entry = elementEntries[elementSelector]!\n if (elementSelector === 'window') {\n window.scrollTo({\n top: entry.scrollY,\n left: entry.scrollX,\n behavior,\n })\n } else if (elementSelector) {\n const element = document.querySelector(elementSelector)\n if (element) {\n element.scrollLeft = entry.scrollX\n element.scrollTop = entry.scrollY\n }\n }\n }\n\n break scroll\n }\n\n // If we don't have a cached entry for the hash,\n // Which means we've never seen this location before,\n // we need to check if there is a hash in the URL.\n // If there is, we need to scroll it's ID into view.\n const hash = (location ?? window.location).hash.split('#', 2)[1]\n\n if (hash) {\n const hashScrollIntoViewOptions =\n window.history.state?.__hashScrollIntoViewOptions ?? true\n\n if (hashScrollIntoViewOptions) {\n const el = document.getElementById(hash)\n if (el) {\n el.scrollIntoView(hashScrollIntoViewOptions)\n }\n }\n\n break scroll\n }\n\n // If there is no cached entry for the hash and there is no hash in the URL,\n // we need to scroll to the top of the page for every scrollToTop element\n const scrollOptions = { top: 0, left: 0, behavior }\n window.scrollTo(scrollOptions)\n if (scrollToTopSelectors) {\n for (const selector of scrollToTopSelectors) {\n if (selector === 'window') continue\n const element =\n typeof selector === 'function'\n ? selector()\n : document.querySelector(selector)\n if (element) element.scrollTo(scrollOptions)\n }\n }\n }\n\n //\n ignoreScroll = false\n}\n\n/** Setup global listeners and hooks to support scroll restoration. */\n/** Setup global listeners and hooks to support scroll restoration. */\nexport function setupScrollRestoration(router: AnyRouter, force?: boolean) {\n if (!scrollRestorationCache && !(isServer ?? router.isServer)) {\n return\n }\n const shouldScrollRestoration =\n force ?? router.options.scrollRestoration ?? false\n\n if (shouldScrollRestoration) {\n router.isScrollRestoring = true\n }\n\n if (\n (isServer ?? router.isServer) ||\n router.isScrollRestorationSetup ||\n !scrollRestorationCache\n ) {\n return\n }\n\n router.isScrollRestorationSetup = true\n\n //\n ignoreScroll = false\n\n const getKey =\n router.options.getScrollRestorationKey || defaultGetScrollRestorationKey\n\n window.history.scrollRestoration = 'manual'\n\n // // Create a MutationObserver to monitor DOM changes\n // const mutationObserver = new MutationObserver(() => {\n // ;ignoreScroll = true\n // requestAnimationFrame(() => {\n // ;ignoreScroll = false\n\n // // Attempt to restore scroll position on each dom\n // // mutation until the user scrolls. We do this\n // // because dynamic content may come in at different\n // // ticks after the initial render and we want to\n // // keep up with that content as much as possible.\n // // As soon as the user scrolls, we no longer need\n // // to attempt router.\n // // console.log('mutation observer restoreScroll')\n // restoreScroll(\n // storageKey,\n // getKey(router.state.location),\n // router.options.scrollRestorationBehavior,\n // )\n // })\n // })\n\n // const observeDom = () => {\n // // Observe changes to the entire document\n // mutationObserver.observe(document, {\n // childList: true, // Detect added or removed child nodes\n // subtree: true, // Monitor all descendants\n // characterData: true, // Detect text content changes\n // })\n // }\n\n // const unobserveDom = () => {\n // mutationObserver.disconnect()\n // }\n\n // observeDom()\n\n const onScroll = (event: Event) => {\n // unobserveDom()\n\n if (ignoreScroll || !router.isScrollRestoring) {\n return\n }\n\n let elementSelector = ''\n\n if (event.target === document || event.target === window) {\n elementSelector = 'window'\n } else {\n const attrId = (event.target as Element).getAttribute(\n 'data-scroll-restoration-id',\n )\n\n if (attrId) {\n elementSelector = `[data-scroll-restoration-id=\"${attrId}\"]`\n } else {\n elementSelector = getCssSelector(event.target)\n }\n }\n\n const restoreKey = getKey(router.state.location)\n\n scrollRestorationCache.set((state) => {\n const keyEntry = (state[restoreKey] ||= {} as ScrollRestorationByElement)\n\n const elementEntry = (keyEntry[elementSelector] ||=\n {} as ScrollRestorationEntry)\n\n if (elementSelector === 'window') {\n elementEntry.scrollX = window.scrollX || 0\n elementEntry.scrollY = window.scrollY || 0\n } else if (elementSelector) {\n const element = document.querySelector(elementSelector)\n if (element) {\n elementEntry.scrollX = element.scrollLeft || 0\n elementEntry.scrollY = element.scrollTop || 0\n }\n }\n\n return state\n })\n }\n\n // Throttle the scroll event to avoid excessive updates\n if (typeof document !== 'undefined') {\n document.addEventListener('scroll', throttle(onScroll, 100), true)\n }\n\n router.subscribe('onRendered', (event) => {\n // unobserveDom()\n\n const cacheKey = getKey(event.toLocation)\n\n // If the user doesn't want to restore the scroll position,\n // we don't need to do anything.\n if (!router.resetNextScroll) {\n router.resetNextScroll = true\n return\n }\n if (typeof router.options.scrollRestoration === 'function') {\n const shouldRestore = router.options.scrollRestoration({\n location: router.latestLocation,\n })\n if (!shouldRestore) {\n return\n }\n }\n\n restoreScroll({\n storageKey,\n key: cacheKey,\n behavior: router.options.scrollRestorationBehavior,\n shouldScrollRestoration: router.isScrollRestoring,\n scrollToTopSelectors: router.options.scrollToTopSelectors,\n location: router.history.location,\n })\n\n if (router.isScrollRestoring) {\n // Mark the location as having been seen\n scrollRestorationCache.set((state) => {\n state[cacheKey] ||= {} as ScrollRestorationByElement\n\n return state\n })\n }\n })\n}\n\n/**\n * @private\n * Handles hash-based scrolling after navigation completes.\n * To be used in framework-specific <Transitioner> components during the onResolved event.\n *\n * Provides hash scrolling for programmatic navigation when default browser handling is prevented.\n * @param router The router instance containing current location and state\n */\n/**\n * @private\n * Handles hash-based scrolling after navigation completes.\n * To be used in framework-specific Transitioners.\n */\nexport function handleHashScroll(router: AnyRouter) {\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n const hashScrollIntoViewOptions =\n router.state.location.state.__hashScrollIntoViewOptions ?? true\n\n if (hashScrollIntoViewOptions && router.state.location.hash !== '') {\n const el = document.getElementById(router.state.location.hash)\n if (el) {\n el.scrollIntoView(hashScrollIntoViewOptions)\n }\n }\n }\n}\n"],"names":["functionalUpdate","storageKey","isServer"],"mappings":"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"}
@@ -220,6 +220,10 @@ function decodePath(path, decodeIgnore) {
220
220
  }
221
221
  return result;
222
222
  }
223
+ function encodeNonAscii(path) {
224
+ if (!/[^\u0000-\u007F]/.test(path)) return path;
225
+ return path.replace(/[^\u0000-\u007F]/gu, encodeURIComponent);
226
+ }
223
227
  function buildDevStylesUrl(basepath, routeIds) {
224
228
  const trimmedBasepath = basepath.replace(/^\/+|\/+$/g, "");
225
229
  const normalizedBasepath = trimmedBasepath === "" ? "" : `/${trimmedBasepath}`;
@@ -230,6 +234,7 @@ exports.buildDevStylesUrl = buildDevStylesUrl;
230
234
  exports.createControlledPromise = createControlledPromise;
231
235
  exports.decodePath = decodePath;
232
236
  exports.deepEqual = deepEqual;
237
+ exports.encodeNonAscii = encodeNonAscii;
233
238
  exports.escapeHtml = escapeHtml;
234
239
  exports.findLast = findLast;
235
240
  exports.functionalUpdate = functionalUpdate;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type { RouteIds } from './routeInfo'\nimport type { AnyRouter } from './router'\n\nexport type Awaitable<T> = T | Promise<T>\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\nexport type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue\n ? TYesResult\n : TNoResult\n\nexport type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<\n TValue,\n TKey\n> &\n Required<Pick<TValue, TKey>>\n\nexport type PickRequired<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n}\n\nexport type PickOptional<T> = {\n [K in keyof T as undefined extends T[K] ? K : never]: T[K]\n}\n\n// from https://stackoverflow.com/a/76458160\nexport type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never\n\nexport type Expand<T> = T extends object\n ? T extends infer O\n ? O extends Function\n ? O\n : { [K in keyof O]: O[K] }\n : never\n : T\n\nexport type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>\n }\n : T\n\nexport type MakeDifferenceOptional<TLeft, TRight> = keyof TLeft &\n keyof TRight extends never\n ? TRight\n : Omit<TRight, keyof TLeft & keyof TRight> & {\n [K in keyof TLeft & keyof TRight]?: TRight[K]\n }\n\n// from https://stackoverflow.com/a/53955431\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type IsUnion<T, U extends T = T> = (\n T extends any ? (U extends T ? false : true) : never\n) extends false\n ? false\n : true\n\nexport type IsNonEmptyObject<T> = T extends object\n ? keyof T extends never\n ? false\n : true\n : false\n\nexport type Assign<TLeft, TRight> = TLeft extends any\n ? TRight extends any\n ? IsNonEmptyObject<TLeft> extends false\n ? TRight\n : IsNonEmptyObject<TRight> extends false\n ? TLeft\n : keyof TLeft & keyof TRight extends never\n ? TLeft & TRight\n : Omit<TLeft, keyof TRight> & TRight\n : never\n : never\n\nexport type IntersectAssign<TLeft, TRight> = TLeft extends any\n ? TRight extends any\n ? IsNonEmptyObject<TLeft> extends false\n ? TRight\n : IsNonEmptyObject<TRight> extends false\n ? TLeft\n : TRight & TLeft\n : never\n : never\n\nexport type Timeout = ReturnType<typeof setTimeout>\n\nexport type Updater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev?: TPrevious) => TResult)\n\nexport type NonNullableUpdater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev: TPrevious) => TResult)\n\nexport type ExtractObjects<TUnion> = TUnion extends MergeAllPrimitive\n ? never\n : TUnion\n\nexport type PartialMergeAllObject<TUnion> =\n ExtractObjects<TUnion> extends infer TObj\n ? [TObj] extends [never]\n ? never\n : {\n [TKey in TObj extends any ? keyof TObj : never]?: TObj extends any\n ? TKey extends keyof TObj\n ? TObj[TKey]\n : never\n : never\n }\n : never\n\nexport type MergeAllPrimitive =\n | ReadonlyArray<any>\n | number\n | string\n | bigint\n | boolean\n | symbol\n | undefined\n | null\n\nexport type ExtractPrimitives<TUnion> = TUnion extends MergeAllPrimitive\n ? TUnion\n : TUnion extends object\n ? never\n : TUnion\n\nexport type PartialMergeAll<TUnion> =\n | ExtractPrimitives<TUnion>\n | PartialMergeAllObject<TUnion>\n\nexport type Constrain<T, TConstraint, TDefault = TConstraint> =\n | (T extends TConstraint ? T : never)\n | TDefault\n\nexport type ConstrainLiteral<T, TConstraint, TDefault = TConstraint> =\n | (T & TConstraint)\n | TDefault\n\n/**\n * To be added to router types\n */\nexport type UnionToIntersection<T> = (\n T extends any ? (arg: T) => any : never\n) extends (arg: infer T) => any\n ? T\n : never\n\n/**\n * Merges everything in a union into one object.\n * This mapped type is homomorphic which means it preserves stuff! :)\n */\nexport type MergeAllObjects<\n TUnion,\n TIntersected = UnionToIntersection<ExtractObjects<TUnion>>,\n> = [keyof TIntersected] extends [never]\n ? never\n : {\n [TKey in keyof TIntersected]: TUnion extends any\n ? TUnion[TKey & keyof TUnion]\n : never\n }\n\nexport type MergeAll<TUnion> =\n | MergeAllObjects<TUnion>\n | ExtractPrimitives<TUnion>\n\nexport type ValidateJSON<T> = ((...args: Array<any>) => any) extends T\n ? unknown extends T\n ? never\n : 'Function is not serializable'\n : { [K in keyof T]: ValidateJSON<T[K]> }\n\nexport type LooseReturnType<T> = T extends (\n ...args: Array<any>\n) => infer TReturn\n ? TReturn\n : never\n\nexport type LooseAsyncReturnType<T> = T extends (\n ...args: Array<any>\n) => infer TReturn\n ? TReturn extends Promise<infer TReturn>\n ? TReturn\n : TReturn\n : never\n\n/**\n * Return the last element of an array.\n * Intended for non-empty arrays used within router internals.\n */\nexport function last<T>(arr: ReadonlyArray<T>) {\n return arr[arr.length - 1]\n}\n\nfunction isFunction(d: any): d is Function {\n return typeof d === 'function'\n}\n\n/**\n * Apply a value-or-updater to a previous value.\n * Accepts either a literal value or a function of the previous value.\n */\nexport function functionalUpdate<TPrevious, TResult = TPrevious>(\n updater: Updater<TPrevious, TResult> | NonNullableUpdater<TPrevious, TResult>,\n previous: TPrevious,\n): TResult {\n if (isFunction(updater)) {\n return updater(previous)\n }\n\n return updater\n}\n\nconst hasOwn = Object.prototype.hasOwnProperty\nconst isEnumerable = Object.prototype.propertyIsEnumerable\n\n/**\n * This function returns `prev` if `_next` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between immutable JSON values for example.\n * Do not use this with signals\n */\nexport function replaceEqualDeep<T>(prev: any, _next: T, _depth = 0): T {\n if (prev === _next) {\n return prev\n }\n\n if (_depth > 500) return _next\n\n const next = _next as any\n\n const array = isPlainArray(prev) && isPlainArray(next)\n\n if (!array && !(isPlainObject(prev) && isPlainObject(next))) return next\n\n const prevItems = array ? prev : getEnumerableOwnKeys(prev)\n if (!prevItems) return next\n const nextItems = array ? next : getEnumerableOwnKeys(next)\n if (!nextItems) return next\n const prevSize = prevItems.length\n const nextSize = nextItems.length\n const copy: any = array ? new Array(nextSize) : {}\n\n let equalItems = 0\n\n for (let i = 0; i < nextSize; i++) {\n const key = array ? i : (nextItems[i] as any)\n const p = prev[key]\n const n = next[key]\n\n if (p === n) {\n copy[key] = p\n if (array ? i < prevSize : hasOwn.call(prev, key)) equalItems++\n continue\n }\n\n if (\n p === null ||\n n === null ||\n typeof p !== 'object' ||\n typeof n !== 'object'\n ) {\n copy[key] = n\n continue\n }\n\n const v = replaceEqualDeep(p, n, _depth + 1)\n copy[key] = v\n if (v === p) equalItems++\n }\n\n return prevSize === nextSize && equalItems === prevSize ? prev : copy\n}\n\n/**\n * Equivalent to `Reflect.ownKeys`, but ensures that objects are \"clone-friendly\":\n * will return false if object has any non-enumerable properties.\n *\n * Optimized for the common case where objects have no symbol properties.\n */\nfunction getEnumerableOwnKeys(o: object) {\n const names = Object.getOwnPropertyNames(o)\n\n // Fast path: check all string property names are enumerable\n for (const name of names) {\n if (!isEnumerable.call(o, name)) return false\n }\n\n // Only check symbols if the object has any (most plain objects don't)\n const symbols = Object.getOwnPropertySymbols(o)\n\n // Fast path: no symbols, return names directly (avoids array allocation/concat)\n if (symbols.length === 0) return names\n\n // Slow path: has symbols, need to check and merge\n const keys: Array<string | symbol> = names\n for (const symbol of symbols) {\n if (!isEnumerable.call(o, symbol)) return false\n keys.push(symbol)\n }\n return keys\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any) {\n if (!hasObjectPrototype(o)) {\n return false\n }\n\n // If has modified constructor\n const ctor = o.constructor\n if (typeof ctor === 'undefined') {\n return true\n }\n\n // If has modified prototype\n const prot = ctor.prototype\n if (!hasObjectPrototype(prot)) {\n return false\n }\n\n // If constructor does not have an Object-specific method\n if (!prot.hasOwnProperty('isPrototypeOf')) {\n return false\n }\n\n // Most likely a plain Object\n return true\n}\n\nfunction hasObjectPrototype(o: any) {\n return Object.prototype.toString.call(o) === '[object Object]'\n}\n\n/**\n * Check if a value is a \"plain\" array (no extra enumerable keys).\n */\nexport function isPlainArray(value: unknown): value is Array<unknown> {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\n/**\n * Perform a deep equality check with options for partial comparison and\n * ignoring `undefined` values. Optimized for router state comparisons.\n */\nexport function deepEqual(\n a: any,\n b: any,\n opts?: { partial?: boolean; ignoreUndefined?: boolean },\n): boolean {\n if (a === b) {\n return true\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n for (let i = 0, l = a.length; i < l; i++) {\n if (!deepEqual(a[i], b[i], opts)) return false\n }\n return true\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n const ignoreUndefined = opts?.ignoreUndefined ?? true\n\n if (opts?.partial) {\n for (const k in b) {\n if (!ignoreUndefined || b[k] !== undefined) {\n if (!deepEqual(a[k], b[k], opts)) return false\n }\n }\n return true\n }\n\n let aCount = 0\n if (!ignoreUndefined) {\n aCount = Object.keys(a).length\n } else {\n for (const k in a) {\n if (a[k] !== undefined) aCount++\n }\n }\n\n let bCount = 0\n for (const k in b) {\n if (!ignoreUndefined || b[k] !== undefined) {\n bCount++\n if (bCount > aCount || !deepEqual(a[k], b[k], opts)) return false\n }\n }\n\n return aCount === bCount\n }\n\n return false\n}\n\nexport type StringLiteral<T> = T extends string\n ? string extends T\n ? string\n : T\n : never\n\nexport type ThrowOrOptional<T, TThrow extends boolean> = TThrow extends true\n ? T\n : T | undefined\n\nexport type StrictOrFrom<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean = true,\n> = TStrict extends false\n ? {\n from?: never\n strict: TStrict\n }\n : {\n from: ConstrainLiteral<TFrom, RouteIds<TRouter['routeTree']>>\n strict?: TStrict\n }\n\nexport type ThrowConstraint<\n TStrict extends boolean,\n TThrow extends boolean,\n> = TStrict extends false ? (TThrow extends true ? never : TThrow) : TThrow\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n value?: T\n}\n\n/**\n * Create a promise with exposed resolve/reject and status fields.\n * Useful for coordinating async router lifecycle operations.\n */\nexport function createControlledPromise<T>(onResolve?: (value: T) => void) {\n let resolveLoadPromise!: (value: T) => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<T>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = (value: T) => {\n controlledPromise.status = 'resolved'\n controlledPromise.value = value\n resolveLoadPromise(value)\n onResolve?.(value)\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Heuristically detect dynamic import \"module not found\" errors\n * across major browsers for lazy route component handling.\n */\nexport function isModuleNotFoundError(error: any): boolean {\n // chrome: \"Failed to fetch dynamically imported module: http://localhost:5173/src/routes/posts.index.tsx?tsr-split\"\n // firefox: \"error loading dynamically imported module: http://localhost:5173/src/routes/posts.index.tsx?tsr-split\"\n // safari: \"Importing a module script failed.\"\n if (typeof error?.message !== 'string') return false\n return (\n error.message.startsWith('Failed to fetch dynamically imported module') ||\n error.message.startsWith('error loading dynamically imported module') ||\n error.message.startsWith('Importing a module script failed')\n )\n}\n\nexport function isPromise<T>(\n value: Promise<Awaited<T>> | T,\n): value is Promise<Awaited<T>> {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as Promise<T>).then === 'function',\n )\n}\n\nexport function findLast<T>(\n array: ReadonlyArray<T>,\n predicate: (item: T) => boolean,\n): T | undefined {\n for (let i = array.length - 1; i >= 0; i--) {\n const item = array[i]!\n if (predicate(item)) return item\n }\n return undefined\n}\n\n/**\n * Remove control characters that can cause open redirect vulnerabilities.\n * Characters like \\r (CR) and \\n (LF) can trick URL parsers into interpreting\n * paths like \"/\\r/evil.com\" as \"http://evil.com\".\n */\nfunction sanitizePathSegment(segment: string): string {\n // Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)\n // These include CR (\\r = 0x0D), LF (\\n = 0x0A), and other potentially dangerous characters\n // eslint-disable-next-line no-control-regex\n return segment.replace(/[\\x00-\\x1f\\x7f]/g, '')\n}\n\nfunction decodeSegment(segment: string): string {\n let decoded: string\n try {\n decoded = decodeURI(segment)\n } catch {\n // if the decoding fails, try to decode the various parts leaving the malformed tags in place\n decoded = segment.replaceAll(/%[0-9A-F]{2}/gi, (match) => {\n try {\n return decodeURI(match)\n } catch {\n return match\n }\n })\n }\n return sanitizePathSegment(decoded)\n}\n\n/**\n * List of URL protocols that are safe for navigation.\n * Only these protocols are allowed in redirects and navigation.\n */\nexport const SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:']\n\n/**\n * Check if a URL string uses a protocol that is not in the safe list.\n * Returns true for dangerous protocols like javascript:, data:, vbscript:, etc.\n *\n * The URL constructor correctly normalizes:\n * - Mixed case (JavaScript: → javascript:)\n * - Whitespace/control characters (java\\nscript: → javascript:)\n * - Leading whitespace\n *\n * For relative URLs (no protocol), returns false (safe).\n *\n * @param url - The URL string to check\n * @returns true if the URL uses a dangerous (non-whitelisted) protocol\n */\nexport function isDangerousProtocol(url: string): boolean {\n if (!url) return false\n\n try {\n // Use the URL constructor - it correctly normalizes protocols\n // per WHATWG URL spec, handling all bypass attempts automatically\n const parsed = new URL(url)\n return !SAFE_URL_PROTOCOLS.includes(parsed.protocol)\n } catch {\n // URL constructor throws for relative URLs (no protocol)\n // These are safe - they can't execute scripts\n return false\n }\n}\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\nconst HTML_ESCAPE_LOOKUP: { [match: string]: string } = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nconst HTML_ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\n/**\n * Escape HTML special characters in a string to prevent XSS attacks\n * when embedding strings in script tags during SSR.\n *\n * This is essential for preventing XSS vulnerabilities when user-controlled\n * content is embedded in inline scripts.\n */\nexport function escapeHtml(str: string): string {\n return str.replace(HTML_ESCAPE_REGEX, (match) => HTML_ESCAPE_LOOKUP[match]!)\n}\n\nexport function decodePath(path: string, decodeIgnore?: Array<string>): string {\n if (!path) return path\n const re = decodeIgnore\n ? new RegExp(`${decodeIgnore.join('|')}`, 'gi')\n : /%25|%5C/gi\n let cursor = 0\n let result = ''\n let match\n while (null !== (match = re.exec(path))) {\n result += decodeSegment(path.slice(cursor, match.index)) + match[0]\n cursor = re.lastIndex\n }\n result = result + decodeSegment(cursor ? path.slice(cursor) : path)\n\n // Prevent open redirect via protocol-relative URLs (e.g. \"//evil.com\")\n // After sanitizing control characters, paths like \"/\\r/evil.com\" become \"//evil.com\"\n // Collapse leading double slashes to a single slash\n if (result.startsWith('//')) {\n result = '/' + result.replace(/^\\/+/, '')\n }\n\n return result\n}\n\n/**\n * Builds the dev-mode CSS styles URL for route-scoped CSS collection.\n * Used by HeadContent components in all framework implementations to construct\n * the URL for the `/@tanstack-start/styles.css` endpoint.\n *\n * @param basepath - The router's basepath (may or may not have leading slash)\n * @param routeIds - Array of matched route IDs to include in the CSS collection\n * @returns The full URL path for the dev styles CSS endpoint\n */\nexport function buildDevStylesUrl(\n basepath: string,\n routeIds: Array<string>,\n): string {\n // Trim all leading and trailing slashes from basepath\n const trimmedBasepath = basepath.replace(/^\\/+|\\/+$/g, '')\n // Build normalized basepath: empty string for root, or '/path' for non-root\n const normalizedBasepath = trimmedBasepath === '' ? '' : `/${trimmedBasepath}`\n return `${normalizedBasepath}/@tanstack-start/styles.css?routes=${encodeURIComponent(routeIds.join(','))}`\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type { RouteIds } from './routeInfo'\nimport type { AnyRouter } from './router'\n\nexport type Awaitable<T> = T | Promise<T>\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\nexport type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue\n ? TYesResult\n : TNoResult\n\nexport type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<\n TValue,\n TKey\n> &\n Required<Pick<TValue, TKey>>\n\nexport type PickRequired<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n}\n\nexport type PickOptional<T> = {\n [K in keyof T as undefined extends T[K] ? K : never]: T[K]\n}\n\n// from https://stackoverflow.com/a/76458160\nexport type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never\n\nexport type Expand<T> = T extends object\n ? T extends infer O\n ? O extends Function\n ? O\n : { [K in keyof O]: O[K] }\n : never\n : T\n\nexport type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>\n }\n : T\n\nexport type MakeDifferenceOptional<TLeft, TRight> = keyof TLeft &\n keyof TRight extends never\n ? TRight\n : Omit<TRight, keyof TLeft & keyof TRight> & {\n [K in keyof TLeft & keyof TRight]?: TRight[K]\n }\n\n// from https://stackoverflow.com/a/53955431\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type IsUnion<T, U extends T = T> = (\n T extends any ? (U extends T ? false : true) : never\n) extends false\n ? false\n : true\n\nexport type IsNonEmptyObject<T> = T extends object\n ? keyof T extends never\n ? false\n : true\n : false\n\nexport type Assign<TLeft, TRight> = TLeft extends any\n ? TRight extends any\n ? IsNonEmptyObject<TLeft> extends false\n ? TRight\n : IsNonEmptyObject<TRight> extends false\n ? TLeft\n : keyof TLeft & keyof TRight extends never\n ? TLeft & TRight\n : Omit<TLeft, keyof TRight> & TRight\n : never\n : never\n\nexport type IntersectAssign<TLeft, TRight> = TLeft extends any\n ? TRight extends any\n ? IsNonEmptyObject<TLeft> extends false\n ? TRight\n : IsNonEmptyObject<TRight> extends false\n ? TLeft\n : TRight & TLeft\n : never\n : never\n\nexport type Timeout = ReturnType<typeof setTimeout>\n\nexport type Updater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev?: TPrevious) => TResult)\n\nexport type NonNullableUpdater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev: TPrevious) => TResult)\n\nexport type ExtractObjects<TUnion> = TUnion extends MergeAllPrimitive\n ? never\n : TUnion\n\nexport type PartialMergeAllObject<TUnion> =\n ExtractObjects<TUnion> extends infer TObj\n ? [TObj] extends [never]\n ? never\n : {\n [TKey in TObj extends any ? keyof TObj : never]?: TObj extends any\n ? TKey extends keyof TObj\n ? TObj[TKey]\n : never\n : never\n }\n : never\n\nexport type MergeAllPrimitive =\n | ReadonlyArray<any>\n | number\n | string\n | bigint\n | boolean\n | symbol\n | undefined\n | null\n\nexport type ExtractPrimitives<TUnion> = TUnion extends MergeAllPrimitive\n ? TUnion\n : TUnion extends object\n ? never\n : TUnion\n\nexport type PartialMergeAll<TUnion> =\n | ExtractPrimitives<TUnion>\n | PartialMergeAllObject<TUnion>\n\nexport type Constrain<T, TConstraint, TDefault = TConstraint> =\n | (T extends TConstraint ? T : never)\n | TDefault\n\nexport type ConstrainLiteral<T, TConstraint, TDefault = TConstraint> =\n | (T & TConstraint)\n | TDefault\n\n/**\n * To be added to router types\n */\nexport type UnionToIntersection<T> = (\n T extends any ? (arg: T) => any : never\n) extends (arg: infer T) => any\n ? T\n : never\n\n/**\n * Merges everything in a union into one object.\n * This mapped type is homomorphic which means it preserves stuff! :)\n */\nexport type MergeAllObjects<\n TUnion,\n TIntersected = UnionToIntersection<ExtractObjects<TUnion>>,\n> = [keyof TIntersected] extends [never]\n ? never\n : {\n [TKey in keyof TIntersected]: TUnion extends any\n ? TUnion[TKey & keyof TUnion]\n : never\n }\n\nexport type MergeAll<TUnion> =\n | MergeAllObjects<TUnion>\n | ExtractPrimitives<TUnion>\n\nexport type ValidateJSON<T> = ((...args: Array<any>) => any) extends T\n ? unknown extends T\n ? never\n : 'Function is not serializable'\n : { [K in keyof T]: ValidateJSON<T[K]> }\n\nexport type LooseReturnType<T> = T extends (\n ...args: Array<any>\n) => infer TReturn\n ? TReturn\n : never\n\nexport type LooseAsyncReturnType<T> = T extends (\n ...args: Array<any>\n) => infer TReturn\n ? TReturn extends Promise<infer TReturn>\n ? TReturn\n : TReturn\n : never\n\n/**\n * Return the last element of an array.\n * Intended for non-empty arrays used within router internals.\n */\nexport function last<T>(arr: ReadonlyArray<T>) {\n return arr[arr.length - 1]\n}\n\nfunction isFunction(d: any): d is Function {\n return typeof d === 'function'\n}\n\n/**\n * Apply a value-or-updater to a previous value.\n * Accepts either a literal value or a function of the previous value.\n */\nexport function functionalUpdate<TPrevious, TResult = TPrevious>(\n updater: Updater<TPrevious, TResult> | NonNullableUpdater<TPrevious, TResult>,\n previous: TPrevious,\n): TResult {\n if (isFunction(updater)) {\n return updater(previous)\n }\n\n return updater\n}\n\nconst hasOwn = Object.prototype.hasOwnProperty\nconst isEnumerable = Object.prototype.propertyIsEnumerable\n\n/**\n * This function returns `prev` if `_next` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between immutable JSON values for example.\n * Do not use this with signals\n */\nexport function replaceEqualDeep<T>(prev: any, _next: T, _depth = 0): T {\n if (prev === _next) {\n return prev\n }\n\n if (_depth > 500) return _next\n\n const next = _next as any\n\n const array = isPlainArray(prev) && isPlainArray(next)\n\n if (!array && !(isPlainObject(prev) && isPlainObject(next))) return next\n\n const prevItems = array ? prev : getEnumerableOwnKeys(prev)\n if (!prevItems) return next\n const nextItems = array ? next : getEnumerableOwnKeys(next)\n if (!nextItems) return next\n const prevSize = prevItems.length\n const nextSize = nextItems.length\n const copy: any = array ? new Array(nextSize) : {}\n\n let equalItems = 0\n\n for (let i = 0; i < nextSize; i++) {\n const key = array ? i : (nextItems[i] as any)\n const p = prev[key]\n const n = next[key]\n\n if (p === n) {\n copy[key] = p\n if (array ? i < prevSize : hasOwn.call(prev, key)) equalItems++\n continue\n }\n\n if (\n p === null ||\n n === null ||\n typeof p !== 'object' ||\n typeof n !== 'object'\n ) {\n copy[key] = n\n continue\n }\n\n const v = replaceEqualDeep(p, n, _depth + 1)\n copy[key] = v\n if (v === p) equalItems++\n }\n\n return prevSize === nextSize && equalItems === prevSize ? prev : copy\n}\n\n/**\n * Equivalent to `Reflect.ownKeys`, but ensures that objects are \"clone-friendly\":\n * will return false if object has any non-enumerable properties.\n *\n * Optimized for the common case where objects have no symbol properties.\n */\nfunction getEnumerableOwnKeys(o: object) {\n const names = Object.getOwnPropertyNames(o)\n\n // Fast path: check all string property names are enumerable\n for (const name of names) {\n if (!isEnumerable.call(o, name)) return false\n }\n\n // Only check symbols if the object has any (most plain objects don't)\n const symbols = Object.getOwnPropertySymbols(o)\n\n // Fast path: no symbols, return names directly (avoids array allocation/concat)\n if (symbols.length === 0) return names\n\n // Slow path: has symbols, need to check and merge\n const keys: Array<string | symbol> = names\n for (const symbol of symbols) {\n if (!isEnumerable.call(o, symbol)) return false\n keys.push(symbol)\n }\n return keys\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any) {\n if (!hasObjectPrototype(o)) {\n return false\n }\n\n // If has modified constructor\n const ctor = o.constructor\n if (typeof ctor === 'undefined') {\n return true\n }\n\n // If has modified prototype\n const prot = ctor.prototype\n if (!hasObjectPrototype(prot)) {\n return false\n }\n\n // If constructor does not have an Object-specific method\n if (!prot.hasOwnProperty('isPrototypeOf')) {\n return false\n }\n\n // Most likely a plain Object\n return true\n}\n\nfunction hasObjectPrototype(o: any) {\n return Object.prototype.toString.call(o) === '[object Object]'\n}\n\n/**\n * Check if a value is a \"plain\" array (no extra enumerable keys).\n */\nexport function isPlainArray(value: unknown): value is Array<unknown> {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\n/**\n * Perform a deep equality check with options for partial comparison and\n * ignoring `undefined` values. Optimized for router state comparisons.\n */\nexport function deepEqual(\n a: any,\n b: any,\n opts?: { partial?: boolean; ignoreUndefined?: boolean },\n): boolean {\n if (a === b) {\n return true\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n for (let i = 0, l = a.length; i < l; i++) {\n if (!deepEqual(a[i], b[i], opts)) return false\n }\n return true\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n const ignoreUndefined = opts?.ignoreUndefined ?? true\n\n if (opts?.partial) {\n for (const k in b) {\n if (!ignoreUndefined || b[k] !== undefined) {\n if (!deepEqual(a[k], b[k], opts)) return false\n }\n }\n return true\n }\n\n let aCount = 0\n if (!ignoreUndefined) {\n aCount = Object.keys(a).length\n } else {\n for (const k in a) {\n if (a[k] !== undefined) aCount++\n }\n }\n\n let bCount = 0\n for (const k in b) {\n if (!ignoreUndefined || b[k] !== undefined) {\n bCount++\n if (bCount > aCount || !deepEqual(a[k], b[k], opts)) return false\n }\n }\n\n return aCount === bCount\n }\n\n return false\n}\n\nexport type StringLiteral<T> = T extends string\n ? string extends T\n ? string\n : T\n : never\n\nexport type ThrowOrOptional<T, TThrow extends boolean> = TThrow extends true\n ? T\n : T | undefined\n\nexport type StrictOrFrom<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean = true,\n> = TStrict extends false\n ? {\n from?: never\n strict: TStrict\n }\n : {\n from: ConstrainLiteral<TFrom, RouteIds<TRouter['routeTree']>>\n strict?: TStrict\n }\n\nexport type ThrowConstraint<\n TStrict extends boolean,\n TThrow extends boolean,\n> = TStrict extends false ? (TThrow extends true ? never : TThrow) : TThrow\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n value?: T\n}\n\n/**\n * Create a promise with exposed resolve/reject and status fields.\n * Useful for coordinating async router lifecycle operations.\n */\nexport function createControlledPromise<T>(onResolve?: (value: T) => void) {\n let resolveLoadPromise!: (value: T) => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<T>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = (value: T) => {\n controlledPromise.status = 'resolved'\n controlledPromise.value = value\n resolveLoadPromise(value)\n onResolve?.(value)\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Heuristically detect dynamic import \"module not found\" errors\n * across major browsers for lazy route component handling.\n */\nexport function isModuleNotFoundError(error: any): boolean {\n // chrome: \"Failed to fetch dynamically imported module: http://localhost:5173/src/routes/posts.index.tsx?tsr-split\"\n // firefox: \"error loading dynamically imported module: http://localhost:5173/src/routes/posts.index.tsx?tsr-split\"\n // safari: \"Importing a module script failed.\"\n if (typeof error?.message !== 'string') return false\n return (\n error.message.startsWith('Failed to fetch dynamically imported module') ||\n error.message.startsWith('error loading dynamically imported module') ||\n error.message.startsWith('Importing a module script failed')\n )\n}\n\nexport function isPromise<T>(\n value: Promise<Awaited<T>> | T,\n): value is Promise<Awaited<T>> {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as Promise<T>).then === 'function',\n )\n}\n\nexport function findLast<T>(\n array: ReadonlyArray<T>,\n predicate: (item: T) => boolean,\n): T | undefined {\n for (let i = array.length - 1; i >= 0; i--) {\n const item = array[i]!\n if (predicate(item)) return item\n }\n return undefined\n}\n\n/**\n * Remove control characters that can cause open redirect vulnerabilities.\n * Characters like \\r (CR) and \\n (LF) can trick URL parsers into interpreting\n * paths like \"/\\r/evil.com\" as \"http://evil.com\".\n */\nfunction sanitizePathSegment(segment: string): string {\n // Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)\n // These include CR (\\r = 0x0D), LF (\\n = 0x0A), and other potentially dangerous characters\n // eslint-disable-next-line no-control-regex\n return segment.replace(/[\\x00-\\x1f\\x7f]/g, '')\n}\n\nfunction decodeSegment(segment: string): string {\n let decoded: string\n try {\n decoded = decodeURI(segment)\n } catch {\n // if the decoding fails, try to decode the various parts leaving the malformed tags in place\n decoded = segment.replaceAll(/%[0-9A-F]{2}/gi, (match) => {\n try {\n return decodeURI(match)\n } catch {\n return match\n }\n })\n }\n return sanitizePathSegment(decoded)\n}\n\n/**\n * List of URL protocols that are safe for navigation.\n * Only these protocols are allowed in redirects and navigation.\n */\nexport const SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:']\n\n/**\n * Check if a URL string uses a protocol that is not in the safe list.\n * Returns true for dangerous protocols like javascript:, data:, vbscript:, etc.\n *\n * The URL constructor correctly normalizes:\n * - Mixed case (JavaScript: → javascript:)\n * - Whitespace/control characters (java\\nscript: → javascript:)\n * - Leading whitespace\n *\n * For relative URLs (no protocol), returns false (safe).\n *\n * @param url - The URL string to check\n * @returns true if the URL uses a dangerous (non-whitelisted) protocol\n */\nexport function isDangerousProtocol(url: string): boolean {\n if (!url) return false\n\n try {\n // Use the URL constructor - it correctly normalizes protocols\n // per WHATWG URL spec, handling all bypass attempts automatically\n const parsed = new URL(url)\n return !SAFE_URL_PROTOCOLS.includes(parsed.protocol)\n } catch {\n // URL constructor throws for relative URLs (no protocol)\n // These are safe - they can't execute scripts\n return false\n }\n}\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\nconst HTML_ESCAPE_LOOKUP: { [match: string]: string } = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nconst HTML_ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\n/**\n * Escape HTML special characters in a string to prevent XSS attacks\n * when embedding strings in script tags during SSR.\n *\n * This is essential for preventing XSS vulnerabilities when user-controlled\n * content is embedded in inline scripts.\n */\nexport function escapeHtml(str: string): string {\n return str.replace(HTML_ESCAPE_REGEX, (match) => HTML_ESCAPE_LOOKUP[match]!)\n}\n\nexport function decodePath(path: string, decodeIgnore?: Array<string>): string {\n if (!path) return path\n const re = decodeIgnore\n ? new RegExp(`${decodeIgnore.join('|')}`, 'gi')\n : /%25|%5C/gi\n let cursor = 0\n let result = ''\n let match\n while (null !== (match = re.exec(path))) {\n result += decodeSegment(path.slice(cursor, match.index)) + match[0]\n cursor = re.lastIndex\n }\n result = result + decodeSegment(cursor ? path.slice(cursor) : path)\n\n // Prevent open redirect via protocol-relative URLs (e.g. \"//evil.com\")\n // After sanitizing control characters, paths like \"/\\r/evil.com\" become \"//evil.com\"\n // Collapse leading double slashes to a single slash\n if (result.startsWith('//')) {\n result = '/' + result.replace(/^\\/+/, '')\n }\n\n return result\n}\n\n/**\n * Encodes non-ASCII (unicode) characters in a path while preserving\n * already percent-encoded sequences. This is used to generate proper\n * href values without constructing URL objects.\n *\n * Unlike encodeURI, this won't double-encode percent-encoded sequences\n * like %2F or %25 because it only targets non-ASCII characters.\n */\nexport function encodeNonAscii(path: string): string {\n // eslint-disable-next-line no-control-regex\n if (!/[^\\u0000-\\u007F]/.test(path)) return path\n // eslint-disable-next-line no-control-regex\n return path.replace(/[^\\u0000-\\u007F]/gu, encodeURIComponent)\n}\n\n/**\n * Builds the dev-mode CSS styles URL for route-scoped CSS collection.\n * Used by HeadContent components in all framework implementations to construct\n * the URL for the `/@tanstack-start/styles.css` endpoint.\n *\n * @param basepath - The router's basepath (may or may not have leading slash)\n * @param routeIds - Array of matched route IDs to include in the CSS collection\n * @returns The full URL path for the dev styles CSS endpoint\n */\nexport function buildDevStylesUrl(\n basepath: string,\n routeIds: Array<string>,\n): string {\n // Trim all leading and trailing slashes from basepath\n const trimmedBasepath = basepath.replace(/^\\/+|\\/+$/g, '')\n // Build normalized basepath: empty string for root, or '/path' for non-root\n const normalizedBasepath = trimmedBasepath === '' ? '' : `/${trimmedBasepath}`\n return `${normalizedBasepath}/@tanstack-start/styles.css?routes=${encodeURIComponent(routeIds.join(','))}`\n}\n"],"names":[],"mappings":"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"}
@@ -140,6 +140,15 @@ export declare function isDangerousProtocol(url: string): boolean;
140
140
  */
141
141
  export declare function escapeHtml(str: string): string;
142
142
  export declare function decodePath(path: string, decodeIgnore?: Array<string>): string;
143
+ /**
144
+ * Encodes non-ASCII (unicode) characters in a path while preserving
145
+ * already percent-encoded sequences. This is used to generate proper
146
+ * href values without constructing URL objects.
147
+ *
148
+ * Unlike encodeURI, this won't double-encode percent-encoded sequences
149
+ * like %2F or %25 because it only targets non-ASCII characters.
150
+ */
151
+ export declare function encodeNonAscii(path: string): string;
143
152
  /**
144
153
  * Builds the dev-mode CSS styles URL for route-scoped CSS collection.
145
154
  * Used by HeadContent components in all framework implementations to construct
@@ -14,7 +14,6 @@ export { joinPaths, cleanPath, trimPathLeft, trimPathRight, trimPath, removeTrai
14
14
  export { encode, decode } from './qss.js';
15
15
  export { rootRouteId } from './root.js';
16
16
  export type { RootRouteId } from './root.js';
17
- export { isServer } from './isServer.js';
18
17
  export { BaseRoute, BaseRouteApi, BaseRootRoute } from './route.js';
19
18
  export type { AnyPathParams, SearchSchemaInput, AnyContext, RouteContext, PreloadableObj, RoutePathOptions, StaticDataRouteOption, RoutePathOptionsIntersection, SearchFilter, SearchMiddlewareContext, SearchMiddleware, ResolveId, InferFullSearchSchema, InferFullSearchSchemaInput, InferAllParams, InferAllContext, MetaDescriptor, RouteLinkEntry, SearchValidator, AnySearchValidator, DefaultSearchValidator, ErrorRouteProps, ErrorComponentProps, NotFoundRouteProps, ResolveParams, ParseParamsFn, StringifyParamsFn, ParamsOptions, UpdatableStaticRouteOption, ContextReturnType, ContextAsyncReturnType, ResolveRouteContext, ResolveLoaderData, RoutePrefix, TrimPath, TrimPathLeft, TrimPathRight, ResolveSearchSchemaFnInput, ResolveSearchSchemaInput, ResolveSearchSchemaFn, ResolveSearchSchema, ResolveFullSearchSchema, ResolveFullSearchSchemaInput, ResolveAllContext, BeforeLoadContextParameter, RouteContextParameter, ResolveAllParamsFromParent, AnyRoute, Route, RouteTypes, FullSearchSchemaOption, RemountDepsOptions, MakeRemountDepsOptionsUnion, ResolveFullPath, AnyRouteWithContext, RouteOptions, FileBaseRouteOptions, BaseRouteOptions, UpdatableRouteOptions, RouteLoaderFn, LoaderFnContext, RouteContextFn, ContextOptions, RouteContextOptions, BeforeLoadContextOptions, RootRouteOptions, RootRouteOptionsExtensions, UpdatableRouteOptionsExtensions, RouteConstraints, RouteTypesById, RouteMask, RouteExtensions, RouteLazyFn, RouteAddChildrenFn, RouteAddFileChildrenFn, RouteAddFileTypesFn, ResolveOptionalParams, ResolveRequiredParams, RootRoute, FilebaseRouteOptionsInterface, } from './route.js';
20
19
  export { defaultSerializeError, getLocationChangeInfo, RouterCore, lazyFn, SearchParamError, PathParamError, getInitialRouterState, getMatchedRoutes, trailingSlashOptions, } from './router.js';
package/dist/esm/index.js CHANGED
@@ -18,7 +18,6 @@ import { createSerializationAdapter, makeSerovalPlugin, makeSsrSerovalPlugin } f
18
18
  import { defaultSerovalPlugins } from "./ssr/serializer/seroval-plugins.js";
19
19
  import { RawStream, RawStreamSSRPlugin, createRawStreamDeserializePlugin, createRawStreamRPCPlugin } from "./ssr/serializer/RawStream.js";
20
20
  import { composeRewrites, executeRewriteInput, executeRewriteOutput } from "./rewrite.js";
21
- import { isServer } from "@tanstack/router-is-server";
22
21
  export {
23
22
  BaseRootRoute,
24
23
  BaseRoute,
@@ -67,7 +66,6 @@ export {
67
66
  isPlainObject,
68
67
  isRedirect,
69
68
  isResolvedRedirect,
70
- isServer,
71
69
  joinPaths,
72
70
  last,
73
71
  lazyFn,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1 @@
1
+ export declare const isServer = false;
@@ -0,0 +1,5 @@
1
+ const isServer = false;
2
+ export {
3
+ isServer
4
+ };
5
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sources":["../../../src/isServer/client.ts"],"sourcesContent":["export const isServer = false\n"],"names":[],"mappings":"AAAO,MAAM,WAAW;"}
@@ -0,0 +1 @@
1
+ export declare const isServer: boolean | undefined;
@@ -0,0 +1,5 @@
1
+ const isServer = void 0;
2
+ export {
3
+ isServer
4
+ };
5
+ //# sourceMappingURL=development.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"development.js","sources":["../../../src/isServer/development.ts"],"sourcesContent":["// Development/test mode - returns undefined so fallback to router.isServer is used\nexport const isServer: boolean | undefined = undefined\n"],"names":[],"mappings":"AACO,MAAM,WAAgC;"}
@@ -0,0 +1 @@
1
+ export declare const isServer = true;
@@ -0,0 +1,5 @@
1
+ const isServer = true;
2
+ export {
3
+ isServer
4
+ };
5
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sources":["../../../src/isServer/server.ts"],"sourcesContent":["export const isServer = true\n"],"names":[],"mappings":"AAAO,MAAM,WAAW;"}
@@ -1,10 +1,10 @@
1
1
  import { batch } from "@tanstack/store";
2
2
  import invariant from "tiny-invariant";
3
+ import { isServer } from "@tanstack/router-core/isServer";
3
4
  import { isPromise, createControlledPromise } from "./utils.js";
4
5
  import { isNotFound } from "./not-found.js";
5
6
  import { rootRouteId } from "./root.js";
6
7
  import { isRedirect } from "./redirect.js";
7
- import { isServer } from "@tanstack/router-is-server";
8
8
  const triggerOnReady = (inner) => {
9
9
  if (!inner.rendered) {
10
10
  inner.rendered = true;
@@ -1 +1 @@
1
- {"version":3,"file":"load-matches.js","sources":["../../src/load-matches.ts"],"sourcesContent":["import { batch } from '@tanstack/store'\nimport invariant from 'tiny-invariant'\nimport { createControlledPromise, isPromise } from './utils'\nimport { isNotFound } from './not-found'\nimport { rootRouteId } from './root'\nimport { isRedirect } from './redirect'\nimport { isServer } from './isServer'\nimport type { NotFoundError } from './not-found'\nimport type { ParsedLocation } from './location'\nimport type {\n AnyRoute,\n BeforeLoadContextOptions,\n LoaderFnContext,\n SsrContextOptions,\n} from './route'\nimport type { AnyRouteMatch, MakeRouteMatch } from './Matches'\nimport type { AnyRouter, SSROption, UpdateMatchFn } from './router'\n\n/**\n * An object of this shape is created when calling `loadMatches`.\n * It contains everything we need for all other functions in this file\n * to work. (It's basically the function's argument, plus a few mutable states)\n */\ntype InnerLoadContext = {\n /** the calling router instance */\n router: AnyRouter\n location: ParsedLocation\n /** mutable state, scoped to a `loadMatches` call */\n firstBadMatchIndex?: number\n /** mutable state, scoped to a `loadMatches` call */\n rendered?: boolean\n updateMatch: UpdateMatchFn\n matches: Array<AnyRouteMatch>\n preload?: boolean\n onReady?: () => Promise<void>\n sync?: boolean\n /** mutable state, scoped to a `loadMatches` call */\n matchPromises: Array<Promise<AnyRouteMatch>>\n}\n\nconst triggerOnReady = (inner: InnerLoadContext): void | Promise<void> => {\n if (!inner.rendered) {\n inner.rendered = true\n return inner.onReady?.()\n }\n}\n\nconst resolvePreload = (inner: InnerLoadContext, matchId: string): boolean => {\n return !!(\n inner.preload && !inner.router.state.matches.some((d) => d.id === matchId)\n )\n}\n\n/**\n * Builds the accumulated context from router options and all matches up to (and optionally including) the given index.\n * Merges __routeContext and __beforeLoadContext from each match.\n */\nconst buildMatchContext = (\n inner: InnerLoadContext,\n index: number,\n includeCurrentMatch: boolean = true,\n): Record<string, unknown> => {\n const context: Record<string, unknown> = {\n ...(inner.router.options.context ?? {}),\n }\n const end = includeCurrentMatch ? index : index - 1\n for (let i = 0; i <= end; i++) {\n const innerMatch = inner.matches[i]\n if (!innerMatch) continue\n const m = inner.router.getMatch(innerMatch.id)\n if (!m) continue\n Object.assign(context, m.__routeContext, m.__beforeLoadContext)\n }\n return context\n}\n\nconst _handleNotFound = (inner: InnerLoadContext, err: NotFoundError) => {\n // Find the route that should handle the not found error\n // First check if a specific route is requested to show the error\n const routeCursor =\n inner.router.routesById[err.routeId ?? ''] ?? inner.router.routeTree\n\n // Ensure a NotFoundComponent exists on the route\n if (\n !routeCursor.options.notFoundComponent &&\n (inner.router.options as any)?.defaultNotFoundComponent\n ) {\n routeCursor.options.notFoundComponent = (\n inner.router.options as any\n ).defaultNotFoundComponent\n }\n\n // Ensure we have a notFoundComponent\n invariant(\n routeCursor.options.notFoundComponent,\n 'No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router.',\n )\n\n // Find the match for this route\n const matchForRoute = inner.matches.find((m) => m.routeId === routeCursor.id)\n\n invariant(matchForRoute, 'Could not find match for route: ' + routeCursor.id)\n\n // Assign the error to the match - using non-null assertion since we've checked with invariant\n inner.updateMatch(matchForRoute.id, (prev) => ({\n ...prev,\n status: 'notFound',\n error: err,\n isFetching: false,\n }))\n\n if ((err as any).routerCode === 'BEFORE_LOAD' && routeCursor.parentRoute) {\n err.routeId = routeCursor.parentRoute.id\n _handleNotFound(inner, err)\n }\n}\n\nconst handleRedirectAndNotFound = (\n inner: InnerLoadContext,\n match: AnyRouteMatch | undefined,\n err: unknown,\n): void => {\n if (!isRedirect(err) && !isNotFound(err)) return\n\n if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) {\n throw err\n }\n\n // in case of a redirecting match during preload, the match does not exist\n if (match) {\n match._nonReactive.beforeLoadPromise?.resolve()\n match._nonReactive.loaderPromise?.resolve()\n match._nonReactive.beforeLoadPromise = undefined\n match._nonReactive.loaderPromise = undefined\n\n const status = isRedirect(err) ? 'redirected' : 'notFound'\n\n match._nonReactive.error = err\n\n inner.updateMatch(match.id, (prev) => ({\n ...prev,\n status,\n context: buildMatchContext(inner, match.index),\n isFetching: false,\n error: err,\n }))\n\n if (isNotFound(err) && !err.routeId) {\n err.routeId = match.routeId\n }\n\n match._nonReactive.loadPromise?.resolve()\n }\n\n if (isRedirect(err)) {\n inner.rendered = true\n err.options._fromLocation = inner.location\n err.redirectHandled = true\n err = inner.router.resolveRedirect(err)\n throw err\n } else {\n _handleNotFound(inner, err)\n throw err\n }\n}\n\nconst shouldSkipLoader = (\n inner: InnerLoadContext,\n matchId: string,\n): boolean => {\n const match = inner.router.getMatch(matchId)!\n // upon hydration, we skip the loader if the match has been dehydrated on the server\n if (!(isServer ?? inner.router.isServer) && match._nonReactive.dehydrated) {\n return true\n }\n\n if ((isServer ?? inner.router.isServer) && match.ssr === false) {\n return true\n }\n\n return false\n}\n\nconst handleSerialError = (\n inner: InnerLoadContext,\n index: number,\n err: any,\n routerCode: string,\n): void => {\n const { id: matchId, routeId } = inner.matches[index]!\n const route = inner.router.looseRoutesById[routeId]!\n\n // Much like suspense, we use a promise here to know if\n // we've been outdated by a new loadMatches call and\n // should abort the current async operation\n if (err instanceof Promise) {\n throw err\n }\n\n err.routerCode = routerCode\n inner.firstBadMatchIndex ??= index\n handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), err)\n\n try {\n route.options.onError?.(err)\n } catch (errorHandlerErr) {\n err = errorHandlerErr\n handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), err)\n }\n\n inner.updateMatch(matchId, (prev) => {\n prev._nonReactive.beforeLoadPromise?.resolve()\n prev._nonReactive.beforeLoadPromise = undefined\n prev._nonReactive.loadPromise?.resolve()\n\n return {\n ...prev,\n error: err,\n status: 'error',\n isFetching: false,\n updatedAt: Date.now(),\n abortController: new AbortController(),\n }\n })\n}\n\nconst isBeforeLoadSsr = (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): void | Promise<void> => {\n const existingMatch = inner.router.getMatch(matchId)!\n const parentMatchId = inner.matches[index - 1]?.id\n const parentMatch = parentMatchId\n ? inner.router.getMatch(parentMatchId)!\n : undefined\n\n // in SPA mode, only SSR the root route\n if (inner.router.isShell()) {\n existingMatch.ssr = route.id === rootRouteId\n return\n }\n\n if (parentMatch?.ssr === false) {\n existingMatch.ssr = false\n return\n }\n\n const parentOverride = (tempSsr: SSROption) => {\n if (tempSsr === true && parentMatch?.ssr === 'data-only') {\n return 'data-only'\n }\n return tempSsr\n }\n\n const defaultSsr = inner.router.options.defaultSsr ?? true\n\n if (route.options.ssr === undefined) {\n existingMatch.ssr = parentOverride(defaultSsr)\n return\n }\n\n if (typeof route.options.ssr !== 'function') {\n existingMatch.ssr = parentOverride(route.options.ssr)\n return\n }\n const { search, params } = existingMatch\n\n const ssrFnContext: SsrContextOptions<any, any, any> = {\n search: makeMaybe(search, existingMatch.searchError),\n params: makeMaybe(params, existingMatch.paramsError),\n location: inner.location,\n matches: inner.matches.map((match) => ({\n index: match.index,\n pathname: match.pathname,\n fullPath: match.fullPath,\n staticData: match.staticData,\n id: match.id,\n routeId: match.routeId,\n search: makeMaybe(match.search, match.searchError),\n params: makeMaybe(match.params, match.paramsError),\n ssr: match.ssr,\n })),\n }\n\n const tempSsr = route.options.ssr(ssrFnContext)\n if (isPromise(tempSsr)) {\n return tempSsr.then((ssr) => {\n existingMatch.ssr = parentOverride(ssr ?? defaultSsr)\n })\n }\n\n existingMatch.ssr = parentOverride(tempSsr ?? defaultSsr)\n return\n}\n\nconst setupPendingTimeout = (\n inner: InnerLoadContext,\n matchId: string,\n route: AnyRoute,\n match: AnyRouteMatch,\n): void => {\n if (match._nonReactive.pendingTimeout !== undefined) return\n\n const pendingMs =\n route.options.pendingMs ?? inner.router.options.defaultPendingMs\n const shouldPending = !!(\n inner.onReady &&\n !(isServer ?? inner.router.isServer) &&\n !resolvePreload(inner, matchId) &&\n (route.options.loader ||\n route.options.beforeLoad ||\n routeNeedsPreload(route)) &&\n typeof pendingMs === 'number' &&\n pendingMs !== Infinity &&\n (route.options.pendingComponent ??\n (inner.router.options as any)?.defaultPendingComponent)\n )\n\n if (shouldPending) {\n const pendingTimeout = setTimeout(() => {\n // Update the match and prematurely resolve the loadMatches promise so that\n // the pending component can start rendering\n triggerOnReady(inner)\n }, pendingMs)\n match._nonReactive.pendingTimeout = pendingTimeout\n }\n}\n\nconst preBeforeLoadSetup = (\n inner: InnerLoadContext,\n matchId: string,\n route: AnyRoute,\n): void | Promise<void> => {\n const existingMatch = inner.router.getMatch(matchId)!\n\n // If we are in the middle of a load, either of these will be present\n // (not to be confused with `loadPromise`, which is always defined)\n if (\n !existingMatch._nonReactive.beforeLoadPromise &&\n !existingMatch._nonReactive.loaderPromise\n )\n return\n\n setupPendingTimeout(inner, matchId, route, existingMatch)\n\n const then = () => {\n const match = inner.router.getMatch(matchId)!\n if (\n match.preload &&\n (match.status === 'redirected' || match.status === 'notFound')\n ) {\n handleRedirectAndNotFound(inner, match, match.error)\n }\n }\n\n // Wait for the previous beforeLoad to resolve before we continue\n return existingMatch._nonReactive.beforeLoadPromise\n ? existingMatch._nonReactive.beforeLoadPromise.then(then)\n : then()\n}\n\nconst executeBeforeLoad = (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): void | Promise<void> => {\n const match = inner.router.getMatch(matchId)!\n\n // explicitly capture the previous loadPromise\n const prevLoadPromise = match._nonReactive.loadPromise\n match._nonReactive.loadPromise = createControlledPromise<void>(() => {\n prevLoadPromise?.resolve()\n })\n\n const { paramsError, searchError } = match\n\n if (paramsError) {\n handleSerialError(inner, index, paramsError, 'PARSE_PARAMS')\n }\n\n if (searchError) {\n handleSerialError(inner, index, searchError, 'VALIDATE_SEARCH')\n }\n\n setupPendingTimeout(inner, matchId, route, match)\n\n const abortController = new AbortController()\n\n const parentMatchId = inner.matches[index - 1]?.id\n const parentMatch = parentMatchId\n ? inner.router.getMatch(parentMatchId)!\n : undefined\n const parentMatchContext =\n parentMatch?.context ?? inner.router.options.context ?? undefined\n\n let isPending = false\n const pending = () => {\n if (isPending) return\n isPending = true\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: 'beforeLoad',\n fetchCount: prev.fetchCount + 1,\n abortController,\n // Note: We intentionally don't update context here.\n // Context should only be updated after beforeLoad resolves to avoid\n // components seeing incomplete context during async beforeLoad execution.\n }))\n }\n\n const resolve = () => {\n match._nonReactive.beforeLoadPromise?.resolve()\n match._nonReactive.beforeLoadPromise = undefined\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: false,\n }))\n }\n\n // if there is no `beforeLoad` option, just mark as pending and resolve\n // Context will be updated later in loadRouteMatch after loader completes\n if (!route.options.beforeLoad) {\n batch(() => {\n pending()\n resolve()\n })\n return\n }\n\n match._nonReactive.beforeLoadPromise = createControlledPromise<void>()\n\n // Build context from all parent matches, excluding current match's __beforeLoadContext\n // (since we're about to execute beforeLoad for this match)\n const context = {\n ...buildMatchContext(inner, index, false),\n ...match.__routeContext,\n }\n const { search, params, cause } = match\n const preload = resolvePreload(inner, matchId)\n const beforeLoadFnContext: BeforeLoadContextOptions<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = {\n search,\n abortController,\n params,\n preload,\n context,\n location: inner.location,\n navigate: (opts: any) =>\n inner.router.navigate({\n ...opts,\n _fromLocation: inner.location,\n }),\n buildLocation: inner.router.buildLocation,\n cause: preload ? 'preload' : cause,\n matches: inner.matches,\n ...inner.router.options.additionalContext,\n }\n\n const updateContext = (beforeLoadContext: any) => {\n if (beforeLoadContext === undefined) {\n batch(() => {\n pending()\n resolve()\n })\n return\n }\n if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {\n pending()\n handleSerialError(inner, index, beforeLoadContext, 'BEFORE_LOAD')\n }\n\n batch(() => {\n pending()\n // Only store __beforeLoadContext here, don't update context yet\n // Context will be updated in loadRouteMatch after loader completes\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n __beforeLoadContext: beforeLoadContext,\n }))\n resolve()\n })\n }\n\n let beforeLoadContext\n try {\n beforeLoadContext = route.options.beforeLoad(beforeLoadFnContext)\n if (isPromise(beforeLoadContext)) {\n pending()\n return beforeLoadContext\n .catch((err) => {\n handleSerialError(inner, index, err, 'BEFORE_LOAD')\n })\n .then(updateContext)\n }\n } catch (err) {\n pending()\n handleSerialError(inner, index, err, 'BEFORE_LOAD')\n }\n\n updateContext(beforeLoadContext)\n return\n}\n\nconst handleBeforeLoad = (\n inner: InnerLoadContext,\n index: number,\n): void | Promise<void> => {\n const { id: matchId, routeId } = inner.matches[index]!\n const route = inner.router.looseRoutesById[routeId]!\n\n const serverSsr = () => {\n // on the server, determine whether SSR the current match or not\n if (isServer ?? inner.router.isServer) {\n const maybePromise = isBeforeLoadSsr(inner, matchId, index, route)\n if (isPromise(maybePromise)) return maybePromise.then(queueExecution)\n }\n return queueExecution()\n }\n\n const execute = () => executeBeforeLoad(inner, matchId, index, route)\n\n const queueExecution = () => {\n if (shouldSkipLoader(inner, matchId)) return\n const result = preBeforeLoadSetup(inner, matchId, route)\n return isPromise(result) ? result.then(execute) : execute()\n }\n\n return serverSsr()\n}\n\nconst executeHead = (\n inner: InnerLoadContext,\n matchId: string,\n route: AnyRoute,\n): void | Promise<\n Pick<\n AnyRouteMatch,\n 'meta' | 'links' | 'headScripts' | 'headers' | 'scripts' | 'styles'\n >\n> => {\n const match = inner.router.getMatch(matchId)\n // in case of a redirecting match during preload, the match does not exist\n if (!match) {\n return\n }\n if (!route.options.head && !route.options.scripts && !route.options.headers) {\n return\n }\n const assetContext = {\n ssr: inner.router.options.ssr,\n matches: inner.matches,\n match,\n params: match.params,\n loaderData: match.loaderData,\n }\n\n return Promise.all([\n route.options.head?.(assetContext),\n route.options.scripts?.(assetContext),\n route.options.headers?.(assetContext),\n ]).then(([headFnContent, scripts, headers]) => {\n const meta = headFnContent?.meta\n const links = headFnContent?.links\n const headScripts = headFnContent?.scripts\n const styles = headFnContent?.styles\n\n return {\n meta,\n links,\n headScripts,\n headers,\n scripts,\n styles,\n }\n })\n}\n\nconst getLoaderContext = (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): LoaderFnContext => {\n const parentMatchPromise = inner.matchPromises[index - 1] as any\n const { params, loaderDeps, abortController, cause } =\n inner.router.getMatch(matchId)!\n\n const context = buildMatchContext(inner, index)\n\n const preload = resolvePreload(inner, matchId)\n\n return {\n params,\n deps: loaderDeps,\n preload: !!preload,\n parentMatchPromise,\n abortController,\n context,\n location: inner.location,\n navigate: (opts) =>\n inner.router.navigate({\n ...opts,\n _fromLocation: inner.location,\n }),\n cause: preload ? 'preload' : cause,\n route,\n ...inner.router.options.additionalContext,\n }\n}\n\nconst runLoader = async (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): Promise<void> => {\n try {\n // If the Matches component rendered\n // the pending component and needs to show it for\n // a minimum duration, we''ll wait for it to resolve\n // before committing to the match and resolving\n // the loadPromise\n\n const match = inner.router.getMatch(matchId)!\n\n // Actually run the loader and handle the result\n try {\n if (!(isServer ?? inner.router.isServer) || match.ssr === true) {\n loadRouteChunk(route)\n }\n\n // Kick off the loader!\n const loaderResult = route.options.loader?.(\n getLoaderContext(inner, matchId, index, route),\n )\n const loaderResultIsPromise =\n route.options.loader && isPromise(loaderResult)\n\n const willLoadSomething = !!(\n loaderResultIsPromise ||\n route._lazyPromise ||\n route._componentsPromise ||\n route.options.head ||\n route.options.scripts ||\n route.options.headers ||\n match._nonReactive.minPendingPromise\n )\n\n if (willLoadSomething) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: 'loader',\n }))\n }\n\n if (route.options.loader) {\n const loaderData = loaderResultIsPromise\n ? await loaderResult\n : loaderResult\n\n handleRedirectAndNotFound(\n inner,\n inner.router.getMatch(matchId),\n loaderData,\n )\n if (loaderData !== undefined) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n loaderData,\n }))\n }\n }\n\n // Lazy option can modify the route options,\n // so we need to wait for it to resolve before\n // we can use the options\n if (route._lazyPromise) await route._lazyPromise\n const pendingPromise = match._nonReactive.minPendingPromise\n if (pendingPromise) await pendingPromise\n\n // Last but not least, wait for the the components\n // to be preloaded before we resolve the match\n if (route._componentsPromise) await route._componentsPromise\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n error: undefined,\n context: buildMatchContext(inner, index),\n status: 'success',\n isFetching: false,\n updatedAt: Date.now(),\n }))\n } catch (e) {\n let error = e\n\n if ((error as any)?.name === 'AbortError') {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n status: prev.status === 'pending' ? 'success' : prev.status,\n isFetching: false,\n context: buildMatchContext(inner, index),\n }))\n return\n }\n\n const pendingPromise = match._nonReactive.minPendingPromise\n if (pendingPromise) await pendingPromise\n\n if (isNotFound(e)) {\n await (route.options.notFoundComponent as any)?.preload?.()\n }\n\n handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), e)\n\n try {\n route.options.onError?.(e)\n } catch (onErrorError) {\n error = onErrorError\n handleRedirectAndNotFound(\n inner,\n inner.router.getMatch(matchId),\n onErrorError,\n )\n }\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n error,\n context: buildMatchContext(inner, index),\n status: 'error',\n isFetching: false,\n }))\n }\n } catch (err) {\n const match = inner.router.getMatch(matchId)\n // in case of a redirecting match during preload, the match does not exist\n if (match) {\n match._nonReactive.loaderPromise = undefined\n }\n handleRedirectAndNotFound(inner, match, err)\n }\n}\n\nconst loadRouteMatch = async (\n inner: InnerLoadContext,\n index: number,\n): Promise<AnyRouteMatch> => {\n const { id: matchId, routeId } = inner.matches[index]!\n let loaderShouldRunAsync = false\n let loaderIsRunningAsync = false\n const route = inner.router.looseRoutesById[routeId]!\n\n if (shouldSkipLoader(inner, matchId)) {\n if (isServer ?? inner.router.isServer) {\n return inner.router.getMatch(matchId)!\n }\n } else {\n const prevMatch = inner.router.getMatch(matchId)!\n // there is a loaderPromise, so we are in the middle of a load\n if (prevMatch._nonReactive.loaderPromise) {\n // do not block if we already have stale data we can show\n // but only if the ongoing load is not a preload since error handling is different for preloads\n // and we don't want to swallow errors\n if (prevMatch.status === 'success' && !inner.sync && !prevMatch.preload) {\n return prevMatch\n }\n await prevMatch._nonReactive.loaderPromise\n const match = inner.router.getMatch(matchId)!\n const error = match._nonReactive.error || match.error\n if (error) {\n handleRedirectAndNotFound(inner, match, error)\n }\n } else {\n // This is where all of the stale-while-revalidate magic happens\n const age = Date.now() - prevMatch.updatedAt\n\n const preload = resolvePreload(inner, matchId)\n\n const staleAge = preload\n ? (route.options.preloadStaleTime ??\n inner.router.options.defaultPreloadStaleTime ??\n 30_000) // 30 seconds for preloads by default\n : (route.options.staleTime ??\n inner.router.options.defaultStaleTime ??\n 0)\n\n const shouldReloadOption = route.options.shouldReload\n\n // Default to reloading the route all the time\n // Allow shouldReload to get the last say,\n // if provided.\n const shouldReload =\n typeof shouldReloadOption === 'function'\n ? shouldReloadOption(getLoaderContext(inner, matchId, index, route))\n : shouldReloadOption\n\n const nextPreload =\n !!preload && !inner.router.state.matches.some((d) => d.id === matchId)\n const match = inner.router.getMatch(matchId)!\n match._nonReactive.loaderPromise = createControlledPromise<void>()\n if (nextPreload !== match.preload) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n preload: nextPreload,\n }))\n }\n\n // If the route is successful and still fresh, just resolve\n const { status, invalid } = match\n loaderShouldRunAsync =\n status === 'success' && (invalid || (shouldReload ?? age > staleAge))\n if (preload && route.options.preload === false) {\n // Do nothing\n } else if (loaderShouldRunAsync && !inner.sync) {\n loaderIsRunningAsync = true\n ;(async () => {\n try {\n await runLoader(inner, matchId, index, route)\n const match = inner.router.getMatch(matchId)!\n match._nonReactive.loaderPromise?.resolve()\n match._nonReactive.loadPromise?.resolve()\n match._nonReactive.loaderPromise = undefined\n } catch (err) {\n if (isRedirect(err)) {\n await inner.router.navigate(err.options)\n }\n }\n })()\n } else if (status !== 'success' || (loaderShouldRunAsync && inner.sync)) {\n await runLoader(inner, matchId, index, route)\n }\n }\n }\n const match = inner.router.getMatch(matchId)!\n if (!loaderIsRunningAsync) {\n match._nonReactive.loaderPromise?.resolve()\n match._nonReactive.loadPromise?.resolve()\n }\n\n clearTimeout(match._nonReactive.pendingTimeout)\n match._nonReactive.pendingTimeout = undefined\n if (!loaderIsRunningAsync) match._nonReactive.loaderPromise = undefined\n match._nonReactive.dehydrated = undefined\n\n const nextIsFetching = loaderIsRunningAsync ? match.isFetching : false\n if (nextIsFetching !== match.isFetching || match.invalid !== false) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: nextIsFetching,\n invalid: false,\n }))\n return inner.router.getMatch(matchId)!\n } else {\n return match\n }\n}\n\nexport async function loadMatches(arg: {\n router: AnyRouter\n location: ParsedLocation\n matches: Array<AnyRouteMatch>\n preload?: boolean\n onReady?: () => Promise<void>\n updateMatch: UpdateMatchFn\n sync?: boolean\n}): Promise<Array<MakeRouteMatch>> {\n const inner: InnerLoadContext = Object.assign(arg, {\n matchPromises: [],\n })\n\n // make sure the pending component is immediately rendered when hydrating a match that is not SSRed\n // the pending component was already rendered on the server and we want to keep it shown on the client until minPendingMs is reached\n if (\n !(isServer ?? inner.router.isServer) &&\n inner.router.state.matches.some((d) => d._forcePending)\n ) {\n triggerOnReady(inner)\n }\n\n try {\n // Execute all beforeLoads one by one\n for (let i = 0; i < inner.matches.length; i++) {\n const beforeLoad = handleBeforeLoad(inner, i)\n if (isPromise(beforeLoad)) await beforeLoad\n }\n\n // Execute all loaders in parallel\n const max = inner.firstBadMatchIndex ?? inner.matches.length\n for (let i = 0; i < max; i++) {\n inner.matchPromises.push(loadRouteMatch(inner, i))\n }\n // Use allSettled to ensure all loaders complete regardless of success/failure\n const results = await Promise.allSettled(inner.matchPromises)\n\n const failures = results\n // TODO when we drop support for TS 5.4, we can use the built-in type guard for PromiseRejectedResult\n .filter(\n (result): result is PromiseRejectedResult =>\n result.status === 'rejected',\n )\n .map((result) => result.reason)\n\n // Find first redirect (throw immediately) or notFound (throw after head execution)\n let firstNotFound: unknown\n for (const err of failures) {\n if (isRedirect(err)) {\n throw err\n }\n if (!firstNotFound && isNotFound(err)) {\n firstNotFound = err\n }\n }\n\n // serially execute head functions after all loaders have completed (successfully or not)\n // Each head execution is wrapped in try-catch to ensure all heads run even if one fails\n for (const match of inner.matches) {\n const { id: matchId, routeId } = match\n const route = inner.router.looseRoutesById[routeId]!\n try {\n const headResult = executeHead(inner, matchId, route)\n if (headResult) {\n const head = await headResult\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n ...head,\n }))\n }\n } catch (err) {\n // Log error but continue executing other head functions\n console.error(`Error executing head for route ${routeId}:`, err)\n }\n }\n\n // Throw notFound after head execution\n if (firstNotFound) {\n throw firstNotFound\n }\n\n const readyPromise = triggerOnReady(inner)\n if (isPromise(readyPromise)) await readyPromise\n } catch (err) {\n if (isNotFound(err) && !inner.preload) {\n const readyPromise = triggerOnReady(inner)\n if (isPromise(readyPromise)) await readyPromise\n throw err\n }\n if (isRedirect(err)) {\n throw err\n }\n }\n return inner.matches\n}\n\nexport async function loadRouteChunk(route: AnyRoute) {\n if (!route._lazyLoaded && route._lazyPromise === undefined) {\n if (route.lazyFn) {\n route._lazyPromise = route.lazyFn().then((lazyRoute) => {\n // explicitly don't copy over the lazy route's id\n const { id: _id, ...options } = lazyRoute.options\n Object.assign(route.options, options)\n route._lazyLoaded = true\n route._lazyPromise = undefined // gc promise, we won't need it anymore\n })\n } else {\n route._lazyLoaded = true\n }\n }\n\n // If for some reason lazy resolves more lazy components...\n // We'll wait for that before we attempt to preload the\n // components themselves.\n if (!route._componentsLoaded && route._componentsPromise === undefined) {\n const loadComponents = () => {\n const preloads = []\n for (const type of componentTypes) {\n const preload = (route.options[type] as any)?.preload\n if (preload) preloads.push(preload())\n }\n if (preloads.length)\n return Promise.all(preloads).then(() => {\n route._componentsLoaded = true\n route._componentsPromise = undefined // gc promise, we won't need it anymore\n })\n route._componentsLoaded = true\n route._componentsPromise = undefined // gc promise, we won't need it anymore\n return\n }\n route._componentsPromise = route._lazyPromise\n ? route._lazyPromise.then(loadComponents)\n : loadComponents()\n }\n return route._componentsPromise\n}\n\nfunction makeMaybe<TValue, TError>(\n value: TValue,\n error: TError,\n): { status: 'success'; value: TValue } | { status: 'error'; error: TError } {\n if (error) {\n return { status: 'error' as const, error }\n }\n return { status: 'success' as const, value }\n}\n\nexport function routeNeedsPreload(route: AnyRoute) {\n for (const componentType of componentTypes) {\n if ((route.options[componentType] as any)?.preload) {\n return true\n }\n }\n return false\n}\n\nexport const componentTypes = [\n 'component',\n 'errorComponent',\n 'pendingComponent',\n 'notFoundComponent',\n] as const\n"],"names":["tempSsr","beforeLoadContext","match"],"mappings":"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"}
1
+ {"version":3,"file":"load-matches.js","sources":["../../src/load-matches.ts"],"sourcesContent":["import { batch } from '@tanstack/store'\nimport invariant from 'tiny-invariant'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { createControlledPromise, isPromise } from './utils'\nimport { isNotFound } from './not-found'\nimport { rootRouteId } from './root'\nimport { isRedirect } from './redirect'\nimport type { NotFoundError } from './not-found'\nimport type { ParsedLocation } from './location'\nimport type {\n AnyRoute,\n BeforeLoadContextOptions,\n LoaderFnContext,\n SsrContextOptions,\n} from './route'\nimport type { AnyRouteMatch, MakeRouteMatch } from './Matches'\nimport type { AnyRouter, SSROption, UpdateMatchFn } from './router'\n\n/**\n * An object of this shape is created when calling `loadMatches`.\n * It contains everything we need for all other functions in this file\n * to work. (It's basically the function's argument, plus a few mutable states)\n */\ntype InnerLoadContext = {\n /** the calling router instance */\n router: AnyRouter\n location: ParsedLocation\n /** mutable state, scoped to a `loadMatches` call */\n firstBadMatchIndex?: number\n /** mutable state, scoped to a `loadMatches` call */\n rendered?: boolean\n updateMatch: UpdateMatchFn\n matches: Array<AnyRouteMatch>\n preload?: boolean\n onReady?: () => Promise<void>\n sync?: boolean\n /** mutable state, scoped to a `loadMatches` call */\n matchPromises: Array<Promise<AnyRouteMatch>>\n}\n\nconst triggerOnReady = (inner: InnerLoadContext): void | Promise<void> => {\n if (!inner.rendered) {\n inner.rendered = true\n return inner.onReady?.()\n }\n}\n\nconst resolvePreload = (inner: InnerLoadContext, matchId: string): boolean => {\n return !!(\n inner.preload && !inner.router.state.matches.some((d) => d.id === matchId)\n )\n}\n\n/**\n * Builds the accumulated context from router options and all matches up to (and optionally including) the given index.\n * Merges __routeContext and __beforeLoadContext from each match.\n */\nconst buildMatchContext = (\n inner: InnerLoadContext,\n index: number,\n includeCurrentMatch: boolean = true,\n): Record<string, unknown> => {\n const context: Record<string, unknown> = {\n ...(inner.router.options.context ?? {}),\n }\n const end = includeCurrentMatch ? index : index - 1\n for (let i = 0; i <= end; i++) {\n const innerMatch = inner.matches[i]\n if (!innerMatch) continue\n const m = inner.router.getMatch(innerMatch.id)\n if (!m) continue\n Object.assign(context, m.__routeContext, m.__beforeLoadContext)\n }\n return context\n}\n\nconst _handleNotFound = (inner: InnerLoadContext, err: NotFoundError) => {\n // Find the route that should handle the not found error\n // First check if a specific route is requested to show the error\n const routeCursor =\n inner.router.routesById[err.routeId ?? ''] ?? inner.router.routeTree\n\n // Ensure a NotFoundComponent exists on the route\n if (\n !routeCursor.options.notFoundComponent &&\n (inner.router.options as any)?.defaultNotFoundComponent\n ) {\n routeCursor.options.notFoundComponent = (\n inner.router.options as any\n ).defaultNotFoundComponent\n }\n\n // Ensure we have a notFoundComponent\n invariant(\n routeCursor.options.notFoundComponent,\n 'No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router.',\n )\n\n // Find the match for this route\n const matchForRoute = inner.matches.find((m) => m.routeId === routeCursor.id)\n\n invariant(matchForRoute, 'Could not find match for route: ' + routeCursor.id)\n\n // Assign the error to the match - using non-null assertion since we've checked with invariant\n inner.updateMatch(matchForRoute.id, (prev) => ({\n ...prev,\n status: 'notFound',\n error: err,\n isFetching: false,\n }))\n\n if ((err as any).routerCode === 'BEFORE_LOAD' && routeCursor.parentRoute) {\n err.routeId = routeCursor.parentRoute.id\n _handleNotFound(inner, err)\n }\n}\n\nconst handleRedirectAndNotFound = (\n inner: InnerLoadContext,\n match: AnyRouteMatch | undefined,\n err: unknown,\n): void => {\n if (!isRedirect(err) && !isNotFound(err)) return\n\n if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) {\n throw err\n }\n\n // in case of a redirecting match during preload, the match does not exist\n if (match) {\n match._nonReactive.beforeLoadPromise?.resolve()\n match._nonReactive.loaderPromise?.resolve()\n match._nonReactive.beforeLoadPromise = undefined\n match._nonReactive.loaderPromise = undefined\n\n const status = isRedirect(err) ? 'redirected' : 'notFound'\n\n match._nonReactive.error = err\n\n inner.updateMatch(match.id, (prev) => ({\n ...prev,\n status,\n context: buildMatchContext(inner, match.index),\n isFetching: false,\n error: err,\n }))\n\n if (isNotFound(err) && !err.routeId) {\n err.routeId = match.routeId\n }\n\n match._nonReactive.loadPromise?.resolve()\n }\n\n if (isRedirect(err)) {\n inner.rendered = true\n err.options._fromLocation = inner.location\n err.redirectHandled = true\n err = inner.router.resolveRedirect(err)\n throw err\n } else {\n _handleNotFound(inner, err)\n throw err\n }\n}\n\nconst shouldSkipLoader = (\n inner: InnerLoadContext,\n matchId: string,\n): boolean => {\n const match = inner.router.getMatch(matchId)!\n // upon hydration, we skip the loader if the match has been dehydrated on the server\n if (!(isServer ?? inner.router.isServer) && match._nonReactive.dehydrated) {\n return true\n }\n\n if ((isServer ?? inner.router.isServer) && match.ssr === false) {\n return true\n }\n\n return false\n}\n\nconst handleSerialError = (\n inner: InnerLoadContext,\n index: number,\n err: any,\n routerCode: string,\n): void => {\n const { id: matchId, routeId } = inner.matches[index]!\n const route = inner.router.looseRoutesById[routeId]!\n\n // Much like suspense, we use a promise here to know if\n // we've been outdated by a new loadMatches call and\n // should abort the current async operation\n if (err instanceof Promise) {\n throw err\n }\n\n err.routerCode = routerCode\n inner.firstBadMatchIndex ??= index\n handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), err)\n\n try {\n route.options.onError?.(err)\n } catch (errorHandlerErr) {\n err = errorHandlerErr\n handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), err)\n }\n\n inner.updateMatch(matchId, (prev) => {\n prev._nonReactive.beforeLoadPromise?.resolve()\n prev._nonReactive.beforeLoadPromise = undefined\n prev._nonReactive.loadPromise?.resolve()\n\n return {\n ...prev,\n error: err,\n status: 'error',\n isFetching: false,\n updatedAt: Date.now(),\n abortController: new AbortController(),\n }\n })\n}\n\nconst isBeforeLoadSsr = (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): void | Promise<void> => {\n const existingMatch = inner.router.getMatch(matchId)!\n const parentMatchId = inner.matches[index - 1]?.id\n const parentMatch = parentMatchId\n ? inner.router.getMatch(parentMatchId)!\n : undefined\n\n // in SPA mode, only SSR the root route\n if (inner.router.isShell()) {\n existingMatch.ssr = route.id === rootRouteId\n return\n }\n\n if (parentMatch?.ssr === false) {\n existingMatch.ssr = false\n return\n }\n\n const parentOverride = (tempSsr: SSROption) => {\n if (tempSsr === true && parentMatch?.ssr === 'data-only') {\n return 'data-only'\n }\n return tempSsr\n }\n\n const defaultSsr = inner.router.options.defaultSsr ?? true\n\n if (route.options.ssr === undefined) {\n existingMatch.ssr = parentOverride(defaultSsr)\n return\n }\n\n if (typeof route.options.ssr !== 'function') {\n existingMatch.ssr = parentOverride(route.options.ssr)\n return\n }\n const { search, params } = existingMatch\n\n const ssrFnContext: SsrContextOptions<any, any, any> = {\n search: makeMaybe(search, existingMatch.searchError),\n params: makeMaybe(params, existingMatch.paramsError),\n location: inner.location,\n matches: inner.matches.map((match) => ({\n index: match.index,\n pathname: match.pathname,\n fullPath: match.fullPath,\n staticData: match.staticData,\n id: match.id,\n routeId: match.routeId,\n search: makeMaybe(match.search, match.searchError),\n params: makeMaybe(match.params, match.paramsError),\n ssr: match.ssr,\n })),\n }\n\n const tempSsr = route.options.ssr(ssrFnContext)\n if (isPromise(tempSsr)) {\n return tempSsr.then((ssr) => {\n existingMatch.ssr = parentOverride(ssr ?? defaultSsr)\n })\n }\n\n existingMatch.ssr = parentOverride(tempSsr ?? defaultSsr)\n return\n}\n\nconst setupPendingTimeout = (\n inner: InnerLoadContext,\n matchId: string,\n route: AnyRoute,\n match: AnyRouteMatch,\n): void => {\n if (match._nonReactive.pendingTimeout !== undefined) return\n\n const pendingMs =\n route.options.pendingMs ?? inner.router.options.defaultPendingMs\n const shouldPending = !!(\n inner.onReady &&\n !(isServer ?? inner.router.isServer) &&\n !resolvePreload(inner, matchId) &&\n (route.options.loader ||\n route.options.beforeLoad ||\n routeNeedsPreload(route)) &&\n typeof pendingMs === 'number' &&\n pendingMs !== Infinity &&\n (route.options.pendingComponent ??\n (inner.router.options as any)?.defaultPendingComponent)\n )\n\n if (shouldPending) {\n const pendingTimeout = setTimeout(() => {\n // Update the match and prematurely resolve the loadMatches promise so that\n // the pending component can start rendering\n triggerOnReady(inner)\n }, pendingMs)\n match._nonReactive.pendingTimeout = pendingTimeout\n }\n}\n\nconst preBeforeLoadSetup = (\n inner: InnerLoadContext,\n matchId: string,\n route: AnyRoute,\n): void | Promise<void> => {\n const existingMatch = inner.router.getMatch(matchId)!\n\n // If we are in the middle of a load, either of these will be present\n // (not to be confused with `loadPromise`, which is always defined)\n if (\n !existingMatch._nonReactive.beforeLoadPromise &&\n !existingMatch._nonReactive.loaderPromise\n )\n return\n\n setupPendingTimeout(inner, matchId, route, existingMatch)\n\n const then = () => {\n const match = inner.router.getMatch(matchId)!\n if (\n match.preload &&\n (match.status === 'redirected' || match.status === 'notFound')\n ) {\n handleRedirectAndNotFound(inner, match, match.error)\n }\n }\n\n // Wait for the previous beforeLoad to resolve before we continue\n return existingMatch._nonReactive.beforeLoadPromise\n ? existingMatch._nonReactive.beforeLoadPromise.then(then)\n : then()\n}\n\nconst executeBeforeLoad = (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): void | Promise<void> => {\n const match = inner.router.getMatch(matchId)!\n\n // explicitly capture the previous loadPromise\n const prevLoadPromise = match._nonReactive.loadPromise\n match._nonReactive.loadPromise = createControlledPromise<void>(() => {\n prevLoadPromise?.resolve()\n })\n\n const { paramsError, searchError } = match\n\n if (paramsError) {\n handleSerialError(inner, index, paramsError, 'PARSE_PARAMS')\n }\n\n if (searchError) {\n handleSerialError(inner, index, searchError, 'VALIDATE_SEARCH')\n }\n\n setupPendingTimeout(inner, matchId, route, match)\n\n const abortController = new AbortController()\n\n const parentMatchId = inner.matches[index - 1]?.id\n const parentMatch = parentMatchId\n ? inner.router.getMatch(parentMatchId)!\n : undefined\n const parentMatchContext =\n parentMatch?.context ?? inner.router.options.context ?? undefined\n\n let isPending = false\n const pending = () => {\n if (isPending) return\n isPending = true\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: 'beforeLoad',\n fetchCount: prev.fetchCount + 1,\n abortController,\n // Note: We intentionally don't update context here.\n // Context should only be updated after beforeLoad resolves to avoid\n // components seeing incomplete context during async beforeLoad execution.\n }))\n }\n\n const resolve = () => {\n match._nonReactive.beforeLoadPromise?.resolve()\n match._nonReactive.beforeLoadPromise = undefined\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: false,\n }))\n }\n\n // if there is no `beforeLoad` option, just mark as pending and resolve\n // Context will be updated later in loadRouteMatch after loader completes\n if (!route.options.beforeLoad) {\n batch(() => {\n pending()\n resolve()\n })\n return\n }\n\n match._nonReactive.beforeLoadPromise = createControlledPromise<void>()\n\n // Build context from all parent matches, excluding current match's __beforeLoadContext\n // (since we're about to execute beforeLoad for this match)\n const context = {\n ...buildMatchContext(inner, index, false),\n ...match.__routeContext,\n }\n const { search, params, cause } = match\n const preload = resolvePreload(inner, matchId)\n const beforeLoadFnContext: BeforeLoadContextOptions<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = {\n search,\n abortController,\n params,\n preload,\n context,\n location: inner.location,\n navigate: (opts: any) =>\n inner.router.navigate({\n ...opts,\n _fromLocation: inner.location,\n }),\n buildLocation: inner.router.buildLocation,\n cause: preload ? 'preload' : cause,\n matches: inner.matches,\n ...inner.router.options.additionalContext,\n }\n\n const updateContext = (beforeLoadContext: any) => {\n if (beforeLoadContext === undefined) {\n batch(() => {\n pending()\n resolve()\n })\n return\n }\n if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {\n pending()\n handleSerialError(inner, index, beforeLoadContext, 'BEFORE_LOAD')\n }\n\n batch(() => {\n pending()\n // Only store __beforeLoadContext here, don't update context yet\n // Context will be updated in loadRouteMatch after loader completes\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n __beforeLoadContext: beforeLoadContext,\n }))\n resolve()\n })\n }\n\n let beforeLoadContext\n try {\n beforeLoadContext = route.options.beforeLoad(beforeLoadFnContext)\n if (isPromise(beforeLoadContext)) {\n pending()\n return beforeLoadContext\n .catch((err) => {\n handleSerialError(inner, index, err, 'BEFORE_LOAD')\n })\n .then(updateContext)\n }\n } catch (err) {\n pending()\n handleSerialError(inner, index, err, 'BEFORE_LOAD')\n }\n\n updateContext(beforeLoadContext)\n return\n}\n\nconst handleBeforeLoad = (\n inner: InnerLoadContext,\n index: number,\n): void | Promise<void> => {\n const { id: matchId, routeId } = inner.matches[index]!\n const route = inner.router.looseRoutesById[routeId]!\n\n const serverSsr = () => {\n // on the server, determine whether SSR the current match or not\n if (isServer ?? inner.router.isServer) {\n const maybePromise = isBeforeLoadSsr(inner, matchId, index, route)\n if (isPromise(maybePromise)) return maybePromise.then(queueExecution)\n }\n return queueExecution()\n }\n\n const execute = () => executeBeforeLoad(inner, matchId, index, route)\n\n const queueExecution = () => {\n if (shouldSkipLoader(inner, matchId)) return\n const result = preBeforeLoadSetup(inner, matchId, route)\n return isPromise(result) ? result.then(execute) : execute()\n }\n\n return serverSsr()\n}\n\nconst executeHead = (\n inner: InnerLoadContext,\n matchId: string,\n route: AnyRoute,\n): void | Promise<\n Pick<\n AnyRouteMatch,\n 'meta' | 'links' | 'headScripts' | 'headers' | 'scripts' | 'styles'\n >\n> => {\n const match = inner.router.getMatch(matchId)\n // in case of a redirecting match during preload, the match does not exist\n if (!match) {\n return\n }\n if (!route.options.head && !route.options.scripts && !route.options.headers) {\n return\n }\n const assetContext = {\n ssr: inner.router.options.ssr,\n matches: inner.matches,\n match,\n params: match.params,\n loaderData: match.loaderData,\n }\n\n return Promise.all([\n route.options.head?.(assetContext),\n route.options.scripts?.(assetContext),\n route.options.headers?.(assetContext),\n ]).then(([headFnContent, scripts, headers]) => {\n const meta = headFnContent?.meta\n const links = headFnContent?.links\n const headScripts = headFnContent?.scripts\n const styles = headFnContent?.styles\n\n return {\n meta,\n links,\n headScripts,\n headers,\n scripts,\n styles,\n }\n })\n}\n\nconst getLoaderContext = (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): LoaderFnContext => {\n const parentMatchPromise = inner.matchPromises[index - 1] as any\n const { params, loaderDeps, abortController, cause } =\n inner.router.getMatch(matchId)!\n\n const context = buildMatchContext(inner, index)\n\n const preload = resolvePreload(inner, matchId)\n\n return {\n params,\n deps: loaderDeps,\n preload: !!preload,\n parentMatchPromise,\n abortController,\n context,\n location: inner.location,\n navigate: (opts) =>\n inner.router.navigate({\n ...opts,\n _fromLocation: inner.location,\n }),\n cause: preload ? 'preload' : cause,\n route,\n ...inner.router.options.additionalContext,\n }\n}\n\nconst runLoader = async (\n inner: InnerLoadContext,\n matchId: string,\n index: number,\n route: AnyRoute,\n): Promise<void> => {\n try {\n // If the Matches component rendered\n // the pending component and needs to show it for\n // a minimum duration, we''ll wait for it to resolve\n // before committing to the match and resolving\n // the loadPromise\n\n const match = inner.router.getMatch(matchId)!\n\n // Actually run the loader and handle the result\n try {\n if (!(isServer ?? inner.router.isServer) || match.ssr === true) {\n loadRouteChunk(route)\n }\n\n // Kick off the loader!\n const loaderResult = route.options.loader?.(\n getLoaderContext(inner, matchId, index, route),\n )\n const loaderResultIsPromise =\n route.options.loader && isPromise(loaderResult)\n\n const willLoadSomething = !!(\n loaderResultIsPromise ||\n route._lazyPromise ||\n route._componentsPromise ||\n route.options.head ||\n route.options.scripts ||\n route.options.headers ||\n match._nonReactive.minPendingPromise\n )\n\n if (willLoadSomething) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: 'loader',\n }))\n }\n\n if (route.options.loader) {\n const loaderData = loaderResultIsPromise\n ? await loaderResult\n : loaderResult\n\n handleRedirectAndNotFound(\n inner,\n inner.router.getMatch(matchId),\n loaderData,\n )\n if (loaderData !== undefined) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n loaderData,\n }))\n }\n }\n\n // Lazy option can modify the route options,\n // so we need to wait for it to resolve before\n // we can use the options\n if (route._lazyPromise) await route._lazyPromise\n const pendingPromise = match._nonReactive.minPendingPromise\n if (pendingPromise) await pendingPromise\n\n // Last but not least, wait for the the components\n // to be preloaded before we resolve the match\n if (route._componentsPromise) await route._componentsPromise\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n error: undefined,\n context: buildMatchContext(inner, index),\n status: 'success',\n isFetching: false,\n updatedAt: Date.now(),\n }))\n } catch (e) {\n let error = e\n\n if ((error as any)?.name === 'AbortError') {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n status: prev.status === 'pending' ? 'success' : prev.status,\n isFetching: false,\n context: buildMatchContext(inner, index),\n }))\n return\n }\n\n const pendingPromise = match._nonReactive.minPendingPromise\n if (pendingPromise) await pendingPromise\n\n if (isNotFound(e)) {\n await (route.options.notFoundComponent as any)?.preload?.()\n }\n\n handleRedirectAndNotFound(inner, inner.router.getMatch(matchId), e)\n\n try {\n route.options.onError?.(e)\n } catch (onErrorError) {\n error = onErrorError\n handleRedirectAndNotFound(\n inner,\n inner.router.getMatch(matchId),\n onErrorError,\n )\n }\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n error,\n context: buildMatchContext(inner, index),\n status: 'error',\n isFetching: false,\n }))\n }\n } catch (err) {\n const match = inner.router.getMatch(matchId)\n // in case of a redirecting match during preload, the match does not exist\n if (match) {\n match._nonReactive.loaderPromise = undefined\n }\n handleRedirectAndNotFound(inner, match, err)\n }\n}\n\nconst loadRouteMatch = async (\n inner: InnerLoadContext,\n index: number,\n): Promise<AnyRouteMatch> => {\n const { id: matchId, routeId } = inner.matches[index]!\n let loaderShouldRunAsync = false\n let loaderIsRunningAsync = false\n const route = inner.router.looseRoutesById[routeId]!\n\n if (shouldSkipLoader(inner, matchId)) {\n if (isServer ?? inner.router.isServer) {\n return inner.router.getMatch(matchId)!\n }\n } else {\n const prevMatch = inner.router.getMatch(matchId)!\n // there is a loaderPromise, so we are in the middle of a load\n if (prevMatch._nonReactive.loaderPromise) {\n // do not block if we already have stale data we can show\n // but only if the ongoing load is not a preload since error handling is different for preloads\n // and we don't want to swallow errors\n if (prevMatch.status === 'success' && !inner.sync && !prevMatch.preload) {\n return prevMatch\n }\n await prevMatch._nonReactive.loaderPromise\n const match = inner.router.getMatch(matchId)!\n const error = match._nonReactive.error || match.error\n if (error) {\n handleRedirectAndNotFound(inner, match, error)\n }\n } else {\n // This is where all of the stale-while-revalidate magic happens\n const age = Date.now() - prevMatch.updatedAt\n\n const preload = resolvePreload(inner, matchId)\n\n const staleAge = preload\n ? (route.options.preloadStaleTime ??\n inner.router.options.defaultPreloadStaleTime ??\n 30_000) // 30 seconds for preloads by default\n : (route.options.staleTime ??\n inner.router.options.defaultStaleTime ??\n 0)\n\n const shouldReloadOption = route.options.shouldReload\n\n // Default to reloading the route all the time\n // Allow shouldReload to get the last say,\n // if provided.\n const shouldReload =\n typeof shouldReloadOption === 'function'\n ? shouldReloadOption(getLoaderContext(inner, matchId, index, route))\n : shouldReloadOption\n\n const nextPreload =\n !!preload && !inner.router.state.matches.some((d) => d.id === matchId)\n const match = inner.router.getMatch(matchId)!\n match._nonReactive.loaderPromise = createControlledPromise<void>()\n if (nextPreload !== match.preload) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n preload: nextPreload,\n }))\n }\n\n // If the route is successful and still fresh, just resolve\n const { status, invalid } = match\n loaderShouldRunAsync =\n status === 'success' && (invalid || (shouldReload ?? age > staleAge))\n if (preload && route.options.preload === false) {\n // Do nothing\n } else if (loaderShouldRunAsync && !inner.sync) {\n loaderIsRunningAsync = true\n ;(async () => {\n try {\n await runLoader(inner, matchId, index, route)\n const match = inner.router.getMatch(matchId)!\n match._nonReactive.loaderPromise?.resolve()\n match._nonReactive.loadPromise?.resolve()\n match._nonReactive.loaderPromise = undefined\n } catch (err) {\n if (isRedirect(err)) {\n await inner.router.navigate(err.options)\n }\n }\n })()\n } else if (status !== 'success' || (loaderShouldRunAsync && inner.sync)) {\n await runLoader(inner, matchId, index, route)\n }\n }\n }\n const match = inner.router.getMatch(matchId)!\n if (!loaderIsRunningAsync) {\n match._nonReactive.loaderPromise?.resolve()\n match._nonReactive.loadPromise?.resolve()\n }\n\n clearTimeout(match._nonReactive.pendingTimeout)\n match._nonReactive.pendingTimeout = undefined\n if (!loaderIsRunningAsync) match._nonReactive.loaderPromise = undefined\n match._nonReactive.dehydrated = undefined\n\n const nextIsFetching = loaderIsRunningAsync ? match.isFetching : false\n if (nextIsFetching !== match.isFetching || match.invalid !== false) {\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n isFetching: nextIsFetching,\n invalid: false,\n }))\n return inner.router.getMatch(matchId)!\n } else {\n return match\n }\n}\n\nexport async function loadMatches(arg: {\n router: AnyRouter\n location: ParsedLocation\n matches: Array<AnyRouteMatch>\n preload?: boolean\n onReady?: () => Promise<void>\n updateMatch: UpdateMatchFn\n sync?: boolean\n}): Promise<Array<MakeRouteMatch>> {\n const inner: InnerLoadContext = Object.assign(arg, {\n matchPromises: [],\n })\n\n // make sure the pending component is immediately rendered when hydrating a match that is not SSRed\n // the pending component was already rendered on the server and we want to keep it shown on the client until minPendingMs is reached\n if (\n !(isServer ?? inner.router.isServer) &&\n inner.router.state.matches.some((d) => d._forcePending)\n ) {\n triggerOnReady(inner)\n }\n\n try {\n // Execute all beforeLoads one by one\n for (let i = 0; i < inner.matches.length; i++) {\n const beforeLoad = handleBeforeLoad(inner, i)\n if (isPromise(beforeLoad)) await beforeLoad\n }\n\n // Execute all loaders in parallel\n const max = inner.firstBadMatchIndex ?? inner.matches.length\n for (let i = 0; i < max; i++) {\n inner.matchPromises.push(loadRouteMatch(inner, i))\n }\n // Use allSettled to ensure all loaders complete regardless of success/failure\n const results = await Promise.allSettled(inner.matchPromises)\n\n const failures = results\n // TODO when we drop support for TS 5.4, we can use the built-in type guard for PromiseRejectedResult\n .filter(\n (result): result is PromiseRejectedResult =>\n result.status === 'rejected',\n )\n .map((result) => result.reason)\n\n // Find first redirect (throw immediately) or notFound (throw after head execution)\n let firstNotFound: unknown\n for (const err of failures) {\n if (isRedirect(err)) {\n throw err\n }\n if (!firstNotFound && isNotFound(err)) {\n firstNotFound = err\n }\n }\n\n // serially execute head functions after all loaders have completed (successfully or not)\n // Each head execution is wrapped in try-catch to ensure all heads run even if one fails\n for (const match of inner.matches) {\n const { id: matchId, routeId } = match\n const route = inner.router.looseRoutesById[routeId]!\n try {\n const headResult = executeHead(inner, matchId, route)\n if (headResult) {\n const head = await headResult\n inner.updateMatch(matchId, (prev) => ({\n ...prev,\n ...head,\n }))\n }\n } catch (err) {\n // Log error but continue executing other head functions\n console.error(`Error executing head for route ${routeId}:`, err)\n }\n }\n\n // Throw notFound after head execution\n if (firstNotFound) {\n throw firstNotFound\n }\n\n const readyPromise = triggerOnReady(inner)\n if (isPromise(readyPromise)) await readyPromise\n } catch (err) {\n if (isNotFound(err) && !inner.preload) {\n const readyPromise = triggerOnReady(inner)\n if (isPromise(readyPromise)) await readyPromise\n throw err\n }\n if (isRedirect(err)) {\n throw err\n }\n }\n return inner.matches\n}\n\nexport async function loadRouteChunk(route: AnyRoute) {\n if (!route._lazyLoaded && route._lazyPromise === undefined) {\n if (route.lazyFn) {\n route._lazyPromise = route.lazyFn().then((lazyRoute) => {\n // explicitly don't copy over the lazy route's id\n const { id: _id, ...options } = lazyRoute.options\n Object.assign(route.options, options)\n route._lazyLoaded = true\n route._lazyPromise = undefined // gc promise, we won't need it anymore\n })\n } else {\n route._lazyLoaded = true\n }\n }\n\n // If for some reason lazy resolves more lazy components...\n // We'll wait for that before we attempt to preload the\n // components themselves.\n if (!route._componentsLoaded && route._componentsPromise === undefined) {\n const loadComponents = () => {\n const preloads = []\n for (const type of componentTypes) {\n const preload = (route.options[type] as any)?.preload\n if (preload) preloads.push(preload())\n }\n if (preloads.length)\n return Promise.all(preloads).then(() => {\n route._componentsLoaded = true\n route._componentsPromise = undefined // gc promise, we won't need it anymore\n })\n route._componentsLoaded = true\n route._componentsPromise = undefined // gc promise, we won't need it anymore\n return\n }\n route._componentsPromise = route._lazyPromise\n ? route._lazyPromise.then(loadComponents)\n : loadComponents()\n }\n return route._componentsPromise\n}\n\nfunction makeMaybe<TValue, TError>(\n value: TValue,\n error: TError,\n): { status: 'success'; value: TValue } | { status: 'error'; error: TError } {\n if (error) {\n return { status: 'error' as const, error }\n }\n return { status: 'success' as const, value }\n}\n\nexport function routeNeedsPreload(route: AnyRoute) {\n for (const componentType of componentTypes) {\n if ((route.options[componentType] as any)?.preload) {\n return true\n }\n }\n return false\n}\n\nexport const componentTypes = [\n 'component',\n 'errorComponent',\n 'pendingComponent',\n 'notFoundComponent',\n] as const\n"],"names":["tempSsr","beforeLoadContext","match"],"mappings":"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"}
@@ -43,8 +43,7 @@ export interface ParsedLocation<TSearchObj extends AnySchema = {}> {
43
43
  publicHref: string;
44
44
  /**
45
45
  * @private
46
- * @description The full URL of the location.
47
- * @private
46
+ * @description Whether the publicHref is external (different origin from rewrite).
48
47
  */
49
- url: URL;
48
+ external: boolean;
50
49
  }