import type { AsyncData } from '#app' import type { ComputedRef, Ref } from 'vue' import { v4 as uuid4 } from 'uuid' import type { AsyncDataExecuteOptions, AsyncDataRequestStatus, } from '#app/composables/asyncData' import { useEntityManager } from '~/composables/data/useEntityManager' import type ApiResource from '~/models/ApiResource' import type { Collection } from '~/types/data' import type Query from '~/services/data/Query' interface useEntityFetchReturnType { fetch: ( model: typeof ApiResource, id: number, ) => AsyncData fetchCollection: ( model: typeof ApiResource, parent?: ApiResource | null, query?: Query | null, ) => { data: ComputedRef pending: Ref refresh: ( opts?: AsyncDataExecuteOptions, ) => Promise | null> error: Ref status: Ref } getRef: ( model: new () => T, id: Ref, ) => ComputedRef } // TODO: améliorer le typage des fonctions sur le modèle de getRef export const useEntityFetch = ( lazy: boolean = false, ): useEntityFetchReturnType => { const { em } = useEntityManager() const fetch = (model: typeof ApiResource, id: number) => useAsyncData( model.entity + '_' + id + '_' + uuid4(), () => em.fetch(model, id, true), { lazy }, ) const fetchCollection = ( model: typeof ApiResource, parent: ApiResource | null = null, query: Query | null = null, ) => { const { data, pending, refresh, error, status } = useAsyncData( model.entity + '_many_' + uuid4(), () => em.fetchCollection(model, parent, query), { lazy, deep: true }, ) return { data: computed(() => (data.value !== null ? data.value.value : null)), pending, refresh, error, status, } } const getRef = ( model: new () => T, id: Ref, ): ComputedRef => { return computed(() => (id.value ? (em.find(model, id.value) as T) : null)) } return { fetch, fetchCollection, getRef } }