@arrai-innovations/reactive-helpers 21.1.2 → 22.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.
Files changed (78) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +109 -21
  3. package/config/commonCrud.js +7 -10
  4. package/config/listCrud.js +33 -33
  5. package/config/objectCrud.js +64 -59
  6. package/package.json +103 -89
  7. package/types/config/listCrud.d.ts +83 -28
  8. package/types/config/objectCrud.d.ts +139 -49
  9. package/types/tests/benchmarks/fixtures.d.ts +60 -0
  10. package/types/tests/benchmarks/listLayers.bench.d.ts +1 -0
  11. package/types/tests/benchmarks/listPush.bench.d.ts +1 -0
  12. package/types/tests/benchmarks/listStream.bench.d.ts +1 -0
  13. package/types/tests/unit/use/lifecycleCleanup.spec.d.ts +1 -0
  14. package/types/tests/unit/use/listPerformance.spec.d.ts +1 -0
  15. package/types/tests/unit/utils/cancellablePromise.spec.d.ts +1 -0
  16. package/types/use/cancellableIntent.d.ts +36 -33
  17. package/types/use/combineClasses.d.ts +5 -2
  18. package/types/use/error.d.ts +39 -19
  19. package/types/use/list.d.ts +27 -26
  20. package/types/use/listCalculated.d.ts +38 -55
  21. package/types/use/listFilter.d.ts +25 -33
  22. package/types/use/listInstance.d.ts +94 -81
  23. package/types/use/listRelated.d.ts +37 -57
  24. package/types/use/listSearch.d.ts +54 -52
  25. package/types/use/listSort.d.ts +31 -40
  26. package/types/use/listSubscription.d.ts +33 -36
  27. package/types/use/loading.d.ts +20 -10
  28. package/types/use/loadingError.d.ts +12 -3
  29. package/types/use/object.d.ts +8 -5
  30. package/types/use/objectCalculated.d.ts +46 -39
  31. package/types/use/objectInstance.d.ts +70 -74
  32. package/types/use/objectRelated.d.ts +51 -41
  33. package/types/use/objectSubscription.d.ts +38 -48
  34. package/types/use/proxyError.d.ts +15 -6
  35. package/types/use/proxyLoading.d.ts +11 -5
  36. package/types/use/proxyLoadingError.d.ts +19 -7
  37. package/types/use/search.d.ts +33 -29
  38. package/types/utils/assignReactiveObject.d.ts +3 -0
  39. package/types/utils/cancellableFetch.d.ts +2 -3
  40. package/types/utils/cancellablePromise.d.ts +42 -8
  41. package/types/utils/classes.d.ts +7 -1
  42. package/types/utils/deepUnref.d.ts +1 -1
  43. package/types/utils/getFakePk.d.ts +2 -2
  44. package/types/utils/isReactiveTyped.d.ts +2 -0
  45. package/types/utils/keyDiff.d.ts +4 -6
  46. package/types/utils/relatedCalculatedHelpers.d.ts +2 -0
  47. package/types/utils/watches.d.ts +1 -1
  48. package/use/cancellableIntent.js +36 -9
  49. package/use/combineClasses.js +2 -2
  50. package/use/error.js +10 -14
  51. package/use/list.js +6 -18
  52. package/use/listCalculated.js +28 -38
  53. package/use/listFilter.js +12 -24
  54. package/use/listInstance.js +101 -60
  55. package/use/listRelated.js +18 -37
  56. package/use/listSearch.js +9 -18
  57. package/use/listSort.js +95 -64
  58. package/use/listSubscription.js +19 -25
  59. package/use/loading.js +5 -7
  60. package/use/loadingError.js +3 -3
  61. package/use/object.js +14 -27
  62. package/use/objectCalculated.js +21 -25
  63. package/use/objectInstance.js +55 -50
  64. package/use/objectRelated.js +19 -25
  65. package/use/objectSubscription.js +18 -30
  66. package/use/proxyError.js +10 -10
  67. package/use/proxyLoading.js +5 -5
  68. package/use/proxyLoadingError.js +13 -8
  69. package/use/search.js +5 -11
  70. package/utils/assignReactiveObject.js +3 -3
  71. package/utils/cancellableFetch.js +3 -3
  72. package/utils/cancellablePromise.js +25 -8
  73. package/utils/classes.js +2 -2
  74. package/utils/deepUnref.js +1 -5
  75. package/utils/getFakePk.js +2 -2
  76. package/utils/isReactiveTyped.js +2 -0
  77. package/utils/keyDiff.js +1 -3
  78. package/utils/relatedCalculatedHelpers.js +2 -0
package/use/object.js CHANGED
@@ -14,48 +14,38 @@ import { effectScope, shallowReactive, shallowReadonly, toRef } from "vue";
14
14
  */
15
15
 
