import { createUseFetch } from '#imports' import type { AsyncData, UseFetchOptions } from '#app' import type { KeysOf, PickFrom } from '#app/composables/asyncData' import type { NitroFetchRequest, TypedInternalResponse, AvailableRouterMethod } from 'nitropack/types' import type { FetchError } from 'ofetch' import type { Ref } from 'vue' /** 与 `R.success` / `R.error` 返回结构对齐 */ export type ApiResponse = { code: number message: string data: T } /** 从 Nitro 推断的响应体上剥离一层 `ApiResponse`,得到 `data` 字段类型 */ export type UnwrapApiResponse = T extends ApiResponse ? D : T export function unwrapApiBody(payload: ApiResponse): T { if (payload.code !== 0) { throw new Error(payload.message) } return payload.data } export const request = $fetch.create({}) const httpFetchDefaults = { retry: 0, $fetch: request, transform: unwrapApiBody, } const _useHttpFetch = createUseFetch(httpFetchDefaults) const _useLazyHttpFetch = createUseFetch({ ...httpFetchDefaults, lazy: true, }) type DefaultMethod = 'get' extends AvailableRouterMethod ? 'get' : AvailableRouterMethod type HttpFetchOptions< _ResT, DataT, PickKeys extends KeysOf, DefaultT, ReqT extends NitroFetchRequest, Method extends AvailableRouterMethod, > = Omit, 'transform'> /** * 带项目默认选项的 `useFetch`,并在类型上将 `data` 视为接口 `{ code, data, message }` 中的内层 `data`。 * * 说明:Nuxt的 `createUseFetch` 在类型上不会把工厂里的 `transform` 的出参当作 `AsyncData['data']`, * 因此这里用薄包装修正 `DataT`(见 `UnwrapApiResponse`)。 */ export function useHttpFetch< ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, Method extends AvailableRouterMethod = ResT extends void ? DefaultMethod : AvailableRouterMethod, _ResT = ResT extends void ? TypedInternalResponse> : ResT, DataT = UnwrapApiResponse<_ResT>, PickKeys extends KeysOf = KeysOf, DefaultT = undefined, >( url: ReqT | Ref | (() => ReqT), opts?: HttpFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>, ): AsyncData, ErrorT | undefined> { return _useHttpFetch(url, opts) as AsyncData, ErrorT | undefined> } export function useLazyHttpFetch< ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, Method extends AvailableRouterMethod = ResT extends void ? DefaultMethod : AvailableRouterMethod, _ResT = ResT extends void ? TypedInternalResponse> : ResT, DataT = UnwrapApiResponse<_ResT>, PickKeys extends KeysOf = KeysOf, DefaultT = undefined, >( url: ReqT | Ref | (() => ReqT), opts?: HttpFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>, ): AsyncData, ErrorT | undefined> { return _useLazyHttpFetch(url, opts) as AsyncData< DefaultT | PickFrom, ErrorT | undefined > }