@arrai-innovations/reactive-helpers 20.1.2 → 21.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/README.md +22 -893
  2. package/config/listCrud.js +30 -27
  3. package/config/objectCrud.js +20 -13
  4. package/index.js +5 -3
  5. package/package.json +5 -3
  6. package/types/config/commonCrud.d.ts +0 -1
  7. package/types/config/listCrud.d.ts +28 -41
  8. package/types/config/objectCrud.d.ts +14 -29
  9. package/types/index.d.ts +5 -4
  10. package/types/tests/unit/config/listCrud.spec.d.ts +0 -1
  11. package/types/tests/unit/config/objectCrud.spec.d.ts +0 -1
  12. package/types/tests/unit/crudPromise.d.ts +42 -15
  13. package/types/tests/unit/mockOnUnmounted.d.ts +0 -1
  14. package/types/tests/unit/poll.d.ts +0 -1
  15. package/types/tests/unit/scopedIt.d.ts +15 -0
  16. package/types/tests/unit/setup.d.ts +2 -0
  17. package/types/tests/unit/use/cancellableIntent.spec.d.ts +0 -1
  18. package/types/tests/unit/use/combineClasses.spec.d.ts +1 -0
  19. package/types/tests/unit/use/list.spec.d.ts +1 -0
  20. package/types/tests/unit/use/listCalculated.spec.d.ts +0 -1
  21. package/types/tests/unit/use/listFilter.spec.d.ts +0 -1
  22. package/types/tests/unit/use/listInstance.spec.d.ts +0 -1
  23. package/types/tests/unit/use/listRelated.spec.d.ts +0 -1
  24. package/types/tests/unit/use/listSearch.spec.d.ts +0 -1
  25. package/types/tests/unit/use/listSort.spec.d.ts +0 -1
  26. package/types/tests/unit/use/listSubscription.spec.d.ts +0 -1
  27. package/types/tests/unit/use/loadingError.spec.d.ts +0 -1
  28. package/types/tests/unit/use/object.spec.d.ts +1 -0
  29. package/types/tests/unit/use/objectCalculated.spec.d.ts +1 -0
  30. package/types/tests/unit/use/objectInstance.spec.d.ts +0 -1
  31. package/types/tests/unit/use/objectRelated.spec.d.ts +1 -0
  32. package/types/tests/unit/use/objectSubscription.spec.d.ts +0 -1
  33. package/types/tests/unit/use/proxyLoadingError.spec.d.ts +0 -1
  34. package/types/tests/unit/use/search.error.spec.d.ts +1 -0
  35. package/types/tests/unit/use/search.spec.d.ts +0 -1
  36. package/types/tests/unit/utils/assignReactiveObject.extra.spec.d.ts +1 -0
  37. package/types/tests/unit/utils/assignReactiveObject.refs.spec.d.ts +1 -0
  38. package/types/tests/unit/utils/assignReactiveObject.spec.d.ts +0 -1
  39. package/types/tests/unit/utils/cancellableFetch.spec.d.ts +1 -0
  40. package/types/tests/unit/utils/classes.spec.d.ts +0 -1
  41. package/types/tests/unit/utils/compact.spec.d.ts +1 -0
  42. package/types/tests/unit/utils/deepUnref.spec.d.ts +1 -0
  43. package/types/tests/unit/utils/deleteKey.spec.d.ts +0 -1
  44. package/types/tests/unit/utils/flattenPaths.spec.d.ts +0 -1
  45. package/types/tests/unit/utils/flattenPathsWithValues.spec.d.ts +1 -0
  46. package/types/tests/unit/utils/getFakePk.spec.d.ts +1 -0
  47. package/types/tests/unit/utils/keepAliveTry.spec.d.ts +1 -0
  48. package/types/tests/unit/utils/keyDiff.spec.d.ts +0 -1
  49. package/types/tests/unit/utils/set.spec.d.ts +0 -1
  50. package/types/tests/unit/utils/transformWalk.spec.d.ts +1 -0
  51. package/types/tests/unit/utils/unwrapNested.spec.d.ts +1 -0
  52. package/types/tests/unit/utils/watches.spec.d.ts +0 -1
  53. package/types/use/cancellableIntent.d.ts +121 -48
  54. package/types/use/combineClasses.d.ts +0 -1
  55. package/types/use/error.d.ts +48 -0
  56. package/types/use/list.d.ts +9 -32
  57. package/types/use/listCalculated.d.ts +107 -49
  58. package/types/use/listFilter.d.ts +13 -31
  59. package/types/use/listInstance.d.ts +137 -71
  60. package/types/use/listRelated.d.ts +106 -43
  61. package/types/use/listSearch.d.ts +24 -12
  62. package/types/use/listSort.d.ts +3 -34
  63. package/types/use/listSubscription.d.ts +40 -57
  64. package/types/use/loading.d.ts +37 -0
  65. package/types/use/loadingError.d.ts +5 -100
  66. package/types/use/object.d.ts +3 -12
  67. package/types/use/objectCalculated.d.ts +3 -9
  68. package/types/use/objectInstance.d.ts +59 -47
  69. package/types/use/objectRelated.d.ts +3 -9
  70. package/types/use/objectSubscription.d.ts +33 -51
  71. package/types/use/proxyError.d.ts +27 -0
  72. package/types/use/proxyLoading.d.ts +15 -0
  73. package/types/use/proxyLoadingError.d.ts +8 -16
  74. package/types/use/search.d.ts +2 -3
  75. package/types/utils/assignReactiveObject.d.ts +0 -1
  76. package/types/utils/cancellableFetch.d.ts +0 -1
  77. package/types/utils/cancellablePromise.d.ts +0 -1
  78. package/types/utils/classes.d.ts +2 -8
  79. package/types/utils/compact.d.ts +0 -1
  80. package/types/utils/deepUnref.d.ts +2 -23
  81. package/types/utils/deleteKey.d.ts +6 -6
  82. package/types/utils/flattenPaths.d.ts +0 -1
  83. package/types/utils/flattenPathsWithValues.d.ts +29 -0
  84. package/types/utils/getFakePk.d.ts +0 -1
  85. package/types/utils/keepAliveTry.d.ts +0 -1
  86. package/types/utils/keyDiff.d.ts +9 -10
  87. package/types/utils/loadingCombine.d.ts +0 -1
  88. package/types/utils/proxyRunning.d.ts +2 -3
  89. package/types/utils/refIfReactive.d.ts +0 -1
  90. package/types/utils/relatedCalculatedHelpers.d.ts +0 -1
  91. package/types/utils/set.d.ts +0 -1
  92. package/types/utils/transformWalk.d.ts +0 -1
  93. package/types/utils/unwrapNested.d.ts +0 -1
  94. package/types/utils/watches.d.ts +0 -1
  95. package/use/cancellableIntent.js +185 -100
  96. package/use/error.js +44 -0
  97. package/use/list.js +51 -111
  98. package/use/listCalculated.js +75 -98
  99. package/use/listFilter.js +91 -186
  100. package/use/listInstance.js +357 -282
  101. package/use/listRelated.js +52 -72
  102. package/use/listSearch.js +49 -86
  103. package/use/listSort.js +121 -237
  104. package/use/listSubscription.js +181 -274
  105. package/use/loading.js +35 -0
  106. package/use/loadingError.js +7 -81
  107. package/use/object.js +47 -67
  108. package/use/objectCalculated.js +103 -65
  109. package/use/objectInstance.js +253 -241
  110. package/use/objectRelated.js +48 -30
  111. package/use/objectSubscription.js +110 -175
  112. package/use/proxyError.js +48 -0
  113. package/use/proxyLoading.js +22 -0
  114. package/use/proxyLoadingError.js +9 -35
  115. package/use/search.js +4 -2
  116. package/utils/assignReactiveObject.js +8 -8
  117. package/utils/classes.js +7 -28
  118. package/utils/deepUnref.js +15 -2
  119. package/utils/deleteKey.js +13 -5
  120. package/utils/flattenPathsWithValues.js +65 -0
  121. package/utils/keyDiff.js +5 -5
  122. package/utils/proxyRunning.js +16 -10
  123. package/types/config/commonCrud.d.ts.map +0 -1
  124. package/types/config/listCrud.d.ts.map +0 -1
  125. package/types/config/objectCrud.d.ts.map +0 -1
  126. package/types/index.d.ts.map +0 -1
  127. package/types/tests/unit/config/listCrud.spec.d.ts.map +0 -1
  128. package/types/tests/unit/config/objectCrud.spec.d.ts.map +0 -1
  129. package/types/tests/unit/crudPromise.d.ts.map +0 -1
  130. package/types/tests/unit/expectHelpers.d.ts +0 -2
  131. package/types/tests/unit/expectHelpers.d.ts.map +0 -1
  132. package/types/tests/unit/mockOnUnmounted.d.ts.map +0 -1
  133. package/types/tests/unit/poll.d.ts.map +0 -1
  134. package/types/tests/unit/use/cancellableIntent.spec.d.ts.map +0 -1
  135. package/types/tests/unit/use/listCalculated.spec.d.ts.map +0 -1
  136. package/types/tests/unit/use/listFilter.spec.d.ts.map +0 -1
  137. package/types/tests/unit/use/listInstance.spec.d.ts.map +0 -1
  138. package/types/tests/unit/use/listRelated.spec.d.ts.map +0 -1
  139. package/types/tests/unit/use/listSearch.spec.d.ts.map +0 -1
  140. package/types/tests/unit/use/listSort.spec.d.ts.map +0 -1
  141. package/types/tests/unit/use/listSubscription.spec.d.ts.map +0 -1
  142. package/types/tests/unit/use/loadingError.spec.d.ts.map +0 -1
  143. package/types/tests/unit/use/objectInstance.spec.d.ts.map +0 -1
  144. package/types/tests/unit/use/objectSubscription.spec.d.ts.map +0 -1
  145. package/types/tests/unit/use/proxyLoadingError.spec.d.ts.map +0 -1
  146. package/types/tests/unit/use/search.spec.d.ts.map +0 -1
  147. package/types/tests/unit/utils/assignReactiveObject.spec.d.ts.map +0 -1
  148. package/types/tests/unit/utils/classes.spec.d.ts.map +0 -1
  149. package/types/tests/unit/utils/deleteKey.spec.d.ts.map +0 -1
  150. package/types/tests/unit/utils/flattenPaths.spec.d.ts.map +0 -1
  151. package/types/tests/unit/utils/keyDiff.spec.d.ts.map +0 -1
  152. package/types/tests/unit/utils/set.spec.d.ts.map +0 -1
  153. package/types/tests/unit/utils/watches.spec.d.ts.map +0 -1
  154. package/types/use/cancellableIntent.d.ts.map +0 -1
  155. package/types/use/combineClasses.d.ts.map +0 -1
  156. package/types/use/list.d.ts.map +0 -1
  157. package/types/use/listCalculated.d.ts.map +0 -1
  158. package/types/use/listFilter.d.ts.map +0 -1
  159. package/types/use/listInstance.d.ts.map +0 -1
  160. package/types/use/listKeys.d.ts +0 -15
  161. package/types/use/listKeys.d.ts.map +0 -1
  162. package/types/use/listRelated.d.ts.map +0 -1
  163. package/types/use/listSearch.d.ts.map +0 -1
  164. package/types/use/listSort.d.ts.map +0 -1
  165. package/types/use/listSubscription.d.ts.map +0 -1
  166. package/types/use/loadingError.d.ts.map +0 -1
  167. package/types/use/object.d.ts.map +0 -1
  168. package/types/use/objectCalculated.d.ts.map +0 -1
  169. package/types/use/objectInstance.d.ts.map +0 -1
  170. package/types/use/objectRelated.d.ts.map +0 -1
  171. package/types/use/objectSubscription.d.ts.map +0 -1
  172. package/types/use/paginatedListInstance.d.ts +0 -60
  173. package/types/use/paginatedListInstance.d.ts.map +0 -1
  174. package/types/use/proxyLoadingError.d.ts.map +0 -1
  175. package/types/use/search.d.ts.map +0 -1
  176. package/types/use/watchesRunning.d.ts +0 -63
  177. package/types/use/watchesRunning.d.ts.map +0 -1
  178. package/types/utils/assignReactiveObject.d.ts.map +0 -1
  179. package/types/utils/cancellableFetch.d.ts.map +0 -1
  180. package/types/utils/cancellablePromise.d.ts.map +0 -1
  181. package/types/utils/classes.d.ts.map +0 -1
  182. package/types/utils/compact.d.ts.map +0 -1
  183. package/types/utils/deepUnref.d.ts.map +0 -1
  184. package/types/utils/deleteKey.d.ts.map +0 -1
  185. package/types/utils/flattenPaths.d.ts.map +0 -1
  186. package/types/utils/getFakePk.d.ts.map +0 -1
  187. package/types/utils/keepAliveTry.d.ts.map +0 -1
  188. package/types/utils/keyDiff.d.ts.map +0 -1
  189. package/types/utils/loadingCombine.d.ts.map +0 -1
  190. package/types/utils/proxyRunning.d.ts.map +0 -1
  191. package/types/utils/refIfReactive.d.ts.map +0 -1
  192. package/types/utils/relatedCalculatedHelpers.d.ts.map +0 -1
  193. package/types/utils/set.d.ts.map +0 -1
  194. package/types/utils/transformWalk.d.ts.map +0 -1
  195. package/types/utils/unwrapNested.d.ts.map +0 -1
  196. package/types/utils/watches.d.ts.map +0 -1
  197. package/use/listKeys.js +0 -105
  198. package/use/paginatedListInstance.js +0 -126
  199. package/use/watchesRunning.js +0 -69
