useEntityFetch.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import type { AsyncData } from '#app'
  2. import type { ComputedRef, Ref } from 'vue'
  3. import { v4 as uuid4 } from 'uuid'
  4. import type {
  5. AsyncDataExecuteOptions,
  6. AsyncDataRequestStatus,
  7. } from '#app/composables/asyncData'
  8. import { useEntityManager } from '~/composables/data/useEntityManager'
  9. import type ApiResource from '~/models/ApiResource'
  10. import type { Collection } from '~/types/data'
  11. import type Query from '~/services/data/Query'
  12. interface useEntityFetchReturnType {
  13. fetch: <T extends typeof ApiResource>(
  14. model: T,
  15. id?: number | null,
  16. ) => AsyncData<InstanceType<T> | null, Error | null>
  17. fetchCollection: <T extends typeof ApiResource>(
  18. model: T,
  19. parent?: T | null,
  20. query?: typeof Query | Query | null,
  21. ) => {
  22. data: ComputedRef<Collection<InstanceType<T>> | null>
  23. refresh: (
  24. opts?: AsyncDataExecuteOptions,
  25. ) => Promise<ComputedRef<Collection<InstanceType<T>>> | null>
  26. error: Ref<Error | null>
  27. status: Ref<AsyncDataRequestStatus>
  28. }
  29. getRef: <T extends ApiResource>(
  30. model: new () => T,
  31. id: Ref<number | null>,
  32. ) => ComputedRef<null | T>
  33. }
  34. export const useEntityFetch = (
  35. lazy: boolean = false,
  36. ): useEntityFetchReturnType => {
  37. const { em } = useEntityManager()
  38. const fetch = <T extends typeof ApiResource>(
  39. model: T,
  40. id?: number | null,
  41. ): AsyncData<InstanceType<T> | null, Error | null> => {
  42. return useAsyncData(
  43. model.entity + '_' + id + '_' + uuid4(),
  44. () => em.fetch(model, id),
  45. { lazy },
  46. )
  47. }
  48. const fetchCollection = <T extends typeof ApiResource>(
  49. model: T,
  50. parent: T | null = null,
  51. query: Query | null = null,
  52. ) => {
  53. const { data, refresh, error, status } = useAsyncData(
  54. model.entity + '_many_' + uuid4(),
  55. () => em.fetchCollection(model, parent, query),
  56. { lazy, deep: true },
  57. )
  58. return {
  59. data: computed(() => (data.value !== null ? data.value.value : null)),
  60. refresh,
  61. error,
  62. status,
  63. }
  64. }
  65. const getRef = <T extends ApiResource>(
  66. model: new () => T,
  67. id: Ref<number | null>,
  68. ): ComputedRef<T | null> => {
  69. return computed(() => (id.value ? (em.find(model, id.value) as T) : null))
  70. }
  71. return { fetch, fetchCollection, getRef }
  72. }