@arrai-innovations/reactive-helpers 3.0.0 → 3.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arrai-innovations/reactive-helpers",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
5
5
  "main": "index.js",
6
6
  "directories": {
package/use/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./cancellableIntent.js";
1
2
  export * from "./listCalculated.js";
2
3
  export * from "./listFilter.js";
3
4
  export * from "./listInstance.js";
@@ -11,3 +12,4 @@ export * from "./objectRelated.js";
11
12
  export * from "./objectSubscription.js";
12
13
  export * from "./paginatedListInstance.js";
13
14
  export * from "./search.js";
15
+ export * from "./watchesRunning.js";
@@ -1,6 +1,7 @@
1
1
  import { isEmpty } from "lodash";
2
2
  import { computed, effectScope, onScopeDispose, reactive, toRef, watch } from "vue";
3
- import { keyDiff } from "../utils";
3
+ import { keyDiff, loadingCombine } from "../utils";
4
+ import { useWatchesRunning } from "./watchesRunning";
4
5
 
5
6
  export function useListCalculateds(instances, args) {
6
7
  for (const [key, value] of Object.entries(args)) {
@@ -23,6 +24,8 @@ export function useListCalculated({
23
24
  calculatedObjectsRules,
24
25
  calculatedObjectsObjects: {},
25
26
  objects: {},
27
+ parentStateObjectsWatchRunning: false,
28
+ calculatedObjectsWatchRunning: false,
26
29
  });
27
30
  const calculatedObjectsEffectScopes = {};
28
31
 
@@ -56,6 +59,7 @@ export function useListCalculated({
56
59
  },
57
60
  });
58
61
  }
62
+ state.parentStateObjectsWatchRunning = false;
59
63
  }
60
64
 
61
65
  function calculatedObjectsWatch() {
@@ -98,9 +102,12 @@ export function useListCalculated({
98
102
  }
99
103
  calculatedObjectsEffectScopes[objectKey] = calculatedObjectsEffectScope;
100
104
  }
105
+ state.calculatedObjectsWatchRunning = false;
101
106
  parentStateObjectsWatch();
102
107
  }
103
108
 
109
+ let watchesRunning = null;
110
+
104
111
  const es = effectScope();
105
112
 
