feathers-utils 5.0.2 → 5.2.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 (39) hide show
  1. package/README.md +4 -0
  2. package/dist/index.cjs +181 -26
  3. package/dist/index.d.cts +20 -5
  4. package/dist/index.d.mts +20 -5
  5. package/dist/index.d.ts +20 -5
  6. package/dist/index.mjs +175 -23
  7. package/package.json +18 -20
  8. package/src/filters/object.ts +2 -2
  9. package/src/hooks/checkMulti.ts +151 -0
  10. package/src/hooks/from-client-for-server/common.ts +1 -0
  11. package/src/hooks/from-client-for-server/index.ts +2 -0
  12. package/src/hooks/from-client-for-server/paramsForServer.ts +100 -0
  13. package/src/hooks/from-client-for-server/paramsFromClient.ts +105 -0
  14. package/src/hooks/index.ts +1 -0
  15. package/src/hooks/setData.ts +509 -0
  16. package/src/mixins/debounce-mixin/DebouncedStore.ts +1 -9
  17. package/src/mixins/debounce-mixin/debounceMixin.ts +2 -1
  18. package/src/mixins/debounce-mixin/utils.ts +10 -0
  19. package/src/types.ts +1 -0
  20. package/src/utils/_utils.internal.ts +16 -0
  21. package/src/utils/deflattenQuery.ts +109 -0
  22. package/src/utils/filterQuery.ts +112 -40
  23. package/src/utils/flattenQuery.ts +198 -0
  24. package/src/utils/getItemsIsArray.ts +279 -0
  25. package/src/utils/getPaginate.ts +74 -1
  26. package/src/utils/index.ts +2 -0
  27. package/src/utils/isMulti.ts +51 -0
  28. package/src/utils/isPaginated.ts +72 -0
  29. package/src/utils/markHookForSkip.ts +411 -0
  30. package/src/utils/mergeQuery/mergeArrays.ts +68 -0
  31. package/src/utils/mergeQuery/mergeQuery.ts +464 -3
  32. package/src/utils/mergeQuery/types.ts +0 -1
  33. package/src/utils/mergeQuery/utils.ts +93 -5
  34. package/src/utils/pushSet.ts +67 -1
  35. package/src/utils/setQueryKeySafely.ts +169 -4
  36. package/src/utils/setResultEmpty.ts +260 -0
  37. package/src/utils/shouldSkip.ts +121 -0
  38. package/src/utils/validateQueryProperty.ts +3 -6
  39. package/src/utils/internal.utils.ts +0 -9
package/README.md CHANGED
@@ -25,6 +25,8 @@ npm i feathers-utils
25
25
  - `createRelated`: simply create related items from a hook.
26
26
  - `forEach`
27
27
  - `onDelete`: simply remove/set null related items from a hook.
28
+ - `paramsForServer`
29
+ - `paramsFromClient`
28
30
  - `parseFields`
29
31
  - `removeRelated`: simple remove related items from a hook. Basically `cascade` at feathers level.
30
32
  - `runPerItem`: run a function for every item. Meant for `multi:true`.
@@ -38,6 +40,8 @@ npm i feathers-utils
38
40
 
39
41
  - `defineHooks`
40
42
  - `filterQuery`
43
+ - `flattenQuery`
44
+ - `deflattenQuery`
41
45
  - `getItemsIsArray(context)`: returns `{ items: any[], isArray: boolean }`
42
46
  - `getPaginate`
43
47
  - `isMulti(context) => Boolean`: returns true, if `find`, `create/patch/remove`: multi
package/dist/index.cjs CHANGED
@@ -1,30 +1,23 @@
1
1
  'use strict';
2
2
 
3
3
  const errors = require('@feathersjs/errors');
4
- const _isEqual = require('lodash/isEqual.js');
4
+ const fastEquals = require('fast-equals');
5
5
  const _get = require('lodash/get.js');