package/use/list.js CHANGED
@@ -1,21 +1,11 @@
1
1
  import { useListCalculated } from "./listCalculated.js";
2
2
  import { useListFilter } from "./listFilter.js";
3
3
  import { useListInstance } from "./listInstance.js";
4
- import {
5
- listSortFunctions,
6
- listFilterFunctions,
7
- listRelatedFunctions,
8
- listCalculatedFunctions,
9
- listSubscriptionFunctions,
10
- listInstanceFunctions,
11
- listSearchFunctions,
12
- } from "./listKeys.js";
13
4
  import { useListRelated } from "./listRelated.js";
14
5
  import { useListSearch } from "./listSearch.js";
15
6
  import { useListSort } from "./listSort.js";
16
7
  import { useListSubscription } from "./listSubscription.js";
17
- import { usePagedListInstance } from "./paginatedListInstance.js";
18
- import { effectScope, reactive, shallowReactive, shallowReadonly, toRef } from "vue";
8
+ import { effectScope, shallowReactive, shallowReadonly, toRef } from "vue";
19
9
 
20
10
  /**
21
11
  * Provides a comprehensive Vue 3 composable function for managing a list of objects. This module orchestrates several
@@ -66,45 +56,17 @@ export class ListError extends Error {
66
56
  /**
67
57
  * @typedef {object} ListOptions
68
58
  * @property {ListRawProps} props - The properties for configuring the list.
69
- * @property {import('../config/listCrud.js').ListCrudHandlers} handlers - Additional handlers to be included in the list manager.
70
- * @property {boolean} paged - Indicates whether the list should be paginated.
71
- * @property {import('vue').Ref<boolean>|boolean} keepOldPages - Indicates whether old pages should be kept when paginating.
72
- * @property {boolean} clearListOnListIntentTriggered - Indicates whether the list should be cleared when the list intent is triggered.
73
- * @property {number} searchThrottle - The throttle time for text search.
74
- * @property {number} sortThrottleWait - The throttle time for sorting.
75
- * @property {boolean} searchShowAllWhenEmpty - Indicates whether all items should be shown when the search query is empty.
76
- */
77
-
78
- /**
79
- * Represents the combined state definitions for all list-related components.
80
- * This interface aggregates the raw state from multiple list management functionalities.
81
- *
82
- * @typedef {(
83
- * (
84
- * import('./listInstance.js').ListInstanceRawState |
85
- * import('./paginatedListInstance.js').PagedListInstanceRawState
86
- * ) &
87
- * import('./listSubscription.js').ListSubscriptionRawState &
88
- * import('./listRelated.js').ListRelatedRawState &
89
- * import('./listCalculated.js').ListCalculatedRawState &
90
- * import('./listFilter.js').ListFilterRawState &
91
- * import('./listSearch.js').ListSearchRawState &
92
- * import('./listSort.js').ListSortRawState
93
- * )} ListRawState
94
- */
95
-
96
- /**
97
- * Represents the reactive state derived from aggregating states of various list-related components.
98
- * This state is typically used within Vue components for reactivity and access to updated list properties.
99
- *
100
- * @typedef {import('vue').UnwrapNestedRefs<ListRawState>} ListState
59
+ * @property {import('../config/listCrud.js').ListCrudHandlers} [handlers] - Additional handlers to be included in the list manager.
60
+ * @property {number} [searchThrottle] - The throttle time for text search.
61
+ * @property {number} [sortThrottleWait] - The throttle time for sorting.
62
+ * @property {boolean} [searchShowAllWhenEmpty] - Indicates whether all items should be shown when the search query is empty.
101
63
  */