106
113
  es.run(() => {
@@ -126,6 +133,16 @@ export function useListCalculated({
126
133
  { immediate: true }
127
134
  );
128
135
 
136
+ watchesRunning = useWatchesRunning({
137
+ triggerRefs: [computed(() => (!isEmpty(state.calculatedObjectsRules) ? parentState.loading : false))],
138
+ watchSentinelRefs: [
139
+ toRef(state, "parentStateObjectsWatchRunning"),
140
+ toRef(state, "calculatedObjectsWatchRunning"),
141
+ ],
142
+ });
143
+
144
+ state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.running));
145
+
129
146
  onScopeDispose(() => {
130
147
  for (const objectKey of Object.keys(calculatedObjectsEffectScopes)) {
131
148
  calculatedObjectsEffectScopes[objectKey].stop();
@@ -135,6 +152,8 @@ export function useListCalculated({
135
152
 
136
153
  return {
137
154
  state,
155
+ parentState,
156
+ watchesRunning,
138
157
  effectScope: es,
139
158
  };
140
159
  }
@@ -1,6 +1,7 @@
1
1
  import { get, isArray, isEmpty, isUndefined } from "lodash";
2
2
  import { computed, effectScope, onScopeDispose, reactive, toRef, unref, watch } from "vue";
3
- import { keyDiff } from "../utils/keyDiff";
3
+ import { keyDiff, loadingCombine } from "../utils";
4
+ import { useWatchesRunning } from "./watchesRunning";
4
5
 
5
6
  export function useListRelateds(instances, args) {
6
7
  for (const [key, value] of Object.entries(args)) {
@@ -20,6 +21,8 @@ export function useListRelated({
20
21
  relatedObjectsRules: relatedObjectsRules,
21
22
  relatedObjectsObjects: {},
22
23
  objects: {},
24
+ parentStateObjectsWatchRunning: false,
25
+ relatedObjectsWatchRunning: false,
23
26
  });
24
27
  const relatedObjectsEffectScopes = {};
25
28
 
@@ -128,6 +131,8 @@ export function useListRelated({
128
131
  parentStateObjectsWatch();
129
132
  }
130
133
 
134
+ let watchesRunning = null;
135
+
131
136
  const es = effectScope();
132
137
 
133
138
  es.run(() => {
@@ -150,6 +155,16 @@ export function useListRelated({
150
155
  { immediate: true }
151
156
  );
152
157
 
158
+ watchesRunning = useWatchesRunning({
159
+ triggerRefs: [computed(() => (!isEmpty(state.relatedObjectsRules) ? parentState.loading : false))],
160
+ watchSentinelRefs: [
161
+ toRef(state, "parentStateObjectsWatchRunning"),
162
+ toRef(state, "relatedObjectsWatchRunning"),
163
+ ],
164
+ });
165
+
166
+ state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.running));
167
+
153
168
  onScopeDispose(() => {
154
169
  for (const objectKey of Object.keys(relatedObjectsEffectScopes)) {
155
170
  relatedObjectsEffectScopes[objectKey].stop();
@@ -159,6 +174,7 @@ export function useListRelated({
159
174
  return {
160
175
  state,
161
176
  parentState,
177
+ watchesRunning,
162
178
  effectScope: es,
163
179
  };
164
180
  }
@@ -1,7 +1,7 @@
1
1
  import inspect from "browser-util-inspect";
2
2
  import { cloneDeep, isEmpty, isObject } from "lodash";
3
3
  import { computed, effectScope, reactive, toRef } from "vue";
4
- import { useCancellableIntent } from "../utils/cancellableIntent";
4
+ import { useCancellableIntent } from "./cancellableIntent";
5
5
  import { loadingCombine } from "../utils/loadingCombine";
6
6
  import { useListInstance } from "./listInstance";
7
7
 
package/use/object.js CHANGED
@@ -82,6 +82,7 @@ export const useObject = ({ props }) => {
82
82
  error: null,
83
83
  errored: null,
84
84
  object: null,
85
+ running: null,
85
86
  });
86
87
  exposedState = new Proxy(proxyBase, {
87
88
  // get values from the current state
@@ -1,5 +1,7 @@
1
+ import { isEmpty } from "lodash";
1
2
  import { computed, effectScope, onScopeDispose, reactive, toRef, watch } from "vue";
2
- import { keyDiff } from "../utils";
3
+ import { keyDiff, loadingCombine } from "../utils";
4
+ import { useWatchesRunning } from "./watchesRunning";
3
5
 
4
6
  export function useObjectCalculateds(instances, args) {
5
7
  for (const [key, value] of Object.entries(args)) {
@@ -20,6 +22,8 @@ export function useObjectCalculated({
20
22
  calculatedObjectRules,
21
23
  calculatedObjectObjects: {},
22
24
  object: {},
25
+ parentStateObjectWatchRunning: false,
26
+ calculatedObjectWatchRunning: false,
23
27
  });
24
28
  const calculatedObjectEffectScopes = {};
25
29
  const calculatedObjectOriginalFunctions = {};
@@ -27,6 +31,8 @@ export function useObjectCalculated({
27
31
  // don't change calculatedObjectPropertyName on us or it will break
28
32
  const copn = calculatedObjectPropertyName + "";
29
33
 
34
+ let watchesRunning = null;
35
+
30
36
  const es = effectScope();
31
37
 
32
38
  es.run(() => {
@@ -66,48 +72,52 @@ export function useObjectCalculated({
66
72
  state.errored = toRef(parentState, "errored");
67
73
  state.deleted = toRef(parentState, "deleted");
68
74
 
69
- watch(
70
- [() => state.calculatedObjectRules && Object.keys(state.calculatedObjectRules)],
71
- () => {
72
- let addedKeys = [],
73
- removedKeys = [],
74
- sameKeys = [];
75
- if (!state.calculatedObjectRules) {
76
- removedKeys = Object.keys(calculatedObjectOriginalFunctions);
77
- } else {
78
- ({ addedKeys, removedKeys, sameKeys } = keyDiff(
79
- Object.keys(state.calculatedObjectRules),
80
- Object.keys(calculatedObjectOriginalFunctions)
81
- ));
82
- }
83
- for (const sameKey of sameKeys) {
84
- if (calculatedObjectOriginalFunctions[sameKey] !== state.calculatedObjectRules[sameKey]) {
85
- removedKeys.push(sameKey);
86
- addedKeys.push(sameKey);
87
- }
88
- }
89
- for (const removedKey of removedKeys) {
90
- delete calculatedObjectOriginalFunctions[removedKey];
91
- delete state.calculatedObjectObjects[removedKey];
92
- if (calculatedObjectEffectScopes[removedKey]) {
93
- calculatedObjectEffectScopes[removedKey].stop();
94
- delete calculatedObjectEffectScopes[removedKey];
95
- }
75
+ watch([() => state.calculatedObjectRules && Object.keys(state.calculatedObjectRules)], () => {
76
+ let addedKeys = [],
77
+ removedKeys = [],
78
+ sameKeys = [];
79
+ if (!state.calculatedObjectRules) {
80
+ removedKeys = Object.keys(calculatedObjectOriginalFunctions);
81
+ } else {
82
+ ({ addedKeys, removedKeys, sameKeys } = keyDiff(
83
+ Object.keys(state.calculatedObjectRules),
84
+ Object.keys(calculatedObjectOriginalFunctions)
85
+ ));
86
+ }
87
+ for (const sameKey of sameKeys) {
88
+ if (calculatedObjectOriginalFunctions[sameKey] !== state.calculatedObjectRules[sameKey]) {
89
+ removedKeys.push(sameKey);
90
+ addedKeys.push(sameKey);
96
91
  }
97
- for (const addedKey of addedKeys) {
98
- calculatedObjectOriginalFunctions[addedKey] = state.calculatedObjectRules[addedKey];
99
- calculatedObjectEffectScopes[addedKey] = effectScope();
100
- calculatedObjectEffectScopes[addedKey].run(() => {
101
- state.calculatedObjectObjects[addedKey] = computed(() =>
102
- calculatedObjectOriginalFunctions[addedKey](state.object)
103
- );
104
- });
92
+ }
93
+ for (const removedKey of removedKeys) {
94
+ delete calculatedObjectOriginalFunctions[removedKey];
95
+ delete state.calculatedObjectObjects[removedKey];
96
+ if (calculatedObjectEffectScopes[removedKey]) {
97
+ calculatedObjectEffectScopes[removedKey].stop();
98
+ delete calculatedObjectEffectScopes[removedKey];
105
99
  }
106
- },
107
- {
108
- immediate: true,
109
100
  }
110
- );
101
+ for (const addedKey of addedKeys) {
102
+ calculatedObjectOriginalFunctions[addedKey] = state.calculatedObjectRules[addedKey];
103
+ calculatedObjectEffectScopes[addedKey] = effectScope();
104
+ calculatedObjectEffectScopes[addedKey].run(() => {
105
+ state.calculatedObjectObjects[addedKey] = computed(() =>
106
+ calculatedObjectOriginalFunctions[addedKey](state.object)
107
+ );
108
+ });
109
+ }
110
+ });
111
+
112
+ watchesRunning = useWatchesRunning({
113
+ triggerRefs: [computed(() => (!isEmpty(state.calculatedObjectRules) ? parentState.loading : false))],
114
+ watchSentinelRefs: [
115
+ toRef(state, "parentStateObjectWatchRunning"),
116
+ toRef(state, "calculatedObjectWatchRunning"),
117
+ ],
118
+ });
119
+
120
+ state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.running));
111
121
 
112
122
  onScopeDispose(() => {
113
123
  for (const key in calculatedObjectEffectScopes) {
@@ -121,6 +131,7 @@ export function useObjectCalculated({
121
131
  return {
122
132
  state,
123
133
  parentState,
134
+ watchesRunning,
124
135
  effectScope: es,
125
136
  };
126
137
  }
@@ -1,6 +1,7 @@
1
- import { get, isArray, isUndefined } from "lodash";
1
+ import { get, isArray, isEmpty, isUndefined } from "lodash";
2
2
  import { computed, effectScope, onScopeDispose, reactive, toRef, unref, watch } from "vue";
3
- import { keyDiff } from "../utils";
3
+ import { keyDiff, loadingCombine } from "../utils";
4
+ import { useWatchesRunning } from "./watchesRunning";
4
5
 
5
6
  export function useObjectRelateds(instances, args) {
6
7
  for (const [key, value] of Object.entries(args)) {
@@ -21,12 +22,16 @@ export function useObjectRelated({
21
22
  relatedObjectRules,
22
23
  relatedObjectObjects: {},
23
24
  object: {},
25
+ parentStateObjectWatchRunning: false,
26
+ relatedObjectWatchRunning: false,
24
27
  });
25
28
  const relatedObjectEffectScopes = {};
26
29
 
27
30
  // don't change relatedObjectPropertyName on us or it will break
28
31
  const ropn = relatedObjectPropertyName + "";
29
32
 
33
+ let watchesRunning = null;
34
+
30
35
  const es = effectScope();
31
36
 
32
37
  es.run(() => {
@@ -66,53 +71,57 @@ export function useObjectRelated({
66
71
  state.errored = toRef(parentState, "errored");
67
72
  state.deleted = toRef(parentState, "deleted");
68
73
 
69
- watch(
70
- [() => state.relatedObjectRules && Object.keys(state.relatedObjectRules)],
71
- () => {
72
- let addedRuleKeys = [],
73
- removedRuleKeys = [];
74
- if (!state.relatedObjectRules) {
75
- removedRuleKeys = Object.keys(state.relatedObjectObjects);
76
- } else {
77
- ({ addedKeys: addedRuleKeys, removedKeys: removedRuleKeys } = keyDiff(
78
- Object.keys(state.relatedObjectRules),
79
- Object.keys(state.relatedObjectObjects)
80
- ));
81
- }
74
+ watch([() => state.relatedObjectRules && Object.keys(state.relatedObjectRules)], () => {
75
+ let addedRuleKeys = [],
76
+ removedRuleKeys = [];
77
+ if (!state.relatedObjectRules) {
78
+ removedRuleKeys = Object.keys(state.relatedObjectObjects);
79
+ } else {
80
+ ({ addedKeys: addedRuleKeys, removedKeys: removedRuleKeys } = keyDiff(
81
+ Object.keys(state.relatedObjectRules),
82
+ Object.keys(state.relatedObjectObjects)
83
+ ));
84
+ }
82
85
 
83
- for (const removedRuleKey of removedRuleKeys) {
84
- delete state.relatedObjectObjects[removedRuleKey];
85
- if (relatedObjectEffectScopes[removedRuleKey]) {
86
- relatedObjectEffectScopes[removedRuleKey].stop();
87
- delete relatedObjectEffectScopes[removedRuleKey];
88
- }
86
+ for (const removedRuleKey of removedRuleKeys) {
87
+ delete state.relatedObjectObjects[removedRuleKey];
88
+ if (relatedObjectEffectScopes[removedRuleKey]) {
89
+ relatedObjectEffectScopes[removedRuleKey].stop();
90
+ delete relatedObjectEffectScopes[removedRuleKey];
89
91
  }
90
- for (const addedRuleKey of addedRuleKeys) {
91
- relatedObjectEffectScopes[addedRuleKey] = effectScope();
92
- relatedObjectEffectScopes[addedRuleKey].run(() => {
93
- state.relatedObjectObjects[addedRuleKey] = computed(() => {
94
- // deal with computed objects being passed.
95
- const ruleObjects = unref(state.relatedObjectRules?.[addedRuleKey]?.objects);
96
- const rulePkKey = state.relatedObjectRules?.[addedRuleKey]?.pkKey || addedRuleKey;
97
- if (!ruleObjects || !rulePkKey) {
98
- return undefined;
99
- }
100
- const value = get(parentState.object, rulePkKey);
101
- if (isUndefined(value)) {
102
- return undefined;
103
- }
104
- if (isArray(value)) {
105
- return value.map((e) => ruleObjects[e]);
106
- }
107
- return ruleObjects[value];
108
- });
92
+ }
93
+ for (const addedRuleKey of addedRuleKeys) {
94
+ relatedObjectEffectScopes[addedRuleKey] = effectScope();
95
+ relatedObjectEffectScopes[addedRuleKey].run(() => {
96
+ state.relatedObjectObjects[addedRuleKey] = computed(() => {
97
+ // deal with computed objects being passed.
98
+ const ruleObjects = unref(state.relatedObjectRules?.[addedRuleKey]?.objects);
99
+ const rulePkKey = state.relatedObjectRules?.[addedRuleKey]?.pkKey || addedRuleKey;
100
+ if (!ruleObjects || !rulePkKey) {
101
+ return undefined;
102
+ }
103
+ const value = get(parentState.object, rulePkKey);
104
+ if (isUndefined(value)) {
105
+ return undefined;
106
+ }
107
+ if (isArray(value)) {
108
+ return value.map((e) => ruleObjects[e]);
109
+ }
110
+ return ruleObjects[value];
109
111
  });
110
- }
111
- },
112
- {
113
- immediate: true,
112
+ });
114
113
  }
115
- );
114
+ });
115
+
116
+ watchesRunning = useWatchesRunning({
117
+ triggerRefs: [computed(() => (!isEmpty(state.relatedObjectRules) ? parentState.loading : false))],
118
+ watchSentinelRefs: [
119
+ toRef(state, "parentStateObjectWatchRunning"),
120
+ toRef(state, "relatedObjectWatchRunning"),
121
+ ],
122
+ });
123
+
124
+ state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.running));
116
125
 
117
126
  onScopeDispose(() => {
118
127
  for (const key in relatedObjectEffectScopes) {
@@ -120,9 +129,11 @@ export function useObjectRelated({
120
129
  }
121
130
  });
122
131
  });
132
+
123
133
  return {
124
134
  state,
125
135
  parentState,
136
+ watchesRunning,
126
137
  effectScope: es,
127
138
  };
128
139
  }
@@ -1,7 +1,6 @@
1
1
  import { computed, effectScope, reactive, toRef } from "vue";
2
- import { assignReactiveObject } from "../utils/assignReactiveObject";
3
- import { useCancellableIntent } from "../utils/cancellableIntent";
4
- import { loadingCombine } from "../utils/loadingCombine";
2
+ import { assignReactiveObject, loadingCombine } from "../utils";
3
+ import { useCancellableIntent } from "./cancellableIntent";
5
4
  import { useObjectInstance } from "./objectInstance";
6
5
 
7
6
  export class ObjectSubscriptionError extends Error {
@@ -0,0 +1,31 @@
1
+ import { computed, effectScope, reactive, unref, watch } from "vue";
2
+ import { loadingCombine } from "../utils";
3
+
4
+ export function useWatchesRunning({ triggerRefs, watchSentinelRefs }) {
5
+ const state = reactive({});
6
+
7
+ const es = effectScope();
8
+
9
+ es.run(() => {
10
+ watch(
11
+ triggerRefs,
12
+ (values) => {
13
+ if (values.every((value) => unref(value))) {
14
+ watchSentinelRefs.forEach((ref) => {
15
+ ref.value = true;
16
+ });
17
+ }
18
+ },
19
+ {
20
+ immediate: true,
21
+ deep: true,
22
+ }
23
+ );
24
+ state.running = computed(() => loadingCombine(watchSentinelRefs.map((ref) => ref.value)));
25
+ });
26
+
27
+ return {
28
+ state,
29
+ effectScope: es,
30
+ };
31
+ }
@@ -2,7 +2,6 @@ import inspect from "browser-util-inspect";
2
2
  import { isArray, isObject } from "lodash";
3
3
  import { isReactive, isRef, toRef, unref } from "vue";
4
4
  import { keyDiff } from "./keyDiff.js";
5
- import { union } from "./set.js";
6
5
 
7
6
  export class AssignReactiveObjectError extends Error {
8
7
  constructor(message) {
@@ -17,7 +16,7 @@ function isArrayOrObject(key, value) {
17
16
  }
18
17
  }
19
18
 
20
- export function addOrUpdateReactiveObject(target, source, exclude = [], addedKeys = null, sameKeys = null) {
19
+ function validateTargetAndSource(target, source) {
21
20
  isArrayOrObject("target", target);
22
21
  isArrayOrObject("source", source);
23
22
  if (isRef(target)) {
@@ -30,12 +29,13 @@ export function addOrUpdateReactiveObject(target, source, exclude = [], addedKey
30
29
  isArrayOrObject("unrefedSource", unrefedSource);
31
30
  source = unrefedSource;
32
31
  }
33
- if (!addedKeys && !sameKeys) {
34
- ({ addedKeys, sameKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
35
- }
32
+ return { target, source };
33
+ }
34
+
35
+ function reactiveReplaceKeys(target, source, keys, exclude) {
36
36
  const targetIsReactive = isReactive(target);
37
37
  const sourceIsReactive = isReactive(source);
38
- for (const key of union(addedKeys, sameKeys)) {
38
+ for (const key of keys) {
39
39
  if (!exclude.includes(key)) {
40
40
  if (targetIsReactive && sourceIsReactive) {
41
41
  target[key] = toRef(source, key);
@@ -46,24 +46,50 @@ export function addOrUpdateReactiveObject(target, source, exclude = [], addedKey
46
46
  }
47
47
  }
48
48
 
49
- export function assignReactiveObject(target, source, exclude = []) {
50
- if (target === source) {
51
- return;
49
+ export function addReactiveObject(target, source, exclude = [], addedKeys = null) {
50
+ if (!addedKeys) {
51
+ if (target === source) {
52
+ return;
53
+ }
54
+ ({ target, source } = validateTargetAndSource(target, source));
55
+ ({ addedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
52
56
  }
53
- isArrayOrObject("target", target);
54
- isArrayOrObject("source", source);
55
- if (isRef(target)) {
56
- const unrefedTarget = unref(target);
57
- isArrayOrObject("unrefedTarget", unrefedTarget);
58
- target = unrefedTarget;
57
+ reactiveReplaceKeys(target, source, addedKeys, exclude);
58
+ }
59
+
60
+ export function updateReactiveObject(target, source, exclude = [], sameKeys = null) {
61
+ if (!sameKeys) {
62
+ if (target === source) {
63
+ return;
64
+ }
65
+ ({ target, source } = validateTargetAndSource(target, source));
66
+ ({ sameKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
59
67
  }
60
- if (isRef(source)) {
61
- const unrefedSource = unref(source);
62
- isArrayOrObject("unrefedSource", unrefedSource);
63
- source = unrefedSource;
68
+ reactiveReplaceKeys(target, source, sameKeys, exclude);
69
+ }
70
+
71
+ export function addOrUpdateReactiveObject(target, source, exclude = [], addedKeys = null, sameKeys = null) {
72
+ if (!addedKeys && !sameKeys) {
73
+ if (target === source) {
74
+ return;
75
+ }
76
+ ({ target, source } = validateTargetAndSource(target, source));
77
+ ({ addedKeys, sameKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
78
+ }
79
+ addReactiveObject(target, source, exclude, addedKeys);
80
+ updateReactiveObject(target, source, exclude, sameKeys);
81
+ }
82
+
83
+ // there isn't much reactive about this I guess...
84
+ export function trimReactiveObject(target, source, exclude = [], removedKeys = null) {
85
+ if (!removedKeys) {
86
+ if (target === source) {
87
+ return;
88
+ }
89
+ ({ target, source } = validateTargetAndSource(target, source));
90
+ ({ removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
64
91
  }
65
92
  const targetIsArray = isArray(target);
66
- const { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
67
93
  if (targetIsArray) {
68
94
  // Remove indices in reverse (descending) order to keep them stable
69
95
  for (const removedKey of [...removedKeys].map((key) => parseInt(key, 10)).sort((a, b) => b - a)) {
@@ -78,5 +104,54 @@ export function assignReactiveObject(target, source, exclude = []) {
78
104
  }
79
105
  }
80
106
  }
107
+ }
108
+
109
+ export function assignReactiveObject(target, source, exclude = []) {
110
+ if (target === source) {
111
+ return;
112
+ }
113
+ ({ target, source } = validateTargetAndSource(target, source));
114
+ const { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
115
+ trimReactiveObject(target, removedKeys, exclude);
81
116
  addOrUpdateReactiveObject(target, source, exclude, addedKeys, sameKeys);
82
117
  }
118
+
119
+ function assignReactiveObjectRecursive(target, source, exclude = [], path = "") {
120
+ let addedKeys, sameKeys, removedKeys;
121
+ try {
122
+ ({ addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
123
+ } catch (error) {
124
+ debugger;
125
+ }
126
+ trimReactiveObject(target, removedKeys, exclude);
127
+ addReactiveObject(target, source, exclude, addedKeys);
128
+ const keysForRecurse = [];
129
+ const keysForReplace = [];
130
+ for (const key of sameKeys) {
131
+ if (!exclude.includes(key)) {
132
+ if (isObject(source[key]) && isObject(target[key])) {
133
+ keysForRecurse.push(key);
134
+ } else if (target[key] !== source[key]) {
135
+ keysForReplace.push(key);
136
+ }
137
+ }
138
+ }
139
+ reactiveReplaceKeys(target, source, keysForReplace, exclude);
140
+ for (const key of keysForRecurse) {
141
+ // scope exclude for this next level, remove keys that don't start with the current path, trim keys that do to remove the current path
142
+ const nextLevelExclude = exclude
143
+ .filter((excludeKey) => !excludeKey.startsWith(path))
144
+ .map((excludeKey) => excludeKey.replace(path, ""));
145
+ const nextPath = isArray(source[key]) ? `${path}[${key}]` : `${path}.${key}`;
146
+ assignReactiveObjectRecursive(target[key], source[key], nextLevelExclude, nextPath);
147
+ }
148
+ }
149
+
150
+ export function assignReactiveObjectDeep(target, source, exclude = []) {
151
+ // exclude keys will need to be lodash get strings
152
+ if (target === source) {
153
+ return;
154
+ }
155
+ ({ target, source } = validateTargetAndSource(target, source));
156
+ assignReactiveObjectRecursive(target, source, exclude);
157
+ }
package/utils/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from "./assignReactiveObject";
2
- export * from "./cancellableIntent";
3
2
  export * from "./flattenPaths";
4
3
  export * from "./getFakeId";
5
4
  export * from "./keyDiff";
File without changes