feathers-utils 2.0.0-9 → 2.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 (156) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -1
  3. package/dist/index.cjs +964 -0
  4. package/dist/index.d.ts +262 -5
  5. package/dist/index.mjs +938 -0
  6. package/package.json +35 -38
  7. package/src/filters/object.ts +1 -1
  8. package/src/hooks/forEach.ts +47 -0
  9. package/src/hooks/index.ts +3 -0
  10. package/src/hooks/makeSequelizeQuery.ts_ +4 -4
  11. package/src/hooks/parseFields.ts +27 -0
  12. package/src/hooks/runPerItem.ts +4 -6
  13. package/src/hooks/setData.ts +4 -5
  14. package/src/index.ts +1 -0
  15. package/src/typesInternal.ts +7 -0
  16. package/src/utility-types/index.ts +116 -0
  17. package/src/utils/getItemsIsArray.ts +27 -11
  18. package/src/utils/getPaginate.ts +2 -1
  19. package/src/utils/internal.utils.ts +6 -0
  20. package/src/utils/mergeQuery/mergeQuery.ts +62 -25
  21. package/src/utils/mergeQuery/utils.ts +82 -29
  22. package/dist/esm/filters/array.d.ts +0 -2
  23. package/dist/esm/filters/array.js +0 -17
  24. package/dist/esm/filters/index.d.ts +0 -2
  25. package/dist/esm/filters/index.js +0 -2
  26. package/dist/esm/filters/object.d.ts +0 -2
  27. package/dist/esm/filters/object.js +0 -15
  28. package/dist/esm/hooks/checkMulti.d.ts +0 -5
  29. package/dist/esm/hooks/checkMulti.js +0 -20
  30. package/dist/esm/hooks/createRelated.d.ts +0 -12
  31. package/dist/esm/hooks/createRelated.js +0 -31
  32. package/dist/esm/hooks/index.d.ts +0 -6
  33. package/dist/esm/hooks/index.js +0 -6
  34. package/dist/esm/hooks/onDelete.d.ts +0 -12
  35. package/dist/esm/hooks/onDelete.js +0 -47
  36. package/dist/esm/hooks/removeRelated.d.ts +0 -11
  37. package/dist/esm/hooks/removeRelated.js +0 -37
  38. package/dist/esm/hooks/runPerItem.d.ts +0 -10
  39. package/dist/esm/hooks/runPerItem.js +0 -29
  40. package/dist/esm/hooks/setData.d.ts +0 -11
  41. package/dist/esm/hooks/setData.js +0 -46
  42. package/dist/esm/index.d.ts +0 -5
  43. package/dist/esm/index.js +0 -5
  44. package/dist/esm/mixins/debounce-mixin/DebouncedStore.d.ts +0 -18
  45. package/dist/esm/mixins/debounce-mixin/DebouncedStore.js +0 -46
  46. package/dist/esm/mixins/debounce-mixin/debounceMixin.d.ts +0 -3
  47. package/dist/esm/mixins/debounce-mixin/debounceMixin.js +0 -19
  48. package/dist/esm/mixins/debounce-mixin/index.d.ts +0 -3
  49. package/dist/esm/mixins/debounce-mixin/index.js +0 -3
  50. package/dist/esm/mixins/debounce-mixin/types.d.ts +0 -13
  51. package/dist/esm/mixins/debounce-mixin/types.js +0 -1
  52. package/dist/esm/mixins/index.d.ts +0 -1
  53. package/dist/esm/mixins/index.js +0 -1
  54. package/dist/esm/types.d.ts +0 -3
  55. package/dist/esm/types.js +0 -1
  56. package/dist/esm/typesInternal.d.ts +0 -3
  57. package/dist/esm/typesInternal.js +0 -3
  58. package/dist/esm/utils/filterQuery.d.ts +0 -8
  59. package/dist/esm/utils/filterQuery.js +0 -30
  60. package/dist/esm/utils/getItemsIsArray.d.ts +0 -10
  61. package/dist/esm/utils/getItemsIsArray.js +0 -16
  62. package/dist/esm/utils/getPaginate.d.ts +0 -9
  63. package/dist/esm/utils/getPaginate.js +0 -20
  64. package/dist/esm/utils/index.d.ts +0 -11
  65. package/dist/esm/utils/index.js +0 -11
  66. package/dist/esm/utils/isMulti.d.ts +0 -11
  67. package/dist/esm/utils/isMulti.js +0 -26
  68. package/dist/esm/utils/isPaginated.d.ts +0 -5
  69. package/dist/esm/utils/isPaginated.js +0 -11
  70. package/dist/esm/utils/markHookForSkip.d.ts +0 -7
  71. package/dist/esm/utils/markHookForSkip.js +0 -18
  72. package/dist/esm/utils/mergeQuery/index.d.ts +0 -3
  73. package/dist/esm/utils/mergeQuery/index.js +0 -3
  74. package/dist/esm/utils/mergeQuery/mergeArrays.d.ts +0 -3
  75. package/dist/esm/utils/mergeQuery/mergeArrays.js +0 -37
  76. package/dist/esm/utils/mergeQuery/mergeQuery.d.ts +0 -3
  77. package/dist/esm/utils/mergeQuery/mergeQuery.js +0 -70
  78. package/dist/esm/utils/mergeQuery/types.d.ts +0 -13
  79. package/dist/esm/utils/mergeQuery/types.js +0 -1
  80. package/dist/esm/utils/mergeQuery/utils.d.ts +0 -11
  81. package/dist/esm/utils/mergeQuery/utils.js +0 -272
  82. package/dist/esm/utils/pushSet.d.ts +0 -8
  83. package/dist/esm/utils/pushSet.js +0 -22
  84. package/dist/esm/utils/setResultEmpty.d.ts +0 -5
  85. package/dist/esm/utils/setResultEmpty.js +0 -28
  86. package/dist/esm/utils/shouldSkip.d.ts +0 -8
  87. package/dist/esm/utils/shouldSkip.js +0 -29
  88. package/dist/esm/utils/validateQueryProperty.d.ts +0 -5
  89. package/dist/esm/utils/validateQueryProperty.js +0 -23
  90. package/dist/filters/array.d.ts +0 -2
  91. package/dist/filters/array.js +0 -21
  92. package/dist/filters/index.d.ts +0 -2
  93. package/dist/filters/index.js +0 -18
  94. package/dist/filters/object.d.ts +0 -2
  95. package/dist/filters/object.js +0 -22
  96. package/dist/hooks/checkMulti.d.ts +0 -5
  97. package/dist/hooks/checkMulti.js +0 -24
  98. package/dist/hooks/createRelated.d.ts +0 -12
  99. package/dist/hooks/createRelated.js +0 -44
  100. package/dist/hooks/index.d.ts +0 -6
  101. package/dist/hooks/index.js +0 -22
  102. package/dist/hooks/onDelete.d.ts +0 -12
  103. package/dist/hooks/onDelete.js +0 -60
  104. package/dist/hooks/removeRelated.d.ts +0 -11
  105. package/dist/hooks/removeRelated.js +0 -50
  106. package/dist/hooks/runPerItem.d.ts +0 -10
  107. package/dist/hooks/runPerItem.js +0 -42
  108. package/dist/hooks/setData.d.ts +0 -11
  109. package/dist/hooks/setData.js +0 -54
  110. package/dist/index.js +0 -21
  111. package/dist/mixins/debounce-mixin/DebouncedStore.d.ts +0 -18
  112. package/dist/mixins/debounce-mixin/DebouncedStore.js +0 -65
  113. package/dist/mixins/debounce-mixin/debounceMixin.d.ts +0 -3
  114. package/dist/mixins/debounce-mixin/debounceMixin.js +0 -23
  115. package/dist/mixins/debounce-mixin/index.d.ts +0 -3
  116. package/dist/mixins/debounce-mixin/index.js +0 -19
  117. package/dist/mixins/debounce-mixin/types.d.ts +0 -13
  118. package/dist/mixins/debounce-mixin/types.js +0 -2
  119. package/dist/mixins/index.d.ts +0 -1
  120. package/dist/mixins/index.js +0 -17
  121. package/dist/types.d.ts +0 -3
  122. package/dist/types.js +0 -2
  123. package/dist/typesInternal.d.ts +0 -3
  124. package/dist/typesInternal.js +0 -4
  125. package/dist/utils/filterQuery.d.ts +0 -8
  126. package/dist/utils/filterQuery.js +0 -46
  127. package/dist/utils/getItemsIsArray.d.ts +0 -10
  128. package/dist/utils/getItemsIsArray.js +0 -20
  129. package/dist/utils/getPaginate.d.ts +0 -9
  130. package/dist/utils/getPaginate.js +0 -22
  131. package/dist/utils/index.d.ts +0 -11
  132. package/dist/utils/index.js +0 -27
  133. package/dist/utils/isMulti.d.ts +0 -11
  134. package/dist/utils/isMulti.js +0 -30
  135. package/dist/utils/isPaginated.d.ts +0 -5
  136. package/dist/utils/isPaginated.js +0 -15
  137. package/dist/utils/markHookForSkip.d.ts +0 -7
  138. package/dist/utils/markHookForSkip.js +0 -22
  139. package/dist/utils/mergeQuery/index.d.ts +0 -3
  140. package/dist/utils/mergeQuery/index.js +0 -19
  141. package/dist/utils/mergeQuery/mergeArrays.d.ts +0 -3
  142. package/dist/utils/mergeQuery/mergeArrays.js +0 -41
  143. package/dist/utils/mergeQuery/mergeQuery.d.ts +0 -3
  144. package/dist/utils/mergeQuery/mergeQuery.js +0 -77
  145. package/dist/utils/mergeQuery/types.d.ts +0 -13
  146. package/dist/utils/mergeQuery/types.js +0 -2
  147. package/dist/utils/mergeQuery/utils.d.ts +0 -11
  148. package/dist/utils/mergeQuery/utils.js +0 -287
  149. package/dist/utils/pushSet.d.ts +0 -8
  150. package/dist/utils/pushSet.js +0 -29
  151. package/dist/utils/setResultEmpty.d.ts +0 -5
  152. package/dist/utils/setResultEmpty.js +0 -32
  153. package/dist/utils/shouldSkip.d.ts +0 -8
  154. package/dist/utils/shouldSkip.js +0 -33
  155. package/dist/utils/validateQueryProperty.d.ts +0 -5
  156. package/dist/utils/validateQueryProperty.js +0 -25
@@ -1,8 +0,0 @@
1
- import type { FilterQueryOptions as PlainFilterQueryOptions, AdapterBase } from "@feathersjs/adapter-commons";
2
- import type { Query } from "@feathersjs/feathers";
3
- export interface FilterQueryOptions<T> {
4
- service?: AdapterBase<T>;
5
- operators?: PlainFilterQueryOptions["operators"];
6
- filters?: PlainFilterQueryOptions["filters"];
7
- }
8
- export declare function filterQuery<T>(query: Query, _options?: FilterQueryOptions<T>): any;
@@ -1,30 +0,0 @@
1
- import { filterQuery as plainFilterQuery } from "@feathersjs/adapter-commons";
2
- export function filterQuery(query, _options) {
3
- query = query || {};
4
- _options = _options || {};
5
- const { service, ...options } = _options;
6
- if (service) {
7
- const operators = options.operators
8
- ? options.operators
9
- : service.options?.operators;
10
- const filters = options.filters
11
- ? options.filters
12
- : service.options?.filters;
13
- const optionsForFilterQuery = {};
14
- if (operators) {
15
- optionsForFilterQuery.operators = operators;
16
- }
17
- if (filters) {
18
- optionsForFilterQuery.filters = filters;
19
- }
20
- if (service &&
21
- "filterQuery" in service &&
22
- typeof service.filterQuery === "function") {
23
- return service.filterQuery({ query }, optionsForFilterQuery);
24
- }
25
- else {
26
- return plainFilterQuery(query, optionsForFilterQuery);
27
- }
28
- }
29
- return plainFilterQuery(query, options);
30
- }
@@ -1,10 +0,0 @@
1
- import type { HookContext } from "@feathersjs/feathers";
2
- export interface GetItemsIsArrayResult<T = any> {
3
- items: T[];
4
- isArray: boolean;
5
- }
6
- /**
7
- * util to get items from context, return it as an array, no matter if it is an array or not
8
- * uses `context.result` if existent. uses `context.data` otherwise
9
- */
10
- export declare const getItemsIsArray: <T = any, H extends HookContext<import("@feathersjs/feathers").Application<any, any>, any> = HookContext<import("@feathersjs/feathers").Application<any, any>, any>>(context: H) => GetItemsIsArrayResult<T>;
@@ -1,16 +0,0 @@
1
- /**
2
- * util to get items from context, return it as an array, no matter if it is an array or not
3
- * uses `context.result` if existent. uses `context.data` otherwise
4
- */
5
- export const getItemsIsArray = (context) => {
6
- let itemOrItems = context.result !== undefined ? context.result : context.data;
7
- itemOrItems =
8
- itemOrItems && context.method === "find"
9
- ? itemOrItems.data || itemOrItems
10
- : itemOrItems;
11
- const isArray = Array.isArray(itemOrItems);
12
- return {
13
- items: isArray ? itemOrItems : itemOrItems != null ? [itemOrItems] : [],
14
- isArray,
15
- };
16
- };
@@ -1,9 +0,0 @@
1
- import type { PaginationOptions } from "@feathersjs/adapter-commons";
2
- import type { HookContext } from "@feathersjs/feathers";
3
- /**
4
- * util to get paginate options from context
5
- * 1. it uses `context.params.paginate` if it exists
6
- * 2. it uses `service.options.paginate` if it exists
7
- * 3. it uses `context.params.adapter` if it exists
8
- */
9
- 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;
@@ -1,20 +0,0 @@
1
- /**
2
- * util to get paginate options from context
3
- * 1. it uses `context.params.paginate` if it exists
4
- * 2. it uses `service.options.paginate` if it exists
5
- * 3. it uses `context.params.adapter` if it exists
6
- */
7
- export const getPaginate = (context) => {
8
- if (Object.prototype.hasOwnProperty.call(context.params, "paginate")) {
9
- return context.params.paginate || undefined;
10
- }
11
- if (context.params.paginate === false) {
12
- return undefined;
13
- }
14
- let options = context.service?.options || {};
15
- options = {
16
- ...options,
17
- ...context.params.adapter,
18
- };
19
- return options.paginate || undefined;
20
- };
@@ -1,11 +0,0 @@
1
- export * from "./mergeQuery";
2
- export * from "./filterQuery";
3
- export * from "./getItemsIsArray";
4
- export * from "./getPaginate";
5
- export * from "./isMulti";
6
- export * from "./isPaginated";
7
- export * from "./markHookForSkip";
8
- export * from "./pushSet";
9
- export * from "./setResultEmpty";
10
- export * from "./shouldSkip";
11
- export * from "./validateQueryProperty";
@@ -1,11 +0,0 @@
1
- export * from "./mergeQuery";
2
- export * from "./filterQuery";
3
- export * from "./getItemsIsArray";
4
- export * from "./getPaginate";
5
- export * from "./isMulti";
6
- export * from "./isPaginated";
7
- export * from "./markHookForSkip";
8
- export * from "./pushSet";
9
- export * from "./setResultEmpty";
10
- export * from "./shouldSkip";
11
- export * from "./validateQueryProperty";
@@ -1,11 +0,0 @@
1
- import type { HookContext } from "@feathersjs/feathers";
2
- /**
3
- * util to check if a hook is a multi hook:
4
- * - find: true
5
- * - get: false
6
- * - create: `context.data` is an array
7
- * - update: false
8
- * - patch: `context.id == null`
9
- * - remove: `context.id == null`
10
- */
11
- 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,26 +0,0 @@
1
- /**
2
- * util to check if a hook is a multi hook:
3
- * - find: true
4
- * - get: false
5
- * - create: `context.data` is an array
6
- * - update: false
7
- * - patch: `context.id == null`
8
- * - remove: `context.id == null`
9
- */
10
- export const isMulti = (context) => {
11
- const { method } = context;
12
- if (method === "find") {
13
- return true;
14
- }
15
- else if (["patch", "remove"].includes(method)) {
16
- return context.id == null;
17
- }
18
- else if (method === "create") {
19
- const items = context.type === "before" ? context.data : context.result;
20
- return Array.isArray(items);
21
- }
22
- else if (["get", "update"].includes(method)) {
23
- return false;
24
- }
25
- return false;
26
- };
@@ -1,5 +0,0 @@
1
- import type { HookContext } from "@feathersjs/feathers";
2
- /**
3
- * util to check if a hook is a paginated hook using `getPaginate`
4
- */
5
- 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,11 +0,0 @@
1
- import { getPaginate } from "./getPaginate";
2
- /**
3
- * util to check if a hook is a paginated hook using `getPaginate`
4
- */
5
- export const isPaginated = (context) => {
6
- if (context.params.paginate === false || context.method !== "find") {
7
- return false;
8
- }
9
- const paginate = getPaginate(context);
10
- return !!paginate;
11
- };
@@ -1,7 +0,0 @@
1
- import type { HookContext } from "@feathersjs/feathers";
2
- import type { HookType } from "feathers-hooks-common";
3
- import type { MaybeArray } from "../typesInternal";
4
- /**
5
- * util to mark a hook for skip, has to be used with `shouldSkip`
6
- */
7
- export declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H | undefined;
@@ -1,18 +0,0 @@
1
- import { pushSet } from "./pushSet";
2
- /**
3
- * util to mark a hook for skip, has to be used with `shouldSkip`
4
- */
5
- export function markHookForSkip(hookName, type, context) {
6
- // @ts-expect-error context is not of type 'H'
7
- context = context || {};
8
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
9
- const params = context.params || {};
10
- const types = Array.isArray(type) ? type : [type];
11
- types.forEach((t) => {
12
- const combinedName = t === "all" ? hookName : `${type}:${hookName}`;
13
- pushSet(params, ["skipHooks"], combinedName, { unique: true });
14
- });
15
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16
- context.params = params;
17
- return context;
18
- }
@@ -1,3 +0,0 @@
1
- export * from "./mergeArrays";
2
- export * from "./mergeQuery";
3
- export * from "./types";
@@ -1,3 +0,0 @@
1
- export * from "./mergeArrays";
2
- export * from "./mergeQuery";
3
- export * from "./types";
@@ -1,3 +0,0 @@
1
- import type { Path } from "../../typesInternal";
2
- import type { Handle, ActionOnEmptyIntersect } from "./types";
3
- export declare function mergeArrays<T>(targetArr: T[], sourceArr: T[], handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
@@ -1,37 +0,0 @@
1
- export function mergeArrays(targetArr, sourceArr, handle, prependKey, actionOnEmptyIntersect) {
2
- if (!sourceArr && !targetArr) {
3
- return;
4
- }
5
- if (handle === "target") {
6
- return targetArr;
7
- }
8
- else if (handle === "source") {
9
- return sourceArr;
10
- }
11
- else if (handle === "combine") {
12
- if (!sourceArr || !Array.isArray(sourceArr)) {
13
- return targetArr;
14
- }
15
- if (!targetArr || !Array.isArray(targetArr)) {
16
- return sourceArr;
17
- }
18
- const arr = targetArr.concat(sourceArr);
19
- return [...new Set(arr)];
20
- }
21
- else if (handle === "intersect" || handle === "intersectOrFull") {
22
- const targetIsArray = !targetArr || !Array.isArray(targetArr);
23
- const sourceIsArray = !sourceArr || !Array.isArray(sourceArr);
24
- if ((targetIsArray || sourceIsArray) && handle === "intersect") {
25
- if (actionOnEmptyIntersect) {
26
- actionOnEmptyIntersect(targetArr, sourceArr, prependKey || []);
27
- }
28
- return;
29
- }
30
- if (handle === "intersectOrFull") {
31
- const val = !targetIsArray ? targetArr : sourceArr;
32
- return val;
33
- }
34
- return targetArr.filter((val) => sourceArr.includes(val));
35
- }
36
- return undefined;
37
- }
@@ -1,3 +0,0 @@
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,70 +0,0 @@
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
- filters: fullOptions.filters,
10
- service: fullOptions.service,
11
- });
12
- moveProperty(targetFilters, targetQuery, "$or");
13
- moveProperty(targetFilters, targetQuery, "$and");
14
- if (target.$limit) {
15
- targetFilters.$limit = target.$limit;
16
- }
17
- let {
18
- // eslint-disable-next-line prefer-const
19
- filters: sourceFilters, query: sourceQuery, } = filterQuery(source, {
20
- operators: fullOptions.operators,
21
- filters: fullOptions.filters,
22
- service: fullOptions.service,
23
- });
24
- moveProperty(sourceFilters, sourceQuery, "$or");
25
- moveProperty(sourceFilters, sourceQuery, "$and");
26
- if (source.$limit) {
27
- sourceFilters.$limit = source.$limit;
28
- }
29
- //#region filters
30
- if (target &&
31
- !Object.prototype.hasOwnProperty.call(target, "$limit") &&
32
- Object.prototype.hasOwnProperty.call(targetFilters, "$limit")) {
33
- delete targetFilters.$limit;
34
- }
35
- if (source &&
36
- !Object.prototype.hasOwnProperty.call(source, "$limit") &&
37
- Object.prototype.hasOwnProperty.call(sourceFilters, "$limit")) {
38
- delete sourceFilters.$limit;
39
- }
40
- handleArray(targetFilters, sourceFilters, ["$select"], fullOptions);
41
- // remaining filters
42
- delete sourceFilters["$select"];
43
- _merge(targetFilters, sourceFilters);
44
- //#endregion
45
- //#region '$or' / '$and'
46
- if (options?.useLogicalConjunction &&
47
- (options.defaultHandle === "combine" ||
48
- options.defaultHandle === "intersect") &&
49
- !_isEmpty(targetQuery)) {
50
- const logicalOp = options.defaultHandle === "combine" ? "$or" : "$and";
51
- if (Object.prototype.hasOwnProperty.call(sourceQuery, logicalOp)) {
52
- // omit '$or'/'$and' and put all other props into '$or'/'$and'
53
- const andOr = sourceQuery[logicalOp];
54
- delete sourceQuery[logicalOp];
55
- andOr.push(sourceQuery);
56
- sourceQuery = { [logicalOp]: andOr };
57
- }
58
- else {
59
- sourceQuery = { [logicalOp]: [sourceQuery] };
60
- }
61
- }
62
- //#endregion
63
- const keys = Object.keys(sourceQuery);
64
- for (let i = 0, n = keys.length; i < n; i++) {
65
- const key = keys[i];
66
- handleCircular(targetQuery, sourceQuery, [key], fullOptions);
67
- }
68
- const result = Object.assign({}, targetFilters, targetQuery);
69
- return result;
70
- }
@@ -1,13 +0,0 @@
1
- import type { Path } from "../../typesInternal";
2
- import type { FilterQueryOptions } from "../filterQuery";
3
- export type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
4
- export type FirstLast = "first" | "last";
5
- export 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
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,11 +0,0 @@
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[];
@@ -1,272 +0,0 @@
1
- import { Forbidden } from "@feathersjs/errors";
2
- import _get from "lodash/get.js";
3
- import _has from "lodash/has.js";
4
- import _isEmpty from "lodash/isEmpty.js";
5
- import _isEqual from "lodash/isEqual.js";
6
- import _set from "lodash/set.js";
7
- import _uniqWith from "lodash/uniqWith.js";
8
- import { mergeArrays } from "./mergeArrays";
9
- export const hasOwnProperty = (obj, key) => {
10
- return Object.prototype.hasOwnProperty.call(obj, key);
11
- };
12
- export function handleArray(target, source, key, options) {
13
- const targetVal = _get(target, key);
14
- const sourceVal = _get(source, key);
15
- if (!sourceVal && !targetVal) {
16
- return;
17
- }
18
- const handle = _get(options, ["handle", ...key], options.defaultHandle);
19
- const arr = mergeArrays(targetVal, sourceVal, handle, key, options.actionOnEmptyIntersect);
20
- _set(target, key, arr);
21
- }
22
- export function handleCircular(target, source, prependKey, options) {
23
- if (target?.$or) {
24
- target.$or = cleanOr(target.$or);
25
- if (!target.$or) {
26
- delete target.$or;
27
- }
28
- }
29
- if (source?.$or) {
30
- source.$or = cleanOr(source.$or);
31
- if (!source.$or) {
32
- delete source.$or;
33
- }
34
- }
35
- if (target?.$and) {
36
- target.$and = cleanAnd(target.$and);
37
- if (!target.$and) {
38
- delete target.$and;
39
- }
40
- }
41
- if (source?.$and) {
42
- source.$and = cleanAnd(source.$and);
43
- if (!source.$and) {
44
- delete source.$and;
45
- }
46
- }
47
- if (!_has(source, prependKey)) {
48
- return;
49
- }
50
- if (!_has(target, prependKey)) {
51
- _set(target, prependKey, _get(source, prependKey));
52
- return;
53
- }
54
- const { defaultHandle, actionOnEmptyIntersect } = options;
55
- if (defaultHandle === "target") {
56
- return;
57
- }
58
- const getTargetVal = () => {
59
- return prependKey.length > 0 ? _get(target, prependKey) : target;
60
- };
61
- const getSourceVal = () => {
62
- return prependKey.length > 0 ? _get(source, prependKey) : source;
63
- };
64
- const targetVal = getTargetVal();
65
- const sourceVal = getSourceVal();
66
- if (_isEqual(targetVal, sourceVal)) {
67
- return;
68
- }
69
- if (defaultHandle === "source") {
70
- _set(target, prependKey, sourceVal);
71
- return;
72
- }
73
- if (targetVal === null || sourceVal === null) {
74
- _set(target, prependKey, sourceVal);
75
- return;
76
- }
77
- const typeOfTargetVal = typeof targetVal;
78
- if (["boolean"].includes(typeOfTargetVal)) {
79
- if (defaultHandle === "intersect") {
80
- actionOnEmptyIntersect(target, source, prependKey);
81
- }
82
- _set(target, prependKey, sourceVal);
83
- return;
84
- }
85
- const typeOfSourceVal = typeof sourceVal;
86
- const isTargetSimple = ["string", "number"].includes(typeOfTargetVal);
87
- const isSourceSimple = ["string", "number"].includes(typeOfSourceVal);
88
- if (isTargetSimple || isSourceSimple) {
89
- if (isTargetSimple && isSourceSimple) {
90
- if (defaultHandle === "combine") {
91
- _set(target, prependKey, { $in: [...new Set([targetVal, sourceVal])] });
92
- return;
93
- }
94
- else if (defaultHandle === "intersect") {
95
- actionOnEmptyIntersect(target, source, prependKey);
96
- }
97
- else {
98
- throw new Error("should not reach here");
99
- }
100
- }
101
- else if (hasOwnProperty(targetVal, "$in") ||
102
- hasOwnProperty(sourceVal, "$in")) {
103
- const targetHasIn = hasOwnProperty(targetVal, "$in");
104
- const $in = targetHasIn ? targetVal["$in"] : sourceVal["$in"];
105
- const otherVal = isTargetSimple ? targetVal : sourceVal;
106
- if ($in.length === 1 && _isEqual($in[0], otherVal)) {
107
- _set(target, prependKey, otherVal);
108
- return;
109
- }
110
- else if (defaultHandle === "combine") {
111
- if (!$in.some((x) => _isEqual(x, otherVal))) {
112
- $in.push(otherVal);
113
- }
114
- _set(target, `${prependKey}.$in`, $in);
115
- return;
116
- }
117
- else if (defaultHandle === "intersect") {
118
- if ($in.some((x) => _isEqual(x, otherVal))) {
119
- _set(target, prependKey, otherVal);
120
- }
121
- else {
122
- actionOnEmptyIntersect(target, source, prependKey);
123
- }
124
- return;
125
- }
126
- return;
127
- }
128
- }
129
- const isTargetArray = Array.isArray(targetVal);
130
- const isSourceArray = Array.isArray(sourceVal);
131
- if (isTargetArray && isSourceArray) {
132
- const key = prependKey[prependKey.length - 1];
133
- if (key === "$or") {
134
- if (defaultHandle === "combine") {
135
- const newVals = sourceVal.filter((x) => !targetVal.some((y) => _isEqual(x, y)));
136
- targetVal.push(...newVals);
137
- }
138
- else if (defaultHandle === "intersect") {
139
- // combine into "$and"
140
- const targetParent = getParentProp(target, prependKey);
141
- const sourceParent = getParentProp(source, prependKey);
142
- targetParent.$and = targetParent.$and || [];
143
- targetParent.$and.push({ $or: targetVal }, { $or: sourceVal });
144
- targetParent.$and = cleanAnd(targetParent.$and);
145
- if (!targetParent.$and) {
146
- delete targetParent.$and;
147
- }
148
- delete targetParent.$or;
149
- delete sourceParent.$or;
150
- handleCircular(target, source, [...prependKey, "$and"], options);
151
- return;
152
- }
153
- return;
154
- }
155
- else if (key === "$and") {
156
- if (defaultHandle === "combine") {
157
- // combine into "$or"
158
- const targetParent = getParentProp(target, prependKey);
159
- const sourceParent = getParentProp(source, prependKey);
160
- targetParent.$or = targetParent.$or || [];
161
- targetParent.$or.push({ $and: targetVal }, { $and: sourceVal });
162
- targetParent.$or = cleanOr(targetParent.$or);
163
- if (!targetParent.$or) {
164
- delete targetParent.$or;
165
- }
166
- delete targetParent.$and;
167
- delete sourceParent.$and;
168
- handleCircular(target, source, [...prependKey, "$or"], options);
169
- return;
170
- }
171
- else if (defaultHandle === "intersect") {
172
- const newVals = sourceVal.filter((x) => !targetVal.some((y) => _isEqual(x, y)));
173
- targetVal.push(...newVals);
174
- return;
175
- }
176
- }
177
- else if (key === "$in") {
178
- if (defaultHandle === "combine") {
179
- let $in = targetVal.concat(sourceVal);
180
- $in = [...new Set($in)];
181
- _set(target, prependKey, $in);
182
- return;
183
- }
184
- else if (defaultHandle === "intersect") {
185
- const $in = targetVal.filter((x) => sourceVal.some((y) => _isEqual(x, y)));
186
- if ($in.length === 0) {
187
- actionOnEmptyIntersect(target, source, prependKey);
188
- }
189
- else if ($in.length === 1) {
190
- _set(target, prependKey.slice(0, -1), $in[0]);
191
- return;
192
- }
193
- else {
194
- _set(target, prependKey, $in);
195
- }
196
- }
197
- return;
198
- }
199
- _set(target, prependKey, sourceVal);
200
- return;
201
- }
202
- if (typeOfTargetVal !== "object" || typeOfSourceVal !== "object") {
203
- _set(target, prependKey, sourceVal);
204
- return;
205
- }
206
- // both are objects
207
- const sourceKeys = Object.keys(sourceVal);
208
- for (let i = 0, n = sourceKeys.length; i < n; i++) {
209
- const key = sourceKeys[i];
210
- handleCircular(target, source, [...prependKey, key], options);
211
- }
212
- }
213
- export function makeDefaultOptions(options) {
214
- options = options || {};
215
- options.defaultHandle = options.defaultHandle || "combine";
216
- options.useLogicalConjunction = Object.prototype.hasOwnProperty.call(options, "useLogicalConjunction")
217
- ? options.useLogicalConjunction
218
- : false;
219
- options.actionOnEmptyIntersect =
220
- options.actionOnEmptyIntersect ||
221
- (() => {
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
- export 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 getParentProp(target, path) {
238
- if (path.length <= 1) {
239
- return target;
240
- }
241
- const pathOneUp = path.slice(0, -1);
242
- return _get(target, pathOneUp);
243
- }
244
- export function cleanOr(target) {
245
- if (!target || !Array.isArray(target) || target.length <= 0) {
246
- return target;
247
- }
248
- if (target.some((x) => _isEmpty(x))) {
249
- return undefined;
250
- }
251
- else {
252
- return arrayWithoutDuplicates(target);
253
- }
254
- }
255
- export function cleanAnd(target) {
256
- if (!target || !Array.isArray(target) || target.length <= 0) {
257
- return target;
258
- }
259
- if (target.every((x) => _isEmpty(x))) {
260
- return undefined;
261
- }
262
- else {
263
- target = target.filter((x) => !_isEmpty(x));
264
- return arrayWithoutDuplicates(target);
265
- }
266
- }
267
- export function arrayWithoutDuplicates(target) {
268
- if (!target || !Array.isArray(target)) {
269
- return target;
270
- }
271
- return _uniqWith(target, _isEqual);
272
- }
@@ -1,8 +0,0 @@
1
- import type { Path } from "../typesInternal";
2
- export interface PushSetOptions {
3
- unique?: boolean;
4
- }
5
- /**
6
- * util to push a value to an array at a given path in an object
7
- */
8
- export declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val: unknown, options?: PushSetOptions) => unknown[];