102
64
 
103
65
  /**
104
66
  * Holds references to instances of all list-related composables, facilitating direct access and management.
105
67
  *
106
68
  * @typedef {{
107
- * listInstance: import('./listInstance.js').ListInstance | import('./paginatedListInstance.js').PagedListInstance,
69
+ * listInstance: import('./listInstance.js').ListInstance,
108
70
  * listSubscription: import('./listSubscription.js').ListSubscription,
109
71
  * listRelated: import('./listRelated.js').ListRelated,
110
72
  * listCalculated: import('./listCalculated.js').ListCalculated,
@@ -123,20 +85,14 @@ export class ListError extends Error {
123
85
  * )} ListFunctions
124
86
  */
125
87
 
126
- // & import('./listRelated.js').ListRelatedFunctions
127
- // & import('./listCalculated.js').ListCalculatedFunctions
128
- // & import('./listFilter.js').ListFilterFunctions
129
- // & import('./listSearch.js').ListSearchFunctions
130
- // & import('./listSort.js').ListSortFunctions
131
-
132
88
  /**
133
89
  * Encapsulates properties relevant to the overall management of list-related hooks, including state, direct access to hooks,
134
90
  * and scoped effects.
135
91
  *
136
92
  * @typedef {object} ListManagerProperties
137
93
  * @property {ListManaged} managed - A readonly reference to the managed list hooks.
138
- * @property {ListState} state - Represents the final reactive state in the list processing chain.
139
- * @property {import('vue').EffectScope} effectScope - Encapsulates all reactive effects related to the list hooks.
94
+ * @property {import('./listSort.js').ListSortState} state - Represents the final reactive state in the list processing chain.
95
+ * @property {() => void} stop - A function to stop the effect scope and clean up resources.
140
96
  */
