import { createUseFetch } from '#imports' import type { NitroFetchRequest } from 'nitropack/types' import type { $Fetch } from 'ofetch' import type { NuxtApp } from '#app' /** 与 `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({ credentials: 'include', }) interface AsyncDataRequestContext { cause: 'initial' | 'refresh:manual' | 'refresh:hook' | 'watch' } function ssrFriendlyCache(key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext): DataT | undefined { // SSR 首次水合用 payload 缓存(零闪烁),refresh 时跳过缓存走真实请求 if (ctx.cause === 'initial') { return nuxtApp.payload.data[key] as DataT | undefined } return undefined } const httpFetchDefaults = { retry: 0, $fetch: import.meta.server ? undefined : request, transform: unwrapApiBody, getCachedData: ssrFriendlyCache, } export const _useHttpFetch = createUseFetch(httpFetchDefaults) export const _useLazyHttpFetch = createUseFetch({ ...httpFetchDefaults, lazy: true, })