import { ofetch } from 'ofetch' export interface RequestOptions extends RequestInit { onErrorOccured?: (error: Error, statusCode: number) => void onSuccess?: (data: T, statusCode: number) => void onStart?: () => void } /** * @function useMyFetch * * @description * Makes a request to a given url, handles cookies and errors. * * @param {string} url - The url to make a request to. * @param {RequestOptions} [options] - The options to use for the request. * * @returns {Promise} - A promise resolving to the response data * or undefined if an error occurred. * * @example * const { data } = useMyFetch<{ name: string }>('/api/user') */ export const useMyFetch = async ( url: string, options?: RequestOptions, ): Promise => { if (options?.onStart) options.onStart() let response = null try { const event = useRequestEvent() if (options == null) options = {} options.credentials = 'include' if (import.meta.server) { const api_uri = event?.node.req.headers['api-uri'] || 'http://localhost:4000' url = api_uri + url options.headers = event?.headers } response = await ofetch.raw(url, options) if (import.meta.server && !event?.handled) { for (const cookie of response.headers.getSetCookie()) { event?.headers.set('Cookie', cookie) event?.node.res.setHeader('set-cookie', cookie) } } // handle errors if any if (!response.ok && typeof options.onErrorOccured == 'function') { options.onErrorOccured(new Error(response.statusText), response.status) } // handle success to be able clearly marked that request has finished if (response.ok && typeof options.onSuccess == 'function') { options.onSuccess(response._data, response.status) } return response._data as T } catch (e) { // handle errors if any if (typeof options?.onErrorOccured == 'function') { options.onErrorOccured(e as Error, response?.status || 500) } else { console.error(e) } return {} as T } }