useEntityFetch.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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>(model: T, id?: number|null): AsyncData<InstanceType<T> | null, Error | null> => {
  39. return useAsyncData(
  40. model.entity + '_' + id + '_' + uuid4(),
  41. () => em.fetch(model, id),
  42. { lazy },
  43. )
  44. }
  45. const fetchCollection = <T extends typeof ApiResource> (
  46. model: T,
  47. parent: T | null = null,
  48. query: Query | null = null,
  49. ) => {
  50. const {
  51. data,
  52. refresh,
  53. error,
  54. status
  55. } = useAsyncData(
  56. model.entity + '_many_' + uuid4(),
  57. () => em.fetchCollection(model, parent, query),
  58. { lazy, deep: true },
  59. )
  60. return {
  61. data: computed(() => (data.value !== null ? data.value.value : null)),
  62. refresh,
  63. error,
  64. status,
  65. }
  66. }
  67. const getRef = <T extends ApiResource>(
  68. model: new () => T,
  69. id: Ref<number | null>,
  70. ): ComputedRef<T | null> => {
  71. return computed(() => (id.value ? (em.find(model, id.value) as T) : null))
  72. }
  73. return { fetch, fetchCollection, getRef }
  74. }