useEntityFetch.ts 2.3 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. import type {Collection as PiniaOrmCollection} from "pinia-orm";
  13. interface useEntityFetchReturnType {
  14. fetch: <T extends typeof ApiResource>(
  15. model: T,
  16. id?: number | null
  17. ) => AsyncData<InstanceType<T> | null, Error | null>
  18. fetchCollection: (
  19. model: typeof ApiResource,
  20. parent?: ApiResource | null,
  21. query?: typeof Query | Query| null,
  22. ) => {
  23. data: ComputedRef<Collection | null>
  24. pending: Ref<boolean>
  25. refresh: (
  26. opts?: AsyncDataExecuteOptions,
  27. ) => Promise<ComputedRef<Collection> | null>
  28. error: Ref<Error | null>
  29. status: Ref<AsyncDataRequestStatus>
  30. }
  31. getRef: <T extends ApiResource>(
  32. model: new () => T,
  33. id: Ref<number | null>,
  34. ) => ComputedRef<null | T>
  35. }
  36. // TODO: améliorer le typage des fonctions sur le modèle de getRef
  37. export const useEntityFetch = (
  38. lazy: boolean = false,
  39. ): useEntityFetchReturnType => {
  40. const { em } = useEntityManager()
  41. const fetch = <T extends typeof ApiResource>(model: T, id?: number|null): AsyncData<InstanceType<T> | null, Error | null> =>
  42. useAsyncData(
  43. model.entity + '_' + id + '_' + uuid4(),
  44. () => em.fetch(model, id),
  45. { lazy },
  46. )
  47. const fetchCollection = (
  48. model: typeof ApiResource,
  49. parent: ApiResource | null = null,
  50. query: Query | null = null,
  51. ) => {
  52. const { data, pending, refresh, error, status } = useAsyncData(
  53. model.entity + '_many_' + uuid4(),
  54. () => em.fetchCollection(model, parent, query),
  55. { lazy, deep: true },
  56. )
  57. return {
  58. data: computed(() => (data.value !== null ? data.value.value : null)),
  59. pending,
  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. }