16
16
  /**
17
- * Defines the raw reactive properties that can be passed to an object instance.
18
- *
19
17
  * @typedef {(
20
18
  * import('./objectInstance.js').ObjectInstanceRawProps &
21
19
  * import('./objectSubscription.js').ObjectSubscriptionRawProps &
22
20
  * import('./objectRelated.js').ObjectRelatedRawProps &
23
21
  * import('./objectCalculated.js').ObjectCalculatedRawProps
24
- * )} ObjectManagerRawProps
22
+ * )} ObjectManagerRawProps - Defines the raw reactive properties that can be passed to an object instance.
25
23
  */
26
24
 
27
25
  /**
28
- * Defines the reactive properties that can be passed to an object instance.
29
- *
30
- * @typedef {import('vue').UnwrapNestedRefs<ObjectManagerRawProps>} ObjectManagerProps
26
+ * @typedef {import('vue').UnwrapNestedRefs<ObjectManagerRawProps>} ObjectManagerProps - Defines the reactive properties that can be passed to an object instance.
31
27
  */
32
28
 
33
29
  /**
34
- * Defines the non-reactive handlers that can be passed to an object instance.
35
- *
36
- * @typedef {object} ObjectManagerOptions
30
+ * @typedef {object} ObjectManagerOptions - Defines the non-reactive handlers that can be passed to an object instance.
37
31
  * @property {ObjectManagerProps} props - The reactive properties to be passed to the object instance.
38
32
  * @property {import('../config/objectCrud.js').ObjectCrudHandlers} handlers - The non-reactive handlers to be passed to the object instance.
39
33
  */
40
34
 
41
35
  /**
42
- * Defines the managed object, containing the managed object instance, subscription, related objects, and calculated objects.
43
- *
44
36
  * @typedef {{
45
37
  * objectInstance: import('./objectInstance.js').ObjectInstance,
46
38
  * objectSubscription: import('./objectSubscription.js').ObjectSubscription,
47
39
  * objectRelated: import('./objectRelated.js').ObjectRelated,
48
40
  * objectCalculated: import('./objectCalculated.js').ObjectCalculated,
49
- * }} ObjectManaged
41
+ * }} ObjectManaged - Defines the managed object, containing the managed object instance, subscription, related objects, and calculated objects.
50
42
  */
51
43
 
52
44
  /**
53
- * Defines the functions provided by the object manager.
54
- *
55
45
  * @typedef {(
56
46
  * import('./objectInstance.js').ObjectInstanceFunctions
57
47
  * & import('./objectSubscription.js').ObjectSubscriptionFunctions
58
- * )} ObjectManagerFunctions
48
+ * )} ObjectManagerFunctions - Defines the functions provided by the object manager.
59
49
  * @property {Function} clearError - Clears the error state of the managed subscription and instance.
60
50
  * @property {Function} clear - Clears the managed instance & any error state.
61
51
  */
@@ -64,9 +54,7 @@ import { effectScope, shallowReactive, shallowReadonly, toRef } from "vue";
64
54
  // & import('./objectCalculated.js').ObjectCalculatedFunctions
65
55
 
66
56
  /**
67
- * Defines the properties available on an object manager.
68
- *
69
- * @typedef {object} ObjectManagerProperties
57
+ * @typedef {object} ObjectManagerProperties - Defines the properties available on an object manager.
70
58
  * @property {ObjectManaged} managed - The managed object.
71
59
  * @property {import('./objectCalculated.js').ObjectCalculatedState} state - The state of the managed object.
72
60
  * @property {() => void} stop - Stop the effect scope of the managed object.
@@ -74,7 +62,7 @@ import { effectScope, shallowReactive, shallowReadonly, toRef } from "vue";
74
62
 
75
63
  /**
76
64
  *
77
- * @typedef {ObjectManagerProperties & ObjectManagerFunctions} ObjectManager
65
+ * @typedef {ObjectManagerProperties & ObjectManagerFunctions} ObjectManager - The fully managed object returned by useObject, combining its properties and functions.
78
66
  */
79
67
 
