{"version":3,"file":"ssr-server.cjs","names":[],"sources":["../../../src/ssr/ssr-server.ts"],"sourcesContent":["import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'\nimport { invariant } from '../invariant'\nimport {\n  createInlineCssPlaceholderAsset,\n  createInlineCssStyleAsset,\n  getStylesheetHref,\n  isInlinableStylesheet,\n} from '../manifest'\nimport { decodePath } from '../utils'\nimport { createLRUCache } from '../lru-cache'\nimport { rootRouteId } from '../root'\nimport minifiedTsrBootStrapScript from './tsrScript?script-string'\nimport { GLOBAL_TSR, TSR_SCRIPT_BARRIER_ID } from './constants'\nimport { dehydrateSsrMatchId } from './ssr-match-id'\nimport { defaultSerovalPlugins } from './serializer/seroval-plugins'\nimport { makeSsrSerovalPlugin } from './serializer/transformer'\nimport type { LRUCache } from '../lru-cache'\nimport type { DehydratedMatch, DehydratedRouter } from './types'\nimport type { AnySerializationAdapter } from './serializer/transformer'\nimport type { AnyRouter } from '../router'\nimport type { AnyRouteMatch } from '../Matches'\nimport type { Manifest, RouterManagedTag } from '../manifest'\n\ndeclare module '../router' {\n  interface ServerSsr {\n    setRenderFinished: () => void\n    cleanup: () => void\n  }\n  interface RouterEvents {\n    onInjectedHtml: {\n      type: 'onInjectedHtml'\n    }\n    onSerializationFinished: {\n      type: 'onSerializationFinished'\n    }\n  }\n}\n\nconst SCOPE_ID = 'tsr'\n\nconst TSR_PREFIX = GLOBAL_TSR + '.router='\nconst P_PREFIX = GLOBAL_TSR + '.p(()=>'\nconst P_SUFFIX = ')'\n\nexport function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {\n  const dehydratedMatch: DehydratedMatch = {\n    i: dehydrateSsrMatchId(match.id),\n    u: match.updatedAt,\n    s: match.status,\n  }\n\n  const properties = [\n    ['__beforeLoadContext', 'b'],\n    ['loaderData', 'l'],\n    ['error', 'e'],\n    ['ssr', 'ssr'],\n  ] as const\n\n  for (const [key, shorthand] of properties) {\n    if (match[key] !== undefined) {\n      dehydratedMatch[shorthand] = match[key]\n    }\n  }\n  if (match.globalNotFound) {\n    dehydratedMatch.g = true\n  }\n  return dehydratedMatch\n}\n\nconst INITIAL_SCRIPTS = [\n  getCrossReferenceHeader(SCOPE_ID),\n  minifiedTsrBootStrapScript,\n]\n\nclass ScriptBuffer {\n  private router: AnyRouter | undefined\n  private _queue: Array<string>\n  private _scriptBarrierLifted = false\n  private _cleanedUp = false\n  private _pendingMicrotask = false\n\n  constructor(router: AnyRouter) {\n    this.router = router\n    // Copy INITIAL_SCRIPTS to avoid mutating the shared array\n    this._queue = INITIAL_SCRIPTS.slice()\n  }\n\n  enqueue(script: string) {\n    if (this._cleanedUp) return\n    this._queue.push(script)\n    // If barrier is lifted, schedule injection (if not already scheduled)\n    if (this._scriptBarrierLifted && !this._pendingMicrotask) {\n      this._pendingMicrotask = true\n      queueMicrotask(() => {\n        this._pendingMicrotask = false\n        this.injectBufferedScripts()\n      })\n    }\n  }\n\n  liftBarrier() {\n    if (this._scriptBarrierLifted || this._cleanedUp) return\n    this._scriptBarrierLifted = true\n    if (this._queue.length > 0 && !this._pendingMicrotask) {\n      this._pendingMicrotask = true\n      queueMicrotask(() => {\n        this._pendingMicrotask = false\n        this.injectBufferedScripts()\n      })\n    }\n  }\n\n  /**\n   * Flushes any pending scripts synchronously.\n   * Call this before emitting onSerializationFinished to ensure all scripts are injected.\n   *\n   * IMPORTANT: Only injects if the barrier has been lifted. Before the barrier is lifted,\n   * scripts should remain in the queue so takeBufferedScripts() can retrieve them\n   */\n  flush() {\n    if (!this._scriptBarrierLifted) return\n    if (this._cleanedUp) return\n    this._pendingMicrotask = false\n    const scriptsToInject = this.takeAll()\n    if (scriptsToInject && this.router?.serverSsr) {\n      this.router.serverSsr.injectScript(scriptsToInject)\n    }\n  }\n\n  takeAll() {\n    const bufferedScripts = this._queue\n    this._queue = []\n    if (bufferedScripts.length === 0) {\n      return undefined\n    }\n    // Optimization: if only one script, avoid join\n    if (bufferedScripts.length === 1) {\n      return bufferedScripts[0] + ';document.currentScript.remove()'\n    }\n    // Append cleanup script and join - avoid push() to not mutate then iterate\n    return bufferedScripts.join(';') + ';document.currentScript.remove()'\n  }\n\n  injectBufferedScripts() {\n    if (this._cleanedUp) return\n    // Early return if queue is empty (avoids unnecessary takeAll() call)\n    if (this._queue.length === 0) return\n    const scriptsToInject = this.takeAll()\n    if (scriptsToInject && this.router?.serverSsr) {\n      this.router.serverSsr.injectScript(scriptsToInject)\n    }\n  }\n\n  cleanup() {\n    this._cleanedUp = true\n    this._queue = []\n    this.router = undefined\n  }\n}\n\nconst isProd = process.env.NODE_ENV === 'production'\n\ntype FilteredRoutes = Manifest['routes']\n\ntype ManifestLRU = LRUCache<string, FilteredRoutes>\ntype InlineCssLRU = LRUCache<string, string>\n\nconst MANIFEST_CACHE_SIZE = 100\nconst manifestCaches = new WeakMap<Manifest, ManifestLRU>()\nconst inlineCssCaches = new WeakMap<Manifest, InlineCssLRU>()\n\nfunction getManifestCache(manifest: Manifest): ManifestLRU {\n  const cache = manifestCaches.get(manifest)\n  if (cache) return cache\n  const newCache = createLRUCache<string, FilteredRoutes>(MANIFEST_CACHE_SIZE)\n  manifestCaches.set(manifest, newCache)\n  return newCache\n}\n\nfunction getInlineCssCache(manifest: Manifest): InlineCssLRU {\n  const cache = inlineCssCaches.get(manifest)\n  if (cache) return cache\n  const newCache = createLRUCache<string, string>(MANIFEST_CACHE_SIZE)\n  inlineCssCaches.set(manifest, newCache)\n  return newCache\n}\n\nfunction getInlineCssHrefsForMatches(\n  manifest: Manifest | undefined,\n  matches: Array<AnyRouteMatch>,\n) {\n  const styles = manifest?.inlineCss?.styles\n  if (!styles) return []\n\n  const seen = new Set<string>()\n  const hrefs: Array<string> = []\n\n  for (const match of matches) {\n    const assets = manifest?.routes[match.routeId]?.assets ?? []\n    for (const asset of assets) {\n      const href = getStylesheetHref(asset)\n      if (!href || seen.has(href) || styles[href] === undefined) {\n        continue\n      }\n      seen.add(href)\n      hrefs.push(href)\n    }\n  }\n\n  return hrefs\n}\n\nfunction getInlineCssForHrefs(manifest: Manifest, hrefs: Array<string>) {\n  const styles = manifest.inlineCss?.styles\n  if (!styles || hrefs.length === 0) return undefined\n\n  const cacheKey = hrefs.join('\\0')\n  if (isProd) {\n    const cached = getInlineCssCache(manifest).get(cacheKey)\n    if (cached !== undefined) return cached\n  }\n\n  const css = hrefs.map((href) => styles[href]!).join('')\n\n  if (isProd) {\n    getInlineCssCache(manifest).set(cacheKey, css)\n  }\n\n  return css\n}\n\nfunction getInlineCssAssetForMatches(\n  manifest: Manifest | undefined,\n  matches: Array<AnyRouteMatch>,\n) {\n  if (!manifest?.inlineCss) return undefined\n\n  const hrefs = getInlineCssHrefsForMatches(manifest, matches)\n  const css = getInlineCssForHrefs(manifest, hrefs)\n\n  return css === undefined ? undefined : createInlineCssStyleAsset(css)\n}\n\nfunction stripInlinedStylesheetAssets(\n  manifest: Manifest,\n  routes: FilteredRoutes,\n  matches: Array<AnyRouteMatch>,\n): FilteredRoutes {\n  if (!manifest.inlineCss) {\n    return routes\n  }\n\n  const nextRoutes: FilteredRoutes = {}\n\n  for (const [routeId, route] of Object.entries(routes)) {\n    const assets = route.assets?.filter(\n      (asset) => !isInlinableStylesheet(manifest, asset),\n    )\n\n    const nextRoute = { ...route }\n    if (assets) {\n      if (assets.length > 0) {\n        nextRoute.assets = assets\n      } else {\n        delete nextRoute.assets\n      }\n    }\n    nextRoutes[routeId] = nextRoute\n  }\n\n  if (getInlineCssAssetForMatches(manifest, matches)) {\n    const rootRoute = nextRoutes[rootRouteId] ?? {}\n    nextRoutes[rootRouteId] = {\n      ...rootRoute,\n      assets: [createInlineCssPlaceholderAsset(), ...(rootRoute.assets ?? [])],\n    }\n  }\n\n  return nextRoutes\n}\n\nexport function attachRouterServerSsrUtils({\n  router,\n  manifest,\n  getRequestAssets,\n  includeUnmatchedRouteAssets = true,\n}: {\n  router: AnyRouter\n  manifest: Manifest | undefined\n  getRequestAssets?: () => Array<RouterManagedTag> | undefined\n  includeUnmatchedRouteAssets?: boolean\n}) {\n  router.ssr = {\n    get manifest() {\n      const requestAssets = getRequestAssets?.()\n      const inlineCssAsset = getInlineCssAssetForMatches(\n        manifest,\n        router.stores.matches.get(),\n      )\n      if (!requestAssets?.length && !inlineCssAsset) return manifest\n      // Merge request-scoped assets into root route without mutating cached manifest\n      return {\n        ...manifest,\n        routes: {\n          ...manifest?.routes,\n          [rootRouteId]: {\n            ...manifest?.routes?.[rootRouteId],\n            assets: [\n              ...(requestAssets ?? []),\n              ...(inlineCssAsset ? [inlineCssAsset] : []),\n              ...(manifest?.routes?.[rootRouteId]?.assets ?? []),\n            ],\n          },\n        },\n      }\n    },\n  }\n  let _dehydrated = false\n  let _serializationFinished = false\n  const renderFinishedListeners: Array<() => void> = []\n  const serializationFinishedListeners: Array<() => void> = []\n  const scriptBuffer = new ScriptBuffer(router)\n  let injectedHtmlBuffer = ''\n\n  router.serverSsr = {\n    injectHtml: (html: string) => {\n      if (!html) return\n      // Buffer the HTML so it can be retrieved via takeBufferedHtml()\n      injectedHtmlBuffer += html\n      // Emit event to notify subscribers that new HTML is available\n      router.emit({\n        type: 'onInjectedHtml',\n      })\n    },\n    injectScript: (script: string) => {\n      if (!script) return\n      const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ''}>${script}</script>`\n      router.serverSsr!.injectHtml(html)\n    },\n    dehydrate: async (opts?: { requestAssets?: Array<RouterManagedTag> }) => {\n      if (_dehydrated) {\n        if (process.env.NODE_ENV !== 'production') {\n          throw new Error('Invariant failed: router is already dehydrated!')\n        }\n\n        invariant()\n      }\n      let matchesToDehydrate = router.stores.matches.get()\n      if (router.isShell()) {\n        // In SPA mode we only want to dehydrate the root match\n        matchesToDehydrate = matchesToDehydrate.slice(0, 1)\n      }\n      const matches = matchesToDehydrate.map(dehydrateMatch)\n\n      let manifestToDehydrate: Manifest | undefined = undefined\n      // For currently matched routes, send full manifest (preloads + assets).\n      // For unmatched routes, include assets only when includeUnmatchedRouteAssets\n      // is true; otherwise omit them entirely. Preloads for unmatched routes are\n      // still excluded because they are handled via dynamic imports.\n      if (manifest) {\n        // Prod-only caching; in dev manifests may be replaced/updated (HMR)\n        const currentRouteIdsList = matchesToDehydrate.map((m) => m.routeId)\n        const manifestCacheKey = `${currentRouteIdsList.join('\\0')}\\0includeUnmatchedRouteAssets=${includeUnmatchedRouteAssets}`\n\n        let filteredRoutes: FilteredRoutes | undefined\n\n        if (isProd) {\n          filteredRoutes = getManifestCache(manifest).get(manifestCacheKey)\n        }\n\n        if (!filteredRoutes) {\n          const currentRouteIds = new Set(currentRouteIdsList)\n          const nextFilteredRoutes: FilteredRoutes = {}\n\n          for (const routeId in manifest.routes) {\n            const routeManifest = manifest.routes[routeId]!\n            if (currentRouteIds.has(routeId)) {\n              nextFilteredRoutes[routeId] = routeManifest\n            } else if (\n              includeUnmatchedRouteAssets &&\n              routeManifest.assets &&\n              routeManifest.assets.length > 0\n            ) {\n              nextFilteredRoutes[routeId] = {\n                assets: routeManifest.assets,\n              }\n            }\n          }\n\n          filteredRoutes = stripInlinedStylesheetAssets(\n            manifest,\n            nextFilteredRoutes,\n            matchesToDehydrate,\n          )\n\n          if (isProd) {\n            getManifestCache(manifest).set(manifestCacheKey, filteredRoutes)\n          }\n        }\n\n        manifestToDehydrate = {\n          routes: { ...filteredRoutes },\n        }\n\n        // Merge request-scoped assets into root route (without mutating cached manifest)\n        if (opts?.requestAssets?.length) {\n          const existingRoot = manifestToDehydrate.routes[rootRouteId]\n          manifestToDehydrate.routes[rootRouteId] = {\n            ...existingRoot,\n            assets: [...opts.requestAssets, ...(existingRoot?.assets ?? [])],\n          }\n        }\n      }\n      const dehydratedRouter: DehydratedRouter = {\n        manifest: manifestToDehydrate,\n        matches,\n      }\n      const lastMatchId = matchesToDehydrate[matchesToDehydrate.length - 1]?.id\n      if (lastMatchId) {\n        dehydratedRouter.lastMatchId = dehydrateSsrMatchId(lastMatchId)\n      }\n      const dehydratedData = await router.options.dehydrate?.()\n      if (dehydratedData) {\n        dehydratedRouter.dehydratedData = dehydratedData\n      }\n      _dehydrated = true\n\n      const trackPlugins = { didRun: false }\n      const serializationAdapters = router.options.serializationAdapters as\n        | Array<AnySerializationAdapter>\n        | undefined\n      const plugins = serializationAdapters\n        ? serializationAdapters\n            .map((t) => makeSsrSerovalPlugin(t, trackPlugins))\n            .concat(defaultSerovalPlugins)\n        : defaultSerovalPlugins\n\n      const signalSerializationComplete = () => {\n        _serializationFinished = true\n        try {\n          serializationFinishedListeners.forEach((l) => l())\n          router.emit({ type: 'onSerializationFinished' })\n        } catch (err) {\n          console.error('Serialization listener error:', err)\n        } finally {\n          serializationFinishedListeners.length = 0\n          renderFinishedListeners.length = 0\n        }\n      }\n\n      crossSerializeStream(dehydratedRouter, {\n        refs: new Map(),\n        plugins,\n        onSerialize: (data, initial) => {\n          let serialized = initial ? TSR_PREFIX + data : data\n          if (trackPlugins.didRun) {\n            serialized = P_PREFIX + serialized + P_SUFFIX\n          }\n          scriptBuffer.enqueue(serialized)\n        },\n        onError: (err: unknown) => {\n          console.error('Serialization error:', err)\n          if (err && (err as any).stack) {\n            console.error((err as any).stack)\n          }\n          signalSerializationComplete()\n        },\n        scopeId: SCOPE_ID,\n        onDone: () => {\n          scriptBuffer.enqueue(GLOBAL_TSR + '.e()')\n          // Flush all pending scripts synchronously before signaling completion\n          // This ensures all scripts are injected before onSerializationFinished is emitted\n          scriptBuffer.flush()\n          signalSerializationComplete()\n        },\n      })\n    },\n    isDehydrated() {\n      return _dehydrated\n    },\n    isSerializationFinished() {\n      return _serializationFinished\n    },\n    onRenderFinished: (listener) => renderFinishedListeners.push(listener),\n    onSerializationFinished: (listener) =>\n      serializationFinishedListeners.push(listener),\n    setRenderFinished: () => {\n      // Wrap in try-catch to ensure scriptBuffer.liftBarrier() is always called\n      try {\n        renderFinishedListeners.forEach((l) => l())\n      } catch (err) {\n        console.error('Error in render finished listener:', err)\n      } finally {\n        // Clear listeners after calling them to prevent memory leaks\n        renderFinishedListeners.length = 0\n      }\n      scriptBuffer.liftBarrier()\n    },\n    takeBufferedScripts() {\n      const scripts = scriptBuffer.takeAll()\n      const serverBufferedScript: RouterManagedTag = {\n        tag: 'script',\n        attrs: {\n          nonce: router.options.ssr?.nonce,\n          className: '$tsr',\n          id: TSR_SCRIPT_BARRIER_ID,\n        },\n        children: scripts,\n      }\n      return serverBufferedScript\n    },\n    liftScriptBarrier() {\n      scriptBuffer.liftBarrier()\n    },\n    takeBufferedHtml() {\n      if (!injectedHtmlBuffer) {\n        return undefined\n      }\n      const buffered = injectedHtmlBuffer\n      injectedHtmlBuffer = ''\n      return buffered\n    },\n    cleanup() {\n      // Guard against multiple cleanup calls\n      if (!router.serverSsr) return\n      renderFinishedListeners.length = 0\n      serializationFinishedListeners.length = 0\n      injectedHtmlBuffer = ''\n      scriptBuffer.cleanup()\n      router.serverSsr = undefined\n    },\n  }\n}\n\n/**\n * Get the origin for the request.\n *\n * SECURITY: We intentionally do NOT trust the Origin header for determining\n * the router's origin. The Origin header can be spoofed by attackers, which\n * could lead to SSRF-like vulnerabilities where redirects are constructed\n * using a malicious origin (CVE-2024-34351).\n *\n * Instead, we derive the origin from request.url, which is typically set by\n * the server infrastructure (not client-controlled headers).\n *\n * For applications behind proxies that need to trust forwarded headers,\n * use the router's `origin` option to explicitly configure a trusted origin.\n */\nexport function getOrigin(request: Request) {\n  try {\n    return new URL(request.url).origin\n  } catch {}\n  return 'http://localhost'\n}\n\n// server and browser can decode/encode characters differently in paths and search params.\n// Server generally strictly follows the WHATWG URL Standard, while browsers may differ for legacy reasons.\n// for example, in paths \"|\" is not encoded on the server but is encoded on chromium (and not on firefox) while \"대\" is encoded on both sides.\n// Another anomaly is that in Node new URLSearchParams and new URL also decode/encode characters differently.\n// new URLSearchParams() encodes \"|\" while new URL() does not, and in this instance\n// chromium treats search params differently than paths, i.e. \"|\" is not encoded in search params.\nexport function getNormalizedURL(url: string | URL, base?: string | URL) {\n  // ensure backslashes are encoded correctly in the URL\n  if (typeof url === 'string') url = url.replace('\\\\', '%5C')\n\n  const rawUrl = new URL(url, base)\n  const { path: decodedPathname, handledProtocolRelativeURL } = decodePath(\n    rawUrl.pathname,\n  )\n  const searchParams = new URLSearchParams(rawUrl.search)\n  const normalizedHref =\n    decodedPathname +\n    (searchParams.size > 0 ? '?' : '') +\n    searchParams.toString() +\n    rawUrl.hash\n\n  return {\n    url: new URL(normalizedHref, rawUrl.origin),\n    handledProtocolRelativeURL,\n  }\n}\n"],"mappings":"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"}