@arrai-innovations/reactive-helpers 1.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/.circleci/config.yml +91 -0
- package/.commitlintrc.json +3 -0
- package/.editorconfig +5 -0
- package/.eslintignore +2 -0
- package/.eslintrc.js +26 -0
- package/.husky/commit-msg +2 -0
- package/.husky/pre-commit +2 -0
- package/.idea/encodings.xml +6 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/prettier.xml +8 -0
- package/.idea/reactive-helpers.iml +15 -0
- package/.lintstagedrc +11 -0
- package/.prettierignore +4 -0
- package/.prettierrc.js +5 -0
- package/README.md +598 -0
- package/babel.config.js +15 -0
- package/index.js +2 -0
- package/jest.config.mjs +27 -0
- package/package.json +59 -0
- package/tests/unit/.eslintrc.js +10 -0
- package/tests/unit/expectHelpers.js +6 -0
- package/tests/unit/mockOnUnmounted.js +9 -0
- package/tests/unit/use/index.spec.js +18 -0
- package/tests/unit/use/listFilter.spec.js +332 -0
- package/tests/unit/use/listInstance.spec.js +424 -0
- package/tests/unit/use/listRelated.spec.js +73 -0
- package/tests/unit/use/listSort.spec.js +220 -0
- package/tests/unit/use/listSubscription.spec.js +540 -0
- package/tests/unit/use/objectInstance.spec.js +897 -0
- package/tests/unit/use/objectSubscription.spec.js +671 -0
- package/tests/unit/use/search.spec.js +67 -0
- package/tests/unit/use/watches.spec.js +252 -0
- package/tests/unit/utils/assignReactiveObject.spec.js +127 -0
- package/tests/unit/utils/index.spec.js +18 -0
- package/tests/unit/utils/keyDiff.spec.js +67 -0
- package/tests/unit/utils/set.spec.js +68 -0
- package/tests/unit/utils/unrefAndToRawDeep.spec.js +170 -0
- package/use/index.js +8 -0
- package/use/listFilter.js +157 -0
- package/use/listInstance.js +144 -0
- package/use/listRelated.js +135 -0
- package/use/listSort.js +190 -0
- package/use/listSubscription.js +143 -0
- package/use/objectInstance.js +222 -0
- package/use/objectSubscription.js +188 -0
- package/use/search.js +104 -0
- package/utils/assignReactiveObject.js +62 -0
- package/utils/index.js +5 -0
- package/utils/keyDiff.js +10 -0
- package/utils/set.js +48 -0
- package/utils/unrefAndToRawDeep.js +49 -0
- package/utils/watches.js +170 -0
package/use/listSort.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { effectScope, onScopeDispose, reactive, toRef, unref, watch } from "vue";
|
|
2
|
+
import { cloneDeep, get, identity, isEmpty, isNull, isUndefined, partial, throttle, zip } from "lodash";
|
|
3
|
+
import { assignReactiveObject, keyDiff } from "../utils";
|
|
4
|
+
|
|
5
|
+
const collator = new Intl.Collator(undefined, { numeric: true });
|
|
6
|
+
|
|
7
|
+
const defaultSortThrottleWait = Symbol("defaultSortThrottleWait");
|
|
8
|
+
|
|
9
|
+
const defaultOptions = {
|
|
10
|
+
sortThrottleWait: 100,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function setListSortDefaultOptions({ sortThrottleWait }) {
|
|
14
|
+
defaultOptions.sortThrottleWait = sortThrottleWait;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function useListSorts(args, parentInstances) {
|
|
18
|
+
const sorts = {};
|
|
19
|
+
for (const [key, value] of Object.entries(args)) {
|
|
20
|
+
sorts[key] = useListSort({ parentState: parentInstances[key].state || parentInstances[key], ...value });
|
|
21
|
+
}
|
|
22
|
+
return sorts;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useListSort({ parentState, orderByRules, sortThrottleWait = defaultSortThrottleWait }) {
|
|
26
|
+
if (sortThrottleWait === defaultSortThrottleWait) {
|
|
27
|
+
sortThrottleWait = defaultOptions.sortThrottleWait;
|
|
28
|
+
}
|
|
29
|
+
const state = reactive({
|
|
30
|
+
orderByRules,
|
|
31
|
+
order: [],
|
|
32
|
+
objectsInOrder: [],
|
|
33
|
+
sortCriteria: {},
|
|
34
|
+
sortCriteriaWatches: {},
|
|
35
|
+
orderByDesc: [],
|
|
36
|
+
});
|
|
37
|
+
const es = effectScope();
|
|
38
|
+
|
|
39
|
+
function removeSortCriteria(removedKey) {
|
|
40
|
+
const stopWatches = state.sortCriteriaWatches[removedKey] || [];
|
|
41
|
+
let stopWatch = stopWatches.pop();
|
|
42
|
+
while (stopWatch) {
|
|
43
|
+
stopWatch();
|
|
44
|
+
stopWatch = stopWatches.pop();
|
|
45
|
+
}
|
|
46
|
+
delete state.sortCriteriaWatches[removedKey];
|
|
47
|
+
delete state.sortCriteria[removedKey];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function addSortCriteria(object, key) {
|
|
51
|
+
const oldStopWatches = state.sortCriteriaWatches[key] || [];
|
|
52
|
+
let stopWatch = oldStopWatches.pop();
|
|
53
|
+
while (stopWatch) {
|
|
54
|
+
stopWatch();
|
|
55
|
+
stopWatch = oldStopWatches.pop();
|
|
56
|
+
}
|
|
57
|
+
const stopWatches = [];
|
|
58
|
+
if (!state.sortCriteria[key]) {
|
|
59
|
+
state.sortCriteria[key] = [];
|
|
60
|
+
}
|
|
61
|
+
stopWatches.push(
|
|
62
|
+
watch(
|
|
63
|
+
[object, state.orderByRules],
|
|
64
|
+
() => {
|
|
65
|
+
const newSearchCriteria = [];
|
|
66
|
+
for (const orderByObj of state.orderByRules.filter(identity)) {
|
|
67
|
+
const obo = unref(orderByObj);
|
|
68
|
+
const getter = obo.keyFn ? obo.keyFn : partial(get, partial.placeholder, obo.key);
|
|
69
|
+
newSearchCriteria.push(getter(object));
|
|
70
|
+
}
|
|
71
|
+
assignReactiveObject(state.sortCriteria[key], newSearchCriteria);
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
deep: true,
|
|
75
|
+
immediate: true,
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
state.sortCriteriaWatches[key] = stopWatches;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function sortCriteriaWatch() {
|
|
83
|
+
if (!state.orderByRules || !state.orderByRules.filter(identity).length) {
|
|
84
|
+
if (!isEmpty(state.sortCriteria)) {
|
|
85
|
+
for (const removedKey of Object.keys(state.sortCriteria)) {
|
|
86
|
+
removeSortCriteria(removedKey);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const { removedKeys, addedKeys } = keyDiff(Object.keys(parentState.objects), Object.keys(state.sortCriteria));
|
|
92
|
+
for (const removedKey of removedKeys) {
|
|
93
|
+
removeSortCriteria(removedKey);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const addedKey of addedKeys) {
|
|
97
|
+
const object = parentState.objects[addedKey];
|
|
98
|
+
addSortCriteria(object, addedKey);
|
|
99
|
+
}
|
|
100
|
+
assignReactiveObject(
|
|
101
|
+
state.orderByDesc,
|
|
102
|
+
state.orderByRules.filter(identity).map((e) => e.desc || false)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function sortWatch() {
|
|
107
|
+
if (!state.orderByRules || !state.orderByRules.length) {
|
|
108
|
+
const serverOrderObjectsInOrder = parentState.addedOrder
|
|
109
|
+
.map((e) => parentState.objects[e])
|
|
110
|
+
.filter(identity);
|
|
111
|
+
assignReactiveObject(
|
|
112
|
+
state.order,
|
|
113
|
+
serverOrderObjectsInOrder.map((e) => String(e.id))
|
|
114
|
+
);
|
|
115
|
+
assignReactiveObject(state.objectsInOrder, serverOrderObjectsInOrder);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let idList = Object.keys(parentState.objects);
|
|
120
|
+
|
|
121
|
+
idList.sort((xKey, yKey) => {
|
|
122
|
+
const xCriteria = state.sortCriteria[xKey];
|
|
123
|
+
const yCriteria = state.sortCriteria[yKey];
|
|
124
|
+
for (let [x, y, orderByObj] of zip(xCriteria, yCriteria, state.orderByRules)) {
|
|
125
|
+
if (!orderByObj) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (orderByObj.desc) {
|
|
129
|
+
[x, y] = [y, x];
|
|
130
|
+
}
|
|
131
|
+
const isUndefinedX = isUndefined(x) || isNull(x);
|
|
132
|
+
const isUndefinedY = isUndefined(y) || isNull(y);
|
|
133
|
+
if (isUndefinedX && isUndefinedY) {
|
|
134
|
+
continue;
|
|
135
|
+
} else if (isUndefinedX) {
|
|
136
|
+
return -1;
|
|
137
|
+
} else if (isUndefinedY) {
|
|
138
|
+
return 1;
|
|
139
|
+
}
|
|
140
|
+
if (orderByObj.localeCompare) {
|
|
141
|
+
const strComp = collator.compare(x, y);
|
|
142
|
+
if (strComp) {
|
|
143
|
+
return strComp;
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
if (x < y) {
|
|
147
|
+
return -1;
|
|
148
|
+
}
|
|
149
|
+
if (x > y) {
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return 0;
|
|
155
|
+
});
|
|
156
|
+
assignReactiveObject(state.order, idList);
|
|
157
|
+
assignReactiveObject(state.objectsInOrder, idList.map((e) => parentState.objects[e]).filter(identity));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const throttledSortWatch = throttle(sortWatch, sortThrottleWait);
|
|
161
|
+
|
|
162
|
+
es.run(() => {
|
|
163
|
+
state.objects = toRef(parentState, "objects");
|
|
164
|
+
// we do not need two immediate watches to the same function.
|
|
165
|
+
watch(() => Object.keys(parentState.objects), sortCriteriaWatch);
|
|
166
|
+
watch(() => cloneDeep(state.orderByRules), sortCriteriaWatch, {
|
|
167
|
+
deep: true,
|
|
168
|
+
immediate: true,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
watch(
|
|
172
|
+
[toRef(state, "orderByDesc"), () => state.sortCriteria, () => parentState.addedOrder],
|
|
173
|
+
throttledSortWatch,
|
|
174
|
+
{
|
|
175
|
+
deep: true,
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
onScopeDispose(() => {
|
|
179
|
+
Object.keys(state.sortCriteriaWatches).forEach((key) => {
|
|
180
|
+
removeSortCriteria(key);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
state,
|
|
187
|
+
parentState,
|
|
188
|
+
effectScope: es,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { effectScope, onScopeDispose, reactive } from "vue";
|
|
2
|
+
import { useListInstance } from "./listInstance";
|
|
3
|
+
import { cloneDeep, isEmpty, isObject } from "lodash";
|
|
4
|
+
import { assignReactiveObject } from "../utils/assignReactiveObject";
|
|
5
|
+
import inspect from "browser-util-inspect";
|
|
6
|
+
|
|
7
|
+
export class ListSubscriptionError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "ListSubscriptionError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const defaultCrud = reactive({
|
|
15
|
+
subscribe: undefined,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export function setListSubscriptionCrud({ subscribe }) {
|
|
19
|
+
defaultCrud.subscribe = subscribe;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function useListSubscriptions(args, listInstances = {}) {
|
|
23
|
+
const subscriptions = {};
|
|
24
|
+
for (const [key, value] of Object.entries(args)) {
|
|
25
|
+
subscriptions[key] = useListSubscription({ listInstance: listInstances[key], ...value });
|
|
26
|
+
}
|
|
27
|
+
return subscriptions;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function useListSubscription({ listInstance, crudArgs, defaultListArgs, defaultRetrieveArgs }) {
|
|
31
|
+
if (!listInstance) {
|
|
32
|
+
listInstance = useListInstance({ crudArgs, defaultListArgs, defaultRetrieveArgs });
|
|
33
|
+
}
|
|
34
|
+
let cancelSubscription = null;
|
|
35
|
+
const state = reactive({
|
|
36
|
+
listSubscriptionCrud: {},
|
|
37
|
+
intendToSubscribe: false,
|
|
38
|
+
});
|
|
39
|
+
assignReactiveObject(state.listSubscriptionCrud, defaultCrud);
|
|
40
|
+
|
|
41
|
+
async function subscribe({ listArgs, retrieveArgs } = {}) {
|
|
42
|
+
if (!listArgs) {
|
|
43
|
+
listArgs = cloneDeep(listInstance.state.defaultListArgs);
|
|
44
|
+
}
|
|
45
|
+
if (!retrieveArgs) {
|
|
46
|
+
retrieveArgs = cloneDeep(listInstance.state.defaultRetrieveArgs);
|
|
47
|
+
}
|
|
48
|
+
if (!cancelSubscription) {
|
|
49
|
+
cancelSubscription = await state.listSubscriptionCrud.subscribe({
|
|
50
|
+
crudArgs: listInstance.state.listInstanceCrud.args,
|
|
51
|
+
listArgs,
|
|
52
|
+
retrieveArgs,
|
|
53
|
+
subscriptionEventCallback,
|
|
54
|
+
});
|
|
55
|
+
state.subscribed = true;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function subscriptionEventCallback(data, action) {
|
|
62
|
+
if (!data || (isObject(data) && isEmpty(data))) {
|
|
63
|
+
throw new ListSubscriptionError(`got update with no data (${inspect(data)}), action: ${action}`);
|
|
64
|
+
} else if (action === "delete") {
|
|
65
|
+
deleteFromSubscription(data);
|
|
66
|
+
} else if (action === "create") {
|
|
67
|
+
addFromSubscription(data);
|
|
68
|
+
} else if (action === "update") {
|
|
69
|
+
updateFromSubscription(data);
|
|
70
|
+
} else {
|
|
71
|
+
throw new ListSubscriptionError(`got update for unknown action: ${action}\n${inspect(data)}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function unsubscribe() {
|
|
76
|
+
if (cancelSubscription) {
|
|
77
|
+
const returnValue = await cancelSubscription();
|
|
78
|
+
state.subscribed = false;
|
|
79
|
+
cancelSubscription = null;
|
|
80
|
+
return returnValue;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function addFromSubscription(data) {
|
|
86
|
+
if (!data.id) {
|
|
87
|
+
throw new ListSubscriptionError(`addFromSubscription: data missing id.\n${inspect(data)}`);
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
listInstance.addListObject(data);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
if (err.name === "ListError" && err.code === "duplicate-id") {
|
|
93
|
+
throw new ListSubscriptionError(`addFromSubscription: add for existing id in objects (${data.id}).`);
|
|
94
|
+
}
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function updateFromSubscription(data) {
|
|
100
|
+
if (!data.id) {
|
|
101
|
+
throw new ListSubscriptionError(`updateFromSubscription: data missing id.\n${inspect(data)}`);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
listInstance.updateListObject(data);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (err.name === "ListError" && err.code === "missing-object") {
|
|
107
|
+
throw new ListSubscriptionError(
|
|
108
|
+
`updateFromSubscription: update for id not in objects (${inspect(data.id)}).`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function deleteFromSubscription(id) {
|
|
116
|
+
try {
|
|
117
|
+
listInstance.deleteListObject(id);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (err.name === "ListError" && err.code === "missing-object") {
|
|
120
|
+
throw new ListSubscriptionError(
|
|
121
|
+
`deleteFromSubscription: delete for id not in objects (${inspect(id)}).`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const es = effectScope();
|
|
129
|
+
|
|
130
|
+
es.run(() => {
|
|
131
|
+
onScopeDispose(async () => {
|
|
132
|
+
await unsubscribe();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
state,
|
|
138
|
+
listInstance,
|
|
139
|
+
subscribe,
|
|
140
|
+
unsubscribe,
|
|
141
|
+
effectScope: es,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { isEmpty } from "lodash";
|
|
2
|
+
import { effectScope, reactive, unref } from "vue";
|
|
3
|
+
import { assignReactiveObject } from "../utils/assignReactiveObject";
|
|
4
|
+
|
|
5
|
+
export class ObjectError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "ObjectError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const defaultCrud = reactive({
|
|
13
|
+
args: {},
|
|
14
|
+
retrieve: undefined,
|
|
15
|
+
create: undefined,
|
|
16
|
+
update: undefined,
|
|
17
|
+
patch: undefined,
|
|
18
|
+
delete: undefined,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export function setObjectInstanceCrud({ retrieve, create, update, patch, delete: deleteFn, args = {} }) {
|
|
22
|
+
defaultCrud.retrieve = retrieve;
|
|
23
|
+
defaultCrud.create = create;
|
|
24
|
+
defaultCrud.update = update;
|
|
25
|
+
defaultCrud.patch = patch;
|
|
26
|
+
defaultCrud.delete = deleteFn;
|
|
27
|
+
assignReactiveObject(defaultCrud.args, args);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function useObjectInstances(instanceArgs) {
|
|
31
|
+
const instances = {};
|
|
32
|
+
for (const [key, value] of Object.entries(instanceArgs)) {
|
|
33
|
+
instances[key] = useObjectInstance(value);
|
|
34
|
+
}
|
|
35
|
+
return instances;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function useObjectInstance({ crudArgs, retrieveArgs }) {
|
|
39
|
+
const state = reactive({
|
|
40
|
+
objectInstanceCrud: {
|
|
41
|
+
args: {},
|
|
42
|
+
retrieve: undefined,
|
|
43
|
+
create: undefined,
|
|
44
|
+
update: undefined,
|
|
45
|
+
patch: undefined,
|
|
46
|
+
delete: undefined,
|
|
47
|
+
},
|
|
48
|
+
object: {},
|
|
49
|
+
defaultRetrieveArgs: retrieveArgs,
|
|
50
|
+
loading: undefined,
|
|
51
|
+
errored: false,
|
|
52
|
+
error: null,
|
|
53
|
+
deleted: false,
|
|
54
|
+
});
|
|
55
|
+
assignReactiveObject(state.objectInstanceCrud, defaultCrud);
|
|
56
|
+
if (crudArgs) {
|
|
57
|
+
assignReactiveObject(state.objectInstanceCrud.args, crudArgs);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function retrieve({ id, ...retrieveArgs }) {
|
|
61
|
+
if (state.loading) {
|
|
62
|
+
throw new ObjectError("already loading.");
|
|
63
|
+
}
|
|
64
|
+
if (isEmpty(retrieveArgs) && !isEmpty(unref(state.defaultRetrieveArgs))) {
|
|
65
|
+
retrieveArgs = unref(state.defaultRetrieveArgs);
|
|
66
|
+
}
|
|
67
|
+
state.loading = true;
|
|
68
|
+
state.errored = false;
|
|
69
|
+
state.error = null;
|
|
70
|
+
return state.objectInstanceCrud
|
|
71
|
+
.retrieve({
|
|
72
|
+
crudArgs: state.objectInstanceCrud.args,
|
|
73
|
+
id,
|
|
74
|
+
retrieveArgs,
|
|
75
|
+
})
|
|
76
|
+
.then((object) => {
|
|
77
|
+
assignReactiveObject(state.object, object);
|
|
78
|
+
return Promise.resolve(true);
|
|
79
|
+
})
|
|
80
|
+
.catch((error) => {
|
|
81
|
+
state.errored = true;
|
|
82
|
+
state.error = error;
|
|
83
|
+
return Promise.resolve(false);
|
|
84
|
+
})
|
|
85
|
+
.finally(() => {
|
|
86
|
+
state.loading = false;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function create({ object, ...retrieveArgs }) {
|
|
91
|
+
if (state.loading) {
|
|
92
|
+
throw new ObjectError("already loading.");
|
|
93
|
+
}
|
|
94
|
+
if (isEmpty(retrieveArgs) && !isEmpty(unref(state.defaultRetrieveArgs))) {
|
|
95
|
+
retrieveArgs = unref(state.defaultRetrieveArgs);
|
|
96
|
+
}
|
|
97
|
+
state.loading = true;
|
|
98
|
+
state.errored = false;
|
|
99
|
+
state.error = null;
|
|
100
|
+
return state.objectInstanceCrud
|
|
101
|
+
.create({
|
|
102
|
+
crudArgs: state.objectInstanceCrud.args,
|
|
103
|
+
object,
|
|
104
|
+
retrieveArgs,
|
|
105
|
+
})
|
|
106
|
+
.then((object) => {
|
|
107
|
+
assignReactiveObject(state.object, object);
|
|
108
|
+
return Promise.resolve(true);
|
|
109
|
+
})
|
|
110
|
+
.catch((error) => {
|
|
111
|
+
state.errored = true;
|
|
112
|
+
state.error = error;
|
|
113
|
+
return Promise.resolve(false);
|
|
114
|
+
})
|
|
115
|
+
.finally(() => {
|
|
116
|
+
state.loading = false;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function update({ object, ...retrieveArgs }) {
|
|
121
|
+
if (state.loading) {
|
|
122
|
+
throw new ObjectError("already loading.");
|
|
123
|
+
}
|
|
124
|
+
if (isEmpty(retrieveArgs) && !isEmpty(unref(state.defaultRetrieveArgs))) {
|
|
125
|
+
retrieveArgs = unref(state.defaultRetrieveArgs);
|
|
126
|
+
}
|
|
127
|
+
state.loading = true;
|
|
128
|
+
state.errored = false;
|
|
129
|
+
state.error = null;
|
|
130
|
+
return state.objectInstanceCrud
|
|
131
|
+
.update({
|
|
132
|
+
crudArgs: state.objectInstanceCrud.args,
|
|
133
|
+
object,
|
|
134
|
+
retrieveArgs,
|
|
135
|
+
})
|
|
136
|
+
.then((object) => {
|
|
137
|
+
assignReactiveObject(state.object, object);
|
|
138
|
+
return Promise.resolve(true);
|
|
139
|
+
})
|
|
140
|
+
.catch((error) => {
|
|
141
|
+
state.errored = true;
|
|
142
|
+
state.error = error;
|
|
143
|
+
return Promise.resolve(false);
|
|
144
|
+
})
|
|
145
|
+
.finally(() => {
|
|
146
|
+
state.loading = false;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function patch({ id, partialObject, ...retrieveArgs }) {
|
|
151
|
+
if (state.loading) {
|
|
152
|
+
throw new ObjectError("already loading.");
|
|
153
|
+
}
|
|
154
|
+
if (isEmpty(retrieveArgs) && !isEmpty(unref(state.defaultRetrieveArgs))) {
|
|
155
|
+
retrieveArgs = unref(state.defaultRetrieveArgs);
|
|
156
|
+
}
|
|
157
|
+
state.loading = true;
|
|
158
|
+
state.errored = false;
|
|
159
|
+
state.error = null;
|
|
160
|
+
return state.objectInstanceCrud
|
|
161
|
+
.patch({
|
|
162
|
+
crudArgs: state.objectInstanceCrud.args,
|
|
163
|
+
id,
|
|
164
|
+
partialObject,
|
|
165
|
+
retrieveArgs,
|
|
166
|
+
})
|
|
167
|
+
.then((object) => {
|
|
168
|
+
assignReactiveObject(state.object, object);
|
|
169
|
+
return Promise.resolve(true);
|
|
170
|
+
})
|
|
171
|
+
.catch((error) => {
|
|
172
|
+
state.errored = true;
|
|
173
|
+
state.error = error;
|
|
174
|
+
return Promise.resolve(false);
|
|
175
|
+
})
|
|
176
|
+
.finally(() => {
|
|
177
|
+
state.loading = false;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function deleteFn(id) {
|
|
182
|
+
if (state.loading) {
|
|
183
|
+
throw new ObjectError("already loading.");
|
|
184
|
+
}
|
|
185
|
+
state.loading = true;
|
|
186
|
+
state.errored = false;
|
|
187
|
+
state.error = null;
|
|
188
|
+
return state.objectInstanceCrud
|
|
189
|
+
.delete({
|
|
190
|
+
crudArgs: state.objectInstanceCrud.args,
|
|
191
|
+
id,
|
|
192
|
+
})
|
|
193
|
+
.then(() => {
|
|
194
|
+
state.deleted = true;
|
|
195
|
+
assignReactiveObject(state.object, {});
|
|
196
|
+
return Promise.resolve(true);
|
|
197
|
+
})
|
|
198
|
+
.catch((error) => {
|
|
199
|
+
state.errored = true;
|
|
200
|
+
state.error = error;
|
|
201
|
+
return Promise.resolve(false);
|
|
202
|
+
})
|
|
203
|
+
.finally(() => {
|
|
204
|
+
state.loading = false;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const es = effectScope();
|
|
209
|
+
|
|
210
|
+
// we could have effects? let's keep the interface to keep our options open to add without major changes.
|
|
211
|
+
es.run(() => {});
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
state,
|
|
215
|
+
retrieve,
|
|
216
|
+
create,
|
|
217
|
+
update,
|
|
218
|
+
patch,
|
|
219
|
+
delete: deleteFn,
|
|
220
|
+
effectScope: es,
|
|
221
|
+
};
|
|
222
|
+
}
|