80
68
  /**
@@ -128,7 +116,7 @@ function mergeFns(source) {
128
116
  * ```
129
117
  * <script setup>
130
118
  * import { useObject } from "@arrai-innovations/reactive-helpers";
131
- * import { reactive, ref, toRef } from "vue";
119
+ * import { computed, reactive, toRef } from "vue";
132
120
  *
133
121
  * const someObjectsSource = reactive({
134
122
  * objects: {
@@ -171,25 +159,24 @@ function mergeFns(source) {
171
159
  * order: ['3','1','2'],
172
160
  * },
173
161
  * secondOrder: {
174
- * pkKey: 'relatedObject.secondOrderId',
162
+ * pkKey: 'relatedItem.firstOrder.secondOrderId',
175
163
  * objects: someOtherObjectsSource.objects,
176
164
  * },
177
165
  * },
178
166
  * calculatedObjectRules: {
179
- * someRule: (object, relatedObject, calculatedObjects) => {
180
- * // some complex calculation, relatedObjects would be assuming there was a listRelated between the two
181
- * // calculatedObjects would be the other calculated objects in the list
182
- * // including yourself, so try not to create circular dependencies
167
+ * someRule: (object, relatedObject) => {
168
+ * // some complex calculation. relatedObject holds the objects matched by relatedObjectRules above,
169
+ * // keyed by rule name.
183
170
  * // this is used as a computed body.
184
171
  * return object.foo + object.name;
185
172
  * },
186
- * ...
173
+ * // ...further rules
187
174
  * },
188
175
  * intendToRetrieve: false,
189
176
  * intendToSubscribe: false,
190
177
  * });
191
178
  * objectProps.intendToRetrieve = objectProps.intendToSubscribe = computed(()=> !!props.pk);
192
- * const objectManager = useObject(objectProps);
179
+ * const objectManager = useObject({ props: objectProps });
193
180
  * // objectManager.state.object comes back from the server (via configured crud retrieve function)
194
181
  * // { id: 2, name: 'two', foo: 'bar', some_objects_id: 2, some_objects_list_ids: ['1','2','3'] }
195
182
  * </script>
@@ -14,19 +14,19 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
14
14
  */
15
15
 
16
16
  /**
17
- * The object calculated state keys.
18
- *
19
17
  * @typedef {{
20
18
  * [ruleKey: string]: (object: any, relatedObject: any) => any
21
- * }} ObjectCalculatedRules
19
+ * }} ObjectCalculatedRules - Rules for calculating values from the managed object, keyed by rule name. Each rule is used
20
+ * as a computed body and receives exactly two arguments: the managed object and its related objects (the latter only
21
+ * populated when a useObjectRelated sits upstream).
22
22
  */
23
23
 
24
24
  /**
25
25
  * @typedef {object} ObjectCalculatedRawState - The raw state for object calculated.
26
26
  * @property {ObjectCalculatedRules} calculatedObjectRules - The calculated object rules.
27
27
  * @property {{
28
- * [ruleKey: string]: import('vue').ComputedRef<any>
29
- * }} calculatedObject - The calculated object.
28
+ * [ruleKey: string]: any
29
+ * }} calculatedObject - The calculated values, by rule name. Each entry is backed by a computed, but it is read through a reactive proxy that unwraps it, so reads yield the calculated value and never carry a `.value`.
30
30
  * @property {boolean} calculatedObjectWatchRunning - Whether the calculated object watch is running.
31
31
  * @property {boolean} parentStateObjectWatchRunning - Whether the parent state object watch is running.
32
32
  * @property {boolean} calculatedRunning - Whether the calculated is running.
@@ -40,7 +40,7 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
40
40
  * import('./objectInstance.js').ObjectInstanceRawState &
41
41
  * Partial<import('./objectSubscription.js').ObjectSubscriptionRawState> &
42
42
  * Partial<import('./objectRelated.js').ObjectRelatedRawState>
43
- * )} ObjectCalculatedParentRawState
43
+ * )} ObjectCalculatedParentRawState - The raw, pre-unwrapped parent state consumed by the object calculated mixin, aggregating the upstream object composable states.
44
44
  */
45
45
 
46
46
  /**
@@ -52,18 +52,14 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
52
52
  */
53
53
 
54
54
  /**
55
- * The state for object calculated.
56
- *
57
55
  * @typedef {import('vue').UnwrapNestedRefs<
58
56
  * ObjectCalculatedParentRawState &
59
57
  * ObjectCalculatedRawState
60
- * >} ObjectCalculatedState
58
+ * >} ObjectCalculatedState - The state for object calculated.
61
59
  */
62
60
 
63
61
  /**
64
- * The properties for object calculated.
65
- *
66
- * @typedef {object} ObjectCalculatedProperties
62
+ * @typedef {object} ObjectCalculatedProperties - The properties for object calculated.
67
63
  * @property {ObjectCalculatedParentState} parentState - The parent state.
68
64
  * @property {ObjectCalculatedState} state - The object calculated state.
69
65
  * @property {() => void} stop - Stops composition's effects and cleans up resources.
@@ -72,15 +68,13 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
72
68
  // if we provided functions, we would add a typedef and mix them into ObjectCalculated
73
69
 
74
70
  /**
75
- * The object calculated instance.
76
- *
77
- * @typedef {ObjectCalculatedProperties} ObjectCalculated
71
+ * @typedef {ObjectCalculatedProperties} ObjectCalculated - The object calculated instance.
78
72
  */
79
73
 
80
74
  /**
81
75
  *
82
76
  *
83
- * @typedef {object} ObjectCalculatedRawProps
77
+ * @typedef {object} ObjectCalculatedRawProps - The consumer-supplied props for the object calculated composable, namely the calculated-object rules ref.
84
78
  * @property {import('vue').Ref<ObjectCalculatedRules>} calculatedObjectRules - The calculated object rules.
85
79
  */
86
80
 
@@ -88,9 +82,10 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
88
82
  *
89
83
  * @typedef {({
90
84
  * parentState: ObjectCalculatedParentState,
91
- * } & ObjectCalculatedRawProps)} ObjectCalculatedOptions
85
+ * } & ObjectCalculatedRawProps)} ObjectCalculatedOptions - The options used to create an object calculated instance (the parent state plus the calculated-object rules).
92
86
  */
93
87
 
88
+ /** @internal */
94
89
  export const objectCalculatedStateKeys = [
95
90
  "calculatedObject",
96
91
  "calculatedObjectRules",
@@ -100,6 +95,7 @@ export const objectCalculatedStateKeys = [
100
95
  // "running",
101
96
  ];
102
97
 
98
+ /** @internal */
103
99
  export const objectCalculatedFunctions = [];
104
100
 
105
101
  /**
@@ -131,7 +127,7 @@ export function useObjectCalculateds(objectCalculatedArgs) {
131
127
  * ```vue
132
128
  * <script setup>
133
129
  * import { useObjectCalculated, useObjectSubscription } from "@arrai-innovations/reactive-helpers";
134
- * import { ref, reactive } from "vue";
130
+ * import { reactive } from "vue";
135
131
  *
136
132
  * const objectSubscriptionProps = reactive({
137
133
  * // whatever object subscription props you need to work with your crud implementation
@@ -140,21 +136,21 @@ export function useObjectCalculateds(objectCalculatedArgs) {
140
136
  * pk: '1',
141
137
  * pkKey: 'id',
142
138
  * intendToRetrieve: true,
143
- * };
144
- * const objectSubscription = useObjectSubscription(objectSubscriptionProps);
139
+ * });
140
+ * const objectSubscription = useObjectSubscription({ props: objectSubscriptionProps });
145
141
  * const objectCalculatedProps = reactive({
146
142
  * parentState: objectSubscription.state,
147
143
  * calculatedObjectRules: {
148
- * someRule: (object, relatedObject, calculatedObjects) => {
149
- * // some complex calculation, relatedObjects would be assuming there was a listRelated between the two
150
- * // calculatedObjects would be the other calculated objects in the list
151
- * // including yourself, so try not to create circular dependencies
144
+ * someRule: (object, relatedObject) => {
145
+ * // some complex calculation. relatedObject holds the managed object's related objects, and is
146
+ * // only populated when a useObjectRelated sits between the object and this composable.
152
147
  * // this is used as a computed body.
153
148
  * return object.someProperty + object.someOtherProperty;
154
149
  * },
155
- * ...
150
+ * // ...further rules
156
151
  * },
157
152
  * });
153
+ * const objectCalculated = useObjectCalculated(objectCalculatedProps);
158
154
  * </script>
159
155
  * <template>
160
156
  * <div>
@@ -2,7 +2,7 @@ import { defaultObjectCrud, getObjectCrud } from "../config/objectCrud.js";
2
2
  import { assignReactiveObject } from "../utils/assignReactiveObject.js";
3
3
  import { useLoadingError } from "./loadingError.js";
4
4
  import { reactive, readonly, ref } from "vue";
5
- import { CancellablePromise, wrapMaybeCancellable } from "../utils/cancellablePromise.js";
5
+ import { wrapMaybeCancellable } from "../utils/cancellablePromise.js";
6
6
  import { pkRefIfReactive, refIfReactive } from "../utils/refIfReactive.js";
7
7
 
8
8
  /**
@@ -12,34 +12,25 @@ import { pkRefIfReactive, refIfReactive } from "../utils/refIfReactive.js";
12
12
  */
13
13
 
14
14
  /**
15
- * The object being managed by the instance. It must include a primary key field as identifying property, matching
16
- * the name provided to the object/list's `pkKey` value, which is not known statically.
17
- *
18
- * @typedef {{[key: string]: any}} ExistingCrudObject
15
+ * @typedef {{[key: string]: any}} ExistingCrudObject - The object being managed by the instance. It must include a primary key field as identifying property, matching the name provided to the object/list's `pkKey` value, which is not known statically.
19
16
  */
20
17
 
21
18
  /**
22
- * The object you would like an object instance to create for you.
23
- *
24
- * @typedef {{[key: string]: any}} NewCrudObject
19
+ * @typedef {{[key: string]: any}} NewCrudObject - The object you would like an object instance to create for you.
25
20
  */
26
21
 
27
22
  /**
28
- * @typedef {ExistingCrudObject|NewCrudObject} CrudObject
23
+ * @typedef {ExistingCrudObject|NewCrudObject} CrudObject - An object managed by an object instance, either an existing object or a new object to be created.
29
24
  */
30
25
 
31
26
  /**
32
- * Arguments to be passed to the object instance.
33
- *
34
- * @typedef {object} ObjectInstanceOptions
27
+ * @typedef {object} ObjectInstanceOptions - Arguments to be passed to the object instance.
35
28
  * @property {import('vue').UnwrapNestedRefs<ObjectInstanceRawProps>} props - The reactive configuration object.
36
29
  * @property {import('../config/objectCrud.js').ObjectCrudHandlers} [handlers] - An object of custom crud handlers to use instead of the defaults.
37
30
  */
38
31
 
39
32
  /**
40
- * Reactive arguments to be passed to the object instance.
41
- *
42
- * @typedef {object} ObjectInstanceRawProps
33
+ * @typedef {object} ObjectInstanceRawProps - Reactive arguments to be passed to the object instance.
43
34
  * @property {import('../config/commonCrud.js').PkInput} [pk] - The pk of the object, optional to support creating new objects.
44
35
  * @property {string} pkKey - The pk key of the object.
45
36
  * @property {object} params - The arguments to be passed to the retrieve function.
@@ -47,7 +38,7 @@ import { pkRefIfReactive, refIfReactive } from "../utils/refIfReactive.js";
47
38
  */
48
39
 
49
40
  /**
50
- * @typedef {object} ObjectInstanceRawStateCrud
41
+ * @typedef {object} ObjectInstanceRawStateCrud - The raw CRUD handlers and target args stored in an object instance's reactive state.
51
42
  * @property {import('vue').Reactive<import('../config/objectCrud.js').TargetArgs|{}>} args - The arguments to be passed to the crud handlers.
52
43
  * @property {import('../config/objectCrud.js').CrudCreateFn} create - The create function.
53
44
  * @property {import('../config/objectCrud.js').CrudRetrieveFn} retrieve - The retrieve function.
@@ -59,42 +50,34 @@ import { pkRefIfReactive, refIfReactive } from "../utils/refIfReactive.js";
59
50
  */
60
51
 
61
52
  /**
62
- * The raw state of the object instance.
63
- *
64
- * @typedef {object} ObjectInstanceRawMyState
53
+ * @typedef {object} ObjectInstanceRawMyState - The raw state of the object instance.
65
54
  * @property {import('vue').Reactive<ObjectInstanceRawStateCrud>} crud - The crud handlers.
66
55
  * @property {import('vue').Ref<import('../config/commonCrud.js').Pk|undefined>} pk - The pk of the object.
67
56
  * @property {import('vue').Ref<string|undefined>} pkKey - The pk key of the object.
68
57
  * @property {import('vue').Ref<{[key:string]: any}>} params - The arguments to be passed to the retrieve function.
69
58
  * @property {import('vue').Reactive<CrudObject>} object - The object.
70
- * @property {boolean} deleted - Whether the object is deleted.
59
+ * @property {boolean} deleted - Whether the object was deleted by the delete action or a subscription delete
60
+ * event. Cleared when a later create, retrieve, update, or patch repopulates the object, and by `clear()`.
71
61
  */
72
62
 
73
63
  /**
74
- * The raw state of the object instance.
75
- *
76
- * @typedef {ObjectInstanceRawMyState & import('./loadingError.js').LoadingErrorProperties} ObjectInstanceRawState
64
+ * @typedef {ObjectInstanceRawMyState & import('./loadingError.js').LoadingErrorProperties} ObjectInstanceRawState - The raw state of the object instance.
77
65
  */
78
66
 
79
67
  /**
80
- * Manages a reactive state of an object including its CRUD status, loading states, and any operational errors.
81
- * Reactivity ensures that any changes in state immediately reflect in the UI components that depend on this state.
82
- *
83
- * @typedef {import('vue').Reactive<ObjectInstanceRawState>} ObjectInstanceState
68
+ * @typedef {import('vue').Reactive<ObjectInstanceRawState>} ObjectInstanceState - Manages a reactive state of an object including its CRUD status, loading states, and any operational errors. Reactivity ensures that any changes in state immediately reflect in the UI components that depend on this state.
84
69
  */
85
70
 
86
- /** @typedef {{ object: NewCrudObject }} ObjectInstanceCreateArgs */
87
- /** @typedef {{ object: ExistingCrudObject }} ObjectInstanceUpdateArgs */
88
- /** @typedef {{ partialObject: ExistingCrudObject }} ObjectInstancePatchArgs */
71
+ /** @typedef {{ object: NewCrudObject }} ObjectInstanceCreateArgs - The argument shape for an object instance's create operation, carrying the new object to create. */
72
+ /** @typedef {{ object: ExistingCrudObject }} ObjectInstanceUpdateArgs - The argument shape for an object instance's update operation, carrying the existing object to update. */
73
+ /** @typedef {{ partialObject: ExistingCrudObject }} ObjectInstancePatchArgs - The argument shape for an object instance's patch operation, carrying the partial object to apply. */
89
74
 
90
75
  /**
91
- * @typedef {{[key:string]: any}} AdditionalArgs
76
+ * @typedef {{[key:string]: any}} AdditionalArgs - Arbitrary extra arguments forwarded through to an object instance's CRUD operations.
92
77
  */
93
78
 
94
79
  /**
95
- * The functions available on the object instance.
96
- *
97
- * @typedef {object} ObjectInstanceMyFunctions
80
+ * @typedef {object} ObjectInstanceMyFunctions - The functions available on the object instance.
98
81
  * @property {(args: ObjectInstanceCreateArgs & AdditionalArgs) => import('../utils/cancellablePromise.js').MaybeCancellablePromise<boolean|never>} create - Called to turn the current object into a new object on the server.
99
82
  * @property {(args?: Partial<import('./cancellableIntent.js').CommonRunTracking> & AdditionalArgs) => import('../utils/cancellablePromise.js').MaybeCancellablePromise<boolean|never>} retrieve - Called to retrieve the current object by pk from the server.
100
83
  * @property {(args: ObjectInstanceUpdateArgs & AdditionalArgs) => import('../utils/cancellablePromise.js').MaybeCancellablePromise<boolean|never>} update - Called to update the current object on the server.
@@ -105,25 +88,19 @@ import { pkRefIfReactive, refIfReactive } from "../utils/refIfReactive.js";
105
88
  */
106
89
 
107
90
  /**
108
- * The functions available on the object instance, including the ability to clear LoadingError errors.
109
- *
110
91
  * @typedef {(
111
92
  * import('./error.js').ErrorReadOnlyFunctions &
112
93
  * ObjectInstanceMyFunctions
113
- * )} ObjectInstanceFunctions
94
+ * )} ObjectInstanceFunctions - The functions available on the object instance, including the ability to clear LoadingError errors.
114
95
  */
115
96
 
116
97
  /**
117
- * The properties of the object instance.
118
- *
119
- * @typedef {object} ObjectInstanceProperties
98
+ * @typedef {object} ObjectInstanceProperties - The properties of the object instance.
120
99
  * @property {ObjectInstanceState} state - The state of the object instance.
121
100
  */
122
101
 
123
102
  /**
124
- * The instance of the object instance.
125
- *
126
- * @typedef {ObjectInstanceFunctions & ObjectInstanceProperties} ObjectInstance
103
+ * @typedef {ObjectInstanceFunctions & ObjectInstanceProperties} ObjectInstance - The instance of the object instance.
127
104
  */
128
105
 
129
106
  /**
@@ -144,6 +121,7 @@ export class ObjectError extends Error {
144
121
  }
145
122
  }
146
123
 
124
+ /** @internal */
147
125
  export const objectInstanceStateKeys = [
148
126
  "crud",
149
127
  "pk",
@@ -156,6 +134,7 @@ export const objectInstanceStateKeys = [
156
134
  "deleted",
157
135
  ];
158
136
 
137
+ /** @internal */
159
138
  export const objectInstanceFunctions = [
160
139
  "create",
161
140
  "retrieve",
@@ -302,10 +281,14 @@ export function useObjectInstance({ props, handlers = {} }) {
302
281
  createPromise
303
282
  .then((/** @type {ExistingCrudObject} */ object) => {
304
283
  assignReactiveObject(state.object, object);
284
+ state.deleted = false;
305
285
  return true;
306
286
  })
307
287
  .catch((/** @type {Error} */ error) => {
308
- loadingError.setError(error);
288
+ // A deliberate cancellation rejects with the cancel reason; that is not an error.
289
+ if (!isCancelled.value) {
290
+ loadingError.setError(error);
291
+ }
309
292
  return false;
310
293
  })
311
294
  .finally(() => {
@@ -348,17 +331,21 @@ export function useObjectInstance({ props, handlers = {} }) {
348
331
  } catch (error) {
349
332
  loadingError.setError(error);
350
333
  loadingError.clearLoading();
351
- return CancellablePromise.resolve(false);
334
+ return Promise.resolve(false);
352
335
  }
353
336
 
354
337
  promises.retrieve = wrapMaybeCancellable(
355
338
  retrievePromise
356
339
  .then((/** @type {ExistingCrudObject} */ object) => {
357
340
  assignReactiveObject(state.object, object);
341
+ state.deleted = false;
358
342
  return true;
359
343
  })
360
344
  .catch((/** @type {Error} */ error) => {
361
- loadingError.setError(error);
345
+ // A deliberate cancellation rejects with the cancel reason; that is not an error.
346
+ if (!isCancelled.value) {
347
+ loadingError.setError(error);
348
+ }
362
349
  return false;
363
350
  })
364
351
  .finally(() => {
@@ -398,10 +385,14 @@ export function useObjectInstance({ props, handlers = {} }) {
398
385
  updatePromise
399
386
  .then((/** @type {ExistingCrudObject} */ object) => {
400
387
  assignReactiveObject(state.object, object);
388
+ state.deleted = false;
401
389
  return true;
402
390
  })
403
391
  .catch((/** @type {Error} */ error) => {
404
- loadingError.setError(error);
392
+ // A deliberate cancellation rejects with the cancel reason; that is not an error.
393
+ if (!isCancelled.value) {
394
+ loadingError.setError(error);
395
+ }
405
396
  return false;
406
397
  })
407
398
  .finally(() => {
@@ -425,11 +416,13 @@ export function useObjectInstance({ props, handlers = {} }) {
425
416
  }
426
417
  loadingError.setLoading();
427
418
  loadingError.clearError();
419
+ const isCancelled = ref(false);
428
420
  const deletePromise = state.crud.delete({
429
421
  ...args,
430
422
  target: state.crud.args,
431
423
  pk: state.pk,
432
424
  pkKey: state.pkKey,
425
+ isCancelled: readonly(isCancelled),
433
426
  });
434
427
  return wrapMaybeCancellable(
435
428
  deletePromise
@@ -439,7 +432,10 @@ export function useObjectInstance({ props, handlers = {} }) {
439
432
  return true;
440
433
  })
441
434
  .catch((/** @type {Error} */ error) => {
442
- loadingError.setError(error);
435
+ // A deliberate cancellation rejects with the cancel reason; that is not an error.
436
+ if (!isCancelled.value) {
437
+ loadingError.setError(error);
438
+ }
443
439
  return false;
444
440
  })
445
441
  .finally(() => {
@@ -447,6 +443,7 @@ export function useObjectInstance({ props, handlers = {} }) {
447
443
  }),
448
444
  deletePromise.cancel
449
445
  ? async (/** @type {any} */ reason) => {
446
+ isCancelled.value = true;
450
447
  await deletePromise.cancel?.(reason);
451
448
  loadingError.clearLoading();
452
449
  }
@@ -476,10 +473,14 @@ export function useObjectInstance({ props, handlers = {} }) {
476
473
  patchPromise
477
474
  .then((/** @type {ExistingCrudObject} */ object) => {
478
475
  assignReactiveObject(state.object, object);
476
+ state.deleted = false;
479
477
  return true;
480
478
  })
481
479
  .catch((/** @type {Error} */ error) => {
482
- loadingError.setError(error);
480
+ // A deliberate cancellation rejects with the cancel reason; that is not an error.
481
+ if (!isCancelled.value) {
482
+ loadingError.setError(error);
483
+ }
483
484
  return false;
484
485
  })
485
486
  .finally(() => {
@@ -515,7 +516,10 @@ export function useObjectInstance({ props, handlers = {} }) {
515
516
  return true;
516
517
  })
517
518
  .catch((/** @type {Error} */ error) => {
518
- loadingError.setError(error);
519
+ // A deliberate cancellation rejects with the cancel reason; that is not an error.
520
+ if (!isCancelled.value) {
521
+ loadingError.setError(error);
522
+ }
519
523
  return false;
520
524
  })
521
525
  .finally(() => {
@@ -534,6 +538,7 @@ export function useObjectInstance({ props, handlers = {} }) {
534
538
  clear: () => {
535
539
  loadingError.clearError();
536
540
  assignReactiveObject(state.object, {});
541
+ state.deleted = false;
537
542
  },
538
543
  };
539
544
  return instance;
@@ -20,30 +20,27 @@ import { computed, effectScope, nextTick, reactive, ref, toRef, unref, watch } f
20
20
 
21
21
  // todo: pkKey is misnamed, it should be fkKey... this will be a major breaking change.
22
22
  /**
23
- * The rule for defining relationships for the managed object to other collections of objects.
24
- *
25
- * @typedef {object} ObjectRelatedRule
26
- * @property {string} pkKey - The key in the managed object that corresponds to the key in the related object.
23
+ * @typedef {object} ObjectRelatedRule - The rule for defining relationships for the managed object to other collections of objects.
24
+ * @property {string} [pkKey] - The key in the managed object that corresponds to the key in the related object.
25
+ * Defaults to the rule's own key when omitted.
27
26
  * @property {import('./listInstance.js').ObjectsByPk} objects - The related objects, indexed by the key in the related object.
28
- * @property {string[]} order - The order of the related objects, if the related objects are an array.
27
+ * @property {string[]} [order] - The order of the related objects, if the related objects are an array.
29
28
  */
30
29
 
31
30
  /**
32
- * The rules for defining relationships for the managed object to other collections of objects.
33
- *
34
31
  * @typedef {{
35
32
  * [rule: string]: ObjectRelatedRule,
36
- * }} ObjectRelatedRawRules
33
+ * }} ObjectRelatedRawRules - The rules for defining relationships for the managed object to other collections of objects.
37
34
  */
38
35
 
39
36
  /**
40
37
  *
41
38
  *
42
- * @typedef {object} ObjectRelatedRawState
39
+ * @typedef {object} ObjectRelatedRawState - The raw reactive state of the object related composable, holding its rules, computed relations, and running flags.
43
40
  * @property {ObjectRelatedRawRules} relatedObjectRules - The rules for defining relationships for the managed object to other collections of objects.
44
41
  * @property {{
45
- * [rule: string]: import('vue').ComputedRef<any>,
46
- * }} relatedObject - The related objects, indexed by the key in the related object.
42
+ * [rule: string]: any,
43
+ * }} relatedObject - The related objects, by rule name. Each entry is backed by a computed, but it is read through a reactive proxy that unwraps it, so reads yield the related object (or array of related objects) and never carry a `.value`.
47
44
  * @property {boolean} relatedObjectWatchRunning - Whether the related object watch is running.
48
45
  * @property {boolean} parentStateObjectWatchRunning - Whether the parent state object watch is running.
49
46
  * @property {boolean} relatedRunning - Whether the related objects are loading.
@@ -56,13 +53,13 @@ import { computed, effectScope, nextTick, reactive, ref, toRef, unref, watch } f
56
53
  * @typedef {(
57
54
  * import('./objectInstance.js').ObjectInstanceRawState &
58
55
  * Partial<import('./objectSubscription.js').ObjectSubscriptionRawState>
59
- * )} ObjectRelatedParentRawState
56
+ * )} ObjectRelatedParentRawState - The raw, pre-unwrapped parent state consumed by the object related mixin (object instance plus optional subscription state).
60
57
  */
61
58
 
62
59
  /**
63
60
  *
64
61
  *
65
- * @typedef {import('vue').UnwrapNestedRefs<ObjectRelatedParentRawState>} ObjectRelatedParentState
62
+ * @typedef {import('vue').UnwrapNestedRefs<ObjectRelatedParentRawState>} ObjectRelatedParentState - The unwrapped reactive parent state consumed by the object related mixin.
66
63
  */
67
64
 
68
65
  /**
@@ -71,9 +68,10 @@ import { computed, effectScope, nextTick, reactive, ref, toRef, unref, watch } f
71
68
  * @typedef {import('vue').UnwrapNestedRefs<(
72
69
  * ObjectRelatedParentRawState &
73
70
  * ObjectRelatedRawState
74
- * )>} ObjectRelatedState
71
+ * )>} ObjectRelatedState - The unwrapped reactive state of the object related composable, combining the parent state with its own related state.
75
72
  */
76
73
 
74
+ /** @internal */
77
75
  export const objectRelatedStateKeys = [
78
76
  "relatedObject",
79
77
  "relatedObjectRules",
@@ -83,10 +81,11 @@ export const objectRelatedStateKeys = [
83
81
  "running",
84
82
  ];
85
83
 
84
+ /** @internal */
86
85
  export const objectRelatedFunctions = [];
87
86
 
88
87
  /**
89
- * @typedef {object} ObjectRelatedProperties
88
+ * @typedef {object} ObjectRelatedProperties - The members (state, parentState, stop) contributed by the object related composable.
90
89
  * @property {ObjectRelatedState} state - The state of the object related instance.
91
90
  * @property {ObjectRelatedParentState} parentState - The parent state.
92
91
  * @property {() => void} stop - Stops all effects of the object related instance.
@@ -96,27 +95,22 @@ export const objectRelatedFunctions = [];
96
95
  // if we provided functions, we would add a typedef and mix them into ObjectRelated
97
96
 
98
97
  /**
99
- * An instance of an object related reactive object.
100
- *
101
- * @typedef {ObjectRelatedProperties} ObjectRelated
98
+ * @typedef {ObjectRelatedProperties} ObjectRelated - An instance of an object related reactive object.
102
99
  */
103
100
 
104
101
  /**
105
- * Non-parent state options for useObjectRelated.
106
- *
107
- * @typedef {object} ObjectRelatedRawProps
102
+ * @typedef {object} ObjectRelatedRawProps - Non-parent state options for useObjectRelated.
108
103
  * @property {import('vue').Ref<ObjectRelatedRawRules>} relatedObjectRules - The rules for defining relationships for the managed object to other collections of objects.
109
104
  */
110
105
 
111
106
  /**
112
- * Options for useObjectRelated.
113
- *
114
107
  * @typedef {{
115
108
  * parentState: ObjectRelatedParentState,
116
- * } & ObjectRelatedRawProps} ObjectRelatedOptions
109
+ * } & ObjectRelatedRawProps} ObjectRelatedOptions - Options for useObjectRelated.
117
110
  */
118
111
 
119
112
  /**
113
+ * Creates multiple object related instances keyed by name from a map of options.
120
114
  *
121
115
  * @param {{
122
116
  * [key: string]: ObjectRelatedOptions
@@ -185,7 +179,7 @@ export function useObjectRelateds(objectRelatedArgs) {
185
179
  * order: ['3','1','2'],
186
180
  * },
187
181
  * secondOrder: {
188
- * pkKey: 'relatedObject.secondOrderId',
182
+ * pkKey: 'relatedItem.firstOrder.secondOrderId',
189
183
  * objects: someOtherObjectsSource.objects,
190
184
  * },
191
185
  * },