feathers-utils 3.1.3 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -8,7 +8,6 @@ const _has = require('lodash/has.js');
8
8
  const _set = require('lodash/set.js');
9
9
  const _uniqWith = require('lodash/uniqWith.js');
10
10
  const fastEquals = require('fast-equals');
11
- const adapterCommons = require('@feathersjs/adapter-commons');
12
11
  const _isEqual = require('lodash/isEqual.js');
13
12
  const commons = require('@feathersjs/commons');
14
13
  const feathersHooksCommon = require('feathers-hooks-common');
@@ -284,15 +283,6 @@ function makeDefaultOptions$1(options) {
284
283
  }
285
284
  return options;
286
285
  }
287
- function moveProperty(from, to, ...keys) {
288
- keys.forEach((key) => {
289
- if (!hasOwnProperty(from, key)) {
290
- return;
291
- }
292
- to[key] = from[key];
293
- delete from[key];
294
- });
295
- }
296
286
  function getParentProp(target, path) {
297
287
  if (path.length <= 1) {
298
288
  return target;
@@ -362,59 +352,29 @@ function areQueriesOverlapping(target, source) {
362
352
  return false;
363
353
  }
364
354
 
365
- function filterQuery(query, _options) {
366
- query = query || {};
367
- _options = _options || {};
368
- const { service, ...options } = _options;
369
- if (service) {
370
- const operators = options.operators ? options.operators : service.options?.operators;
371
- const filters = options.filters ? options.filters : service.options?.filters;
372
- const optionsForFilterQuery = {};
373
- if (operators) {
374
- optionsForFilterQuery.operators = operators;
375
- }
376
- if (filters) {
377
- optionsForFilterQuery.filters = filters;
378
- }
379
- if (service && "filterQuery" in service && typeof service.filterQuery === "function") {
380
- return service.filterQuery({ query }, optionsForFilterQuery);
381
- } else {
382
- return adapterCommons.filterQuery(query, optionsForFilterQuery);
383
- }
355
+ function filterQuery(providedQuery) {
356
+ providedQuery ?? (providedQuery = {});
357
+ const { $select, $limit, $skip, $sort, ...query } = providedQuery;
358
+ const result = { query };
359
+ if ("$select" in providedQuery) {
360
+ result.$select = $select;
361
+ }
362
+ if ("$limit" in providedQuery) {
363
+ result.$limit = $limit;
384
364
  }
385
- return adapterCommons.filterQuery(query, options);
365
+ if ("$skip" in providedQuery) {
366
+ result.$skip = $skip;
367
+ }
368
+ if ("$sort" in providedQuery) {
369
+ result.$sort = $sort;
370
+ }
371
+ return result;
386
372
  }
387
373
 
388
374
  function mergeQuery(target, source, _options) {
389
375
  const options = makeDefaultOptions$1(_options);
390
- const { filters: targetFilters, query: targetQuery } = filterQuery(target, {
391
- operators: options.operators,
392
- filters: options.filters,
393
- service: options.service
394
- });
395
- moveProperty(targetFilters, targetQuery, "$or", "$and");
396
- if ("$limit" in target) {
397
- targetFilters.$limit = target.$limit;
398
- }
399
- let {
400
- // eslint-disable-next-line prefer-const
401
- filters: sourceFilters,
402
- query: sourceQuery
403
- } = filterQuery(source, {
404
- operators: options.operators,
405
- filters: options.filters,
406
- service: options.service
407
- });
408
- moveProperty(sourceFilters, sourceQuery, "$or", "$and");
409
- if (source.$limit) {
410
- sourceFilters.$limit = source.$limit;
411
- }
412
- if (target && !hasOwnProperty(target, "$limit") && hasOwnProperty(targetFilters, "$limit")) {
413
- delete targetFilters.$limit;
414
- }
415
- if (source && !hasOwnProperty(source, "$limit") && hasOwnProperty(sourceFilters, "$limit")) {
416
- delete sourceFilters.$limit;
417
- }
376
+ const { query: targetQuery, ...targetFilters } = filterQuery(target);
377
+ let { query: sourceQuery, ...sourceFilters } = filterQuery(source);
418
378
  handleArray(targetFilters, sourceFilters, ["$select"], options);
419
379
  delete sourceFilters["$select"];
420
380
  _merge__default(targetFilters, sourceFilters);
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import * as _feathersjs_feathers from '@feathersjs/feathers';
2
2
  import { HookContext, Application, Id, Query, Params } from '@feathersjs/feathers';
3
3
  import { HookContext as HookContext$1, Application as Application$1 } from '@feathersjs/feathers/lib';
4
4
  import { PropertyPath, DebouncedFunc } from 'lodash';
5
- import { AdapterBase, FilterQueryOptions as FilterQueryOptions$1, PaginationOptions } from '@feathersjs/adapter-commons';
5
+ import { PaginationOptions, FilterQueryOptions } from '@feathersjs/adapter-commons';
6
6
  import { HookType } from 'feathers-hooks-common';
7
7
 
8
8
  /**
@@ -125,17 +125,10 @@ declare class DebouncedStore {
125
125
 
126
126
  declare function debounceMixin(options?: Partial<InitDebounceMixinOptions>): (app: Application$1) => void;
127
127
 
128
- interface FilterQueryOptions<T> {
129
- service?: AdapterBase<T>;
130
- operators?: FilterQueryOptions$1["operators"];
131
- filters?: FilterQueryOptions$1["filters"];
132
- }
133
- declare function filterQuery<T>(query: Query, _options?: FilterQueryOptions<T>): any;
134
-
135
128
  type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
136
129
  type FirstLast = "first" | "last";
137
130
  type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
138
- interface MergeQueryOptions<T> extends FilterQueryOptions<T> {
131
+ interface MergeQueryOptions {
139
132
  defaultHandle: Handle;
140
133
  actionOnEmptyIntersect: ActionOnEmptyIntersect;
141
134
  useLogicalConjunction: boolean;
@@ -153,7 +146,22 @@ declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | und
153
146
  * @param _options
154
147
  * @returns Query
155
148
  */
156
- declare function mergeQuery<T = any>(target: Query, source: Query, _options?: Partial<MergeQueryOptions<T>>): Query;
149
+ declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
150
+
151
+ type FilterQueryResult<Q extends Query> = {
152
+ $select: Q["$select"] extends any ? Q["$select"] : never;
153
+ $limit: Q["$limit"] extends any ? Q["$limit"] : never;
154
+ $skip: Q["$skip"] extends any ? Q["$skip"] : never;
155
+ $sort: Q["$sort"] extends any ? Q["$sort"] : never;
156
+ query: Omit<Q, "$select" | "$limit" | "$skip" | "$sort">;
157
+ };
158
+ /**
159
+ * Extracts $select, $limit, $skip, $sort from a query and returns the rest as a query object.
160
+ *
161
+ * @param providedQuery
162
+ * @returns
163
+ */
164
+ declare function filterQuery<Q extends Query>(providedQuery?: Q): FilterQueryResult<Q>;
157
165
 
158
166
  /**
159
167
  * util to get paginate options from context
@@ -217,9 +225,9 @@ type SetQueryKeySafelyOptions = {
217
225
  };
218
226
  declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
219
227
 
220
- declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
228
+ declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
221
229
 
222
- declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
230
+ declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
223
231
 
224
232
  type Single<T> = T extends Array<infer U> ? U : T;
225
233
  type AsArray<T> = T extends any[] ? T : [T];
@@ -267,4 +275,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
267
275
  type InferDataFromPath<App extends Application, Path extends string, Method extends "create" | "update" | "patch"> = Method extends "create" ? InferCreateDataFromPath<App, Path> : Method extends "update" ? InferUpdateDataFromPath<App, Path> : Method extends "patch" ? InferPatchDataFromPath<App, Path> : never;
268
276
  type InferResultFromPath<App extends Application, Path extends string, Method extends "get" | "find" | "create" | "update" | "patch" | "remove"> = Method extends "get" ? InferGetResultFromPath<App, Path> : Method extends "find" ? InferFindResultFromPath<App, Path> : Method extends "create" ? InferCreateResultFromPath<App, Path> : Method extends "update" ? InferUpdateResultFromPath<App, Path> : Method extends "patch" ? InferPatchResultFromPath<App, Path> : Method extends "remove" ? InferRemoveResultFromPath<App, Path> : never;
269
277
 
270
- export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FilterQueryOptions, type FirstLast, type GetItemsIsArrayFrom, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
278
+ export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import * as _feathersjs_feathers from '@feathersjs/feathers';
2
2
  import { HookContext, Application, Id, Query, Params } from '@feathersjs/feathers';
3
3
  import { HookContext as HookContext$1, Application as Application$1 } from '@feathersjs/feathers/lib';
4
4
  import { PropertyPath, DebouncedFunc } from 'lodash';
5
- import { AdapterBase, FilterQueryOptions as FilterQueryOptions$1, PaginationOptions } from '@feathersjs/adapter-commons';
5
+ import { PaginationOptions, FilterQueryOptions } from '@feathersjs/adapter-commons';
6
6
  import { HookType } from 'feathers-hooks-common';
7
7
 
8
8
  /**
@@ -125,17 +125,10 @@ declare class DebouncedStore {
125
125
 
126
126
  declare function debounceMixin(options?: Partial<InitDebounceMixinOptions>): (app: Application$1) => void;
127
127
 
128
- interface FilterQueryOptions<T> {
129
- service?: AdapterBase<T>;
130
- operators?: FilterQueryOptions$1["operators"];
131
- filters?: FilterQueryOptions$1["filters"];
132
- }
133
- declare function filterQuery<T>(query: Query, _options?: FilterQueryOptions<T>): any;
134
-
135
128
  type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
136
129
  type FirstLast = "first" | "last";
137
130
  type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
138
- interface MergeQueryOptions<T> extends FilterQueryOptions<T> {
131
+ interface MergeQueryOptions {
139
132
  defaultHandle: Handle;
140
133
  actionOnEmptyIntersect: ActionOnEmptyIntersect;
141
134
  useLogicalConjunction: boolean;
@@ -153,7 +146,22 @@ declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | und
153
146
  * @param _options
154
147
  * @returns Query
155
148
  */
156
- declare function mergeQuery<T = any>(target: Query, source: Query, _options?: Partial<MergeQueryOptions<T>>): Query;
149
+ declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
150
+
151
+ type FilterQueryResult<Q extends Query> = {
152
+ $select: Q["$select"] extends any ? Q["$select"] : never;
153
+ $limit: Q["$limit"] extends any ? Q["$limit"] : never;
154
+ $skip: Q["$skip"] extends any ? Q["$skip"] : never;
155
+ $sort: Q["$sort"] extends any ? Q["$sort"] : never;
156
+ query: Omit<Q, "$select" | "$limit" | "$skip" | "$sort">;
157
+ };
158
+ /**
159
+ * Extracts $select, $limit, $skip, $sort from a query and returns the rest as a query object.
160
+ *
161
+ * @param providedQuery
162
+ * @returns
163
+ */
164
+ declare function filterQuery<Q extends Query>(providedQuery?: Q): FilterQueryResult<Q>;
157
165
 
158
166
  /**
159
167
  * util to get paginate options from context
@@ -217,9 +225,9 @@ type SetQueryKeySafelyOptions = {
217
225
  };
218
226
  declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
219
227
 
220
- declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
228
+ declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
221
229
 
222
- declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
230
+ declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
223
231
 
224
232
  type Single<T> = T extends Array<infer U> ? U : T;
225
233
  type AsArray<T> = T extends any[] ? T : [T];
@@ -267,4 +275,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
267
275
  type InferDataFromPath<App extends Application, Path extends string, Method extends "create" | "update" | "patch"> = Method extends "create" ? InferCreateDataFromPath<App, Path> : Method extends "update" ? InferUpdateDataFromPath<App, Path> : Method extends "patch" ? InferPatchDataFromPath<App, Path> : never;
268
276
  type InferResultFromPath<App extends Application, Path extends string, Method extends "get" | "find" | "create" | "update" | "patch" | "remove"> = Method extends "get" ? InferGetResultFromPath<App, Path> : Method extends "find" ? InferFindResultFromPath<App, Path> : Method extends "create" ? InferCreateResultFromPath<App, Path> : Method extends "update" ? InferUpdateResultFromPath<App, Path> : Method extends "patch" ? InferPatchResultFromPath<App, Path> : Method extends "remove" ? InferRemoveResultFromPath<App, Path> : never;
269
277
 
270
- export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FilterQueryOptions, type FirstLast, type GetItemsIsArrayFrom, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
278
+ export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as _feathersjs_feathers from '@feathersjs/feathers';
2
2
  import { HookContext, Application, Id, Query, Params } from '@feathersjs/feathers';
3
3
  import { HookContext as HookContext$1, Application as Application$1 } from '@feathersjs/feathers/lib';
4
4
  import { PropertyPath, DebouncedFunc } from 'lodash';
5
- import { AdapterBase, FilterQueryOptions as FilterQueryOptions$1, PaginationOptions } from '@feathersjs/adapter-commons';
5
+ import { PaginationOptions, FilterQueryOptions } from '@feathersjs/adapter-commons';
6
6
  import { HookType } from 'feathers-hooks-common';
7
7
 
8
8
  /**
@@ -125,17 +125,10 @@ declare class DebouncedStore {
125
125
 
126
126
  declare function debounceMixin(options?: Partial<InitDebounceMixinOptions>): (app: Application$1) => void;
127
127
 
128
- interface FilterQueryOptions<T> {
129
- service?: AdapterBase<T>;
130
- operators?: FilterQueryOptions$1["operators"];
131
- filters?: FilterQueryOptions$1["filters"];
132
- }
133
- declare function filterQuery<T>(query: Query, _options?: FilterQueryOptions<T>): any;
134
-
135
128
  type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
136
129
  type FirstLast = "first" | "last";
137
130
  type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
138
- interface MergeQueryOptions<T> extends FilterQueryOptions<T> {
131
+ interface MergeQueryOptions {
139
132
  defaultHandle: Handle;
140
133
  actionOnEmptyIntersect: ActionOnEmptyIntersect;
141
134
  useLogicalConjunction: boolean;
@@ -153,7 +146,22 @@ declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | und
153
146
  * @param _options
154
147
  * @returns Query
155
148
  */
156
- declare function mergeQuery<T = any>(target: Query, source: Query, _options?: Partial<MergeQueryOptions<T>>): Query;
149
+ declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
150
+
151
+ type FilterQueryResult<Q extends Query> = {
152
+ $select: Q["$select"] extends any ? Q["$select"] : never;
153
+ $limit: Q["$limit"] extends any ? Q["$limit"] : never;
154
+ $skip: Q["$skip"] extends any ? Q["$skip"] : never;
155
+ $sort: Q["$sort"] extends any ? Q["$sort"] : never;
156
+ query: Omit<Q, "$select" | "$limit" | "$skip" | "$sort">;
157
+ };
158
+ /**
159
+ * Extracts $select, $limit, $skip, $sort from a query and returns the rest as a query object.
160
+ *
161
+ * @param providedQuery
162
+ * @returns
163
+ */
164
+ declare function filterQuery<Q extends Query>(providedQuery?: Q): FilterQueryResult<Q>;
157
165
 
158
166
  /**
159
167
  * util to get paginate options from context
@@ -217,9 +225,9 @@ type SetQueryKeySafelyOptions = {
217
225
  };
218
226
  declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
219
227
 
220
- declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
228
+ declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
221
229
 
222
- declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
230
+ declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
223
231
 
224
232
  type Single<T> = T extends Array<infer U> ? U : T;
225
233
  type AsArray<T> = T extends any[] ? T : [T];
@@ -267,4 +275,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
267
275
  type InferDataFromPath<App extends Application, Path extends string, Method extends "create" | "update" | "patch"> = Method extends "create" ? InferCreateDataFromPath<App, Path> : Method extends "update" ? InferUpdateDataFromPath<App, Path> : Method extends "patch" ? InferPatchDataFromPath<App, Path> : never;
268
276
  type InferResultFromPath<App extends Application, Path extends string, Method extends "get" | "find" | "create" | "update" | "patch" | "remove"> = Method extends "get" ? InferGetResultFromPath<App, Path> : Method extends "find" ? InferFindResultFromPath<App, Path> : Method extends "create" ? InferCreateResultFromPath<App, Path> : Method extends "update" ? InferUpdateResultFromPath<App, Path> : Method extends "patch" ? InferPatchResultFromPath<App, Path> : Method extends "remove" ? InferRemoveResultFromPath<App, Path> : never;
269
277
 
270
- export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FilterQueryOptions, type FirstLast, type GetItemsIsArrayFrom, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
278
+ export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/dist/index.mjs CHANGED
@@ -6,7 +6,6 @@ import _has from 'lodash/has.js';
6
6
  import _set from 'lodash/set.js';
7
7
  import _uniqWith from 'lodash/uniqWith.js';
8
8
  import { deepEqual } from 'fast-equals';
9
- import { filterQuery as filterQuery$1 } from '@feathersjs/adapter-commons';
10
9
  import _isEqual from 'lodash/isEqual.js';
11
10
  import { _ } from '@feathersjs/commons';
12
11
  import { checkContext } from 'feathers-hooks-common';
@@ -270,15 +269,6 @@ function makeDefaultOptions$1(options) {
270
269
  }
271
270
  return options;
272
271
  }
273
- function moveProperty(from, to, ...keys) {
274
- keys.forEach((key) => {
275
- if (!hasOwnProperty(from, key)) {
276
- return;
277
- }
278
- to[key] = from[key];
279
- delete from[key];
280
- });
281
- }
282
272
  function getParentProp(target, path) {
283
273
  if (path.length <= 1) {
284
274
  return target;
@@ -348,59 +338,29 @@ function areQueriesOverlapping(target, source) {
348
338
  return false;
349
339
  }
350
340
 
351
- function filterQuery(query, _options) {
352
- query = query || {};
353
- _options = _options || {};
354
- const { service, ...options } = _options;
355
- if (service) {
356
- const operators = options.operators ? options.operators : service.options?.operators;
357
- const filters = options.filters ? options.filters : service.options?.filters;
358
- const optionsForFilterQuery = {};
359
- if (operators) {
360
- optionsForFilterQuery.operators = operators;
361
- }
362
- if (filters) {
363
- optionsForFilterQuery.filters = filters;
364
- }
365
- if (service && "filterQuery" in service && typeof service.filterQuery === "function") {
366
- return service.filterQuery({ query }, optionsForFilterQuery);
367
- } else {
368
- return filterQuery$1(query, optionsForFilterQuery);
369
- }
341
+ function filterQuery(providedQuery) {
342
+ providedQuery ?? (providedQuery = {});
343
+ const { $select, $limit, $skip, $sort, ...query } = providedQuery;
344
+ const result = { query };
345
+ if ("$select" in providedQuery) {
346
+ result.$select = $select;
347
+ }
348
+ if ("$limit" in providedQuery) {
349
+ result.$limit = $limit;
350
+ }
351
+ if ("$skip" in providedQuery) {
352
+ result.$skip = $skip;
370
353
  }
371
- return filterQuery$1(query, options);
354
+ if ("$sort" in providedQuery) {
355
+ result.$sort = $sort;
356
+ }
357
+ return result;
372
358
  }
373
359
 
374
360
  function mergeQuery(target, source, _options) {
375
361
  const options = makeDefaultOptions$1(_options);
376
- const { filters: targetFilters, query: targetQuery } = filterQuery(target, {
377
- operators: options.operators,
378
- filters: options.filters,
379
- service: options.service
380
- });
381
- moveProperty(targetFilters, targetQuery, "$or", "$and");
382
- if ("$limit" in target) {
383
- targetFilters.$limit = target.$limit;
384
- }
385
- let {
386
- // eslint-disable-next-line prefer-const
387
- filters: sourceFilters,
388
- query: sourceQuery
389
- } = filterQuery(source, {
390
- operators: options.operators,
391
- filters: options.filters,
392
- service: options.service
393
- });
394
- moveProperty(sourceFilters, sourceQuery, "$or", "$and");
395
- if (source.$limit) {
396
- sourceFilters.$limit = source.$limit;
397
- }
398
- if (target && !hasOwnProperty(target, "$limit") && hasOwnProperty(targetFilters, "$limit")) {
399
- delete targetFilters.$limit;
400
- }
401
- if (source && !hasOwnProperty(source, "$limit") && hasOwnProperty(sourceFilters, "$limit")) {
402
- delete sourceFilters.$limit;
403
- }
362
+ const { query: targetQuery, ...targetFilters } = filterQuery(target);
363
+ let { query: sourceQuery, ...sourceFilters } = filterQuery(source);
404
364
  handleArray(targetFilters, sourceFilters, ["$select"], options);
405
365
  delete sourceFilters["$select"];
406
366
  _merge(targetFilters, sourceFilters);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feathers-utils",
3
- "version": "3.1.3",
3
+ "version": "4.0.0",
4
4
  "description": "Some utils for projects using '@feathersjs/feathers'",
5
5
  "author": "fratzinger",
6
6
  "repository": {
@@ -1,45 +1,98 @@
1
- import { filterQuery as plainFilterQuery } from "@feathersjs/adapter-commons";
1
+ import type { Query } from "@feathersjs/feathers";
2
2
 
3
- import type {
4
- FilterQueryOptions as PlainFilterQueryOptions,
5
- AdapterBase,
6
- } from "@feathersjs/adapter-commons";
3
+ type FilterQueryResult<Q extends Query> = {
4
+ $select: Q["$select"] extends any ? Q["$select"] : never;
5
+ $limit: Q["$limit"] extends any ? Q["$limit"] : never;
6
+ $skip: Q["$skip"] extends any ? Q["$skip"] : never;
7
+ $sort: Q["$sort"] extends any ? Q["$sort"] : never;
8
+ query: Omit<Q, "$select" | "$limit" | "$skip" | "$sort">;
9
+ };
7
10
 
8
- import type { Query } from "@feathersjs/feathers";
11
+ /**
12
+ * Extracts $select, $limit, $skip, $sort from a query and returns the rest as a query object.
13
+ *
14
+ * @param providedQuery
15
+ * @returns
16
+ */
17
+ export function filterQuery<Q extends Query>(
18
+ providedQuery?: Q,
19
+ ): FilterQueryResult<Q> {
20
+ providedQuery ??= {} as Q;
21
+ const { $select, $limit, $skip, $sort, ...query } = providedQuery;
9
22
 
10
- export interface FilterQueryOptions<T> {
11
- service?: AdapterBase<T>;
12
- operators?: PlainFilterQueryOptions["operators"];
13
- filters?: PlainFilterQueryOptions["filters"];
14
- }
23
+ const result: FilterQueryResult<Q> = { query } as any;
24
+
25
+ if ("$select" in providedQuery) {
26
+ result.$select = $select;
27
+ }
28
+
29
+ if ("$limit" in providedQuery) {
30
+ result.$limit = $limit;
31
+ }
32
+
33
+ if ("$skip" in providedQuery) {
34
+ result.$skip = $skip;
35
+ }
15
36
 
16
- export function filterQuery<T>(query: Query, _options?: FilterQueryOptions<T>) {
17
- query = query || {};
18
- _options = _options || {};
19
- const { service, ...options } = _options;
20
- if (service) {
21
- const operators = options.operators
22
- ? options.operators
23
- : service.options?.operators;
24
- const filters = options.filters
25
- ? options.filters
26
- : service.options?.filters;
27
- const optionsForFilterQuery: PlainFilterQueryOptions = {};
28
- if (operators) {
29
- optionsForFilterQuery.operators = operators;
30
- }
31
- if (filters) {
32
- optionsForFilterQuery.filters = filters;
33
- }
34
- if (
35
- service &&
36
- "filterQuery" in service &&
37
- typeof service.filterQuery === "function"
38
- ) {
39
- return service.filterQuery({ query }, optionsForFilterQuery);
40
- } else {
41
- return plainFilterQuery(query, optionsForFilterQuery);
42
- }
37
+ if ("$sort" in providedQuery) {
38
+ result.$sort = $sort;
43
39
  }
44
- return plainFilterQuery(query, options);
40
+
41
+ return result;
42
+ }
43
+
44
+ if (import.meta.vitest) {
45
+ const { it, expect } = import.meta.vitest;
46
+
47
+ it("should filter query", () => {
48
+ const query = {
49
+ $select: ["a"],
50
+ $limit: 10,
51
+ $skip: 10,
52
+ $sort: {
53
+ a: 1,
54
+ },
55
+ a: 1,
56
+ b: 2,
57
+ };
58
+
59
+ expect(filterQuery(query)).toEqual({
60
+ $select: ["a"],
61
+ $limit: 10,
62
+ $skip: 10,
63
+ $sort: {
64
+ a: 1,
65
+ },
66
+ query: {
67
+ a: 1,
68
+ b: 2,
69
+ },
70
+ });
71
+ });
72
+
73
+ it("should not include filters if not provided", () => {
74
+ const query = {
75
+ a: 1,
76
+ b: 2,
77
+ };
78
+
79
+ expect(filterQuery(query)).toEqual({
80
+ query: {
81
+ a: 1,
82
+ b: 2,
83
+ },
84
+ });
85
+ });
86
+
87
+ it("sets empty query object if empty object is provided", () => {
88
+ expect(filterQuery({})).toEqual({
89
+ query: {},
90
+ });
91
+ });
92
+
93
+ it("sets empty query object if undefined is provided", () => {
94
+ expect(filterQuery(undefined)).toEqual({
95
+ query: {},
96
+ });
97
+ });
45
98
  }
@@ -7,7 +7,6 @@ import {
7
7
  handleCircular,
8
8
  isQueryMoreExplicitThanQuery,
9
9
  makeDefaultOptions,
10
- moveProperty,
11
10
  } from "./utils";
12
11
  import type { MergeQueryOptions } from "./types";
13
12
  import { filterQuery } from "../filterQuery";
@@ -20,58 +19,19 @@ import { hasOwnProperty } from "../internal.utils";
20
19
  * @param _options
21
20
  * @returns Query
22
21
  */
23
- export function mergeQuery<T = any>(
22
+ export function mergeQuery(
24
23
  target: Query,
25
24
  source: Query,
26
- _options?: Partial<MergeQueryOptions<T>>,
25
+ _options?: Partial<MergeQueryOptions>,
27
26
  ): Query {
28
27
  const options = makeDefaultOptions(_options);
29
- const { filters: targetFilters, query: targetQuery } = filterQuery(target, {
30
- operators: options.operators,
31
- filters: options.filters,
32
- service: options.service,
33
- });
34
28
 
35
- moveProperty(targetFilters, targetQuery, "$or", "$and");
29
+ const { query: targetQuery, ...targetFilters } = filterQuery(target);
36
30
 
37
- if ("$limit" in target) {
38
- targetFilters.$limit = target.$limit;
39
- }
40
-
41
- let {
42
- // eslint-disable-next-line prefer-const
43
- filters: sourceFilters,
44
- query: sourceQuery,
45
- } = filterQuery(source, {
46
- operators: options.operators,
47
- filters: options.filters,
48
- service: options.service,
49
- });
50
-
51
- moveProperty(sourceFilters, sourceQuery, "$or", "$and");
52
-
53
- if (source.$limit) {
54
- sourceFilters.$limit = source.$limit;
55
- }
31
+ // eslint-disable-next-line prefer-const
32
+ let { query: sourceQuery, ...sourceFilters } = filterQuery(source);
56
33
 
57
34
  //#region filters
58
-
59
- if (
60
- target &&
61
- !hasOwnProperty(target, "$limit") &&
62
- hasOwnProperty(targetFilters, "$limit")
63
- ) {
64
- delete targetFilters.$limit;
65
- }
66
-
67
- if (
68
- source &&
69
- !hasOwnProperty(source, "$limit") &&
70
- hasOwnProperty(sourceFilters, "$limit")
71
- ) {
72
- delete sourceFilters.$limit;
73
- }
74
-
75
35
  handleArray(targetFilters, sourceFilters, ["$select"], options);
76
36
  // remaining filters
77
37
  delete sourceFilters["$select"];
@@ -1,5 +1,4 @@
1
1
  import type { Path } from "../../typesInternal";
2
- import type { FilterQueryOptions } from "../filterQuery";
3
2
 
4
3
  export type Handle =
5
4
  | "target"
@@ -15,7 +14,7 @@ export type ActionOnEmptyIntersect = (
15
14
  prependKey: Path,
16
15
  ) => void;
17
16
 
18
- export interface MergeQueryOptions<T> extends FilterQueryOptions<T> {
17
+ export interface MergeQueryOptions {
19
18
  defaultHandle: Handle;
20
19
  actionOnEmptyIntersect: ActionOnEmptyIntersect;
21
20
  useLogicalConjunction: boolean;
@@ -12,11 +12,11 @@ import { deepEqual as _isEqual } from "fast-equals";
12
12
  import type { Query } from "@feathersjs/feathers";
13
13
  import { hasOwnProperty } from "../internal.utils";
14
14
 
15
- export function handleArray<T>(
15
+ export function handleArray(
16
16
  target: Record<string, unknown>,
17
17
  source: Record<string, unknown>,
18
18
  key: Path,
19
- options: MergeQueryOptions<T>,
19
+ options: MergeQueryOptions,
20
20
  ): void {
21
21
  const targetVal = _get(target, key);
22
22
  const sourceVal = _get(source, key);
@@ -38,11 +38,11 @@ export function handleArray<T>(
38
38
  _set(target, key, arr);
39
39
  }
40
40
 
41
- export function handleCircular<T>(
41
+ export function handleCircular(
42
42
  target: Record<string, unknown>,
43
43
  source: Record<string, unknown>,
44
44
  prependKey: Path,
45
- options: MergeQueryOptions<T>,
45
+ options: MergeQueryOptions,
46
46
  ): void {
47
47
  if (target?.$or) {
48
48
  target.$or = cleanOr(target.$or as Record<string, unknown>[]);
@@ -257,10 +257,10 @@ export function handleCircular<T>(
257
257
  }
258
258
  }
259
259
 
260
- export function makeDefaultOptions<T>(
261
- options?: Partial<MergeQueryOptions<T>>,
262
- ): MergeQueryOptions<T> {
263
- options ??= {} as MergeQueryOptions<T>;
260
+ export function makeDefaultOptions(
261
+ options?: Partial<MergeQueryOptions>,
262
+ ): MergeQueryOptions {
263
+ options ??= {} as MergeQueryOptions;
264
264
  options.defaultHandle ??= "combine";
265
265
  options.useLogicalConjunction ??= false;
266
266
  options.actionOnEmptyIntersect ??= () => {
@@ -270,7 +270,7 @@ export function makeDefaultOptions<T>(
270
270
  if (options.defaultHandle === "intersect") {
271
271
  options.handle.$select = options.handle.$select || "intersectOrFull";
272
272
  }
273
- return options as MergeQueryOptions<T>;
273
+ return options as MergeQueryOptions;
274
274
  }
275
275
 
276
276
  export function moveProperty(