141
97
 
142
98
  /**
@@ -146,6 +102,31 @@ export class ListError extends Error {
146
102
  * @typedef {ListFunctions & ListManagerProperties} ListManager
147
103
  */
148
104
 
105
+ /* eslint-disable jsdoc/valid-types */
106
+ /**
107
+ * Extract function properties from a source object, excluding `stop`.
108
+ *
109
+ * @template {object} T
110
+ * @param {T} source - The source object from which to extract function properties.
111
+ * @returns {{
112
+ * [K in keyof T as K extends "stop" ? never : T[K] extends (...args: any[]) => any ? K : never]: T[K]
113
+ * }} - An object containing only the function properties of the source object, excluding `stop`.
114
+ */
115
+ function mergeFns(source) {
116
+ const returnedFns = {};
117
+ for (const key of Object.keys(source)) {
118
+ if (key !== "stop") {
119
+ const val = source[key];
120
+ if (typeof val === "function") {
121
+ returnedFns[key] = val;
122
+ }
123
+ }
124
+ }
125
+ // @ts-ignore
126
+ return returnedFns;
127
+ }
128
+ /* eslint-enable jsdoc/valid-types */
129
+
149
130
  /**
150
131
  * Initializes multiple list management instances with provided configurations.
151
132
  *
@@ -177,16 +158,8 @@ export const useLists = (listOptions) => {
177
158
  * @returns {ListManager} - The managed stack of list-related composable functions.
178
159
  * @throws {ListError} - If required options are not provided.
179
160
  */
