@arrai-innovations/reactive-helpers 11.1.0 → 11.3.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/docs.md
CHANGED
|
@@ -686,12 +686,13 @@ The configuration options used to create a list subscription.
|
|
|
686
686
|
**Kind**: global typedef
|
|
687
687
|
**Properties**
|
|
688
688
|
|
|
689
|
-
| Name
|
|
690
|
-
|
|
|
691
|
-
| props
|
|
692
|
-
| functions
|
|
693
|
-
| listInstance
|
|
694
|
-
| keepOldPages
|
|
689
|
+
| Name | Type | Description |
|
|
690
|
+
| ------------------------------ | ---------------- | ---------------------------------------------------------------------------------------- |
|
|
691
|
+
| props | `object` | passed on to a created list instance if one is not provided |
|
|
692
|
+
| functions | `object` | passed on to a created list instance if one is not provided |
|
|
693
|
+
| listInstance | [`ListInstance`] | a list instance to use instead of creating one |
|
|
694
|
+
| keepOldPages | `boolean` | if true, pages will not be cleared when defaultPageCallback is called. default is false. |
|
|
695
|
+
| clearListOnListIntentTriggered | `boolean` | if true, the list will be cleared when the list intent is triggered. default is false. |
|
|
695
696
|
|
|
696
697
|
## ListSubscriptionState
|
|
697
698
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ import { expectErrorToBeNull } from "../expectHelpers.js";
|
|
|
3
3
|
import flushPromises from "flush-promises";
|
|
4
4
|
import keyBy from "lodash-es/keyBy.js";
|
|
5
5
|
import { inspect } from "util";
|
|
6
|
-
import { isReactive, nextTick, reactive } from "vue";
|
|
6
|
+
import { isReactive, nextTick, reactive, isRef, isReadonly } from "vue";
|
|
7
7
|
|
|
8
8
|
afterAll(() => {
|
|
9
9
|
vi.restoreAllMocks();
|
|
@@ -16,6 +16,7 @@ describe("use/listInstance.spec.js", function () {
|
|
|
16
16
|
const listCrud = await import("../../../config/listCrud.js");
|
|
17
17
|
const imported = await import("../../../use/listInstance");
|
|
18
18
|
globalList = vi.fn();
|
|
19
|
+
globalList.cancel = vi.fn();
|
|
19
20
|
listCrud.setListCrud({
|
|
20
21
|
list: globalList,
|
|
21
22
|
args: { stream: "test_stream" },
|
|
@@ -128,6 +129,7 @@ describe("use/listInstance.spec.js", function () {
|
|
|
128
129
|
listArgs: { user: 1 },
|
|
129
130
|
retrieveArgs: { fields: fields },
|
|
130
131
|
pageCallback: passedPageCallback,
|
|
132
|
+
isCancelled: expect.any(Object), // ref
|
|
131
133
|
});
|
|
132
134
|
expect(globalList).toHaveBeenCalledTimes(1);
|
|
133
135
|
});
|
|
@@ -153,6 +155,7 @@ describe("use/listInstance.spec.js", function () {
|
|
|
153
155
|
listArgs: { user: 1 },
|
|
154
156
|
retrieveArgs: { fields: fields },
|
|
155
157
|
pageCallback: expect.any(Function),
|
|
158
|
+
isCancelled: expect.any(Object), // ref
|
|
156
159
|
});
|
|
157
160
|
expect(globalList).toHaveBeenCalledTimes(1);
|
|
158
161
|
expectErrorToBeNull(listInstance.state.error);
|
|
@@ -207,6 +210,7 @@ describe("use/listInstance.spec.js", function () {
|
|
|
207
210
|
listArgs: { user: 1 },
|
|
208
211
|
retrieveArgs: { fields: fields },
|
|
209
212
|
pageCallback: passedPageCallback,
|
|
213
|
+
isCancelled: expect.any(Object), // ref
|
|
210
214
|
});
|
|
211
215
|
expect(globalList).toHaveBeenCalledTimes(1);
|
|
212
216
|
});
|
|
@@ -272,6 +276,7 @@ describe("use/listInstance.spec.js", function () {
|
|
|
272
276
|
listArgs: { user: 1 },
|
|
273
277
|
retrieveArgs: { fields: fields },
|
|
274
278
|
pageCallback: passedPageCallback,
|
|
279
|
+
isCancelled: expect.any(Object), // ref
|
|
275
280
|
});
|
|
276
281
|
expect(globalList).toHaveBeenCalledTimes(1);
|
|
277
282
|
});
|
|
@@ -318,6 +323,7 @@ describe("use/listInstance.spec.js", function () {
|
|
|
318
323
|
listArgs: { user: 1 },
|
|
319
324
|
retrieveArgs: { fields: fields },
|
|
320
325
|
pageCallback: passedPageCallback,
|
|
326
|
+
isCancelled: expect.any(Object), // ref
|
|
321
327
|
});
|
|
322
328
|
expect(globalList).toHaveBeenCalledTimes(1);
|
|
323
329
|
|
|
@@ -560,4 +566,39 @@ describe("use/listInstance.spec.js", function () {
|
|
|
560
566
|
expect(listInstance.state.order).toEqual(crudListResolvedPage3.map((e) => e.id.toString()));
|
|
561
567
|
expect(listInstance.state.objectsInOrder).toEqual(crudListResolvedPage3);
|
|
562
568
|
});
|
|
569
|
+
describe("list promise cancellation", function () {
|
|
570
|
+
it("cancels and sets isCancelled", async function () {
|
|
571
|
+
let myListFnCancelResolve, passedIsCancelled;
|
|
572
|
+
const myListFn = vi.fn().mockImplementation(({ isCancelled }) => {
|
|
573
|
+
passedIsCancelled = isCancelled;
|
|
574
|
+
const promise = new Promise(() => {});
|
|
575
|
+
promise.cancel = async () => {
|
|
576
|
+
await new Promise((resolve) => {
|
|
577
|
+
myListFnCancelResolve = resolve;
|
|
578
|
+
});
|
|
579
|
+
};
|
|
580
|
+
return promise;
|
|
581
|
+
});
|
|
582
|
+
const listInstance = useListInstance({
|
|
583
|
+
props: {},
|
|
584
|
+
functions: {
|
|
585
|
+
list: myListFn,
|
|
586
|
+
},
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const cancelablePromise = listInstance.list();
|
|
590
|
+
|
|
591
|
+
expect(passedIsCancelled).toBeTruthy();
|
|
592
|
+
expect(isRef(passedIsCancelled)).toBe(true);
|
|
593
|
+
expect(isReadonly(passedIsCancelled)).toBe(true);
|
|
594
|
+
expect(passedIsCancelled.value).toBe(false);
|
|
595
|
+
expect(cancelablePromise.cancel).toBeTruthy();
|
|
596
|
+
|
|
597
|
+
const cancelPromise = cancelablePromise.cancel();
|
|
598
|
+
myListFnCancelResolve();
|
|
599
|
+
await cancelPromise;
|
|
600
|
+
|
|
601
|
+
expect(passedIsCancelled.value).toBe(true);
|
|
602
|
+
});
|
|
603
|
+
});
|
|
563
604
|
});
|
|
@@ -142,7 +142,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
142
142
|
obj: listSubscription.subscribeIntent.state,
|
|
143
143
|
prop: "active",
|
|
144
144
|
});
|
|
145
|
-
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
146
145
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
147
146
|
expect(returnValue).toBe(true);
|
|
148
147
|
|
|
@@ -288,7 +287,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
288
287
|
crudSubscribeResolvable[0].cancel.resolve(true);
|
|
289
288
|
const returnValue = await unsubscribe;
|
|
290
289
|
await poll(() => !listSubscription.state.subscribed);
|
|
291
|
-
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
292
290
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
293
291
|
expect(returnValue).toBe(true);
|
|
294
292
|
expect(listSubscription.state.subscribed).toBe(false);
|
|
@@ -322,7 +320,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
322
320
|
crudSubscribeResolvable[0].cancel.resolve(true);
|
|
323
321
|
const returnValue = await unsubscribePromise;
|
|
324
322
|
await poll(() => !listSubscription.state.subscribed);
|
|
325
|
-
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
326
323
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
327
324
|
expect(returnValue).toBe(true);
|
|
328
325
|
expect(listSubscription.state.subscribed).toBe(false);
|
|
@@ -382,7 +379,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
382
379
|
crudSubscribeResolvable[0].cancel.resolve(true);
|
|
383
380
|
const returnValue = await unsubscribePromise;
|
|
384
381
|
await poll(() => !listSubscription.state.subscribed);
|
|
385
|
-
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
386
382
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
387
383
|
expect(returnValue).toBe(true);
|
|
388
384
|
expect(listSubscription.state.subscribed).toBe(false);
|
|
@@ -455,7 +451,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
455
451
|
crudSubscribeResolvable[0].cancel.resolve(true);
|
|
456
452
|
const returnValue = await unsubscribePromise;
|
|
457
453
|
await poll(() => !listSubscription.state.subscribed);
|
|
458
|
-
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
459
454
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
460
455
|
expect(returnValue).toBe(true);
|
|
461
456
|
expect(listSubscription.state.subscribed).toBe(false);
|
|
@@ -508,7 +503,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
508
503
|
await crudSubscribeResolvable[1].resolve();
|
|
509
504
|
await crudListResolvable[1].resolve();
|
|
510
505
|
await poll(() => listSubscription.state.subscribed);
|
|
511
|
-
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledWith();
|
|
512
506
|
expect(crudSubscribeResolvable[0].promise.cancel).toHaveBeenCalledTimes(1);
|
|
513
507
|
|
|
514
508
|
expect(crudSubscribe).toHaveBeenCalledTimes(2);
|
|
@@ -518,7 +512,6 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
518
512
|
const returnValue = await unsubscribePromise;
|
|
519
513
|
expect(returnValue).toBe(true);
|
|
520
514
|
await poll(() => !listSubscription.state.subscribed);
|
|
521
|
-
expect(crudSubscribeResolvable[1].promise.cancel).toHaveBeenCalledWith();
|
|
522
515
|
expect(crudSubscribeResolvable[1].promise.cancel).toHaveBeenCalledTimes(1);
|
|
523
516
|
expect(listSubscription.state.subscribed).toBe(false);
|
|
524
517
|
});
|
|
@@ -622,4 +615,52 @@ describe("use/listSubscription.spec.js", function () {
|
|
|
622
615
|
expect(inspect(listSubscription.A)).toEqual(inspect(listSubscriptionA));
|
|
623
616
|
expect(inspect(listSubscription.B)).toEqual(inspect(listSubscriptionB));
|
|
624
617
|
});
|
|
618
|
+
describe("clearListOnListIntentTriggered true", function () {
|
|
619
|
+
it("on true", async function () {
|
|
620
|
+
crudSubscribeResolvable[0].promise.cancel.mockImplementation(() => Promise.resolve(true));
|
|
621
|
+
const listArgs = reactive({
|
|
622
|
+
user: 1,
|
|
623
|
+
});
|
|
624
|
+
const retrieveArgs = reactive({
|
|
625
|
+
fields: fields,
|
|
626
|
+
});
|
|
627
|
+
const listInstance = useListInstance({
|
|
628
|
+
props: { listArgs, retrieveArgs },
|
|
629
|
+
});
|
|
630
|
+
listInstance.clearList = vi.fn().mockImplementationOnce(() => undefined);
|
|
631
|
+
const listSubscription = useListSubscription({
|
|
632
|
+
listInstance,
|
|
633
|
+
clearListOnListIntentTriggered: true,
|
|
634
|
+
});
|
|
635
|
+
listSubscription.subscribe();
|
|
636
|
+
await nextTick();
|
|
637
|
+
await flushPromises();
|
|
638
|
+
listArgs.user = 2;
|
|
639
|
+
expect(listInstance.clearList).toHaveBeenCalledTimes(1);
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
describe("clearListOnListIntentTriggered false", function () {
|
|
643
|
+
it("on true", async function () {
|
|
644
|
+
crudSubscribeResolvable[0].promise.cancel.mockImplementation(() => Promise.resolve(true));
|
|
645
|
+
const listArgs = reactive({
|
|
646
|
+
user: 1,
|
|
647
|
+
});
|
|
648
|
+
const retrieveArgs = reactive({
|
|
649
|
+
fields: fields,
|
|
650
|
+
});
|
|
651
|
+
const listInstance = useListInstance({
|
|
652
|
+
props: { listArgs, retrieveArgs },
|
|
653
|
+
});
|
|
654
|
+
listInstance.clearList = vi.fn().mockImplementationOnce(() => undefined);
|
|
655
|
+
const listSubscription = useListSubscription({
|
|
656
|
+
listInstance,
|
|
657
|
+
clearListOnListIntentTriggered: false,
|
|
658
|
+
});
|
|
659
|
+
listSubscription.subscribe();
|
|
660
|
+
await nextTick();
|
|
661
|
+
await flushPromises();
|
|
662
|
+
listArgs.user = 2;
|
|
663
|
+
expect(listInstance.clearList).toHaveBeenCalledTimes(0);
|
|
664
|
+
});
|
|
665
|
+
});
|
|
625
666
|
});
|
package/use/cancellableIntent.js
CHANGED
|
@@ -54,7 +54,7 @@ export function useCancellableIntent({
|
|
|
54
54
|
return false;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const doIntentWatch =
|
|
57
|
+
const doIntentWatch = () => {
|
|
58
58
|
state.errored = false;
|
|
59
59
|
state.error = null;
|
|
60
60
|
if (state.activeCount === undefined) {
|
|
@@ -127,13 +127,13 @@ export function useCancellableIntent({
|
|
|
127
127
|
}
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
-
const guardWatch =
|
|
130
|
+
const guardWatch = () => {
|
|
131
131
|
if (delayedWatch) {
|
|
132
132
|
// if all guards are false, run the watch
|
|
133
133
|
if (Object.values(guardArguments).every((x) => !x)) {
|
|
134
134
|
const myDelayedWatch = delayedWatch;
|
|
135
135
|
delayedWatch = null;
|
|
136
|
-
|
|
136
|
+
myDelayedWatch();
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
};
|
package/use/list.js
CHANGED
|
@@ -31,6 +31,7 @@ export const useList = ({
|
|
|
31
31
|
functions = {},
|
|
32
32
|
paged = false,
|
|
33
33
|
keepOldPages = false,
|
|
34
|
+
clearListOnListIntentTriggered = false,
|
|
34
35
|
searchThrottle = 500,
|
|
35
36
|
sortThrottleWait,
|
|
36
37
|
searchShowAllWhenEmpty,
|
|
@@ -63,6 +64,7 @@ export const useList = ({
|
|
|
63
64
|
|
|
64
65
|
managed.listSubscription = useListSubscription({
|
|
65
66
|
listInstance: managed.listInstance,
|
|
67
|
+
clearListOnListIntentTriggered,
|
|
66
68
|
});
|
|
67
69
|
managed.listSubscription.state.intendToList = toRef(props, "intendToList");
|
|
68
70
|
managed.listSubscription.state.intendToSubscribe = toRef(props, "intendToSubscribe");
|
package/use/listInstance.js
CHANGED
|
@@ -2,7 +2,7 @@ import { getListCrud } from "../config/listCrud.js";
|
|
|
2
2
|
import { assignReactiveObject } from "../utils/assignReactiveObject.js";
|
|
3
3
|
import { getFakeId } from "../utils/getFakeId.js";
|
|
4
4
|
import inspect from "browser-util-inspect";
|
|
5
|
-
import { effectScope, reactive, toRef, watch, computed, unref } from "vue";
|
|
5
|
+
import { effectScope, reactive, toRef, watch, computed, unref, ref, readonly } from "vue";
|
|
6
6
|
|
|
7
7
|
export class ListError extends Error {
|
|
8
8
|
constructor(message, code) {
|
|
@@ -182,16 +182,19 @@ export function useListInstance({ props, functions = {}, keepOldPages = false })
|
|
|
182
182
|
state.loading = true;
|
|
183
183
|
state.errored = false;
|
|
184
184
|
state.error = null;
|
|
185
|
+
const isCancelled = ref(false);
|
|
185
186
|
const listPromise = state.crud.list({
|
|
186
187
|
crudArgs: state.crud.args,
|
|
187
188
|
retrieveArgs: state.retrieveArgs,
|
|
188
189
|
listArgs: state.listArgs,
|
|
189
190
|
pageCallback: returnedObject.pageCallback,
|
|
191
|
+
isCancelled: readonly(isCancelled),
|
|
190
192
|
});
|
|
191
193
|
let resolveState = false;
|
|
192
194
|
if (listPromise.cancel) {
|
|
193
195
|
promises.list.cancel = async () => {
|
|
194
196
|
let promise = listPromise.cancel();
|
|
197
|
+
isCancelled.value = true;
|
|
195
198
|
if (promise) {
|
|
196
199
|
await promise;
|
|
197
200
|
}
|
package/use/listSubscription.js
CHANGED
|
@@ -22,6 +22,7 @@ export class ListSubscriptionError extends Error {
|
|
|
22
22
|
* @property {object} functions - passed on to a created list instance if one is not provided
|
|
23
23
|
* @property {ListInstance} listInstance - a list instance to use instead of creating one
|
|
24
24
|
* @property {boolean} keepOldPages - if true, pages will not be cleared when defaultPageCallback is called. default is false.
|
|
25
|
+
* @property {boolean} clearListOnListIntentTriggered - if true, the list will be cleared when the list intent is triggered. default is false.
|
|
25
26
|
*/
|
|
26
27
|
|
|
27
28
|
/* eslint-disable jsdoc/check-types */
|
|
@@ -70,7 +71,13 @@ export function useListSubscriptions(args, listInstances = {}) {
|
|
|
70
71
|
* @param {ListSubscriptionOptions} options - the configuration options for the list subscription
|
|
71
72
|
* @returns {ListSubscription} - the list subscription
|
|
72
73
|
*/
|
|
73
|
-
export function useListSubscription({
|
|
74
|
+
export function useListSubscription({
|
|
75
|
+
listInstance,
|
|
76
|
+
props,
|
|
77
|
+
functions,
|
|
78
|
+
keepOldPages = false,
|
|
79
|
+
clearListOnListIntentTriggered = false,
|
|
80
|
+
}) {
|
|
74
81
|
if (!listInstance && !props) {
|
|
75
82
|
throw new ListSubscriptionError("useListSubscription should be passed listInstance or props and functions.");
|
|
76
83
|
}
|
|
@@ -233,7 +240,12 @@ export function useListSubscription({ listInstance, props, functions, keepOldPag
|
|
|
233
240
|
state.subscribed = toRef(subscribeIntent.state, "active");
|
|
234
241
|
|
|
235
242
|
listIntent = useCancellableIntent({
|
|
236
|
-
awaitableWithCancel:
|
|
243
|
+
awaitableWithCancel: () => {
|
|
244
|
+
if (clearListOnListIntentTriggered) {
|
|
245
|
+
listInstance.clearList();
|
|
246
|
+
}
|
|
247
|
+
return listInstance.list();
|
|
248
|
+
},
|
|
237
249
|
watchArguments: reactive({
|
|
238
250
|
intendToList: toRef(state, "intendToList"),
|
|
239
251
|
listArgs: toRef(parentState, "listArgs"),
|