{"version":3,"file":"renderRouterToStream.cjs","names":[],"sources":["../../../src/ssr/renderRouterToStream.tsx"],"sourcesContent":["import { PassThrough, Readable } from 'node:stream'\nimport ReactDOMServer from 'react-dom/server'\nimport { isbot } from 'isbot'\nimport {\n  createSsrStreamResponse,\n  getSsrStatus,\n  transformReadableStreamWithRouter,\n  waitForRequest,\n} from '@tanstack/router-core/ssr/server'\nimport type { AnyRouter } from '@tanstack/router-core'\nimport type { ReactNode } from 'react'\n\nexport const renderRouterToStream = async ({\n  request,\n  router,\n  responseHeaders,\n  children,\n}: {\n  request: Request\n  router: AnyRouter\n  responseHeaders: Headers\n  children: ReactNode\n}) => {\n  const signal = request.signal\n  if (signal.aborted) {\n    router.serverSsr?.cleanup()\n    throw signal.reason\n  }\n  let rendererTeardown = false\n  const bot = isbot(request.headers.get('User-Agent'))\n  const onError =\n    (\n      renderer: string,\n    ): ReactDOMServer.RenderToPipeableStreamOptions['onError'] =>\n    (error, info) => {\n      if (!rendererTeardown && !signal.aborted) {\n        console.error(`Error in ${renderer}:`, error, info)\n      }\n    }\n\n  try {\n    if (typeof ReactDOMServer.renderToReadableStream === 'function') {\n      const stream = await ReactDOMServer.renderToReadableStream(children, {\n        signal,\n        nonce: router.options.ssr?.nonce,\n        progressiveChunkSize: Number.POSITIVE_INFINITY,\n        onError: onError('renderToReadableStream'),\n      })\n      // The transform owns the reader and bounds bot readiness by its lifetime.\n      const rendererAbort = bot ? new AbortController() : undefined\n      const responseStream = transformReadableStreamWithRouter(router, stream, {\n        rendererSafePoint: 'script-close',\n        signal,\n        onAbort: (reason) => {\n          rendererTeardown = true\n          rendererAbort?.abort(reason)\n        },\n      })\n      if (rendererAbort) {\n        await waitForRequest(stream.allReady, rendererAbort.signal)\n      }\n      return createSsrStreamResponse(\n        router,\n        new Response(responseStream, {\n          status: getSsrStatus(router),\n          headers: responseHeaders,\n        }),\n      )\n    }\n\n    if (typeof ReactDOMServer.renderToPipeableStream === 'function') {\n      const reactAppPassthrough = new PassThrough()\n      let pipeable:\n        | ReturnType<typeof ReactDOMServer.renderToPipeableStream>\n        | undefined\n      let resolveReady!: () => void\n      const ready = new Promise<void>((resolve) => {\n        resolveReady = resolve\n      })\n      const rendererAbort = new AbortController()\n      const abortPipeable = (reason?: unknown) => {\n        if (rendererTeardown) {\n          return\n        }\n        rendererTeardown = true\n        rendererAbort.abort(reason)\n        try {\n          pipeable?.abort(reason)\n        } catch {\n          // ignore — React may throw if already aborted/finished\n        }\n      }\n      try {\n        pipeable = ReactDOMServer.renderToPipeableStream(children, {\n          nonce: router.options.ssr?.nonce,\n          progressiveChunkSize: Number.POSITIVE_INFINITY,\n          ...(bot\n            ? { onAllReady: resolveReady }\n            : { onShellReady: resolveReady }),\n          onError: onError('renderToPipeableStream'),\n          onShellError: (error) => rendererAbort.abort(error),\n        })\n        const responseStream = transformReadableStreamWithRouter(\n          router,\n          Readable.toWeb(reactAppPassthrough),\n          {\n            rendererSafePoint: 'script-close',\n            signal,\n            onAbort: abortPipeable,\n          },\n        )\n\n        await waitForRequest(ready, rendererAbort.signal)\n        pipeable.pipe(reactAppPassthrough)\n\n        return createSsrStreamResponse(\n          router,\n          new Response(responseStream, {\n            status: getSsrStatus(router),\n            headers: responseHeaders,\n          }),\n        )\n      } catch (error) {\n        abortPipeable(error)\n        throw error\n      }\n    }\n\n    throw new Error(\n      'No renderToReadableStream or renderToPipeableStream found in react-dom/server. Ensure you are using a version of react-dom that supports streaming.',\n    )\n  } catch (error) {\n    router.serverSsr?.cleanup()\n    throw error\n  }\n}\n"],"mappings":";;;;;;;AAYA,IAAa,uBAAuB,OAAO,EACzC,SACA,QACA,iBACA,eAMI;CACJ,MAAM,SAAS,QAAQ;CACvB,IAAI,OAAO,SAAS;EAClB,OAAO,WAAW,QAAQ;EAC1B,MAAM,OAAO;CACf;CACA,IAAI,mBAAmB;CACvB,MAAM,OAAA,GAAA,MAAA,OAAY,QAAQ,QAAQ,IAAI,YAAY,CAAC;CACnD,MAAM,WAEF,cAED,OAAO,SAAS;EACf,IAAI,CAAC,oBAAoB,CAAC,OAAO,SAC/B,QAAQ,MAAM,YAAY,SAAS,IAAI,OAAO,IAAI;CAEtD;CAEF,IAAI;EACF,IAAI,OAAO,iBAAA,QAAe,2BAA2B,YAAY;GAC/D,MAAM,SAAS,MAAM,iBAAA,QAAe,uBAAuB,UAAU;IACnE;IACA,OAAO,OAAO,QAAQ,KAAK;IAC3B,sBAAsB,OAAO;IAC7B,SAAS,QAAQ,wBAAwB;GAC3C,CAAC;GAED,MAAM,gBAAgB,MAAM,IAAI,gBAAgB,IAAI,KAAA;GACpD,MAAM,kBAAA,GAAA,iCAAA,mCAAmD,QAAQ,QAAQ;IACvE,mBAAmB;IACnB;IACA,UAAU,WAAW;KACnB,mBAAmB;KACnB,eAAe,MAAM,MAAM;IAC7B;GACF,CAAC;GACD,IAAI,eACF,OAAA,GAAA,iCAAA,gBAAqB,OAAO,UAAU,cAAc,MAAM;GAE5D,QAAA,GAAA,iCAAA,yBACE,QACA,IAAI,SAAS,gBAAgB;IAC3B,SAAA,GAAA,iCAAA,cAAqB,MAAM;IAC3B,SAAS;GACX,CAAC,CACH;EACF;EAEA,IAAI,OAAO,iBAAA,QAAe,2BAA2B,YAAY;GAC/D,MAAM,sBAAsB,IAAI,YAAA,YAAY;GAC5C,IAAI;GAGJ,IAAI;GACJ,MAAM,QAAQ,IAAI,SAAe,YAAY;IAC3C,eAAe;GACjB,CAAC;GACD,MAAM,gBAAgB,IAAI,gBAAgB;GAC1C,MAAM,iBAAiB,WAAqB;IAC1C,IAAI,kBACF;IAEF,mBAAmB;IACnB,cAAc,MAAM,MAAM;IAC1B,IAAI;KACF,UAAU,MAAM,MAAM;IACxB,QAAQ,CAER;GACF;GACA,IAAI;IACF,WAAW,iBAAA,QAAe,uBAAuB,UAAU;KACzD,OAAO,OAAO,QAAQ,KAAK;KAC3B,sBAAsB,OAAO;KAC7B,GAAI,MACA,EAAE,YAAY,aAAa,IAC3B,EAAE,cAAc,aAAa;KACjC,SAAS,QAAQ,wBAAwB;KACzC,eAAe,UAAU,cAAc,MAAM,KAAK;IACpD,CAAC;IACD,MAAM,kBAAA,GAAA,iCAAA,mCACJ,QACA,YAAA,SAAS,MAAM,mBAAmB,GAClC;KACE,mBAAmB;KACnB;KACA,SAAS;IACX,CACF;IAEA,OAAA,GAAA,iCAAA,gBAAqB,OAAO,cAAc,MAAM;IAChD,SAAS,KAAK,mBAAmB;IAEjC,QAAA,GAAA,iCAAA,yBACE,QACA,IAAI,SAAS,gBAAgB;KAC3B,SAAA,GAAA,iCAAA,cAAqB,MAAM;KAC3B,SAAS;IACX,CAAC,CACH;GACF,SAAS,OAAO;IACd,cAAc,KAAK;IACnB,MAAM;GACR;EACF;EAEA,MAAM,IAAI,MACR,qJACF;CACF,SAAS,OAAO;EACd,OAAO,WAAW,QAAQ;EAC1B,MAAM;CACR;AACF"}