@finema/core 3.17.2 → 3.18.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.
Files changed (88) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +1 -1
  3. package/dist/runtime/components/FlexDeck/index.vue +79 -79
  4. package/dist/runtime/components/Form/FieldWrapper.vue +13 -13
  5. package/dist/runtime/components/Form/Fields.vue +13 -13
  6. package/dist/runtime/components/Form/InputCheckbox/index.d.vue.ts +5 -1
  7. package/dist/runtime/components/Form/InputCheckbox/index.vue +18 -18
  8. package/dist/runtime/components/Form/InputCheckbox/index.vue.d.ts +5 -1
  9. package/dist/runtime/components/Form/InputCheckboxGroup/index.d.vue.ts +5 -1
  10. package/dist/runtime/components/Form/InputCheckboxGroup/index.vue +21 -21
  11. package/dist/runtime/components/Form/InputCheckboxGroup/index.vue.d.ts +5 -1
  12. package/dist/runtime/components/Form/InputCurrency/index.d.vue.ts +5 -1
  13. package/dist/runtime/components/Form/InputCurrency/index.vue +49 -49
  14. package/dist/runtime/components/Form/InputCurrency/index.vue.d.ts +5 -1
  15. package/dist/runtime/components/Form/InputDateTime/index.d.vue.ts +5 -1
  16. package/dist/runtime/components/Form/InputDateTime/index.vue +63 -63
  17. package/dist/runtime/components/Form/InputDateTime/index.vue.d.ts +5 -1
  18. package/dist/runtime/components/Form/InputDateTimeRange/index.d.vue.ts +5 -1
  19. package/dist/runtime/components/Form/InputDateTimeRange/index.vue +56 -56
  20. package/dist/runtime/components/Form/InputDateTimeRange/index.vue.d.ts +5 -1
  21. package/dist/runtime/components/Form/InputMonth/index.d.vue.ts +5 -1
  22. package/dist/runtime/components/Form/InputMonth/index.vue.d.ts +5 -1
  23. package/dist/runtime/components/Form/InputNumber/index.d.vue.ts +5 -1
  24. package/dist/runtime/components/Form/InputNumber/index.vue +20 -20
  25. package/dist/runtime/components/Form/InputNumber/index.vue.d.ts +5 -1
  26. package/dist/runtime/components/Form/InputSearch/index.d.vue.ts +9 -1
  27. package/dist/runtime/components/Form/InputSearch/index.vue.d.ts +9 -1
  28. package/dist/runtime/components/Form/InputSelect/index.d.vue.ts +7 -1
  29. package/dist/runtime/components/Form/InputSelect/index.vue +110 -110
  30. package/dist/runtime/components/Form/InputSelect/index.vue.d.ts +7 -1
  31. package/dist/runtime/components/Form/InputSelectMultiple/index.d.vue.ts +7 -1
  32. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +118 -118
  33. package/dist/runtime/components/Form/InputSelectMultiple/index.vue.d.ts +7 -1
  34. package/dist/runtime/components/Form/InputTags/index.d.vue.ts +11 -1
  35. package/dist/runtime/components/Form/InputTags/index.vue +54 -54
  36. package/dist/runtime/components/Form/InputTags/index.vue.d.ts +11 -1
  37. package/dist/runtime/components/Form/InputText/index.d.vue.ts +7 -1
  38. package/dist/runtime/components/Form/InputText/index.vue +85 -85
  39. package/dist/runtime/components/Form/InputText/index.vue.d.ts +7 -1
  40. package/dist/runtime/components/Form/InputTextarea/index.d.vue.ts +5 -1
  41. package/dist/runtime/components/Form/InputTextarea/index.vue +18 -18
  42. package/dist/runtime/components/Form/InputTextarea/index.vue.d.ts +5 -1
  43. package/dist/runtime/components/Form/InputTime/index.d.vue.ts +5 -1
  44. package/dist/runtime/components/Form/InputTime/index.vue +38 -38
  45. package/dist/runtime/components/Form/InputTime/index.vue.d.ts +5 -1
  46. package/dist/runtime/components/Form/InputToggle/index.d.vue.ts +5 -1
  47. package/dist/runtime/components/Form/InputToggle/index.vue +17 -17
  48. package/dist/runtime/components/Form/InputToggle/index.vue.d.ts +5 -1
  49. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +30 -30
  50. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +50 -50
  51. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +50 -50
  52. package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +50 -50
  53. package/dist/runtime/components/Form/InputWYSIWYG/EditorImageUploadNode.vue +18 -18
  54. package/dist/runtime/components/Form/InputWYSIWYG/EditorLinkPopover.vue +65 -65
  55. package/dist/runtime/components/Form/InputWYSIWYG/README.md +96 -96
  56. package/dist/runtime/components/Form/InputWYSIWYG/index.vue +41 -41
  57. package/dist/runtime/components/Form/fileState/EmptyState.vue +21 -21
  58. package/dist/runtime/components/Form/fileState/FailedState.vue +33 -33
  59. package/dist/runtime/components/Form/fileState/LoadingState.vue +24 -24
  60. package/dist/runtime/components/Form/fileState/MultipleFilesState.vue +75 -75
  61. package/dist/runtime/components/Form/fileState/PreviewModal.vue +23 -23
  62. package/dist/runtime/components/Form/index.vue +5 -5
  63. package/dist/runtime/components/Image.vue +28 -28
  64. package/dist/runtime/components/Log/index.vue +17 -17
  65. package/dist/runtime/components/Table/Base.d.vue.ts +8 -2
  66. package/dist/runtime/components/Table/Base.vue +117 -117
  67. package/dist/runtime/components/Table/Base.vue.d.ts +8 -2
  68. package/dist/runtime/components/Table/ColumnDate.vue +1 -1
  69. package/dist/runtime/components/Table/ColumnDateTime.vue +1 -1
  70. package/dist/runtime/components/Table/ColumnImage.vue +4 -4
  71. package/dist/runtime/components/Table/ColumnText.vue +10 -10
  72. package/dist/runtime/components/Table/Pagination.vue +62 -62
  73. package/dist/runtime/components/Table/Simple.vue +19 -19
  74. package/dist/runtime/components/Table/index.vue +33 -33
  75. package/dist/runtime/composables/loaderList.js +38 -15
  76. package/dist/runtime/composables/loaderObject.js +49 -20
  77. package/dist/runtime/composables/loaderPage.js +300 -168
  78. package/dist/runtime/helpers/apiBaseHelper.d.ts +3 -2
  79. package/dist/runtime/helpers/apiBaseHelper.js +33 -3
  80. package/dist/runtime/helpers/apiCancelHelper.d.ts +6 -0
  81. package/dist/runtime/helpers/apiCancelHelper.js +22 -0
  82. package/dist/runtime/helpers/apiListHelper.js +2 -1
  83. package/dist/runtime/helpers/apiObjectHelper.d.ts +3 -1
  84. package/dist/runtime/helpers/apiObjectHelper.js +2 -1
  85. package/dist/runtime/helpers/apiPageHelper.d.ts +9 -3
  86. package/dist/runtime/helpers/apiPageHelper.js +10 -5
  87. package/dist/runtime/server/tsconfig.json +3 -3
  88. package/package.json +2 -2
