feathers-utils 2.0.0-2 → 2.0.0-4

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 (139) hide show
  1. package/dist/esm/filters/array.d.ts +1 -1
  2. package/dist/esm/filters/array.js +2 -2
  3. package/dist/esm/filters/object.d.ts +2 -0
  4. package/dist/esm/filters/object.js +8 -0
  5. package/dist/esm/hooks/checkMulti.d.ts +2 -2
  6. package/dist/esm/hooks/createRelated.d.ts +8 -2
  7. package/dist/esm/hooks/createRelated.js +2 -3
  8. package/dist/esm/hooks/onDelete.d.ts +8 -2
  9. package/dist/esm/hooks/onDelete.js +8 -7
  10. package/dist/esm/hooks/removeRelated.d.ts +7 -2
  11. package/dist/esm/hooks/removeRelated.js +8 -7
  12. package/dist/esm/hooks/runPerItem.d.ts +5 -2
  13. package/dist/esm/hooks/runPerItem.js +1 -1
  14. package/dist/esm/hooks/setData.d.ts +7 -2
  15. package/dist/esm/hooks/setData.js +3 -2
  16. package/dist/esm/index.d.ts +19 -34
  17. package/dist/esm/index.js +21 -33
  18. package/dist/esm/mixins/debounce-mixin/DebouncedStore.d.ts +5 -2
  19. package/dist/esm/mixins/debounce-mixin/DebouncedStore.js +2 -2
  20. package/dist/esm/mixins/debounce-mixin/debounceMixin.d.ts +3 -0
  21. package/dist/esm/mixins/debounce-mixin/debounceMixin.js +19 -0
  22. package/dist/esm/mixins/debounce-mixin/index.d.ts +3 -8
  23. package/dist/esm/mixins/debounce-mixin/index.js +3 -20
  24. package/dist/esm/mixins/debounce-mixin/types.d.ts +13 -0
  25. package/dist/esm/mixins/debounce-mixin/types.js +1 -0
  26. package/dist/esm/types.d.ts +1 -77
  27. package/dist/esm/types.js +0 -1
  28. package/dist/esm/typesInternal.d.ts +3 -0
  29. package/dist/esm/typesInternal.js +3 -0
  30. package/dist/esm/utils/filterQuery.d.ts +6 -1
  31. package/dist/esm/utils/filterQuery.js +5 -3
  32. package/dist/esm/utils/getItemsIsArray.d.ts +5 -2
  33. package/dist/esm/utils/getItemsIsArray.js +7 -12
  34. package/dist/esm/utils/getPaginate.d.ts +2 -6
  35. package/dist/esm/utils/getPaginate.js +1 -1
  36. package/dist/esm/utils/isMulti.d.ts +1 -1
  37. package/dist/esm/utils/isPaginated.d.ts +1 -1
  38. package/dist/esm/utils/markHookForSkip.d.ts +3 -2
  39. package/dist/esm/utils/markHookForSkip.js +6 -5
  40. package/dist/esm/utils/mergeQuery/index.d.ts +3 -3
  41. package/dist/esm/utils/mergeQuery/index.js +3 -338
  42. package/dist/esm/utils/mergeQuery/mergeArrays.d.ts +2 -1
  43. package/dist/esm/utils/mergeQuery/mergeArrays.js +2 -2
  44. package/dist/esm/utils/mergeQuery/mergeQuery.d.ts +3 -0
  45. package/dist/esm/utils/mergeQuery/mergeQuery.js +68 -0
  46. package/dist/esm/utils/mergeQuery/types.d.ts +13 -0
  47. package/dist/esm/utils/mergeQuery/types.js +1 -0
  48. package/dist/esm/utils/mergeQuery/utils.d.ts +11 -0
  49. package/dist/esm/utils/mergeQuery/utils.js +272 -0
  50. package/dist/esm/utils/pushSet.d.ts +4 -1
  51. package/dist/esm/utils/pushSet.js +1 -1
  52. package/dist/esm/utils/setResultEmpty.d.ts +1 -1
  53. package/dist/esm/utils/setResultEmpty.js +1 -1
  54. package/dist/esm/utils/shouldSkip.d.ts +1 -1
  55. package/dist/esm/utils/validateQueryProperty.js +1 -1
  56. package/dist/filters/array.d.ts +1 -1
  57. package/dist/filters/array.js +2 -2
  58. package/dist/filters/object.d.ts +2 -0
  59. package/dist/filters/object.js +15 -0
  60. package/dist/hooks/checkMulti.d.ts +2 -2
  61. package/dist/hooks/createRelated.d.ts +8 -2
  62. package/dist/hooks/createRelated.js +2 -3
  63. package/dist/hooks/onDelete.d.ts +8 -2
  64. package/dist/hooks/onDelete.js +8 -7
  65. package/dist/hooks/removeRelated.d.ts +7 -2
  66. package/dist/hooks/removeRelated.js +8 -7
  67. package/dist/hooks/runPerItem.d.ts +5 -2
  68. package/dist/hooks/runPerItem.js +1 -1
  69. package/dist/hooks/setData.d.ts +7 -2
  70. package/dist/hooks/setData.js +3 -2
  71. package/dist/index.d.ts +19 -34
  72. package/dist/index.js +23 -49
  73. package/dist/mixins/debounce-mixin/DebouncedStore.d.ts +5 -2
  74. package/dist/mixins/debounce-mixin/DebouncedStore.js +2 -2
  75. package/dist/mixins/debounce-mixin/debounceMixin.d.ts +3 -0
  76. package/dist/mixins/debounce-mixin/debounceMixin.js +23 -0
  77. package/dist/mixins/debounce-mixin/index.d.ts +3 -8
  78. package/dist/mixins/debounce-mixin/index.js +17 -22
  79. package/dist/mixins/debounce-mixin/types.d.ts +13 -0
  80. package/dist/mixins/debounce-mixin/types.js +2 -0
  81. package/dist/types.d.ts +1 -77
  82. package/dist/types.js +0 -1
  83. package/dist/typesInternal.d.ts +3 -0
  84. package/dist/typesInternal.js +4 -0
  85. package/dist/utils/filterQuery.d.ts +6 -1
  86. package/dist/utils/filterQuery.js +4 -2
  87. package/dist/utils/getItemsIsArray.d.ts +5 -2
  88. package/dist/utils/getItemsIsArray.js +7 -12
  89. package/dist/utils/getPaginate.d.ts +2 -6
  90. package/dist/utils/isMulti.d.ts +1 -1
  91. package/dist/utils/isPaginated.d.ts +1 -1
  92. package/dist/utils/markHookForSkip.d.ts +3 -2
  93. package/dist/utils/markHookForSkip.js +6 -5
  94. package/dist/utils/mergeQuery/index.d.ts +3 -3
  95. package/dist/utils/mergeQuery/index.js +16 -342
  96. package/dist/utils/mergeQuery/mergeArrays.d.ts +2 -1
  97. package/dist/utils/mergeQuery/mergeArrays.js +2 -2
  98. package/dist/utils/mergeQuery/mergeQuery.d.ts +3 -0
  99. package/dist/utils/mergeQuery/mergeQuery.js +75 -0
  100. package/dist/utils/mergeQuery/types.d.ts +13 -0
  101. package/dist/utils/mergeQuery/types.js +2 -0
  102. package/dist/utils/mergeQuery/utils.d.ts +11 -0
  103. package/dist/utils/mergeQuery/utils.js +287 -0
  104. package/dist/utils/pushSet.d.ts +4 -1
  105. package/dist/utils/pushSet.js +1 -1
  106. package/dist/utils/setResultEmpty.d.ts +1 -1
  107. package/dist/utils/setResultEmpty.js +1 -1
  108. package/dist/utils/shouldSkip.d.ts +1 -1
  109. package/package.json +5 -2
  110. package/src/filters/array.ts +13 -9
  111. package/src/filters/object.ts +15 -0
  112. package/src/hooks/checkMulti.ts +8 -6
  113. package/src/hooks/createRelated.ts +21 -12
  114. package/src/hooks/onDelete.ts +28 -13
  115. package/src/hooks/removeRelated.ts +28 -16
  116. package/src/hooks/runPerItem.ts +19 -10
  117. package/src/hooks/setData.ts +24 -15
  118. package/src/index.ts +21 -38
  119. package/src/mixins/debounce-mixin/DebouncedStore.ts +29 -24
  120. package/src/mixins/debounce-mixin/debounceMixin.ts +33 -0
  121. package/src/mixins/debounce-mixin/index.ts +3 -39
  122. package/src/mixins/debounce-mixin/types.ts +16 -0
  123. package/src/types.ts +6 -117
  124. package/src/typesInternal.ts +6 -0
  125. package/src/utils/filterQuery.ts +22 -10
  126. package/src/utils/getItemsIsArray.ts +15 -16
  127. package/src/utils/getPaginate.ts +11 -14
  128. package/src/utils/isMulti.ts +3 -3
  129. package/src/utils/isPaginated.ts +6 -4
  130. package/src/utils/markHookForSkip.ts +18 -16
  131. package/src/utils/mergeQuery/index.ts +3 -379
  132. package/src/utils/mergeQuery/mergeArrays.ts +25 -18
  133. package/src/utils/mergeQuery/mergeQuery.ts +102 -0
  134. package/src/utils/mergeQuery/types.ts +25 -0
  135. package/src/utils/mergeQuery/utils.ts +342 -0
  136. package/src/utils/pushSet.ts +14 -7
  137. package/src/utils/setResultEmpty.ts +8 -6
  138. package/src/utils/shouldSkip.ts +4 -4
  139. package/src/utils/validateQueryProperty.ts +8 -4
