import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios' import { Api } from 'nocodb-sdk' import type { Ref } from 'vue' import type { EventHook, MaybeRef } from '@vueuse/core' import { addAxiosInterceptors } from './interceptors' import { createEventHook, ref, unref, useNuxtApp } from '#imports' import type { NuxtApp } from '#app' interface UseApiReturn { api: Api isLoading: Ref error: Ref | null> response: Ref | null> onError: EventHook>['on'] onResponse: EventHook>['on'] } export function createApiInstance(app: NuxtApp, baseURL = 'http://localhost:8080') { const api = new Api({ baseURL, }) addAxiosInterceptors(api, app) return api } /** todo: add props? */ interface UseApiProps { axiosConfig?: MaybeRef> useGlobalInstance?: MaybeRef } export function useApi(props: UseApiProps = {}): UseApiReturn { const isLoading = ref(false) const error = ref(null) const response = ref(null) const errorHook = createEventHook>() const responseHook = createEventHook>() const api = unref(props.useGlobalInstance) ? useNuxtApp().$api : createApiInstance(useNuxtApp()) api.instance.interceptors.request.use( (config) => { error.value = null response.value = null isLoading.value = true return { ...config, ...unref(props), } }, (requestError) => { errorHook.trigger(requestError) error.value = requestError response.value = null isLoading.value = false return requestError }, ) api.instance.interceptors.response.use( (apiResponse) => { responseHook.trigger(apiResponse as AxiosResponse) // can't properly typecast response.value = apiResponse isLoading.value = false return apiResponse }, (apiError) => { errorHook.trigger(apiError) error.value = apiError isLoading.value = false return apiError }, ) return { api, isLoading, response, error, onError: errorHook.on, onResponse: responseHook.on } }