@arrai-innovations/reactive-helpers 11.4.2 → 13.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.
- package/.husky/pre-commit +0 -1
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.prettierignore +1 -0
- package/README.md +11 -10
- package/config/listCrud.js +32 -1
- package/config/objectCrud.js +47 -1
- package/docs/README.md +43 -0
- package/docs/config/listCrud.md +97 -0
- package/docs/config/objectCrud.md +123 -0
- package/docs/use/cancellableIntent.md +163 -0
- package/docs/use/combineClasses.md +52 -0
- package/docs/use/list.md +285 -0
- package/docs/use/listCalculated.md +773 -0
- package/docs/use/listFilter.md +877 -0
- package/docs/use/listInstance.md +483 -0
- package/docs/use/listKeys.md +91 -0
- package/docs/use/listRelated.md +685 -0
- package/docs/use/listSearch.md +889 -0
- package/docs/use/listSort.md +1144 -0
- package/docs/use/listSubscription.md +379 -0
- package/docs/use/loadingError.md +21 -0
- package/docs/use/object.md +437 -0
- package/docs/use/objectCalculated.md +606 -0
- package/docs/use/objectInstance.md +486 -0
- package/docs/use/objectRelated.md +588 -0
- package/docs/use/objectSubscription.md +459 -0
- package/docs/use/paginatedListInstance.md +147 -0
- package/docs/use/search.md +311 -0
- package/docs/use/watchesRunning.md +80 -0
- package/docs/utils/assignReactiveObject.md +351 -0
- package/docs/utils/classes.md +100 -0
- package/docs/utils/compact.md +57 -0
- package/docs/utils/deleteKey.md +53 -0
- package/docs/utils/flattenPaths.md +45 -0
- package/docs/utils/getFakeId.md +34 -0
- package/docs/utils/keyDiff.md +101 -0
- package/docs/utils/loadingCombine.md +28 -0
- package/docs/utils/proxyRunning.md +33 -0
- package/docs/utils/relatedCalculatedHelpers.md +75 -0
- package/docs/utils/set.md +139 -0
- package/docs/utils/transformWalk.md +33 -0
- package/docs/utils/watches.md +441 -0
- package/eslint.config.js +125 -0
- package/index.js +34 -3
- package/lint-staged.config.js +5 -1
- package/makeTypeDoc.sh +25 -0
- package/package.json +27 -19
- package/tests/unit/config/listCrud.spec.js +5 -0
- package/tests/unit/config/objectCrud.spec.js +5 -0
- package/tests/unit/crudPromise.js +22 -3
- package/tests/unit/mockOnUnmounted.js +1 -1
- package/tests/unit/use/cancellableIntent.spec.js +2 -0
- package/tests/unit/use/listCalculated.spec.js +4 -3
- package/tests/unit/use/listFilter.spec.js +11 -7
- package/tests/unit/use/listInstance.spec.js +32 -14
- package/tests/unit/use/listRelated.spec.js +3 -2
- package/tests/unit/use/listSearch.spec.js +9 -7
- package/tests/unit/use/listSort.spec.js +29 -22
- package/tests/unit/use/listSubscription.spec.js +11 -5
- package/tests/unit/use/objectInstance.spec.js +15 -2
- package/tests/unit/use/objectSubscription.spec.js +31 -16
- package/tests/unit/use/search.spec.js +2 -2
- package/tests/unit/utils/assignReactiveObject.spec.js +21 -13
- package/tests/unit/utils/classes.spec.js +7 -6
- package/tests/unit/utils/watches.spec.js +4 -4
- package/tsconfig.json +19 -0
- package/typedoc-local-plugins/customize-output.js +13 -0
- package/typedoc.json +12 -0
- package/use/cancellableIntent.js +73 -2
- package/use/combineClasses.js +41 -31
- package/use/list.js +139 -5
- package/use/listCalculated.js +175 -10
- package/use/listFilter.js +175 -21
- package/use/listInstance.js +215 -94
- package/use/listRelated.js +260 -72
- package/use/listSearch.js +178 -57
- package/use/listSort.js +188 -21
- package/use/listSubscription.js +211 -63
- package/use/loadingError.js +43 -0
- package/use/object.js +187 -23
- package/use/objectCalculated.js +168 -16
- package/use/objectInstance.js +183 -102
- package/use/objectRelated.js +276 -84
- package/use/objectSubscription.js +169 -17
- package/use/paginatedListInstance.js +30 -1
- package/use/search.js +39 -23
- package/use/watchesRunning.js +41 -6
- package/utils/assignReactiveObject.js +139 -88
- package/utils/classes.js +57 -48
- package/utils/compact.js +28 -2
- package/utils/deleteKey.js +14 -1
- package/utils/flattenPaths.js +19 -9
- package/utils/getFakeId.js +11 -1
- package/utils/keyDiff.js +26 -35
- package/utils/loadingCombine.js +7 -4
- package/utils/proxyRunning.js +16 -8
- package/utils/relatedCalculatedHelpers.js +17 -0
- package/utils/set.js +66 -0
- package/utils/transformWalk.js +7 -6
- package/utils/watches.js +205 -71
- package/.eslintignore +0 -2
- package/.eslintrc.cjs +0 -25
- package/.jsdoc2md.json +0 -4
- package/config/index.js +0 -2
- package/docs.md +0 -1002
- package/jsdoc-to-markdown.sh +0 -16
- package/tests/unit/.eslintrc.cjs +0 -11
- package/tests/unit/config/index.spec.js +0 -18
- package/tests/unit/use/index.spec.js +0 -18
- package/tests/unit/utils/index.spec.js +0 -18
- package/use/index.js +0 -19
- package/utils/debugMessage.js +0 -209
- package/utils/debugWatch.js +0 -29
- package/utils/index.js +0 -16
- package/utils/lifecycleDebug.js +0 -126
|
@@ -1,7 +1,36 @@
|
|
|
1
1
|
import { useListInstance } from "./listInstance.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @module use/paginatedListInstance.js
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} PagedListListanceOptions
|
|
10
|
+
* @property {boolean} [keepOldPages=false] - Whether to keep old pages.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} PagedListInstanceState
|
|
15
|
+
* @property {number} totalRecords - The total records.
|
|
16
|
+
* @property {number} totalPages - The total pages.
|
|
17
|
+
* @property {number} perPage - The per page.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {object} PagedListInstance
|
|
22
|
+
* @property {import('./listInstance.js').ListInstanceState & PagedListInstanceState} state - The state.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @param {PagedListListanceOptions & import('./listInstance.js').ListInstanceOptions} options - The options.
|
|
28
|
+
* @returns {PagedListInstance} - The paged list instance.
|
|
29
|
+
*/
|
|
3
30
|
export function usePagedListInstance({ keepOldPages = false, ...useListInstanceArgs }) {
|
|
4
|
-
const listInstance =
|
|
31
|
+
const listInstance = /** @type {PagedListInstance & import('./listInstance.js').ListInstance} */ (
|
|
32
|
+
/** @type {unknown} */ (useListInstance(useListInstanceArgs))
|
|
33
|
+
);
|
|
5
34
|
|
|
6
35
|
listInstance.state.totalRecords = 0;
|
|
7
36
|
listInstance.state.totalPages = 0;
|
package/use/search.js
CHANGED
|
@@ -15,33 +15,46 @@ const unionReduce = (accumulator, currentValue) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* FlexSearch.Document search options
|
|
18
|
+
* FlexSearch.Document search options.
|
|
19
|
+
*
|
|
19
20
|
* @typedef {object} SearchOptions
|
|
20
|
-
* @property {number} limit -
|
|
21
|
+
* @property {number} limit - Limit of results.
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
|
-
// eslint-disable-next-line jsdoc/require-property
|
|
24
24
|
/**
|
|
25
|
-
* FlexSearch.
|
|
25
|
+
* Configuration options for creating a document in FlexSearch.
|
|
26
|
+
*
|
|
26
27
|
* @typedef {object} DocumentOptions
|
|
28
|
+
* @property {string} id - The document field to use as an identifier. Default is "id".
|
|
29
|
+
* @property {boolean|string} tag - The document field to use as a tag. Default is false, can be set to a string.
|
|
30
|
+
* @property {string | string[] | object[]} index - Fields to index. Can be a single string, an array of strings, or an array of objects specifying custom index options.
|
|
31
|
+
* @property {boolean|string|string[]} store - Specifies if and what document fields to store. Can be false, a string, or an array of strings. Default is false.
|
|
32
|
+
* @property {string} [tokenizer] - Specifies the tokenizer to use.
|
|
33
|
+
* @property {number} [minLength] - Minimum length of a token to be indexed.
|
|
27
34
|
*/
|
|
28
35
|
|
|
29
36
|
/**
|
|
30
|
-
* @typedef {object}
|
|
31
|
-
* @property {string} search -
|
|
32
|
-
* @property {object} results -
|
|
33
|
-
* @property {boolean} searched -
|
|
34
|
-
* @property {boolean} searching -
|
|
37
|
+
* @typedef {object} SearchRawState
|
|
38
|
+
* @property {string} search - The search string.
|
|
39
|
+
* @property {object} results - The results, where the keys are the ids of the objects that match, and the values are true.
|
|
40
|
+
* @property {boolean} searched - Whether the search has been performed.
|
|
41
|
+
* @property {boolean} searching - Whether the search is currently running.
|
|
42
|
+
* @property {DocumentOptions} customDocumentOptions - FlexSearch.Document options.
|
|
43
|
+
* @property {SearchOptions} customSearchOptions - Search options.
|
|
44
|
+
* @property {number} called - The number of times the search has been called.
|
|
45
|
+
* @property {number} pending - The number of times the search has been called, but has not yet returned.
|
|
46
|
+
* @property {boolean} running - Whether the search is currently running or has pending calls.
|
|
35
47
|
*/
|
|
36
48
|
|
|
37
49
|
/**
|
|
38
50
|
* @typedef {object} SearchInstance
|
|
39
|
-
* @property {
|
|
40
|
-
* @property {
|
|
41
|
-
* @property {
|
|
42
|
-
* @property {
|
|
43
|
-
* @property {
|
|
44
|
-
* @property {
|
|
51
|
+
* @property {import('vue').UnwrapNestedRefs<SearchRawState>} state - The state.
|
|
52
|
+
* @property {Function} addIndex - Add an index.
|
|
53
|
+
* @property {Function} updateIndex - Update an index.
|
|
54
|
+
* @property {Function} removeIndex - Remove an index.
|
|
55
|
+
* @property {Function} clearIndex - Clear the index.
|
|
56
|
+
* @property {EventTarget} events - An event target.
|
|
57
|
+
* @property {object} effectScope - A Vue effect scope.
|
|
45
58
|
*/
|
|
46
59
|
|
|
47
60
|
const defaultDocumentOptions = {
|
|
@@ -53,18 +66,20 @@ const defaultDocumentOptions = {
|
|
|
53
66
|
};
|
|
54
67
|
|
|
55
68
|
/**
|
|
56
|
-
* A reactive object for passing document options or search options to useSearch
|
|
69
|
+
* A reactive object for passing document options or search options to useSearch.
|
|
70
|
+
*
|
|
57
71
|
* @typedef {object} SearchProps
|
|
58
|
-
* @property {DocumentOptions} customDocumentOptions - FlexSearch.Document options
|
|
59
|
-
* @property {SearchOptions} customSearchOptions -
|
|
72
|
+
* @property {DocumentOptions} customDocumentOptions - FlexSearch.Document options.
|
|
73
|
+
* @property {SearchOptions} customSearchOptions - Search options.
|
|
60
74
|
*/
|
|
61
75
|
|
|
62
76
|
/**
|
|
63
|
-
* A reactive wrapper around FlexSearch.Index
|
|
64
|
-
*
|
|
65
|
-
* @param {
|
|
66
|
-
* @param {
|
|
67
|
-
* @
|
|
77
|
+
* A reactive wrapper around FlexSearch.Index.
|
|
78
|
+
*
|
|
79
|
+
* @param {object} options - Options.
|
|
80
|
+
* @param {SearchProps} options.props - Props.
|
|
81
|
+
* @param {number} [options.throttle] - Throttle wait time.
|
|
82
|
+
* @returns {SearchInstance} - The instance.
|
|
68
83
|
*/
|
|
69
84
|
export function useSearch({ props, throttle = 500 }) {
|
|
70
85
|
let searchIndex;
|
|
@@ -158,6 +173,7 @@ export function useSearch({ props, throttle = 500 }) {
|
|
|
158
173
|
}
|
|
159
174
|
}
|
|
160
175
|
|
|
176
|
+
// @ts-ignore - this is a valid function, not sure why their types don't work for us.
|
|
161
177
|
const _throttledDoSearch = asyncThrottle(doSearch, throttle);
|
|
162
178
|
const throttledDoSearch = () => {
|
|
163
179
|
++state.called;
|
package/use/watchesRunning.js
CHANGED
|
@@ -1,8 +1,46 @@
|
|
|
1
|
-
import { loadingCombine } from "../utils/
|
|
1
|
+
import { loadingCombine } from "../utils/loadingCombine.js";
|
|
2
2
|
import { computed, effectScope, reactive, unref, watch } from "vue";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Vue Composition API composable function for watches running.
|
|
6
|
+
*
|
|
7
|
+
* @module use/watchesRunning.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The state for watches running.
|
|
12
|
+
*
|
|
13
|
+
* @typedef {object} WatchesRunningRawState
|
|
14
|
+
* @property {import('vue').ComputedRef<boolean>} running - Whether the watches are running.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The state for watches running.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {import('vue').UnwrapNestedRefs<WatchesRunningRawState>} WatchesRunningState
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* An instance of `useWatchesRunning`.
|
|
25
|
+
*
|
|
26
|
+
* @typedef {object} WatchesRunning
|
|
27
|
+
* @property {WatchesRunningState} state - The state for watches running.
|
|
28
|
+
* @property {import('vue').EffectScope} effectScope - The effect scope for watches running.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A composable function for handling watches running. When all the trigger refs are true,
|
|
33
|
+
* the watch sentinel refs are set to true.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} options - The options for the watches running.
|
|
36
|
+
* @param {import('vue').WatchSource[]} options.triggerRefs - The trigger refs.
|
|
37
|
+
* @param {import('vue').Ref<boolean>[]} options.watchSentinelRefs - The watch sentinel refs.
|
|
38
|
+
* @returns {WatchesRunning} - The watches running.
|
|
39
|
+
*/
|
|
4
40
|
export function useWatchesRunning({ triggerRefs, watchSentinelRefs }) {
|
|
5
|
-
const state = reactive({
|
|
41
|
+
const state = reactive({
|
|
42
|
+
running: undefined,
|
|
43
|
+
});
|
|
6
44
|
|
|
7
45
|
const es = effectScope();
|
|
8
46
|
|
|
@@ -21,10 +59,7 @@ export function useWatchesRunning({ triggerRefs, watchSentinelRefs }) {
|
|
|
21
59
|
deep: true,
|
|
22
60
|
}
|
|
23
61
|
);
|
|
24
|
-
state.running = computed(() =>
|
|
25
|
-
const values = watchSentinelRefs.map((ref) => unref(ref));
|
|
26
|
-
return loadingCombine(values);
|
|
27
|
-
});
|
|
62
|
+
state.running = computed(() => loadingCombine(...watchSentinelRefs.map((ref) => unref(ref))));
|
|
28
63
|
});
|
|
29
64
|
|
|
30
65
|
return {
|
|
@@ -4,44 +4,53 @@ import isArray from "lodash-es/isArray.js";
|
|
|
4
4
|
import isObject from "lodash-es/isObject.js";
|
|
5
5
|
import isObjectLike from "lodash-es/isObjectLike.js";
|
|
6
6
|
import { isReactive, isRef, toRef, unref } from "vue";
|
|
7
|
+
import isSet from "lodash-es/isSet.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* Reactive object assignment utilities
|
|
10
|
-
*
|
|
10
|
+
* Reactive object assignment utilities.
|
|
11
|
+
*
|
|
12
|
+
* @module utils/assignReactiveObject.js
|
|
11
13
|
*/
|
|
12
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when an invalid value is passed to a function.
|
|
17
|
+
*/
|
|
13
18
|
export class AssignReactiveObjectError extends Error {
|
|
14
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} message - The error message.
|
|
21
|
+
* @param {string} code - The error code.
|
|
22
|
+
*/
|
|
23
|
+
constructor(message, code) {
|
|
15
24
|
super(message);
|
|
16
25
|
this.name = "AssignReactiveObjectError";
|
|
26
|
+
this.code = code;
|
|
17
27
|
}
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
/**
|
|
21
|
-
* @typedef {
|
|
22
|
-
* @private
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {Ref|object|Array} ValidTargetOrSource targets and sources must be refs, objects, or arrays
|
|
31
|
+
* @typedef {import("vue").Ref<object | any[]> | object | any[]} ValidTargetOrSource targets and sources must be refs, objects, or arrays
|
|
27
32
|
* and refs must ultimately resolve to objects or arrays
|
|
28
33
|
*/
|
|
29
34
|
|
|
30
35
|
/**
|
|
31
36
|
* Validates that a value is an array or an object, and throws an error if it is not.
|
|
37
|
+
*
|
|
32
38
|
* @private
|
|
33
|
-
* @param {string} key The key being validated.
|
|
34
|
-
* @param {*} value The value being validated.
|
|
39
|
+
* @param {string} key - The key being validated.
|
|
40
|
+
* @param {*} value - The value being validated.
|
|
35
41
|
* @throws {AssignReactiveObjectError} If the value is not an array or an object.
|
|
36
42
|
*/
|
|
37
43
|
function isArrayOrObject(key, value) {
|
|
38
44
|
if (!(isArray(value) || isObject(value))) {
|
|
39
|
-
throw new AssignReactiveObjectError(
|
|
45
|
+
throw new AssignReactiveObjectError(
|
|
46
|
+
`${key} must be an object or an array, not ${inspect(value)}`,
|
|
47
|
+
"invalid-type"
|
|
48
|
+
);
|
|
40
49
|
}
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
/**
|
|
44
|
-
* @typedef validateTargetAndSourceResult
|
|
53
|
+
* @typedef {object} validateTargetAndSourceResult
|
|
45
54
|
* @private
|
|
46
55
|
* @property {ValidTargetOrSource} target The validated target value.
|
|
47
56
|
* @property {ValidTargetOrSource} source The validated source value.
|
|
@@ -50,9 +59,10 @@ function isArrayOrObject(key, value) {
|
|
|
50
59
|
/**
|
|
51
60
|
* Validates that the target and source values are arrays or objects, and returns them.
|
|
52
61
|
* If either value is a ref, it is dereferenced before validation.
|
|
62
|
+
*
|
|
53
63
|
* @private
|
|
54
|
-
* @param {ValidTargetOrSource} target The target value to validate.
|
|
55
|
-
* @param {ValidTargetOrSource} source The source value to validate.
|
|
64
|
+
* @param {ValidTargetOrSource} target - The target value to validate.
|
|
65
|
+
* @param {ValidTargetOrSource} source - The source value to validate.
|
|
56
66
|
* @returns {validateTargetAndSourceResult} An object containing the validated target and source values.
|
|
57
67
|
* @throws {AssignReactiveObjectError} If either value is not an array or an object.
|
|
58
68
|
*/
|
|
@@ -75,11 +85,12 @@ function validateTargetAndSource(target, source) {
|
|
|
75
85
|
/**
|
|
76
86
|
* Replaces keys in a target object or array with reactive refs to the corresponding keys in a
|
|
77
87
|
* source object or array.
|
|
88
|
+
*
|
|
78
89
|
* @private
|
|
79
|
-
* @param {ValidTargetOrSource} target The object receiving values.
|
|
80
|
-
* @param {ValidTargetOrSource} source The object providing values.
|
|
81
|
-
* @param {Array} keys The keys to replace.
|
|
82
|
-
* @param {Array} [exclude] Keys to exclude from replacement.
|
|
90
|
+
* @param {ValidTargetOrSource} target - The object receiving values.
|
|
91
|
+
* @param {ValidTargetOrSource} source - The object providing values.
|
|
92
|
+
* @param {Array|Set} keys - The keys to replace.
|
|
93
|
+
* @param {Array} [exclude] - Keys to exclude from replacement.
|
|
83
94
|
* @returns {boolean} True if any keys were replaced, false otherwise.
|
|
84
95
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
85
96
|
*/
|
|
@@ -113,11 +124,11 @@ function reactiveReplaceKeys(target, source, keys, exclude) {
|
|
|
113
124
|
|
|
114
125
|
/**
|
|
115
126
|
* Adds to a target the missing keys from a source. `addedKeys` can be precalculated to avoid recalculation.
|
|
116
|
-
*
|
|
117
|
-
* @param {ValidTargetOrSource} target The object receiving values.
|
|
118
|
-
* @param {ValidTargetOrSource} source The object providing values.
|
|
119
|
-
* @param {Array} [exclude] Keys to exclude from the addition.
|
|
120
|
-
* @param {Array} [addedKeys] Precaulcated array of keys to add, if available. Otherwise, the
|
|
127
|
+
*
|
|
128
|
+
* @param {ValidTargetOrSource} target - The object receiving values.
|
|
129
|
+
* @param {ValidTargetOrSource} source - The object providing values.
|
|
130
|
+
* @param {Array} [exclude] - Keys to exclude from the addition.
|
|
131
|
+
* @param {Array|Set} [addedKeys] - Precaulcated array of keys to add, if available. Otherwise, the
|
|
121
132
|
* keys will be calculated.
|
|
122
133
|
* @returns {boolean} True if any keys were added, false otherwise.
|
|
123
134
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
@@ -135,11 +146,11 @@ export function addReactiveObject(target, source, exclude, addedKeys = null) {
|
|
|
135
146
|
|
|
136
147
|
/**
|
|
137
148
|
* Updates a target with mutually shared keys from a source. `sameKeys` can be precalculated to avoid recalculation.
|
|
138
|
-
*
|
|
139
|
-
* @param {ValidTargetOrSource} target The object receiving values.
|
|
140
|
-
* @param {ValidTargetOrSource} source The object providing values.
|
|
141
|
-
* @param {Array} [exclude] Keys to exclude from the update.
|
|
142
|
-
* @param {Array} [sameKeys] Precaulcated array of keys to update, if available. Otherwise, the
|
|
149
|
+
*
|
|
150
|
+
* @param {ValidTargetOrSource} target - The object receiving values.
|
|
151
|
+
* @param {ValidTargetOrSource} source - The object providing values.
|
|
152
|
+
* @param {Array} [exclude] - Keys to exclude from the update.
|
|
153
|
+
* @param {Array|Set} [sameKeys] - Precaulcated array of keys to update, if available. Otherwise, the
|
|
143
154
|
* keys will be calculated.
|
|
144
155
|
* @returns {boolean} True if any keys were updated, false otherwise.
|
|
145
156
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
@@ -157,17 +168,25 @@ export function updateReactiveObject(target, source, exclude, sameKeys = null) {
|
|
|
157
168
|
|
|
158
169
|
/**
|
|
159
170
|
* Adds to a target the missing keys from a source, and updates a target with mutually shared keys from a source.
|
|
160
|
-
*
|
|
161
|
-
* @param {ValidTargetOrSource} target The object receiving values.
|
|
162
|
-
* @param {ValidTargetOrSource} source The object providing values.
|
|
163
|
-
* @param {Array} [exclude] Keys to exclude from the addition or update.
|
|
164
|
-
* @param {Array} [addedKeys] Precaulcated array of keys to add, if available. Otherwise, the
|
|
171
|
+
*
|
|
172
|
+
* @param {ValidTargetOrSource} target - The object receiving values.
|
|
173
|
+
* @param {ValidTargetOrSource} source - The object providing values.
|
|
174
|
+
* @param {Array} [exclude] - Keys to exclude from the addition or update.
|
|
175
|
+
* @param {Array|Set} [addedKeys] - Precaulcated array of keys to add, if available. Otherwise, the
|
|
165
176
|
* keys will be calculated.
|
|
166
|
-
* @param {Array} [sameKeys] Precaulcated array of keys to update, if available. Otherwise, the
|
|
177
|
+
* @param {Array|Set} [sameKeys] - Precaulcated array of keys to update, if available. Otherwise, the
|
|
167
178
|
* keys will be calculated.
|
|
179
|
+
* @param {boolean} [doNotSetUndefinedKeys=true] - If true, do not update keys in the target that are undefined in the source.
|
|
168
180
|
* @returns {boolean} True if any keys were added or updated, false otherwise.
|
|
169
181
|
*/
|
|
170
|
-
export function addOrUpdateReactiveObject(
|
|
182
|
+
export function addOrUpdateReactiveObject(
|
|
183
|
+
target,
|
|
184
|
+
source,
|
|
185
|
+
exclude,
|
|
186
|
+
addedKeys = null,
|
|
187
|
+
sameKeys = null,
|
|
188
|
+
doNotSetUndefinedKeys = true
|
|
189
|
+
) {
|
|
171
190
|
if (!addedKeys && !sameKeys) {
|
|
172
191
|
if (target === source) {
|
|
173
192
|
return false;
|
|
@@ -175,19 +194,34 @@ export function addOrUpdateReactiveObject(target, source, exclude, addedKeys = n
|
|
|
175
194
|
({ target, source } = validateTargetAndSource(target, source));
|
|
176
195
|
({ addedKeys, sameKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []));
|
|
177
196
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
197
|
+
// if the source update value is undefined, we should not update the target
|
|
198
|
+
if (sameKeys && doNotSetUndefinedKeys) {
|
|
199
|
+
for (const key of sameKeys) {
|
|
200
|
+
if (source[key] === undefined) {
|
|
201
|
+
if (isSet(sameKeys)) {
|
|
202
|
+
sameKeys.delete(key);
|
|
203
|
+
} else {
|
|
204
|
+
const index = sameKeys.indexOf(key);
|
|
205
|
+
if (index !== -1) {
|
|
206
|
+
sameKeys.splice(index, 1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const wasAdded = addReactiveObject(target, source, exclude, addedKeys);
|
|
214
|
+
const wasUpdated = updateReactiveObject(target, source, exclude, sameKeys);
|
|
215
|
+
return wasAdded || wasUpdated;
|
|
182
216
|
}
|
|
183
217
|
|
|
184
218
|
/**
|
|
185
219
|
* Removes keys from a target that are not present in a source.
|
|
186
|
-
*
|
|
187
|
-
* @param {ValidTargetOrSource} target The object receiving trimming.
|
|
188
|
-
* @param {ValidTargetOrSource|null} source The object that provides the allowed set of keys for calculating `removedKeys`.
|
|
189
|
-
* @param {Array} [exclude] Keys to exclude from removal.
|
|
190
|
-
* @param {Array} [removedKeys] An array to store removed keys.
|
|
220
|
+
*
|
|
221
|
+
* @param {ValidTargetOrSource} target - The object receiving trimming.
|
|
222
|
+
* @param {ValidTargetOrSource|null} source - The object that provides the allowed set of keys for calculating `removedKeys`.
|
|
223
|
+
* @param {Array} [exclude] - Keys to exclude from removal.
|
|
224
|
+
* @param {Array|Set} [removedKeys] - An array to store removed keys.
|
|
191
225
|
* @returns {boolean} True if any keys were removed, false otherwise.
|
|
192
226
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
193
227
|
*/
|
|
@@ -240,6 +274,15 @@ function checkIfReversed(target, source) {
|
|
|
240
274
|
return true;
|
|
241
275
|
}
|
|
242
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Change a target to match a source, where keys missing from the source are removed from the target,
|
|
279
|
+
* keys present in the source are added to the target, and keys present in both are updated in the target.
|
|
280
|
+
* This function is optimized for arrays.
|
|
281
|
+
*
|
|
282
|
+
* @param {ValidTargetOrSource} target - The array receiving updates.
|
|
283
|
+
* @param {ValidTargetOrSource} source - The reactive array to assign.
|
|
284
|
+
* @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
|
|
285
|
+
*/
|
|
243
286
|
export function assignReactiveArray(target, source) {
|
|
244
287
|
if (target === source) {
|
|
245
288
|
return false;
|
|
@@ -252,8 +295,9 @@ export function assignReactiveArray(target, source) {
|
|
|
252
295
|
didAnything = true;
|
|
253
296
|
} else {
|
|
254
297
|
const { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
|
|
255
|
-
|
|
256
|
-
|
|
298
|
+
const wasTrimmed = trimReactiveObject(target, source, null, removedKeys);
|
|
299
|
+
const wasChanged = addOrUpdateReactiveObject(target, source, null, addedKeys, sameKeys, false);
|
|
300
|
+
didAnything = wasTrimmed || wasChanged;
|
|
257
301
|
}
|
|
258
302
|
return didAnything;
|
|
259
303
|
}
|
|
@@ -261,10 +305,10 @@ export function assignReactiveArray(target, source) {
|
|
|
261
305
|
/**
|
|
262
306
|
* Change a target to match a source, where keys missing from the source are removed from the target,
|
|
263
307
|
* keys present in the source are added to the target, and keys present in both are updated in the target.
|
|
264
|
-
*
|
|
265
|
-
* @param {ValidTargetOrSource} target The target object or array.
|
|
266
|
-
* @param {ValidTargetOrSource} source The reactive object to assign.
|
|
267
|
-
* @param {Array} [exclude] Keys to exclude from the assignment.
|
|
308
|
+
*
|
|
309
|
+
* @param {ValidTargetOrSource} target - The target object or array.
|
|
310
|
+
* @param {ValidTargetOrSource} source - The reactive object to assign.
|
|
311
|
+
* @param {Array} [exclude] - Keys to exclude from the assignment.
|
|
268
312
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
269
313
|
* @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
|
|
270
314
|
*/
|
|
@@ -280,10 +324,9 @@ export function assignReactiveObject(target, source, exclude) {
|
|
|
280
324
|
}
|
|
281
325
|
({ target, source } = validateTargetAndSource(target, source));
|
|
282
326
|
const { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return didAnything;
|
|
327
|
+
const wasTrimmed = trimReactiveObject(target, source, exclude, removedKeys);
|
|
328
|
+
const wasChanged = addOrUpdateReactiveObject(target, source, exclude, addedKeys, sameKeys, false);
|
|
329
|
+
return wasTrimmed || wasChanged;
|
|
287
330
|
}
|
|
288
331
|
|
|
289
332
|
/**
|
|
@@ -291,21 +334,21 @@ export function assignReactiveObject(target, source, exclude) {
|
|
|
291
334
|
* keys present in the source are added to the target, and keys present in both are updated in the target.
|
|
292
335
|
*
|
|
293
336
|
* As an internal function, this function does not validate its arguments and has no optional arguments.
|
|
337
|
+
*
|
|
294
338
|
* @private
|
|
295
|
-
* @param {ValidTargetOrSource} target The object receiving updates.
|
|
296
|
-
* @param {ValidTargetOrSource} source The object providing updates.
|
|
297
|
-
* @param {Array} exclude Keys to exclude from the update.
|
|
298
|
-
* @param {Array} addedKeys Precaulcated array of keys to add, if available. Otherwise, the
|
|
339
|
+
* @param {ValidTargetOrSource} target - The object receiving updates.
|
|
340
|
+
* @param {ValidTargetOrSource} source - The object providing updates.
|
|
341
|
+
* @param {Array} exclude - Keys to exclude from the update.
|
|
342
|
+
* @param {Array|Set} addedKeys - Precaulcated array of keys to add, if available. Otherwise, the
|
|
299
343
|
* keys will be calculated.
|
|
300
|
-
* @param {Array} sameKeys Precaulcated array of keys to update, if available. Otherwise, the
|
|
344
|
+
* @param {Array|Set} sameKeys - Precaulcated array of keys to update, if available. Otherwise, the
|
|
301
345
|
* keys will be calculated.
|
|
302
|
-
* @param {string} path The current path, used to rescope exclude for the next level.
|
|
303
|
-
* @param {Function} fn The recursive function to call, likely the calling function itself.
|
|
346
|
+
* @param {string} path - The current path, used to rescope exclude for the next level.
|
|
347
|
+
* @param {Function} fn - The recursive function to call, likely the calling function itself.
|
|
304
348
|
* @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
|
|
305
349
|
*/
|
|
306
350
|
function recursiveInner(target, source, exclude, addedKeys, sameKeys, path, fn) {
|
|
307
|
-
|
|
308
|
-
didAnything |= addReactiveObject(target, source, exclude, addedKeys);
|
|
351
|
+
const wasAdded = addReactiveObject(target, source, exclude, addedKeys);
|
|
309
352
|
const keysForRecurse = [];
|
|
310
353
|
const keysForReplace = [];
|
|
311
354
|
for (const key of sameKeys) {
|
|
@@ -317,7 +360,7 @@ function recursiveInner(target, source, exclude, addedKeys, sameKeys, path, fn)
|
|
|
317
360
|
}
|
|
318
361
|
}
|
|
319
362
|
}
|
|
320
|
-
|
|
363
|
+
const wasReplaced = reactiveReplaceKeys(target, source, keysForReplace, exclude);
|
|
321
364
|
for (const key of keysForRecurse) {
|
|
322
365
|
// 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
|
|
323
366
|
const nextLevelExclude = exclude
|
|
@@ -326,7 +369,7 @@ function recursiveInner(target, source, exclude, addedKeys, sameKeys, path, fn)
|
|
|
326
369
|
const nextPath = isArray(source[key]) ? `${path}[${key}]` : `${path}.${key}`;
|
|
327
370
|
fn(target[key], source[key], nextLevelExclude, nextPath);
|
|
328
371
|
}
|
|
329
|
-
return
|
|
372
|
+
return wasAdded || wasReplaced;
|
|
330
373
|
}
|
|
331
374
|
|
|
332
375
|
/**
|
|
@@ -334,29 +377,37 @@ function recursiveInner(target, source, exclude, addedKeys, sameKeys, path, fn)
|
|
|
334
377
|
* keys present in the source are added to the target, and keys present in both are updated in the target.
|
|
335
378
|
*
|
|
336
379
|
* An internal function to avoid validating arguments repeatedly.
|
|
380
|
+
*
|
|
337
381
|
* @private
|
|
338
|
-
* @param {ValidTargetOrSource} target The object receiving updates.
|
|
339
|
-
* @param {ValidTargetOrSource} source The object providing updates.
|
|
340
|
-
* @param {Array} [exclude] Keys to exclude from the assignment.
|
|
341
|
-
* @param {string} [path] The current path, used to rescope exclude for the next level.
|
|
382
|
+
* @param {ValidTargetOrSource} target - The object receiving updates.
|
|
383
|
+
* @param {ValidTargetOrSource} source - The object providing updates.
|
|
384
|
+
* @param {Array} [exclude] - Keys to exclude from the assignment.
|
|
385
|
+
* @param {string} [path] - The current path, used to rescope exclude for the next level.
|
|
342
386
|
* @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
|
|
343
387
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
344
388
|
*/
|
|
345
389
|
function assignReactiveObjectRecursive(target, source, exclude, path = "") {
|
|
346
390
|
let { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
391
|
+
const wasTrimmed = trimReactiveObject(target, source, exclude, removedKeys);
|
|
392
|
+
const recursiveDidAnything = recursiveInner(
|
|
393
|
+
target,
|
|
394
|
+
source,
|
|
395
|
+
exclude,
|
|
396
|
+
addedKeys,
|
|
397
|
+
sameKeys,
|
|
398
|
+
path,
|
|
399
|
+
assignReactiveObjectRecursive
|
|
400
|
+
);
|
|
401
|
+
return wasTrimmed || recursiveDidAnything;
|
|
351
402
|
}
|
|
352
403
|
|
|
353
404
|
/**
|
|
354
405
|
* Recursively change a target to match a source, where keys missing from the source are removed from the target,
|
|
355
406
|
* keys present in the source are added to the target, and keys present in both are updated in the target.
|
|
356
|
-
*
|
|
357
|
-
* @param {ValidTargetOrSource} target The object receiving updates.
|
|
358
|
-
* @param {ValidTargetOrSource} source The object providing updates.
|
|
359
|
-
* @param {Array} [exclude] Keys to exclude from the assignment.
|
|
407
|
+
*
|
|
408
|
+
* @param {ValidTargetOrSource} target - The object receiving updates.
|
|
409
|
+
* @param {ValidTargetOrSource} source - The object providing updates.
|
|
410
|
+
* @param {Array} [exclude] - Keys to exclude from the assignment.
|
|
360
411
|
* @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
|
|
361
412
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
362
413
|
*/
|
|
@@ -374,26 +425,26 @@ export function assignReactiveObjectDeep(target, source, exclude) {
|
|
|
374
425
|
* keys present in both are updated in the target. Missing keys are not removed.
|
|
375
426
|
*
|
|
376
427
|
* As an internal function, this function does not validate its argument.
|
|
428
|
+
*
|
|
377
429
|
* @private
|
|
378
|
-
* @param {ValidTargetOrSource} target The object receiving updates.
|
|
379
|
-
* @param {ValidTargetOrSource} source The object providing updates.
|
|
380
|
-
* @param {Array} [exclude] Keys to exclude from the update.
|
|
381
|
-
* @param {string} [path] The current path, used to rescope exclude for the next level.
|
|
430
|
+
* @param {ValidTargetOrSource} target - The object receiving updates.
|
|
431
|
+
* @param {ValidTargetOrSource} source - The object providing updates.
|
|
432
|
+
* @param {Array} [exclude] - Keys to exclude from the update.
|
|
433
|
+
* @param {string} [path] - The current path, used to rescope exclude for the next level.
|
|
382
434
|
* @returns {boolean} True if any keys were added or updated, false otherwise.
|
|
383
435
|
*/
|
|
384
436
|
function addOrUpdateReactiveObjectRecursive(target, source, exclude, path = "") {
|
|
385
|
-
let addedKeys,
|
|
386
|
-
sameKeys = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
|
|
437
|
+
let { addedKeys, sameKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
|
|
387
438
|
return recursiveInner(target, source, exclude, addedKeys, sameKeys, path, addOrUpdateReactiveObjectRecursive);
|
|
388
439
|
}
|
|
389
440
|
|
|
390
441
|
/**
|
|
391
442
|
* Recursively change a target to match a source, where keys present in the source are added to the target, and
|
|
392
443
|
* keys present in both are updated in the target. Missing keys are not removed.
|
|
393
|
-
*
|
|
394
|
-
* @param {ValidTargetOrSource} target The object receiving updates.
|
|
395
|
-
* @param {ValidTargetOrSource} source The object providing updates.
|
|
396
|
-
* @param {Array} [exclude] Keys to exclude from the update.
|
|
444
|
+
*
|
|
445
|
+
* @param {ValidTargetOrSource} target - The object receiving updates.
|
|
446
|
+
* @param {ValidTargetOrSource} source - The object providing updates.
|
|
447
|
+
* @param {Array} [exclude] - Keys to exclude from the update.
|
|
397
448
|
* @returns {boolean} True if any keys were added or updated, false otherwise.
|
|
398
449
|
* @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
|
|
399
450
|
*/
|