@arrai-innovations/reactive-helpers 3.1.0 → 3.2.1

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.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -72,48 +72,42 @@ export function useObjectCalculated({
72
72
  state.errored = toRef(parentState, "errored");
73
73
  state.deleted = toRef(parentState, "deleted");
74
74
 
75
- watch(
76
- [() => state.calculatedObjectRules && Object.keys(state.calculatedObjectRules)],
77
- () => {
78
- let addedKeys = [],
79
- removedKeys = [],
80
- sameKeys = [];
81
- if (!state.calculatedObjectRules) {
82
- removedKeys = Object.keys(calculatedObjectOriginalFunctions);
83
- } else {
84
- ({ addedKeys, removedKeys, sameKeys } = keyDiff(
85
- Object.keys(state.calculatedObjectRules),
86
- Object.keys(calculatedObjectOriginalFunctions)
87
- ));
88
- }
89
- for (const sameKey of sameKeys) {
90
- if (calculatedObjectOriginalFunctions[sameKey] !== state.calculatedObjectRules[sameKey]) {
91
- removedKeys.push(sameKey);
92
- addedKeys.push(sameKey);
93
- }
94
- }
95
- for (const removedKey of removedKeys) {
96
- delete calculatedObjectOriginalFunctions[removedKey];
97
- delete state.calculatedObjectObjects[removedKey];
98
- if (calculatedObjectEffectScopes[removedKey]) {
99
- calculatedObjectEffectScopes[removedKey].stop();
100
- delete calculatedObjectEffectScopes[removedKey];
101
- }
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);
102
91
  }
103
- for (const addedKey of addedKeys) {
104
- calculatedObjectOriginalFunctions[addedKey] = state.calculatedObjectRules[addedKey];
105
- calculatedObjectEffectScopes[addedKey] = effectScope();
106
- calculatedObjectEffectScopes[addedKey].run(() => {
107
- state.calculatedObjectObjects[addedKey] = computed(() =>
108
- calculatedObjectOriginalFunctions[addedKey](state.object)
109
- );
110
- });
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];
111
99
  }
112
- },
113
- {
114
- immediate: true,
115
100
  }
116
- );
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
+ });
117
111
 
118
112
  watchesRunning = useWatchesRunning({
119
113
  triggerRefs: [computed(() => (!isEmpty(state.calculatedObjectRules) ? parentState.loading : false))],
@@ -71,53 +71,47 @@ export function useObjectRelated({
71
71
  state.errored = toRef(parentState, "errored");
72
72
  state.deleted = toRef(parentState, "deleted");
73
73
 
74
- watch(
75
- [() => state.relatedObjectRules && Object.keys(state.relatedObjectRules)],
76
- () => {
77
- let addedRuleKeys = [],
78
- removedRuleKeys = [];
79
- if (!state.relatedObjectRules) {
80
- removedRuleKeys = Object.keys(state.relatedObjectObjects);
81
- } else {
82
- ({ addedKeys: addedRuleKeys, removedKeys: removedRuleKeys } = keyDiff(
83
- Object.keys(state.relatedObjectRules),
84
- Object.keys(state.relatedObjectObjects)
85
- ));
86
- }
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
+ }
87
85
 
88
- for (const removedRuleKey of removedRuleKeys) {
89
- delete state.relatedObjectObjects[removedRuleKey];
90
- if (relatedObjectEffectScopes[removedRuleKey]) {
91
- relatedObjectEffectScopes[removedRuleKey].stop();
92
- delete relatedObjectEffectScopes[removedRuleKey];
93
- }
86
+ for (const removedRuleKey of removedRuleKeys) {
87
+ delete state.relatedObjectObjects[removedRuleKey];
88
+ if (relatedObjectEffectScopes[removedRuleKey]) {
89
+ relatedObjectEffectScopes[removedRuleKey].stop();
90
+ delete relatedObjectEffectScopes[removedRuleKey];
94
91
  }
95
- for (const addedRuleKey of addedRuleKeys) {
96
- relatedObjectEffectScopes[addedRuleKey] = effectScope();
97
- relatedObjectEffectScopes[addedRuleKey].run(() => {
98
- state.relatedObjectObjects[addedRuleKey] = computed(() => {
99
- // deal with computed objects being passed.
100
- const ruleObjects = unref(state.relatedObjectRules?.[addedRuleKey]?.objects);
101
- const rulePkKey = state.relatedObjectRules?.[addedRuleKey]?.pkKey || addedRuleKey;
102
- if (!ruleObjects || !rulePkKey) {
103
- return undefined;
104
- }
105
- const value = get(parentState.object, rulePkKey);
106
- if (isUndefined(value)) {
107
- return undefined;
108
- }
109
- if (isArray(value)) {
110
- return value.map((e) => ruleObjects[e]);
111
- }
112
- return ruleObjects[value];
113
- });
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];
114
111
  });
115
- }
116
- },
117
- {
118
- immediate: true,
112
+ });
119
113
  }
120
- );
114
+ });
121
115
 
122
116
  watchesRunning = useWatchesRunning({
123
117
  triggerRefs: [computed(() => (!isEmpty(state.relatedObjectRules) ? parentState.loading : false))],
@@ -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
+ }