@arrai-innovations/reactive-helpers 3.3.0 → 4.1.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 +2 -1
- package/tests/unit/use/listCalculated.spec.js +76 -0
- package/tests/unit/use/listFilter.spec.js +6 -6
- package/tests/unit/use/listRelated.spec.js +22 -19
- package/tests/unit/use/listSort.spec.js +6 -5
- package/tests/unit/use/listSubscription.spec.js +9 -5
- package/use/cancellableIntent.js +53 -46
- package/use/list.js +34 -24
- package/use/listCalculated.js +38 -47
- package/use/listRelated.js +36 -63
- package/use/listSubscription.js +10 -11
- package/use/object.js +30 -21
- package/use/objectCalculated.js +6 -32
- package/use/objectRelated.js +6 -32
- package/use/objectSubscription.js +10 -11
- package/utils/index.js +0 -1
- package/utils/watches.js +6 -2
- package/tests/unit/utils/unrefAndToRawDeep.spec.js +0 -170
- package/utils/unrefAndToRawDeep.js +0 -49
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arrai-innovations/reactive-helpers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"lodash": "^4.17.21",
|
|
55
55
|
"pinst": "^3.0.0",
|
|
56
56
|
"vue": "^3.2.33",
|
|
57
|
+
"vue-deepunref": "^1.0.1",
|
|
57
58
|
"vue-router": "^4.0.15"
|
|
58
59
|
}
|
|
59
60
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { nextTick } from "vue";
|
|
2
|
+
import { deepUnref } from "vue-deepunref";
|
|
3
|
+
|
|
4
|
+
describe("use/listCalculated", () => {
|
|
5
|
+
let useListInstance, useListCalculated;
|
|
6
|
+
beforeEach(async () => {
|
|
7
|
+
const listInstanceModule = await import("../../../use/listInstance");
|
|
8
|
+
useListInstance = listInstanceModule.useListInstance;
|
|
9
|
+
const listCalculatedModule = await import("../../../use/listCalculated");
|
|
10
|
+
useListCalculated = listCalculatedModule.useListCalculated;
|
|
11
|
+
});
|
|
12
|
+
it("should return a list of calculated items", async () => {
|
|
13
|
+
const mainListInstance = useListInstance({});
|
|
14
|
+
const calculatedListInstance = useListInstance({});
|
|
15
|
+
mainListInstance.addListObject({
|
|
16
|
+
id: "1",
|
|
17
|
+
name: "main",
|
|
18
|
+
calculated_items: ["2", "3"],
|
|
19
|
+
calculated_id: "4",
|
|
20
|
+
});
|
|
21
|
+
calculatedListInstance.addListObject({
|
|
22
|
+
id: "2",
|
|
23
|
+
name: "calculated1",
|
|
24
|
+
});
|
|
25
|
+
calculatedListInstance.addListObject({
|
|
26
|
+
id: "3",
|
|
27
|
+
name: "calculated2",
|
|
28
|
+
});
|
|
29
|
+
calculatedListInstance.addListObject({
|
|
30
|
+
id: "4",
|
|
31
|
+
name: "calculated3",
|
|
32
|
+
});
|
|
33
|
+
const listCalculated = useListCalculated({
|
|
34
|
+
parentState: mainListInstance.state,
|
|
35
|
+
calculatedObjectsRules: {
|
|
36
|
+
calculatedItems: (obj) => obj.calculated_items.map((x) => calculatedListInstance.state.objects[x]),
|
|
37
|
+
calculatedItem: (obj) => calculatedListInstance.state.objects[obj.calculated_id],
|
|
38
|
+
},
|
|
39
|
+
calculatedObjectsPropertyName: "myCalculatedObjects",
|
|
40
|
+
});
|
|
41
|
+
await nextTick();
|
|
42
|
+
// listCalculated.state.objects is doing proxy shenanigans
|
|
43
|
+
// in uses handler.has
|
|
44
|
+
expect("myCalculatedObjects" in listCalculated.state).toBe(true);
|
|
45
|
+
expect(!!listCalculated.state.myCalculatedObjects?.[1]).toBe(true);
|
|
46
|
+
expect("calculatedItems" in listCalculated.state.myCalculatedObjects[1]).toBe(true);
|
|
47
|
+
expect("calculatedItem" in listCalculated.state.myCalculatedObjects[1]).toBe(true);
|
|
48
|
+
// expect uses enumeration, which uses handler.ownKeys and handler.getOwnPropertyDescriptor
|
|
49
|
+
expect(deepUnref(listCalculated.state.objects)).toEqual({
|
|
50
|
+
1: {
|
|
51
|
+
id: "1",
|
|
52
|
+
name: "main",
|
|
53
|
+
calculated_id: "4",
|
|
54
|
+
calculated_items: ["2", "3"],
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
expect(deepUnref(listCalculated.state.myCalculatedObjects)).toEqual({
|
|
58
|
+
1: {
|
|
59
|
+
calculatedItems: [
|
|
60
|
+
{
|
|
61
|
+
id: "2",
|
|
62
|
+
name: "calculated1",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "3",
|
|
66
|
+
name: "calculated2",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
calculatedItem: {
|
|
70
|
+
id: "4",
|
|
71
|
+
name: "calculated3",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { nextTick, reactive, ref } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { deepUnref } from "vue-deepunref";
|
|
3
3
|
import { useListFilters, useListSort } from "../../../use";
|
|
4
|
-
import {
|
|
4
|
+
import { doAwaitNot } from "../../../utils/watches";
|
|
5
5
|
|
|
6
6
|
describe("use/listFilter", () => {
|
|
7
7
|
let useListInstance, useListFilter, setDefaultSearchOptions;
|
|
@@ -318,10 +318,10 @@ describe("use/listFilter", () => {
|
|
|
318
318
|
|
|
319
319
|
expect(listFilters.A.state.excludedValues).toEqual({ id: 1, name: "three" });
|
|
320
320
|
expect(listFilters.B.state.allowedValues).toEqual({ id: 2, name: "four" });
|
|
321
|
-
expect(
|
|
322
|
-
expect(
|
|
323
|
-
expect(
|
|
324
|
-
expect(
|
|
321
|
+
expect(deepUnref(listFilters.A.parentState)).toEqual(deepUnref(listFilterA.parentState));
|
|
322
|
+
expect(deepUnref(listFilters.B.parentState)).toEqual(deepUnref(listFilterB.parentState));
|
|
323
|
+
expect(deepUnref(listFilters.A.state)).toEqual(deepUnref(listFilterA.state));
|
|
324
|
+
expect(deepUnref(listFilters.B.state)).toEqual(deepUnref(listFilterB.state));
|
|
325
325
|
});
|
|
326
326
|
});
|
|
327
327
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { nextTick } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { deepUnref } from "vue-deepunref";
|
|
3
3
|
|
|
4
4
|
describe("use/listRelated", () => {
|
|
5
5
|
let useListInstance, useListRelated;
|
|
@@ -47,31 +47,34 @@ describe("use/listRelated", () => {
|
|
|
47
47
|
await nextTick();
|
|
48
48
|
// listRelated.state.objects is doing proxy shenanigans
|
|
49
49
|
// in uses handler.has
|
|
50
|
-
expect("myRelatedObjects" in listRelated.state
|
|
51
|
-
expect(
|
|
52
|
-
expect("
|
|
50
|
+
expect("myRelatedObjects" in listRelated.state).toBe(true);
|
|
51
|
+
expect(!!listRelated.state.myRelatedObjects?.[1]).toBe(true);
|
|
52
|
+
expect("relatedItems" in listRelated.state.myRelatedObjects[1]).toBe(true);
|
|
53
|
+
expect("relatedItem" in listRelated.state.myRelatedObjects[1]).toBe(true);
|
|
53
54
|
// expect uses enumeration, which uses handler.ownKeys and handler.getOwnPropertyDescriptor
|
|
54
|
-
expect(
|
|
55
|
+
expect(deepUnref(listRelated.state.objects)).toEqual({
|
|
55
56
|
1: {
|
|
56
57
|
id: "1",
|
|
57
58
|
name: "main",
|
|
58
59
|
related_id: "4",
|
|
59
60
|
related_items: ["2", "3"],
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
name: "related2",
|
|
69
|
-
},
|
|
70
|
-
],
|
|
71
|
-
relatedItem: {
|
|
72
|
-
id: "4",
|
|
73
|
-
name: "related3",
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
expect(deepUnref(listRelated.state.myRelatedObjects)).toEqual({
|
|
64
|
+
1: {
|
|
65
|
+
relatedItems: [
|
|
66
|
+
{
|
|
67
|
+
id: "2",
|
|
68
|
+
name: "related1",
|
|
74
69
|
},
|
|
70
|
+
{
|
|
71
|
+
id: "3",
|
|
72
|
+
name: "related2",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
relatedItem: {
|
|
76
|
+
id: "4",
|
|
77
|
+
name: "related3",
|
|
75
78
|
},
|
|
76
79
|
},
|
|
77
80
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { nextTick } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { deepUnref } from "vue-deepunref";
|
|
3
|
+
import { doAwaitTimeout } from "../../../utils";
|
|
3
4
|
|
|
4
5
|
describe("use/useListSort", () => {
|
|
5
6
|
let listInstance,
|
|
@@ -178,10 +179,10 @@ describe("use/useListSort", () => {
|
|
|
178
179
|
},
|
|
179
180
|
listInstances
|
|
180
181
|
);
|
|
181
|
-
expect(
|
|
182
|
-
expect(
|
|
183
|
-
expect(
|
|
184
|
-
expect(
|
|
182
|
+
expect(deepUnref(listSorts.A.parentState)).toEqual(deepUnref(listInstanceA.state));
|
|
183
|
+
expect(deepUnref(listSorts.B.parentState)).toEqual(deepUnref(listInstanceB.state));
|
|
184
|
+
expect(deepUnref(listSorts.A.state)).toEqual(deepUnref(listSortA.state));
|
|
185
|
+
expect(deepUnref(listSorts.B.state)).toEqual(deepUnref(listSortB.state));
|
|
185
186
|
});
|
|
186
187
|
describe("useListSort/sortThrottleWait", () => {
|
|
187
188
|
it("respects throttle time prior to triggering", async () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { nextTick, reactive } from "vue";
|
|
2
|
-
import { inspect } from "util";
|
|
3
|
-
import { doAwaitTimeout } from "../../../utils";
|
|
4
1
|
import flushPromises from "flush-promises";
|
|
2
|
+
import { inspect } from "util";
|
|
3
|
+
import { nextTick, reactive } from "vue";
|
|
4
|
+
import { doAwaitNot, doAwaitTimeout } from "../../../utils";
|
|
5
5
|
import { CancellableResolvable } from "../crudPromise";
|
|
6
6
|
import { poll } from "../poll";
|
|
7
7
|
|
|
@@ -512,8 +512,12 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
512
512
|
listArgs.user = 2;
|
|
513
513
|
retrieveArgs.fields = ["name"];
|
|
514
514
|
await nextTick();
|
|
515
|
-
await
|
|
516
|
-
await
|
|
515
|
+
await crudSubscribeResolvable[1].resolve();
|
|
516
|
+
await crudListResolvable[1].resolve();
|
|
517
|
+
await doAwaitNot({
|
|
518
|
+
obj: listSubscription.listIntent.state,
|
|
519
|
+
prop: "resolving",
|
|
520
|
+
});
|
|
517
521
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
518
522
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
519
523
|
expect(crudSubscribe).toHaveBeenCalledWith({
|
package/use/cancellableIntent.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { identity, isEqual } from "lodash";
|
|
2
|
+
import { effectScope, nextTick, onScopeDispose, reactive, readonly, watch } from "vue";
|
|
3
|
+
import { deepUnref } from "vue-deepunref";
|
|
3
4
|
|
|
4
5
|
/*
|
|
5
6
|
* Calls your awaitable function with the arguments you pass in, when the watch arguments change and are all truthy.
|
|
6
|
-
* Watch arguments
|
|
7
|
+
* Watch arguments should be a reactive object.
|
|
7
8
|
* If the promise is not resolved before the watch arguments change again, the previous promise is cancelled.
|
|
8
9
|
*/
|
|
9
10
|
export function useCancellableIntent({ awaitableWithCancel, watchArguments = {}, clearActiveOnResolved = true }) {
|
|
@@ -15,11 +16,12 @@ export function useCancellableIntent({ awaitableWithCancel, watchArguments = {},
|
|
|
15
16
|
}
|
|
16
17
|
const state = reactive({
|
|
17
18
|
active: undefined,
|
|
19
|
+
resolving: undefined,
|
|
18
20
|
errored: false,
|
|
19
21
|
error: null,
|
|
20
22
|
clearActiveOnResolved,
|
|
21
23
|
});
|
|
22
|
-
let
|
|
24
|
+
let previousWatchValues = null,
|
|
23
25
|
cancelFunction = null;
|
|
24
26
|
|
|
25
27
|
const es = effectScope();
|
|
@@ -32,6 +34,7 @@ export function useCancellableIntent({ awaitableWithCancel, watchArguments = {},
|
|
|
32
34
|
async function cancel() {
|
|
33
35
|
if (cancelFunction) {
|
|
34
36
|
state.active = false;
|
|
37
|
+
state.resolving = false;
|
|
35
38
|
const cancelPromise = cancelFunction().catch(console.error);
|
|
36
39
|
cancelFunction = null;
|
|
37
40
|
return cancelPromise;
|
|
@@ -39,54 +42,58 @@ export function useCancellableIntent({ awaitableWithCancel, watchArguments = {},
|
|
|
39
42
|
return false;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
awaitablePromise
|
|
65
|
-
.then(() => {
|
|
66
|
-
if (state.clearActiveOnResolved) {
|
|
67
|
-
cancelFunction = null;
|
|
68
|
-
state.active = false;
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
.catch(async (err) => {
|
|
72
|
-
await cancel();
|
|
73
|
-
console.error(err);
|
|
74
|
-
state.errored = true;
|
|
75
|
-
state.error = err;
|
|
76
|
-
throw err;
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
deep: true,
|
|
82
|
-
immediate: true,
|
|
45
|
+
const watchFn = () => {
|
|
46
|
+
let newWatchValues = deepUnref(Object.values(watchArguments));
|
|
47
|
+
if (isEqual(newWatchValues, previousWatchValues)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
previousWatchValues = newWatchValues;
|
|
51
|
+
cancel().catch(console.error);
|
|
52
|
+
if (Object.values(previousWatchValues).every(identity)) {
|
|
53
|
+
state.errored = false;
|
|
54
|
+
state.error = null;
|
|
55
|
+
let awaitablePromise = awaitableWithCancel();
|
|
56
|
+
state.active = true;
|
|
57
|
+
state.resolving = true;
|
|
58
|
+
if (awaitablePromise.cancel) {
|
|
59
|
+
cancelFunction = async () => {
|
|
60
|
+
state.active = false;
|
|
61
|
+
state.resolving = false;
|
|
62
|
+
cancelFunction = null;
|
|
63
|
+
return awaitablePromise.cancel();
|
|
64
|
+
};
|
|
83
65
|
}
|
|
84
|
-
|
|
66
|
+
awaitablePromise
|
|
67
|
+
.then(() => {
|
|
68
|
+
state.resolving = false;
|
|
69
|
+
if (state.clearActiveOnResolved) {
|
|
70
|
+
cancelFunction = null;
|
|
71
|
+
state.active = false;
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.catch(async (err) => {
|
|
75
|
+
await cancel();
|
|
76
|
+
console.error(err);
|
|
77
|
+
state.errored = true;
|
|
78
|
+
state.error = err;
|
|
79
|
+
throw err;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
es.run(() => {
|
|
85
|
+
watch(() => Object.values(watchArguments), watchFn, {
|
|
86
|
+
// this can't be immediate because subscribe wants to look at our state, which won't exist yet.
|
|
87
|
+
deep: true,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
nextTick().then(watchFn);
|
|
85
91
|
|
|
86
92
|
onScopeDispose(cancel);
|
|
87
93
|
});
|
|
88
94
|
return {
|
|
89
95
|
state,
|
|
96
|
+
watchArguments: readonly(watchArguments),
|
|
90
97
|
stop,
|
|
91
98
|
cancel,
|
|
92
99
|
};
|
package/use/list.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { effectScope, shallowReactive, shallowReadonly, toRef, watch } from "vue";
|
|
1
|
+
import { effectScope, reactive, shallowReactive, shallowReadonly, toRef, watch } from "vue";
|
|
2
2
|
import { useListCalculated } from "./listCalculated";
|
|
3
3
|
import { useListInstance } from "./listInstance";
|
|
4
4
|
import { useListRelated } from "./listRelated";
|
|
5
5
|
import { useListSubscription } from "./listSubscription";
|
|
6
|
+
import { usePagedListInstance } from "./paginatedListInstance";
|
|
6
7
|
|
|
7
8
|
// the big brother of useObject, managing a chain of useList* instances.
|
|
8
|
-
export const useList = ({ props, functions }) => {
|
|
9
|
+
export const useList = ({ props, functions, paged = false }) => {
|
|
9
10
|
const managed = shallowReactive({
|
|
10
11
|
listInstance: null,
|
|
11
12
|
listSubscription: null,
|
|
@@ -14,7 +15,7 @@ export const useList = ({ props, functions }) => {
|
|
|
14
15
|
});
|
|
15
16
|
const es = effectScope();
|
|
16
17
|
|
|
17
|
-
managed.listInstance = useListInstance({
|
|
18
|
+
managed.listInstance = (paged ? usePagedListInstance : useListInstance)({
|
|
18
19
|
crudArgs: toRef(props, "crudArgs"),
|
|
19
20
|
functions,
|
|
20
21
|
retrieveArgs: toRef(props, "retrieveArgs"),
|
|
@@ -60,7 +61,7 @@ export const useList = ({ props, functions }) => {
|
|
|
60
61
|
});
|
|
61
62
|
};
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
const exposedState = reactive({});
|
|
64
65
|
|
|
65
66
|
es.run(() => {
|
|
66
67
|
watch(
|
|
@@ -73,31 +74,40 @@ export const useList = ({ props, functions }) => {
|
|
|
73
74
|
intentPropsWatch,
|
|
74
75
|
{ immediate: true }
|
|
75
76
|
);
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
77
|
+
const propertiesToRelay = [
|
|
78
|
+
"loading",
|
|
79
|
+
"error",
|
|
80
|
+
"errored",
|
|
81
|
+
"objects",
|
|
82
|
+
"order",
|
|
83
|
+
"objectsInOrder",
|
|
84
|
+
"running",
|
|
85
|
+
"relatedObjects",
|
|
86
|
+
"calculatedObjects",
|
|
87
|
+
];
|
|
88
|
+
watch(
|
|
89
|
+
() =>
|
|
90
|
+
managed.listCalculated?.state ||
|
|
91
|
+
managed.listRelated?.state ||
|
|
92
|
+
managed.listSubscription?.state ||
|
|
93
|
+
managed.listInstance?.state,
|
|
94
|
+
(newState, oldState) => {
|
|
95
|
+
if (newState !== oldState && newState) {
|
|
96
|
+
propertiesToRelay.forEach((x) => {
|
|
97
|
+
exposedState[x] = toRef(newState, x);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
94
100
|
},
|
|
95
|
-
|
|
101
|
+
{
|
|
102
|
+
immediate: true,
|
|
103
|
+
}
|
|
104
|
+
);
|
|
96
105
|
});
|
|
97
106
|
|
|
98
107
|
return {
|
|
108
|
+
// we manage the keys on both of these, so hands off the root.
|
|
99
109
|
managed: shallowReadonly(managed),
|
|
100
|
-
state: exposedState,
|
|
110
|
+
state: shallowReadonly(exposedState),
|
|
101
111
|
effectScope: es,
|
|
102
112
|
};
|
|
103
113
|
};
|
package/use/listCalculated.js
CHANGED
|
@@ -19,11 +19,11 @@ export function useListCalculated({
|
|
|
19
19
|
parentState,
|
|
20
20
|
calculatedObjectsRules,
|
|
21
21
|
calculatedObjectsPropertyName = "calculatedObjects", // NOT REACTIVE
|
|
22
|
+
passThroughPropertyNames = ["relatedObjects"], // NOT REACTIVE
|
|
22
23
|
}) {
|
|
23
24
|
const state = reactive({
|
|
24
25
|
calculatedObjectsRules,
|
|
25
26
|
calculatedObjectsObjects: {},
|
|
26
|
-
objects: {},
|
|
27
27
|
parentStateObjectsWatchRunning: false,
|
|
28
28
|
calculatedObjectsWatchRunning: false,
|
|
29
29
|
});
|
|
@@ -39,7 +39,6 @@ export function useListCalculated({
|
|
|
39
39
|
);
|
|
40
40
|
for (const removedKey of removedKeys) {
|
|
41
41
|
delete state.calculatedObjectsObjects[removedKey];
|
|
42
|
-
delete state.objects[removedKey];
|
|
43
42
|
if (calculatedObjectsEffectScopes[removedKey]) {
|
|
44
43
|
calculatedObjectsEffectScopes[removedKey].stop();
|
|
45
44
|
delete calculatedObjectsEffectScopes[removedKey];
|
|
@@ -47,63 +46,46 @@ export function useListCalculated({
|
|
|
47
46
|
}
|
|
48
47
|
for (const addedKey of addedKeys) {
|
|
49
48
|
state.calculatedObjectsObjects[addedKey] = {};
|
|
50
|
-
state.objects[addedKey] = new Proxy(parentState.objects[addedKey], {
|
|
51
|
-
get(target, prop, receiver) {
|
|
52
|
-
if (prop === copn) {
|
|
53
|
-
return state.calculatedObjectsObjects[addedKey];
|
|
54
|
-
}
|
|
55
|
-
return Reflect.get(target, prop, receiver);
|
|
56
|
-
},
|
|
57
|
-
ownKeys(target) {
|
|
58
|
-
return Reflect.ownKeys(target).concat(copn);
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
49
|
}
|
|
62
50
|
state.parentStateObjectsWatchRunning = false;
|
|
63
51
|
}
|
|
64
52
|
|
|
65
53
|
function calculatedObjectsWatch() {
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const calculatedObjectsRulesIsEmpty = isEmpty(state.calculatedObjectsRules);
|
|
54
|
+
const calculatedObjectsRulesIsEmpty = !state.calculatedObjectsRules || isEmpty(state.calculatedObjectsRules);
|
|
70
55
|
for (const objectKey of Object.keys(state.calculatedObjectsObjects)) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
removedRuleKeys = Object.keys(calculatedObjectsObject[copn]);
|
|
89
|
-
addedRuleKeys = [];
|
|
90
|
-
}
|
|
91
|
-
for (const removedRuleKey of removedRuleKeys) {
|
|
92
|
-
delete calculatedObjectsObject[copn][removedRuleKey];
|
|
56
|
+
if (!calculatedObjectsEffectScopes[objectKey]) {
|
|
57
|
+
calculatedObjectsEffectScopes[objectKey] = effectScope();
|
|
58
|
+
}
|
|
59
|
+
const originalObject = parentState.objects[objectKey];
|
|
60
|
+
if (!state.calculatedObjectsObjects[objectKey]) {
|
|
61
|
+
state.calculatedObjectsObjects[objectKey] = {};
|
|
62
|
+
}
|
|
63
|
+
const calculatedObjectsObject = state.calculatedObjectsObjects[objectKey];
|
|
64
|
+
let removedRuleKeys, addedRuleKeys;
|
|
65
|
+
if (!calculatedObjectsRulesIsEmpty) {
|
|
66
|
+
({ removedKeys: removedRuleKeys, addedKeys: addedRuleKeys } = keyDiff(
|
|
67
|
+
Object.keys(state.calculatedObjectsRules),
|
|
68
|
+
Object.keys(calculatedObjectsObject)
|
|
69
|
+
));
|
|
70
|
+
} else {
|
|
71
|
+
if (isEmpty(calculatedObjectsObject)) {
|
|
72
|
+
return;
|
|
93
73
|
}
|
|
74
|
+
removedRuleKeys = Object.keys(calculatedObjectsObject);
|
|
75
|
+
addedRuleKeys = [];
|
|
76
|
+
}
|
|
77
|
+
for (const removedRuleKey of removedRuleKeys) {
|
|
78
|
+
delete calculatedObjectsObject[removedRuleKey];
|
|
79
|
+
}
|
|
80
|
+
calculatedObjectsEffectScopes[objectKey].run(() => {
|
|
94
81
|
for (const addedRuleKey of addedRuleKeys) {
|
|
95
|
-
calculatedObjectsObject[
|
|
82
|
+
calculatedObjectsObject[addedRuleKey] = computed(() => {
|
|
96
83
|
return state.calculatedObjectsRules?.[addedRuleKey]?.(originalObject);
|
|
97
84
|
});
|
|
98
85
|
}
|
|
99
86
|
});
|
|
100
|
-
if (calculatedObjectsEffectScopes[objectKey]) {
|
|
101
|
-
calculatedObjectsEffectScopes[objectKey].stop();
|
|
102
|
-
}
|
|
103
|
-
calculatedObjectsEffectScopes[objectKey] = calculatedObjectsEffectScope;
|
|
104
87
|
}
|
|
105
88
|
state.calculatedObjectsWatchRunning = false;
|
|
106
|
-
parentStateObjectsWatch();
|
|
107
89
|
}
|
|
108
90
|
|
|
109
91
|
let watchesRunning = null;
|
|
@@ -118,7 +100,12 @@ export function useListCalculated({
|
|
|
118
100
|
state.retrieveArgs = toRef(parentState, "retrieveArgs");
|
|
119
101
|
state.listArgs = toRef(parentState, "listArgs");
|
|
120
102
|
state.order = toRef(parentState, "order");
|
|
121
|
-
state.
|
|
103
|
+
state.objects = toRef(parentState, "objects");
|
|
104
|
+
state.objectsInOrder = toRef(parentState, "objectsInOrder");
|
|
105
|
+
state[copn] = toRef(state, "calculatedObjectsObjects");
|
|
106
|
+
for (let key in passThroughPropertyNames) {
|
|
107
|
+
state[key] = toRef(parentState, key);
|
|
108
|
+
}
|
|
122
109
|
|
|
123
110
|
watch(() => Object.keys(parentState.objects), parentStateObjectsWatch, { immediate: true });
|
|
124
111
|
watch(
|
|
@@ -134,7 +121,11 @@ export function useListCalculated({
|
|
|
134
121
|
);
|
|
135
122
|
|
|
136
123
|
watchesRunning = useWatchesRunning({
|
|
137
|
-
triggerRefs: [
|
|
124
|
+
triggerRefs: [
|
|
125
|
+
computed(() =>
|
|
126
|
+
state.calculatedObjectsRules && !isEmpty(state.calculatedObjectsRules) ? parentState.loading : false
|
|
127
|
+
),
|
|
128
|
+
],
|
|
138
129
|
watchSentinelRefs: [
|
|
139
130
|
toRef(state, "parentStateObjectsWatchRunning"),
|
|
140
131
|
toRef(state, "calculatedObjectsWatchRunning"),
|
package/use/listRelated.js
CHANGED
|
@@ -16,11 +16,11 @@ export function useListRelated({
|
|
|
16
16
|
parentState,
|
|
17
17
|
relatedObjectsRules,
|
|
18
18
|
relatedObjectsPropertyName = "relatedObjects", // NOT REACTIVE
|
|
19
|
+
passThroughPropertyNames = ["calculatedObjects"], // NOT REACTIVE
|
|
19
20
|
}) {
|
|
20
21
|
const state = reactive({
|
|
21
22
|
relatedObjectsRules: relatedObjectsRules,
|
|
22
23
|
relatedObjectsObjects: {},
|
|
23
|
-
objects: {},
|
|
24
24
|
parentStateObjectsWatchRunning: false,
|
|
25
25
|
relatedObjectsWatchRunning: false,
|
|
26
26
|
});
|
|
@@ -36,7 +36,6 @@ export function useListRelated({
|
|
|
36
36
|
);
|
|
37
37
|
for (const removedKey of removedKeys) {
|
|
38
38
|
delete state.relatedObjectsObjects[removedKey];
|
|
39
|
-
delete state.objects[removedKey];
|
|
40
39
|
if (relatedObjectsEffectScopes[removedKey]) {
|
|
41
40
|
relatedObjectsEffectScopes[removedKey].stop();
|
|
42
41
|
delete relatedObjectsEffectScopes[removedKey];
|
|
@@ -44,69 +43,35 @@ export function useListRelated({
|
|
|
44
43
|
}
|
|
45
44
|
for (const addedKey of addedKeys) {
|
|
46
45
|
state.relatedObjectsObjects[addedKey] = {};
|
|
47
|
-
state.objects[addedKey] = new Proxy(parentState.objects[addedKey], {
|
|
48
|
-
get(target, prop, receiver) {
|
|
49
|
-
if (prop === ropn) {
|
|
50
|
-
return state.relatedObjectsObjects[addedKey];
|
|
51
|
-
}
|
|
52
|
-
return Reflect.get(target, prop, receiver);
|
|
53
|
-
},
|
|
54
|
-
ownKeys(target) {
|
|
55
|
-
return Reflect.ownKeys(target).concat(ropn);
|
|
56
|
-
},
|
|
57
|
-
has(target, prop) {
|
|
58
|
-
if (prop === ropn) {
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
return Reflect.has(target, prop);
|
|
62
|
-
},
|
|
63
|
-
getOwnPropertyDescriptor(target, p) {
|
|
64
|
-
if (p === ropn) {
|
|
65
|
-
return {
|
|
66
|
-
configurable: true,
|
|
67
|
-
enumerable: true,
|
|
68
|
-
value: state.relatedObjectsObjects[addedKey],
|
|
69
|
-
writable: true,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
return Reflect.getOwnPropertyDescriptor(target, p);
|
|
73
|
-
},
|
|
74
|
-
defineProperty() {
|
|
75
|
-
return false;
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
46
|
}
|
|
47
|
+
state.parentStateObjectsWatchRunning = false;
|
|
79
48
|
}
|
|
80
49
|
|
|
81
50
|
function relatedObjectsWatch() {
|
|
82
|
-
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const relatedObjectsRulesIsEmpty = isEmpty(state.relatedObjectsRules);
|
|
51
|
+
const relatedObjectsRulesIsEmpty = !state.relatedObjectsRules || isEmpty(state.relatedObjectsRules);
|
|
86
52
|
for (const objectKey of Object.keys(state.relatedObjectsObjects)) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Object.keys(relatedObjectsObject)
|
|
99
|
-
));
|
|
100
|
-
} else {
|
|
101
|
-
if (isEmpty(relatedObjectsObject)) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
removedRuleKeys = Object.keys(relatedObjectsObject);
|
|
105
|
-
addedRuleKeys = [];
|
|
106
|
-
}
|
|
107
|
-
for (const removedRuleKey of removedRuleKeys) {
|
|
108
|
-
delete relatedObjectsObject[removedRuleKey];
|
|
53
|
+
const relatedObjectsObject = state.relatedObjectsObjects[objectKey];
|
|
54
|
+
const originalObject = parentState.objects[objectKey];
|
|
55
|
+
let removedRuleKeys, addedRuleKeys;
|
|
56
|
+
if (!relatedObjectsRulesIsEmpty) {
|
|
57
|
+
({ removedKeys: removedRuleKeys, addedKeys: addedRuleKeys } = keyDiff(
|
|
58
|
+
Object.keys(state.relatedObjectsRules),
|
|
59
|
+
Object.keys(relatedObjectsObject)
|
|
60
|
+
));
|
|
61
|
+
} else {
|
|
62
|
+
if (isEmpty(relatedObjectsObject)) {
|
|
63
|
+
return;
|
|
109
64
|
}
|
|
65
|
+
removedRuleKeys = Object.keys(relatedObjectsObject);
|
|
66
|
+
addedRuleKeys = [];
|
|
67
|
+
}
|
|
68
|
+
for (const removedRuleKey of removedRuleKeys) {
|
|
69
|
+
delete relatedObjectsObject[removedRuleKey];
|
|
70
|
+
}
|
|
71
|
+
if (!relatedObjectsEffectScopes[objectKey]) {
|
|
72
|
+
relatedObjectsEffectScopes[objectKey] = effectScope();
|
|
73
|
+
}
|
|
74
|
+
relatedObjectsEffectScopes[objectKey].run(() => {
|
|
110
75
|
for (const addedRuleKey of addedRuleKeys) {
|
|
111
76
|
relatedObjectsObject[addedRuleKey] = computed(() => {
|
|
112
77
|
// deal with computed objects being passed.
|
|
@@ -126,9 +91,8 @@ export function useListRelated({
|
|
|
126
91
|
});
|
|
127
92
|
}
|
|
128
93
|
});
|
|
129
|
-
relatedObjectsEffectScopes[objectKey] = relatedObjectsEffectScope;
|
|
130
94
|
}
|
|
131
|
-
|
|
95
|
+
state.relatedObjectsWatchRunning = false;
|
|
132
96
|
}
|
|
133
97
|
|
|
134
98
|
let watchesRunning = null;
|
|
@@ -143,7 +107,12 @@ export function useListRelated({
|
|
|
143
107
|
state.retrieveArgs = toRef(parentState, "retrieveArgs");
|
|
144
108
|
state.listArgs = toRef(parentState, "listArgs");
|
|
145
109
|
state.order = toRef(parentState, "order");
|
|
146
|
-
state.
|
|
110
|
+
state.objects = toRef(parentState, "objects");
|
|
111
|
+
state.objectsInOrder = toRef(parentState, "objectsInOrder");
|
|
112
|
+
state[ropn] = toRef(state, "relatedObjectsObjects");
|
|
113
|
+
for (let key in passThroughPropertyNames) {
|
|
114
|
+
state[key] = toRef(parentState, key);
|
|
115
|
+
}
|
|
147
116
|
|
|
148
117
|
watch(() => Object.keys(parentState.objects), parentStateObjectsWatch, { immediate: true });
|
|
149
118
|
watch(
|
|
@@ -156,7 +125,11 @@ export function useListRelated({
|
|
|
156
125
|
);
|
|
157
126
|
|
|
158
127
|
watchesRunning = useWatchesRunning({
|
|
159
|
-
triggerRefs: [
|
|
128
|
+
triggerRefs: [
|
|
129
|
+
computed(() =>
|
|
130
|
+
state.relatedObjectsRules && !isEmpty(state.relatedObjectsRules) ? parentState.loading : false
|
|
131
|
+
),
|
|
132
|
+
],
|
|
160
133
|
watchSentinelRefs: [
|
|
161
134
|
toRef(state, "parentStateObjectsWatchRunning"),
|
|
162
135
|
toRef(state, "relatedObjectsWatchRunning"),
|
package/use/listSubscription.js
CHANGED
|
@@ -167,11 +167,11 @@ export function useListSubscription({ listInstance, crudArgs, listArgs, retrieve
|
|
|
167
167
|
catchPromise.cancel = subscribePromise.cancel;
|
|
168
168
|
return catchPromise;
|
|
169
169
|
},
|
|
170
|
-
watchArguments:
|
|
171
|
-
toRef(state, "intendToSubscribe"),
|
|
172
|
-
toRef(listInstance.state, "listArgs"),
|
|
173
|
-
toRef(state, "retrieveArgs"),
|
|
174
|
-
|
|
170
|
+
watchArguments: reactive({
|
|
171
|
+
intendToSubscribe: toRef(state, "intendToSubscribe"),
|
|
172
|
+
listArgs: toRef(listInstance.state, "listArgs"),
|
|
173
|
+
retrieveArgs: toRef(listInstance.state, "retrieveArgs"),
|
|
174
|
+
}),
|
|
175
175
|
clearActiveOnResolved: false,
|
|
176
176
|
});
|
|
177
177
|
|
|
@@ -182,12 +182,11 @@ export function useListSubscription({ listInstance, crudArgs, listArgs, retrieve
|
|
|
182
182
|
listInstance.clearList();
|
|
183
183
|
return listInstance.list();
|
|
184
184
|
},
|
|
185
|
-
watchArguments:
|
|
186
|
-
toRef(state, "intendToList"),
|
|
187
|
-
toRef(listInstance.state, "listArgs"),
|
|
188
|
-
toRef(state, "retrieveArgs"),
|
|
189
|
-
|
|
190
|
-
nameOnLog: "listIntent",
|
|
185
|
+
watchArguments: reactive({
|
|
186
|
+
intendToList: toRef(state, "intendToList"),
|
|
187
|
+
listArgs: toRef(listInstance.state, "listArgs"),
|
|
188
|
+
retrieveArgs: toRef(listInstance.state, "retrieveArgs"),
|
|
189
|
+
}),
|
|
191
190
|
});
|
|
192
191
|
});
|
|
193
192
|
|
package/use/object.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { effectScope, shallowReactive, shallowReadonly, toRef, watch } from "vue";
|
|
1
|
+
import { effectScope, reactive, shallowReactive, shallowReadonly, toRef, watch } from "vue";
|
|
2
2
|
import { useObjectCalculated } from "./objectCalculated";
|
|
3
3
|
import { useObjectInstance } from "./objectInstance";
|
|
4
4
|
import { useObjectRelated } from "./objectRelated";
|
|
@@ -60,7 +60,7 @@ export const useObject = ({ props, functions }) => {
|
|
|
60
60
|
});
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
const exposedState = reactive({});
|
|
64
64
|
|
|
65
65
|
es.run(() => {
|
|
66
66
|
watch(
|
|
@@ -72,30 +72,39 @@ export const useObject = ({ props, functions }) => {
|
|
|
72
72
|
intentPropsWatch,
|
|
73
73
|
{ immediate: true }
|
|
74
74
|
);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
75
|
+
|
|
76
|
+
const propertiesToRelay = [
|
|
77
|
+
"loading",
|
|
78
|
+
"error",
|
|
79
|
+
"errored",
|
|
80
|
+
"object",
|
|
81
|
+
"running",
|
|
82
|
+
"relatedObject",
|
|
83
|
+
"calculatedObject",
|
|
84
|
+
];
|
|
85
|
+
watch(
|
|
86
|
+
() =>
|
|
87
|
+
managed.objectCalculated?.state ||
|
|
88
|
+
managed.objectRelated?.state ||
|
|
89
|
+
managed.objectSubscription?.state ||
|
|
90
|
+
managed.objectInstance.state,
|
|
91
|
+
(newState, oldState) => {
|
|
92
|
+
if (newState !== oldState && newState) {
|
|
93
|
+
propertiesToRelay.forEach((x) => {
|
|
94
|
+
exposedState[x] = toRef(newState, x);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
92
97
|
},
|
|
93
|
-
|
|
98
|
+
{
|
|
99
|
+
immediate: true,
|
|
100
|
+
}
|
|
101
|
+
);
|
|
94
102
|
});
|
|
95
103
|
|
|
96
104
|
return {
|
|
105
|
+
// we manage the keys on both of these, so hands off the root.
|
|
97
106
|
managed: shallowReadonly(managed),
|
|
98
|
-
state: exposedState,
|
|
107
|
+
state: shallowReadonly(exposedState),
|
|
99
108
|
effectScope: es,
|
|
100
109
|
};
|
|
101
110
|
};
|
package/use/objectCalculated.js
CHANGED
|
@@ -17,11 +17,11 @@ export function useObjectCalculated({
|
|
|
17
17
|
parentState,
|
|
18
18
|
calculatedObjectRules,
|
|
19
19
|
calculatedObjectPropertyName = "calculatedObject", // NOT REACTIVE
|
|
20
|
+
passThroughPropertyNames = ["relatedObject"], // NOT REACTIVE
|
|
20
21
|
}) {
|
|
21
22
|
const state = reactive({
|
|
22
23
|
calculatedObjectRules,
|
|
23
24
|
calculatedObjectObjects: {},
|
|
24
|
-
object: {},
|
|
25
25
|
parentStateObjectWatchRunning: false,
|
|
26
26
|
calculatedObjectWatchRunning: false,
|
|
27
27
|
});
|
|
@@ -36,41 +36,15 @@ export function useObjectCalculated({
|
|
|
36
36
|
const es = effectScope();
|
|
37
37
|
|
|
38
38
|
es.run(() => {
|
|
39
|
-
state.object = new Proxy(parentState.object, {
|
|
40
|
-
get(target, key, receiver) {
|
|
41
|
-
if (key === copn) {
|
|
42
|
-
return state.calculatedObjectObjects;
|
|
43
|
-
}
|
|
44
|
-
return Reflect.get(target, key, receiver);
|
|
45
|
-
},
|
|
46
|
-
ownKeys(target) {
|
|
47
|
-
return Reflect.ownKeys(target).concat(copn);
|
|
48
|
-
},
|
|
49
|
-
has(target, key) {
|
|
50
|
-
if (key === copn) {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
return Reflect.has(target, key);
|
|
54
|
-
},
|
|
55
|
-
getOwnPropertyDescriptor(target, key) {
|
|
56
|
-
if (key === copn) {
|
|
57
|
-
return {
|
|
58
|
-
configurable: true,
|
|
59
|
-
enumerable: true,
|
|
60
|
-
value: state.calculatedObjectObjects,
|
|
61
|
-
writable: true,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
65
|
-
},
|
|
66
|
-
defineProperty() {
|
|
67
|
-
return false;
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
39
|
state.loading = toRef(parentState, "loading");
|
|
71
40
|
state.error = toRef(parentState, "error");
|
|
72
41
|
state.errored = toRef(parentState, "errored");
|
|
73
42
|
state.deleted = toRef(parentState, "deleted");
|
|
43
|
+
state.object = toRef(parentState, "object");
|
|
44
|
+
state[copn] = toRef(state, "calculatedObjectObjects");
|
|
45
|
+
for (let key in passThroughPropertyNames) {
|
|
46
|
+
state[key] = toRef(parentState, key);
|
|
47
|
+
}
|
|
74
48
|
|
|
75
49
|
watch([() => state.calculatedObjectRules && Object.keys(state.calculatedObjectRules)], () => {
|
|
76
50
|
let addedKeys = [],
|
package/use/objectRelated.js
CHANGED
|
@@ -17,11 +17,11 @@ export function useObjectRelated({
|
|
|
17
17
|
parentState,
|
|
18
18
|
relatedObjectRules,
|
|
19
19
|
relatedObjectPropertyName = "relatedObject", // NOT REACTIVE
|
|
20
|
+
passThroughPropertyNames = ["calculatedObject"], // NOT REACTIVE
|
|
20
21
|
}) {
|
|
21
22
|
const state = reactive({
|
|
22
23
|
relatedObjectRules,
|
|
23
24
|
relatedObjectObjects: {},
|
|
24
|
-
object: {},
|
|
25
25
|
parentStateObjectWatchRunning: false,
|
|
26
26
|
relatedObjectWatchRunning: false,
|
|
27
27
|
});
|
|
@@ -35,41 +35,15 @@ export function useObjectRelated({
|
|
|
35
35
|
const es = effectScope();
|
|
36
36
|
|
|
37
37
|
es.run(() => {
|
|
38
|
-
state.object = new Proxy(parentState.object, {
|
|
39
|
-
get(target, key, receiver) {
|
|
40
|
-
if (key === ropn) {
|
|
41
|
-
return state.relatedObjectObjects;
|
|
42
|
-
}
|
|
43
|
-
return Reflect.get(target, key, receiver);
|
|
44
|
-
},
|
|
45
|
-
ownKeys(target) {
|
|
46
|
-
return Reflect.ownKeys(target).concat(ropn);
|
|
47
|
-
},
|
|
48
|
-
has(target, key) {
|
|
49
|
-
if (key === ropn) {
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
return Reflect.has(target, key);
|
|
53
|
-
},
|
|
54
|
-
getOwnPropertyDescriptor(target, key) {
|
|
55
|
-
if (key === ropn) {
|
|
56
|
-
return {
|
|
57
|
-
configurable: true,
|
|
58
|
-
enumerable: true,
|
|
59
|
-
value: state.relatedObjectObjects,
|
|
60
|
-
writable: true,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
64
|
-
},
|
|
65
|
-
defineProperty() {
|
|
66
|
-
return false;
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
38
|
state.loading = toRef(parentState, "loading");
|
|
70
39
|
state.error = toRef(parentState, "error");
|
|
71
40
|
state.errored = toRef(parentState, "errored");
|
|
72
41
|
state.deleted = toRef(parentState, "deleted");
|
|
42
|
+
state.object = toRef(parentState, "object");
|
|
43
|
+
state[ropn] = toRef(state, "relatedObjectObjects");
|
|
44
|
+
for (let key in passThroughPropertyNames) {
|
|
45
|
+
state[key] = toRef(parentState, key);
|
|
46
|
+
}
|
|
73
47
|
|
|
74
48
|
watch([() => state.relatedObjectRules && Object.keys(state.relatedObjectRules)], () => {
|
|
75
49
|
let addedRuleKeys = [],
|
|
@@ -155,22 +155,21 @@ export function useObjectSubscription({ objectInstance, crudArgs, id, retrieveAr
|
|
|
155
155
|
|
|
156
156
|
subscribeIntent = useCancellableIntent({
|
|
157
157
|
awaitableWithCancel: subscribe,
|
|
158
|
-
watchArguments:
|
|
159
|
-
toRef(state, "intendToSubscribe"),
|
|
160
|
-
toRef(objectInstance.state, "id"),
|
|
161
|
-
toRef(state, "retrieveArgs"),
|
|
162
|
-
|
|
158
|
+
watchArguments: reactive({
|
|
159
|
+
intendToSubscribe: toRef(state, "intendToSubscribe"),
|
|
160
|
+
listArgs: toRef(objectInstance.state, "id"),
|
|
161
|
+
retrieveArgs: toRef(objectInstance.state, "retrieveArgs"),
|
|
162
|
+
}),
|
|
163
163
|
clearActiveOnResolved: false,
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
retrieveIntent = useCancellableIntent({
|
|
167
167
|
awaitableWithCancel: objectInstance.retrieve,
|
|
168
|
-
watchArguments:
|
|
169
|
-
toRef(state, "intendToRetrieve"),
|
|
170
|
-
toRef(objectInstance.state, "id"),
|
|
171
|
-
toRef(state, "retrieveArgs"),
|
|
172
|
-
|
|
173
|
-
nameForLog: "retrieveIntent",
|
|
168
|
+
watchArguments: reactive({
|
|
169
|
+
intendToSubscribe: toRef(state, "intendToRetrieve"),
|
|
170
|
+
listArgs: toRef(objectInstance.state, "id"),
|
|
171
|
+
retrieveArgs: toRef(objectInstance.state, "retrieveArgs"),
|
|
172
|
+
}),
|
|
174
173
|
});
|
|
175
174
|
});
|
|
176
175
|
|
package/utils/index.js
CHANGED
package/utils/watches.js
CHANGED
|
@@ -42,6 +42,8 @@ export class AwaitTimeout {
|
|
|
42
42
|
});
|
|
43
43
|
this.timeout = timeout;
|
|
44
44
|
this.timeoutId = null;
|
|
45
|
+
// prebuild the exception for a more useful stack.
|
|
46
|
+
this.cancelledError = new AwaitTimeoutError("Cancelled", "timeout_cancelled");
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
start() {
|
|
@@ -65,7 +67,7 @@ export class AwaitTimeout {
|
|
|
65
67
|
if (this.timeoutId) {
|
|
66
68
|
clearTimeout(this.timeoutId);
|
|
67
69
|
delete this.timeoutId;
|
|
68
|
-
this.reject(
|
|
70
|
+
this.reject(this.cancelledError);
|
|
69
71
|
}
|
|
70
72
|
if (this.resolve) {
|
|
71
73
|
delete this.resolve;
|
|
@@ -94,13 +96,15 @@ export class AwaitNot {
|
|
|
94
96
|
this.prop = prop;
|
|
95
97
|
this.trueISW = new ImmediateStopWatch();
|
|
96
98
|
this.falseISW = new ImmediateStopWatch();
|
|
99
|
+
// prebuild the exception for a more useful stack.
|
|
100
|
+
this.timeoutError = new AwaitNotError("Timeout", "timeout");
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
start() {
|
|
100
104
|
this.timeout.promise
|
|
101
105
|
.then(() => {
|
|
102
106
|
this.stop();
|
|
103
|
-
this.reject(
|
|
107
|
+
this.reject(this.timeoutError);
|
|
104
108
|
})
|
|
105
109
|
.catch((err) => {
|
|
106
110
|
this.stop();
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { reactive, ref, toRef, unref } from "vue";
|
|
2
|
-
import { circular, unrefAndToRawDeep } from "../../../utils";
|
|
3
|
-
|
|
4
|
-
describe("unrefAndToRawDeep", () => {
|
|
5
|
-
it("should unref refs", () => {
|
|
6
|
-
const obj = {
|
|
7
|
-
a: ref(1),
|
|
8
|
-
b: ref(true),
|
|
9
|
-
c: ref("foo"),
|
|
10
|
-
d: ref(null),
|
|
11
|
-
};
|
|
12
|
-
expect(unrefAndToRawDeep(obj)).toEqual({
|
|
13
|
-
a: 1,
|
|
14
|
-
b: true,
|
|
15
|
-
c: "foo",
|
|
16
|
-
d: null,
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
it("should toRaw reactive", () => {
|
|
20
|
-
const obj = {
|
|
21
|
-
state: reactive({
|
|
22
|
-
a: 1,
|
|
23
|
-
b: true,
|
|
24
|
-
c: "foo",
|
|
25
|
-
d: null,
|
|
26
|
-
}),
|
|
27
|
-
parentState: reactive({
|
|
28
|
-
a: 1,
|
|
29
|
-
b: true,
|
|
30
|
-
c: "foo",
|
|
31
|
-
d: null,
|
|
32
|
-
}),
|
|
33
|
-
};
|
|
34
|
-
expect(unrefAndToRawDeep(obj)).toEqual({
|
|
35
|
-
state: {
|
|
36
|
-
a: 1,
|
|
37
|
-
b: true,
|
|
38
|
-
c: "foo",
|
|
39
|
-
d: null,
|
|
40
|
-
},
|
|
41
|
-
parentState: {
|
|
42
|
-
a: 1,
|
|
43
|
-
b: true,
|
|
44
|
-
c: "foo",
|
|
45
|
-
d: null,
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
it("should handle arrays", () => {
|
|
50
|
-
const arr = [ref(1), ref(true), ref("foo"), ref(null)];
|
|
51
|
-
const arr2 = [
|
|
52
|
-
reactive({
|
|
53
|
-
a: 1,
|
|
54
|
-
b: true,
|
|
55
|
-
c: "foo",
|
|
56
|
-
d: null,
|
|
57
|
-
}),
|
|
58
|
-
reactive({
|
|
59
|
-
a: 2,
|
|
60
|
-
b: false,
|
|
61
|
-
c: "bar",
|
|
62
|
-
d: NaN,
|
|
63
|
-
}),
|
|
64
|
-
];
|
|
65
|
-
expect(unrefAndToRawDeep(arr)).toEqual([1, true, "foo", null]);
|
|
66
|
-
expect(unrefAndToRawDeep(arr2)).toEqual([
|
|
67
|
-
{
|
|
68
|
-
a: 1,
|
|
69
|
-
b: true,
|
|
70
|
-
c: "foo",
|
|
71
|
-
d: null,
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
a: 2,
|
|
75
|
-
|
|
76
|
-
b: false,
|
|
77
|
-
c: "bar",
|
|
78
|
-
d: NaN,
|
|
79
|
-
},
|
|
80
|
-
]);
|
|
81
|
-
});
|
|
82
|
-
it("should toRaw reactive with circular ref", () => {
|
|
83
|
-
const state = reactive({
|
|
84
|
-
objects: {
|
|
85
|
-
1: {
|
|
86
|
-
id: 1,
|
|
87
|
-
name: "one",
|
|
88
|
-
parent: 2,
|
|
89
|
-
children: [],
|
|
90
|
-
refProperty: ref(null),
|
|
91
|
-
},
|
|
92
|
-
2: {
|
|
93
|
-
id: 2,
|
|
94
|
-
name: "two",
|
|
95
|
-
parent: null,
|
|
96
|
-
children: [1],
|
|
97
|
-
refProperty: ref(null),
|
|
98
|
-
},
|
|
99
|
-
3: {
|
|
100
|
-
id: 3,
|
|
101
|
-
name: "three",
|
|
102
|
-
parent: null,
|
|
103
|
-
children: [],
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
state.objects["1"].relatedObjects = reactive({
|
|
108
|
-
parent: toRef(state.objects, "2"),
|
|
109
|
-
});
|
|
110
|
-
state.objects["2"].relatedObjects = reactive({
|
|
111
|
-
children: [toRef(state.objects, "1")],
|
|
112
|
-
});
|
|
113
|
-
state.objects["1"].refProperty = toRef(state.objects["3"], "name");
|
|
114
|
-
state.objects["2"].refProperty = toRef(state.objects["3"], "name");
|
|
115
|
-
expect(state.objects["1"]).toBe(unref(state.objects["2"].relatedObjects.children[0]));
|
|
116
|
-
expect(state.objects["2"]).toBe(state.objects["1"].relatedObjects.parent);
|
|
117
|
-
expect(state.objects["1"].refProperty).toBe(state.objects["3"].name);
|
|
118
|
-
expect(state.objects["2"].refProperty).toBe(state.objects["3"].name);
|
|
119
|
-
expect(unrefAndToRawDeep(state)).toEqual({
|
|
120
|
-
objects: {
|
|
121
|
-
1: {
|
|
122
|
-
id: 1,
|
|
123
|
-
name: "one",
|
|
124
|
-
parent: 2,
|
|
125
|
-
children: [],
|
|
126
|
-
refProperty: "three",
|
|
127
|
-
relatedObjects: {
|
|
128
|
-
parent: {
|
|
129
|
-
id: 2,
|
|
130
|
-
name: "two",
|
|
131
|
-
parent: null,
|
|
132
|
-
children: [1],
|
|
133
|
-
refProperty: "three",
|
|
134
|
-
relatedObjects: {
|
|
135
|
-
children: [circular],
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
2: {
|
|
141
|
-
id: 2,
|
|
142
|
-
name: "two",
|
|
143
|
-
parent: null,
|
|
144
|
-
children: [1],
|
|
145
|
-
refProperty: "three",
|
|
146
|
-
relatedObjects: {
|
|
147
|
-
children: [
|
|
148
|
-
{
|
|
149
|
-
id: 1,
|
|
150
|
-
name: "one",
|
|
151
|
-
parent: 2,
|
|
152
|
-
children: [],
|
|
153
|
-
refProperty: "three",
|
|
154
|
-
relatedObjects: {
|
|
155
|
-
parent: circular,
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
],
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
3: {
|
|
162
|
-
id: 3,
|
|
163
|
-
name: "three",
|
|
164
|
-
parent: null,
|
|
165
|
-
children: [],
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { isProxy, isRef, toRaw, unref } from "vue";
|
|
2
|
-
import { isArray, isUndefined } from "lodash";
|
|
3
|
-
import { isObjectLike } from "lodash/lang";
|
|
4
|
-
|
|
5
|
-
export const circular = Symbol("circular");
|
|
6
|
-
|
|
7
|
-
export function unrefAndToRawDeep(obj) {
|
|
8
|
-
if (isUndefined(obj)) {
|
|
9
|
-
return obj;
|
|
10
|
-
}
|
|
11
|
-
const seen = new Set();
|
|
12
|
-
const returnValue = isArray(obj) ? [] : {};
|
|
13
|
-
const queue = [];
|
|
14
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
15
|
-
queue.push([returnValue, key, value]);
|
|
16
|
-
}
|
|
17
|
-
while (queue.length) {
|
|
18
|
-
const [writePosition, key, value] = queue.shift();
|
|
19
|
-
if (seen.has(value)) {
|
|
20
|
-
// if (seen.some((item) => item === value)) {
|
|
21
|
-
writePosition[key] = circular;
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
let raw = value;
|
|
25
|
-
if (isRef(raw)) {
|
|
26
|
-
const refValue = unref(raw);
|
|
27
|
-
// primitive values are not added to the seen set
|
|
28
|
-
if (isObjectLike(refValue)) {
|
|
29
|
-
seen.add(raw);
|
|
30
|
-
}
|
|
31
|
-
raw = unref(raw);
|
|
32
|
-
}
|
|
33
|
-
if (isProxy(raw)) {
|
|
34
|
-
// this doesn't seem to do anything for the current test case.
|
|
35
|
-
// seen.add(raw);
|
|
36
|
-
raw = toRaw(raw);
|
|
37
|
-
}
|
|
38
|
-
if (!isObjectLike(raw)) {
|
|
39
|
-
// primitive values don't need to add to the queue
|
|
40
|
-
writePosition[key] = raw;
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
writePosition[key] = isArray(raw) ? [] : {};
|
|
44
|
-
for (const [nextKey, nextValue] of Object.entries(raw)) {
|
|
45
|
-
queue.push([writePosition[key], nextKey, nextValue]);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return returnValue;
|
|
49
|
-
}
|