{"version":3,"sources":["../src/hooks/use-stream.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\"\nimport type { StartStreamArgs, StartStreamBase, StopStream, UseStreamProps } from \"@/types\"\n\n/**\n * `useStream` is a custom React hook that creates a fetch request to a stream endpoint and manages the state of that stream\n * It provides functionalities to start and stop the stream, and manages the loading state.\n *\n * @param {UseStreamProps} props - The props for the hook include optional callback\n * functions that will be invoked at different stages of the stream lifecycle.\n *\n * @returns {\n *  startStream: StartStream,\n *  stopStream: StopStream\n * }\n *\n * @example\n * ```\n * const {\n *   loading,\n *   startStream,\n *   stopStream\n * } = useStream({ onBeforeStart: ..., onStop: ... });\n * ```\n */\nexport function useStream({ onBeforeStart, onStop }: UseStreamProps): {\n  startStream: StartStreamBase\n  stopStream: StopStream\n} {\n  const abortControllerRef = useRef<AbortController | null>(null)\n\n  /**\n   * @function startStream\n   * Starts a stream with the provided arguments.\n   *\n   * @param {StartStreamArgs} args - The arguments for starting the stream, including the URL and optional body.\n   *\n   * @returns {Promise<Response>} - A promise that resolves with the Response object from the fetch API.\n   *\n   * @example\n   * ```\n   * startStream({ url: 'http://example.com', body: { key: 'value' } });\n   * ```\n   */\n  const startStream = async ({\n    url,\n    body = {},\n    headers = {},\n    method = \"POST\"\n  }: StartStreamArgs): Promise<ReadableStream<Uint8Array>> => {\n    try {\n      const abortController = new AbortController()\n      abortControllerRef.current = abortController\n\n      onBeforeStart && onBeforeStart()\n\n      const response = await fetch(`${url}`, {\n        method,\n        headers,\n        signal: abortController.signal,\n        ...(method === \"POST\" ? { body: JSON.stringify(body) } : {})\n      })\n\n      if (!response.ok || !response?.body) {\n        throw response\n      }\n\n      return response?.body\n    } catch (err: any) {\n      if (err?.name === \"AbortError\") {\n        console.log(\"useStream: stream aborted\", err)\n        abortControllerRef.current = null\n\n        throw err\n      }\n\n      console.error(`useStream: error`, err)\n      throw err\n    }\n  }\n\n  /**\n   * @function stopStream\n   * Stops the current stream.\n   *\n   * @example\n   * ```\n   * stopStream();\n   * ```\n   */\n  const stopStream = useCallback(() => {\n    if (abortControllerRef.current) {\n      abortControllerRef?.current?.abort()\n      abortControllerRef.current = null\n    }\n    onStop && onStop()\n  }, [onStop])\n\n  useEffect(() => {\n    return () => {\n      stopStream()\n    }\n  }, [stopStream])\n\n  return {\n    startStream,\n    stopStream\n  }\n}\n"],"mappings":";;;AAAA,SAAS,aAAa,WAAW,cAAc;AAwBxC,SAAS,UAAU,EAAE,eAAe,OAAO,GAGhD;AACA,QAAM,qBAAqB,OAA+B,IAAI;AAe9D,QAAM,cAAc,OAAO;AAAA,IACzB;AAAA,IACA,OAAO,CAAC;AAAA,IACR,UAAU,CAAC;AAAA,IACX,SAAS;AAAA,EACX,MAA4D;AAC1D,QAAI;AACF,YAAM,kBAAkB,IAAI,gBAAgB;AAC5C,yBAAmB,UAAU;AAE7B,uBAAiB,cAAc;AAE/B,YAAM,WAAW,MAAM,MAAM,GAAG,GAAG,IAAI;AAAA,QACrC;AAAA,QACA;AAAA,QACA,QAAQ,gBAAgB;AAAA,QACxB,GAAI,WAAW,SAAS,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,MAC5D,CAAC;AAED,UAAI,CAAC,SAAS,MAAM,CAAC,UAAU,MAAM;AACnC,cAAM;AAAA,MACR;AAEA,aAAO,UAAU;AAAA,IACnB,SAAS,KAAU;AACjB,UAAI,KAAK,SAAS,cAAc;AAC9B,gBAAQ,IAAI,6BAA6B,GAAG;AAC5C,2BAAmB,UAAU;AAE7B,cAAM;AAAA,MACR;AAEA,cAAQ,MAAM,oBAAoB,GAAG;AACrC,YAAM;AAAA,IACR;AAAA,EACF;AAWA,QAAM,aAAa,YAAY,MAAM;AACnC,QAAI,mBAAmB,SAAS;AAC9B,0BAAoB,SAAS,MAAM;AACnC,yBAAmB,UAAU;AAAA,IAC/B;AACA,cAAU,OAAO;AAAA,EACnB,GAAG,CAAC,MAAM,CAAC;AAEX,YAAU,MAAM;AACd,WAAO,MAAM;AACX,iBAAW;AAAA,IACb;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;","names":[]}