{"version":3,"file":"createRequestHandler.cjs","sources":["../../../src/ssr/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from './headers'\nimport {\n  attachRouterServerSsrUtils,\n  getNormalizedURL,\n  getOrigin,\n} from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyHeaders } from './headers'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n  cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n  createRouter,\n  request,\n  getRouterManifest,\n}: {\n  createRouter: () => TRouter\n  request: Request\n  getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n  return async (cb) => {\n    const router = createRouter()\n    // Track whether the callback will handle cleanup\n    let cbWillCleanup = false\n\n    try {\n      attachRouterServerSsrUtils({\n        router,\n        manifest: await getRouterManifest?.(),\n      })\n\n      // normalizing and sanitizing the pathname here for server, so we always deal with the same format during SSR.\n      const { url } = getNormalizedURL(request.url, 'http://localhost')\n      const origin = getOrigin(request)\n      const href = url.href.replace(url.origin, '')\n\n      // Create a history for the router\n      const history = createMemoryHistory({\n        initialEntries: [href],\n      })\n\n      // Update the router with the history and context\n      router.update({\n        history,\n        origin: router.options.origin ?? origin,\n      })\n\n      await router.load()\n\n      await router.serverSsr?.dehydrate()\n\n      const responseHeaders = getRequestHeaders({\n        router,\n      })\n\n      // Mark that the callback will handle cleanup\n      cbWillCleanup = true\n      return cb({\n        request,\n        router,\n        responseHeaders,\n      })\n    } finally {\n      if (!cbWillCleanup) {\n        // Clean up router SSR state if the callback won't handle it\n        // (e.g., if an error occurred before the callback was invoked).\n        // When the callback runs, it handles cleanup (either via transformStreamWithRouter\n        // for streaming, or directly in renderRouterToString for non-streaming).\n        router.serverSsr?.cleanup()\n      }\n    }\n  }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n  const matchHeaders = opts.router.state.matches.map<AnyHeaders>(\n    (match) => match.headers,\n  )\n\n  // Handle Redirects\n  const { redirect } = opts.router.state\n  if (redirect) {\n    matchHeaders.push(redirect.headers)\n  }\n\n  return mergeHeaders(\n    {\n      'Content-Type': 'text/html; charset=UTF-8',\n    },\n    ...matchHeaders,\n  )\n}\n"],"names":["attachRouterServerSsrUtils","getNormalizedURL","getOrigin","history","createMemoryHistory","mergeHeaders"],"mappings":";;;;;AAgBO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;AACnB,UAAM,SAAS,aAAA;AAEf,QAAI,gBAAgB;AAEpB,QAAI;AACFA,2CAA2B;AAAA,QACzB;AAAA,QACA,UAAU,MAAM,oBAAA;AAAA,MAAoB,CACrC;AAGD,YAAM,EAAE,IAAA,IAAQC,UAAAA,iBAAiB,QAAQ,KAAK,kBAAkB;AAChE,YAAM,SAASC,UAAAA,UAAU,OAAO;AAChC,YAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,YAAMC,YAAUC,QAAAA,oBAAoB;AAAA,QAClC,gBAAgB,CAAC,IAAI;AAAA,MAAA,CACtB;AAGD,aAAO,OAAO;AAAA,QAAA,SACZD;AAAAA,QACA,QAAQ,OAAO,QAAQ,UAAU;AAAA,MAAA,CAClC;AAED,YAAM,OAAO,KAAA;AAEb,YAAM,OAAO,WAAW,UAAA;AAExB,YAAM,kBAAkB,kBAAkB;AAAA,QACxC;AAAA,MAAA,CACD;AAGD,sBAAgB;AAChB,aAAO,GAAG;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH,UAAA;AACE,UAAI,CAAC,eAAe;AAKlB,eAAO,WAAW,QAAA;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,QAAM,eAAe,KAAK,OAAO,MAAM,QAAQ;AAAA,IAC7C,CAAC,UAAU,MAAM;AAAA,EAAA;AAInB,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AACjC,MAAI,UAAU;AACZ,iBAAa,KAAK,SAAS,OAAO;AAAA,EACpC;AAEA,SAAOE,QAAAA;AAAAA,IACL;AAAA,MACE,gBAAgB;AAAA,IAAA;AAAA,IAElB,GAAG;AAAA,EAAA;AAEP;;"}