feathers-utils 6.0.0 → 7.0.1
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/README.md +3 -4
- package/dist/index.cjs +81 -99
- package/dist/index.d.cts +35 -33
- package/dist/index.d.mts +35 -33
- package/dist/index.d.ts +35 -33
- package/dist/index.mjs +81 -99
- package/package.json +29 -32
- package/src/.DS_Store +0 -0
- package/src/filters/array.ts +11 -13
- package/src/filters/index.ts +2 -2
- package/src/filters/object.ts +11 -11
- package/src/hooks/.DS_Store +0 -0
- package/src/hooks/checkMulti.ts +98 -82
- package/src/hooks/createRelated.ts +41 -41
- package/src/hooks/forEach.ts +32 -32
- package/src/hooks/from-client-for-server/common.ts +1 -1
- package/src/hooks/from-client-for-server/index.ts +2 -2
- package/src/hooks/from-client-for-server/paramsForServer.ts +32 -32
- package/src/hooks/from-client-for-server/paramsFromClient.ts +25 -25
- package/src/hooks/index.ts +9 -9
- package/src/hooks/onDelete.ts +54 -55
- package/src/hooks/parseFields.ts +13 -13
- package/src/hooks/removeRelated.ts +22 -20
- package/src/hooks/runPerItem.ts +17 -18
- package/src/hooks/setData.ts +295 -264
- package/src/index.ts +6 -6
- package/src/mixins/debounce-mixin/DebouncedStore.ts +29 -29
- package/src/mixins/debounce-mixin/debounceMixin.ts +17 -17
- package/src/mixins/debounce-mixin/index.ts +3 -3
- package/src/mixins/debounce-mixin/types.ts +9 -9
- package/src/mixins/debounce-mixin/utils.ts +3 -3
- package/src/mixins/index.ts +1 -1
- package/src/types.ts +3 -5
- package/src/typesInternal.ts +14 -14
- package/src/utility-types/index.ts +48 -48
- package/src/utils/_utils.internal.ts +5 -5
- package/src/utils/defineHooks.ts +8 -8
- package/src/utils/deflattenQuery.ts +31 -31
- package/src/utils/filterQuery.ts +58 -58
- package/src/utils/flattenQuery.ts +54 -54
- package/src/utils/getItemsIsArray.ts +148 -149
- package/src/utils/getPaginate.ts +31 -31
- package/src/utils/index.ts +17 -17
- package/src/utils/isMulti.ts +48 -40
- package/src/utils/isPaginated.ts +30 -30
- package/src/utils/markHookForSkip.ts +177 -178
- package/src/utils/mergeQuery/index.ts +3 -3
- package/src/utils/mergeQuery/mergeArrays.ts +67 -67
- package/src/utils/mergeQuery/mergeQuery.ts +211 -211
- package/src/utils/mergeQuery/types.ts +12 -12
- package/src/utils/mergeQuery/utils.ts +224 -224
- package/src/utils/optimizeBatchPatch.ts +42 -42
- package/src/utils/pushSet.ts +57 -57
- package/src/utils/setQueryKeySafely.ts +68 -68
- package/src/utils/setResultEmpty.ts +125 -123
- package/src/utils/shouldSkip.ts +72 -72
- package/src/utils/toJSON.ts +4 -4
- package/src/utils/validateQueryProperty.ts +10 -10
- package/src/hooks/makeSequelizeQuery.ts_ +0 -90
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Forbidden } from
|
|
2
|
-
import _get from
|
|
3
|
-
import _has from
|
|
4
|
-
|
|
5
|
-
import _set from
|
|
6
|
-
import _uniqWith from
|
|
7
|
-
import type { Path } from
|
|
8
|
-
import { mergeArrays } from
|
|
9
|
-
import type { Handle, MergeQueryOptions } from
|
|
10
|
-
import { deepEqual as _isEqual } from
|
|
11
|
-
import type { Query } from
|
|
12
|
-
import { hasOwnProperty, isEmpty } from
|
|
1
|
+
import { Forbidden } from '@feathersjs/errors'
|
|
2
|
+
import _get from 'lodash/get.js'
|
|
3
|
+
import _has from 'lodash/has.js'
|
|
4
|
+
|
|
5
|
+
import _set from 'lodash/set.js'
|
|
6
|
+
import _uniqWith from 'lodash/uniqWith.js'
|
|
7
|
+
import type { Path } from '../../typesInternal.js'
|
|
8
|
+
import { mergeArrays } from './mergeArrays.js'
|
|
9
|
+
import type { Handle, MergeQueryOptions } from './types.js'
|
|
10
|
+
import { deepEqual as _isEqual } from 'fast-equals'
|
|
11
|
+
import type { Query } from '@feathersjs/feathers'
|
|
12
|
+
import { hasOwnProperty, isEmpty } from '../_utils.internal.js'
|
|
13
13
|
|
|
14
14
|
export function handleArray(
|
|
15
15
|
target: Record<string, unknown>,
|
|
@@ -17,24 +17,24 @@ export function handleArray(
|
|
|
17
17
|
key: Path,
|
|
18
18
|
options: MergeQueryOptions,
|
|
19
19
|
): void {
|
|
20
|
-
const targetVal = _get(target, key)
|
|
21
|
-
const sourceVal = _get(source, key)
|
|
20
|
+
const targetVal = _get(target, key)
|
|
21
|
+
const sourceVal = _get(source, key)
|
|
22
22
|
if (!sourceVal && !targetVal) {
|
|
23
|
-
return
|
|
23
|
+
return
|
|
24
24
|
}
|
|
25
25
|
const handle: Handle = _get(
|
|
26
26
|
options,
|
|
27
|
-
[
|
|
27
|
+
['handle', ...key],
|
|
28
28
|
options.defaultHandle,
|
|
29
|
-
)
|
|
29
|
+
)
|
|
30
30
|
const arr = mergeArrays(
|
|
31
31
|
targetVal,
|
|
32
32
|
sourceVal,
|
|
33
33
|
handle,
|
|
34
34
|
key,
|
|
35
35
|
options.actionOnEmptyIntersect,
|
|
36
|
-
)
|
|
37
|
-
_set(target, key, arr)
|
|
36
|
+
)
|
|
37
|
+
_set(target, key, arr)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function handleCircular(
|
|
@@ -44,232 +44,232 @@ export function handleCircular(
|
|
|
44
44
|
options: MergeQueryOptions,
|
|
45
45
|
): void {
|
|
46
46
|
if (target?.$or) {
|
|
47
|
-
target.$or = cleanOr(target.$or as Record<string, unknown>[])
|
|
47
|
+
target.$or = cleanOr(target.$or as Record<string, unknown>[])
|
|
48
48
|
if (!target.$or) {
|
|
49
|
-
delete target.$or
|
|
49
|
+
delete target.$or
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
if (source?.$or) {
|
|
53
|
-
source.$or = cleanOr(source.$or as Record<string, unknown>[])
|
|
53
|
+
source.$or = cleanOr(source.$or as Record<string, unknown>[])
|
|
54
54
|
if (!source.$or) {
|
|
55
|
-
delete source.$or
|
|
55
|
+
delete source.$or
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
if (target?.$and) {
|
|
60
|
-
target.$and = cleanAnd(target.$and as Record<string, unknown>[])
|
|
60
|
+
target.$and = cleanAnd(target.$and as Record<string, unknown>[])
|
|
61
61
|
if (!target.$and) {
|
|
62
|
-
delete target.$and
|
|
62
|
+
delete target.$and
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
if (source?.$and) {
|
|
67
|
-
source.$and = cleanAnd(source.$and as Record<string, unknown>[])
|
|
67
|
+
source.$and = cleanAnd(source.$and as Record<string, unknown>[])
|
|
68
68
|
if (!source.$and) {
|
|
69
|
-
delete source.$and
|
|
69
|
+
delete source.$and
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
if (!_has(source, prependKey)) {
|
|
74
|
-
return
|
|
74
|
+
return
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
if (!_has(target, prependKey)) {
|
|
78
|
-
_set(target, prependKey, _get(source, prependKey))
|
|
79
|
-
return
|
|
78
|
+
_set(target, prependKey, _get(source, prependKey))
|
|
79
|
+
return
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const { defaultHandle, actionOnEmptyIntersect } = options
|
|
82
|
+
const { defaultHandle, actionOnEmptyIntersect } = options
|
|
83
83
|
|
|
84
|
-
if (defaultHandle ===
|
|
85
|
-
return
|
|
84
|
+
if (defaultHandle === 'target') {
|
|
85
|
+
return
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
const getTargetVal = () => {
|
|
89
|
-
return prependKey.length > 0 ? _get(target, prependKey) : target
|
|
90
|
-
}
|
|
89
|
+
return prependKey.length > 0 ? _get(target, prependKey) : target
|
|
90
|
+
}
|
|
91
91
|
|
|
92
92
|
const getSourceVal = () => {
|
|
93
|
-
return prependKey.length > 0 ? _get(source, prependKey) : source
|
|
94
|
-
}
|
|
93
|
+
return prependKey.length > 0 ? _get(source, prependKey) : source
|
|
94
|
+
}
|
|
95
95
|
|
|
96
|
-
const targetVal = getTargetVal()
|
|
97
|
-
const sourceVal = getSourceVal()
|
|
96
|
+
const targetVal = getTargetVal()
|
|
97
|
+
const sourceVal = getSourceVal()
|
|
98
98
|
|
|
99
99
|
if (_isEqual(targetVal, sourceVal)) {
|
|
100
|
-
return
|
|
100
|
+
return
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
if (defaultHandle ===
|
|
104
|
-
_set(target, prependKey, sourceVal)
|
|
105
|
-
return
|
|
103
|
+
if (defaultHandle === 'source') {
|
|
104
|
+
_set(target, prependKey, sourceVal)
|
|
105
|
+
return
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
if (targetVal === null || sourceVal === null) {
|
|
109
|
-
_set(target, prependKey, sourceVal)
|
|
110
|
-
return
|
|
109
|
+
_set(target, prependKey, sourceVal)
|
|
110
|
+
return
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
const typeOfTargetVal = typeof targetVal
|
|
113
|
+
const typeOfTargetVal = typeof targetVal
|
|
114
114
|
|
|
115
|
-
if ([
|
|
116
|
-
if (defaultHandle ===
|
|
117
|
-
actionOnEmptyIntersect(target, source, prependKey)
|
|
115
|
+
if (['boolean'].includes(typeOfTargetVal)) {
|
|
116
|
+
if (defaultHandle === 'intersect') {
|
|
117
|
+
actionOnEmptyIntersect(target, source, prependKey)
|
|
118
118
|
}
|
|
119
|
-
_set(target, prependKey, sourceVal)
|
|
120
|
-
return
|
|
119
|
+
_set(target, prependKey, sourceVal)
|
|
120
|
+
return
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
const typeOfSourceVal = typeof sourceVal
|
|
123
|
+
const typeOfSourceVal = typeof sourceVal
|
|
124
124
|
|
|
125
|
-
const isTargetSimple = [
|
|
126
|
-
const isSourceSimple = [
|
|
125
|
+
const isTargetSimple = ['string', 'number'].includes(typeOfTargetVal)
|
|
126
|
+
const isSourceSimple = ['string', 'number'].includes(typeOfSourceVal)
|
|
127
127
|
|
|
128
128
|
if (isTargetSimple || isSourceSimple) {
|
|
129
129
|
if (isTargetSimple && isSourceSimple) {
|
|
130
|
-
if (defaultHandle ===
|
|
131
|
-
_set(target, prependKey, { $in: [...new Set([targetVal, sourceVal])] })
|
|
132
|
-
return
|
|
133
|
-
} else if (defaultHandle ===
|
|
134
|
-
actionOnEmptyIntersect(target, source, prependKey)
|
|
130
|
+
if (defaultHandle === 'combine') {
|
|
131
|
+
_set(target, prependKey, { $in: [...new Set([targetVal, sourceVal])] })
|
|
132
|
+
return
|
|
133
|
+
} else if (defaultHandle === 'intersect') {
|
|
134
|
+
actionOnEmptyIntersect(target, source, prependKey)
|
|
135
135
|
} else {
|
|
136
|
-
throw new Error(
|
|
136
|
+
throw new Error('should not reach here')
|
|
137
137
|
}
|
|
138
138
|
} else if (
|
|
139
|
-
hasOwnProperty(targetVal,
|
|
140
|
-
hasOwnProperty(sourceVal,
|
|
139
|
+
hasOwnProperty(targetVal, '$in') ||
|
|
140
|
+
hasOwnProperty(sourceVal, '$in')
|
|
141
141
|
) {
|
|
142
|
-
const targetHasIn = hasOwnProperty(targetVal,
|
|
142
|
+
const targetHasIn = hasOwnProperty(targetVal, '$in')
|
|
143
143
|
|
|
144
|
-
const $in = targetHasIn ? targetVal[
|
|
145
|
-
const otherVal = isTargetSimple ? targetVal : sourceVal
|
|
144
|
+
const $in = targetHasIn ? targetVal['$in'] : sourceVal['$in']
|
|
145
|
+
const otherVal = isTargetSimple ? targetVal : sourceVal
|
|
146
146
|
if ($in.length === 1 && _isEqual($in[0], otherVal)) {
|
|
147
|
-
_set(target, prependKey, otherVal)
|
|
148
|
-
return
|
|
149
|
-
} else if (defaultHandle ===
|
|
147
|
+
_set(target, prependKey, otherVal)
|
|
148
|
+
return
|
|
149
|
+
} else if (defaultHandle === 'combine') {
|
|
150
150
|
if (!$in.some((x: unknown) => _isEqual(x, otherVal))) {
|
|
151
|
-
$in.push(otherVal)
|
|
151
|
+
$in.push(otherVal)
|
|
152
152
|
}
|
|
153
|
-
_set(target, `${prependKey}.$in`, $in)
|
|
154
|
-
return
|
|
155
|
-
} else if (defaultHandle ===
|
|
153
|
+
_set(target, `${prependKey}.$in`, $in)
|
|
154
|
+
return
|
|
155
|
+
} else if (defaultHandle === 'intersect') {
|
|
156
156
|
if ($in.some((x: unknown) => _isEqual(x, otherVal))) {
|
|
157
|
-
_set(target, prependKey, otherVal)
|
|
157
|
+
_set(target, prependKey, otherVal)
|
|
158
158
|
} else {
|
|
159
|
-
actionOnEmptyIntersect(target, source, prependKey)
|
|
159
|
+
actionOnEmptyIntersect(target, source, prependKey)
|
|
160
160
|
}
|
|
161
|
-
return
|
|
161
|
+
return
|
|
162
162
|
}
|
|
163
|
-
return
|
|
163
|
+
return
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
const isTargetArray = Array.isArray(targetVal)
|
|
168
|
-
const isSourceArray = Array.isArray(sourceVal)
|
|
167
|
+
const isTargetArray = Array.isArray(targetVal)
|
|
168
|
+
const isSourceArray = Array.isArray(sourceVal)
|
|
169
169
|
|
|
170
170
|
if (isTargetArray && isSourceArray) {
|
|
171
|
-
const key = prependKey[prependKey.length - 1]
|
|
172
|
-
if (key ===
|
|
173
|
-
if (defaultHandle ===
|
|
171
|
+
const key = prependKey[prependKey.length - 1]
|
|
172
|
+
if (key === '$or') {
|
|
173
|
+
if (defaultHandle === 'combine') {
|
|
174
174
|
const newVals = sourceVal.filter(
|
|
175
175
|
(x: unknown) => !targetVal.some((y: unknown) => _isEqual(x, y)),
|
|
176
|
-
)
|
|
177
|
-
targetVal.push(...newVals)
|
|
178
|
-
} else if (defaultHandle ===
|
|
176
|
+
)
|
|
177
|
+
targetVal.push(...newVals)
|
|
178
|
+
} else if (defaultHandle === 'intersect') {
|
|
179
179
|
// combine into "$and"
|
|
180
|
-
const targetParent = getParentProp(target, prependKey)
|
|
181
|
-
const sourceParent = getParentProp(source, prependKey)
|
|
182
|
-
targetParent.$and = targetParent.$and || []
|
|
180
|
+
const targetParent = getParentProp(target, prependKey)
|
|
181
|
+
const sourceParent = getParentProp(source, prependKey)
|
|
182
|
+
targetParent.$and = targetParent.$and || []
|
|
183
183
|
|
|
184
|
-
targetParent.$and.push({ $or: targetVal }, { $or: sourceVal })
|
|
184
|
+
targetParent.$and.push({ $or: targetVal }, { $or: sourceVal })
|
|
185
185
|
|
|
186
|
-
targetParent.$and = cleanAnd(targetParent.$and)
|
|
186
|
+
targetParent.$and = cleanAnd(targetParent.$and)
|
|
187
187
|
if (!targetParent.$and) {
|
|
188
|
-
delete targetParent.$and
|
|
188
|
+
delete targetParent.$and
|
|
189
189
|
}
|
|
190
|
-
delete targetParent.$or
|
|
191
|
-
delete sourceParent.$or
|
|
192
|
-
handleCircular(target, source, [...prependKey,
|
|
193
|
-
return
|
|
190
|
+
delete targetParent.$or
|
|
191
|
+
delete sourceParent.$or
|
|
192
|
+
handleCircular(target, source, [...prependKey, '$and'], options)
|
|
193
|
+
return
|
|
194
194
|
}
|
|
195
|
-
return
|
|
196
|
-
} else if (key ===
|
|
197
|
-
if (defaultHandle ===
|
|
195
|
+
return
|
|
196
|
+
} else if (key === '$and') {
|
|
197
|
+
if (defaultHandle === 'combine') {
|
|
198
198
|
// combine into "$or"
|
|
199
|
-
const targetParent = getParentProp(target, prependKey)
|
|
200
|
-
const sourceParent = getParentProp(source, prependKey)
|
|
199
|
+
const targetParent = getParentProp(target, prependKey)
|
|
200
|
+
const sourceParent = getParentProp(source, prependKey)
|
|
201
201
|
|
|
202
|
-
targetParent.$or = targetParent.$or || []
|
|
203
|
-
targetParent.$or.push({ $and: targetVal }, { $and: sourceVal })
|
|
204
|
-
targetParent.$or = cleanOr(targetParent.$or)
|
|
202
|
+
targetParent.$or = targetParent.$or || []
|
|
203
|
+
targetParent.$or.push({ $and: targetVal }, { $and: sourceVal })
|
|
204
|
+
targetParent.$or = cleanOr(targetParent.$or)
|
|
205
205
|
if (!targetParent.$or) {
|
|
206
|
-
delete targetParent.$or
|
|
206
|
+
delete targetParent.$or
|
|
207
207
|
}
|
|
208
|
-
delete targetParent.$and
|
|
209
|
-
delete sourceParent.$and
|
|
210
|
-
handleCircular(target, source, [...prependKey,
|
|
211
|
-
return
|
|
212
|
-
} else if (defaultHandle ===
|
|
208
|
+
delete targetParent.$and
|
|
209
|
+
delete sourceParent.$and
|
|
210
|
+
handleCircular(target, source, [...prependKey, '$or'], options)
|
|
211
|
+
return
|
|
212
|
+
} else if (defaultHandle === 'intersect') {
|
|
213
213
|
const newVals = sourceVal.filter(
|
|
214
214
|
(x: unknown) => !targetVal.some((y: unknown) => _isEqual(x, y)),
|
|
215
|
-
)
|
|
216
|
-
targetVal.push(...newVals)
|
|
217
|
-
return
|
|
215
|
+
)
|
|
216
|
+
targetVal.push(...newVals)
|
|
217
|
+
return
|
|
218
218
|
}
|
|
219
|
-
} else if (key ===
|
|
220
|
-
if (defaultHandle ===
|
|
221
|
-
let $in: unknown[] = targetVal.concat(sourceVal)
|
|
222
|
-
$in = [...new Set($in)]
|
|
223
|
-
_set(target, prependKey, $in)
|
|
224
|
-
return
|
|
225
|
-
} else if (defaultHandle ===
|
|
219
|
+
} else if (key === '$in') {
|
|
220
|
+
if (defaultHandle === 'combine') {
|
|
221
|
+
let $in: unknown[] = targetVal.concat(sourceVal)
|
|
222
|
+
$in = [...new Set($in)]
|
|
223
|
+
_set(target, prependKey, $in)
|
|
224
|
+
return
|
|
225
|
+
} else if (defaultHandle === 'intersect') {
|
|
226
226
|
const $in = targetVal.filter((x: unknown) =>
|
|
227
227
|
sourceVal.some((y: unknown) => _isEqual(x, y)),
|
|
228
|
-
)
|
|
228
|
+
)
|
|
229
229
|
if ($in.length === 0) {
|
|
230
|
-
actionOnEmptyIntersect(target, source, prependKey)
|
|
230
|
+
actionOnEmptyIntersect(target, source, prependKey)
|
|
231
231
|
} else if ($in.length === 1) {
|
|
232
|
-
_set(target, prependKey.slice(0, -1), $in[0])
|
|
233
|
-
return
|
|
232
|
+
_set(target, prependKey.slice(0, -1), $in[0])
|
|
233
|
+
return
|
|
234
234
|
} else {
|
|
235
|
-
_set(target, prependKey, $in)
|
|
235
|
+
_set(target, prependKey, $in)
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
|
-
return
|
|
238
|
+
return
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
_set(target, prependKey, sourceVal)
|
|
242
|
-
return
|
|
241
|
+
_set(target, prependKey, sourceVal)
|
|
242
|
+
return
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
if (typeOfTargetVal !==
|
|
246
|
-
_set(target, prependKey, sourceVal)
|
|
247
|
-
return
|
|
245
|
+
if (typeOfTargetVal !== 'object' || typeOfSourceVal !== 'object') {
|
|
246
|
+
_set(target, prependKey, sourceVal)
|
|
247
|
+
return
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// both are objects
|
|
251
|
-
const sourceKeys = Object.keys(sourceVal)
|
|
251
|
+
const sourceKeys = Object.keys(sourceVal)
|
|
252
252
|
|
|
253
253
|
for (let i = 0, n = sourceKeys.length; i < n; i++) {
|
|
254
|
-
const key = sourceKeys[i]
|
|
255
|
-
handleCircular(target, source, [...prependKey, key], options)
|
|
254
|
+
const key = sourceKeys[i]
|
|
255
|
+
handleCircular(target, source, [...prependKey, key], options)
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
export function makeDefaultOptions(
|
|
260
260
|
options?: Partial<MergeQueryOptions>,
|
|
261
261
|
): MergeQueryOptions {
|
|
262
|
-
options ??= {} as MergeQueryOptions
|
|
263
|
-
options.defaultHandle ??=
|
|
264
|
-
options.useLogicalConjunction ??= false
|
|
262
|
+
options ??= {} as MergeQueryOptions
|
|
263
|
+
options.defaultHandle ??= 'combine'
|
|
264
|
+
options.useLogicalConjunction ??= false
|
|
265
265
|
options.actionOnEmptyIntersect ??= () => {
|
|
266
|
-
throw new Forbidden("You're not allowed to make this request")
|
|
267
|
-
}
|
|
268
|
-
options.handle = options.handle || {}
|
|
269
|
-
if (options.defaultHandle ===
|
|
270
|
-
options.handle.$select = options.handle.$select ||
|
|
266
|
+
throw new Forbidden("You're not allowed to make this request")
|
|
267
|
+
}
|
|
268
|
+
options.handle = options.handle || {}
|
|
269
|
+
if (options.defaultHandle === 'intersect') {
|
|
270
|
+
options.handle.$select = options.handle.$select || 'intersectOrFull'
|
|
271
271
|
}
|
|
272
|
-
return options as MergeQueryOptions
|
|
272
|
+
return options as MergeQueryOptions
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
export function moveProperty(
|
|
@@ -279,32 +279,32 @@ export function moveProperty(
|
|
|
279
279
|
): void {
|
|
280
280
|
keys.forEach((key) => {
|
|
281
281
|
if (!hasOwnProperty(from, key)) {
|
|
282
|
-
return
|
|
282
|
+
return
|
|
283
283
|
}
|
|
284
|
-
to[key] = from[key]
|
|
285
|
-
delete from[key]
|
|
286
|
-
})
|
|
284
|
+
to[key] = from[key]
|
|
285
|
+
delete from[key]
|
|
286
|
+
})
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
export function getParentProp(target: Record<string, unknown>, path: Path) {
|
|
290
290
|
if (path.length <= 1) {
|
|
291
|
-
return target
|
|
291
|
+
return target
|
|
292
292
|
}
|
|
293
|
-
const pathOneUp = path.slice(0, -1)
|
|
294
|
-
return _get(target, pathOneUp)
|
|
293
|
+
const pathOneUp = path.slice(0, -1)
|
|
294
|
+
return _get(target, pathOneUp)
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
export function cleanOr(
|
|
298
298
|
target: Record<string, unknown>[],
|
|
299
299
|
): Record<string, unknown>[] | undefined {
|
|
300
300
|
if (!target || !Array.isArray(target) || target.length <= 0) {
|
|
301
|
-
return target
|
|
301
|
+
return target
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
if (target.some((x) => isEmpty(x))) {
|
|
305
|
-
return undefined
|
|
305
|
+
return undefined
|
|
306
306
|
} else {
|
|
307
|
-
return arrayWithoutDuplicates(target)
|
|
307
|
+
return arrayWithoutDuplicates(target)
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
|
|
@@ -312,23 +312,23 @@ export function cleanAnd(
|
|
|
312
312
|
target: Record<string, unknown>[],
|
|
313
313
|
): Record<string, unknown>[] | undefined {
|
|
314
314
|
if (!target || !Array.isArray(target) || target.length <= 0) {
|
|
315
|
-
return target
|
|
315
|
+
return target
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
if (target.every((x) => isEmpty(x))) {
|
|
319
|
-
return undefined
|
|
319
|
+
return undefined
|
|
320
320
|
} else {
|
|
321
|
-
target = target.filter((x) => !isEmpty(x))
|
|
322
|
-
return arrayWithoutDuplicates(target)
|
|
321
|
+
target = target.filter((x) => !isEmpty(x))
|
|
322
|
+
return arrayWithoutDuplicates(target)
|
|
323
323
|
}
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
export function arrayWithoutDuplicates<T>(target: T[]): T[] {
|
|
327
327
|
if (!target || !Array.isArray(target)) {
|
|
328
|
-
return target
|
|
328
|
+
return target
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
-
return _uniqWith(target, _isEqual)
|
|
331
|
+
return _uniqWith(target, _isEqual)
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
/**
|
|
@@ -342,142 +342,142 @@ export function isQueryMoreExplicitThanQuery(
|
|
|
342
342
|
source: Query,
|
|
343
343
|
): Query | undefined {
|
|
344
344
|
if (!target || !source) {
|
|
345
|
-
return
|
|
345
|
+
return
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
const targetKeys = Object.keys(target)
|
|
349
|
-
const sourceKeys = Object.keys(source)
|
|
348
|
+
const targetKeys = Object.keys(target)
|
|
349
|
+
const sourceKeys = Object.keys(source)
|
|
350
350
|
|
|
351
351
|
// sourceQuery: {}; targetQuery: { something }
|
|
352
352
|
if (!sourceKeys.length) {
|
|
353
|
-
return target
|
|
353
|
+
return target
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
// sourceQuery: { something }; targetQuery: {}
|
|
357
357
|
if (!targetKeys.length) {
|
|
358
|
-
return source
|
|
358
|
+
return source
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
if (targetKeys.every((key) => _isEqual(target[key], source[key]))) {
|
|
362
362
|
// every property of target is exactly in source
|
|
363
|
-
return source
|
|
363
|
+
return source
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
if (sourceKeys.every((key) => _isEqual(target[key], source[key]))) {
|
|
367
367
|
// every property of source is exactly in target
|
|
368
|
-
return target
|
|
368
|
+
return target
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
-
return
|
|
371
|
+
return
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
export function areQueriesOverlapping(target: Query, source: Query): boolean {
|
|
375
375
|
if (!target || !source) {
|
|
376
|
-
return false
|
|
376
|
+
return false
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
const targetKeys = Object.keys(target)
|
|
380
|
-
const sourceKeys = Object.keys(source)
|
|
379
|
+
const targetKeys = Object.keys(target)
|
|
380
|
+
const sourceKeys = Object.keys(source)
|
|
381
381
|
|
|
382
382
|
if (!sourceKeys.length || !targetKeys.length) {
|
|
383
|
-
return false
|
|
383
|
+
return false
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
if (
|
|
387
387
|
targetKeys.some((x) => sourceKeys.includes(x)) ||
|
|
388
388
|
sourceKeys.some((x) => targetKeys.includes(x))
|
|
389
389
|
) {
|
|
390
|
-
return true
|
|
390
|
+
return true
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
return false
|
|
393
|
+
return false
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
if (import.meta.vitest) {
|
|
397
|
-
const { describe, it, expect } = import.meta.vitest
|
|
397
|
+
const { describe, it, expect } = import.meta.vitest
|
|
398
398
|
|
|
399
|
-
describe(
|
|
400
|
-
it(
|
|
401
|
-
const query = areQueriesOverlapping({}, {})
|
|
399
|
+
describe('areQueriesOverlapping', function () {
|
|
400
|
+
it('empty', function () {
|
|
401
|
+
const query = areQueriesOverlapping({}, {})
|
|
402
402
|
|
|
403
|
-
expect(query).toBe(false)
|
|
404
|
-
})
|
|
403
|
+
expect(query).toBe(false)
|
|
404
|
+
})
|
|
405
405
|
|
|
406
|
-
it(
|
|
407
|
-
const query = areQueriesOverlapping({ id: 1 }, { id: 1 })
|
|
406
|
+
it('share same properties', function () {
|
|
407
|
+
const query = areQueriesOverlapping({ id: 1 }, { id: 1 })
|
|
408
408
|
|
|
409
|
-
expect(query).toBe(true)
|
|
410
|
-
})
|
|
409
|
+
expect(query).toBe(true)
|
|
410
|
+
})
|
|
411
411
|
|
|
412
|
-
it(
|
|
413
|
-
const query = areQueriesOverlapping({ id: 1 }, { id: 2 })
|
|
412
|
+
it('share same properties with different values', function () {
|
|
413
|
+
const query = areQueriesOverlapping({ id: 1 }, { id: 2 })
|
|
414
414
|
|
|
415
|
-
expect(query).toBe(true)
|
|
416
|
-
})
|
|
415
|
+
expect(query).toBe(true)
|
|
416
|
+
})
|
|
417
417
|
|
|
418
|
-
it(
|
|
418
|
+
it('share some properties', function () {
|
|
419
419
|
const query = areQueriesOverlapping(
|
|
420
420
|
{ id: 1, test1: true, test2: true },
|
|
421
421
|
{ id: 2, test3: true, test4: true },
|
|
422
|
-
)
|
|
422
|
+
)
|
|
423
423
|
|
|
424
|
-
expect(query).toBe(true)
|
|
425
|
-
})
|
|
424
|
+
expect(query).toBe(true)
|
|
425
|
+
})
|
|
426
426
|
|
|
427
|
-
it(
|
|
428
|
-
const query = areQueriesOverlapping({ id: 1 }, { test: true })
|
|
427
|
+
it('do not share properties', function () {
|
|
428
|
+
const query = areQueriesOverlapping({ id: 1 }, { test: true })
|
|
429
429
|
|
|
430
|
-
expect(query).toBe(false)
|
|
431
|
-
})
|
|
432
|
-
})
|
|
430
|
+
expect(query).toBe(false)
|
|
431
|
+
})
|
|
432
|
+
})
|
|
433
433
|
|
|
434
|
-
describe(
|
|
435
|
-
it(
|
|
436
|
-
const query = isQueryMoreExplicitThanQuery({}, {})
|
|
434
|
+
describe('isQueryMoreExplicitThanQuery', function () {
|
|
435
|
+
it('empty', function () {
|
|
436
|
+
const query = isQueryMoreExplicitThanQuery({}, {})
|
|
437
437
|
|
|
438
|
-
expect(query).toStrictEqual({})
|
|
439
|
-
})
|
|
438
|
+
expect(query).toStrictEqual({})
|
|
439
|
+
})
|
|
440
440
|
|
|
441
|
-
it(
|
|
442
|
-
const query = isQueryMoreExplicitThanQuery({}, { id: 1 })
|
|
441
|
+
it('query1 is empty', function () {
|
|
442
|
+
const query = isQueryMoreExplicitThanQuery({}, { id: 1 })
|
|
443
443
|
|
|
444
|
-
expect(query).toStrictEqual({ id: 1 })
|
|
445
|
-
})
|
|
444
|
+
expect(query).toStrictEqual({ id: 1 })
|
|
445
|
+
})
|
|
446
446
|
|
|
447
|
-
it(
|
|
448
|
-
const query = isQueryMoreExplicitThanQuery({ id: 1 }, {})
|
|
447
|
+
it('query2 is empty', function () {
|
|
448
|
+
const query = isQueryMoreExplicitThanQuery({ id: 1 }, {})
|
|
449
449
|
|
|
450
|
-
expect(query).toStrictEqual({ id: 1 })
|
|
451
|
-
})
|
|
450
|
+
expect(query).toStrictEqual({ id: 1 })
|
|
451
|
+
})
|
|
452
452
|
|
|
453
|
-
it(
|
|
453
|
+
it('query1 is superset of query2', function () {
|
|
454
454
|
const query = isQueryMoreExplicitThanQuery(
|
|
455
455
|
{ id: 1, test: true },
|
|
456
456
|
{ id: 1 },
|
|
457
|
-
)
|
|
457
|
+
)
|
|
458
458
|
|
|
459
|
-
expect(query).toStrictEqual({ id: 1, test: true })
|
|
460
|
-
})
|
|
459
|
+
expect(query).toStrictEqual({ id: 1, test: true })
|
|
460
|
+
})
|
|
461
461
|
|
|
462
|
-
it(
|
|
462
|
+
it('query2 is superset of query1', function () {
|
|
463
463
|
const query = isQueryMoreExplicitThanQuery(
|
|
464
464
|
{ id: 1 },
|
|
465
465
|
{ id: 1, test: true },
|
|
466
|
-
)
|
|
466
|
+
)
|
|
467
467
|
|
|
468
|
-
expect(query).toStrictEqual({ id: 1, test: true })
|
|
469
|
-
})
|
|
468
|
+
expect(query).toStrictEqual({ id: 1, test: true })
|
|
469
|
+
})
|
|
470
470
|
|
|
471
|
-
it(
|
|
472
|
-
const query = isQueryMoreExplicitThanQuery({ id: 1 }, { test: true })
|
|
471
|
+
it('queries do not overlap', function () {
|
|
472
|
+
const query = isQueryMoreExplicitThanQuery({ id: 1 }, { test: true })
|
|
473
473
|
|
|
474
|
-
expect(query).toBeUndefined()
|
|
475
|
-
})
|
|
474
|
+
expect(query).toBeUndefined()
|
|
475
|
+
})
|
|
476
476
|
|
|
477
|
-
it(
|
|
478
|
-
const query = isQueryMoreExplicitThanQuery({ id: 1 }, { id: 2 })
|
|
477
|
+
it('queries overlap but differ', function () {
|
|
478
|
+
const query = isQueryMoreExplicitThanQuery({ id: 1 }, { id: 2 })
|
|
479
479
|
|
|
480
|
-
expect(query).toBeUndefined()
|
|
481
|
-
})
|
|
482
|
-
})
|
|
480
|
+
expect(query).toBeUndefined()
|
|
481
|
+
})
|
|
482
|
+
})
|
|
483
483
|
}
|