@@ -1,5 +1,6 @@
1
1
  import { reactive } from "vue";
2
2
  import { ObjectHelper } from "../utils/ObjectHelper.js";
3
+ import { createCancelableRequest } from "../helpers/apiCancelHelper.js";
3
4
  import {
4
5
  apiAddHelper,
5
6
  apiDeleteHelper,
@@ -49,7 +50,88 @@ export const usePageLoader = (loaderOptions) => {
49
50
  item: null,
50
51
  options: {}
51
52
  });
53
+ const requests = {
54
+ fetch: null,
55
+ find: null,
56
+ add: null,
57
+ update: null,
58
+ delete: null
59
+ };
60
+ const isActiveRequest = (key, currentRequest) => {
61
+ return requests[key] === currentRequest;
62
+ };
63
+ const canUpdateRequest = (key, currentRequest) => {
64
+ return isActiveRequest(key, currentRequest) || !currentRequest.signal.aborted;
65
+ };
66
+ const completeStatus = (status) => ObjectHelper.toCompleteStatus(status);
67
+ const cancelFetch = () => {
68
+ const currentRequest = requests.fetch;
69
+ if (!currentRequest) return;
70
+ currentRequest.controller.abort();
71
+ currentRequest.cleanup();
72
+ requests.fetch = null;
73
+ fetch.status = completeStatus(fetch.status);
74
+ fetch.statusNextPage = completeStatus(fetch.statusNextPage);
75
+ };
76
+ const cancelFind = () => {
77
+ const currentRequest = requests.find;
78
+ if (!currentRequest) return;
79
+ currentRequest.controller.abort();
80
+ currentRequest.cleanup();
81
+ requests.find = null;
82
+ find.status = completeStatus(find.status);
83
+ };
84
+ const cancelAdd = () => {
85
+ const currentRequest = requests.add;
86
+ if (!currentRequest) return;
87
+ currentRequest.controller.abort();
88
+ currentRequest.cleanup();
89
+ requests.add = null;
90
+ add.status = completeStatus(add.status);
91
+ };
92
+ const cancelUpdate = () => {
93
+ const currentRequest = requests.update;
94
+ if (!currentRequest) return;
95
+ currentRequest.controller.abort();
96
+ currentRequest.cleanup();
97
+ requests.update = null;
98
+ update.status = completeStatus(update.status);
99
+ };
100
+ const cancelDelete = () => {
101
+ const currentRequest = requests.delete;
102
+ if (!currentRequest) return;
103
+ currentRequest.controller.abort();
104
+ currentRequest.cleanup();
105
+ requests.delete = null;
106
+ del.status = completeStatus(del.status);
107
+ };
108
+ const cancelAll = () => {
109
+ cancelFetch();
110
+ cancelFind();
111
+ cancelAdd();
112
+ cancelUpdate();
113
+ cancelDelete();
114
+ };
115
+ const cancelRequestByKey = (key) => {
116
+ if (key === "fetch") cancelFetch();
117
+ if (key === "find") cancelFind();
118
+ if (key === "add") cancelAdd();
119
+ if (key === "update") cancelUpdate();
120
+ if (key === "delete") cancelDelete();
121
+ };
122
+ const startRequest = (key, externalSignal, autoCancel = true) => {
123
+ if (autoCancel) cancelRequestByKey(key);
124
+ const currentRequest = createCancelableRequest(externalSignal);
125
+ requests[key] = currentRequest;
126
+ return currentRequest;
127
+ };
128
+ const finishRequest = (key, currentRequest) => {
129
+ currentRequest.cleanup();
130
+ if (!isActiveRequest(key, currentRequest)) return;
131
+ requests[key] = null;
132
+ };
52
133
  const clearAll = () => {
134
+ cancelAll();
53
135
  find.status = ObjectHelper.createStatus();
54
136
  del.status = ObjectHelper.createStatus();
55
137
  add.status = ObjectHelper.createStatus();
@@ -78,138 +160,168 @@ export const usePageLoader = (loaderOptions) => {
78
160
  find.status = ObjectHelper.toLoadingStatus(find.status);
79
161
  };
80
162
  const fetchPage = async (page = 1, query = "", opts) => {
81
- await apiFetchHelper(
82
- () => ({
83
- status: fetch.status,
84
- items: fetch.items,
85
- options: fetch.options
86
- }),
87
- (data) => {
88
- fetch.status = data;
89
- },
90
- (data) => {
91
- fetch.options = data;
92
- },
93
- (data) => {
94
- fetch.items = data;
95
- },
96
- page,
97
- query,
98
- {
99
- ...loaderOptions,
100
- ...opts
101
- }
102
- );
163
+ const currentRequest = startRequest("fetch", opts?.signal);
164
+ try {
165
+ await apiFetchHelper(
166
+ () => ({
167
+ status: fetch.status,
168
+ items: fetch.items,
169
+ options: fetch.options
170
+ }),
171
+ (data) => {
172
+ if (canUpdateRequest("fetch", currentRequest)) fetch.status = data;
173
+ },
174
+ (data) => {
175
+ if (canUpdateRequest("fetch", currentRequest)) fetch.options = data;
176
+ },
177
+ (data) => {
178
+ if (canUpdateRequest("fetch", currentRequest)) fetch.items = data;
179
+ },
180
+ page,
181
+ query,
182
+ {
183
+ ...loaderOptions,
184
+ ...opts,
185
+ signal: currentRequest.signal
186
+ }
187
+ );
188
+ } finally {
189
+ finishRequest("fetch", currentRequest);
190
+ }
103
191
  };
104
192
  const fetchAll = async (query = "", opts = {}) => {
105
193
  opts.params = {
106
194
  ...opts.params,
107
195
  limit: 99999
108
196
  };
109
- await apiFetchHelper(
110
- () => ({
111
- status: fetch.status,
112
- items: fetch.items,
113
- options: fetch.options
114
- }),
115
- (data) => {
116
- fetch.status = data;
117
- },
118
- (data) => {
119
- fetch.options = data;
120
- },
121
- (data) => {
122
- fetch.items = data;
123
- },
124
- 1,
125
- query,
126
- {
127
- ...loaderOptions,
128
- ...opts
129
- }
130
- );
197
+ const currentRequest = startRequest("fetch", opts.signal);
198
+ try {
199
+ await apiFetchHelper(
200
+ () => ({
201
+ status: fetch.status,
202
+ items: fetch.items,
203
+ options: fetch.options
204
+ }),
205
+ (data) => {
206
+ if (canUpdateRequest("fetch", currentRequest)) fetch.status = data;
207
+ },
208
+ (data) => {
209
+ if (canUpdateRequest("fetch", currentRequest)) fetch.options = data;
210
+ },
211
+ (data) => {
212
+ if (canUpdateRequest("fetch", currentRequest)) fetch.items = data;
213
+ },
214
+ 1,
215
+ query,
216
+ {
217
+ ...loaderOptions,
218
+ ...opts,
219
+ signal: currentRequest.signal
220
+ }
221
+ );
222
+ } finally {
223
+ finishRequest("fetch", currentRequest);
224
+ }
131
225
  };
132
226
  const findRun = async (id, opts) => {
133
- await apiFindHelper(
134
- () => ({
135
- status: find.status,
136
- data: find.item,
137
- options: find.options
138
- }),
139
- (data) => {
140
- find.status = data;
141
- },
142
- (data) => {
143
- find.options = data;
144
- },
145
- (data) => {
146
- find.item = data;
147
- },
148
- id,
149
- {
150
- ...loaderOptions,
151
- ...opts
152
- }
153
- );
227
+ const currentRequest = startRequest("find", opts?.signal);
228
+ try {
229
+ await apiFindHelper(
230
+ () => ({
231
+ status: find.status,
232
+ data: find.item,
233
+ options: find.options
234
+ }),
235
+ (data) => {
236
+ if (canUpdateRequest("find", currentRequest)) find.status = data;
237
+ },
238
+ (data) => {
239
+ if (canUpdateRequest("find", currentRequest)) find.options = data;
240
+ },
241
+ (data) => {
242
+ if (canUpdateRequest("find", currentRequest)) find.item = data;
243
+ },
244
+ id,
245
+ {
246
+ ...loaderOptions,
247
+ ...opts,
248
+ signal: currentRequest.signal
249
+ }
250
+ );
251
+ } finally {
252
+ finishRequest("find", currentRequest);
253
+ }
154
254
  };
155
255
  const addRun = async (payload) => {
156
- await apiAddHelper(
157
- () => ({
158
- items: fetch.items,
159
- status: add.status,
160
- data: add.item,
161
- options: add.options
162
- }),
163
- (data) => {
164
- add.status = data;
165
- },
166
- (data) => {
167
- add.options = data;
168
- },
169
- (data) => {
170
- add.item = data;
171
- },
172
- (data) => {
173
- fetch.items = data;
174
- },
175
- payload.data,
176
- {
177
- ...loaderOptions,
178
- ...payload
179
- }
180
- );
256
+ const currentRequest = startRequest("add", payload.signal, false);
257
+ try {
258
+ await apiAddHelper(
259
+ () => ({
260
+ items: fetch.items,
261
+ status: add.status,
262
+ data: add.item,
263
+ options: add.options
264
+ }),
265
+ (data) => {
266
+ if (canUpdateRequest("add", currentRequest)) add.status = data;
267
+ },
268
+ (data) => {
269
+ if (canUpdateRequest("add", currentRequest)) add.options = data;
270
+ },
271
+ (data) => {
272
+ if (canUpdateRequest("add", currentRequest)) add.item = data;
273
+ },
274
+ (data) => {
275
+ if (canUpdateRequest("add", currentRequest)) fetch.items = data;
276
+ },
277
+ payload.data,
278
+ {
279
+ ...loaderOptions,
280
+ ...payload,
281
+ signal: currentRequest.signal
282
+ }
283
+ );
284
+ } finally {
285
+ finishRequest("add", currentRequest);
286
+ }
181
287
  };
182
288
  const updateRun = async (id, payload) => {
183
- await updateHelper(
184
- () => ({
185
- items: fetch.items,
186
- status: update.status,
187
- data: update.item,
188
- oldData: find.item,
189
- options: update.options
190
- }),
191
- (data) => {
192
- update.status = data;
193
- },
194
- (data) => {
195
- update.options = data;
196
- },
197
- (data) => {
198
- update.item = data;
199
- },
200
- (data) => {
201
- fetch.items = data;
202
- },
203
- (data) => {
204
- find.item = data;
205
- },
206
- id,
207
- payload.data,
208
- {
209
- ...loaderOptions,
210
- ...payload
211
- }
212
- );
289
+ const currentRequest = startRequest("update", payload.signal, false);
290
+ try {
291
+ await updateHelper(
292
+ () => ({
293
+ items: fetch.items,
294
+ status: update.status,
295
+ data: update.item,
296
+ oldData: find.item,
297
+ options: update.options
298
+ }),
299
+ (data) => {
300
+ if (canUpdateRequest("update", currentRequest)) update.status = data;
301
+ },
302
+ (data) => {
303
+ if (canUpdateRequest("update", currentRequest)) update.options = data;
304
+ },
305
+ (data) => {
306
+ if (canUpdateRequest("update", currentRequest)) update.item = data;
307
+ },
308
+ (data) => {
309
+ if (canUpdateRequest("update", currentRequest)) fetch.items = data;
310
+ },
311
+ (data) => {
312
+ if (canUpdateRequest("update", currentRequest)) find.item = data;
313
+ },
314
+ id,
315
+ payload.data,
316
+ {
317
+ ...loaderOptions,
318
+ ...payload,
319
+ signal: currentRequest.signal
320
+ }
321
+ );
322
+ } finally {
323
+ finishRequest("update", currentRequest);
324
+ }
213
325
  };
214
326
  const fetchSearch = async (query = "", opts) => {
215
327
  await fetchPage(1, query, opts);
@@ -219,29 +331,37 @@ export const usePageLoader = (loaderOptions) => {
219
331
  page: _page,
220
332
  ...params
221
333
  } = fetch.options?.request?.params || {};
222
- await apiFetchHelper(
223
- () => ({
224
- status: fetch.status,
225
- items: fetch.items,
226
- options: fetch.options
227
- }),
228
- (data) => {
229
- fetch.statusNextPage = data;
230
- },
231
- (data) => {
232
- fetch.options = data;
233
- },
234
- (data) => {
235
- fetch.items = [...fetch.items, ...data];
236
- },
237
- fetch.options.currentPage + 1,
238
- fetch.options.search || "",
239
- {
240
- ...loaderOptions,
241
- params,
242
- ...opts
243
- }
244
- );
334
+ const currentRequest = startRequest("fetch", opts?.signal);
335
+ try {
336
+ await apiFetchHelper(
337
+ () => ({
338
+ status: fetch.status,
339
+ items: fetch.items,
340
+ options: fetch.options
341
+ }),
342
+ (data) => {
343
+ if (canUpdateRequest("fetch", currentRequest)) fetch.statusNextPage = data;
344
+ },
345
+ (data) => {
346
+ if (canUpdateRequest("fetch", currentRequest)) fetch.options = data;
347
+ },
348
+ (data) => {
349
+ if (canUpdateRequest("fetch", currentRequest)) {
350
+ fetch.items = [...fetch.items, ...data];
351
+ }
352
+ },
353
+ fetch.options.currentPage + 1,
354
+ fetch.options.search || "",
355
+ {
356
+ ...loaderOptions,
357
+ params,
358
+ ...opts,
359
+ signal: currentRequest.signal
360
+ }
361
+ );
362
+ } finally {
363
+ finishRequest("fetch", currentRequest);
364
+ }
245
365
  };
246
366
  const fetchPageChange = async (page, opts) => {
247
367
  const {
@@ -254,31 +374,37 @@ export const usePageLoader = (loaderOptions) => {
254
374
  });
255
375
  };
256
376
  const deleteRun = async (id, opts) => {
257
- await apiDeleteHelper(
258
- () => ({
259
- status: del.status,
260
- data: del.item,
261
- items: fetch.items,
262
- options: del.options
263
- }),
264
- (data) => {
265
- del.status = data;
266
- },
267
- (data) => {
268
- del.options = data;
269
- },
270
- (data) => {
271
- del.item = data;
272
- },
273
- (data) => {
274
- fetch.items = data;
275
- },
276
- id,
277
- {
278
- ...loaderOptions,
279
- ...opts
280
- }
281
- );
377
+ const currentRequest = startRequest("delete", opts?.signal, false);
378
+ try {
379
+ await apiDeleteHelper(
380
+ () => ({
381
+ status: del.status,
382
+ data: del.item,
383
+ items: fetch.items,
384
+ options: del.options
385
+ }),
386
+ (data) => {
387
+ if (canUpdateRequest("delete", currentRequest)) del.status = data;
388
+ },
389
+ (data) => {
390
+ if (canUpdateRequest("delete", currentRequest)) del.options = data;
391
+ },
392
+ (data) => {
393
+ if (canUpdateRequest("delete", currentRequest)) del.item = data;
394
+ },
395
+ (data) => {
396
+ if (canUpdateRequest("delete", currentRequest)) fetch.items = data;
397
+ },
398
+ id,
399
+ {
400
+ ...loaderOptions,
401
+ ...opts,
402
+ signal: currentRequest.signal
403
+ }
404
+ );
405
+ } finally {
406
+ finishRequest("delete", currentRequest);
407
+ }
282
408
  };
283
409
  return {
284
410
  // State and methods
@@ -299,6 +425,12 @@ export const usePageLoader = (loaderOptions) => {
299
425
  addRun,
300
426
  updateRun,
301
427
  deleteRun,
428
+ cancelFetch,
429
+ cancelFind,
430
+ cancelAdd,
431
+ cancelUpdate,
432
+ cancelDelete,
433
+ cancelAll,
302
434
  clearAll
303
435
  };
304
436
  };
@@ -1,9 +1,10 @@
1
- import type { AxiosRequestConfig } from 'axios';
1
+ import { type AxiosRequestConfig } from 'axios';
2
2
  import type { IAPIOptions, IStatus } from '../types/lib.js';
3
3
  export interface IBaseLoaderOptions {
4
4
  isMock?: boolean;
5
5
  params?: Record<string, any>;
6
6
  expire?: number;
7
+ signal?: AbortSignal;
7
8
  [key: string]: any;
8
9
  }
9
10
  export interface IRequestContext {
@@ -14,7 +15,7 @@ export interface IRequestContext {
14
15
  }
15
16
  export declare const checkExpiration: (timestamp: number | undefined, expire?: number) => boolean;
16
17
  export declare const bindParamsToUrl: (urlTemplate: string, urlParams?: Record<string, any>) => string;
17
- export declare const prepareRequestOptions: (baseOptions?: AxiosRequestConfig, requestOptions?: AxiosRequestConfig, params?: Record<string, any>) => AxiosRequestConfig;
18
+ export declare const prepareRequestOptions: (baseOptions?: AxiosRequestConfig, requestOptions?: AxiosRequestConfig, params?: Record<string, any>, signal?: AbortSignal) => AxiosRequestConfig;
18
19
  export declare const handleApiRequest: <T>(requestContext: IRequestContext, mockData: T | T[] | null, callbacks: {
19
20
  onSuccess: (data: T, status?: number) => void;
20
21
  onError: (error: any) => void;
@@ -1,3 +1,4 @@
1
+ import axios from "axios";
1
2
  import { ObjectHelper } from "../utils/ObjectHelper.js";
2
3
  import { NewRequester } from "../lib/Requester.js";
3
4
  import { _merge } from "#imports";
@@ -12,12 +13,40 @@ export const bindParamsToUrl = (urlTemplate, urlParams = {}) => {
12
13
  });
13
14
  return resultUrl;
14
15
  };
15
- export const prepareRequestOptions = (baseOptions, requestOptions, params) => {
16
+ export const prepareRequestOptions = (baseOptions, requestOptions, params, signal) => {
16
17
  const options = _merge({}, baseOptions, requestOptions, {
17
- params
18
+ params,
19
+ ...signal ? {
20
+ signal
21
+ } : {}
18
22
  });
19
23
  return options;
20
24
  };
25
+ const createAbortError = () => ({
26
+ code: "ERR_CANCELED",
27
+ name: "AbortError",
28
+ message: "Request canceled"
29
+ });
30
+ const isAbortError = (error) => {
31
+ return axios.isCancel(error) || error?.code === "ERR_CANCELED" || error?.name === "AbortError";
32
+ };
33
+ const wait = (ms, signal) => new Promise((resolve, reject) => {
34
+ if (signal?.aborted) {
35
+ reject(createAbortError());
36
+ return;
37
+ }
38
+ const timeout = setTimeout(() => {
39
+ signal?.removeEventListener?.("abort", abort);
40
+ resolve();
41
+ }, ms);
42
+ const abort = () => {
43
+ clearTimeout(timeout);
44
+ reject(createAbortError());
45
+ };
46
+ signal?.addEventListener?.("abort", abort, {
47
+ once: true
48
+ });
49
+ });
21
50
  export const handleApiRequest = async (requestContext, mockData, callbacks) => {
22
51
  const {
23
52
  url,
@@ -27,13 +56,14 @@ export const handleApiRequest = async (requestContext, mockData, callbacks) => {
27
56
  } = requestContext;
28
57
  try {
29
58
  if (mockData) {
30
- await new Promise((resolve) => setTimeout(resolve, 300));
59
+ await wait(300, options.signal);
31
60
  callbacks.onSuccess(mockData);
32
61
  } else {
33
62
  const response = await NewRequester.create(method, url, data, options);
34
63
  callbacks.onSuccess(response.data, response.status);
35
64
  }
36
65
  } catch (error) {
66
+ if (isAbortError(error)) return;
37
67
  callbacks.onError(error);
38
68
  } finally {
39
69
  callbacks.onComplete?.();
@@ -0,0 +1,6 @@
1
+ export interface ICancelableRequest {
2
+ controller: AbortController;
3
+ signal: AbortSignal;
4
+ cleanup: () => void;
5
+ }
6
+ export declare const createCancelableRequest: (externalSignal?: AbortSignal) => ICancelableRequest;
@@ -0,0 +1,22 @@
1
+ export const createCancelableRequest = (externalSignal) => {
2
+ const controller = new AbortController();
3
+ const abort = () => {
4
+ controller.abort();
5
+ };
6
+ if (externalSignal) {
7
+ if (externalSignal.aborted) {
8
+ abort();
9
+ } else {
10
+ externalSignal.addEventListener("abort", abort, {
11
+ once: true
12
+ });
13
+ }
14
+ }
15
+ return {
16
+ controller,
17
+ signal: controller.signal,
18
+ cleanup: () => {
19
+ externalSignal?.removeEventListener("abort", abort);
20
+ }
21
+ };
22
+ };
@@ -15,7 +15,8 @@ export const apiListHelper = async (state, onUpdateStatus, onUpdateOptions, onUp
15
15
  const requestOptions = prepareRequestOptions(
16
16
  {},
17
17
  opts.getRequestOptions?.(opts),
18
- opts.params
18
+ opts.params,
19
+ opts.signal
19
20
  );
20
21
  const url = bindParamsToUrl(opts.getURL ? opts.getURL(opts) : opts.url, opts.urlBind || {});
21
22
  await handleApiRequest(
@@ -21,6 +21,7 @@ export interface IUseObjectLoader<T, B, _O> {
21
21
  data: ComputedRef<T | null>;
22
22
  options: ComputedRef<IAPIOptions>;
23
23
  run: (payload?: IObjectRunLoaderOptions<T, B>) => Promise<void>;
24
+ cancel: () => void;
24
25
  clear: () => void;
25
26
  setLoading: () => void;
26
27
  setData: (data: T | null) => void;
@@ -29,7 +30,8 @@ export interface IUseListLoader<T, O> {
29
30
  status: ComputedRef<IStatus>;
30
31
  items: ComputedRef<T[]>;
31
32
  options: ComputedRef<Record<string, any>>;
32
- run: (opts?: IListRunLoaderOptions<T, O>) => void;
33
+ run: (opts?: IListRunLoaderOptions<T, O>) => Promise<void>;
34
+ cancel: () => void;
33
35
  setItems: (items: T[]) => void;
34
36
  clear: () => void;
35
37
  setLoading: () => void;
@@ -15,7 +15,8 @@ export const apiObjectHelper = async (state, onUpdateStatus, onUpdateOptions, on
15
15
  const requestOptions = prepareRequestOptions(
16
16
  {},
17
17
  opts.getRequestOptions?.(payload, opts),
18
- opts.params
18
+ opts.params,
19
+ opts.signal
19
20
  );
20
21
  const url = bindParamsToUrl(opts.getURL ? opts.getURL(payload, opts) : opts.url, opts.urlBind || {});
21
22
  await handleApiRequest(