180
- export const useList = ({
181
- props,
182
- handlers = {},
183
- paged,
184
- keepOldPages,
185
- clearListOnListIntentTriggered,
186
- searchThrottle = 500,
187
- sortThrottleWait,
188
- searchShowAllWhenEmpty,
189
- }) => {
161
+ export const useList = ({ props, handlers = {}, searchThrottle = 500, sortThrottleWait, searchShowAllWhenEmpty }) => {
162
+ /** @type {ListManaged} */
190
163
  const managed = shallowReactive({
191
164
  listInstance: null,
192
165
  listSubscription: null,
@@ -196,12 +169,6 @@ export const useList = ({
196
169
  listSearch: null,
197
170
  listSort: null,
198
171
  });
199
- if (paged === undefined || keepOldPages === undefined || clearListOnListIntentTriggered === undefined) {
200
- throw new ListError(
201
- "useList requires paged, keepOldPages, and clearListOnListIntentTriggered to be all set.",
202
- "missing-arguments"
203
- );
204
- }
205
172
 
206
173
  if (!("params" in props)) {
207
174
  console.error("params not set, must be true for intendToList or intendToSubscribe to work.");
@@ -210,18 +177,15 @@ export const useList = ({
210
177
  const es = effectScope();
211
178
 
212
179
  es.run(() => {
213
- managed.listInstance = (paged ? usePagedListInstance : useListInstance)({
180
+ managed.listInstance = useListInstance({
214
181
  props,
215
182
  handlers,
216
- keepOldPages,
217
183
  });
218
184
 
219
185
  managed.listSubscription = useListSubscription({
220
186
  listInstance: managed.listInstance,
221
- clearListOnListIntentTriggered,
187
+ props,
222
188
  });
223
- managed.listSubscription.state.intendToList = toRef(props, "intendToList");
224
- managed.listSubscription.state.intendToSubscribe = toRef(props, "intendToSubscribe");
225
189
 
226
190
  managed.listRelated = useListRelated({
227
191
  parentState: managed.listSubscription.state,
@@ -241,12 +205,7 @@ export const useList = ({
241
205
 
242
206
  managed.listSearch = useListSearch({
243
207
  parentState: managed.listFilter.state,
244
- props: reactive({
245
- textSearchRules: toRef(props, "textSearchRules"),
246
- textSearchValue: toRef(props, "textSearchValue"),
247
- customDocumentOptions: toRef(props, "customDocumentOptions"),
248
- customSearchOptions: toRef(props, "customSearchOptions"),
249
- }),
208
+ props,
250
209
  throttle: searchThrottle,
251
210
  showAllWhenEmpty: searchShowAllWhenEmpty,
252
211
  });
@@ -258,40 +217,21 @@ export const useList = ({
258
217
  });
259
218
  });
260
219
 
261
- const clearError = () => {
262
- managed.listSubscription.clearError();
263
- managed.listInstance.clearError();
264
- };
265
-
220
+ // noinspection UnnecessaryLocalVariableJS
266
221
  /** @type {ListManager} */
267
- // @ts-ignore - we're going to assign remaining properties below.
268
- const returnObject = {
269
- // we manage the keys on both of these, so hands off the root.
222
+ const manager = {
270
223
  managed: shallowReadonly(managed),
271
224
  state: managed.listSort.state,
272
- effectScope: es,
225
+ stop: () => {
226
+ es.stop();
227
+ },
228
+ ...mergeFns(managed.listInstance),
229
+ ...mergeFns(managed.listSubscription),
230
+ ...mergeFns(managed.listRelated),
231
+ ...mergeFns(managed.listCalculated),
232
+ ...mergeFns(managed.listFilter),
233
+ ...mergeFns(managed.listSearch),
234
+ ...mergeFns(managed.listSort),
273
235
  };
274
- const handledDuplicateFunctions = {
275
- clearError,
276
- };
277
- for (const [source, fnNames] of [
278
- [managed.listInstance, listInstanceFunctions],
279
- [managed.listSubscription, listSubscriptionFunctions],
280
- [managed.listRelated, listRelatedFunctions],
281
- [managed.listCalculated, listCalculatedFunctions],
282
- [managed.listFilter, listFilterFunctions],
283
- [managed.listSearch, listSearchFunctions],
284
- [managed.listSort, listSortFunctions],
285
- ]) {
286
- for (const fnName of fnNames) {
287
- if (handledDuplicateFunctions[fnName]) {
288
- continue;
289
- }
290
- returnObject[fnName] = source[fnName];
291
- }
292
- }
293
- for (const [fnName, fn] of Object.entries(handledDuplicateFunctions)) {
294
- returnObject[fnName] = fn;
295
- }
296
- return returnObject;
236
+ return manager;
297
237
  };
@@ -1,19 +1,8 @@
1
- import { difference } from "../utils/set.js";
2
1
  import { keyDiff } from "../utils/keyDiff.js";
3
2
  import { loadingCombine } from "../utils/loadingCombine.js";
4
3
  import { proxyRunning } from "../utils/proxyRunning.js";
5
- import {
6
- listCalculatedStateKeys,
7
- listFilterStateKeys,
8
- listInstanceStateKeys,
9
- listRelatedStateKeys,
10
- listSearchStateKeys,
11
- listSortStateKeys,
12
- listSubscriptionStateKeys,
13
- } from "./listKeys.js";
14
- import { useWatchesRunning } from "./watchesRunning.js";
15
4
  import isEmpty from "lodash-es/isEmpty.js";
16
- import { computed, effectScope, onScopeDispose, reactive, ref, toRef, unref, watch } from "vue";
5
+ import { computed, effectScope, nextTick, reactive, ref, toRef, toRefs, unref, watch } from "vue";
17
6
 
18
7
  /**
19
8
  * This module provides a Vue Composition API composable function for dynamically calculating properties in lists
@@ -29,9 +18,9 @@ import { computed, effectScope, onScopeDispose, reactive, ref, toRef, unref, wat
29
18
  * object from the list, optionally its related objects, and previously calculated properties to compute a new
30
19
  * property. These functions are reactive and re-evaluate when underlying dependencies change.
31
20
  *
32
- * @typedef {import('vue').Ref<{
21
+ * @typedef {{
33
22
  * [rule: string]: (
34
- * object: import('./listInstance.js').ListObject,
23
+ * object: import('../use/objectInstance.js').ExistingCrudObject,
35
24
  * relatedObject: {
36
25
  * [rule: string]: any,
37
26
  * },
@@ -39,8 +28,7 @@ import { computed, effectScope, onScopeDispose, reactive, ref, toRef, unref, wat
39
28
  * [rule: string]: import('vue').ComputedRef<any>,
40
29
  * }
41
30
  * ) => any,
42
- * }>} ListCalculatedRules
43
- *
31
+ * }} ListCalculatedRules
44
32
  */
45
33
 
46
34
  /**
@@ -51,8 +39,8 @@ import { computed, effectScope, onScopeDispose, reactive, ref, toRef, unref, wat
51
39
  * @property {ListCalculatedRules} calculatedObjectsRules - The rules for the calculated objects.
52
40
  * @property {boolean} calculatedObjectsParentStateObjectsWatchRunning - Whether the parent state objects watch is running.
53
41
  * @property {boolean} calculatedObjectsWatchRunning - Whether the calculated objects watch is running.
54
- * @property {boolean} calculatedRunning - Whether the calculated properties are running.
55
- * @property {import('vue').Ref<boolean>} running - Whether the list is running.
42
+ * @property {import('vue').ComputedRef<boolean>} calculatedRunning - Whether the calculated properties are running.
43
+ * @property {import('vue').ComputedRef<boolean>} running - Whether the list is running.
56
44
  * @private
57
45
  */
58
46
 
@@ -86,24 +74,12 @@ import { computed, effectScope, onScopeDispose, reactive, ref, toRef, unref, wat
86
74
  * )>} ListCalculatedParentState
87
75
  */
88
76
 
89
- const parentStateKeys = difference(
90
- new Set([
91
- ...listInstanceStateKeys,
92
- ...listSubscriptionStateKeys,
93
- ...listRelatedStateKeys,
94
- ...listFilterStateKeys,
95
- ...listSortStateKeys,
96
- ...listSearchStateKeys,
97
- ]),
98
- new Set(listCalculatedStateKeys)
99
- );
100
-
101
77
  /**
102
78
  * The options to create a list calculated composition function.
103
79
  *
104
80
  * @typedef {object} ListCalculatedOptions - Options to configure the behavior of the list calculated properties.
105
81
  * @property {ListCalculatedParentState} parentState - The parent state that interacts with the calculated objects.
106
- * @property {ListCalculatedRules} calculatedObjectsRules - A reactive reference to rules used for dynamic calculations
82
+ * @property {import('vue').Ref<ListCalculatedRules>} calculatedObjectsRules - A reactive reference to rules used for dynamic calculations
107
83
  * within list objects. Proper setup of this reference ensures that updates are managed reactively, including deep
108
84
  * property changes.
109
85
  */
@@ -114,8 +90,7 @@ const parentStateKeys = difference(
114
90
  * @typedef {object} ListCalculatedProperties
115
91
  * @property {ListCalculatedState} state - The state for the list calculated property.
116
92
  * @property {ListCalculatedParentState} parentState - The parent state object.
117
- * @property {import('./watchesRunning.js').WatchesRunning} watchesRunning - The watches running.
118
- * @property {import('vue').EffectScope} effectScope - The effect scope for the list calculated property.
93
+ * @property {() => void} stop - Stops composition's effects and cleans up resources.
119
94
  */
120
95
 
121
96
  // if we provided functions, we would add a typedef and mix them into ListCalculated
@@ -199,13 +174,22 @@ export function useListCalculateds(listCalculatedArgs) {
199
174
  * list, facilitating real-time updates and complex dependency management across multiple components.
200
175
  */
201
176
  export function useListCalculated({ parentState, calculatedObjectsRules }) {
177
+ const es = effectScope();
178
+ const parentRefs = toRefs(parentState);
179
+ /** @type {import('vue').Ref<boolean|undefined>} */
180
+ const parentRunning = ref(undefined);
181
+ proxyRunning(parentState, "running", parentRunning);
202
182
  /** @type {ListCalculatedState} */
203
- // @ts-ignore - The rest of the properties are added in the effect scope.
204
183
  const state = reactive({
184
+ ...parentRefs,
205
185
  calculatedObjectsRules,
206
186
  calculatedObjects: {},
207
- calculatedObjectsParentStateObjectsWatchRunning: false,
208
- calculatedObjectsWatchRunning: false,
187
+ calculatedObjectsParentStateObjectsWatchRunning: true,
188
+ calculatedObjectsWatchRunning: true,
189
+ calculatedRunning: computed(() =>
190
+ loadingCombine(state.calculatedObjectsParentStateObjectsWatchRunning, state.calculatedObjectsWatchRunning)
191
+ ),
192
+ running: computed(() => loadingCombine(state.calculatedRunning, parentRunning.value)),
209
193
  });
210
194
  const calculatedObjectsEffectScopes = {};
211
195
 
@@ -217,14 +201,16 @@ export function useListCalculated({ parentState, calculatedObjectsRules }) {
217
201
  for (const removedKey of removedKeys) {
218
202
  delete state.calculatedObjects[removedKey];
219
203
  if (calculatedObjectsEffectScopes[removedKey]) {
220
- calculatedObjectsEffectScopes[removedKey].stop();
204
+ calculatedObjectsEffectScopes[removedKey].objectScope.stop();
221
205
  delete calculatedObjectsEffectScopes[removedKey];
222
206
  }
223
207
  }
224
208
  for (const addedKey of addedKeys) {
225
209
  state.calculatedObjects[addedKey] = {};
226
210
  }
227
- state.calculatedObjectsParentStateObjectsWatchRunning = false;
211
+ nextTick(() => {
212
+ state.calculatedObjectsParentStateObjectsWatchRunning = false;
213
+ });
228
214
  }
229
215
 
230
216
  function calculatedObjectsWatch() {
@@ -248,84 +234,75 @@ export function useListCalculated({ parentState, calculatedObjectsRules }) {
248
234
  addedRuleKeys = [];
249
235
  }
250
236
  for (const removedRuleKey of removedRuleKeys) {
251
- // @ts-ignore - this is an unofficial api, effect is internal
252
- calculatedObjectsObject[removedRuleKey]?.effect?.stop?.();
253
- delete calculatedObjectsObject[removedRuleKey];
237
+ if (calculatedObjectsEffectScopes[objectKey]?.ruleScopes?.[removedRuleKey]) {
238
+ calculatedObjectsEffectScopes[objectKey].ruleScopes[removedRuleKey].stop();
239
+ delete calculatedObjectsEffectScopes[objectKey].ruleScopes[removedRuleKey];
240
+ }
254
241
  }
255
242
  if (!calculatedObjectsEffectScopes[objectKey]) {
256
- calculatedObjectsEffectScopes[objectKey] = effectScope();
243
+ calculatedObjectsEffectScopes[objectKey] = {
244
+ objectScope: es.run(() => effectScope()),
245
+ ruleScopes: {},
246
+ };
257
247
  }
258
248
  const originalObjectRef = toRef(parentState.objects, objectKey);
259
249
  const relatedObjectRef = parentState.relatedObjects
260
250
  ? toRef(parentState.relatedObjects, objectKey)
261
251
  : ref(undefined);
262
- calculatedObjectsEffectScopes[objectKey].run(() => {
252
+ calculatedObjectsEffectScopes[objectKey].objectScope.run(() => {
263
253
  for (const addedRuleKey of addedRuleKeys) {
264
- calculatedObjectsObject[addedRuleKey] = computed(() =>
265
- state.calculatedObjectsRules?.[addedRuleKey]?.(
266
- unref(originalObjectRef),
267
- unref(relatedObjectRef),
268
- calculatedObjectsObject
254
+ const addedRuleScope = effectScope();
255
+ calculatedObjectsObject[addedRuleKey] = addedRuleScope.run(() =>
256
+ computed(() =>
257
+ state.calculatedObjectsRules?.[addedRuleKey]?.(
258
+ unref(originalObjectRef),
259
+ unref(relatedObjectRef),
260
+ calculatedObjectsObject
261
+ )
269
262
  )
270
263
  );
264
+ calculatedObjectsEffectScopes[objectKey].ruleScopes[addedRuleKey] = addedRuleScope;
271
265
  }
272
266
  });
273
267
  }
274
- state.calculatedObjectsWatchRunning = false;
275
- }
276
-
277
- let watchesRunning = null;
278
-
279
- const es = effectScope();
280
-
281
- es.run(() => {
282
- for (const key of parentStateKeys) {
283
- state[key] = toRef(parentState, key);
284
- }
285
-
286
- watch(() => Object.keys(parentState.objects), parentStateObjectsWatch, { immediate: true });
287
- watch(
288
- [
289
- () => Object.keys(state.calculatedObjects),
290
- () =>
291
- state.calculatedObjectsRules
292
- ? Object.keys(state.calculatedObjectsRules)
293
- : state.calculatedObjectsRules,
294
- ],
295
- calculatedObjectsWatch,
296
- { immediate: true }
297
- );
298
-
299
- watchesRunning = useWatchesRunning({
300
- triggerRefs: [
301
- computed(() =>
302
- state.calculatedObjectsRules && !isEmpty(state.calculatedObjectsRules) ? parentState.loading : false
303
- ),
304
- ],
305
- watchSentinelRefs: [
306
- toRef(state, "calculatedObjectsParentStateObjectsWatchRunning"),
307
- toRef(state, "calculatedObjectsWatchRunning"),
308
- ],
268
+ nextTick(() => {
269
+ state.calculatedObjectsWatchRunning = false;
309
270
  });
271
+ }
310
272
 
311
- // @ts-ignore - proxy the running property
312
- state.calculatedRunning = toRef(watchesRunning.state, "running");
313
- const parentRunning = ref(undefined);
314
- proxyRunning(parentState, "running", parentRunning);
315
- // @ts-ignore - combine the running properties
316
- state.running = computed(() => loadingCombine(watchesRunning.state.running, parentRunning.value));
317
-
318
- onScopeDispose(() => {
319
- for (const objectKey of Object.keys(calculatedObjectsEffectScopes)) {
320
- calculatedObjectsEffectScopes[objectKey].stop();
321
- }
322
- });
323
- });
273
+ watch(
274
+ () => Object.keys(parentState.objects),
275
+ () => {
276
+ state.calculatedObjectsParentStateObjectsWatchRunning = true;
277
+ },
278
+ { flush: "sync" }
279
+ );
280
+ watch(() => Object.keys(parentState.objects), parentStateObjectsWatch, { immediate: true });
281
+ watch(
282
+ () => Object.keys(state.calculatedObjects),
283
+ () => {
284
+ state.calculatedObjectsWatchRunning = true;
285
+ },
286
+ { flush: "sync" }
287
+ );
288
+ watch(
289
+ [
290
+ () => Object.keys(state.calculatedObjects),
291
+ () =>
292
+ state.calculatedObjectsRules ? Object.keys(state.calculatedObjectsRules) : state.calculatedObjectsRules,
293
+ ],
294
+ calculatedObjectsWatch,
295
+ { immediate: true }
296
+ );
324
297
 
325
298
  return {
326
299
  state,
327
300
  parentState,
328
- watchesRunning,
329
- effectScope: es,
301
+ stop: () => {
302
+ es.stop();
303
+ for (const key of Object.keys(calculatedObjectsEffectScopes)) {
304
+ delete calculatedObjectsEffectScopes[key];
305
+ }
306
+ },
330
307
  };
331
308
  }