@arrai-innovations/reactive-helpers 13.0.3 → 13.0.4
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/config/listCrud.js +14 -1
- package/docs/config/listCrud.md +44 -0
- package/docs/use/listInstance.md +7 -0
- package/package.json +1 -1
- package/tests/unit/config/listCrud.spec.js +1 -1
- package/tests/unit/use/listInstance.spec.js +49 -1
- package/use/listInstance.js +30 -0
- package/use/listKeys.js +1 -0
package/config/listCrud.js
CHANGED
|
@@ -12,6 +12,7 @@ import { isReactive, toRef } from "vue";
|
|
|
12
12
|
const defaultCrud = {
|
|
13
13
|
args: {},
|
|
14
14
|
list: undefined,
|
|
15
|
+
bulkDelete: undefined,
|
|
15
16
|
subscribe: undefined,
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -39,6 +40,12 @@ const defaultCrud = {
|
|
|
39
40
|
* been cancelled.
|
|
40
41
|
*/
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {object} DeleteFnArgs
|
|
45
|
+
* @property {object} crudArgs - The arguments to be passed to the crud functions.
|
|
46
|
+
* @property {string[]} ids - The ids of the objects to be deleted.
|
|
47
|
+
*/
|
|
48
|
+
|
|
42
49
|
/**
|
|
43
50
|
* @typedef {(
|
|
44
51
|
* newOrUpdatedOrDeleteObject:import('../use/listInstance.js').ListObject|string,
|
|
@@ -58,6 +65,10 @@ const defaultCrud = {
|
|
|
58
65
|
* @typedef {(ListFnArgs)=>void} ListFn
|
|
59
66
|
*/
|
|
60
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @typedef {(DeleteFnArgs)=>void} BulkDeleteFn
|
|
70
|
+
*/
|
|
71
|
+
|
|
61
72
|
/**
|
|
62
73
|
* @typedef {(SubscribeFnArgs)=>void} SubscribeFn
|
|
63
74
|
*/
|
|
@@ -65,6 +76,7 @@ const defaultCrud = {
|
|
|
65
76
|
/**
|
|
66
77
|
* @typedef {object} ListCrudFunctions
|
|
67
78
|
* @property {ListFn} [list] - The list function to get a list of items.
|
|
79
|
+
* @property {BulkDeleteFn} [bulkDelete] - The delete function to bulk delete a list of items.
|
|
68
80
|
* @property {SubscribeFn} [subscribe] - The subscribe function to get a subscription to a list of items.
|
|
69
81
|
*/
|
|
70
82
|
|
|
@@ -80,9 +92,10 @@ const defaultCrud = {
|
|
|
80
92
|
* @throws {Error} - If unknown keys are passed.
|
|
81
93
|
* @returns {void}
|
|
82
94
|
*/
|
|
83
|
-
export const setListCrud = ({ list, subscribe, args = {}, ...rest }) => {
|
|
95
|
+
export const setListCrud = ({ list, bulkDelete, subscribe, args = {}, ...rest }) => {
|
|
84
96
|
defaultCrud.list = list;
|
|
85
97
|
defaultCrud.subscribe = subscribe;
|
|
98
|
+
defaultCrud.bulkDelete = bulkDelete;
|
|
86
99
|
Object.assign(defaultCrud.args, cloneDeep(args));
|
|
87
100
|
if (Object.keys(rest).length) {
|
|
88
101
|
throw new Error(`Unknown key(s) passed to setListCrud: ${Object.keys(rest).join(", ")}`);
|
package/docs/config/listCrud.md
CHANGED
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
|
|
9
9
|
## Interfaces
|
|
10
10
|
|
|
11
|
+
### DeleteFnArgs
|
|
12
|
+
|
|
13
|
+
#### Properties
|
|
14
|
+
|
|
15
|
+
##### crudArgs
|
|
16
|
+
|
|
17
|
+
> **crudArgs**: `any`
|
|
18
|
+
|
|
19
|
+
The arguments to be passed to the crud functions.
|
|
20
|
+
|
|
21
|
+
##### ids
|
|
22
|
+
|
|
23
|
+
> **ids**: `string`[]
|
|
24
|
+
|
|
25
|
+
The ids of the objects to be deleted.
|
|
26
|
+
|
|
27
|
+
***
|
|
28
|
+
|
|
11
29
|
### ListCrudArgs
|
|
12
30
|
|
|
13
31
|
#### Properties
|
|
@@ -24,6 +42,12 @@ The default arguments for the crud functions.
|
|
|
24
42
|
|
|
25
43
|
#### Properties
|
|
26
44
|
|
|
45
|
+
##### bulkDelete
|
|
46
|
+
|
|
47
|
+
> **bulkDelete**: [`BulkDeleteFn`](listCrud.md#bulkdeletefn)
|
|
48
|
+
|
|
49
|
+
The delete function to bulk delete a list of items.
|
|
50
|
+
|
|
27
51
|
##### list
|
|
28
52
|
|
|
29
53
|
> **list**: [`ListFn`](listCrud.md#listfn)
|
|
@@ -129,6 +153,22 @@ The method to call when new data is received.
|
|
|
129
153
|
|
|
130
154
|
## Type Aliases
|
|
131
155
|
|
|
156
|
+
### BulkDeleteFn()
|
|
157
|
+
|
|
158
|
+
> **BulkDeleteFn**\<\>: (`DeleteFnArgs`) => `void`
|
|
159
|
+
|
|
160
|
+
#### Type Parameters
|
|
161
|
+
|
|
162
|
+
#### Parameters
|
|
163
|
+
|
|
164
|
+
• **DeleteFnArgs**: `any`
|
|
165
|
+
|
|
166
|
+
#### Returns
|
|
167
|
+
|
|
168
|
+
`void`
|
|
169
|
+
|
|
170
|
+
***
|
|
171
|
+
|
|
132
172
|
### ListFn()
|
|
133
173
|
|
|
134
174
|
> **ListFn**\<\>: (`ListFnArgs`) => `void`
|
|
@@ -213,6 +253,10 @@ The reactive crud object, which will be mutated.
|
|
|
213
253
|
|
|
214
254
|
The default arguments for the crud functions.
|
|
215
255
|
|
|
256
|
+
• **reactiveCrud.bulkDelete**: [`BulkDeleteFn`](listCrud.md#bulkdeletefn)
|
|
257
|
+
|
|
258
|
+
The delete function to bulk delete a list of items.
|
|
259
|
+
|
|
216
260
|
• **reactiveCrud.list**: [`ListFn`](listCrud.md#listfn)
|
|
217
261
|
|
|
218
262
|
The list function to get a list of items.
|
package/docs/use/listInstance.md
CHANGED
|
@@ -175,6 +175,13 @@ Updates an object in the list.
|
|
|
175
175
|
|
|
176
176
|
Default implementation are used as set by `setListCrud`.
|
|
177
177
|
|
|
178
|
+
###### bulkDelete
|
|
179
|
+
|
|
180
|
+
> **bulkDelete**: [`BulkDeleteFn`](../config/listCrud.md#bulkdeletefn)
|
|
181
|
+
|
|
182
|
+
Provide the implementation for the bulkDelete
|
|
183
|
+
function.
|
|
184
|
+
|
|
178
185
|
###### list
|
|
179
186
|
|
|
180
187
|
> **list**: [`ListFn`](../config/listCrud.md#listfn)
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@ describe("config/listCrud.js", () => {
|
|
|
30
30
|
*/
|
|
31
31
|
const retrievedCrud = reactive({});
|
|
32
32
|
expect(() => getListCrud(retrievedCrud)).not.toThrow();
|
|
33
|
-
expect(new Set(Object.keys(retrievedCrud))).toEqual(new Set(["list", "subscribe", "args"]));
|
|
33
|
+
expect(new Set(Object.keys(retrievedCrud))).toEqual(new Set(["list", "bulkDelete", "subscribe", "args"]));
|
|
34
34
|
expect(retrievedCrud.args).not.toBe(crud.args);
|
|
35
35
|
expect(retrievedCrud.args).toEqual(crud.args);
|
|
36
36
|
expect(retrievedCrud.list).toBe(crud.list);
|
|
@@ -11,15 +11,17 @@ afterAll(() => {
|
|
|
11
11
|
|
|
12
12
|
const fields = ["id", "__str__", "name"];
|
|
13
13
|
describe("use/listInstance.spec.js", function () {
|
|
14
|
-
let useListInstance, ListInstanceError, useListInstances, globalList;
|
|
14
|
+
let useListInstance, ListInstanceError, useListInstances, globalList, globalbulkDelete;
|
|
15
15
|
beforeEach(async () => {
|
|
16
16
|
const listCrud = await import("../../../config/listCrud.js");
|
|
17
17
|
const imported = await import("../../../use/listInstance.js");
|
|
18
18
|
globalList = vi.fn();
|
|
19
|
+
globalbulkDelete = vi.fn(() => Promise.resolve(true));
|
|
19
20
|
// @ts-ignore
|
|
20
21
|
globalList.cancel = vi.fn();
|
|
21
22
|
listCrud.setListCrud({
|
|
22
23
|
list: globalList,
|
|
24
|
+
bulkDelete: globalbulkDelete,
|
|
23
25
|
args: { stream: "test_stream" },
|
|
24
26
|
});
|
|
25
27
|
useListInstance = imported.useListInstance;
|
|
@@ -513,6 +515,52 @@ describe("use/listInstance.spec.js", function () {
|
|
|
513
515
|
expect(listInstance.state.order).toEqual(["2", "3"]);
|
|
514
516
|
});
|
|
515
517
|
});
|
|
518
|
+
describe("bulkDelete", function () {
|
|
519
|
+
it("succeeds", async function () {
|
|
520
|
+
const listArgs = reactive({
|
|
521
|
+
user: 1,
|
|
522
|
+
});
|
|
523
|
+
const retrieveArgs = reactive({
|
|
524
|
+
fields,
|
|
525
|
+
});
|
|
526
|
+
const listInstance = useListInstance({ props: { listArgs, retrieveArgs } });
|
|
527
|
+
let crudListResolve;
|
|
528
|
+
const crudListPromise = new Promise((resolve) => {
|
|
529
|
+
crudListResolve = resolve;
|
|
530
|
+
});
|
|
531
|
+
let passedPageCallback;
|
|
532
|
+
globalList.mockImplementation(({ pageCallback }) => {
|
|
533
|
+
passedPageCallback = pageCallback;
|
|
534
|
+
return crudListPromise;
|
|
535
|
+
});
|
|
536
|
+
const liListResolve = listInstance.list();
|
|
537
|
+
await nextTick();
|
|
538
|
+
// @ts-ignore - pageCallback is set in the mock, if not it will throw which is what we want
|
|
539
|
+
passedPageCallback(crudListResolvedPage2);
|
|
540
|
+
// @ts-ignore - crudListResolve is set in a promise, since we await this will be set
|
|
541
|
+
crudListResolve();
|
|
542
|
+
await flushPromises();
|
|
543
|
+
await expect(liListResolve).resolves.toBe(true);
|
|
544
|
+
|
|
545
|
+
expect({ ...listInstance.state.objects }).toEqual(crudListResolvedObjects2);
|
|
546
|
+
const bulkDeleteResolve = listInstance.bulkDelete();
|
|
547
|
+
expectErrorToBeNull(listInstance.state.error);
|
|
548
|
+
expect(listInstance.state.errored).toBe(false);
|
|
549
|
+
expect(listInstance.state.loading).toBe(true);
|
|
550
|
+
expect(globalbulkDelete).toHaveBeenCalledWith({
|
|
551
|
+
crudArgs: { stream: "test_stream" },
|
|
552
|
+
ids: Object.keys(crudListResolvedObjects2).map(Number),
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
expect(globalbulkDelete).toHaveBeenCalledTimes(1);
|
|
556
|
+
|
|
557
|
+
// @ts-ignore - bulkDeleteResolve is set in a promise, since we await this will be set
|
|
558
|
+
crudListResolve();
|
|
559
|
+
await flushPromises();
|
|
560
|
+
await expect(bulkDeleteResolve).resolves.toBe(true);
|
|
561
|
+
expect({ ...listInstance.state.objects }).toEqual({});
|
|
562
|
+
});
|
|
563
|
+
});
|
|
516
564
|
describe("getFakeId", function () {
|
|
517
565
|
it("returns fakeId", function () {
|
|
518
566
|
const listInstance = useListInstance({ props: {} });
|
package/use/listInstance.js
CHANGED
|
@@ -53,6 +53,8 @@ export class ListInstanceError extends Error {
|
|
|
53
53
|
* @property {object} [functions] - Default implementation are used as set by `setListCrud`.
|
|
54
54
|
* @property {import('../config/listCrud.js').ListFn} [functions.list] - Provide the implementation for the list
|
|
55
55
|
* function.
|
|
56
|
+
* @property {import('../config/listCrud.js').BulkDeleteFn} [functions.bulkDelete] - Provide the implementation for the bulkDelete
|
|
57
|
+
* function.
|
|
56
58
|
* @property {import('../config/listCrud.js').SubscribeFn} [functions.subscribe] - Provide the implementation for the
|
|
57
59
|
* subscribe function.
|
|
58
60
|
* @property {boolean} [keepOldPages=false] - If true, pages will not be cleared when defaultPageCallback is called.
|
|
@@ -254,6 +256,7 @@ export function useListInstance({ props, functions = {}, keepOldPages = false })
|
|
|
254
256
|
crud: {
|
|
255
257
|
args: {},
|
|
256
258
|
list: undefined,
|
|
259
|
+
bulkDelete: undefined,
|
|
257
260
|
},
|
|
258
261
|
retrieveArgs: toRef(props, "retrieveArgs"),
|
|
259
262
|
listArgs: toRef(props, "listArgs"),
|
|
@@ -292,6 +295,31 @@ export function useListInstance({ props, functions = {}, keepOldPages = false })
|
|
|
292
295
|
list: null,
|
|
293
296
|
};
|
|
294
297
|
|
|
298
|
+
async function bulkDeleteFn() {
|
|
299
|
+
if (state.loading) {
|
|
300
|
+
return Promise.reject(new ListInstanceError("already loading.", "already-loading"));
|
|
301
|
+
}
|
|
302
|
+
loadingError.setLoading();
|
|
303
|
+
loadingError.clearError();
|
|
304
|
+
return state.crud
|
|
305
|
+
.bulkDelete({
|
|
306
|
+
crudArgs: state.crud.args,
|
|
307
|
+
ids: Object.keys(state.objects).map(Number),
|
|
308
|
+
})
|
|
309
|
+
.then(() => {
|
|
310
|
+
assignReactiveObject(state.objects, {});
|
|
311
|
+
loadingError.clearError();
|
|
312
|
+
return Promise.resolve(true);
|
|
313
|
+
})
|
|
314
|
+
.catch((error) => {
|
|
315
|
+
loadingError.setError(error);
|
|
316
|
+
return Promise.resolve(false);
|
|
317
|
+
})
|
|
318
|
+
.finally(() => {
|
|
319
|
+
loadingError.clearLoading();
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
295
323
|
function list() {
|
|
296
324
|
// this function cannot be async, or the resulting promise will lose its .cancel() method
|
|
297
325
|
if (promises.list) {
|
|
@@ -316,6 +344,7 @@ export function useListInstance({ props, functions = {}, keepOldPages = false })
|
|
|
316
344
|
pageCallback: returnedObject.pageCallback,
|
|
317
345
|
isCancelled: readonly(isCancelled),
|
|
318
346
|
});
|
|
347
|
+
|
|
319
348
|
let resolveState = false;
|
|
320
349
|
if (listPromise.cancel) {
|
|
321
350
|
promises.list.cancel = async () => {
|
|
@@ -422,6 +451,7 @@ export function useListInstance({ props, functions = {}, keepOldPages = false })
|
|
|
422
451
|
const returnedObject = {
|
|
423
452
|
state,
|
|
424
453
|
list,
|
|
454
|
+
bulkDelete: bulkDeleteFn,
|
|
425
455
|
addListObject,
|
|
426
456
|
updateListObject,
|
|
427
457
|
deleteListObject,
|