stream-hooks
Version:
<div align="center"> <a aria-label="NPM version" href="https://twitter.com/dimitrikennedy"> <img alt="stream-hooks" src="https://img.shields.io/twitter/follow/dimitrikennedy?style=social&labelColor=000000"> </a> <a aria-label="GH Issues" href="h
1 lines • 3.91 kB
Source Map (JSON)
{"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":[]}