import type { InternalApi } from 'nitropack'; import type { WatchSource, WatchStopHandle } from 'vue'; type NitroFetchRequest = Exclude | (string & {}); export type CustomFetchOptions = { watchProps?: WatchSource[], lazy?: boolean, method?: string, getBody?: () => Record, watchKey?: string } type OnResponseCallback = (data: Ref) => any type OnRequestCallback = () => any const watchStopHandles: Record = {} export function useCustomFetch(url: NitroFetchRequest, getHeaders: () => Record, options?: CustomFetchOptions) { const pending = ref(false); const data = ref(); const error = ref(); let onResponseCallback: OnResponseCallback = () => { } let onRequestCallback: OnRequestCallback = () => { } const onResponse = (callback: OnResponseCallback) => { onResponseCallback = callback; } const onRequest = (callback: OnRequestCallback) => { onRequestCallback = callback; } const execute = async () => { onRequestCallback(); pending.value = true; error.value = undefined; try { data.value = await $fetch(url, { headers: getHeaders(), method: (options?.method || 'GET') as any, body: options?.getBody ? JSON.stringify(options.getBody()) : undefined }); onResponseCallback(data); } catch (err) { error.value = err as Error; } finally { pending.value = false; } } if (options?.lazy !== true) { execute(); } if (options?.watchProps) { const watchStop = watch(options.watchProps, () => { execute(); }); const key = options?.watchKey || `${url}`; if (watchStopHandles[key]) watchStopHandles[key](); watchStopHandles[key] = watchStop; console.log('Watchers:', Object.keys(watchStopHandles).length); } const refresh = execute; return { pending, execute, data, error, refresh, onResponse, onRequest }; }