@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.
@@ -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(", ")}`);
@@ -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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arrai-innovations/reactive-helpers",
3
- "version": "13.0.3",
3
+ "version": "13.0.4",
4
4
  "description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -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: {} });
@@ -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,
package/use/listKeys.js CHANGED
@@ -17,6 +17,7 @@ export const listInstanceStateKeys = [
17
17
  ];
18
18
  export const listInstanceFunctions = [
19
19
  "list",
20
+ "bulkDelete",
20
21
  "addListObject",
21
22
  "updateListObject",
22
23
  "deleteListObject",