6
6
  const _set = require('lodash/set.js');
7
7
  const _merge = require('lodash/merge.js');
8
- const _isEmpty = require('lodash/isEmpty.js');
9
8
  const _has = require('lodash/has.js');
10
9
  const _uniqWith = require('lodash/uniqWith.js');
11
- const fastEquals = require('fast-equals');
12
- const commons = require('@feathersjs/commons');
13
10
  const feathersHooksCommon = require('feathers-hooks-common');
14
11
  const _debounce = require('lodash/debounce.js');
15
- const _isObject = require('lodash/isObject.js');
16
12
 
17
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
18
14
 
19
- const _isEqual__default = /*#__PURE__*/_interopDefaultCompat(_isEqual);
20
15
  const _get__default = /*#__PURE__*/_interopDefaultCompat(_get);
21
16
  const _set__default = /*#__PURE__*/_interopDefaultCompat(_set);
22
17
  const _merge__default = /*#__PURE__*/_interopDefaultCompat(_merge);
23
- const _isEmpty__default = /*#__PURE__*/_interopDefaultCompat(_isEmpty);
24
18
  const _has__default = /*#__PURE__*/_interopDefaultCompat(_has);
25
19
  const _uniqWith__default = /*#__PURE__*/_interopDefaultCompat(_uniqWith);
26
20
  const _debounce__default = /*#__PURE__*/_interopDefaultCompat(_debounce);
27
- const _isObject__default = /*#__PURE__*/_interopDefaultCompat(_isObject);
28
21
 
29
22
  function defineHooks(hooks) {
30
23
  return hooks;
@@ -48,6 +41,23 @@ function filterQuery(providedQuery) {
48
41
  }
49
42
  return result;
50
43
  }
44
+ function reassembleQuery(query) {
45
+ const { $select, $limit, $skip, $sort, query: rest } = query;
46
+ const result = rest;
47
+ if ($select !== void 0) {
48
+ result.$select = $select;
49
+ }
50
+ if ($limit !== void 0) {
51
+ result.$limit = $limit;
52
+ }
53
+ if ($skip !== void 0) {
54
+ result.$skip = $skip;
55
+ }
56
+ if ($sort !== void 0) {
57
+ result.$sort = $sort;
58
+ }
59
+ return result;
60
+ }
51
61
 
52
62
  const getItemsIsArray = (context, options) => {
53
63
  const { from = "automatic" } = options || {};
@@ -72,7 +82,9 @@ const getItemsIsArray = (context, options) => {
72
82
  const hasOwnProperty = (obj, ...keys) => {
73
83
  return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x));
74
84
  };
75
- const isPlainObject$1 = (value) => value && [void 0, Object].includes(value.constructor);
85
+ const isObject = (item) => !!item && typeof item === "object" && !Array.isArray(item);
86
+ const isPlainObject = (value) => isObject(value) && value.constructor === {}.constructor;
87
+ const isEmpty = (obj) => [Object, Array].includes((obj || {}).constructor) && !Object.keys(obj || {}).length;
76
88
 
