@arrai-innovations/reactive-helpers 13.0.4 → 13.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/docs/README.md +1 -0
- package/docs/config/listCrud.md +6 -0
- package/docs/config/objectCrud.md +8 -0
- package/docs/use/list.md +10 -0
- package/docs/use/loadingError.md +41 -27
- package/docs/use/object.md +95 -0
- package/docs/use/proxyLoadingError.md +49 -0
- package/docs/utils/classes.md +11 -0
- package/docs/utils/compact.md +4 -0
- package/docs/utils/relatedCalculatedHelpers.md +4 -0
- package/docs/utils/set.md +60 -0
- package/docs/utils/transformWalk.md +29 -0
- package/index.js +1 -0
- package/package.json +14 -14
- package/tests/unit/use/loadingError.spec.js +43 -0
- package/tests/unit/use/proxyLoadingError.spec.js +64 -0
- package/use/listRelated.js +1 -1
- package/use/loadingError.js +16 -2
- package/use/proxyLoadingError.js +59 -0
package/docs/README.md
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
- [use/objectRelated](use/objectRelated.md)
|
|
27
27
|
- [use/objectSubscription](use/objectSubscription.md)
|
|
28
28
|
- [use/paginatedListInstance](use/paginatedListInstance.md)
|
|
29
|
+
- [use/proxyLoadingError](use/proxyLoadingError.md)
|
|
29
30
|
- [use/search](use/search.md)
|
|
30
31
|
- [use/watchesRunning](use/watchesRunning.md)
|
|
31
32
|
- [utils/assignReactiveObject](utils/assignReactiveObject.md)
|
package/docs/config/listCrud.md
CHANGED
|
@@ -289,6 +289,8 @@ The props to set for the crud.
|
|
|
289
289
|
|
|
290
290
|
> **setListCrud**(`options`): `void`
|
|
291
291
|
|
|
292
|
+
Set the list and subscribe functions for the default crud.
|
|
293
|
+
|
|
292
294
|
#### Parameters
|
|
293
295
|
|
|
294
296
|
• **options**: [`ListCrudFunctions`](listCrud.md#listcrudfunctions) & `Partial`\<[`ListCrudArgs`](listCrud.md#listcrudargs)\>
|
|
@@ -298,3 +300,7 @@ The options for the default crud.
|
|
|
298
300
|
#### Returns
|
|
299
301
|
|
|
300
302
|
`void`
|
|
303
|
+
|
|
304
|
+
#### Throws
|
|
305
|
+
|
|
306
|
+
- If unknown keys are passed.
|
|
@@ -326,6 +326,10 @@ The arguments to be passed to the crud functions.
|
|
|
326
326
|
|
|
327
327
|
`void`
|
|
328
328
|
|
|
329
|
+
#### Throws
|
|
330
|
+
|
|
331
|
+
- If an invalid function is passed, or if the function is not a function.
|
|
332
|
+
|
|
329
333
|
***
|
|
330
334
|
|
|
331
335
|
### setObjectCrud()
|
|
@@ -343,3 +347,7 @@ The options for the object crud functions.
|
|
|
343
347
|
#### Returns
|
|
344
348
|
|
|
345
349
|
`void`
|
|
350
|
+
|
|
351
|
+
#### Throws
|
|
352
|
+
|
|
353
|
+
- if unknown keys are passed.
|
package/docs/use/list.md
CHANGED
|
@@ -254,6 +254,9 @@ Current text query used for filtering the list.
|
|
|
254
254
|
|
|
255
255
|
> **useList**(`options`): [`ListManager`](list.md#listmanager)
|
|
256
256
|
|
|
257
|
+
Creates and manages an enhanced list instance by orchestrating various list-related composables.
|
|
258
|
+
It ensures seamless integration of all list functionalities such as sorting, searching, filtering, and advanced state management.
|
|
259
|
+
|
|
257
260
|
#### Parameters
|
|
258
261
|
|
|
259
262
|
• **options**: [`ListOptions`](list.md#listoptions)
|
|
@@ -266,12 +269,19 @@ The options for the list./.
|
|
|
266
269
|
|
|
267
270
|
- The managed stack of list-related composable functions.
|
|
268
271
|
|
|
272
|
+
#### Example
|
|
273
|
+
|
|
274
|
+
```vue
|
|
275
|
+
```
|
|
276
|
+
|
|
269
277
|
***
|
|
270
278
|
|
|
271
279
|
### useLists()
|
|
272
280
|
|
|
273
281
|
> **useLists**(`listOptions`): `object`
|
|
274
282
|
|
|
283
|
+
Initializes multiple list management instances with provided configurations.
|
|
284
|
+
|
|
275
285
|
#### Parameters
|
|
276
286
|
|
|
277
287
|
• **listOptions**
|
package/docs/use/loadingError.md
CHANGED
|
@@ -8,25 +8,55 @@
|
|
|
8
8
|
|
|
9
9
|
## Interfaces
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### LoadingErrorMutations
|
|
12
12
|
|
|
13
13
|
#### Properties
|
|
14
14
|
|
|
15
|
-
#####
|
|
15
|
+
##### clearLoading()
|
|
16
16
|
|
|
17
|
-
> **
|
|
17
|
+
> **clearLoading**: () => `void`
|
|
18
18
|
|
|
19
|
-
Clear the
|
|
19
|
+
Clear the loading state.
|
|
20
20
|
|
|
21
21
|
###### Returns
|
|
22
22
|
|
|
23
23
|
`void`
|
|
24
24
|
|
|
25
|
-
#####
|
|
25
|
+
##### setError()
|
|
26
26
|
|
|
27
|
-
> **
|
|
27
|
+
> **setError**: (`error`) => `void`
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Set the error state.
|
|
30
|
+
|
|
31
|
+
###### Parameters
|
|
32
|
+
|
|
33
|
+
• **error**: `any`
|
|
34
|
+
|
|
35
|
+
###### Returns
|
|
36
|
+
|
|
37
|
+
`void`
|
|
38
|
+
|
|
39
|
+
##### setLoading()
|
|
40
|
+
|
|
41
|
+
> **setLoading**: () => `void`
|
|
42
|
+
|
|
43
|
+
Set the loading state.
|
|
44
|
+
|
|
45
|
+
###### Returns
|
|
46
|
+
|
|
47
|
+
`void`
|
|
48
|
+
|
|
49
|
+
***
|
|
50
|
+
|
|
51
|
+
### LoadingErrorStatus
|
|
52
|
+
|
|
53
|
+
#### Properties
|
|
54
|
+
|
|
55
|
+
##### clearError()
|
|
56
|
+
|
|
57
|
+
> **clearError**: () => `void`
|
|
58
|
+
|
|
59
|
+
Clear the error state.
|
|
30
60
|
|
|
31
61
|
###### Returns
|
|
32
62
|
|
|
@@ -50,29 +80,13 @@ Whether an error has occurred.
|
|
|
50
80
|
|
|
51
81
|
Whether the component is loading.
|
|
52
82
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
> **setError**: (`error`) => `void`
|
|
56
|
-
|
|
57
|
-
Set the error state.
|
|
83
|
+
## Type Aliases
|
|
58
84
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
• **error**: `any`
|
|
62
|
-
|
|
63
|
-
###### Returns
|
|
64
|
-
|
|
65
|
-
`void`
|
|
66
|
-
|
|
67
|
-
##### setLoading()
|
|
68
|
-
|
|
69
|
-
> **setLoading**: () => `void`
|
|
70
|
-
|
|
71
|
-
Set the loading state.
|
|
85
|
+
### LoadingError
|
|
72
86
|
|
|
73
|
-
|
|
87
|
+
> **LoadingError**\<\>: [`LoadingErrorStatus`](loadingError.md#loadingerrorstatus) & [`LoadingErrorMutations`](loadingError.md#loadingerrormutations)
|
|
74
88
|
|
|
75
|
-
|
|
89
|
+
#### Type Parameters
|
|
76
90
|
|
|
77
91
|
## Functions
|
|
78
92
|
|
package/docs/use/object.md
CHANGED
|
@@ -502,6 +502,8 @@ Whether the subscription is loading.
|
|
|
502
502
|
|
|
503
503
|
> **useObject**(`options`): [`ObjectManager`](object.md#objectmanager)
|
|
504
504
|
|
|
505
|
+
Initializes a chain of useObject* functions, returning an object of them.
|
|
506
|
+
|
|
505
507
|
#### Parameters
|
|
506
508
|
|
|
507
509
|
• **options**: [`ObjectManagerOptions`](object.md#objectmanageroptions)
|
|
@@ -514,12 +516,105 @@ The options to be passed to useObjectInstance, useObjectSubscription, useObjectR
|
|
|
514
516
|
|
|
515
517
|
- An object managing a chain of useObject* instances.
|
|
516
518
|
|
|
519
|
+
#### Example
|
|
520
|
+
|
|
521
|
+
```
|
|
522
|
+
<script setup>
|
|
523
|
+
import { useObject } from "@arrai-innovations/reactive-helpers";
|
|
524
|
+
import { reactive, ref, toRef } from "vue";
|
|
525
|
+
|
|
526
|
+
const someObjectsSource = reactive({
|
|
527
|
+
objects: {
|
|
528
|
+
'1': { id: 1, name: 'one', secondOrderId: 15 },
|
|
529
|
+
'2': { id: 2, name: 'two', secondOrderId: 10 },
|
|
530
|
+
'3': { id: 3, name: 'three', secondOrderId: 5 },
|
|
531
|
+
},
|
|
532
|
+
});
|
|
533
|
+
const someOtherObjectsSource = reactive({
|
|
534
|
+
objects: {
|
|
535
|
+
'5': { id: 5, name: 'five' },
|
|
536
|
+
'10': { id: 10, name: 'ten' },
|
|
537
|
+
'15': { id: 15, name: 'fifteen' },
|
|
538
|
+
},
|
|
539
|
+
});
|
|
540
|
+
const props = defineProps({
|
|
541
|
+
app: { type: String, required: true },
|
|
542
|
+
model: { type: String, required: true },
|
|
543
|
+
id: { type: String, default: "" },
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
const objectProps = reactive({
|
|
547
|
+
crudArgs: {
|
|
548
|
+
app: toRef(props, "app"),
|
|
549
|
+
model: toRef(props, "model"),
|
|
550
|
+
},
|
|
551
|
+
retrieveArgs: {
|
|
552
|
+
fields: ['foo', 'bar'],
|
|
553
|
+
},
|
|
554
|
+
relatedObjectRules: {
|
|
555
|
+
firstOrder: {
|
|
556
|
+
pkKey: 'some_objects_id',
|
|
557
|
+
objects: someObjectsSource.objects,
|
|
558
|
+
},
|
|
559
|
+
some_objects_list_ids: {
|
|
560
|
+
// pkKey defaults to match rule name
|
|
561
|
+
objects: someObjectsSource.objects,
|
|
562
|
+
order: ['3','1','2'],
|
|
563
|
+
},
|
|
564
|
+
secondOrder: {
|
|
565
|
+
pkKey: 'relatedObject.secondOrderId',
|
|
566
|
+
objects: someOtherObjectsSource.objects,
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
calculatedObjectRules: {
|
|
570
|
+
someRule: (object, relatedObject, calculatedObjects) => {
|
|
571
|
+
// some complex calculation, relatedObjects would be assuming there was a listRelated between the two
|
|
572
|
+
// calculatedObjects would be the other calculated objects in the list
|
|
573
|
+
// including yourself, so try not to create circular dependencies
|
|
574
|
+
// this is used as a computed body.
|
|
575
|
+
return object.foo + object.name;
|
|
576
|
+
},
|
|
577
|
+
...
|
|
578
|
+
},
|
|
579
|
+
intendToRetrieve: false,
|
|
580
|
+
intendToSubscribe: false,
|
|
581
|
+
});
|
|
582
|
+
objectProps.intendToRetrieve = objectProps.intendToSubscribe = computed(()=> !!props.id);
|
|
583
|
+
const objectManager = useObject(objectProps);
|
|
584
|
+
// objectManager.state.object comes back from the server (via configured crud retrieve function)
|
|
585
|
+
// { id: 2, name: 'two', foo: 'bar', some_objects_id: 2, some_objects_list_ids: ['1','2','3'] }
|
|
586
|
+
</script>
|
|
587
|
+
<template>
|
|
588
|
+
<div v-if="objectManager.state.loading">Loading...</div>
|
|
589
|
+
<div v-else-if="objectManager.state.errored">Error: {{ objectManager.state.error.message }}</div>
|
|
590
|
+
<div v-else-if="objectManager.state.object.id">
|
|
591
|
+
<p>Foo: {{ objectManager.state.object.foo }}</p>
|
|
592
|
+
<!-- 'bar' -->
|
|
593
|
+
|
|
594
|
+
<p>{{ objectManager.state.relatedObject.firstOrder }}</p>
|
|
595
|
+
<!-- { id: 2, name: 'two', secondOrderId: 10 } -->
|
|
596
|
+
|
|
597
|
+
<p>{{ objectManager.state.relatedObject.some_objects_list_ids }}</p>
|
|
598
|
+
<!-- [{ id: 3, name: 'three', secondOrderId: 5 }, { id: 1, name: 'one', secondOrderId: 15 }, { id: 2, name: 'two', secondOrderId: 10 }] -->
|
|
599
|
+
|
|
600
|
+
<p>{{ objectManager.state.relatedObject.secondOrder }}</p>
|
|
601
|
+
<!-- { id: 10, name: 'ten' } -->
|
|
602
|
+
|
|
603
|
+
<p>{{ objectManager.state.calculatedObject.someRule }}</p>
|
|
604
|
+
<!-- 'bartwo' -->
|
|
605
|
+
</div>
|
|
606
|
+
<div v-else>Object not found.</div>
|
|
607
|
+
</template>
|
|
608
|
+
```
|
|
609
|
+
|
|
517
610
|
***
|
|
518
611
|
|
|
519
612
|
### useObjects()
|
|
520
613
|
|
|
521
614
|
> **useObjects**(`objectArgs`): `object`
|
|
522
615
|
|
|
616
|
+
Initializes multiple useObject instances, returning an object of them based on the keys of the objectArgs.
|
|
617
|
+
|
|
523
618
|
#### Parameters
|
|
524
619
|
|
|
525
620
|
• **objectArgs**
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[**@arrai-innovations/reactive-helpers**](../README.md) • **Docs**
|
|
2
|
+
|
|
3
|
+
***
|
|
4
|
+
|
|
5
|
+
[@arrai-innovations/reactive-helpers](../README.md) / use/proxyLoadingError
|
|
6
|
+
|
|
7
|
+
# use/proxyLoadingError
|
|
8
|
+
|
|
9
|
+
## References
|
|
10
|
+
|
|
11
|
+
### ProxyLoadingError
|
|
12
|
+
|
|
13
|
+
Renames and re-exports [LoadingErrorStatus](loadingError.md#loadingerrorstatus)
|
|
14
|
+
|
|
15
|
+
## Type Aliases
|
|
16
|
+
|
|
17
|
+
### WatchableLoadingErrors
|
|
18
|
+
|
|
19
|
+
> **WatchableLoadingErrors**\<\>: `UnwrapNestedRefs` \| `Ref` \| [`WatchableLoadingErrorsRaw`](proxyLoadingError.md#watchableloadingerrorsraw)
|
|
20
|
+
|
|
21
|
+
#### Type Parameters
|
|
22
|
+
|
|
23
|
+
***
|
|
24
|
+
|
|
25
|
+
### WatchableLoadingErrorsRaw
|
|
26
|
+
|
|
27
|
+
> **WatchableLoadingErrorsRaw**\<\>: [`use/loadingError`](loadingError.md)[]
|
|
28
|
+
|
|
29
|
+
#### Type Parameters
|
|
30
|
+
|
|
31
|
+
## Functions
|
|
32
|
+
|
|
33
|
+
### useProxyLoadingError()
|
|
34
|
+
|
|
35
|
+
> **useProxyLoadingError**(`loadingErrors`): [`LoadingErrorStatus`](loadingError.md#loadingerrorstatus)
|
|
36
|
+
|
|
37
|
+
A composable function for managing aggregated loading and error states across multiple sources.
|
|
38
|
+
|
|
39
|
+
#### Parameters
|
|
40
|
+
|
|
41
|
+
• **loadingErrors**: [`WatchableLoadingErrors`](proxyLoadingError.md#watchableloadingerrors)
|
|
42
|
+
|
|
43
|
+
A collection of loading error statuses to monitor and aggregate.
|
|
44
|
+
|
|
45
|
+
#### Returns
|
|
46
|
+
|
|
47
|
+
[`LoadingErrorStatus`](loadingError.md#loadingerrorstatus)
|
|
48
|
+
|
|
49
|
+
An object containing aggregated reactive fields and actions for loading and error states.
|
package/docs/utils/classes.md
CHANGED
|
@@ -30,6 +30,11 @@ The normalized form of the CSS classes, either as a string of space-separated cl
|
|
|
30
30
|
|
|
31
31
|
> **combineClasses**(...`classes`): [`CombinedClasses`](classes.md#combinedclasses)
|
|
32
32
|
|
|
33
|
+
Combines and normalizes different formats of CSS class specifications into a single format suitable for Vue.js
|
|
34
|
+
components. If objects are in the mix, objects are returned. Otherwise, a string is returned.
|
|
35
|
+
|
|
36
|
+
We unref your refs, so probably want a computed around this.
|
|
37
|
+
|
|
33
38
|
#### Parameters
|
|
34
39
|
|
|
35
40
|
• ...**classes**: ([`CombinedClassesArgument`](classes.md#combinedclassesargument) \| [`CombinedClassesArgument`](classes.md#combinedclassesargument)[])[]
|
|
@@ -50,6 +55,8 @@ A variable list of class specifications in
|
|
|
50
55
|
|
|
51
56
|
> **objectifyClasses**(...`classes`): `object` \| `object`[]
|
|
52
57
|
|
|
58
|
+
Normalize various ways of specifying CSS classes into an object for use in Vue.js.
|
|
59
|
+
|
|
53
60
|
#### Parameters
|
|
54
61
|
|
|
55
62
|
• ...**classes**: (`string` \| `string`[] \| `string`[][] \| `object` \| `Ref`\<`string` \| `string`[] \| `string`[][]\>)[]
|
|
@@ -69,6 +76,8 @@ An object or array of objects containing CSS classes. Arrays are used if refs ar
|
|
|
69
76
|
|
|
70
77
|
> **stringifyClass**(`cls`): `string`
|
|
71
78
|
|
|
79
|
+
Normalizes various ways of specifying CSS classes into a space-separated list of CSS classes.
|
|
80
|
+
|
|
72
81
|
#### Parameters
|
|
73
82
|
|
|
74
83
|
• **cls**: `string` \| `string`[] \| `object`
|
|
@@ -87,6 +96,8 @@ A space-separated list of CSS classes.
|
|
|
87
96
|
|
|
88
97
|
> **stringifyClasses**(...`classes`): `string`
|
|
89
98
|
|
|
99
|
+
Normalizes various ways of specifying CSS classes into a space-separated list of CSS classes.
|
|
100
|
+
|
|
90
101
|
#### Parameters
|
|
91
102
|
|
|
92
103
|
• ...**classes**: (`string` \| `string`[] \| `object`)[]
|
package/docs/utils/compact.md
CHANGED
|
@@ -30,6 +30,8 @@ The object or array to compact sparse arrays in.
|
|
|
30
30
|
|
|
31
31
|
> **removeEmptyObjects**(`obj`): `void`
|
|
32
32
|
|
|
33
|
+
Remove empty objects from a mixed object array tree. Mutates the object.
|
|
34
|
+
|
|
33
35
|
#### Parameters
|
|
34
36
|
|
|
35
37
|
• **obj**: `any`
|
|
@@ -46,6 +48,8 @@ The object or array to remove empty objects from.
|
|
|
46
48
|
|
|
47
49
|
> **removeEmptyObjectsAndCompactSparseArrays**(`obj`): `void`
|
|
48
50
|
|
|
51
|
+
Remove empty objects and undefined values from arrays in a mixed object array tree. Mutates the object.
|
|
52
|
+
|
|
49
53
|
#### Parameters
|
|
50
54
|
|
|
51
55
|
• **obj**: `any`
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
|
|
25
25
|
> **getObjectRelatedByKey**(`obj`, `relatedObj`, `key`): [`any`, `string`]
|
|
26
26
|
|
|
27
|
+
Get the object and key of a related item.
|
|
28
|
+
|
|
27
29
|
#### Parameters
|
|
28
30
|
|
|
29
31
|
• **obj**: `any`
|
|
@@ -50,6 +52,8 @@ The object and key of the related item.
|
|
|
50
52
|
|
|
51
53
|
> **getObjectRelatedCalculatedByKey**(`obj`, `relatedObj`, `calculatedObj`, `key`): [`any`, `string`]
|
|
52
54
|
|
|
55
|
+
Get the object and key of a calculated item.
|
|
56
|
+
|
|
53
57
|
#### Parameters
|
|
54
58
|
|
|
55
59
|
• **obj**: `any`
|
package/docs/utils/set.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
> **difference**(`setA`, `setB`): `Set`\<`any`\>
|
|
14
14
|
|
|
15
|
+
Returns the difference of two sets, containing elements present only in the first set but not in the second.
|
|
16
|
+
|
|
15
17
|
#### Parameters
|
|
16
18
|
|
|
17
19
|
• **setA**: `Set`\<`any`\>
|
|
@@ -28,12 +30,22 @@ The second set.
|
|
|
28
30
|
|
|
29
31
|
A new Set containing elements from the first set that are not in the second set.
|
|
30
32
|
|
|
33
|
+
#### Example
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
const a = new Set([1, 2, 3]);
|
|
37
|
+
const b = new Set([3, 4]);
|
|
38
|
+
console.log(difference(a, b)); // Set(1, 2)
|
|
39
|
+
```
|
|
40
|
+
|
|
31
41
|
***
|
|
32
42
|
|
|
33
43
|
### equals()
|
|
34
44
|
|
|
35
45
|
> **equals**(`setA`, `setB`): `boolean`
|
|
36
46
|
|
|
47
|
+
Tests if two sets are equal, meaning they contain exactly the same elements.
|
|
48
|
+
|
|
37
49
|
#### Parameters
|
|
38
50
|
|
|
39
51
|
• **setA**: `Set`\<`any`\>
|
|
@@ -50,12 +62,22 @@ The second set.
|
|
|
50
62
|
|
|
51
63
|
Returns true if both sets are equal in size and content, otherwise false.
|
|
52
64
|
|
|
65
|
+
#### Example
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const a = new Set([1, 2, 3]);
|
|
69
|
+
const b = new Set([1, 2, 3]);
|
|
70
|
+
console.log(equals(a, b)); // true
|
|
71
|
+
```
|
|
72
|
+
|
|
53
73
|
***
|
|
54
74
|
|
|
55
75
|
### intersection()
|
|
56
76
|
|
|
57
77
|
> **intersection**(`setA`, `setB`): `Set`\<`any`\>
|
|
58
78
|
|
|
79
|
+
Returns the intersection of two sets, containing only elements that are present in both sets.
|
|
80
|
+
|
|
59
81
|
#### Parameters
|
|
60
82
|
|
|
61
83
|
• **setA**: `Set`\<`any`\>
|
|
@@ -72,12 +94,22 @@ The second set.
|
|
|
72
94
|
|
|
73
95
|
A new Set containing common elements from both input sets.
|
|
74
96
|
|
|
97
|
+
#### Example
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const a = new Set([1, 2, 3]);
|
|
101
|
+
const b = new Set([2, 3, 4]);
|
|
102
|
+
console.log(intersection(a, b)); // Set(2, 3)
|
|
103
|
+
```
|
|
104
|
+
|
|
75
105
|
***
|
|
76
106
|
|
|
77
107
|
### isSuperset()
|
|
78
108
|
|
|
79
109
|
> **isSuperset**(`set`, `subset`): `boolean`
|
|
80
110
|
|
|
111
|
+
Checks if one set is a superset of another set, meaning all elements of the subset are contained within the set.
|
|
112
|
+
|
|
81
113
|
#### Parameters
|
|
82
114
|
|
|
83
115
|
• **set**: `Set`\<`any`\>
|
|
@@ -94,12 +126,22 @@ The candidate subset.
|
|
|
94
126
|
|
|
95
127
|
Returns true if the set contains all elements of the subset, otherwise false.
|
|
96
128
|
|
|
129
|
+
#### Example
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const a = new Set([1, 2, 3]);
|
|
133
|
+
const b = new Set([2, 3]);
|
|
134
|
+
console.log(isSuperset(a, b)); // true
|
|
135
|
+
```
|
|
136
|
+
|
|
97
137
|
***
|
|
98
138
|
|
|
99
139
|
### symmetricDifference()
|
|
100
140
|
|
|
101
141
|
> **symmetricDifference**(`setA`, `setB`): `Set`\<`any`\>
|
|
102
142
|
|
|
143
|
+
Returns the symmetric difference of two sets, containing elements present in only one of the sets.
|
|
144
|
+
|
|
103
145
|
#### Parameters
|
|
104
146
|
|
|
105
147
|
• **setA**: `Set`\<`any`\>
|
|
@@ -116,12 +158,22 @@ The second set.
|
|
|
116
158
|
|
|
117
159
|
A new Set containing elements that are only in one of the input sets.
|
|
118
160
|
|
|
161
|
+
#### Example
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
const a = new Set([1, 2, 3]);
|
|
165
|
+
const b = new Set([3, 4, 5]);
|
|
166
|
+
console.log(symmetricDifference(a, b)); // Set(1, 2, 4, 5)
|
|
167
|
+
```
|
|
168
|
+
|
|
119
169
|
***
|
|
120
170
|
|
|
121
171
|
### union()
|
|
122
172
|
|
|
123
173
|
> **union**(`setA`, `setB`): `Set`\<`any`\>
|
|
124
174
|
|
|
175
|
+
Returns the union of two sets, containing all unique elements from both sets.
|
|
176
|
+
|
|
125
177
|
#### Parameters
|
|
126
178
|
|
|
127
179
|
• **setA**: `Set`\<`any`\>
|
|
@@ -137,3 +189,11 @@ The second set.
|
|
|
137
189
|
`Set`\<`any`\>
|
|
138
190
|
|
|
139
191
|
A new Set containing all elements from both input sets.
|
|
192
|
+
|
|
193
|
+
#### Example
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const a = new Set([1, 2, 3]);
|
|
197
|
+
const b = new Set([3, 4, 5]);
|
|
198
|
+
console.log(union(a, b)); // Set(1, 2, 3, 4, 5)
|
|
199
|
+
```
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
> **transformWalk**(`obj`, `transformFn`, `path`): `any`
|
|
14
14
|
|
|
15
|
+
Recursively walks through an object's values and applies a transformation function to each value.
|
|
16
|
+
The value recursed into is the transformed value, not the original value.
|
|
17
|
+
|
|
15
18
|
#### Parameters
|
|
16
19
|
|
|
17
20
|
• **obj**: `any`
|
|
@@ -31,3 +34,29 @@ The path to the current value.
|
|
|
31
34
|
`any`
|
|
32
35
|
|
|
33
36
|
The transformed object.
|
|
37
|
+
|
|
38
|
+
#### Example
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const obj = {
|
|
42
|
+
a: 1,
|
|
43
|
+
b: {
|
|
44
|
+
c: 2,
|
|
45
|
+
d: [3, 4, { e: 5 }]
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const transformed = transformWalk(obj, (key, value, path) => {
|
|
50
|
+
if (key === "e") {
|
|
51
|
+
return value * 2;
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
});
|
|
55
|
+
// transformed = {
|
|
56
|
+
// a: 1,
|
|
57
|
+
// b: {
|
|
58
|
+
// c: 2,
|
|
59
|
+
// d: [3, 4, { e: 10 }]
|
|
60
|
+
// }
|
|
61
|
+
// }
|
|
62
|
+
```
|
package/index.js
CHANGED
|
@@ -19,6 +19,7 @@ export * from "./use/objectInstance.js";
|
|
|
19
19
|
export * from "./use/objectRelated.js";
|
|
20
20
|
export * from "./use/objectSubscription.js";
|
|
21
21
|
export * from "./use/paginatedListInstance.js";
|
|
22
|
+
export * from "./use/proxyLoadingError.js";
|
|
22
23
|
export * from "./use/search.js";
|
|
23
24
|
export * from "./use/watchesRunning.js";
|
|
24
25
|
export * from "./utils/assignReactiveObject.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arrai-innovations/reactive-helpers",
|
|
3
|
-
"version": "13.0
|
|
3
|
+
"version": "13.1.0",
|
|
4
4
|
"description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,31 +30,31 @@
|
|
|
30
30
|
"homepage": "https://github.com/arrai-innovations/reactive-helpers#readme",
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@arrai-innovations/commitlint-config": "^1.1.0",
|
|
33
|
-
"@commitlint/cli": "^19.
|
|
33
|
+
"@commitlint/cli": "^19.4.0",
|
|
34
34
|
"@godaddy/dmd": "^1.0.4",
|
|
35
35
|
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
|
36
36
|
"@types/browser-util-inspect": "^0.2.4",
|
|
37
37
|
"@types/lodash-es": "^4.17.12",
|
|
38
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
39
|
-
"@typescript-eslint/parser": "^7.
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
39
|
+
"@typescript-eslint/parser": "^7.18.0",
|
|
40
40
|
"@vitest/coverage-v8": "^1.6.0",
|
|
41
|
-
"@vue/compiler-sfc": "^3.
|
|
41
|
+
"@vue/compiler-sfc": "^3.4.37",
|
|
42
42
|
"@vue/eslint-config-prettier": "^9.0.0",
|
|
43
43
|
"@vue/test-utils": "^2.3.2",
|
|
44
44
|
"doctoc": "^2.1.0",
|
|
45
45
|
"eslint": "^8.56.0",
|
|
46
|
-
"eslint-plugin-jsdoc": "^48.
|
|
46
|
+
"eslint-plugin-jsdoc": "^48.11.0",
|
|
47
47
|
"eslint-plugin-vitest": "~0.5.4",
|
|
48
48
|
"eslint-plugin-vitest-globals": "^1.3.1",
|
|
49
|
-
"eslint-plugin-vue": "^9.
|
|
49
|
+
"eslint-plugin-vue": "^9.27.0",
|
|
50
50
|
"flush-promises": "^1.0.2",
|
|
51
|
-
"globals": "^15.
|
|
52
|
-
"jsdom": "^24.1.
|
|
53
|
-
"lint-staged": "^15.2.
|
|
54
|
-
"prettier": "^3.3.
|
|
55
|
-
"typedoc": "^0.26.
|
|
56
|
-
"typedoc-plugin-markdown": "^4.
|
|
57
|
-
"typescript": "^5.5.
|
|
51
|
+
"globals": "^15.9.0",
|
|
52
|
+
"jsdom": "^24.1.1",
|
|
53
|
+
"lint-staged": "^15.2.8",
|
|
54
|
+
"prettier": "^3.3.3",
|
|
55
|
+
"typedoc": "^0.26.5",
|
|
56
|
+
"typedoc-plugin-markdown": "^4.2.3",
|
|
57
|
+
"typescript": "^5.5.4",
|
|
58
58
|
"vitest": "^1.6.0"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useLoadingError } from "../../../use/loadingError.js";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { describe, it, expect } from "vitest";
|
|
4
|
+
|
|
5
|
+
describe("useLoadingError", () => {
|
|
6
|
+
let loadingError;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
loadingError = useLoadingError();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should initialize with default states", () => {
|
|
13
|
+
expect(loadingError.loading.value).toBe(undefined);
|
|
14
|
+
expect(loadingError.error.value).toBe(null);
|
|
15
|
+
expect(loadingError.errored.value).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should set loading state", () => {
|
|
19
|
+
loadingError.setLoading();
|
|
20
|
+
expect(loadingError.loading.value).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should clear loading state", () => {
|
|
24
|
+
loadingError.setLoading();
|
|
25
|
+
loadingError.clearLoading();
|
|
26
|
+
expect(loadingError.loading.value).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should set error state and mark as errored", () => {
|
|
30
|
+
const error = new Error("Test Error");
|
|
31
|
+
loadingError.setError(error);
|
|
32
|
+
expect(loadingError.error.value).toBe(error);
|
|
33
|
+
expect(loadingError.errored.value).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should clear error state", () => {
|
|
37
|
+
const error = new Error("Test Error");
|
|
38
|
+
loadingError.setError(error);
|
|
39
|
+
loadingError.clearError();
|
|
40
|
+
expect(loadingError.error.value).toBe(null);
|
|
41
|
+
expect(loadingError.errored.value).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useProxyLoadingError } from "../../../use/proxyLoadingError.js";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { describe, it, expect } from "vitest";
|
|
4
|
+
|
|
5
|
+
describe("useProxyLoadingError", () => {
|
|
6
|
+
let loadingError1, loadingError2;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
loadingError1 = {
|
|
10
|
+
loading: ref(false),
|
|
11
|
+
error: ref(null),
|
|
12
|
+
errored: ref(false),
|
|
13
|
+
clearError: vi.fn(),
|
|
14
|
+
};
|
|
15
|
+
loadingError2 = {
|
|
16
|
+
loading: ref(false),
|
|
17
|
+
error: ref(null),
|
|
18
|
+
errored: ref(false),
|
|
19
|
+
clearError: vi.fn(),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should initialize with default states when no errors", () => {
|
|
24
|
+
const proxyLoadingError = useProxyLoadingError([loadingError1, loadingError2]);
|
|
25
|
+
expect(proxyLoadingError.loading.value).toBe(false);
|
|
26
|
+
expect(proxyLoadingError.error.value).toBe(null);
|
|
27
|
+
expect(proxyLoadingError.errored.value).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should reflect loading state when one source is loading", () => {
|
|
31
|
+
loadingError1.loading.value = true;
|
|
32
|
+
const proxyLoadingError = useProxyLoadingError([loadingError1, loadingError2]);
|
|
33
|
+
expect(proxyLoadingError.loading.value).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should reflect error state when one source has an error", () => {
|
|
37
|
+
const error = new Error("Test Error");
|
|
38
|
+
loadingError2.error.value = error;
|
|
39
|
+
loadingError2.errored.value = true;
|
|
40
|
+
const proxyLoadingError = useProxyLoadingError([loadingError1, loadingError2]);
|
|
41
|
+
expect(proxyLoadingError.error.value).toBe(error);
|
|
42
|
+
expect(proxyLoadingError.errored.value).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should clear all errors when clearError is called", () => {
|
|
46
|
+
const proxyLoadingError = useProxyLoadingError([loadingError1, loadingError2]);
|
|
47
|
+
proxyLoadingError.clearError();
|
|
48
|
+
expect(loadingError1.clearError).toHaveBeenCalled();
|
|
49
|
+
expect(loadingError2.clearError).toHaveBeenCalled();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should reflect correct aggregate state when combining multiple sources", () => {
|
|
53
|
+
loadingError1.loading.value = true;
|
|
54
|
+
loadingError2.errored.value = true;
|
|
55
|
+
const error = new Error("Another Error");
|
|
56
|
+
loadingError2.error.value = error;
|
|
57
|
+
|
|
58
|
+
const proxyLoadingError = useProxyLoadingError([loadingError1, loadingError2]);
|
|
59
|
+
|
|
60
|
+
expect(proxyLoadingError.loading.value).toBe(true); // One source is loading
|
|
61
|
+
expect(proxyLoadingError.errored.value).toBe(true); // One source has an error
|
|
62
|
+
expect(proxyLoadingError.error.value).toBe(error); // Error is aggregated
|
|
63
|
+
});
|
|
64
|
+
});
|
package/use/listRelated.js
CHANGED
|
@@ -34,7 +34,7 @@ import { computed, effectScope, onScopeDispose, reactive, ref, toRef, unref, wat
|
|
|
34
34
|
* @typedef {object} ListRelatedRule
|
|
35
35
|
* @property {string} pkKey - Specifies the foreign key used to link objects across lists. Planned to be renamed to
|
|
36
36
|
* 'fkKey' to better reflect its usage.
|
|
37
|
-
* @property {string[]} order - Specifies the order in which related objects should be sorted, if applicable.
|
|
37
|
+
* @property {string[]} [order] - Specifies the order in which related objects should be sorted, if applicable.
|
|
38
38
|
* @property {import('./listInstance.js').ObjectsById} objects - The objects that can be related based on the foreign key.
|
|
39
39
|
*/
|
|
40
40
|
|
package/use/loadingError.js
CHANGED
|
@@ -5,14 +5,28 @@ import { readonly, ref } from "vue";
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* The common API for loading and error states.
|
|
9
|
+
*
|
|
10
|
+
* @typedef {object} LoadingErrorStatus
|
|
9
11
|
* @property {Readonly<import("vue").Ref<boolean|undefined>>} loading - Whether the component is loading.
|
|
10
12
|
* @property {Readonly<import("vue").Ref<Error|null>>} error - The error that occurred.
|
|
11
13
|
* @property {Readonly<import("vue").Ref<boolean>>} errored - Whether an error has occurred.
|
|
14
|
+
* @property {() => void} clearError - Clear the error state.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The writable API for loading and error states.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {object} LoadingErrorMutations
|
|
12
21
|
* @property {() => void} setLoading - Set the loading state.
|
|
13
22
|
* @property {() => void} clearLoading - Clear the loading state.
|
|
14
23
|
* @property {(error) => void} setError - Set the error state.
|
|
15
|
-
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The instance of useLoadingError.
|
|
28
|
+
*
|
|
29
|
+
* @typedef {LoadingErrorStatus & LoadingErrorMutations} LoadingError
|
|
16
30
|
*/
|
|
17
31
|
|
|
18
32
|
/**
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { computed, readonly, unref } from "vue";
|
|
2
|
+
import { loadingCombine } from "../utils/loadingCombine.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {(
|
|
6
|
+
* import('./loadingError.js').LoadingErrorStatus[]
|
|
7
|
+
* )} WatchableLoadingErrorsRaw
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A watchable collection of loading errors.
|
|
12
|
+
*
|
|
13
|
+
* @typedef {(
|
|
14
|
+
* import('vue').UnwrapNestedRefs<WatchableLoadingErrorsRaw> |
|
|
15
|
+
* import('vue').Ref<WatchableLoadingErrorsRaw> |
|
|
16
|
+
* WatchableLoadingErrorsRaw
|
|
17
|
+
* )} WatchableLoadingErrors
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The instance of useProxyLoadingError.
|
|
22
|
+
*
|
|
23
|
+
* @typedef {import('./loadingError.js').LoadingErrorStatus} ProxyLoadingError
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A composable function for managing aggregated loading and error states across multiple sources.
|
|
28
|
+
*
|
|
29
|
+
* @param {WatchableLoadingErrors} loadingErrors - A collection of loading error statuses to monitor and aggregate.
|
|
30
|
+
* @returns {ProxyLoadingError} An object containing aggregated reactive fields and actions for loading and error states.
|
|
31
|
+
*/
|
|
32
|
+
export function useProxyLoadingError(loadingErrors) {
|
|
33
|
+
/** @type {import("vue").ComputedRef<boolean|undefined>} */
|
|
34
|
+
const loading = computed(() =>
|
|
35
|
+
loadingCombine(...unref(loadingErrors).map((loadingError) => unref(loadingError.loading)))
|
|
36
|
+
);
|
|
37
|
+
/** @type {import("vue").ComputedRef<Error|null>} */
|
|
38
|
+
const error = computed(
|
|
39
|
+
() =>
|
|
40
|
+
unref(loadingErrors)
|
|
41
|
+
.map((loadingError) => unref(loadingError.error))
|
|
42
|
+
.find((error) => error) || null
|
|
43
|
+
);
|
|
44
|
+
/** @type {import("vue").ComputedRef<boolean>} */
|
|
45
|
+
const errored = computed(() =>
|
|
46
|
+
unref(loadingErrors)
|
|
47
|
+
.map((loadingError) => unref(loadingError.errored))
|
|
48
|
+
.some((errored) => errored)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
loading: readonly(loading),
|
|
53
|
+
error: readonly(error),
|
|
54
|
+
errored: readonly(errored),
|
|
55
|
+
clearError: () => {
|
|
56
|
+
unref(loadingErrors).forEach((loadingError) => loadingError.clearError());
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|