@@ -1,7 +1,3 @@
1
+ import type { PaginationOptions } from "@feathersjs/adapter-commons";
1
2
  import type { HookContext } from "@feathersjs/feathers";
2
- interface PaginationOptions {
3
- default: number;
4
- max: number;
5
- }
6
- export declare const getPaginate: (context: HookContext) => PaginationOptions | undefined;
7
- export {};
3
+ export declare const getPaginate: <H extends HookContext<import("@feathersjs/feathers").Application<any, any>, any> = HookContext<import("@feathersjs/feathers").Application<any, any>, any>>(context: H) => PaginationOptions | undefined;
@@ -8,7 +8,7 @@ export const getPaginate = (context) => {
8
8
  let options = context.service.options || {};
9
9
  options = {
10
10
  ...options,
11
- ...context.params.adapter
11
+ ...context.params.adapter,
12
12
  };
13
13
  return options.paginate || undefined;
14
14
  };
@@ -1,2 +1,2 @@
1
1
  import type { HookContext } from "@feathersjs/feathers";
2
- export declare const isMulti: (context: HookContext) => boolean;
2
+ export declare const isMulti: <H extends HookContext<import("@feathersjs/feathers").Application<any, any>, any> = HookContext<import("@feathersjs/feathers").Application<any, any>, any>>(context: H) => boolean;
@@ -1,2 +1,2 @@
1
1
  import type { HookContext } from "@feathersjs/feathers";
