@tanstack/router-core
Version:
Modern and scalable routing for React applications
1 lines • 6.45 kB
Source Map (JSON)
{"version":3,"file":"handlerCallback.cjs","names":[],"sources":["../../../src/ssr/handlerCallback.ts"],"sourcesContent":["import type { AnyRouter } from '../router'\n\nexport type SsrResponse =\n | {\n response: Response\n serverSsrCleanup: 'none'\n }\n | {\n response: Response\n serverSsrCleanup: 'stream'\n dispose: (reason?: unknown) => undefined\n }\n\nexport type HandlerCallbackResult = Response | SsrResponse\n\nexport function isSsrResponse(value: unknown): value is SsrResponse {\n if (\n typeof value !== 'object' ||\n value === null ||\n !('response' in value) ||\n !(value.response instanceof Response) ||\n !('serverSsrCleanup' in value)\n ) {\n return false\n }\n\n if (value.serverSsrCleanup === 'none') {\n return true\n }\n\n return (\n value.serverSsrCleanup === 'stream' &&\n 'dispose' in value &&\n typeof value.dispose === 'function'\n )\n}\n\nexport function normalizeSsrResponse(\n result: HandlerCallbackResult,\n): SsrResponse {\n if (result instanceof Response) {\n return { response: result, serverSsrCleanup: 'none' }\n }\n if (isSsrResponse(result)) {\n return result\n }\n\n throw new TypeError('Expected a Response from the SSR handler')\n}\n\nfunction cancelResponseBody(response: Response, reason?: unknown): void {\n const body = response.body\n if (!body) {\n return\n }\n void body.cancel(reason).catch(console.error)\n}\n\nexport function disposeSsrResponse(\n result: HandlerCallbackResult,\n reason?: unknown,\n): undefined {\n const response = normalizeSsrResponse(result)\n if (response.serverSsrCleanup === 'stream') {\n response.dispose(reason)\n } else {\n cancelResponseBody(response.response, reason)\n }\n}\n\n/** The HTTP status that Router's server load selected for this render. */\nexport function getSsrStatus(router: AnyRouter) {\n return router._serverResult?.type === 'render'\n ? router._serverResult.status\n : 200\n}\n\nexport function createSsrStreamResponse(\n router: AnyRouter,\n response: Response,\n): Extract<SsrResponse, { serverSsrCleanup: 'stream' }> {\n const body = response.body\n if (!body) {\n throw new Error('Invariant failed: SSR stream response requires a body')\n }\n\n return {\n response,\n serverSsrCleanup: 'stream',\n dispose(reason?: unknown): undefined {\n // Sever router ownership before asking user/renderer stream machinery to\n // cancel. A custom stream is allowed to ignore cancellation forever.\n router.serverSsr?.cleanup()\n\n void body.cancel(reason).catch(() => {})\n },\n }\n}\n\nexport function bindSsrResponseToRequest(\n router: AnyRouter | undefined,\n result: HandlerCallbackResult,\n signal: AbortSignal,\n): SsrResponse {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup !== 'stream') {\n if (signal.aborted) {\n disposeSsrResponse(result, signal.reason)\n }\n return ssrResponse\n }\n\n const abort = () => {\n disposeSsrResponse(ssrResponse, signal.reason)\n }\n if (signal.aborted) {\n abort()\n return ssrResponse\n }\n\n const serverSsr = router?.serverSsr\n if (serverSsr?.hydrationScripts.requestSignal === signal) {\n // The transform already observes this request. Its cleanup must also\n // dispose the final response, including any middleware-owned body.\n serverSsr.onCleanup(() => {\n if (signal.aborted) {\n abort()\n }\n })\n return ssrResponse\n }\n\n signal.addEventListener('abort', abort, { once: true })\n if (!serverSsr) {\n return ssrResponse\n }\n\n serverSsr.onCleanup(() => {\n signal.removeEventListener('abort', abort)\n })\n return ssrResponse\n}\n\nexport function replaceSsrResponse(\n result: HandlerCallbackResult,\n response: Response,\n reason?: unknown,\n): Extract<SsrResponse, { serverSsrCleanup: 'none' }> {\n disposeSsrResponse(result, reason)\n return { response, serverSsrCleanup: 'none' }\n}\n\nexport function stripSsrResponseBody(\n result: HandlerCallbackResult,\n reason?: unknown,\n): Extract<SsrResponse, { serverSsrCleanup: 'none' }> {\n const ssrResponse = normalizeSsrResponse(result)\n disposeSsrResponse(ssrResponse, reason)\n return {\n response: new Response(null, ssrResponse.response),\n serverSsrCleanup: 'none',\n }\n}\n\nexport interface HandlerCallback<TRouter extends AnyRouter> {\n (ctx: {\n request: Request\n router: TRouter\n responseHeaders: Headers\n }): HandlerCallbackResult | Promise<HandlerCallbackResult>\n}\n\nexport function defineHandlerCallback<TRouter extends AnyRouter>(\n handler: HandlerCallback<TRouter>,\n): HandlerCallback<TRouter> {\n return handler\n}\n"],"mappings":";AAeA,SAAgB,cAAc,OAAsC;CAClE,IACE,OAAO,UAAU,YACjB,UAAU,QACV,EAAE,cAAc,UAChB,EAAE,MAAM,oBAAoB,aAC5B,EAAE,sBAAsB,QAExB,OAAO;CAGT,IAAI,MAAM,qBAAqB,QAC7B,OAAO;CAGT,OACE,MAAM,qBAAqB,YAC3B,aAAa,SACb,OAAO,MAAM,YAAY;AAE7B;AAEA,SAAgB,qBACd,QACa;CACb,IAAI,kBAAkB,UACpB,OAAO;EAAE,UAAU;EAAQ,kBAAkB;CAAO;CAEtD,IAAI,cAAc,MAAM,GACtB,OAAO;CAGT,MAAM,IAAI,UAAU,0CAA0C;AAChE;AAEA,SAAS,mBAAmB,UAAoB,QAAwB;CACtE,MAAM,OAAO,SAAS;CACtB,IAAI,CAAC,MACH;CAEF,KAAU,OAAO,MAAM,EAAE,MAAM,QAAQ,KAAK;AAC9C;AAEA,SAAgB,mBACd,QACA,QACW;CACX,MAAM,WAAW,qBAAqB,MAAM;CAC5C,IAAI,SAAS,qBAAqB,UAChC,SAAS,QAAQ,MAAM;MAEvB,mBAAmB,SAAS,UAAU,MAAM;AAEhD;;AAGA,SAAgB,aAAa,QAAmB;CAC9C,OAAO,OAAO,eAAe,SAAS,WAClC,OAAO,cAAc,SACrB;AACN;AAEA,SAAgB,wBACd,QACA,UACsD;CACtD,MAAM,OAAO,SAAS;CACtB,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,uDAAuD;CAGzE,OAAO;EACL;EACA,kBAAkB;EAClB,QAAQ,QAA6B;GAGnC,OAAO,WAAW,QAAQ;GAE1B,KAAU,OAAO,MAAM,EAAE,YAAY,CAAC,CAAC;EACzC;CACF;AACF;AAEA,SAAgB,yBACd,QACA,QACA,QACa;CACb,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,IAAI,OAAO,SACT,mBAAmB,QAAQ,OAAO,MAAM;EAE1C,OAAO;CACT;CAEA,MAAM,cAAc;EAClB,mBAAmB,aAAa,OAAO,MAAM;CAC/C;CACA,IAAI,OAAO,SAAS;EAClB,MAAM;EACN,OAAO;CACT;CAEA,MAAM,YAAY,QAAQ;CAC1B,IAAI,WAAW,iBAAiB,kBAAkB,QAAQ;EAGxD,UAAU,gBAAgB;GACxB,IAAI,OAAO,SACT,MAAM;EAEV,CAAC;EACD,OAAO;CACT;CAEA,OAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;CACtD,IAAI,CAAC,WACH,OAAO;CAGT,UAAU,gBAAgB;EACxB,OAAO,oBAAoB,SAAS,KAAK;CAC3C,CAAC;CACD,OAAO;AACT;AAEA,SAAgB,mBACd,QACA,UACA,QACoD;CACpD,mBAAmB,QAAQ,MAAM;CACjC,OAAO;EAAE;EAAU,kBAAkB;CAAO;AAC9C;AAEA,SAAgB,qBACd,QACA,QACoD;CACpD,MAAM,cAAc,qBAAqB,MAAM;CAC/C,mBAAmB,aAAa,MAAM;CACtC,OAAO;EACL,UAAU,IAAI,SAAS,MAAM,YAAY,QAAQ;EACjD,kBAAkB;CACpB;AACF;AAUA,SAAgB,sBACd,SAC0B;CAC1B,OAAO;AACT"}