import type { FetchOptions, FetchRequest } from 'ohmyfetch' import type { TypedInternalResponse, NitroFetchRequest } from 'nitropack' import { hash } from 'ohash' import { computed, isRef, Ref } from 'vue' import type { AsyncDataOptions, _Transform, KeyOfRes } 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 = Error, 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> = {} ) { if (process.dev && !opts.key && Object.values(opts).some(v => typeof v === 'function' || v instanceof Blob)) { console.warn('[nuxt] [useFetch] You should provide a key when passing options that are not serializable to JSON:', opts) } const key = '$f_' + (opts.key || hash([request, { ...opts, transform: null }])) const _request = computed(() => { let r = request as Ref | FetchRequest | (() => FetchRequest) if (typeof r === 'function') { r = r() } return (isRef(r) ? r.value : r) as NitroFetchRequest }) const { server, lazy, default: defaultFn, transform, pick, watch, initialCache, ...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, watch: [ _request, ...(watch || []) ] } const asyncData = useAsyncData<_ResT, ErrorT, Transform, PickKeys>(key, () => { return $fetch(_request.value, _fetchOptions) }, _asyncDataOptions) return asyncData } export function useLazyFetch< ResT = void, ErrorT = Error, 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'> = {} ) { return useFetch(request, { ...opts, lazy: true }) }