2
- export declare const isPaginated: (context: HookContext) => boolean;
2
+ export declare const isPaginated: <H extends HookContext<import("@feathersjs/feathers").Application<any, any>, any> = HookContext<import("@feathersjs/feathers").Application<any, any>, any>>(context: H) => boolean;
@@ -1,3 +1,4 @@
1
1
  import type { HookContext } from "@feathersjs/feathers";
2
- import type { HookType, MaybeArray } from "../types";
3
- export declare function markHookForSkip<T>(hookName: string, type: "all" | MaybeArray<HookType>, context?: Partial<HookContext<T>>): Partial<HookContext<T>>;
2
+ import type { HookType } from "feathers-hooks-common";
3
+ import type { MaybeArray } from "../typesInternal";
4
+ export declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H | undefined;
@@ -1,14 +1,15 @@
1
1
  import { pushSet } from "./pushSet";
2
2
  export function markHookForSkip(hookName, type, context) {
3
+ // @ts-expect-error context is not of type 'H'
3
4
  context = context || {};
5
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
4
6
  const params = context.params || {};
5
- const types = (Array.isArray(type)) ? type : [type];
6
- types.forEach(t => {
7
- const combinedName = (t === "all")
8
- ? hookName
9
- : `${type}:${hookName}`;
7
+ const types = Array.isArray(type) ? type : [type];
8
+ types.forEach((t) => {
9
+ const combinedName = t === "all" ? hookName : `${type}:${hookName}`;
10
10
  pushSet(params, ["skipHooks"], combinedName, { unique: true });
11
11
  });
12
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
12
13
  context.params = params;
13
14
  return context;
14
15
  }
@@ -1,3 +1,3 @@
1
- import type { Query } from "@feathersjs/feathers";
2
- import type { MergeQueryOptions } from "../../types";
3
- export declare function mergeQuery<T>(target: Query, source: Query, options?: Partial<MergeQueryOptions<T>>): Query;
1
+ export * from "./mergeArrays";
2
+ export * from "./mergeQuery";
3
+ export * from "./types";
@@ -1,338 +1,3 @@
1
- import _get from "lodash/get.js";
2
- import _has from "lodash/has.js";
3
- import _isEmpty from "lodash/isEmpty.js";
4
- import _isEqual from "lodash/isEqual.js";
5
- import _merge from "lodash/merge.js";
6
- import _set from "lodash/set.js";
7
- import _uniqWith from "lodash/uniqWith.js";
8
- import { mergeArrays } from "./mergeArrays";
9
- import { filterQuery } from "../filterQuery";
10
- import { Forbidden } from "@feathersjs/errors";
11
- const hasOwnProperty = (obj, key) => {
12
- return Object.prototype.hasOwnProperty.call(obj, key);
13
- };
14
- function handleArray(target, source, key, options) {
15
- const targetVal = _get(target, key);
16
- const sourceVal = _get(source, key);
17
- if (!sourceVal && !targetVal) {
18
- return;
19
- }
20
- const handle = _get(options, ["handle", ...key], options.defaultHandle);
21
- const arr = mergeArrays(targetVal, sourceVal, handle, key, options.actionOnEmptyIntersect);
22
- _set(target, key, arr);
23
- }
24
- function handleCircular(target, source, prependKey, options) {
25
- if (target?.$or) {
26
- target.$or = cleanOr(target.$or);
27
- if (!target.$or) {
28
- delete target.$or;
29
- }
30
- }
31
- if (source?.$or) {
32
- source.$or = cleanOr(source.$or);
33
- if (!source.$or) {
34
- delete source.$or;
35
- }
36
- }
37
- if (target?.$and) {
38
- target.$and = cleanAnd(target.$and);
39
- if (!target.$and) {
40
- delete target.$and;
41
- }
42
- }
43
- if (source?.$and) {
44
- source.$and = cleanAnd(source.$and);
45
- if (!source.$and) {
46
- delete source.$and;
47
- }
48
- }
49
- if (!_has(source, prependKey)) {
50
- return;
51
- }
52
- if (!_has(target, prependKey)) {
53
- _set(target, prependKey, _get(source, prependKey));
54
- return;
55
- }
56
- const { defaultHandle, actionOnEmptyIntersect } = options;
57
- if (defaultHandle === "target") {
58
- return;
59
- }
60
- const getTargetVal = () => {
61
- return (prependKey.length > 0) ? _get(target, prependKey) : target;
62
- };
63
- const getSourceVal = () => {
64
- return (prependKey.length > 0) ? _get(source, prependKey) : source;
65
- };
66
- const targetVal = getTargetVal();
67
- const sourceVal = getSourceVal();
68
- if (_isEqual(targetVal, sourceVal)) {
69
- return;
70
- }
71
- if (defaultHandle === "source") {
72
- _set(target, prependKey, sourceVal);
73
- return;
74
- }
75
- if (targetVal === null || sourceVal === null) {
76
- _set(target, prependKey, sourceVal);
77
- return;
78
- }
79
- const typeOfTargetVal = typeof targetVal;
80
- if (["boolean"].includes(typeOfTargetVal)) {
81
- if (defaultHandle === "intersect") {
82
- actionOnEmptyIntersect(target, source, prependKey);
83
- }
84
- _set(target, prependKey, sourceVal);
85
- return;
86
- }
87
- const typeOfSourceVal = typeof sourceVal;
88
- const isTargetSimple = ["string", "number"].includes(typeOfTargetVal);
89
- const isSourceSimple = ["string", "number"].includes(typeOfSourceVal);
90
- if (isTargetSimple || isSourceSimple) {
91
- if (isTargetSimple && isSourceSimple) {
92
- if (defaultHandle === "combine") {
93
- _set(target, prependKey, { $in: [...new Set([targetVal, sourceVal])] });
94
- return;
95
- }
96
- else if (defaultHandle === "intersect") {
97
- actionOnEmptyIntersect(target, source, prependKey);
98
- }
99
- else {
100
- throw new Error("should not reach here");
101
- }
102
- }
103
- else if (hasOwnProperty(targetVal, "$in") || hasOwnProperty(sourceVal, "$in")) {
104
- const targetHasIn = hasOwnProperty(targetVal, "$in");
105
- const $in = (targetHasIn) ? targetVal["$in"] : sourceVal["$in"];
106
- const otherVal = (isTargetSimple) ? targetVal : sourceVal;
107
- if ($in.length === 1 && _isEqual($in[0], otherVal)) {
108
- _set(target, prependKey, otherVal);
109
- return;
110
- }
111
- else if (defaultHandle === "combine") {
112
- if (!$in.some((x) => _isEqual(x, otherVal))) {
113
- $in.push(otherVal);
114
- }
115
- _set(target, `${prependKey}.$in`, $in);
116
- return;
117
- }
118
- else if (defaultHandle === "intersect") {
119
- if ($in.some((x) => _isEqual(x, otherVal))) {
120
- _set(target, prependKey, otherVal);
121
- }
122
- else {
123
- actionOnEmptyIntersect(target, source, prependKey);
124
- }
125
- return;
126
- }
127
- return;
128
- }
129
- }
130
- const isTargetArray = Array.isArray(targetVal);
131
- const isSourceArray = Array.isArray(sourceVal);
132
- if (isTargetArray && isSourceArray) {
133
- const key = prependKey[prependKey.length - 1];
134
- if (key === "$or") {
135
- if (defaultHandle === "combine") {
136
- const newVals = sourceVal.filter((x) => !targetVal.some((y) => _isEqual(x, y)));
137
- targetVal.push(...newVals);
138
- }
139
- else if (defaultHandle === "intersect") {
140
- // combine into "$and"
141
- const targetParent = getParentProp(target, prependKey);
142
- const sourceParent = getParentProp(source, prependKey);
143
- targetParent.$and = targetParent.$and || [];
144
- targetParent.$and.push({ $or: targetVal }, { $or: sourceVal });
145
- targetParent.$and = cleanAnd(targetParent.$and);
146
- if (!targetParent.$and) {
147
- delete targetParent.$and;
148
- }
149
- delete targetParent.$or;
150
- delete sourceParent.$or;
151
- handleCircular(target, source, [...prependKey, "$and"], options);
152
- return;
153
- }
154
- return;
155
- }
156
- else if (key === "$and") {
157
- if (defaultHandle === "combine") {
158
- // combine into "$or"
159
- const targetParent = getParentProp(target, prependKey);
160
- const sourceParent = getParentProp(source, prependKey);
161
- targetParent.$or = targetParent.$or || [];
162
- targetParent.$or.push({ $and: targetVal }, { $and: sourceVal });
163
- targetParent.$or = cleanOr(targetParent.$or);
164
- if (!targetParent.$or) {
165
- delete targetParent.$or;
166
- }
167
- delete targetParent.$and;
168
- delete sourceParent.$and;
169
- handleCircular(target, source, [...prependKey, "$or"], options);
170
- return;
171
- }
172
- else if (defaultHandle === "intersect") {
173
- const newVals = sourceVal.filter((x) => !targetVal.some((y) => _isEqual(x, y)));
174
- targetVal.push(...newVals);
175
- return;
176
- }
177
- }
178
- else if (key === "$in") {
179
- if (defaultHandle === "combine") {
180
- let $in = targetVal.concat(sourceVal);
181
- $in = [...new Set($in)];
182
- _set(target, prependKey, $in);
183
- return;
184
- }
185
- else if (defaultHandle === "intersect") {
186
- const $in = targetVal.filter((x) => sourceVal.some((y) => _isEqual(x, y)));
187
- if ($in.length === 0) {
188
- actionOnEmptyIntersect(target, source, prependKey);
189
- }
190
- else if ($in.length === 1) {
191
- _set(target, prependKey.slice(0, -1), $in[0]);
192
- return;
193
- }
194
- else {
195
- _set(target, prependKey, $in);
196
- }
197
- }
198
- return;
199
- }
200
- _set(target, prependKey, sourceVal);
201
- return;
202
- }
203
- if (typeOfTargetVal !== "object" || typeOfSourceVal !== "object") {
204
- _set(target, prependKey, sourceVal);
205
- return;
206
- }
207
- // both are objects
208
- const sourceKeys = Object.keys(sourceVal);
209
- for (let i = 0, n = sourceKeys.length; i < n; i++) {
210
- const key = sourceKeys[i];
211
- handleCircular(target, source, [...prependKey, key], options);
212
- }
213
- }
214
- function makeDefaultOptions(options) {
215
- options = options || {};
216
- options.defaultHandle = options.defaultHandle || "combine";
217
- options.useLogicalConjunction =
218
- (Object.prototype.hasOwnProperty.call(options, "useLogicalConjunction"))
219
- ? options.useLogicalConjunction
220
- : false;
221
- options.actionOnEmptyIntersect = options.actionOnEmptyIntersect || (() => {
222
- throw new Forbidden("You're not allowed to make this request");
223
- });
224
- options.handle = options.handle || {};
225
- if (options.defaultHandle === "intersect") {
226
- options.handle.$select = options.handle.$select || "intersectOrFull";
227
- }
228
- return options;
229
- }
230
- function moveProperty(source, target, key) {
231
- if (!Object.prototype.hasOwnProperty.call(source, key)) {
232
- return;
233
- }
234
- target[key] = source[key];
235
- delete source[key];
236
- }
237
- export function mergeQuery(target, source, options) {
238
- const fullOptions = makeDefaultOptions(options);
239
- const { filters: targetFilters, query: targetQuery } = filterQuery(target, {
240
- operators: fullOptions.operators,
241
- service: fullOptions.service
242
- });
243
- moveProperty(targetFilters, targetQuery, "$or");
244
- moveProperty(targetFilters, targetQuery, "$and");
245
- if (target.$limit) {
246
- targetFilters.$limit = target.$limit;
247
- }
248
- let {
249
- // eslint-disable-next-line prefer-const
250
- filters: sourceFilters, query: sourceQuery } = filterQuery(source, {
251
- operators: fullOptions.operators,
252
- service: fullOptions.service
253
- });
254
- moveProperty(sourceFilters, sourceQuery, "$or");
255
- moveProperty(sourceFilters, sourceQuery, "$and");
256
- if (source.$limit) {
257
- sourceFilters.$limit = source.$limit;
258
- }
259
- //#region filters
260
- if (target &&
261
- !Object.prototype.hasOwnProperty.call(target, "$limit") &&
262
- Object.prototype.hasOwnProperty.call(targetFilters, "$limit")) {
263
- delete targetFilters.$limit;
264
- }
265
- if (source &&
266
- !Object.prototype.hasOwnProperty.call(source, "$limit") &&
267
- Object.prototype.hasOwnProperty.call(sourceFilters, "$limit")) {
268
- delete sourceFilters.$limit;
269
- }
270
- handleArray(targetFilters, sourceFilters, ["$select"], fullOptions);
271
- // remaining filters
272
- delete sourceFilters["$select"];
273
- _merge(targetFilters, sourceFilters);
274
- //#endregion
275
- //#region '$or' / '$and'
276
- if (options?.useLogicalConjunction &&
277
- (options.defaultHandle === "combine" ||
278
- options.defaultHandle === "intersect") &&
279
- !_isEmpty(targetQuery)) {
280
- const logicalOp = (options.defaultHandle === "combine")
281
- ? "$or"
282
- : "$and";
283
- if (Object.prototype.hasOwnProperty.call(sourceQuery, logicalOp)) {
284
- // omit '$or'/'$and' and put all other props into '$or'/'$and'
285
- const andOr = sourceQuery[logicalOp];
286
- delete sourceQuery[logicalOp];
287
- andOr.push(sourceQuery);
288
- sourceQuery = { [logicalOp]: andOr };
289
- }
290
- else {
291
- sourceQuery = { [logicalOp]: [sourceQuery] };
292
- }
293
- }
294
- //#endregion
295
- const keys = Object.keys(sourceQuery);
296
- for (let i = 0, n = keys.length; i < n; i++) {
297
- const key = keys[i];
298
- handleCircular(targetQuery, sourceQuery, [key], fullOptions);
299
- }
300
- const result = Object.assign({}, targetFilters, targetQuery);
301
- return result;
302
- }
303
- function getParentProp(target, path) {
304
- if (path.length <= 1) {
305
- return target;
306
- }
307
- const pathOneUp = path.slice(0, -1);
308
- return _get(target, pathOneUp);
309
- }
310
- function cleanOr(target) {
311
- if (!target || !Array.isArray(target) || target.length <= 0) {
312
- return target;
313
- }
314
- if (target.some(x => _isEmpty(x))) {
315
- return undefined;
316
- }
317
- else {
318
- return arrayWithoutDuplicates(target);
319
- }
320
- }
321
- function cleanAnd(target) {
322
- if (!target || !Array.isArray(target) || target.length <= 0) {
323
- return target;
324
- }
325
- if (target.every(x => _isEmpty(x))) {
326
- return undefined;
327
- }
328
- else {
329
- target = target.filter(x => !_isEmpty(x));
330
- return arrayWithoutDuplicates(target);
331
- }
332
- }
333
- function arrayWithoutDuplicates(target) {
334
- if (!target || !Array.isArray(target)) {
335
- return target;
336
- }
337
- return _uniqWith(target, _isEqual);
338
- }
1
+ export * from "./mergeArrays";
2
+ export * from "./mergeQuery";
3
+ export * from "./types";
@@ -1,2 +1,3 @@
1
- import type { Handle, ActionOnEmptyIntersect, Path } from "../../types";
1
+ import type { Path } from "../../typesInternal";
2
+ import type { Handle, ActionOnEmptyIntersect } from "./types";
2
3
  export declare function mergeArrays<T>(targetArr: T[], sourceArr: T[], handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
@@ -28,10 +28,10 @@ export function mergeArrays(targetArr, sourceArr, handle, prependKey, actionOnEm
28
28
  return;
29
29
  }
30
30
  if (handle === "intersectOrFull") {
31
- const val = (!targetIsArray) ? targetArr : sourceArr;
31
+ const val = !targetIsArray ? targetArr : sourceArr;
32
32
  return val;
33
33
  }
34
- return targetArr.filter(val => sourceArr.includes(val));
34
+ return targetArr.filter((val) => sourceArr.includes(val));
35
35
  }
36
36
  return undefined;
37
37
  }
@@ -0,0 +1,3 @@
1
+ import type { Query } from "@feathersjs/feathers";
2
+ import type { MergeQueryOptions } from "./types";
3
+ export declare function mergeQuery<T>(target: Query, source: Query, options?: Partial<MergeQueryOptions<T>>): Query;
@@ -0,0 +1,68 @@
1
+ import _merge from "lodash/merge.js";
2
+ import _isEmpty from "lodash/isEmpty.js";
3
+ import { handleArray, handleCircular, makeDefaultOptions, moveProperty, } from "./utils";
4
+ import { filterQuery } from "../filterQuery";
5
+ export function mergeQuery(target, source, options) {
6
+ const fullOptions = makeDefaultOptions(options);
7
+ const { filters: targetFilters, query: targetQuery } = filterQuery(target, {
8
+ operators: fullOptions.operators,
9
+ service: fullOptions.service,
10
+ });
11
+ moveProperty(targetFilters, targetQuery, "$or");
12
+ moveProperty(targetFilters, targetQuery, "$and");
13
+ if (target.$limit) {
14
+ targetFilters.$limit = target.$limit;
15
+ }
16
+ let {
17
+ // eslint-disable-next-line prefer-const
18
+ filters: sourceFilters, query: sourceQuery, } = filterQuery(source, {
19
+ operators: fullOptions.operators,
20
+ service: fullOptions.service,
21
+ });
22
+ moveProperty(sourceFilters, sourceQuery, "$or");
23
+ moveProperty(sourceFilters, sourceQuery, "$and");
24
+ if (source.$limit) {
25
+ sourceFilters.$limit = source.$limit;
26
+ }
27
+ //#region filters
28
+ if (target &&
29
+ !Object.prototype.hasOwnProperty.call(target, "$limit") &&
30
+ Object.prototype.hasOwnProperty.call(targetFilters, "$limit")) {
31
+ delete targetFilters.$limit;
32
+ }
33
+ if (source &&
34
+ !Object.prototype.hasOwnProperty.call(source, "$limit") &&
35
+ Object.prototype.hasOwnProperty.call(sourceFilters, "$limit")) {
36
+ delete sourceFilters.$limit;
37
+ }
38
+ handleArray(targetFilters, sourceFilters, ["$select"], fullOptions);
39
+ // remaining filters
40
+ delete sourceFilters["$select"];
41
+ _merge(targetFilters, sourceFilters);
42
+ //#endregion
43
+ //#region '$or' / '$and'
44
+ if (options?.useLogicalConjunction &&
45
+ (options.defaultHandle === "combine" ||
46
+ options.defaultHandle === "intersect") &&
47
+ !_isEmpty(targetQuery)) {
48
+ const logicalOp = options.defaultHandle === "combine" ? "$or" : "$and";
49
+ if (Object.prototype.hasOwnProperty.call(sourceQuery, logicalOp)) {
50
+ // omit '$or'/'$and' and put all other props into '$or'/'$and'
51
+ const andOr = sourceQuery[logicalOp];
52
+ delete sourceQuery[logicalOp];
53
+ andOr.push(sourceQuery);
54
+ sourceQuery = { [logicalOp]: andOr };
55
+ }
56
+ else {
57
+ sourceQuery = { [logicalOp]: [sourceQuery] };
58
+ }
59
+ }
60
+ //#endregion
61
+ const keys = Object.keys(sourceQuery);
62
+ for (let i = 0, n = keys.length; i < n; i++) {
63
+ const key = keys[i];
64
+ handleCircular(targetQuery, sourceQuery, [key], fullOptions);
65
+ }
66
+ const result = Object.assign({}, targetFilters, targetQuery);
67
+ return result;
68
+ }
@@ -0,0 +1,13 @@
1
+ import type { Path } from "../../typesInternal";
2
+ import type { FilterQueryOptions } from "../filterQuery";
3
+ export declare type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
4
+ export declare type FirstLast = "first" | "last";
5
+ export declare type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
6
+ export interface MergeQueryOptions<T> extends FilterQueryOptions<T> {
7
+ defaultHandle: Handle;
8
+ actionOnEmptyIntersect: ActionOnEmptyIntersect;
9
+ useLogicalConjunction: boolean;
10
+ handle?: {
11
+ [key: string]: Handle;
12
+ };
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { Path } from "../../typesInternal";
2
+ import type { MergeQueryOptions } from "./types";
3
+ export declare const hasOwnProperty: (obj: Record<string, unknown>, key: string) => boolean;
4
+ export declare function handleArray<T>(target: Record<string, unknown>, source: Record<string, unknown>, key: Path, options: MergeQueryOptions<T>): void;
5
+ export declare function handleCircular<T>(target: Record<string, unknown>, source: Record<string, unknown>, prependKey: Path, options: MergeQueryOptions<T>): void;
6
+ export declare function makeDefaultOptions<T>(options?: Partial<MergeQueryOptions<T>>): MergeQueryOptions<T>;
7
+ export declare function moveProperty(source: Record<string, any>, target: Record<string, any>, key: string): void;
8
+ export declare function getParentProp(target: Record<string, unknown>, path: Path): any;
9
+ export declare function cleanOr(target: Record<string, unknown>[]): Record<string, unknown>[] | undefined;
10
+ export declare function cleanAnd(target: Record<string, unknown>[]): Record<string, unknown>[] | undefined;
11
+ export declare function arrayWithoutDuplicates<T>(target: T[]): T[];