@arrai-innovations/reactive-helpers 9.0.2 → 10.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/.idea/inspectionProfiles/Project_Default.xml +1 -0
- package/README.md +405 -65
- package/config/index.js +2 -0
- package/config/listCrud.js +37 -0
- package/config/objectCrud.js +45 -0
- package/docs.md +169 -14
- package/index.js +1 -0
- package/package.json +1 -1
- package/tests/unit/config/index.spec.js +18 -0
- package/tests/unit/config/listCrud.spec.js +107 -0
- package/tests/unit/config/objectCrud.spec.js +155 -0
- package/tests/unit/use/cancellableIntent.spec.js +1 -1
- package/tests/unit/use/listInstance.spec.js +5 -4
- package/tests/unit/use/listSubscription.spec.js +3 -5
- package/use/list.js +48 -14
- package/use/listCalculated.js +3 -0
- package/use/listFilter.js +40 -0
- package/use/listInstance.js +80 -27
- package/use/listRelated.js +5 -1
- package/use/listSort.js +34 -1
- package/use/listSubscription.js +56 -14
- package/use/object.js +26 -5
- package/use/objectCalculated.js +26 -39
- package/use/objectInstance.js +19 -35
- package/use/objectRelated.js +24 -34
- package/use/objectSubscription.js +25 -28
package/use/objectCalculated.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
import { keyDiff
|
|
1
|
+
import { keyDiff } from "../utils/keyDiff.js";
|
|
2
|
+
import { loadingCombine } from "../utils/loadingCombine.js";
|
|
3
|
+
import { objectInstanceStateKeys } from "./objectInstance.js";
|
|
4
|
+
import { objectRelatedStateKeys } from "./objectRelated.js";
|
|
5
|
+
import { objectSubscriptionStateKeys } from "./objectSubscription.js";
|
|
2
6
|
import { useWatchesRunning } from "./watchesRunning.js";
|
|
3
7
|
import isEmpty from "lodash-es/isEmpty.js";
|
|
4
8
|
import { computed, effectScope, onScopeDispose, reactive, toRef, watch } from "vue";
|
|
5
9
|
|
|
10
|
+
export const objectCalculatedStateKeys = [
|
|
11
|
+
"calculatedObject",
|
|
12
|
+
"calculatedObjectRules",
|
|
13
|
+
"calculatedObjectWatchRunning",
|
|
14
|
+
"parentStateObjectWatchRunning",
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export const objectCalculatedFunctions = [];
|
|
18
|
+
|
|
6
19
|
export function useObjectCalculateds(instances, args) {
|
|
7
20
|
for (const [key, value] of Object.entries(args)) {
|
|
8
21
|
useObjectCalculated({
|
|
@@ -13,54 +26,28 @@ export function useObjectCalculateds(instances, args) {
|
|
|
13
26
|
}
|
|
14
27
|
|
|
15
28
|
// the single object version of useListCalculated
|
|
16
|
-
export function useObjectCalculated({
|
|
17
|
-
parentState,
|
|
18
|
-
calculatedObjectRules,
|
|
19
|
-
calculatedObjectPropertyName = "calculatedObject", // NOT REACTIVE
|
|
20
|
-
passThroughPropertyNames = [
|
|
21
|
-
// instance
|
|
22
|
-
"crud",
|
|
23
|
-
"deleted",
|
|
24
|
-
"error",
|
|
25
|
-
"errored",
|
|
26
|
-
"id",
|
|
27
|
-
"loading",
|
|
28
|
-
"object",
|
|
29
|
-
"retrieveArgs",
|
|
30
|
-
// subscription
|
|
31
|
-
"intendToRetrieve",
|
|
32
|
-
"intendToSubscribe",
|
|
33
|
-
"subscribed",
|
|
34
|
-
"subscriptionError",
|
|
35
|
-
"subscriptionErrored",
|
|
36
|
-
"subscriptionLoading",
|
|
37
|
-
// related
|
|
38
|
-
"relatedObject",
|
|
39
|
-
"relatedObjectObjects",
|
|
40
|
-
"relatedObjectRules",
|
|
41
|
-
"relatedObjectWatchRunning",
|
|
42
|
-
"relatedRunning",
|
|
43
|
-
], // NOT REACTIVE
|
|
44
|
-
}) {
|
|
29
|
+
export function useObjectCalculated({ parentState, calculatedObjectRules }) {
|
|
45
30
|
const state = reactive({
|
|
46
31
|
calculatedObjectRules,
|
|
47
|
-
|
|
32
|
+
calculatedObject: {},
|
|
48
33
|
parentStateObjectWatchRunning: false,
|
|
49
34
|
calculatedObjectWatchRunning: false,
|
|
50
35
|
});
|
|
51
36
|
const calculatedObjectEffectScopes = {};
|
|
52
37
|
const calculatedObjectOriginalFunctions = {};
|
|
53
38
|
|
|
54
|
-
// don't change calculatedObjectPropertyName on us or it will break
|
|
55
|
-
const copn = calculatedObjectPropertyName + "";
|
|
56
|
-
|
|
57
39
|
let watchesRunning = null;
|
|
58
40
|
|
|
59
41
|
const es = effectScope();
|
|
60
42
|
|
|
61
43
|
es.run(() => {
|
|
62
|
-
|
|
63
|
-
|
|
44
|
+
for (const key of objectInstanceStateKeys) {
|
|
45
|
+
state[key] = toRef(parentState, key);
|
|
46
|
+
}
|
|
47
|
+
for (const key of objectSubscriptionStateKeys) {
|
|
48
|
+
state[key] = toRef(parentState, key);
|
|
49
|
+
}
|
|
50
|
+
for (const key of objectRelatedStateKeys) {
|
|
64
51
|
state[key] = toRef(parentState, key);
|
|
65
52
|
}
|
|
66
53
|
|
|
@@ -84,7 +71,7 @@ export function useObjectCalculated({
|
|
|
84
71
|
}
|
|
85
72
|
for (const removedKey of removedKeys) {
|
|
86
73
|
delete calculatedObjectOriginalFunctions[removedKey];
|
|
87
|
-
delete state.
|
|
74
|
+
delete state.calculatedObject[removedKey];
|
|
88
75
|
if (calculatedObjectEffectScopes[removedKey]) {
|
|
89
76
|
calculatedObjectEffectScopes[removedKey].stop();
|
|
90
77
|
delete calculatedObjectEffectScopes[removedKey];
|
|
@@ -94,7 +81,7 @@ export function useObjectCalculated({
|
|
|
94
81
|
calculatedObjectOriginalFunctions[addedKey] = state.calculatedObjectRules[addedKey];
|
|
95
82
|
calculatedObjectEffectScopes[addedKey] = effectScope();
|
|
96
83
|
calculatedObjectEffectScopes[addedKey].run(() => {
|
|
97
|
-
state.
|
|
84
|
+
state.calculatedObject[addedKey] = computed(() =>
|
|
98
85
|
calculatedObjectOriginalFunctions[addedKey](state.object)
|
|
99
86
|
);
|
|
100
87
|
});
|
|
@@ -110,7 +97,7 @@ export function useObjectCalculated({
|
|
|
110
97
|
});
|
|
111
98
|
|
|
112
99
|
state.calculatedRunning = toRef(watchesRunning.state, "running");
|
|
113
|
-
state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.
|
|
100
|
+
state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.running));
|
|
114
101
|
|
|
115
102
|
onScopeDispose(() => {
|
|
116
103
|
for (const key in calculatedObjectEffectScopes) {
|
package/use/objectInstance.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import isFunction from "lodash-es/isFunction.js";
|
|
1
|
+
import { getObjectCrud } from "../config/objectCrud.js";
|
|
2
|
+
import { assignReactiveObject } from "../utils/assignReactiveObject.js";
|
|
4
3
|
import { reactive, toRef } from "vue";
|
|
5
4
|
|
|
6
5
|
export class ObjectError extends Error {
|
|
@@ -10,23 +9,18 @@ export class ObjectError extends Error {
|
|
|
10
9
|
}
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
export const objectInstanceStateKeys = [
|
|
13
|
+
"crud",
|
|
14
|
+
"id",
|
|
15
|
+
"retrieveArgs",
|
|
16
|
+
"object",
|
|
17
|
+
"loading",
|
|
18
|
+
"errored",
|
|
19
|
+
"error",
|
|
20
|
+
"deleted",
|
|
21
|
+
];
|
|
21
22
|
|
|
22
|
-
export
|
|
23
|
-
defaultCrud.retrieve = retrieve;
|
|
24
|
-
defaultCrud.create = create;
|
|
25
|
-
defaultCrud.update = update;
|
|
26
|
-
defaultCrud.patch = patch;
|
|
27
|
-
defaultCrud.delete = deleteFn;
|
|
28
|
-
Object.assign(defaultCrud.args, args);
|
|
29
|
-
}
|
|
23
|
+
export const objectInstanceFunctions = ["create", "retrieve", "update", "delete", "patch", "clearError", "clear"];
|
|
30
24
|
|
|
31
25
|
export function useObjectInstances(instanceArgs) {
|
|
32
26
|
const instances = {};
|
|
@@ -40,11 +34,11 @@ export function useObjectInstance({ props, functions = {} }) {
|
|
|
40
34
|
const state = reactive({
|
|
41
35
|
crud: {
|
|
42
36
|
args: {},
|
|
43
|
-
retrieve: undefined,
|
|
44
37
|
create: undefined,
|
|
38
|
+
retrieve: undefined,
|
|
45
39
|
update: undefined,
|
|
46
|
-
patch: undefined,
|
|
47
40
|
delete: undefined,
|
|
41
|
+
patch: undefined,
|
|
48
42
|
},
|
|
49
43
|
object: {},
|
|
50
44
|
id: toRef(props, "id"),
|
|
@@ -54,18 +48,8 @@ export function useObjectInstance({ props, functions = {} }) {
|
|
|
54
48
|
error: null,
|
|
55
49
|
deleted: false,
|
|
56
50
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (props.crudArgs) {
|
|
60
|
-
addOrUpdateReactiveObject(state.crud.args, props.crudArgs);
|
|
61
|
-
}
|
|
62
|
-
for (const [key, value] of Object.entries(functions)) {
|
|
63
|
-
if (isFunction(value) && key in state.crud) {
|
|
64
|
-
state[key] = value;
|
|
65
|
-
} else {
|
|
66
|
-
throw ObjectError(`Invalid function "${key}" for useObjectInstance: invalid key or not a function.`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
51
|
+
|
|
52
|
+
getObjectCrud(state.crud, { props, functions });
|
|
69
53
|
|
|
70
54
|
// due to retrieve being called by `useCancelleableIntent`, if called manually then by the watch,
|
|
71
55
|
// it will run into the loading check. Instead, return the current retrieve promise if it exists.
|
|
@@ -229,11 +213,11 @@ export function useObjectInstance({ props, functions = {} }) {
|
|
|
229
213
|
|
|
230
214
|
return reactive({
|
|
231
215
|
state,
|
|
232
|
-
retrieve,
|
|
233
216
|
create,
|
|
217
|
+
retrieve,
|
|
234
218
|
update,
|
|
235
|
-
patch,
|
|
236
219
|
delete: deleteFn,
|
|
220
|
+
patch,
|
|
237
221
|
clearError,
|
|
238
222
|
clear,
|
|
239
223
|
});
|
package/use/objectRelated.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { loadingCombine } from "../utils/index.js";
|
|
2
|
+
import { keyDiff } from "../utils/keyDiff.js";
|
|
3
|
+
import { objectInstanceStateKeys } from "./objectInstance.js";
|
|
4
|
+
import { objectSubscriptionStateKeys } from "./objectSubscription.js";
|
|
2
5
|
import { useWatchesRunning } from "./watchesRunning.js";
|
|
3
6
|
import get from "lodash-es/get.js";
|
|
4
7
|
import isArray from "lodash-es/isArray.js";
|
|
@@ -6,6 +9,15 @@ import isEmpty from "lodash-es/isEmpty.js";
|
|
|
6
9
|
import isUndefined from "lodash-es/isUndefined.js";
|
|
7
10
|
import { computed, effectScope, onScopeDispose, reactive, toRef, unref, watch } from "vue";
|
|
8
11
|
|
|
12
|
+
export const objectRelatedStateKeys = [
|
|
13
|
+
"relatedObject",
|
|
14
|
+
"relatedObjectRules",
|
|
15
|
+
"relatedObjectWatchRunning",
|
|
16
|
+
"parentStateObjectWatchRunning",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export const objectRelatedFunctions = [];
|
|
20
|
+
|
|
9
21
|
export function useObjectRelateds(instances, args) {
|
|
10
22
|
for (const [key, value] of Object.entries(args)) {
|
|
11
23
|
useObjectRelated({
|
|
@@ -16,47 +28,24 @@ export function useObjectRelateds(instances, args) {
|
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
// the single object version of useListRelated
|
|
19
|
-
export function useObjectRelated({
|
|
20
|
-
parentState,
|
|
21
|
-
relatedObjectRules,
|
|
22
|
-
relatedObjectPropertyName = "relatedObject", // NOT REACTIVE
|
|
23
|
-
passThroughPropertyNames = [
|
|
24
|
-
// instance
|
|
25
|
-
"crud",
|
|
26
|
-
"deleted",
|
|
27
|
-
"error",
|
|
28
|
-
"errored",
|
|
29
|
-
"id",
|
|
30
|
-
"loading",
|
|
31
|
-
"object",
|
|
32
|
-
"retrieveArgs",
|
|
33
|
-
// subscription
|
|
34
|
-
"intendToRetrieve",
|
|
35
|
-
"intendToSubscribe",
|
|
36
|
-
"subscribed",
|
|
37
|
-
"subscriptionError",
|
|
38
|
-
"subscriptionErrored",
|
|
39
|
-
"subscriptionLoading",
|
|
40
|
-
], // NOT REACTIVE
|
|
41
|
-
}) {
|
|
31
|
+
export function useObjectRelated({ parentState, relatedObjectRules }) {
|
|
42
32
|
const state = reactive({
|
|
43
33
|
relatedObjectRules,
|
|
44
|
-
|
|
34
|
+
relatedObject: {},
|
|
45
35
|
parentStateObjectWatchRunning: false,
|
|
46
36
|
relatedObjectWatchRunning: false,
|
|
47
37
|
});
|
|
48
38
|
const relatedObjectEffectScopes = {};
|
|
49
39
|
|
|
50
|
-
// don't change relatedObjectPropertyName on us or it will break
|
|
51
|
-
const ropn = relatedObjectPropertyName + "";
|
|
52
|
-
|
|
53
40
|
let watchesRunning = null;
|
|
54
41
|
|
|
55
42
|
const es = effectScope();
|
|
56
43
|
|
|
57
44
|
es.run(() => {
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
for (const key of objectInstanceStateKeys) {
|
|
46
|
+
state[key] = toRef(parentState, key);
|
|
47
|
+
}
|
|
48
|
+
for (const key of objectSubscriptionStateKeys) {
|
|
60
49
|
state[key] = toRef(parentState, key);
|
|
61
50
|
}
|
|
62
51
|
|
|
@@ -64,16 +53,16 @@ export function useObjectRelated({
|
|
|
64
53
|
let addedRuleKeys = [],
|
|
65
54
|
removedRuleKeys = [];
|
|
66
55
|
if (!state.relatedObjectRules) {
|
|
67
|
-
removedRuleKeys = Object.keys(state.
|
|
56
|
+
removedRuleKeys = Object.keys(state.relatedObject);
|
|
68
57
|
} else {
|
|
69
58
|
({ addedKeys: addedRuleKeys, removedKeys: removedRuleKeys } = keyDiff(
|
|
70
59
|
Object.keys(state.relatedObjectRules),
|
|
71
|
-
Object.keys(state.
|
|
60
|
+
Object.keys(state.relatedObject)
|
|
72
61
|
));
|
|
73
62
|
}
|
|
74
63
|
|
|
75
64
|
for (const removedRuleKey of removedRuleKeys) {
|
|
76
|
-
delete state.
|
|
65
|
+
delete state.relatedObject[removedRuleKey];
|
|
77
66
|
if (relatedObjectEffectScopes[removedRuleKey]) {
|
|
78
67
|
relatedObjectEffectScopes[removedRuleKey].stop();
|
|
79
68
|
delete relatedObjectEffectScopes[removedRuleKey];
|
|
@@ -82,7 +71,7 @@ export function useObjectRelated({
|
|
|
82
71
|
for (const addedRuleKey of addedRuleKeys) {
|
|
83
72
|
relatedObjectEffectScopes[addedRuleKey] = effectScope();
|
|
84
73
|
relatedObjectEffectScopes[addedRuleKey].run(() => {
|
|
85
|
-
state.
|
|
74
|
+
state.relatedObject[addedRuleKey] = computed(() => {
|
|
86
75
|
// deal with computed objects being passed.
|
|
87
76
|
const ruleObjects = unref(state.relatedObjectRules?.[addedRuleKey]?.objects);
|
|
88
77
|
const rulePkKey = state.relatedObjectRules?.[addedRuleKey]?.pkKey || addedRuleKey;
|
|
@@ -111,6 +100,7 @@ export function useObjectRelated({
|
|
|
111
100
|
});
|
|
112
101
|
|
|
113
102
|
state.relatedRunning = toRef(watchesRunning.state, "running");
|
|
103
|
+
state.running = computed(() => loadingCombine(watchesRunning.state.running, parentState.running));
|
|
114
104
|
|
|
115
105
|
onScopeDispose(() => {
|
|
116
106
|
for (const key in relatedObjectEffectScopes) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assignReactiveObject, loadingCombine } from "../utils/index.js";
|
|
2
2
|
import { useCancellableIntent } from "./cancellableIntent.js";
|
|
3
|
-
import { useObjectInstance } from "./objectInstance.js";
|
|
3
|
+
import { useObjectInstance, objectInstanceStateKeys } from "./objectInstance.js";
|
|
4
4
|
import { computed, effectScope, reactive, toRef } from "vue";
|
|
5
5
|
|
|
6
6
|
export class ObjectSubscriptionError extends Error {
|
|
@@ -10,13 +10,22 @@ export class ObjectSubscriptionError extends Error {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
export const objectSubscriptionStateKeys = [
|
|
14
|
+
"subscriptionLoading",
|
|
15
|
+
"subscriptionErrored",
|
|
16
|
+
"subscriptionError",
|
|
17
|
+
"subscribed",
|
|
18
|
+
"intendToRetrieve",
|
|
19
|
+
"intendToSubscribe",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export const objectSubscriptionFunctions = [
|
|
23
|
+
"subscribe",
|
|
24
|
+
"unsubscribe",
|
|
25
|
+
"updateFromSubscription",
|
|
26
|
+
"deleteFromSubscription",
|
|
27
|
+
"clearError",
|
|
28
|
+
];
|
|
20
29
|
|
|
21
30
|
export function useObjectSubscriptions(subscriptionArgs) {
|
|
22
31
|
const subscriptions = {};
|
|
@@ -26,23 +35,9 @@ export function useObjectSubscriptions(subscriptionArgs) {
|
|
|
26
35
|
return subscriptions;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
export function useObjectSubscription({
|
|
30
|
-
objectInstance,
|
|
31
|
-
props,
|
|
32
|
-
passThroughPropertyNames = [
|
|
33
|
-
// instance
|
|
34
|
-
"crud",
|
|
35
|
-
"deleted",
|
|
36
|
-
// "error",
|
|
37
|
-
// "errored",
|
|
38
|
-
"id",
|
|
39
|
-
// "loading",
|
|
40
|
-
"object",
|
|
41
|
-
"retrieveArgs",
|
|
42
|
-
],
|
|
43
|
-
}) {
|
|
38
|
+
export function useObjectSubscription({ objectInstance, props, functions }) {
|
|
44
39
|
if (!objectInstance) {
|
|
45
|
-
objectInstance = useObjectInstance({ props });
|
|
40
|
+
objectInstance = useObjectInstance({ props, functions });
|
|
46
41
|
} else {
|
|
47
42
|
if (!("id" in props)) {
|
|
48
43
|
console.error("id not set, must be true for intendToRetrieve or intendToSubscribe to work.");
|
|
@@ -50,9 +45,11 @@ export function useObjectSubscription({
|
|
|
50
45
|
if (!("retrieveArgs" in props)) {
|
|
51
46
|
console.error("retrieveArgs not set, must be true for intendToRetrieve or intendToSubscribe to work.");
|
|
52
47
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
if (functions) {
|
|
49
|
+
console.error(
|
|
50
|
+
"functions passed to useObjectSubscription, but objectInstance was passed. functions ignored."
|
|
51
|
+
);
|
|
52
|
+
}
|
|
56
53
|
}
|
|
57
54
|
const parentState = objectInstance.state;
|
|
58
55
|
const state = reactive({
|
|
@@ -169,7 +166,7 @@ export function useObjectSubscription({
|
|
|
169
166
|
state.errored = computed(() => parentState.errored || state.subscriptionErrored);
|
|
170
167
|
state.error = computed(() => parentState.error || state.subscriptionError);
|
|
171
168
|
|
|
172
|
-
for (const key of
|
|
169
|
+
for (const key of objectInstanceStateKeys.filter((key) => !["loading", "errored", "error"].includes(key))) {
|
|
173
170
|
state[key] = toRef(parentState, key);
|
|
174
171
|
}
|
|
175
172
|
|