feathers-utils 5.0.2 → 5.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.
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`.
package/dist/index.cjs CHANGED
@@ -877,6 +877,77 @@ function setData(from, to, _options) {
877
877
  };
878
878
  }
879
879
 
880
+ const FROM_CLIENT_FOR_SERVER_DEFAULT_KEY = "_$client";
881
+
882
+ function defineParamsForServer(keyToHide) {
883
+ return function paramsForServer2(...whitelist) {
884
+ return (context) => {
885
+ let clonedParams;
886
+ Object.keys(context.params).forEach((key) => {
887
+ if (key === "query") {
888
+ return;
889
+ }
890
+ if (whitelist.includes(key)) {
891
+ if (!clonedParams) {
892
+ clonedParams = {
893
+ ...context.params,
894
+ query: {
895
+ ...context.params.query
896
+ }
897
+ };
898
+ }
899
+ if (!clonedParams.query[keyToHide]) {
900
+ clonedParams.query[keyToHide] = {};
901
+ }
902
+ clonedParams.query[keyToHide][key] = clonedParams[key];
903
+ delete clonedParams[key];
904
+ }
905
+ });
906
+ if (clonedParams) {
907
+ context.params = clonedParams;
908
+ }
909
+ return context;
910
+ };
911
+ };
912
+ }
913
+ const paramsForServer = defineParamsForServer(
914
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
915
+ );
916
+
917
+ function defineParamsFromClient(keyToHide) {
918
+ return function paramsFromClient2(...whitelist) {
919
+ return (context) => {
920
+ if (!context.params?.query?.[keyToHide] || typeof context.params.query[keyToHide] !== "object") {
921
+ return context;
922
+ }
923
+ const params = {
924
+ ...context.params,
925
+ query: {
926
+ ...context.params.query,
927
+ [keyToHide]: {
928
+ ...context.params.query[keyToHide]
929
+ }
930
+ }
931
+ };
932
+ const client = params.query[keyToHide];
933
+ whitelist.forEach((key) => {
934
+ if (key in client) {
935
+ params[key] = client[key];
936
+ delete client[key];
937
+ }
938
+ });
939
+ if (Object.keys(client).length === 0) {
940
+ delete params.query[keyToHide];
941
+ }
942
+ context.params = params;
943
+ return context;
944
+ };
945
+ };
946
+ }
947
+ const paramsFromClient = defineParamsFromClient(
948
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
949
+ );
950
+
880
951
  var __defProp = Object.defineProperty;
881
952
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
882
953
  var __publicField = (obj, key, value) => {
@@ -1003,6 +1074,8 @@ exports.checkMulti = checkMulti;
1003
1074
  exports.createRelated = createRelated;
1004
1075
  exports.debounceMixin = debounceMixin;
1005
1076
  exports.defineHooks = defineHooks;
1077
+ exports.defineParamsForServer = defineParamsForServer;
1078
+ exports.defineParamsFromClient = defineParamsFromClient;
1006
1079
  exports.filterArray = filterArray;
1007
1080
  exports.filterObject = filterObject;
1008
1081
  exports.filterQuery = filterQuery;
@@ -1017,6 +1090,8 @@ exports.mergeArrays = mergeArrays;
1017
1090
  exports.mergeQuery = mergeQuery;
1018
1091
  exports.onDelete = onDelete;
1019
1092
  exports.optimizeBatchPatch = optimizeBatchPatch;
1093
+ exports.paramsForServer = paramsForServer;
1094
+ exports.paramsFromClient = paramsFromClient;
1020
1095
  exports.parseFields = parseFields;
1021
1096
  exports.pushSet = pushSet;
1022
1097
  exports.removeRelated = removeRelated;
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[];
@@ -298,4 +310,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
298
310
  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
311
  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
312
 
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 };
313
+ 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, defineParamsForServer, defineParamsFromClient, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, 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[];
@@ -298,4 +310,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
298
310
  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
311
  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
312
 
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 };
313
+ 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, defineParamsForServer, defineParamsFromClient, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, 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[];
@@ -298,4 +310,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
298
310
  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
311
  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
312
 
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 };
313
+ 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, defineParamsForServer, defineParamsFromClient, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/dist/index.mjs CHANGED
@@ -863,6 +863,77 @@ function setData(from, to, _options) {
863
863
  };
864
864
  }
865
865
 
866
+ const FROM_CLIENT_FOR_SERVER_DEFAULT_KEY = "_$client";
867
+
868
+ function defineParamsForServer(keyToHide) {
869
+ return function paramsForServer2(...whitelist) {
870
+ return (context) => {
871
+ let clonedParams;
872
+ Object.keys(context.params).forEach((key) => {
873
+ if (key === "query") {
874
+ return;
875
+ }
876
+ if (whitelist.includes(key)) {
877
+ if (!clonedParams) {
878
+ clonedParams = {
879
+ ...context.params,
880
+ query: {
881
+ ...context.params.query
882
+ }
883
+ };
884
+ }
885
+ if (!clonedParams.query[keyToHide]) {
886
+ clonedParams.query[keyToHide] = {};
887
+ }
888
+ clonedParams.query[keyToHide][key] = clonedParams[key];
889
+ delete clonedParams[key];
890
+ }
891
+ });
892
+ if (clonedParams) {
893
+ context.params = clonedParams;
894
+ }
895
+ return context;
896
+ };
897
+ };
898
+ }
899
+ const paramsForServer = defineParamsForServer(
900
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
901
+ );
902
+
903
+ function defineParamsFromClient(keyToHide) {
904
+ return function paramsFromClient2(...whitelist) {
905
+ return (context) => {
906
+ if (!context.params?.query?.[keyToHide] || typeof context.params.query[keyToHide] !== "object") {
907
+ return context;
908
+ }
909
+ const params = {
910
+ ...context.params,
911
+ query: {
912
+ ...context.params.query,
913
+ [keyToHide]: {
914
+ ...context.params.query[keyToHide]
915
+ }
916
+ }
917
+ };
918
+ const client = params.query[keyToHide];
919
+ whitelist.forEach((key) => {
920
+ if (key in client) {
921
+ params[key] = client[key];
922
+ delete client[key];
923
+ }
924
+ });
925
+ if (Object.keys(client).length === 0) {
926
+ delete params.query[keyToHide];
927
+ }
928
+ context.params = params;
929
+ return context;
930
+ };
931
+ };
932
+ }
933
+ const paramsFromClient = defineParamsFromClient(
934
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
935
+ );
936
+
866
937
  var __defProp = Object.defineProperty;
867
938
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
868
939
  var __publicField = (obj, key, value) => {
@@ -984,4 +1055,4 @@ const filterObject = (...keys) => {
984
1055
  return result;
985
1056
  };
986
1057
 
987
- export { DebouncedStore, 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 };
1058
+ export { DebouncedStore, checkMulti, createRelated, debounceMixin, defineHooks, defineParamsForServer, defineParamsFromClient, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feathers-utils",
3
- "version": "5.0.2",
3
+ "version": "5.1.0",
4
4
  "description": "Some utils for projects using '@feathersjs/feathers'",
5
5
  "author": "fratzinger",
6
6
  "repository": {
@@ -0,0 +1 @@
1
+ export const FROM_CLIENT_FOR_SERVER_DEFAULT_KEY = "_$client" as const;
@@ -0,0 +1,2 @@
1
+ export * from "./paramsForServer";
2
+ export * from "./paramsFromClient";
@@ -0,0 +1,100 @@
1
+ import type { HookContext } from "@feathersjs/feathers";
2
+ import { FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } from "./common";
3
+
4
+ export function defineParamsForServer(keyToHide: string) {
5
+ return function paramsForServer(...whitelist: string[]) {
6
+ return <H extends HookContext>(context: H) => {
7
+ // clone params on demand
8
+ let clonedParams;
9
+
10
+ Object.keys(context.params).forEach((key) => {
11
+ if (key === "query") {
12
+ return;
13
+ }
14
+
15
+ if (whitelist.includes(key)) {
16
+ if (!clonedParams) {
17
+ clonedParams = {
18
+ ...context.params,
19
+ query: {
20
+ ...context.params.query,
21
+ },
22
+ };
23
+ }
24
+
25
+ if (!clonedParams.query[keyToHide]) {
26
+ clonedParams.query[keyToHide] = {};
27
+ }
28
+
29
+ clonedParams.query[keyToHide][key] = clonedParams[key];
30
+ delete clonedParams[key];
31
+ }
32
+ });
33
+
34
+ if (clonedParams) {
35
+ context.params = clonedParams;
36
+ }
37
+
38
+ return context;
39
+ };
40
+ };
41
+ }
42
+
43
+ /**
44
+ * a hook to move params to query._$client
45
+ * the server only receives 'query' from params. All other params are ignored.
46
+ * So, to use `$populateParams` on the server, we need to move the params to query._$client
47
+ * the server will move them back to params
48
+ */
49
+ export const paramsForServer = defineParamsForServer(
50
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY,
51
+ );
52
+
53
+ if (import.meta.vitest) {
54
+ const { it, expect } = import.meta.vitest;
55
+
56
+ it("should move params to query._$client", () => {
57
+ expect(
58
+ paramsForServer(
59
+ "a",
60
+ "b",
61
+ )({
62
+ params: {
63
+ a: 1,
64
+ b: 2,
65
+ query: {},
66
+ },
67
+ } as HookContext),
68
+ ).toEqual({
69
+ params: {
70
+ query: {
71
+ _$client: {
72
+ a: 1,
73
+ b: 2,
74
+ },
75
+ },
76
+ },
77
+ });
78
+ });
79
+
80
+ it("should move params to query._$client and leave remaining", () => {
81
+ expect(
82
+ paramsForServer("a")({
83
+ params: {
84
+ a: 1,
85
+ b: 2,
86
+ query: {},
87
+ },
88
+ } as HookContext),
89
+ ).toEqual({
90
+ params: {
91
+ b: 2,
92
+ query: {
93
+ _$client: {
94
+ a: 1,
95
+ },
96
+ },
97
+ },
98
+ });
99
+ });
100
+ }
@@ -0,0 +1,105 @@
1
+ import type { HookContext } from "@feathersjs/feathers";
2
+ import { FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } from "./common";
3
+
4
+ export function defineParamsFromClient(keyToHide: string) {
5
+ return function paramsFromClient(
6
+ ...whitelist: string[]
7
+ ): (context: HookContext) => HookContext {
8
+ return (context: HookContext): HookContext => {
9
+ if (
10
+ !context.params?.query?.[keyToHide] ||
11
+ typeof context.params.query[keyToHide] !== "object"
12
+ ) {
13
+ return context;
14
+ }
15
+
16
+ const params = {
17
+ ...context.params,
18
+ query: {
19
+ ...context.params.query,
20
+ [keyToHide]: {
21
+ ...context.params.query[keyToHide],
22
+ },
23
+ },
24
+ };
25
+
26
+ const client = params.query[keyToHide];
27
+
28
+ whitelist.forEach((key) => {
29
+ if (key in client) {
30
+ params[key] = client[key];
31
+ delete client[key];
32
+ }
33
+ });
34
+
35
+ if (Object.keys(client).length === 0) {
36
+ delete params.query[keyToHide];
37
+ }
38
+
39
+ context.params = params;
40
+
41
+ return context;
42
+ };
43
+ };
44
+ }
45
+
46
+ export const paramsFromClient = defineParamsFromClient(
47
+ FROM_CLIENT_FOR_SERVER_DEFAULT_KEY,
48
+ );
49
+
50
+ if (import.meta.vitest) {
51
+ const { it, expect } = import.meta.vitest;
52
+
53
+ it("should move params to query._$client", () => {
54
+ expect(
55
+ paramsFromClient(
56
+ "a",
57
+ "b",
58
+ )({
59
+ params: {
60
+ query: {
61
+ _$client: {
62
+ a: 1,
63
+ b: 2,
64
+ },
65
+ c: 3,
66
+ },
67
+ },
68
+ } as HookContext),
69
+ ).toEqual({
70
+ params: {
71
+ a: 1,
72
+ b: 2,
73
+ query: {
74
+ c: 3,
75
+ },
76
+ },
77
+ });
78
+ });
79
+
80
+ it("should move params to query._$client and leave remaining", () => {
81
+ expect(
82
+ paramsFromClient("a")({
83
+ params: {
84
+ query: {
85
+ _$client: {
86
+ a: 1,
87
+ b: 2,
88
+ },
89
+ c: 3,
90
+ },
91
+ },
92
+ } as HookContext),
93
+ ).toEqual({
94
+ params: {
95
+ a: 1,
96
+ query: {
97
+ _$client: {
98
+ b: 2,
99
+ },
100
+ c: 3,
101
+ },
102
+ },
103
+ });
104
+ });
105
+ }
@@ -6,3 +6,4 @@ export * from "./parseFields";
6
6
  export * from "./removeRelated";
7
7
  export * from "./runPerItem";
8
8
  export * from "./setData";
9
+ export * from "./from-client-for-server";