import type { FetchError, FetchOptions } from 'ohmyfetch' import type { TypedInternalResponse, NitroFetchRequest } from 'nitropack' import { computed, unref, Ref } from 'vue' import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData' import { useAsyncData } from './asyncData' export type FetchResult = TypedInternalResponse export interface UseFetchOptions< DataT, Transform extends _Transform = _Transform, PickKeys extends KeyOfRes = KeyOfRes > extends AsyncDataOptions, FetchOptions { key?: string } export function useFetch< ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, _ResT = ResT extends void ? FetchResult : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes = KeyOfRes > ( request: Ref | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, Transform, PickKeys> ): AsyncData, PickKeys>, ErrorT | null | true> export function useFetch< ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, _ResT = ResT extends void ? FetchResult : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes = KeyOfRes > ( request: Ref | ReqT | (() => ReqT), arg1?: string | UseFetchOptions<_ResT, Transform, PickKeys>, arg2?: string ) { const [opts = {}, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2] const _key = opts.key || autoKey if (!_key || typeof _key !== 'string') { throw new TypeError('[nuxt] [useFetch] key must be a string: ' + _key) } if (!request) { throw new Error('[nuxt] [useFetch] request is missing.') } const key = '$f' + _key const _request = computed(() => { let r = request if (typeof r === 'function') { r = r() } return unref(r) }) const { server, lazy, default: defaultFn, transform, pick, watch, initialCache, immediate, ...fetchOptions } = opts const _fetchOptions = { ...fetchOptions, cache: typeof opts.cache === 'boolean' ? undefined : opts.cache } const _asyncDataOptions: AsyncDataOptions<_ResT, Transform, PickKeys> = { server, lazy, default: defaultFn, transform, pick, initialCache, immediate, watch: [ _request, ...(watch || []) ] } let controller: AbortController const asyncData = useAsyncData<_ResT, ErrorT, Transform, PickKeys>(key, () => { controller?.abort?.() controller = typeof AbortController !== 'undefined' ? new AbortController() : {} as AbortController return $fetch(_request.value, { signal: controller.signal, ..._fetchOptions }) as Promise<_ResT> }, _asyncDataOptions) return asyncData } export function useLazyFetch< ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, _ResT = ResT extends void ? FetchResult : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes = KeyOfRes > ( request: Ref | ReqT | (() => ReqT), opts?: Omit, 'lazy'> ): AsyncData, PickKeys>, ErrorT | null | true> export function useLazyFetch< ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, _ResT = ResT extends void ? FetchResult : ResT, Transform extends (res: _ResT) => any = (res: _ResT) => _ResT, PickKeys extends KeyOfRes = KeyOfRes > ( request: Ref | ReqT | (() => ReqT), arg1?: string | Omit, 'lazy'>, arg2?: string ) { const [opts, autoKey] = typeof arg1 === 'string' ? [{}, arg1] : [arg1, arg2] return useFetch(request, { ...opts, lazy: true }, // @ts-ignore autoKey) }