useEntityFetch.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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?: InstanceType<T> | null,
  20. query?: typeof Query | Query | null,
  21. ) => {
  22. data: ComputedRef<Collection<InstanceType<T>> | null>
  23. refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
  24. error: Ref<Error | null>
  25. status: Ref<AsyncDataRequestStatus>
  26. }
  27. getRef: <T extends ApiResource>(
  28. model: new () => T,
  29. id: Ref<number | null>,
  30. ) => ComputedRef<null | T>
  31. }
  32. export const useEntityFetch = (
  33. lazy: boolean = false,
  34. ): useEntityFetchReturnType => {
  35. const { em } = useEntityManager()
  36. const fetch = <T extends typeof ApiResource>(
  37. model: T,
  38. id?: number | null,
  39. ): AsyncData<InstanceType<T> | null, Error | null> => {
  40. return useAsyncData(
  41. model.entity + '_' + id + '_' + uuid4(),
  42. () => em.fetch(model, id),
  43. { lazy },
  44. ) as unknown as AsyncData<InstanceType<T> | null, Error | null>
  45. }
  46. const fetchCollection = <T extends typeof ApiResource>(
  47. model: T,
  48. parent: InstanceType<T> | null = null,
  49. query: Query | null = null,
  50. ) => {
  51. const { data, refresh, error, status } = useAsyncData(
  52. model.entity + '_many_' + uuid4(),
  53. () => em.fetchCollection(model, parent, query),
  54. { lazy, deep: true },
  55. )
  56. return {
  57. data: computed(() => (data.value !== null ? data.value.value : null)),
  58. refresh,
  59. error,
  60. status,
  61. }
  62. }
  63. const getRef = <T extends ApiResource>(
  64. model: new () => T,
  65. id: Ref<number | null>,
  66. ): ComputedRef<T | null> => {
  67. return computed(() =>
  68. id.value
  69. ? (em.find(
  70. model as unknown as typeof ApiResource,
  71. id.value,
  72. ) as unknown as T)
  73. : null,
  74. )
  75. }
  76. return { fetch, fetchCollection, getRef }
  77. }