Last active
March 28, 2024 00:46
-
-
Save BarishNamazov/f9827165c4259d29b16a99c9d018588c to your computer and use it in GitHub Desktop.
Custom wrapper for Nuxt's useFetch while keeping type completion features
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { AsyncData, UseFetchOptions, FetchResult } from "nuxt/app"; | |
| import type { FetchError } from "ofetch"; | |
| import type { | |
| NitroFetchRequest, | |
| AvailableRouterMethod as _AvailableRouterMethod, | |
| } from "nitropack"; | |
| // Custom options | |
| interface UseFetchyOptions< | |
| _ResT, | |
| DataT, | |
| PickKeys extends KeysOf<DataT>, | |
| DefaultT, | |
| ReqT extends NitroFetchRequest, | |
| Method extends AvailableRouterMethod<ReqT> | |
| > extends UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method> { | |
| alert?: boolean; | |
| suppress?: boolean; | |
| } | |
| type PickFrom<T, K extends Array<string>> = T extends Array<any> | |
| ? T | |
| : T extends Record<string, any> | |
| ? keyof T extends K[number] | |
| ? T | |
| : K[number] extends never | |
| ? T | |
| : Pick<T, K[number]> | |
| : T; | |
| type KeysOf<T> = Array< | |
| T extends T ? (keyof T extends string ? keyof T : never) : never | |
| >; | |
| type AvailableRouterMethod<R extends NitroFetchRequest> = | |
| | _AvailableRouterMethod<R> | |
| | Uppercase<_AvailableRouterMethod<R>>; | |
| // My custom fetch wrapper enables toasts | |
| // You probably don't want this import | |
| import toasteventbus from "primevue/toasteventbus"; | |
| // Note use of UseFetchyOptions (custom interface defined above) | |
| // for opts parameter | |
| export async function useFetchy< | |
| ResT = void, | |
| ErrorT = FetchError, | |
| ReqT extends NitroFetchRequest = NitroFetchRequest, | |
| Method extends AvailableRouterMethod<ReqT> = ResT extends void | |
| ? "get" extends AvailableRouterMethod<ReqT> | |
| ? "get" | |
| : AvailableRouterMethod<ReqT> | |
| : AvailableRouterMethod<ReqT>, | |
| _ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT, | |
| DataT = _ResT, | |
| PickKeys extends KeysOf<DataT> = KeysOf<DataT>, | |
| DefaultT = DataT | |
| >( | |
| request: Ref<ReqT> | ReqT | (() => ReqT), | |
| opts: UseFetchyOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method> = {} | |
| ): Promise<AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | null>> { | |
| // Custom logic inside | |
| opts.alert = opts.alert ?? true; | |
| opts.suppress = opts.suppress ?? true; | |
| let successMessage = ""; | |
| let errorMessage = ""; | |
| // Actual call to original useFetch | |
| const result = await useFetch< | |
| ResT, | |
| ErrorT, | |
| ReqT, | |
| Method, | |
| _ResT, | |
| DataT, | |
| PickKeys, | |
| DefaultT | |
| >(request, { | |
| ...opts, | |
| onResponse({ response }) { | |
| if (response.ok) { | |
| successMessage = response._data?.message; | |
| } else { | |
| errorMessage = response._data?.message || response.statusText; | |
| } | |
| }, | |
| }); | |
| if (opts.alert && errorMessage) { | |
| toasteventbus.emit("add", { | |
| severity: "error", | |
| summary: "Something went wrong", | |
| detail: errorMessage, | |
| life: 5000, | |
| }); | |
| } | |
| if (opts.alert && successMessage) { | |
| toasteventbus.emit("add", { | |
| severity: "success", | |
| summary: "Success", | |
| detail: successMessage, | |
| life: 2000, | |
| }); | |
| } | |
| if (!opts.suppress && result.error.value) { | |
| throw result.error.value; | |
| } | |
| return result; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment