@arrai-innovations/reactive-helpers 2.0.0 → 2.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arrai-innovations/reactive-helpers",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -219,14 +219,45 @@ describe("use/objectInstance.js", function () {
219
219
  id,
220
220
  retrieveArgs,
221
221
  });
222
+ objectInstance.state.crud.create = jest.fn();
223
+ objectInstance.state.crud.create.mockImplementation(() => new Promise(() => {}));
222
224
  objectInstance.state.crud.retrieve = jest.fn();
223
225
  objectInstance.state.crud.retrieve.mockImplementation(() => new Promise(() => {}));
224
226
  expectErrorToBeNull(objectInstance.state.error);
225
227
  expect(objectInstance.state.errored).toBe(false);
226
228
  expect(objectInstance.state.loading).toBeUndefined();
227
229
  expect({ ...objectInstance.state.object }).toEqual({});
228
- objectInstance.retrieve();
230
+ objectInstance.create({
231
+ fake: "object",
232
+ });
233
+ expectErrorToBeNull(objectInstance.state.error);
234
+ expect(objectInstance.state.errored).toBe(false);
235
+ expect(objectInstance.state.loading).toBe(true);
229
236
  await expect(() => objectInstance.retrieve()).rejects.toThrow(ObjectError);
237
+ expect(objectInstance.state.crud.retrieve).toHaveBeenCalledTimes(0);
238
+ expectErrorToBeNull(objectInstance.state.error);
239
+ expect(objectInstance.state.errored).toBe(false);
240
+ expect(objectInstance.state.loading).toBe(true);
241
+ expect({ ...objectInstance.state.object }).toEqual({});
242
+ });
243
+ it("double retrieve gets the same promise", async function () {
244
+ const id = ref(1);
245
+ const retrieveArgs = reactive({ fields });
246
+ const objectInstance = useObjectInstance({
247
+ crudArgs: { stream: "test_stream" },
248
+ id,
249
+ retrieveArgs,
250
+ });
251
+ objectInstance.state.crud.retrieve = jest.fn();
252
+ objectInstance.state.crud.retrieve.mockImplementation(() => new Promise(() => {}));
253
+ expectErrorToBeNull(objectInstance.state.error);
254
+ expect(objectInstance.state.errored).toBe(false);
255
+ expect(objectInstance.state.loading).toBeUndefined();
256
+ expect({ ...objectInstance.state.object }).toEqual({});
257
+ const firstPromise = objectInstance.retrieve();
258
+ const secondPromise = objectInstance.retrieve();
259
+ // await expect(() => objectInstance.retrieve()).rejects.toThrow(ObjectError);
260
+ expect(firstPromise).toBe(secondPromise);
230
261
  expect(objectInstance.state.crud.retrieve).toHaveBeenCalledWith({
231
262
  crudArgs: { stream: "test_stream" },
232
263
  id: 1,
@@ -175,7 +175,10 @@ export function useListSubscription({ listInstance, crudArgs, listArgs, retrieve
175
175
  state.subscribed = toRef(subscribeIntent.state, "active");
176
176
 
177
177
  listIntent = useCancellableIntent({
178
- awaitableWithCancel: listInstance.list,
178
+ awaitableWithCancel: () => {
179
+ listInstance.clearList();
180
+ return listInstance.list();
181
+ },
179
182
  watchArguments: [toRef(state, "intendToList"), toRef(state, "listArgs"), toRef(state, "retrieveArgs")],
180
183
  });
181
184
  });
@@ -59,15 +59,26 @@ export function useObjectInstance({ crudArgs, id, retrieveArgs }) {
59
59
  assignReactiveObject(state.crud.args, crudArgs);
60
60
  }
61
61
 
62
+ // due to retrieve being called by `useCancelleableIntent`, if called manually then by the watch,
63
+ // it will run into the loading check. Instead, return the current retrieve promise if it exists.
64
+ const promises = {
65
+ retrieve: null,
66
+ };
67
+
62
68
  function retrieve() {
63
69
  // this function cannot be async, or the resulting promise will lose its .cancel() method
70
+ if (promises.retrieve) {
71
+ // if a retrieve is already in progress, return the existing promise
72
+ return promises.retrieve;
73
+ }
64
74
  if (state.loading) {
75
+ // if another operation is already in progress, return a rejected promise
65
76
  return Promise.reject(new ObjectError("already loading."));
66
77
  }
67
78
  state.loading = true;
68
79
  state.errored = false;
69
80
  state.error = null;
70
- return state.crud
81
+ promises.retrieve = state.crud
71
82
  .retrieve({
72
83
  crudArgs: state.crud.args,
73
84
  id: state.id,
@@ -84,7 +95,9 @@ export function useObjectInstance({ crudArgs, id, retrieveArgs }) {
84
95
  })
85
96
  .finally(() => {
86
97
  state.loading = false;
98
+ promises.retrieve = null;
87
99
  });
100
+ return promises.retrieve;
88
101
  }
89
102
 
90
103
  async function create({ object }) {