77
89
  const getPaginate = (context) => {
78
90
  if (hasOwnProperty(context.params, "paginate")) {
@@ -120,7 +132,7 @@ const pushSet = (obj, path, val, options) => {
120
132
  _set__default(obj, path, arr);
121
133
  return arr;
122
134
  } else {
123
- if (options.unique && arr.some((x) => _isEqual__default(x, val))) {
135
+ if (options.unique && arr.some((x) => fastEquals.deepEqual(x, val))) {
124
136
  return arr;
125
137
  }
126
138
  arr.push(val);
@@ -403,7 +415,7 @@ function cleanOr(target) {
403
415
  if (!target || !Array.isArray(target) || target.length <= 0) {
404
416
  return target;
405
417
  }
406
- if (target.some((x) => _isEmpty__default(x))) {
418
+ if (target.some((x) => isEmpty(x))) {
407
419
  return void 0;
408
420
  } else {
409
421
  return arrayWithoutDuplicates(target);
@@ -413,10 +425,10 @@ function cleanAnd(target) {
413
425
  if (!target || !Array.isArray(target) || target.length <= 0) {
414
426
  return target;
415
427
  }
416
- if (target.every((x) => _isEmpty__default(x))) {
428
+ if (target.every((x) => isEmpty(x))) {
417
429
  return void 0;
418
430
  } else {
419
- target = target.filter((x) => !_isEmpty__default(x));
431
+ target = target.filter((x) => !isEmpty(x));
420
432
  return arrayWithoutDuplicates(target);
421
433
  }
422
434
  }
@@ -482,7 +494,7 @@ function mergeQuery(target, source, _options) {
482
494
  ...sourceQuery
483
495
  };
484
496
  }
485
- if (options.useLogicalConjunction && (options.defaultHandle === "combine" || options.defaultHandle === "intersect") && !_isEmpty__default(targetQuery)) {
497
+ if (options.useLogicalConjunction && (options.defaultHandle === "combine" || options.defaultHandle === "intersect") && !isEmpty(targetQuery)) {
486
498
  const logicalOp = options.defaultHandle === "combine" ? "$or" : "$and";
487
499
  if (hasOwnProperty(sourceQuery, logicalOp)) {
488
500
  const andOr = sourceQuery[logicalOp];
@@ -523,7 +535,7 @@ const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
523
535
  }
524
536
  return params;
525
537
  }
526
- if (isPlainObject$1(params.query[key]) && !(operator in params.query[key])) {
538
+ if (isPlainObject(params.query[key]) && !(operator in params.query[key])) {
527
539
  params.query[key][operator] = value;
528
540
  } else {
529
541
  (_a = params.query).$and ?? (_a.$and = []);
@@ -588,9 +600,8 @@ const toJSON = (context) => {
588
600
  return context;
589
601
  };
590
602
 
591
- const isPlainObject = (value) => commons._.isObject(value) && value.constructor === {}.constructor;
592
603
  const validateQueryProperty = (query, operators = []) => {
593
- if (!isPlainObject(query)) {
604
+ if (!isObject(query)) {
594
605
  return query;
595
606
  }
596
607
  for (const key of Object.keys(query)) {
@@ -598,7 +609,7 @@ const validateQueryProperty = (query, operators = []) => {
598
609
  throw new errors.BadRequest(`Invalid query parameter ${key}`, query);
599
610
  }
600
611
  const value = query[key];
601
- if (isPlainObject(value)) {
612
+ if (isObject(value)) {
602
613
  query[key] = validateQueryProperty(value, operators);
603
614
  }
604
615
  }
@@ -631,6 +642,72 @@ function optimizeBatchPatch(items, options) {
631
642
  });
632
643
  }
633
644
 
645
+ function flattenQuery(q) {
646
+ if (Array.isArray(q)) {
647
+ return q.map(flattenQuery);
648
+ }
649
+ if (!isObject(q)) {
650
+ return q;
651
+ }
652
+ const { query, $limit, $select, $skip, $sort } = filterQuery(q);
653
+ const res = {};
654
+ function step(object, options) {
655
+ const { prev = [], result = res } = options ?? {};
656
+ Object.keys(object).forEach((key) => {
657
+ const value = object[key];
658
+ if (Array.isArray(value)) {
659
+ const newValues = value.map(
660
+ (v) => step(v, {
661
+ result: {}
662
+ })
663
+ );
664
+ _set__default(result, [...prev, key], newValues);
665
+ return;
666
+ }
667
+ if (key.startsWith("$")) {
668
+ _set__default(result, [...prev, key], value);
669
+ return;
670
+ }
671
+ const newKey = !prev.length ? [key] : [...prev.slice(0, -1), `${prev[prev.length - 1]}.${key}`];
672
+ if (!isObject(value)) {
673
+ _set__default(result, newKey, value);
674
+ return;
675
+ } else {
676
+ step(value, {
677
+ prev: newKey,
678
+ result
679
+ });
680
+ return;
681
+ }
682
+ });
683
+ return result;
684
+ }
685
+ return reassembleQuery({
686
+ $limit,
687
+ $select,
688
+ $skip,
689
+ $sort,
690
+ query: step(query)
691
+ });
692
+ }
693
+
694
+ function deflattenQuery(query) {
695
+ const result = {};
696
+ Object.keys(query).forEach((key) => {
697
+ const value = query[key];
698
+ if (Array.isArray(value)) {
699
+ _set__default(result, key, value.map(deflattenQuery));
700
+ return;
701
+ }
702
+ if (isObject(value)) {
703
+ _set__default(result, key, deflattenQuery(value));
704
+ return;
705
+ }
706
+ _set__default(result, key, query[key]);
707
+ });
708
+ return result;
709
+ }
710
+
634
711
  function checkMulti() {
635
712
  return (context) => {
636
713
  if (shouldSkip("checkMulti", context)) {
@@ -877,12 +954,77 @@ function setData(from, to, _options) {
877
954
  };
878
955
  }
879
956
 
880
- var __defProp = Object.defineProperty;
881
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
882
- var __publicField = (obj, key, value) => {
883
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
884
- return value;
885
- };
957
+ const FROM_CLIENT_FOR_SERVER_DEFAULT_KEY = "_$client";
958
+
959
+ function defineParamsForServer(keyToHide) {
960
+ return function paramsForServer2(...whitelist) {
961
+ return (context) => {
962
+ let clonedParams;
963
+ Object.keys(context.params).forEach((key) => {
964
+ if (key === "query") {
965
+ return;
966
+ }
967
+ if (whitelist.includes(key)) {
968
+ if (!clonedParams) {
969
+ clonedParams = {
970
+ ...context.params,
971
+ query: {
972
+ ...context.params.query
973
+ }
974
+ };
975
+ }
976
+ if (!clonedParams.query[keyToHide]) {
977
+ clonedParams.query[keyToHide] = {};
978
+ }
979
+ clonedParams.query[keyToHide][key] = clonedParams[key];
980
+ delete clonedParams[key];
981
+ }
982
+ });
983
+ if (clonedParams) {
984
+ context.params = clonedParams;
985
+ }
986
+ return context;
987
+ };
988
+ };
989
+ }
990
+ const paramsForServer = defineParamsForServer(
991
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
992
+ );
993
+
994
+ function defineParamsFromClient(keyToHide) {
995
+ return function paramsFromClient2(...whitelist) {
996
+ return (context) => {
997
+ if (!context.params?.query?.[keyToHide] || typeof context.params.query[keyToHide] !== "object") {
998
+ return context;
999
+ }
1000
+ const params = {
1001
+ ...context.params,
1002
+ query: {
1003
+ ...context.params.query,
1004
+ [keyToHide]: {
1005
+ ...context.params.query[keyToHide]
1006
+ }
1007
+ }
1008
+ };
1009
+ const client = params.query[keyToHide];
1010
+ whitelist.forEach((key) => {
1011
+ if (key in client) {
1012
+ params[key] = client[key];
1013
+ delete client[key];
1014
+ }
1015
+ });
1016
+ if (Object.keys(client).length === 0) {
1017
+ delete params.query[keyToHide];
1018
+ }
1019
+ context.params = params;
1020
+ return context;
1021
+ };
1022
+ };
1023
+ }
1024
+ const paramsFromClient = defineParamsFromClient(
1025
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
1026
+ );
1027
+
886
1028
  const makeDefaultOptions = () => {
887
1029
  return {
888
1030
  leading: false,
@@ -891,6 +1033,13 @@ const makeDefaultOptions = () => {
891
1033
  wait: 100
892
1034
  };
893
1035
  };
1036
+
1037
+ var __defProp = Object.defineProperty;
1038
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1039
+ var __publicField = (obj, key, value) => {
1040
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1041
+ return value;
1042
+ };
894
1043
  class DebouncedStore {
895
1044
  constructor(app, options) {
896
1045
  __publicField(this, "_app");
@@ -983,7 +1132,7 @@ const filterArray = (...keys) => {
983
1132
  };
984
1133
 
985
1134
  const filterQueryObject = (key) => (obj, { operators }) => {
986
- if (obj && !_isObject__default(obj)) {
1135
+ if (obj && !isObject(obj)) {
987
1136
  throw new Error(
988
1137
  `Invalid query parameter: '${key}'. It has to be an object`
989
1138
  );
@@ -1003,22 +1152,28 @@ exports.checkMulti = checkMulti;
1003
1152
  exports.createRelated = createRelated;
1004
1153
  exports.debounceMixin = debounceMixin;
1005
1154
  exports.defineHooks = defineHooks;
1155
+ exports.defineParamsForServer = defineParamsForServer;
1156
+ exports.defineParamsFromClient = defineParamsFromClient;
1157
+ exports.deflattenQuery = deflattenQuery;
1006
1158
  exports.filterArray = filterArray;
1007
1159
  exports.filterObject = filterObject;
1008
1160
  exports.filterQuery = filterQuery;
1161
+ exports.flattenQuery = flattenQuery;
1009
1162
  exports.forEach = forEach;
1010
1163
  exports.getItemsIsArray = getItemsIsArray;
1011
1164
  exports.getPaginate = getPaginate;
1012
1165
  exports.isMulti = isMulti;
1013
1166
  exports.isPaginated = isPaginated;
1014
- exports.makeDefaultOptions = makeDefaultOptions;
1015
1167
  exports.markHookForSkip = markHookForSkip;
1016
1168
  exports.mergeArrays = mergeArrays;
1017
1169
  exports.mergeQuery = mergeQuery;
1018
1170
  exports.onDelete = onDelete;
1019
1171
  exports.optimizeBatchPatch = optimizeBatchPatch;
1172
+ exports.paramsForServer = paramsForServer;
1173
+ exports.paramsFromClient = paramsFromClient;
1020
1174
  exports.parseFields = parseFields;
1021
1175
  exports.pushSet = pushSet;
1176
+ exports.reassembleQuery = reassembleQuery;
1022
1177
  exports.removeRelated = removeRelated;
1023
1178
  exports.runPerItem = runPerItem;
1024
1179
  exports.setData = setData;
package/dist/index.d.cts CHANGED
@@ -102,6 +102,18 @@ interface HookSetDataOptions {
102
102
  */
103
103
  declare function setData<H extends HookContext = HookContext>(from: PropertyPath, to: PropertyPath, _options?: HookSetDataOptions): (context: H) => H;
104
104
 
105
+ declare function defineParamsForServer(keyToHide: string): (...whitelist: string[]) => <H extends HookContext<_feathersjs_feathers.Application<any, any>, any>>(context: H) => H;
106
+ /**
107
+ * a hook to move params to query._$client
108
+ * the server only receives 'query' from params. All other params are ignored.
109
+ * So, to use `$populateParams` on the server, we need to move the params to query._$client
110
+ * the server will move them back to params
111
+ */
112
+ declare const paramsForServer: (...whitelist: string[]) => <H extends HookContext<_feathersjs_feathers.Application<any, any>, any>>(context: H) => H;
113
+
114
+ declare function defineParamsFromClient(keyToHide: string): (...whitelist: string[]) => (context: HookContext) => HookContext;
115
+ declare const paramsFromClient: (...whitelist: string[]) => (context: HookContext) => HookContext;
116
+
105
117
  interface InitDebounceMixinOptions {
106
118
  default: Partial<DebouncedStoreOptions>;
107
119
  blacklist: string[];
@@ -115,7 +127,6 @@ interface DebouncedStoreOptions {
115
127
  wait: number;
116
128
  }
117
129
 
118
- declare const makeDefaultOptions: () => DebouncedStoreOptions;
119
130
  type DebouncedService<T = any> = T & {
120
131
  debouncedStore: DebouncedStore;
121
132
  };
@@ -142,7 +153,7 @@ declare function defineHooks<A extends Application = Application, S = {
142
153
  remove: any;
143
154
  }, Options = HookOptions<A, S>>(hooks: Options): Options;
144
155
 
145
- type FilterQueryResult<Q extends Query> = {
156
+ type FilterQueryResult<Q extends Query = Query> = {
146
157
  $select: Q["$select"] extends any ? Q["$select"] : never;
147
158
  $limit: Q["$limit"] extends any ? Q["$limit"] : never;
148
159
  $skip: Q["$skip"] extends any ? Q["$skip"] : never;
@@ -156,6 +167,7 @@ type FilterQueryResult<Q extends Query> = {
156
167
  * @returns
157
168
  */
158
169
  declare function filterQuery<Q extends Query>(providedQuery?: Q): FilterQueryResult<Q>;
170
+ declare function reassembleQuery(query: FilterQueryResult): Query;
159
171
 
160
172
  /**
161
173
  * util to get paginate options from context
@@ -187,7 +199,6 @@ declare const isPaginated: <H extends HookContext<_feathersjs_feathers.Applicati
187
199
  declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H;
188
200
 
189
201
  type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
190
- type FirstLast = "first" | "last";
191
202
  type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
192
203
  interface MergeQueryOptions {
193
204
  defaultHandle: Handle;
@@ -220,7 +231,7 @@ declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val:
220
231
  type SetQueryKeySafelyOptions = {
221
232
  mutate?: boolean;
222
233
  };
223
- declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
234
+ declare const setQueryKeySafely: (params: Params, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => Params;
224
235
 
225
236
  /**
226
237
  * util to set `context.result` to an empty array or object, depending on the hook type
@@ -248,6 +259,10 @@ type OptimizeBatchPatchOptions = {
248
259
  type OptimizeBatchPatchResultItem<T = Record<string, unknown>, P = Params> = [Id, T, P | undefined];
249
260
  declare function optimizeBatchPatch<T extends Record<string, unknown>, P extends Params>(items: Map<Id, T>, options?: OptimizeBatchPatchOptions): OptimizeBatchPatchResultItem<T, P>[];
250
261
 
262
+ declare function flattenQuery(q: Query): any;
263
+
264
+ declare function deflattenQuery(query: Query): Query;
265
+
251
266
  declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
252
267
 
253
268
  declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
@@ -298,4 +313,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
298
313
  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;
299
314
  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;
300
315
 
301
- 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
316
+ export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, defineParamsForServer, defineParamsFromClient, deflattenQuery, filterArray, filterObject, filterQuery, flattenQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, reassembleQuery, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/dist/index.d.mts CHANGED
@@ -102,6 +102,18 @@ interface HookSetDataOptions {
102
102
  */
103
103
  declare function setData<H extends HookContext = HookContext>(from: PropertyPath, to: PropertyPath, _options?: HookSetDataOptions): (context: H) => H;
104
104
 
105
+ declare function defineParamsForServer(keyToHide: string): (...whitelist: string[]) => <H extends HookContext<_feathersjs_feathers.Application<any, any>, any>>(context: H) => H;
106
+ /**
107
+ * a hook to move params to query._$client
108
+ * the server only receives 'query' from params. All other params are ignored.
109
+ * So, to use `$populateParams` on the server, we need to move the params to query._$client
110
+ * the server will move them back to params
111
+ */
112
+ declare const paramsForServer: (...whitelist: string[]) => <H extends HookContext<_feathersjs_feathers.Application<any, any>, any>>(context: H) => H;
113
+
114
+ declare function defineParamsFromClient(keyToHide: string): (...whitelist: string[]) => (context: HookContext) => HookContext;
115
+ declare const paramsFromClient: (...whitelist: string[]) => (context: HookContext) => HookContext;
116
+
105
117
  interface InitDebounceMixinOptions {
106
118
  default: Partial<DebouncedStoreOptions>;
107
119
  blacklist: string[];
@@ -115,7 +127,6 @@ interface DebouncedStoreOptions {
115
127
  wait: number;
116
128
  }
117
129
 
118
- declare const makeDefaultOptions: () => DebouncedStoreOptions;
119
130
  type DebouncedService<T = any> = T & {
120
131
  debouncedStore: DebouncedStore;
121
132
  };
@@ -142,7 +153,7 @@ declare function defineHooks<A extends Application = Application, S = {
142
153
  remove: any;
143
154
  }, Options = HookOptions<A, S>>(hooks: Options): Options;
144
155
 
145
- type FilterQueryResult<Q extends Query> = {
156
+ type FilterQueryResult<Q extends Query = Query> = {
146
157
  $select: Q["$select"] extends any ? Q["$select"] : never;
147
158
  $limit: Q["$limit"] extends any ? Q["$limit"] : never;
148
159
  $skip: Q["$skip"] extends any ? Q["$skip"] : never;
@@ -156,6 +167,7 @@ type FilterQueryResult<Q extends Query> = {
156
167
  * @returns
157
168
  */
158
169
  declare function filterQuery<Q extends Query>(providedQuery?: Q): FilterQueryResult<Q>;
170
+ declare function reassembleQuery(query: FilterQueryResult): Query;
159
171
 
160
172
  /**
161
173
  * util to get paginate options from context
@@ -187,7 +199,6 @@ declare const isPaginated: <H extends HookContext<_feathersjs_feathers.Applicati
187
199
  declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H;
188
200
 
189
201
  type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
190
- type FirstLast = "first" | "last";
191
202
  type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
192
203
  interface MergeQueryOptions {
193
204
  defaultHandle: Handle;
@@ -220,7 +231,7 @@ declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val:
220
231
  type SetQueryKeySafelyOptions = {
221
232
  mutate?: boolean;
222
233
  };
223
- declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
234
+ declare const setQueryKeySafely: (params: Params, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => Params;
224
235
 
225
236
  /**
226
237
  * util to set `context.result` to an empty array or object, depending on the hook type
@@ -248,6 +259,10 @@ type OptimizeBatchPatchOptions = {
248
259
  type OptimizeBatchPatchResultItem<T = Record<string, unknown>, P = Params> = [Id, T, P | undefined];
249
260
  declare function optimizeBatchPatch<T extends Record<string, unknown>, P extends Params>(items: Map<Id, T>, options?: OptimizeBatchPatchOptions): OptimizeBatchPatchResultItem<T, P>[];
250
261
 
262
+ declare function flattenQuery(q: Query): any;
263
+
264
+ declare function deflattenQuery(query: Query): Query;
265
+
251
266
  declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
252
267
 
253
268
  declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
@@ -298,4 +313,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
298
313
  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;
299
314
  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;
300
315
 
301
- 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
316
+ export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, defineParamsForServer, defineParamsFromClient, deflattenQuery, filterArray, filterObject, filterQuery, flattenQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, reassembleQuery, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/dist/index.d.ts CHANGED
@@ -102,6 +102,18 @@ interface HookSetDataOptions {
102
102
  */
103
103
  declare function setData<H extends HookContext = HookContext>(from: PropertyPath, to: PropertyPath, _options?: HookSetDataOptions): (context: H) => H;
104
104
 
105
+ declare function defineParamsForServer(keyToHide: string): (...whitelist: string[]) => <H extends HookContext<_feathersjs_feathers.Application<any, any>, any>>(context: H) => H;
106
+ /**
107
+ * a hook to move params to query._$client
108
+ * the server only receives 'query' from params. All other params are ignored.
109
+ * So, to use `$populateParams` on the server, we need to move the params to query._$client
110
+ * the server will move them back to params
111
+ */
112
+ declare const paramsForServer: (...whitelist: string[]) => <H extends HookContext<_feathersjs_feathers.Application<any, any>, any>>(context: H) => H;
113
+
114
+ declare function defineParamsFromClient(keyToHide: string): (...whitelist: string[]) => (context: HookContext) => HookContext;
115
+ declare const paramsFromClient: (...whitelist: string[]) => (context: HookContext) => HookContext;
116
+
105
117
  interface InitDebounceMixinOptions {
106
118
  default: Partial<DebouncedStoreOptions>;
107
119
  blacklist: string[];
@@ -115,7 +127,6 @@ interface DebouncedStoreOptions {
115
127
  wait: number;
116
128
  }
117
129
 
118
- declare const makeDefaultOptions: () => DebouncedStoreOptions;
119
130
  type DebouncedService<T = any> = T & {
120
131
  debouncedStore: DebouncedStore;
121
132
  };
@@ -142,7 +153,7 @@ declare function defineHooks<A extends Application = Application, S = {
142
153
  remove: any;
143
154
  }, Options = HookOptions<A, S>>(hooks: Options): Options;
144
155
 
145
- type FilterQueryResult<Q extends Query> = {
156
+ type FilterQueryResult<Q extends Query = Query> = {
146
157
  $select: Q["$select"] extends any ? Q["$select"] : never;
147
158
  $limit: Q["$limit"] extends any ? Q["$limit"] : never;
148
159
  $skip: Q["$skip"] extends any ? Q["$skip"] : never;
@@ -156,6 +167,7 @@ type FilterQueryResult<Q extends Query> = {
156
167
  * @returns
157
168
  */
158
169
  declare function filterQuery<Q extends Query>(providedQuery?: Q): FilterQueryResult<Q>;
170
+ declare function reassembleQuery(query: FilterQueryResult): Query;
159
171
 
160
172
  /**
161
173
  * util to get paginate options from context
@@ -187,7 +199,6 @@ declare const isPaginated: <H extends HookContext<_feathersjs_feathers.Applicati
187
199
  declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H;
188
200
 
189
201
  type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
190
- type FirstLast = "first" | "last";
191
202
  type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
192
203
  interface MergeQueryOptions {
193
204
  defaultHandle: Handle;
@@ -220,7 +231,7 @@ declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val:
220
231
  type SetQueryKeySafelyOptions = {
221
232
  mutate?: boolean;
222
233
  };
223
- declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
234
+ declare const setQueryKeySafely: (params: Params, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => Params;
224
235
 
225
236
  /**
226
237
  * util to set `context.result` to an empty array or object, depending on the hook type
@@ -248,6 +259,10 @@ type OptimizeBatchPatchOptions = {
248
259
  type OptimizeBatchPatchResultItem<T = Record<string, unknown>, P = Params> = [Id, T, P | undefined];
249
260
  declare function optimizeBatchPatch<T extends Record<string, unknown>, P extends Params>(items: Map<Id, T>, options?: OptimizeBatchPatchOptions): OptimizeBatchPatchResultItem<T, P>[];
250
261
 
262
+ declare function flattenQuery(q: Query): any;
263
+
264
+ declare function deflattenQuery(query: Query): Query;
265
+
251
266
  declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
252
267
 
253
268
  declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
@@ -298,4 +313,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
298
313
  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;
299
314
  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;
300
315
 
301
- 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
316
+ export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, defineParamsForServer, defineParamsFromClient, deflattenQuery, filterArray, filterObject, filterQuery, flattenQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, reassembleQuery, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };