feathers-utils 10.0.0 → 10.0.1
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/{hooks-DPFxxjBu.mjs → hooks-CzxNpt2c.mjs} +89 -77
- package/dist/hooks-CzxNpt2c.mjs.map +1 -0
- package/dist/hooks.d.mts +53 -24
- package/dist/hooks.mjs +4 -4
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +5 -5
- package/dist/{predicates-CT08opkD.mjs → predicates-C2SeOKGd.mjs} +16 -11
- package/dist/{predicates-CT08opkD.mjs.map → predicates-C2SeOKGd.mjs.map} +1 -1
- package/dist/predicates.d.mts +1 -1
- package/dist/predicates.mjs +1 -1
- package/dist/{resolve-Cx9osy8O.mjs → resolve-B81gQqXW.mjs} +2 -2
- package/dist/resolve-B81gQqXW.mjs.map +1 -0
- package/dist/resolvers.mjs +1 -1
- package/dist/{transform-result.hook-BUwLePT2.d.mts → transform-result.hook-C8-4Lezj.d.mts} +8 -5
- package/dist/{transform-result.hook-CevWK5TA.mjs → transform-result.hook-DifNj7zf.mjs} +12 -11
- package/dist/transform-result.hook-DifNj7zf.mjs.map +1 -0
- package/dist/transformers.d.mts +1 -1
- package/dist/transformers.mjs +1 -1
- package/dist/{unless.hook-BYWO9hzO.d.mts → unless.hook-CVD7SrZh.d.mts} +6 -3
- package/dist/{utils-1I_iPZkV.mjs → utils-ByzrJKGQ.mjs} +2 -2
- package/dist/{utils-1I_iPZkV.mjs.map → utils-ByzrJKGQ.mjs.map} +1 -1
- package/dist/utils.mjs +2 -2
- package/package.json +1 -1
- package/src/hooks/cache/cache.hook.ts +9 -7
- package/src/hooks/check-multi/check-multi.hook.ts +5 -2
- package/src/hooks/check-required/check-required.hook.ts +6 -1
- package/src/hooks/create-related/create-related.hook.ts +2 -2
- package/src/hooks/debug/debug.hook.ts +1 -1
- package/src/hooks/disable-pagination/disable-pagination.hook.ts +7 -4
- package/src/hooks/disallow/disallow.hook.ts +7 -2
- package/src/hooks/on-delete/on-delete.hook.ts +2 -2
- package/src/hooks/params-for-server/params-for-server.hook.ts +12 -5
- package/src/hooks/params-from-client/params-from-client.hook.ts +10 -6
- package/src/hooks/rate-limit/rate-limit.hook.ts +2 -2
- package/src/hooks/set-data/set-data.hook.ts +8 -7
- package/src/hooks/set-field/set-field.hook.ts +14 -11
- package/src/hooks/set-result/set-result.hook.ts +9 -3
- package/src/hooks/set-slug/set-slug.hook.ts +8 -6
- package/src/hooks/skippable/skippable.hook.ts +15 -12
- package/src/hooks/soft-delete/soft-delete.hook.ts +4 -5
- package/src/hooks/stashable/stashable.hook.ts +9 -8
- package/src/hooks/throw-if/throw-if.hook.ts +2 -2
- package/src/hooks/transform-data/transform-data.hook.ts +2 -4
- package/src/hooks/transform-query/transform-query.hook.ts +6 -5
- package/src/hooks/transform-result/transform-result.hook.ts +6 -9
- package/src/hooks/traverse/traverse.hook.ts +11 -10
- package/src/resolvers/resolve-result/resolve-result.ts +4 -1
- package/dist/hooks-DPFxxjBu.mjs.map +0 -1
- package/dist/resolve-Cx9osy8O.mjs.map +0 -1
- package/dist/transform-result.hook-CevWK5TA.mjs.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { g as every, p as isMulti, t as throwIf, u as isProvider } from "./predicates-
|
|
2
|
-
import { d as checkContext, f as addToQuery, h as sortQueryProperties, r as transformParams, u as contextToJson } from "./utils-
|
|
1
|
+
import { g as every, p as isMulti, t as throwIf, u as isProvider } from "./predicates-C2SeOKGd.mjs";
|
|
2
|
+
import { d as checkContext, f as addToQuery, h as sortQueryProperties, r as transformParams, u as contextToJson } from "./utils-ByzrJKGQ.mjs";
|
|
3
3
|
import { a as traverse$1, i as isPromise, r as toArray, t as early } from "./internal.utils-BWQ25nOd.mjs";
|
|
4
4
|
import { i as getDataIsArray, r as getResultIsArray } from "./mutate-result.util-CCBWix-G.mjs";
|
|
5
|
-
import { r as transformData } from "./transform-result.hook-
|
|
6
|
-
import "./resolve-
|
|
5
|
+
import { r as transformData } from "./transform-result.hook-DifNj7zf.mjs";
|
|
6
|
+
import "./resolve-B81gQqXW.mjs";
|
|
7
7
|
import isObject from "lodash/isObject.js";
|
|
8
8
|
import { copy } from "fast-copy";
|
|
9
9
|
import { BadRequest, Forbidden, MethodNotAllowed, TooManyRequests } from "@feathersjs/errors";
|
|
@@ -68,12 +68,10 @@ const cacheBefore = async (context, cacheMap) => {
|
|
|
68
68
|
const value = await cacheMap.get(context);
|
|
69
69
|
if (value) context.result = value;
|
|
70
70
|
}
|
|
71
|
-
return context;
|
|
72
71
|
};
|
|
73
72
|
const cacheAfter = async (context, cacheMap) => {
|
|
74
73
|
if (context.method === "get" || context.method === "find") await cacheMap.set(context);
|
|
75
74
|
else await cacheMap.clear(context);
|
|
76
|
-
return context;
|
|
77
75
|
};
|
|
78
76
|
var ContextCacheMap = class {
|
|
79
77
|
map;
|
|
@@ -193,14 +191,15 @@ var ContextCacheMap = class {
|
|
|
193
191
|
* @see https://utils.feathersjs.com/hooks/check-multi.html
|
|
194
192
|
*/
|
|
195
193
|
function checkMulti(options) {
|
|
196
|
-
|
|
194
|
+
function hook(context, next) {
|
|
197
195
|
const { service, method } = context;
|
|
198
196
|
if (!service.allowsMulti || !isMulti(context) || method === "find" || service.allowsMulti(method)) {
|
|
199
197
|
if (next) return next();
|
|
200
|
-
return
|
|
198
|
+
return;
|
|
201
199
|
}
|
|
202
200
|
throw options?.error ? options.error(context) : new MethodNotAllowed(`Can not ${method} multiple entries`);
|
|
203
|
-
}
|
|
201
|
+
}
|
|
202
|
+
return hook;
|
|
204
203
|
}
|
|
205
204
|
//#endregion
|
|
206
205
|
//#region src/hooks/check-required/check-required.hook.ts
|
|
@@ -222,7 +221,7 @@ function checkMulti(options) {
|
|
|
222
221
|
*/
|
|
223
222
|
function checkRequired(fieldNames) {
|
|
224
223
|
const fieldNamesArray = toArray(fieldNames);
|
|
225
|
-
|
|
224
|
+
function hook(context, next) {
|
|
226
225
|
checkContext(context, {
|
|
227
226
|
type: ["before", "around"],
|
|
228
227
|
method: [
|
|
@@ -243,7 +242,8 @@ function checkRequired(fieldNames) {
|
|
|
243
242
|
}
|
|
244
243
|
}
|
|
245
244
|
if (next) return next();
|
|
246
|
-
}
|
|
245
|
+
}
|
|
246
|
+
return hook;
|
|
247
247
|
}
|
|
248
248
|
//#endregion
|
|
249
249
|
//#region src/hooks/create-related/create-related.hook.ts
|
|
@@ -278,7 +278,7 @@ function createRelated(options) {
|
|
|
278
278
|
await Promise.all(entries.map(async (entry) => {
|
|
279
279
|
const { data, service, multi } = entry;
|
|
280
280
|
const dataToCreate = (await Promise.all(result.map(async (item) => data(item, context)))).flat().filter((x) => !!x);
|
|
281
|
-
if (!dataToCreate || dataToCreate.length <= 0) return
|
|
281
|
+
if (!dataToCreate || dataToCreate.length <= 0) return;
|
|
282
282
|
if (multi || dataToCreate.length === 1) await context.app.service(service).create(dataToCreate.length === 1 ? dataToCreate[0] : dataToCreate);
|
|
283
283
|
else await Promise.all(dataToCreate.map(async (item) => context.app.service(service).create(item)));
|
|
284
284
|
}));
|
|
@@ -338,19 +338,21 @@ const debug = (msg, ...fieldNames) => async (context, next) => {
|
|
|
338
338
|
*
|
|
339
339
|
* @see https://utils.feathersjs.com/hooks/disable-pagination.html
|
|
340
340
|
*/
|
|
341
|
-
const disablePagination = () =>
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
341
|
+
const disablePagination = () => {
|
|
342
|
+
function hook(context, next) {
|
|
343
|
+
checkContext(context, {
|
|
344
|
+
type: ["before", "around"],
|
|
345
|
+
method: ["find"],
|
|
346
|
+
label: "disablePagination"
|
|
347
|
+
});
|
|
348
|
+
const $limit = context.params?.query?.$limit;
|
|
349
|
+
if ($limit === "-1" || $limit === -1) {
|
|
350
|
+
context.params.paginate = false;
|
|
351
|
+
delete context.params.query.$limit;
|
|
352
|
+
}
|
|
353
|
+
if (next) return next();
|
|
351
354
|
}
|
|
352
|
-
|
|
353
|
-
return context;
|
|
355
|
+
return hook;
|
|
354
356
|
};
|
|
355
357
|
//#endregion
|
|
356
358
|
//#region src/hooks/disallow/disallow.hook.ts
|
|
@@ -375,11 +377,12 @@ const disablePagination = () => (context, next) => {
|
|
|
375
377
|
*/
|
|
376
378
|
const disallow = (transports) => {
|
|
377
379
|
const transportsArr = toArray(transports);
|
|
378
|
-
|
|
380
|
+
function hook(context, next) {
|
|
379
381
|
if (!transports) throw new MethodNotAllowed("Method not allowed");
|
|
380
382
|
if (isProvider(...transportsArr)(context)) throw new MethodNotAllowed(`Provider '${context.params.provider}' can not call '${context.method}' on '${context.path}'. (disallow)`);
|
|
381
|
-
if (next) return next()
|
|
382
|
-
}
|
|
383
|
+
if (next) return next();
|
|
384
|
+
}
|
|
385
|
+
return hook;
|
|
383
386
|
};
|
|
384
387
|
//#endregion
|
|
385
388
|
//#region src/hooks/on-delete/on-delete.hook.ts
|
|
@@ -398,7 +401,7 @@ const onDelete = (options) => {
|
|
|
398
401
|
optionsMulti.forEach(async ({ keyHere, keyThere, onDelete, service, blocking, query }) => {
|
|
399
402
|
let ids = result.map((x) => x[keyHere]).filter((x) => !!x);
|
|
400
403
|
ids = [...new Set(ids)];
|
|
401
|
-
if (!ids || ids.length <= 0) return
|
|
404
|
+
if (!ids || ids.length <= 0) return;
|
|
402
405
|
const params = {
|
|
403
406
|
query: {
|
|
404
407
|
...query,
|
|
@@ -442,7 +445,7 @@ const FROM_CLIENT_FOR_SERVER_DEFAULT_KEY = "_$client";
|
|
|
442
445
|
const paramsForServer = (whitelist, options) => {
|
|
443
446
|
const whitelistArr = toArray(whitelist);
|
|
444
447
|
const { keyToHide = FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } = options || {};
|
|
445
|
-
|
|
448
|
+
function hook(context, next) {
|
|
446
449
|
let clonedParams;
|
|
447
450
|
Object.keys(context.params).forEach((key) => {
|
|
448
451
|
if (key === "query") return;
|
|
@@ -458,8 +461,8 @@ const paramsForServer = (whitelist, options) => {
|
|
|
458
461
|
});
|
|
459
462
|
if (clonedParams) context.params = clonedParams;
|
|
460
463
|
if (next) return next();
|
|
461
|
-
|
|
462
|
-
|
|
464
|
+
}
|
|
465
|
+
return hook;
|
|
463
466
|
};
|
|
464
467
|
//#endregion
|
|
465
468
|
//#region src/hooks/params-from-client/params-from-client.hook.ts
|
|
@@ -483,10 +486,10 @@ const paramsForServer = (whitelist, options) => {
|
|
|
483
486
|
const paramsFromClient = (whitelist, options) => {
|
|
484
487
|
const whitelistArr = toArray(whitelist);
|
|
485
488
|
const { keyToHide = FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } = options || {};
|
|
486
|
-
|
|
489
|
+
function hook(context, next) {
|
|
487
490
|
if (!context.params?.query?.[keyToHide] || typeof context.params.query[keyToHide] !== "object") {
|
|
488
491
|
if (next) return next();
|
|
489
|
-
return
|
|
492
|
+
return;
|
|
490
493
|
}
|
|
491
494
|
const params = {
|
|
492
495
|
...context.params,
|
|
@@ -505,8 +508,8 @@ const paramsFromClient = (whitelist, options) => {
|
|
|
505
508
|
if (Object.keys(client).length === 0) delete params.query[keyToHide];
|
|
506
509
|
context.params = params;
|
|
507
510
|
if (next) return next();
|
|
508
|
-
|
|
509
|
-
|
|
511
|
+
}
|
|
512
|
+
return hook;
|
|
510
513
|
};
|
|
511
514
|
//#endregion
|
|
512
515
|
//#region src/hooks/prevent-changes/prevent-changes.hook.ts
|
|
@@ -577,7 +580,7 @@ const rateLimit = (rateLimiter, options) => {
|
|
|
577
580
|
context.params.rateLimit = res;
|
|
578
581
|
throw new TooManyRequests("Too many requests", { rateLimitRes: res });
|
|
579
582
|
}
|
|
580
|
-
if (next)
|
|
583
|
+
if (next) await next();
|
|
581
584
|
};
|
|
582
585
|
};
|
|
583
586
|
//#endregion
|
|
@@ -600,17 +603,17 @@ const rateLimit = (rateLimiter, options) => {
|
|
|
600
603
|
*/
|
|
601
604
|
function setData(from, to, options) {
|
|
602
605
|
const { allowUndefined = false, overwrite = true } = options ?? {};
|
|
603
|
-
|
|
606
|
+
function hook(context, next) {
|
|
604
607
|
const { data } = getDataIsArray(context);
|
|
605
608
|
const contextJson = contextToJson(context);
|
|
606
609
|
if (!_has(contextJson, from)) {
|
|
607
610
|
if (!context.params?.provider || allowUndefined === true) {
|
|
608
611
|
if (next) return next();
|
|
609
|
-
return
|
|
612
|
+
return;
|
|
610
613
|
}
|
|
611
614
|
if (!overwrite && data.every((item) => _has(item, to))) {
|
|
612
615
|
if (next) return next();
|
|
613
|
-
return
|
|
616
|
+
return;
|
|
614
617
|
}
|
|
615
618
|
throw options?.error ? options.error(context, from) : new Forbidden(`Expected field ${from.toString()} not available`);
|
|
616
619
|
}
|
|
@@ -621,8 +624,8 @@ function setData(from, to, options) {
|
|
|
621
624
|
_set(item, to, val);
|
|
622
625
|
}
|
|
623
626
|
if (next) return next();
|
|
624
|
-
|
|
625
|
-
|
|
627
|
+
}
|
|
628
|
+
return hook;
|
|
626
629
|
}
|
|
627
630
|
//#endregion
|
|
628
631
|
//#region src/hooks/set-field/set-field.hook.ts
|
|
@@ -642,23 +645,25 @@ function setData(from, to, options) {
|
|
|
642
645
|
*
|
|
643
646
|
* @see https://utils.feathersjs.com/hooks/set-field.html
|
|
644
647
|
*/
|
|
645
|
-
const setField = ({ as, from, allowUndefined = false, error }) =>
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
if (
|
|
654
|
-
if (
|
|
655
|
-
|
|
648
|
+
const setField = ({ as, from, allowUndefined = false, error }) => {
|
|
649
|
+
function hook(context, next) {
|
|
650
|
+
const { params } = context;
|
|
651
|
+
checkContext(context, {
|
|
652
|
+
type: ["before", "around"],
|
|
653
|
+
label: "setField"
|
|
654
|
+
});
|
|
655
|
+
const value = _get(context, from);
|
|
656
|
+
if (value === void 0) {
|
|
657
|
+
if (!params.provider || allowUndefined) {
|
|
658
|
+
if (next) return next();
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
throw error ? error(context, from) : new Forbidden(`Expected field ${as} not available`);
|
|
656
662
|
}
|
|
657
|
-
|
|
663
|
+
_setWith(context, as, value, _clone);
|
|
664
|
+
if (next) return next();
|
|
658
665
|
}
|
|
659
|
-
|
|
660
|
-
if (next) return next();
|
|
661
|
-
return context;
|
|
666
|
+
return hook;
|
|
662
667
|
};
|
|
663
668
|
//#endregion
|
|
664
669
|
//#region src/hooks/set-result/set-result.hook.ts
|
|
@@ -703,10 +708,13 @@ function setResult(from, to, options) {
|
|
|
703
708
|
}
|
|
704
709
|
return forResultOrDispatch(context, !!options?.dispatch);
|
|
705
710
|
};
|
|
706
|
-
|
|
707
|
-
if (next) return next().then(() =>
|
|
708
|
-
|
|
709
|
-
|
|
711
|
+
function hook(context, next) {
|
|
712
|
+
if (next) return next().then(() => {
|
|
713
|
+
fn(context);
|
|
714
|
+
});
|
|
715
|
+
fn(context);
|
|
716
|
+
}
|
|
717
|
+
return hook;
|
|
710
718
|
}
|
|
711
719
|
//#endregion
|
|
712
720
|
//#region src/hooks/set-slug/set-slug.hook.ts
|
|
@@ -727,15 +735,15 @@ function setResult(from, to, options) {
|
|
|
727
735
|
* @see https://utils.feathersjs.com/hooks/set-slug.html
|
|
728
736
|
*/
|
|
729
737
|
const setSlug = (slug, fieldName) => {
|
|
730
|
-
|
|
731
|
-
|
|
738
|
+
const targetField = typeof fieldName === "string" ? fieldName : `query.${slug}`;
|
|
739
|
+
function hook(context, next) {
|
|
732
740
|
if (context.params && context.params.provider === "rest") {
|
|
733
741
|
const value = context.params.route[slug];
|
|
734
|
-
if (typeof value === "string" && value[0] !== ":") _set(context.params,
|
|
742
|
+
if (typeof value === "string" && value[0] !== ":") _set(context.params, targetField, value);
|
|
735
743
|
}
|
|
736
744
|
if (next) return next();
|
|
737
|
-
|
|
738
|
-
|
|
745
|
+
}
|
|
746
|
+
return hook;
|
|
739
747
|
};
|
|
740
748
|
//#endregion
|
|
741
749
|
//#region src/hooks/soft-delete/soft-delete.hook.ts
|
|
@@ -765,7 +773,10 @@ const softDelete = (options) => {
|
|
|
765
773
|
label: "softDelete"
|
|
766
774
|
});
|
|
767
775
|
const { disableSoftDeleteKey = "disableSoftDelete" } = options;
|
|
768
|
-
if (context.params[disableSoftDeleteKey])
|
|
776
|
+
if (context.params[disableSoftDeleteKey]) {
|
|
777
|
+
await early(context, next);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
769
780
|
const { deletedQuery, removeData } = options;
|
|
770
781
|
let deleteQuery = getValue(deletedQuery, context);
|
|
771
782
|
if (isPromise(deleteQuery)) deleteQuery = await deleteQuery;
|
|
@@ -781,8 +792,7 @@ const softDelete = (options) => {
|
|
|
781
792
|
const method = options.usePatchWithHooks ? "patch" : "_patch";
|
|
782
793
|
context.result = await context.service[method](context.id, data, params);
|
|
783
794
|
}
|
|
784
|
-
if (next)
|
|
785
|
-
return context;
|
|
795
|
+
if (next) await next();
|
|
786
796
|
};
|
|
787
797
|
};
|
|
788
798
|
const getValue = (value, ...args) => {
|
|
@@ -823,10 +833,10 @@ const defaultStashFunc = (context) => {
|
|
|
823
833
|
function stashable(options) {
|
|
824
834
|
const propName = options?.propName ?? "stashed";
|
|
825
835
|
const stashFunc = options?.stashFunc ?? defaultStashFunc;
|
|
826
|
-
|
|
836
|
+
function hook(context, next) {
|
|
827
837
|
if (context.params._stashable) {
|
|
828
838
|
if (next) return next();
|
|
829
|
-
return
|
|
839
|
+
return;
|
|
830
840
|
}
|
|
831
841
|
checkContext(context, {
|
|
832
842
|
type: ["before", "around"],
|
|
@@ -840,8 +850,8 @@ function stashable(options) {
|
|
|
840
850
|
const promise = stashFunc(context).catch(() => void 0);
|
|
841
851
|
context.params[propName] = () => promise;
|
|
842
852
|
if (next) return next();
|
|
843
|
-
|
|
844
|
-
|
|
853
|
+
}
|
|
854
|
+
return hook;
|
|
845
855
|
}
|
|
846
856
|
//#endregion
|
|
847
857
|
//#region src/hooks/throw-if-is-multi/throw-if-is-multi.hook.ts
|
|
@@ -905,12 +915,14 @@ const throwIfIsProvider = (transports, options) => {
|
|
|
905
915
|
*
|
|
906
916
|
* @see https://utils.feathersjs.com/hooks/traverse.html
|
|
907
917
|
*/
|
|
908
|
-
const traverse = ({ transformer, getObject }) =>
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
918
|
+
const traverse = ({ transformer, getObject }) => {
|
|
919
|
+
function hook(context, next) {
|
|
920
|
+
traverse$1(getObject(context), transformer);
|
|
921
|
+
if (next) return next();
|
|
922
|
+
}
|
|
923
|
+
return hook;
|
|
912
924
|
};
|
|
913
925
|
//#endregion
|
|
914
926
|
export { debug as _, softDelete as a, checkMulti as b, setField as c, preventChanges as d, paramsFromClient as f, disablePagination as g, disallow as h, stashable as i, setData as l, onDelete as m, throwIfIsProvider as n, setSlug as o, paramsForServer as p, throwIfIsMulti as r, setResult as s, traverse as t, rateLimit as u, createRelated as v, cache as x, checkRequired as y };
|
|
915
927
|
|
|
916
|
-
//# sourceMappingURL=hooks-
|
|
928
|
+
//# sourceMappingURL=hooks-CzxNpt2c.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-CzxNpt2c.mjs","names":["defaultError"],"sources":["../src/hooks/cache/cache-utils.ts","../src/hooks/cache/cache.hook.ts","../src/hooks/check-multi/check-multi.hook.ts","../src/hooks/check-required/check-required.hook.ts","../src/hooks/create-related/create-related.hook.ts","../src/hooks/debug/debug.hook.ts","../src/hooks/disable-pagination/disable-pagination.hook.ts","../src/hooks/disallow/disallow.hook.ts","../src/hooks/on-delete/on-delete.hook.ts","../src/hooks/params-for-server/params-for-from-shared.ts","../src/hooks/params-for-server/params-for-server.hook.ts","../src/hooks/params-from-client/params-from-client.hook.ts","../src/hooks/prevent-changes/prevent-changes.hook.ts","../src/hooks/rate-limit/rate-limit.hook.ts","../src/hooks/set-data/set-data.hook.ts","../src/hooks/set-field/set-field.hook.ts","../src/hooks/set-result/set-result.hook.ts","../src/hooks/set-slug/set-slug.hook.ts","../src/hooks/soft-delete/soft-delete.hook.ts","../src/hooks/stashable/stashable.hook.ts","../src/hooks/throw-if-is-multi/throw-if-is-multi.hook.ts","../src/hooks/throw-if-is-provider/throw-if-is-provider.hook.ts","../src/hooks/traverse/traverse.hook.ts"],"sourcesContent":["import isObject from 'lodash/isObject.js'\nimport { sortQueryProperties } from '../../utils/sort-query-properties/sort-query-properties.util.js'\n\nexport { sortQueryProperties }\n\nexport const stableStringify = (obj: Record<string, any>) => {\n if (obj.query) {\n obj = { ...obj, query: sortQueryProperties(obj.query) }\n }\n\n return JSON.stringify(obj, (key, value) => {\n if (typeof value === 'function') {\n throw new Error('Cannot stringify non JSON value')\n }\n\n if (isObject(value)) {\n return Object.keys(value)\n .sort()\n .reduce(\n (result, key) => {\n result[key] = (value as any)[key]\n return result\n },\n {} as Record<string, any>,\n )\n }\n\n return value\n })\n}\n","import type { HookContext, NextFunction, Params } from '@feathersjs/feathers'\nimport { stableStringify } from './cache-utils.js'\nimport { copy } from 'fast-copy'\nimport type { Promisable } from '../../internal.utils.js'\n\ntype Cache = {\n get: (key: string) => Promisable<any>\n set: (key: string, value: any) => Promisable<any>\n delete: (key: string) => Promisable<any>\n clear: () => any\n keys: () => IterableIterator<string>\n}\n\nexport type CacheEvent =\n | { type: 'hit'; method: string; key: string }\n | { type: 'miss'; method: string; key: string }\n | { type: 'set'; method: string; key: string }\n | { type: 'invalidate'; method: string; key: string }\n | { type: 'clear'; method: string }\n\nexport type CacheOptions = {\n /**\n * The cache implementation to use. It should implement the methods `get`, `set`, `delete`, `clear`, and `keys`.\n * This can be a Map, Redis client, or any other cache implementation.\n *\n * Use 'lru-cache' for an LRU cache implementation.\n */\n map: Cache\n /**\n * The id field to use for caching. Defaults to `service.options.id` and if not found, then 'id'.\n */\n id?: string\n /**\n * params are stringified for the key-value cache.\n * There are params properties you don't want to include in the cache key.\n * You can use this function to transform the params before they are stringified.\n */\n transformParams: (params: Params) => Params\n /**\n * Custom serialization function for converting params into a cache key string.\n * By default, uses `stableStringify` which sorts object keys and normalizes\n * query operator arrays (`$or`, `$and`, `$in`, etc.) for order-independent caching.\n *\n * Override this to use a custom serialization strategy.\n *\n * @example\n * ```ts\n * cache({\n * map: new Map(),\n * transformParams: (params) => ({ query: params.query }),\n * serialize: (params) => JSON.stringify(params),\n * })\n * ```\n */\n serialize?: (params: Params) => string\n /**\n * Optional logger callback for cache events (hit, miss, set, invalidate, clear).\n * Useful for debugging and monitoring cache behavior.\n *\n * @example\n * ```ts\n * cache({\n * map: new Map(),\n * transformParams: (params) => ({ query: params.query }),\n * logger: (event) => console.log(`cache ${event.type}`, event),\n * })\n * ```\n */\n logger?: (event: CacheEvent) => void\n}\n\n/**\n * Caches `get` and `find` results based on `params`. On mutating methods (`create`, `update`,\n * `patch`, `remove`), affected cache entries are automatically invalidated.\n * Works as a `before`, `after`, or `around` hook.\n *\n * @example\n * ```ts\n * import { cache } from 'feathers-utils/hooks'\n *\n * const myCache = new Map()\n *\n * app.service('users').hooks({\n * around: {\n * all: [cache({ map: myCache, transformParams: (params) => ({ query: params.query }) })]\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/cache.html\n */\nexport const cache = <H extends HookContext = HookContext>(\n options: CacheOptions,\n) => {\n const cacheMap = new ContextCacheMap(options)\n return async (context: H, next?: NextFunction): Promise<void> => {\n if (context.type === 'before') {\n return await cacheBefore(context, cacheMap)\n }\n if (context.type === 'after') {\n return await cacheAfter(context, cacheMap)\n }\n\n if (context.type === 'around' && next) {\n await cacheBefore(context, cacheMap)\n await next()\n await cacheAfter(context, cacheMap)\n return\n }\n }\n}\n\nconst cacheBefore = async (\n context: HookContext,\n cacheMap: ContextCacheMap,\n): Promise<void> => {\n if (context.method === 'get' || context.method === 'find') {\n const value = await cacheMap.get(context)\n if (value) {\n context.result = value\n }\n }\n}\n\nconst cacheAfter = async (\n context: HookContext,\n cacheMap: ContextCacheMap,\n): Promise<void> => {\n if (context.method === 'get' || context.method === 'find') {\n await cacheMap.set(context)\n } else {\n await cacheMap.clear(context)\n }\n}\n\nclass ContextCacheMap {\n map: Cache\n private delimiter = ':'\n private options: CacheOptions\n private log: ((event: CacheEvent) => void) | undefined\n private serialize: (params: Params) => string\n\n constructor(options: CacheOptions) {\n this.map = options.map\n this.options = options\n this.log = options.logger\n this.serialize = options.serialize ?? stableStringify\n }\n\n private stringifyCacheKey(context: HookContext) {\n if (context.method !== 'get' && context.method !== 'find') {\n throw new Error(\n `Cache can only be used with 'get' or 'find' methods, not '${context.method}'`,\n )\n }\n\n const stringifiedParams = this.serialize(\n this.options.transformParams(context.params ?? {}),\n )\n\n return `${context.id ?? 'null'}${this.delimiter}${stringifiedParams}`\n }\n\n private getCachedId(key: string) {\n const index = key.indexOf(this.delimiter)\n if (index === -1) {\n throw new Error(\n `Cache key '${key}' does not contain a delimiter '${this.delimiter}'`,\n )\n }\n return key.substring(0, index)\n }\n\n private getId(item: Record<string, any>, context: HookContext) {\n const idField = context.service.options?.id || this.options.id || 'id'\n const id = item[idField]\n return id && id.toString ? id.toString() : id\n }\n\n /**\n * Called before get() and find()\n *\n * returns a cached result for the given context if it exists.\n */\n async get(context: HookContext) {\n const key = this.stringifyCacheKey(context)\n const result = this.map.get(key)\n if (result) {\n this.log?.({ type: 'hit', method: context.method, key })\n return copy(result) // Use copy to avoid mutation of the original result\n }\n this.log?.({ type: 'miss', method: context.method, key })\n }\n\n /**\n * Called after get() and find()\n *\n * Caches the result for the given context.\n */\n async set(context: HookContext) {\n const key = this.stringifyCacheKey(context)\n this.log?.({ type: 'set', method: context.method, key })\n return this.map.set(key, copy(context.result)) // Use copy to avoid mutation of the original result\n }\n\n // Called after create(), update(), patch(), and remove()\n async clear<H extends HookContext>(context: H): Promise<H> {\n const results = Array.isArray(context.result)\n ? context.result\n : [context.result]\n\n const promises: Promise<any>[] = []\n\n const itemIds = results\n .map((item: any) => this.getId(item, context))\n .filter(Boolean)\n\n // If no itemIds are found, clear the entire cache to avoid stale data\n if (!itemIds.length) {\n this.log?.({ type: 'clear', method: context.method })\n await this.map.clear()\n return context\n }\n\n for (const key of this.map.keys()) {\n const cachedId = this.getCachedId(key)\n if (cachedId === 'null') {\n // This is a cached `find` request. Any create/patch/update/del\n // could affect the results of this query so it should be deleted\n this.log?.({ type: 'invalidate', method: context.method, key })\n promises.push(this.map.delete(key))\n continue\n }\n\n // This is a cached `get` request\n\n if (context.method === 'create') {\n // If this is a create, we don't need to delete any cached get requests\n continue\n }\n\n for (const itemId of itemIds) {\n if (cachedId === itemId) {\n // If the cached id matches the item id, delete the cached get\n this.log?.({ type: 'invalidate', method: context.method, key })\n promises.push(this.map.delete(key))\n }\n }\n }\n\n await Promise.all(promises)\n\n return context\n }\n}\n","import type { FeathersError } from '@feathersjs/errors'\nimport { MethodNotAllowed } from '@feathersjs/errors'\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { isMulti } from '../../predicates/index.js'\n\nexport type CheckMultiOptions = {\n /**\n * Customize the error that is thrown if the service does not allow multi operations.\n *\n * If not provided, throws a `MethodNotAllowed` error with a message indicating the operation.\n */\n error?: (context: HookContext) => FeathersError\n}\n\n/**\n * Checks if the `multi` option is enabled for the current method and throws a\n * `MethodNotAllowed` error if multi operations are not permitted.\n * Useful to guard against accidental bulk `create`, `patch`, or `remove` calls.\n *\n * @example\n * ```ts\n * import { checkMulti } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { create: [checkMulti()] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/check-multi.html\n */\nexport function checkMulti<H extends HookContext = HookContext>(\n options?: CheckMultiOptions,\n) {\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n const { service, method } = context\n if (\n !service.allowsMulti ||\n !isMulti(context) ||\n method === 'find' ||\n service.allowsMulti(method)\n ) {\n if (next) return next()\n return\n }\n\n throw options?.error\n ? options.error(context)\n : new MethodNotAllowed(`Can not ${method} multiple entries`)\n }\n return hook\n}\n","import _get from 'lodash/get.js'\nimport _has from 'lodash/has.js'\nimport { BadRequest } from '@feathersjs/errors'\n\nimport { checkContext, getDataIsArray } from '../../utils/index.js'\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { MaybeArray } from '../../internal.utils.js'\nimport { toArray } from '../../internal.utils.js'\n\n/**\n * Validates that the specified fields exist on `context.data` and are not falsy.\n * Numeric `0` and boolean `false` are treated as valid values.\n * Throws a `BadRequest` error if any required field is missing or null.\n *\n * @example\n * ```ts\n * import { checkRequired } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { create: [checkRequired(['email', 'password'])] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/check-required.html\n */\nexport function checkRequired<H extends HookContext = HookContext>(\n fieldNames: MaybeArray<string>,\n) {\n const fieldNamesArray = toArray(fieldNames)\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n checkContext(context, {\n type: ['before', 'around'],\n method: ['create', 'update', 'patch'],\n label: 'checkRequired',\n })\n\n const { data } = getDataIsArray(context)\n\n for (let i = 0; i < data.length; i++) {\n const item = data[i]\n\n for (let j = 0; j < fieldNamesArray.length; j++) {\n const name = fieldNamesArray[j]\n\n if (!_has(item, name)) {\n throw new BadRequest(`Field ${name} does not exist. (required)`)\n }\n\n const value = _get(item, name)\n\n if (!value && value !== 0 && value !== false) {\n throw new BadRequest(`Field ${name} is null. (required)`)\n }\n }\n }\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { checkContext, getResultIsArray } from '../../utils/index.js'\nimport type { MaybeArray, Promisable } from '../../internal.utils.js'\nimport type { InferCreateDataSingle } from '../../utility-types/infer-service-methods.js'\nimport type { ResultSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport interface CreateRelatedOptions<\n H extends HookContext = HookContext,\n Services extends H['app']['services'] = H['app']['services'],\n S extends keyof Services = keyof Services,\n> {\n service: S\n /**\n * Is relevant when the current context result is an array.\n *\n * If true, will create multiple related records in a single call to the related service's create method.\n * If false or not provided, will create related records one by one.\n *\n * @default false\n */\n multi?: boolean\n /**\n * A function that returns the data to be created in the related service.\n *\n * Receives the current item from the context result and the full hook context as arguments.\n * Can return a single data object, an array of data objects, or a promise that resolves to either.\n *\n * If the function returns undefined, no related record will be created for that item.\n */\n data: (\n item: ResultSingleHookContext<H>,\n context: H,\n ) => Promisable<MaybeArray<InferCreateDataSingle<Services[S]>> | undefined>\n}\n\n/**\n * Creates related records in other services after a successful `create` call.\n * For each result item, a `data` function produces the record to create in the target service.\n * Supports creating records one-by-one or in a single multi-create when `multi: true`.\n *\n * @example\n * ```ts\n * import { createRelated } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * after: {\n * create: [createRelated({ service: 'profiles', data: (user) => ({ userId: user.id }) })]\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/create-related.html\n */\nexport function createRelated<H extends HookContext = HookContext>(\n options: MaybeArray<CreateRelatedOptions<H>>,\n) {\n return async (context: H, next?: NextFunction): Promise<void> => {\n checkContext(context, {\n type: ['after', 'around'],\n method: ['create'],\n label: 'createRelated',\n })\n\n if (next) {\n await next()\n }\n\n const { result } = getResultIsArray(context)\n\n const entries = Array.isArray(options) ? options : [options]\n\n await Promise.all(\n entries.map(async (entry) => {\n const { data, service, multi } = entry\n\n const dataToCreate = (\n await Promise.all(result.map(async (item) => data(item, context)))\n )\n .flat()\n .filter((x) => !!x)\n\n if (!dataToCreate || dataToCreate.length <= 0) {\n return\n }\n\n if (multi || dataToCreate.length === 1) {\n await context.app\n .service(service as string)\n .create(\n dataToCreate.length === 1\n ? (dataToCreate[0] as any)\n : (dataToCreate as any),\n )\n } else {\n await Promise.all(\n dataToCreate.map(async (item) =>\n context.app.service(service as string).create(item as any),\n ),\n )\n }\n }),\n )\n }\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\n\n/**\n * Logs the current hook context to the console for debugging purposes.\n * Displays timestamp, service path, method, type, id, data, query, result, and\n * any additional param fields you specify.\n *\n * @example\n * ```ts\n * import { debug } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { find: [debug('before find', 'user')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/debug.html\n */\nexport const debug =\n <H extends HookContext = HookContext>(msg: string, ...fieldNames: string[]) =>\n async (context: H, next?: NextFunction): Promise<void> => {\n if (next) {\n await next()\n }\n\n // display timestamp\n const now = new Date()\n console.log(\n `${now.getFullYear()}-${\n now.getMonth() + 1\n }-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`,\n )\n\n if (msg) {\n console.log(msg)\n }\n\n // display service, method & type of hook (before/after/error)\n console.log(\n `${context.type} service('${context.path}').${context.method}()`,\n )\n\n // display id for get, patch, update & remove\n if (!['find', 'create'].includes(context.method) && 'id' in context) {\n console.log('id:', context.id)\n }\n\n if (context.data) {\n console.log('data:', context.data)\n }\n\n if (context.params?.query) {\n console.log('query:', context.params.query)\n }\n\n if (context.result) {\n console.log('result:', context.result)\n }\n\n // display additional params\n const params = context.params || {}\n console.log('params props:', Object.keys(params).sort())\n\n fieldNames.forEach((name) => {\n console.log(`params.${name}:`, params[name])\n })\n\n if (context.error) {\n console.log('error', context.error)\n }\n }\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { checkContext } from '../../utils/index.js'\n\n/**\n * Disables pagination when `query.$limit` is `-1` or `'-1'`.\n * Removes the `$limit` from the query and sets `params.paginate = false`.\n * Must be used as a `before` or `around` hook on the `find` method.\n *\n * @example\n * ```ts\n * import { disablePagination } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { find: [disablePagination()] }\n * })\n * // Then call: app.service('users').find({ query: { $limit: -1 } })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/disable-pagination.html\n */\nexport const disablePagination = <H extends HookContext = HookContext>() => {\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n checkContext(context, {\n type: ['before', 'around'],\n method: ['find'],\n label: 'disablePagination',\n })\n const $limit = context.params?.query?.$limit\n\n if ($limit === '-1' || $limit === -1) {\n context.params.paginate = false\n delete context.params.query.$limit\n }\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import { MethodNotAllowed } from '@feathersjs/errors'\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { TransportName } from '../../types.js'\nimport { isProvider } from '../../predicates/index.js'\nimport type { MaybeArray } from '../../internal.utils.js'\nimport { toArray } from '../../internal.utils.js'\n\n/**\n * Prevents access to a service method completely or for specific transports.\n * When called without arguments, the method is blocked for all callers.\n * When called with transport names, only those transports are blocked.\n *\n * @example\n * ```ts\n * import { disallow } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: {\n * remove: [disallow('external')], // block external access\n * update: [disallow()], // block completely\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/disallow.html\n */\nexport const disallow = <H extends HookContext = HookContext>(\n transports?: MaybeArray<TransportName>,\n) => {\n const transportsArr = toArray(transports)\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n if (!transports) {\n throw new MethodNotAllowed('Method not allowed')\n }\n\n if (isProvider(...(transportsArr as TransportName[]))(context)) {\n throw new MethodNotAllowed(\n `Provider '${context.params.provider}' can not call '${context.method}' on '${context.path}'. (disallow)`,\n )\n }\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { checkContext, getResultIsArray } from '../../utils/index.js'\nimport type { MaybeArray, NeverFallback } from '../../internal.utils.js'\nimport type {\n InferFindParams,\n InferGetResult,\n} from '../../utility-types/infer-service-methods.js'\nimport type { ResultSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport type OnDeleteAction = 'cascade' | 'set null'\n\nexport interface OnDeleteOptions<\n H extends HookContext = HookContext,\n S extends keyof H['app']['services'] = keyof H['app']['services'],\n> {\n /**\n * The related service where related items should be manipulated\n */\n service: S\n /**\n * The propertyKey in the related service\n */\n keyThere: NeverFallback<keyof InferGetResult<H['app']['services'][S]>, string>\n /**\n * The propertyKey in the current service.\n */\n keyHere: keyof ResultSingleHookContext<H>\n /**\n * The action to perform on the related items.\n *\n * - `cascade`: remove related items\n * - `set null`: set the related property to null\n */\n onDelete: OnDeleteAction\n /**\n * Additional query to merge into the service call.\n * Typed based on the related service's query type.\n */\n query?: InferFindParams<H['app']['services'][S]>['query']\n /**\n * If true, the hook will wait for the service to finish before continuing\n *\n * @default false\n */\n blocking?: boolean\n}\n\n/**\n * Manipulates related items when a record is deleted, similar to SQL foreign key actions.\n * Supports `'cascade'` (remove related records) and `'set null'` (nullify the foreign key).\n * Unlike database-level cascades, this hook triggers service events and hooks for related items.\n *\n * @example\n * ```ts\n * import { onDelete } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * after: {\n * remove: [onDelete({ service: 'posts', keyHere: 'id', keyThere: 'userId', onDelete: 'cascade' })]\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/on-delete.html\n */\ntype OnDeleteOptionsDistributed<H extends HookContext> = {\n [S in keyof H['app']['services'] & string]: OnDeleteOptions<H, S>\n}[keyof H['app']['services'] & string]\n\nexport const onDelete = <H extends HookContext = HookContext>(\n options: MaybeArray<OnDeleteOptionsDistributed<H>>,\n) => {\n const optionsMulti = Array.isArray(options) ? options : [options]\n\n return async (context: H, next?: NextFunction): Promise<void> => {\n checkContext(context, {\n type: ['after', 'around'],\n method: 'remove',\n label: 'onDelete',\n })\n\n if (next) {\n await next()\n }\n\n const { result } = getResultIsArray(context)\n\n if (!result.length) {\n return\n }\n\n const promises: Promise<any>[] = []\n\n optionsMulti.forEach(\n async ({ keyHere, keyThere, onDelete, service, blocking, query }) => {\n let ids = result.map((x) => x[keyHere]).filter((x) => !!x)\n ids = [...new Set(ids)]\n\n if (!ids || ids.length <= 0) {\n return\n }\n\n const params = {\n query: {\n ...query,\n ...(ids.length === 1\n ? { [keyThere]: ids[0] }\n : { [keyThere]: { $in: ids } }),\n },\n paginate: false,\n }\n\n let promise: Promise<any> | undefined = undefined\n\n if (onDelete === 'cascade') {\n promise = context.app.service(service as string).remove(null, params)\n } else if (onDelete === 'set null') {\n const data = { [keyThere]: null }\n promise = context.app\n .service(service as string)\n .patch(null, data, params)\n }\n\n if (promise && blocking) {\n promises.push(promise)\n }\n },\n )\n\n if (promises.length) {\n await Promise.all(promises)\n }\n\n return\n }\n}\n","export const FROM_CLIENT_FOR_SERVER_DEFAULT_KEY = '_$client' as const\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { MaybeArray } from '../../internal.utils.js'\nimport { toArray } from '../../internal.utils.js'\nimport { FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } from './params-for-from-shared.js'\n\nexport type ParamsForServerOptions = {\n /**\n * @default '_$client'\n */\n keyToHide?: string\n}\n\n/**\n * Client-side hook that moves whitelisted `params` properties into `query._$client`\n * so they survive the client-to-server transport. The server only receives `query`\n * from params — use `paramsFromClient` on the server to restore them.\n *\n * @example\n * ```ts\n * import { paramsForServer } from 'feathers-utils/hooks'\n *\n * // Client-side\n * app.service('users').hooks({\n * before: { all: [paramsForServer('populateParams')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/params-for-server.html\n */\nexport const paramsForServer = (\n whitelist: MaybeArray<string>,\n options?: ParamsForServerOptions,\n) => {\n const whitelistArr = toArray(whitelist)\n\n const { keyToHide = FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } = options || {}\n\n function hook<H extends HookContext>(context: H): void\n function hook<H extends HookContext>(\n context: H,\n next: NextFunction,\n ): Promise<void>\n function hook<H extends HookContext>(\n context: H,\n next?: NextFunction,\n ): void | Promise<void> {\n // clone params on demand\n let clonedParams: any\n\n Object.keys(context.params).forEach((key) => {\n if (key === 'query') {\n return\n }\n\n if (whitelistArr.includes(key)) {\n if (!clonedParams) {\n clonedParams = {\n ...context.params,\n query: {\n ...context.params.query,\n },\n }\n }\n\n if (!clonedParams.query[keyToHide]) {\n clonedParams.query[keyToHide] = {}\n }\n\n clonedParams.query[keyToHide][key] = clonedParams[key]\n delete clonedParams[key]\n }\n })\n\n if (clonedParams) {\n context.params = clonedParams\n }\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { MaybeArray } from '../../internal.utils.js'\nimport { toArray } from '../../internal.utils.js'\nimport { FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } from '../params-for-server/params-for-from-shared.js'\n\nexport type paramsFromClientOptions = {\n /**\n * @default '_$client'\n */\n keyToHide?: string\n}\n\n/**\n * Server-side hook that extracts whitelisted properties from `query._$client` back\n * into `context.params`. This is the counterpart to `paramsForServer`, which encodes\n * params on the client side for transport.\n *\n * @example\n * ```ts\n * import { paramsFromClient } from 'feathers-utils/hooks'\n *\n * // Server-side\n * app.service('users').hooks({\n * before: { all: [paramsFromClient('populateParams')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/params-from-client.html\n */\nexport const paramsFromClient = (\n whitelist: MaybeArray<string>,\n options?: paramsFromClientOptions,\n) => {\n const whitelistArr = toArray(whitelist)\n const { keyToHide = FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } = options || {}\n function hook(context: HookContext): void\n function hook(context: HookContext, next: NextFunction): Promise<void>\n function hook(\n context: HookContext,\n next?: NextFunction,\n ): void | Promise<void> {\n if (\n !context.params?.query?.[keyToHide] ||\n typeof context.params.query[keyToHide] !== 'object'\n ) {\n if (next) return next()\n return\n }\n\n const params = {\n ...context.params,\n query: {\n ...context.params.query,\n [keyToHide]: {\n ...context.params.query[keyToHide],\n },\n },\n }\n\n const client = params.query[keyToHide]\n\n whitelistArr.forEach((key) => {\n if (key in client) {\n params[key] = client[key]\n delete client[key]\n }\n })\n\n if (Object.keys(client).length === 0) {\n delete params.query[keyToHide]\n }\n\n context.params = params\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import _has from 'lodash/has.js'\nimport _omit from 'lodash/omit.js'\nimport type { FeathersError } from '@feathersjs/errors'\nimport { BadRequest } from '@feathersjs/errors'\nimport { transformData } from '../transform-data/transform-data.hook.js'\nimport type { KeyOfOrDotNotation, MaybeArray } from '../../internal.utils.js'\nimport { toArray } from '../../internal.utils.js'\nimport type { HookContext } from '@feathersjs/feathers'\nimport type { DataSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport type PreventChangesOptions<D, Keys extends KeyOfOrDotNotation<D>> = {\n /**\n * Customize the error that is thrown if the service tries to patch a field that is not allowed.\n *\n * If not provided, throws a `BadRequest` error with a message indicating the field that is not allowed.\n */\n error?: boolean | ((item: D, name: Keys) => FeathersError)\n}\n\n/**\n * Prevents `patch` calls from modifying certain fields. By default, the protected\n * fields are silently removed from `context.data`. When `error` is set, a `BadRequest`\n * is thrown if any protected field is present.\n *\n * Supports dot.notation for nested fields.\n *\n * @example\n * ```ts\n * import { preventChanges } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { patch: [preventChanges(['email', 'role'], { error: true })] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/prevent-changes.html\n */\nexport const preventChanges = <\n H extends HookContext = HookContext,\n D extends DataSingleHookContext<H> = DataSingleHookContext<H>,\n Keys extends KeyOfOrDotNotation<D> = KeyOfOrDotNotation<D>,\n>(\n fieldNames: MaybeArray<Keys>,\n options?: PreventChangesOptions<D, Keys>,\n) => {\n const fieldNamesArr = toArray(fieldNames)\n\n return transformData<H>((item) => {\n if (options?.error) {\n for (let i = 0; i < fieldNamesArr.length; i++) {\n const name = fieldNamesArr[i]\n\n if (_has(item, name)) {\n const error =\n typeof options.error === 'function'\n ? options.error(item as D, name)\n : new BadRequest(\n `Field ${String(name)} may not be patched. (preventChanges)`,\n )\n\n throw error\n }\n }\n } else {\n return _omit(item, fieldNamesArr)\n }\n\n return item\n })\n}\n","import { TooManyRequests } from '@feathersjs/errors'\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { RateLimiterAbstract, RateLimiterRes } from 'rate-limiter-flexible'\nimport { checkContext } from '../../utils/index.js'\nimport type { Promisable } from '../../internal.utils.js'\n\nexport type RateLimitOptions<H extends HookContext = HookContext> = {\n /** Generate the rate-limiting key. Defaults to `context.path`. */\n key?: (context: H) => Promisable<string>\n /** Number of points to consume per request. Defaults to `1`. */\n points?: (context: H) => Promisable<number>\n}\n\n/**\n * Rate limits service method calls using `rate-limiter-flexible`.\n * You provide a pre-configured `RateLimiterAbstract` instance\n * (Memory, Redis, Mongo, etc.) and the hook consumes points per request.\n *\n * @example\n * ```ts\n * import { rateLimit } from 'feathers-utils/hooks'\n * import { RateLimiterMemory } from 'rate-limiter-flexible'\n *\n * const rateLimiter = new RateLimiterMemory({ points: 10, duration: 1 })\n *\n * app.service('users').hooks({\n * before: { find: [rateLimit(rateLimiter)] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/rate-limit.html\n */\nexport const rateLimit = <H extends HookContext = HookContext>(\n rateLimiter: RateLimiterAbstract,\n options?: RateLimitOptions<H>,\n) => {\n const key = options?.key ?? ((context: HookContext) => context.path)\n const points = options?.points ?? (() => 1)\n\n return async (context: H, next?: NextFunction): Promise<void> => {\n checkContext(context, { type: ['before', 'around'], label: 'rateLimit' })\n\n const resolvedKey = await key(context)\n const resolvedPoints = await points(context)\n\n try {\n const res = await rateLimiter.consume(resolvedKey, resolvedPoints)\n context.params.rateLimit = res\n } catch (res) {\n context.params.rateLimit = res as RateLimiterRes\n throw new TooManyRequests('Too many requests', {\n rateLimitRes: res as RateLimiterRes,\n })\n }\n\n if (next) await next()\n }\n}\n","import _get from 'lodash/get.js'\nimport _set from 'lodash/set.js'\nimport _has from 'lodash/has.js'\n\nimport type { FeathersError } from '@feathersjs/errors'\nimport { Forbidden } from '@feathersjs/errors'\n\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { PropertyPath } from 'lodash'\nimport { contextToJson } from '../../utils/context-to-json/context-to-json.util.js'\nimport { getDataIsArray } from '../../utils/index.js'\nimport type { PredicateItemWithContext } from '../../types.js'\n\nexport interface HookSetDataOptions {\n /**\n * Wether to throw if the context[from] is undefined.\n *\n * @default false\n */\n allowUndefined?: boolean\n /**\n * @default true\n */\n overwrite?: boolean | PredicateItemWithContext\n /**\n * Customize the error that is thrown if the context[from] is not available.\n * If not provided, throws a `Forbidden` error with a message indicating the missing field.\n */\n error?: (context: HookContext, from: PropertyPath) => FeathersError\n}\n\n/**\n * Sets a property on each item in `context.data` from another property on the hook context.\n * Supports dot-notation paths for both source and target. Throws a `Forbidden` error\n * if the source field is missing (unless `allowUndefined` is `true`).\n *\n * @example\n * ```ts\n * import { setData } from 'feathers-utils/hooks'\n *\n * app.service('posts').hooks({\n * before: { create: [setData('params.user.id', 'userId')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/set-data.html\n */\nexport function setData<H extends HookContext = HookContext>(\n /**\n * The property path of the context to set the value from. 'dot.notation' is supported.\n *\n * If the property does not exist, the hook will throw an error unless `allowUndefined` is set to true.\n * If the property exists, it will be set to the value of the `to` property path of the data item.\n *\n * @example 'params.user.id'\n */\n from: PropertyPath,\n /**\n * The property path of the data item to set the value to. 'dot.notation' is supported.\n *\n * If the property does not exist, it will be created.\n * If the property exists, it will be overwritten unless `overwrite` is set to false.\n *\n * @example 'userId'\n */\n to: PropertyPath,\n options?: HookSetDataOptions,\n) {\n const { allowUndefined = false, overwrite = true } = options ?? {}\n\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n const { data } = getDataIsArray(context)\n\n const contextJson = contextToJson(context)\n\n if (!_has(contextJson, from)) {\n if (!context.params?.provider || allowUndefined === true) {\n if (next) return next()\n return\n }\n\n if (\n !overwrite &&\n data.every((item: Record<string, unknown>) => _has(item, to))\n ) {\n if (next) return next()\n return\n }\n\n throw options?.error\n ? options.error(context, from)\n : new Forbidden(`Expected field ${from.toString()} not available`)\n }\n\n const val = _get(contextJson, from)\n\n for (let i = 0, len = data.length; i < len; i++) {\n const item: Record<string, unknown> = data[i]\n\n const currentOverwrite =\n typeof overwrite === 'function' ? overwrite(item, context) : overwrite\n\n if (!currentOverwrite && _has(item, to)) {\n continue\n }\n\n _set(item, to, val)\n }\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import _get from 'lodash/get.js'\nimport _setWith from 'lodash/setWith.js'\nimport _clone from 'lodash/clone.js'\nimport { checkContext } from '../../utils/index.js'\nimport type { FeathersError } from '@feathersjs/errors'\nimport { Forbidden } from '@feathersjs/errors'\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\n\nexport interface SetFieldOptions {\n as: string\n from: string\n /**\n * If set to `true`, allows the field to be undefined.\n * If the field is not available and this is `true`, the hook will not throw an error.\n *\n * If set to `false`, the hook will throw an error if the field is not available.\n *\n * @default false\n */\n allowUndefined?: boolean\n /**\n * Customize the error that is thrown if the field is not available.\n *\n * If not provided, throws a `Forbidden` error with a message indicating the missing field.\n */\n error?: (context: HookContext, from: string) => FeathersError\n}\n\n/**\n * Sets a field on the hook context (e.g. `params.query`) based on the value of another\n * context field (e.g. `params.user.id`). Useful for scoping queries to the authenticated user.\n * Throws a `Forbidden` error if the source field is missing (unless `allowUndefined` is `true`).\n *\n * @example\n * ```ts\n * import { setField } from 'feathers-utils/hooks'\n *\n * app.service('posts').hooks({\n * before: { all: [setField({ from: 'params.user.id', as: 'params.query.userId' })] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/set-field.html\n */\nexport const setField = <H extends HookContext = HookContext>({\n as,\n from,\n allowUndefined = false,\n error,\n}: SetFieldOptions) => {\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n const { params } = context\n\n checkContext(context, { type: ['before', 'around'], label: 'setField' })\n\n const value = _get(context, from)\n\n if (value === undefined) {\n if (!params.provider || allowUndefined) {\n if (next) return next()\n return\n }\n\n throw error\n ? error(context, from)\n : new Forbidden(`Expected field ${as} not available`)\n }\n\n _setWith(context, as, value, _clone)\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import _get from 'lodash/get.js'\nimport _set from 'lodash/set.js'\nimport _has from 'lodash/has.js'\n\nimport type { FeathersError } from '@feathersjs/errors'\nimport { Forbidden } from '@feathersjs/errors'\n\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { PropertyPath } from 'lodash'\nimport { contextToJson } from '../../utils/context-to-json/context-to-json.util.js'\nimport { getResultIsArray } from '../../utils/index.js'\nimport type { DispatchOption, PredicateItemWithContext } from '../../types.js'\n\nexport interface SetResultOptions {\n /**\n * Wether to throw if the context[from] is undefined.\n *\n * @default false\n */\n allowUndefined?: boolean\n /**\n * @default true\n */\n overwrite?: boolean | PredicateItemWithContext\n /**\n * Customize the error that is thrown if the context[from] is not available.\n * If not provided, throws a `Forbidden` error with a message indicating the missing field.\n */\n error?: (context: HookContext, from: PropertyPath) => FeathersError\n dispatch?: DispatchOption\n}\n\n/**\n * Sets a property on each item in `context.result` from another property on the hook context.\n * Supports dot-notation paths for both source and target, and can optionally\n * operate on `context.dispatch` as well.\n *\n * @example\n * ```ts\n * import { setResult } from 'feathers-utils/hooks'\n *\n * app.service('posts').hooks({\n * after: { all: [setResult('params.user.id', 'currentUserId')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/set-result.html\n */\nexport function setResult<H extends HookContext = HookContext>(\n /**\n * The property path of the context to set the value from. 'dot.notation' is supported.\n *\n * If the property does not exist, the hook will throw an error unless `allowUndefined` is set to true.\n * If the property exists, it will be set to the value of the `to` property path of the data item.\n *\n * @example 'params.user.id'\n */\n from: PropertyPath,\n /**\n * The property path of the data item to set the value to. 'dot.notation' is supported.\n *\n * If the property does not exist, it will be created.\n * If the property exists, it will be overwritten unless `overwrite` is set to false.\n *\n * @example 'userId'\n */\n to: PropertyPath,\n options?: SetResultOptions,\n) {\n const { allowUndefined = false, overwrite = true } = options ?? {}\n\n const forResultOrDispatch = (context: H, dispatch: boolean) => {\n const { result } = getResultIsArray(context, { dispatch })\n\n const contextJson = contextToJson(context)\n\n if (!_has(contextJson, from)) {\n if (!context.params?.provider || allowUndefined === true) {\n return context\n }\n\n if (\n !overwrite &&\n result.every((item: Record<string, unknown>) => _has(item, to))\n ) {\n return context\n }\n\n throw options?.error\n ? options.error(context, from)\n : new Forbidden(`Expected field ${from.toString()} not available`)\n }\n\n const val = _get(contextJson, from)\n\n for (let i = 0; i < result.length; i++) {\n const item: Record<string, unknown> = result[i]\n\n const currentOverwrite =\n typeof overwrite === 'function' ? overwrite(item, context) : overwrite\n\n if (!currentOverwrite && _has(item, to)) {\n continue\n }\n\n _set(item, to, val)\n }\n\n return context\n }\n\n const fn = (context: H) => {\n if (options?.dispatch === 'both') {\n forResultOrDispatch(context, true)\n return forResultOrDispatch(context, false)\n }\n\n return forResultOrDispatch(context, !!options?.dispatch)\n }\n\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n if (next) {\n return next().then(() => {\n fn(context)\n })\n }\n\n fn(context)\n return\n }\n return hook\n}\n","import _set from 'lodash/set.js'\nimport type { HookContext, NextFunction } from '@feathersjs/feathers'\n\n/**\n * Extracts URL route parameters (slugs) and sets them on `params.query`.\n * For example, given a route `/stores/:storeId`, this hook copies the resolved\n * `storeId` value from `params.route` into the query. Only applies to the `rest` provider.\n *\n * @example\n * ```ts\n * import { setSlug } from 'feathers-utils/hooks'\n *\n * app.service('stores/:storeId/products').hooks({\n * before: { all: [setSlug('storeId')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/set-slug.html\n */\nexport const setSlug = <H extends HookContext = HookContext>(\n slug: string,\n fieldName?: string,\n) => {\n const targetField: string =\n typeof fieldName === 'string' ? fieldName : `query.${slug}`\n\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n if (context.params && context.params.provider === 'rest') {\n const value = context.params.route[slug]\n if (typeof value === 'string' && value[0] !== ':') {\n _set(context.params, targetField, value)\n }\n }\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { addToQuery, checkContext } from '../../utils/index.js'\nimport type { TransformParamsFn } from '../../types.js'\nimport { transformParams } from '../../utils/transform-params/transform-params.util.js'\nimport { early, type Promisable } from '../../internal.utils.js'\nimport { isPromise } from '../../common/index.js'\n\nexport type SoftDeleteOptionFunction<H extends HookContext = HookContext> = (\n context?: H,\n) => Promisable<{ [key: string]: any }>\n\nexport interface SoftDeleteOptions<H extends HookContext = HookContext> {\n /**\n * @example { deletedAt: null }\n */\n deletedQuery: { [key: string]: any } | SoftDeleteOptionFunction<H>\n /**\n * @example { deletedAt: new Date() }\n */\n removeData: { [key: string]: any } | SoftDeleteOptionFunction<H>\n /**\n * Transform the params before calling the service method. E.g. remove 'params.provider' or add custom params.\n */\n transformParams?: TransformParamsFn\n\n /**\n * Key in `params` to disable the soft delete functionality.\n *\n * @default 'disableSoftDelete'\n */\n disableSoftDeleteKey?: string\n\n /**\n * `softDelete` uses `._patch()` internally to mark items as deleted.\n *\n * If you set this option to `true`, it will use the `.patch()` method with hooks instead.\n */\n usePatchWithHooks?: boolean\n}\n\n/**\n * Marks items as deleted instead of physically removing them. On `remove`, the hook\n * patches the record with `removeData` (e.g. `{ deletedAt: new Date() }`). On all other\n * methods, it appends `deletedQuery` (e.g. `{ deletedAt: null }`) to filter out soft-deleted items.\n *\n * @example\n * ```ts\n * import { softDelete } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * around: {\n * all: [softDelete({ deletedQuery: { deletedAt: null }, removeData: { deletedAt: new Date() } })]\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/soft-delete.html\n */\nexport const softDelete = <H extends HookContext = HookContext>(\n options: SoftDeleteOptions<H>,\n) => {\n if (!options?.deletedQuery || !options?.removeData) {\n throw new Error(\n 'You must provide `deletedQuery` and `removeData` options to the softDelete hook.',\n )\n }\n\n return async (context: H, next?: NextFunction): Promise<void> => {\n checkContext(context, { type: ['before', 'around'], label: 'softDelete' })\n\n const { disableSoftDeleteKey = 'disableSoftDelete' } = options\n\n if (context.params[disableSoftDeleteKey]) {\n await early(context, next)\n return\n }\n\n const { deletedQuery, removeData } = options\n\n let deleteQuery = getValue(deletedQuery, context)\n if (isPromise(deleteQuery)) {\n deleteQuery = await deleteQuery\n }\n\n const query = addToQuery(context.params.query, deleteQuery)\n\n const params = transformParams(\n {\n ...context.params,\n query,\n },\n options.transformParams,\n )\n\n context.params = params\n\n if (context.method === 'remove') {\n let data = getValue(removeData, context)\n if (isPromise(data)) {\n data = await data\n }\n const method = options.usePatchWithHooks ? 'patch' : '_patch'\n const result = await context.service[method](context.id, data, params)\n\n context.result = result\n }\n\n if (next) {\n await next()\n }\n }\n}\n\nconst getValue = (value: any, ...args: any[]) => {\n if (typeof value === 'function') {\n return value(...args)\n }\n return value\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { checkContext } from '../../utils/index.js'\n\nexport type StashableOptions = {\n /** The property name on `context.params` to store the stash function. @default 'stashed' */\n propName?: string\n /** Custom function to fetch the pre-mutation state. Defaults to `service.get` or `service.find`. */\n stashFunc?: (context: HookContext) => Promise<any>\n}\n\nconst defaultStashFunc = (context: HookContext) => {\n const isMulti = context.id == null\n\n const params = {\n ...context.params,\n _stashable: true,\n ...(isMulti ? { paginate: false } : {}),\n }\n\n return isMulti\n ? context.service.find(params)\n : context.service.get(context.id, params)\n}\n\n/**\n * Stashes the pre-mutation state of a record into `context.params`.\n * Eagerly starts the fetch but exposes a memoized function — calling it\n * multiple times only hits the database once.\n * Use in `before` hooks on `update`, `patch`, or `remove` methods.\n *\n * @example\n * ```ts\n * import { stashable } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { patch: [stashable()] }\n * })\n *\n * // In a later hook (before or after):\n * const before = await context.params.stashed()\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/stashable.html\n */\nexport function stashable<H extends HookContext = HookContext>(\n options?: StashableOptions,\n) {\n const propName = options?.propName ?? 'stashed'\n const stashFunc = options?.stashFunc ?? defaultStashFunc\n\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n if (context.params._stashable) {\n if (next) return next()\n return\n }\n\n checkContext(context, {\n type: ['before', 'around'],\n method: ['update', 'patch', 'remove'],\n label: 'stashable',\n })\n\n const promise = stashFunc(context).catch(() => undefined)\n\n context.params[propName] = () => promise\n\n if (next) return next()\n\n return\n }\n return hook\n}\n","import type { HookContext } from '@feathersjs/feathers'\nimport type { PredicateFn } from '../../types.js'\nimport { BadRequest, type FeathersError } from '@feathersjs/errors'\nimport { every, isMulti } from '../../predicates/index.js'\nimport { throwIf } from '../throw-if/throw-if.hook.js'\n\nexport type ThrowIfIsMultiOptions = {\n /**\n * A predicate function to filter the contexts that should be checked for multi operations.\n * If provided, only contexts that pass this predicate will be checked for multi operations.\n */\n filter?: PredicateFn\n /**\n * Customize the error that is thrown if the context is multi and the service does not allow it.\n * If not provided, throws a `BadRequest` error.\n */\n error?: (context: HookContext) => FeathersError\n}\n\nconst defaultError = (context: HookContext) =>\n new BadRequest(`Cannot perform multi operation on method '${context.method}'`)\n\n/**\n * Throws a `BadRequest` error when the current operation is a multi operation\n * (array data on `create`, or `id === null` on `patch`/`remove`).\n * Useful to prevent bulk operations on services that should only handle single items.\n *\n * @example\n * ```ts\n * import { throwIfIsMulti } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * before: { all: [throwIfIsMulti()] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/throw-if-is-multi.html\n */\nexport const throwIfIsMulti = <H extends HookContext = HookContext>(\n options?: ThrowIfIsMultiOptions,\n) =>\n throwIf<H>(\n every(\n every(isMulti, (context) => context.method !== 'find'),\n options?.filter,\n ),\n {\n error: options?.error ?? defaultError,\n },\n )\n","import type { HookContext } from '@feathersjs/feathers'\nimport type { PredicateFn, TransportName } from '../../types.js'\nimport { throwIf } from '../throw-if/throw-if.hook.js'\nimport { every, isProvider } from '../../predicates/index.js'\nimport type { FeathersError } from '@feathersjs/errors'\nimport { MethodNotAllowed } from '@feathersjs/errors'\nimport { toArray } from '../../internal.utils.js'\n\nconst defaultError = (context: HookContext) =>\n new MethodNotAllowed(\n `Provider '${context.params.provider}' can not call '${context.method}'.`,\n )\n\nexport type ThrowIfIsIsProviderOptions = {\n filter?: PredicateFn\n /**\n * Customize the error that is thrown if the context is a provider and the service does not allow it.\n * If not provided, throws a `MethodNotAllowed` error.\n */\n error?: (context: HookContext) => FeathersError\n}\n\n/**\n * Throws a `MethodNotAllowed` error when the request comes from one of the specified transports.\n * Combines `throwIf` with the `isProvider` predicate for a convenient one-liner.\n * Use this to restrict methods to server-only or specific transport types.\n *\n * @example\n * ```ts\n * import { throwIfIsProvider } from 'feathers-utils/hooks'\n *\n * app.service('internal').hooks({\n * before: { all: [throwIfIsProvider('external')] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/throw-if-is-provider.html\n */\nexport const throwIfIsProvider = <H extends HookContext = HookContext>(\n transports: TransportName | TransportName[],\n options?: ThrowIfIsIsProviderOptions,\n) => {\n const disallowTransports = toArray(transports)\n\n return throwIf<H>(\n every(isProvider(...(disallowTransports as any)), options?.filter),\n {\n error: options?.error ?? defaultError,\n },\n )\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { traverse as _traverse } from '../../common/index.js'\n\nexport type TraverseOptions = {\n transformer: (transformContext: any) => any\n getObject: (\n context: HookContext,\n ) => Record<string, any> | Record<string, any>[]\n}\n\n/**\n * Recursively walks and transforms fields in record(s) using `neotraverse`.\n * The `getObject` function extracts the target from the context, and `transformer`\n * is called for every node during traversal --- ideal for deep, structural transformations.\n *\n * @example\n * ```ts\n * import { traverse } from 'feathers-utils/hooks'\n *\n * app.service('users').hooks({\n * after: {\n * all: [traverse({ getObject: (ctx) => ctx.result, transformer: function () { if (this.key === 'password') this.remove() } })]\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/traverse.html\n */\nexport const traverse = <H extends HookContext = HookContext>({\n transformer,\n getObject,\n}: TraverseOptions) => {\n function hook(context: H): void\n function hook(context: H, next: NextFunction): Promise<void>\n function hook(context: H, next?: NextFunction): void | Promise<void> {\n _traverse(getObject(context), transformer)\n\n if (next) return next()\n\n return\n }\n return hook\n}\n"],"mappings":"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"}
|