useModels.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { onBeforeUnmount, ref } from "vue";
  2. import { forEachIn } from "@common/utils/forEachIn";
  3. import { useModelStore } from "@/stores/model";
  4. export const useModels = () => {
  5. const modelStore = useModelStore();
  6. const models = ref([]);
  7. const subscriptions = ref({
  8. created: {},
  9. updated: {},
  10. deleted: {}
  11. });
  12. const deletedSubscriptions = ref({});
  13. const onCreated = async (
  14. modelName: string,
  15. callback: (data?: any) => any
  16. ) => {
  17. const uuid = await modelStore.onCreated(modelName, callback);
  18. subscriptions.value.created[modelName] ??= [];
  19. subscriptions.value.created[modelName].push(uuid);
  20. return uuid;
  21. };
  22. const onUpdated = async (
  23. modelName: string,
  24. callback: (data?: any) => any
  25. ) => {
  26. const uuid = await modelStore.onUpdated(modelName, callback);
  27. subscriptions.value.updated[modelName] ??= [];
  28. subscriptions.value.updated[modelName].push(uuid);
  29. return uuid;
  30. };
  31. const onDeleted = async (
  32. modelName: string,
  33. callback: (data?: any) => any
  34. ) => {
  35. const uuid = await modelStore.onDeleted(modelName, callback);
  36. subscriptions.value.deleted[modelName] ??= [];
  37. subscriptions.value.deleted[modelName].push(uuid);
  38. return uuid;
  39. };
  40. const removeCallback = async (
  41. modelName: string,
  42. type: "created" | "updated" | "deleted",
  43. uuid: string
  44. ) => {
  45. if (
  46. !subscriptions.value[type][modelName] ||
  47. !subscriptions.value[type][modelName].find(
  48. subscription => subscription === uuid
  49. )
  50. )
  51. return;
  52. await modelStore.removeCallback(modelName, type, uuid);
  53. delete subscriptions.value[type][modelName][uuid];
  54. };
  55. const setupDeletedSubscriptions = (registeredModels: any[]) =>
  56. forEachIn(
  57. registeredModels.filter(
  58. (model, index) =>
  59. !deletedSubscriptions.value[model._name] &&
  60. registeredModels.findIndex(
  61. storeModel => storeModel._name === model._name
  62. ) === index
  63. ),
  64. async registeredModel => {
  65. deletedSubscriptions.value[registeredModel._name] =
  66. await onDeleted(registeredModel._name, ({ oldDoc }) => {
  67. const modelIndex = models.value.findIndex(
  68. model => model._id === oldDoc._id
  69. );
  70. if (modelIndex < 0) return;
  71. delete models.value[modelIndex];
  72. });
  73. }
  74. );
  75. const registerModels = async (
  76. storeModels: any[],
  77. relations?: Record<string, string | string[]>
  78. ) => {
  79. const registeredModels = await modelStore.registerModels(
  80. storeModels,
  81. relations
  82. );
  83. models.value.push(...registeredModels);
  84. await setupDeletedSubscriptions(registeredModels);
  85. return registeredModels;
  86. };
  87. const loadModels = async (
  88. modelName: string,
  89. modelIds: string | string[],
  90. relations?: Record<string, string | string[]>
  91. ) => {
  92. const registeredModels = (
  93. await modelStore.loadModels(modelName, modelIds, relations)
  94. ).filter(model => model !== null);
  95. if (registerModels.length === 0) return registeredModels;
  96. models.value.push(...registeredModels);
  97. await setupDeletedSubscriptions(registeredModels);
  98. return registeredModels;
  99. };
  100. const unregisterModels = async (modelIds: string[]) => {
  101. await modelStore.unregisterModels(
  102. modelIds.filter(modelId =>
  103. models.value.find(model => modelId === model._id)
  104. )
  105. );
  106. models.value = models.value.filter(
  107. model => !modelIds.includes(model._id)
  108. );
  109. };
  110. onBeforeUnmount(async () => {
  111. await forEachIn(
  112. Object.entries(subscriptions.value),
  113. async ([type, uuids]) =>
  114. Object.entries(uuids).map(async ([modelName, _subscriptions]) =>
  115. forEachIn(_subscriptions, uuid =>
  116. removeCallback(modelName, type, uuid)
  117. )
  118. )
  119. );
  120. await unregisterModels(models.value.map(model => model._id));
  121. });
  122. return {
  123. models,
  124. subscriptions,
  125. deletedSubscriptions,
  126. onCreated,
  127. onUpdated,
  128. onDeleted,
  129. removeCallback,
  130. registerModels,
  131. unregisterModels,
  132. loadModels
  133. };
  134. };