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: T, id?: number | null, ) => AsyncData | null, Error | null> fetchCollection: ( model: T, parent?: T | null, query?: typeof Query | Query | null, ) => { data: ComputedRef> | null> refresh: ( opts?: AsyncDataExecuteOptions, ) => Promise>> | null> error: Ref status: Ref } getRef: ( model: new () => T, id: Ref, ) => ComputedRef } export const useEntityFetch = ( lazy: boolean = false, ): useEntityFetchReturnType => { const { em } = useEntityManager() const fetch = ( model: T, id?: number | null, ): AsyncData | null, Error | null> => { return useAsyncData( model.entity + '_' + id + '_' + uuid4(), () => em.fetch(model, id), { lazy }, ) } const fetchCollection = ( model: T, parent: T | null = null, query: Query | null = null, ) => { const { data, 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)), 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 } }