{"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) => Promise<void>\n    }\n\nexport type HandlerCallbackResult = Response | SsrResponse\n\nexport function isSsrResponse(value: unknown): value is SsrResponse {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    'response' in value &&\n    'serverSsrCleanup' in value\n  )\n}\n\nexport function normalizeSsrResponse(\n  result: HandlerCallbackResult,\n): SsrResponse {\n  return isSsrResponse(result)\n    ? result\n    : { response: result, serverSsrCleanup: 'none' }\n}\n\nexport function disposeSsrResponse(\n  response: SsrResponse,\n  reason?: unknown,\n): Promise<void> {\n  if (response.serverSsrCleanup !== 'stream') {\n    return Promise.resolve()\n  }\n  try {\n    return Promise.resolve(response.dispose(reason))\n  } catch (error) {\n    return Promise.reject(error)\n  }\n}\n\nexport function disposeSsrResponseDetached(\n  result: HandlerCallbackResult,\n  reason?: unknown,\n  onError: (error: unknown) => void = console.error,\n): void {\n  const ssrResponse = normalizeSsrResponse(result)\n  if (ssrResponse.serverSsrCleanup === 'stream') {\n    void disposeSsrResponse(ssrResponse, reason).catch(onError)\n    return\n  }\n\n  if (ssrResponse.response.body) {\n    try {\n      void ssrResponse.response.body.cancel(reason).catch(onError)\n    } catch (error) {\n      onError(error)\n    }\n  }\n}\n\nexport function createSsrStreamResponse<TRouter extends AnyRouter>(\n  router: TRouter,\n  response: Response,\n): SsrResponse {\n  if (!response.body) {\n    throw new Error('Invariant failed: SSR stream response requires a body')\n  }\n\n  let disposed = false\n  return {\n    response,\n    serverSsrCleanup: 'stream',\n    async dispose(reason?: unknown) {\n      if (disposed) {\n        return\n      }\n      disposed = true\n\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      try {\n        await response.body!.cancel(reason)\n      } catch {\n        // Cleanup above already released router SSR state.\n      }\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      disposeSsrResponseDetached(result, signal.reason)\n    }\n    return ssrResponse\n  }\n\n  const failed = (error: unknown) => {\n    router?.serverSsr?.cleanup()\n    console.error(error)\n  }\n  const abort = () => {\n    disposeSsrResponseDetached(ssrResponse, signal.reason, failed)\n  }\n  if (signal.aborted) {\n    abort()\n    return ssrResponse\n  }\n\n  signal.addEventListener('abort', abort, { once: true })\n  router?.serverSsr?.onCleanup(() => {\n    signal.removeEventListener('abort', abort)\n  })\n  return ssrResponse\n}\n\nexport async function replaceSsrResponse(\n  result: HandlerCallbackResult,\n  response: Response,\n  reason?: unknown,\n): Promise<SsrResponse> {\n  const ssrResponse = normalizeSsrResponse(result)\n  await disposeSsrResponse(ssrResponse, reason)\n  return { response, serverSsrCleanup: 'none' }\n}\n\nexport async function stripSsrResponseBody(\n  result: HandlerCallbackResult,\n  reason?: unknown,\n): Promise<SsrResponse> {\n  const ssrResponse = normalizeSsrResponse(result)\n  await 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,OACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,sBAAsB;AAE1B;AAEA,SAAgB,qBACd,QACa;CACb,OAAO,cAAc,MAAM,IACvB,SACA;EAAE,UAAU;EAAQ,kBAAkB;CAAO;AACnD;AAEA,SAAgB,mBACd,UACA,QACe;CACf,IAAI,SAAS,qBAAqB,UAChC,OAAO,QAAQ,QAAQ;CAEzB,IAAI;EACF,OAAO,QAAQ,QAAQ,SAAS,QAAQ,MAAM,CAAC;CACjD,SAAS,OAAO;EACd,OAAO,QAAQ,OAAO,KAAK;CAC7B;AACF;AAEA,SAAgB,2BACd,QACA,QACA,UAAoC,QAAQ,OACtC;CACN,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,mBAAwB,aAAa,MAAM,EAAE,MAAM,OAAO;EAC1D;CACF;CAEA,IAAI,YAAY,SAAS,MACvB,IAAI;EACF,YAAiB,SAAS,KAAK,OAAO,MAAM,EAAE,MAAM,OAAO;CAC7D,SAAS,OAAO;EACd,QAAQ,KAAK;CACf;AAEJ;AAEA,SAAgB,wBACd,QACA,UACa;CACb,IAAI,CAAC,SAAS,MACZ,MAAM,IAAI,MAAM,uDAAuD;CAGzE,IAAI,WAAW;CACf,OAAO;EACL;EACA,kBAAkB;EAClB,MAAM,QAAQ,QAAkB;GAC9B,IAAI,UACF;GAEF,WAAW;GAIX,OAAO,WAAW,QAAQ;GAE1B,IAAI;IACF,MAAM,SAAS,KAAM,OAAO,MAAM;GACpC,QAAQ,CAER;EACF;CACF;AACF;AAEA,SAAgB,yBACd,QACA,QACA,QACa;CACb,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,IAAI,OAAO,SACT,2BAA2B,QAAQ,OAAO,MAAM;EAElD,OAAO;CACT;CAEA,MAAM,UAAU,UAAmB;EACjC,QAAQ,WAAW,QAAQ;EAC3B,QAAQ,MAAM,KAAK;CACrB;CACA,MAAM,cAAc;EAClB,2BAA2B,aAAa,OAAO,QAAQ,MAAM;CAC/D;CACA,IAAI,OAAO,SAAS;EAClB,MAAM;EACN,OAAO;CACT;CAEA,OAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;CACtD,QAAQ,WAAW,gBAAgB;EACjC,OAAO,oBAAoB,SAAS,KAAK;CAC3C,CAAC;CACD,OAAO;AACT;AAEA,eAAsB,mBACpB,QACA,UACA,QACsB;CAEtB,MAAM,mBADc,qBAAqB,MAChB,GAAa,MAAM;CAC5C,OAAO;EAAE;EAAU,kBAAkB;CAAO;AAC9C;AAEA,eAAsB,qBACpB,QACA,QACsB;CACtB,MAAM,cAAc,qBAAqB,MAAM;CAC/C,MAAM,mBAAmB,aAAa,MAAM;CAC5C,OAAO;EACL,UAAU,IAAI,SAAS,MAAM,YAAY,QAAQ;EACjD,kBAAkB;CACpB;AACF;AAUA,SAAgB,sBACd,SAC0B;CAC1B,OAAO;AACT"}