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.
Files changed (50) hide show
  1. package/dist/{hooks-DPFxxjBu.mjs → hooks-CzxNpt2c.mjs} +89 -77
  2. package/dist/hooks-CzxNpt2c.mjs.map +1 -0
  3. package/dist/hooks.d.mts +53 -24
  4. package/dist/hooks.mjs +4 -4
  5. package/dist/index.d.mts +2 -2
  6. package/dist/index.mjs +5 -5
  7. package/dist/{predicates-CT08opkD.mjs → predicates-C2SeOKGd.mjs} +16 -11
  8. package/dist/{predicates-CT08opkD.mjs.map → predicates-C2SeOKGd.mjs.map} +1 -1
  9. package/dist/predicates.d.mts +1 -1
  10. package/dist/predicates.mjs +1 -1
  11. package/dist/{resolve-Cx9osy8O.mjs → resolve-B81gQqXW.mjs} +2 -2
  12. package/dist/resolve-B81gQqXW.mjs.map +1 -0
  13. package/dist/resolvers.mjs +1 -1
  14. package/dist/{transform-result.hook-BUwLePT2.d.mts → transform-result.hook-C8-4Lezj.d.mts} +8 -5
  15. package/dist/{transform-result.hook-CevWK5TA.mjs → transform-result.hook-DifNj7zf.mjs} +12 -11
  16. package/dist/transform-result.hook-DifNj7zf.mjs.map +1 -0
  17. package/dist/transformers.d.mts +1 -1
  18. package/dist/transformers.mjs +1 -1
  19. package/dist/{unless.hook-BYWO9hzO.d.mts → unless.hook-CVD7SrZh.d.mts} +6 -3
  20. package/dist/{utils-1I_iPZkV.mjs → utils-ByzrJKGQ.mjs} +2 -2
  21. package/dist/{utils-1I_iPZkV.mjs.map → utils-ByzrJKGQ.mjs.map} +1 -1
  22. package/dist/utils.mjs +2 -2
  23. package/package.json +1 -1
  24. package/src/hooks/cache/cache.hook.ts +9 -7
  25. package/src/hooks/check-multi/check-multi.hook.ts +5 -2
  26. package/src/hooks/check-required/check-required.hook.ts +6 -1
  27. package/src/hooks/create-related/create-related.hook.ts +2 -2
  28. package/src/hooks/debug/debug.hook.ts +1 -1
  29. package/src/hooks/disable-pagination/disable-pagination.hook.ts +7 -4
  30. package/src/hooks/disallow/disallow.hook.ts +7 -2
  31. package/src/hooks/on-delete/on-delete.hook.ts +2 -2
  32. package/src/hooks/params-for-server/params-for-server.hook.ts +12 -5
  33. package/src/hooks/params-from-client/params-from-client.hook.ts +10 -6
  34. package/src/hooks/rate-limit/rate-limit.hook.ts +2 -2
  35. package/src/hooks/set-data/set-data.hook.ts +8 -7
  36. package/src/hooks/set-field/set-field.hook.ts +14 -11
  37. package/src/hooks/set-result/set-result.hook.ts +9 -3
  38. package/src/hooks/set-slug/set-slug.hook.ts +8 -6
  39. package/src/hooks/skippable/skippable.hook.ts +15 -12
  40. package/src/hooks/soft-delete/soft-delete.hook.ts +4 -5
  41. package/src/hooks/stashable/stashable.hook.ts +9 -8
  42. package/src/hooks/throw-if/throw-if.hook.ts +2 -2
  43. package/src/hooks/transform-data/transform-data.hook.ts +2 -4
  44. package/src/hooks/transform-query/transform-query.hook.ts +6 -5
  45. package/src/hooks/transform-result/transform-result.hook.ts +6 -9
  46. package/src/hooks/traverse/traverse.hook.ts +11 -10
  47. package/src/resolvers/resolve-result/resolve-result.ts +4 -1
  48. package/dist/hooks-DPFxxjBu.mjs.map +0 -1
  49. package/dist/resolve-Cx9osy8O.mjs.map +0 -1
  50. package/dist/transform-result.hook-CevWK5TA.mjs.map +0 -1
@@ -21,20 +21,22 @@ export const setSlug = <H extends HookContext = HookContext>(
21
21
  slug: string,
22
22
  fieldName?: string,
23
23
  ) => {
24
- if (typeof fieldName !== 'string') {
25
- fieldName = `query.${slug}`
26
- }
24
+ const targetField: string =
25
+ typeof fieldName === 'string' ? fieldName : `query.${slug}`
27
26
 
28
- return (context: H, next?: NextFunction) => {
27
+ function hook(context: H): void
28
+ function hook(context: H, next: NextFunction): Promise<void>
29
+ function hook(context: H, next?: NextFunction): void | Promise<void> {
29
30
  if (context.params && context.params.provider === 'rest') {
30
31
  const value = context.params.route[slug]
31
32
  if (typeof value === 'string' && value[0] !== ':') {
32
- _set(context.params, fieldName, value)
33
+ _set(context.params, targetField, value)
33
34
  }
34
35
  }
35
36
 
36
37
  if (next) return next()
37
38
 
38
- return context
39
+ return
39
40
  }
41
+ return hook
40
42
  }
@@ -15,26 +15,29 @@ import type { HookFunction, PredicateFn } from '../../types.js'
15
15
  *
16
16
  * @see https://utils.feathersjs.com/hooks/skippable.html
17
17
  */
18
- export const skippable =
19
- <H extends HookContext = HookContext>(
20
- hook: HookFunction<H>,
21
- predicate: PredicateFn<H>,
22
- ) =>
23
- (context: H, next?: NextFunction) => {
18
+ export const skippable = <H extends HookContext = HookContext>(
19
+ innerHook: HookFunction<H>,
20
+ predicate: PredicateFn<H>,
21
+ ) => {
22
+ function hook(context: H): void
23
+ function hook(context: H, next: NextFunction): Promise<void>
24
+ function hook(context: H, next?: NextFunction): void | Promise<void> {
24
25
  const skip = predicate(context)
25
26
 
26
- function skipOrRun(skip: boolean) {
27
- if (skip) {
27
+ const skipOrRun = (shouldSkip: boolean): void | Promise<void> => {
28
+ if (shouldSkip) {
28
29
  if (next) return next()
29
- return context
30
- } else {
31
- return hook(context, next)
30
+ return
32
31
  }
32
+ if (next) return innerHook(context, next) as Promise<void>
33
+ innerHook(context)
33
34
  }
34
35
 
35
36
  if (!skip || typeof skip === 'boolean') {
36
37
  return skipOrRun(skip)
37
38
  }
38
39
 
39
- return skip.then(skipOrRun)
40
+ return skip.then(skipOrRun) as Promise<void>
40
41
  }
42
+ return hook
43
+ }
@@ -65,13 +65,14 @@ export const softDelete = <H extends HookContext = HookContext>(
65
65
  )
66
66
  }
67
67
 
68
- return async (context: H, next?: NextFunction) => {
68
+ return async (context: H, next?: NextFunction): Promise<void> => {
69
69
  checkContext(context, { type: ['before', 'around'], label: 'softDelete' })
70
70
 
71
71
  const { disableSoftDeleteKey = 'disableSoftDelete' } = options
72
72
 
73
73
  if (context.params[disableSoftDeleteKey]) {
74
- return early(context, next)
74
+ await early(context, next)
75
+ return
75
76
  }
76
77
 
77
78
  const { deletedQuery, removeData } = options
@@ -105,10 +106,8 @@ export const softDelete = <H extends HookContext = HookContext>(
105
106
  }
106
107
 
107
108
  if (next) {
108
- return await next()
109
+ await next()
109
110
  }
110
-
111
- return context
112
111
  }
113
112
  }
114
113
 
@@ -44,17 +44,16 @@ const defaultStashFunc = (context: HookContext) => {
44
44
  */
45
45
  export function stashable<H extends HookContext = HookContext>(
46
46
  options?: StashableOptions,
47
- ): {
48
- (context: H, next: NextFunction): Promise<void>
49
- (context: H): H
50
- } {
47
+ ) {
51
48
  const propName = options?.propName ?? 'stashed'
52
49
  const stashFunc = options?.stashFunc ?? defaultStashFunc
53
50
 
54
- return ((context: H, next?: NextFunction) => {
51
+ function hook(context: H): void
52
+ function hook(context: H, next: NextFunction): Promise<void>
53
+ function hook(context: H, next?: NextFunction): void | Promise<void> {
55
54
  if (context.params._stashable) {
56
55
  if (next) return next()
57
- return context
56
+ return
58
57
  }
59
58
 
60
59
  checkContext(context, {
@@ -68,6 +67,8 @@ export function stashable<H extends HookContext = HookContext>(
68
67
  context.params[propName] = () => promise
69
68
 
70
69
  if (next) return next()
71
- return context
72
- }) as any
70
+
71
+ return
72
+ }
73
+ return hook
73
74
  }
@@ -32,7 +32,7 @@ export const throwIf = <H extends HookContext = HookContext>(
32
32
  predicate: PredicateFn,
33
33
  options?: ThrowIfOptions,
34
34
  ) => {
35
- return async (context: H, next?: NextFunction) => {
35
+ return async (context: H, next?: NextFunction): Promise<void> => {
36
36
  const result = await predicate(context)
37
37
 
38
38
  if (result) {
@@ -42,7 +42,7 @@ export const throwIf = <H extends HookContext = HookContext>(
42
42
  }
43
43
 
44
44
  if (next) {
45
- return await next()
45
+ await next()
46
46
  }
47
47
  }
48
48
  }
@@ -29,12 +29,10 @@ export const transformData =
29
29
  <H extends HookContext = HookContext, D = Data<H>>(
30
30
  transformer: TransformerInputFn<D, H>,
31
31
  ) =>
32
- async (context: H, next?: NextFunction) => {
32
+ async (context: H, next?: NextFunction): Promise<void> => {
33
33
  await mutateData(context, transformer)
34
34
 
35
35
  if (next) {
36
- return next()
36
+ await next()
37
37
  }
38
-
39
- return context
40
38
  }
@@ -23,16 +23,17 @@ export const transformQuery = <
23
23
  >(
24
24
  transformer: TransformerFn<Q, H>,
25
25
  ) => {
26
- return (context: H, next?: NextFunction) => {
26
+ function hook(context: H): void
27
+ function hook(context: H, next: NextFunction): Promise<void>
28
+ function hook(context: H, next?: NextFunction): void | Promise<void> {
27
29
  context.params.query = transformer(context.params.query ?? {}, {
28
30
  context,
29
31
  i: 0,
30
32
  })
31
33
 
32
- if (next) {
33
- return next().then(() => context)
34
- }
34
+ if (next) return next()
35
35
 
36
- return context
36
+ return
37
37
  }
38
+ return hook
38
39
  }
@@ -1,10 +1,6 @@
1
1
  import type { HookContext, NextFunction } from '@feathersjs/feathers'
2
2
  import { mutateResult } from '../../utils/mutate-result/mutate-result.util.js'
3
- import type {
4
- DispatchOption,
5
- HookFunction,
6
- TransformerInputFn,
7
- } from '../../types.js'
3
+ import type { DispatchOption, TransformerInputFn } from '../../types.js'
8
4
  import type { ResultSingleHookContext } from '../../utility-types/hook-context.js'
9
5
  import type { AnyFallback } from '../../internal.utils.js'
10
6
 
@@ -37,9 +33,10 @@ export const transformResult =
37
33
  <H extends HookContext = HookContext, R = Result<H>>(
38
34
  transformer: TransformerInputFn<R, H>,
39
35
  options?: TransformResultOptions,
40
- ): HookFunction<H> =>
41
- (context: H, next?: NextFunction) =>
42
- mutateResult(context, transformer, {
36
+ ) =>
37
+ async (context: H, next?: NextFunction): Promise<void> => {
38
+ await mutateResult(context, transformer, {
43
39
  next,
44
40
  dispatch: options?.dispatch,
45
- }) as Promise<H>
41
+ })
42
+ }
@@ -26,17 +26,18 @@ export type TraverseOptions = {
26
26
  *
27
27
  * @see https://utils.feathersjs.com/hooks/traverse.html
28
28
  */
29
- export const traverse =
30
- <H extends HookContext = HookContext>({
31
- transformer,
32
- getObject,
33
- }: TraverseOptions) =>
34
- (context: H, next?: NextFunction) => {
29
+ export const traverse = <H extends HookContext = HookContext>({
30
+ transformer,
31
+ getObject,
32
+ }: TraverseOptions) => {
33
+ function hook(context: H): void
34
+ function hook(context: H, next: NextFunction): Promise<void>
35
+ function hook(context: H, next?: NextFunction): void | Promise<void> {
35
36
  _traverse(getObject(context), transformer)
36
37
 
37
- if (next) {
38
- return next()
39
- }
38
+ if (next) return next()
40
39
 
41
- return context
40
+ return
42
41
  }
42
+ return hook
43
+ }
@@ -25,7 +25,10 @@ type Result<H extends HookContext> = AnyFallback<
25
25
  * })
26
26
  * ```
27
27
  */
28
- export const resolveResult = <H extends HookContext = HookContext, R = Result<H>>(
28
+ export const resolveResult = <
29
+ H extends HookContext = HookContext,
30
+ R = Result<H>,
31
+ >(
29
32
  resolvers: ResolverObject<R, H>,
30
33
  ): {
31
34
  (context: H, next: NextFunction): Promise<void>
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks-DPFxxjBu.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) => {\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 (context: HookContext, cacheMap: ContextCacheMap) => {\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 return context\n}\n\nconst cacheAfter = async (context: HookContext, cacheMap: ContextCacheMap) => {\n if (context.method === 'get' || context.method === 'find') {\n await cacheMap.set(context)\n } else {\n await cacheMap.clear(context)\n }\n\n return context\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 return (context: H, next?: NextFunction) => {\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 context\n }\n\n throw options?.error\n ? options.error(context)\n : new MethodNotAllowed(`Can not ${method} multiple entries`)\n }\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 return (context: H, next?: NextFunction) => {\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}\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) => {\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 context\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) => {\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 =\n <H extends HookContext = HookContext>() =>\n (context: H, next?: NextFunction) => {\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 context\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 return (context: H, next?: NextFunction) => {\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().then(() => context)\n }\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) => {\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 context\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 return <H extends HookContext>(context: H, next?: NextFunction) => {\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) {\n return next()\n }\n\n return context\n }\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 return (context: HookContext, next?: NextFunction) => {\n if (\n !context.params?.query?.[keyToHide] ||\n typeof context.params.query[keyToHide] !== 'object'\n ) {\n if (next) return next()\n return context\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) {\n return next()\n }\n\n return context\n }\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) => {\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) return 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 return (context: H, next?: NextFunction) => {\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 context\n }\n\n if (\n !overwrite &&\n data.every((item: Record<string, unknown>) => _has(item, to))\n ) {\n if (next) return next()\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, 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) {\n return next()\n }\n\n return context\n }\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 =\n <H extends HookContext = HookContext>({\n as,\n from,\n allowUndefined = false,\n error,\n }: SetFieldOptions) =>\n (context: H, next?: NextFunction) => {\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 context\n }\n\n throw error\n ? error(context, from)\n : new Forbidden(`Expected field ${as} not available`)\n }\n\n context = _setWith(context, as, value, _clone)\n\n if (next) return next()\n\n return context\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 return (context: H, next?: NextFunction) => {\n if (next) {\n return next().then(() => fn(context))\n }\n\n return fn(context)\n }\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 if (typeof fieldName !== 'string') {\n fieldName = `query.${slug}`\n }\n\n return (context: H, next?: NextFunction) => {\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, fieldName, value)\n }\n }\n\n if (next) return next()\n\n return context\n }\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) => {\n checkContext(context, { type: ['before', 'around'], label: 'softDelete' })\n\n const { disableSoftDeleteKey = 'disableSoftDelete' } = options\n\n if (context.params[disableSoftDeleteKey]) {\n return early(context, next)\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 return await next()\n }\n\n return context\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 (context: H, next: NextFunction): Promise<void>\n (context: H): H\n} {\n const propName = options?.propName ?? 'stashed'\n const stashFunc = options?.stashFunc ?? defaultStashFunc\n\n return ((context: H, next?: NextFunction) => {\n if (context.params._stashable) {\n if (next) return next()\n return context\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 return context\n }) as any\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 =\n <H extends HookContext = HookContext>({\n transformer,\n getObject,\n }: TraverseOptions) =>\n (context: H, next?: NextFunction) => {\n _traverse(getObject(context), transformer)\n\n if (next) {\n return next()\n }\n\n return context\n }\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolve-Cx9osy8O.mjs","names":["resolve","resolve","resolve","resolve"],"sources":["../src/resolvers/resolvers.internal.ts","../src/resolvers/resolve-data/resolve-data.ts","../src/resolvers/resolve-result/resolve-result.ts","../src/resolvers/resolve-query/resolve-query.ts","../src/resolvers/resolve/resolve.ts"],"sourcesContent":["import { BadRequest } from '@feathersjs/errors'\nimport type { Promisable } from '../internal.utils.js'\n\nexport interface ResolverPropertyOptions<T, V, C> {\n value: V | undefined\n data: T\n context: C\n properties: ResolverStatus<T, C>\n i: number\n}\n\nexport type ResolverProperty<T, V, C, R = V> = (\n options: ResolverPropertyOptions<T, V, C>,\n) => Promisable<R | undefined>\n\nexport type ResolverObject<T, C> = {\n [K in keyof T & string]?: ResolverProperty<T, T[K], C, T[K]>\n}\n\nexport interface ResolverStatus<T, C> {\n path: string[]\n stack: ResolverProperty<T, any, C>[]\n}\n\nexport interface ResolveOptions<T, D extends Record<string, any>, C> {\n resolvers: ResolverObject<T, C>\n data: D\n context: C\n status?: Partial<ResolverStatus<T, C>>\n propertyNames?: (keyof T)[]\n i?: number\n}\n\nconst toError = (error: any) =>\n typeof error.toJSON === 'function'\n ? error.toJSON()\n : { message: error.message || error }\n\nexport const resolve = <T, D extends Record<string, any>, C>(\n options: ResolveOptions<T, D, C>,\n): Promise<T> | T => {\n const {\n resolvers,\n data,\n context,\n status,\n propertyNames = Object.keys(resolvers) as any as (keyof T)[],\n i = 0,\n } = options\n\n if (!propertyNames.length) {\n return data as any as T\n }\n\n const propertyList = [\n ...new Set(Object.keys(data).concat(propertyNames as string[])),\n ]\n\n const result: any = {}\n const errors: any = {}\n let hasErrors = false\n const { path = [], stack = [] } = status || {}\n const promises: Promise<void>[] = []\n\n for (const name of propertyList) {\n const value = (data as any)[name]\n\n if (!(name in resolvers)) {\n if (value !== undefined) {\n result[name] = value\n }\n continue\n }\n\n const resolver = (resolvers as any)[name] as ResolverProperty<T, any, C>\n\n if (stack.includes(resolver)) {\n continue\n }\n\n const properties: ResolverStatus<T, C> = {\n ...status,\n path: [...path, name],\n stack: [...stack, resolver],\n }\n\n try {\n const resolved = resolver({\n value,\n data: data as any,\n context,\n properties,\n i,\n })\n\n if (resolved instanceof Promise) {\n promises.push(\n resolved\n .then((val) => {\n if (val !== undefined) {\n result[name] = val\n }\n })\n .catch((error: any) => {\n errors[name] = toError(error)\n hasErrors = true\n }),\n )\n } else if (resolved !== undefined) {\n result[name] = resolved\n }\n } catch (error: any) {\n errors[name] = toError(error)\n hasErrors = true\n }\n }\n\n const finalize = () => {\n if (hasErrors) {\n throw new BadRequest('Error resolving data', errors)\n }\n return result as T\n }\n\n if (promises.length) {\n return Promise.all(promises).then(finalize)\n }\n\n return finalize()\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { ResolverObject } from '../resolvers.internal.js'\nimport { resolve } from '../resolvers.internal.js'\nimport { mutateData } from '../../utils/index.js'\nimport type { DataSingleHookContext } from '../../utility-types/hook-context.js'\nimport type { AnyFallback, Promisable } from '../../internal.utils.js'\n\ntype Data<H extends HookContext> = AnyFallback<\n DataSingleHookContext<H>,\n Record<string, any>\n>\n\n/**\n * Resolves and transforms `context.data` using a map of resolver functions.\n * Each property in the resolver object receives the current value and can return\n * a transformed value. Runs before `next()` in the hook pipeline.\n *\n * @example\n * ```ts\n * import { resolveData, lowercase } from 'feathers-utils/resolvers'\n *\n * app.service('users').hooks({\n * before: {\n * create: [resolveData({ email: lowercase() })]\n * }\n * })\n * ```\n */\nexport const resolveData = <H extends HookContext = HookContext, D = Data<H>>(\n resolvers: ResolverObject<D, H>,\n): {\n (context: H, next: NextFunction): Promise<void>\n (context: H): Promisable<H>\n} => {\n const propertyNames = Object.keys(resolvers) as any as (keyof D)[]\n\n if (!propertyNames.length) {\n return ((context: H, next?: NextFunction) => {\n if (next) return next().then(() => context)\n return context\n }) as any\n }\n\n return ((context: H, next?: NextFunction) => {\n const result = mutateData(context, (item, { i }) =>\n resolve({ resolvers, data: item, context, propertyNames, i }),\n )\n\n if (result instanceof Promise) {\n return next ? result.then(() => next()).then(() => context) : result\n }\n\n if (next) return next().then(() => context)\n return result\n }) as any\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { resolve, type ResolverObject } from '../resolvers.internal.js'\nimport { mutateResult } from '../../utils/index.js'\nimport type { ResultSingleHookContext } from '../../utility-types/hook-context.js'\nimport type { AnyFallback, Promisable } from '../../internal.utils.js'\n\ntype Result<H extends HookContext> = AnyFallback<\n ResultSingleHookContext<H>,\n Record<string, any>\n>\n\n/**\n * Resolves and transforms `context.result` using a map of resolver functions.\n * Each property in the resolver object receives the current value and can return\n * a transformed value. Runs after `next()` in the hook pipeline.\n *\n * @example\n * ```ts\n * import { resolveResult, omit } from 'feathers-utils/resolvers'\n *\n * app.service('users').hooks({\n * after: {\n * all: [resolveResult({ password: omit() })]\n * }\n * })\n * ```\n */\nexport const resolveResult = <H extends HookContext = HookContext, R = Result<H>>(\n resolvers: ResolverObject<R, H>,\n): {\n (context: H, next: NextFunction): Promise<void>\n (context: H): Promisable<void>\n} => {\n const propertyNames = Object.keys(resolvers) as any as (keyof R)[]\n\n if (!propertyNames.length) {\n return ((context: H, next?: NextFunction) => {\n if (next) return next()\n }) as any\n }\n\n return ((context: H, next?: NextFunction) => {\n function run(): Promisable<void> {\n const result = mutateResult(context, (item, { i }) =>\n resolve({ resolvers, data: item, context, propertyNames, i }),\n )\n if (result instanceof Promise) return result.then(() => {})\n return\n }\n\n if (next) {\n return next().then(run)\n }\n\n return run()\n }) as any\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { type ResolverObject, resolve } from '../resolvers.internal.js'\nimport type { Promisable } from '../../internal.utils.js'\n\n/**\n * Resolves and transforms `context.params.query` using a map of resolver functions.\n * Each property in the resolver object receives the current query value and can return\n * a transformed value. Runs before `next()` in the hook pipeline.\n *\n * @example\n * ```ts\n * import { resolveQuery, defaults } from 'feathers-utils/resolvers'\n *\n * app.service('users').hooks({\n * before: {\n * find: [resolveQuery({ active: defaults(true) })]\n * }\n * })\n * ```\n */\nexport const resolveQuery = <H extends HookContext>(\n resolvers: ResolverObject<any, H>,\n): {\n (context: H, next: NextFunction): Promise<void>\n (context: H): Promisable<H>\n} => {\n const propertyNames = Object.keys(resolvers) as any as (keyof any)[]\n\n if (!propertyNames.length) {\n return ((context: H, next?: NextFunction) => {\n if (next) return next().then(() => context)\n return context\n }) as any\n }\n\n return ((context: H, next?: NextFunction) => {\n const queryIngoing = context?.params?.query || {}\n const result = resolve({\n resolvers,\n data: queryIngoing,\n context,\n propertyNames,\n })\n\n function assign(query: any) {\n context.params = { ...context.params, query }\n if (next) return next().then(() => context)\n return context\n }\n\n if (result instanceof Promise) {\n return result.then(assign)\n }\n\n return assign(result)\n }) as any\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport type { ResolverObject } from '../resolvers.internal.js'\nimport { resolveData } from '../resolve-data/resolve-data.js'\nimport { resolveQuery } from '../resolve-query/resolve-query.js'\nimport { resolveResult } from '../resolve-result/resolve-result.js'\nimport type {\n DataSingleHookContext,\n ResultSingleHookContext,\n} from '../../utility-types/hook-context.js'\nimport type { AnyFallback } from '../../internal.utils.js'\n\ntype Data<H extends HookContext> = AnyFallback<\n DataSingleHookContext<H>,\n Record<string, any>\n>\n\ntype Result<H extends HookContext> = AnyFallback<\n ResultSingleHookContext<H>,\n Record<string, any>\n>\n\n/**\n * Combines `data`, `query`, and `result` resolvers into a single around hook.\n * Data and query resolvers run before `next()`, while the result resolver runs after.\n * At least one resolver must be provided.\n *\n * @example\n * ```ts\n * import { resolve, lowercase, omit } from 'feathers-utils/resolvers'\n *\n * app.service('users').hooks({\n * around: {\n * all: [resolve({\n * data: { email: lowercase() },\n * result: { password: omit() },\n * })]\n * }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/resolvers/resolve.html\n */\nexport const resolve = <\n H extends HookContext = HookContext,\n D = Data<H>,\n R = Result<H>,\n>(resolverProperties: {\n data?: ResolverObject<D, H>\n query?: ResolverObject<any, H>\n result?: ResolverObject<R, H>\n}) => {\n const dataResolver = resolverProperties.data\n ? resolveData(resolverProperties.data)\n : undefined\n const queryResolver = resolverProperties.query\n ? resolveQuery(resolverProperties.query)\n : undefined\n const resultResolver = resolverProperties.result\n ? resolveResult(resolverProperties.result)\n : undefined\n\n if (!dataResolver && !queryResolver && !resultResolver) {\n throw new Error(\n 'At least one resolver must be provided (data, query, or result)',\n )\n }\n\n return async (context: H, next?: NextFunction) => {\n if (queryResolver || dataResolver) {\n const promisesBefore: Promise<any>[] = []\n\n if (queryResolver) {\n promisesBefore.push(Promise.resolve(queryResolver(context)))\n }\n\n if (dataResolver) {\n promisesBefore.push(Promise.resolve(dataResolver(context)))\n }\n\n await Promise.all(promisesBefore)\n }\n\n if (next) {\n await next()\n }\n\n if (resultResolver) {\n await resultResolver(context)\n }\n\n return\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"transform-result.hook-CevWK5TA.mjs","names":[],"sources":["../src/hooks/transform-data/transform-data.hook.ts","../src/hooks/transform-query/transform-query.hook.ts","../src/hooks/transform-result/transform-result.hook.ts"],"sourcesContent":["import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { mutateData } from '../../utils/mutate-data/mutate-data.util.js'\nimport type { TransformerInputFn } from '../../types.js'\nimport type { DataSingleHookContext } from '../../utility-types/hook-context.js'\nimport type { AnyFallback } from '../../internal.utils.js'\n\ntype Data<H extends HookContext> = AnyFallback<\n DataSingleHookContext<H>,\n Record<string, any>\n>\n\n/**\n * Transforms each item in `context.data` using the provided transformer function.\n * The transformer receives each item and can mutate it in place or return a new object.\n * Commonly used with built-in transformers like `lowercase`, `trim`, or `setNow`.\n *\n * @example\n * ```ts\n * import { transformData, lowercase } from 'feathers-utils/transformers'\n *\n * app.service('users').hooks({\n * before: { create: [transformData(item => lowercase(item, 'email'))] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/transform-data.html\n */\nexport const transformData =\n <H extends HookContext = HookContext, D = Data<H>>(\n transformer: TransformerInputFn<D, H>,\n ) =>\n async (context: H, next?: NextFunction) => {\n await mutateData(context, transformer)\n\n if (next) {\n return next()\n }\n\n return context\n }\n","import type { HookContext, NextFunction, Query } from '@feathersjs/feathers'\nimport type { TransformerFn } from '../../types.js'\n\n/**\n * Transforms `context.params.query` using the provided transformer function.\n * The transformer receives the current query and can return a modified version.\n * Useful for normalizing, sanitizing, or enriching queries before they hit the database.\n *\n * @example\n * ```ts\n * import { transformQuery } from 'feathers-utils/transformers'\n *\n * app.service('users').hooks({\n * before: { find: [transformQuery((query) => ({ ...query, active: true }))] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/transform-query.html\n */\nexport const transformQuery = <\n Q extends Query,\n H extends HookContext = HookContext,\n>(\n transformer: TransformerFn<Q, H>,\n) => {\n return (context: H, next?: NextFunction) => {\n context.params.query = transformer(context.params.query ?? {}, {\n context,\n i: 0,\n })\n\n if (next) {\n return next().then(() => context)\n }\n\n return context\n }\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { mutateResult } from '../../utils/mutate-result/mutate-result.util.js'\nimport type {\n DispatchOption,\n HookFunction,\n TransformerInputFn,\n} from '../../types.js'\nimport type { ResultSingleHookContext } from '../../utility-types/hook-context.js'\nimport type { AnyFallback } from '../../internal.utils.js'\n\ntype Result<H extends HookContext> = AnyFallback<\n ResultSingleHookContext<H>,\n Record<string, any>\n>\n\nexport type TransformResultOptions = {\n dispatch?: DispatchOption\n}\n\n/**\n * Transforms each item in `context.result` using the provided transformer function.\n * The transformer receives each item and can mutate it in place or return a new object.\n * Optionally operates on `context.dispatch` via the `dispatch` option.\n *\n * @example\n * ```ts\n * import { transformResult, omit } from 'feathers-utils/transformers'\n *\n * app.service('users').hooks({\n * after: { all: [transformResult(item => omit(item, 'password'))] }\n * })\n * ```\n *\n * @see https://utils.feathersjs.com/hooks/transform-result.html\n */\nexport const transformResult =\n <H extends HookContext = HookContext, R = Result<H>>(\n transformer: TransformerInputFn<R, H>,\n options?: TransformResultOptions,\n ): HookFunction<H> =>\n (context: H, next?: NextFunction) =>\n mutateResult(context, transformer, {\n next,\n dispatch: options?.dispatch,\n }) as Promise<H>\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2BA,MAAa,iBAET,gBAEF,OAAO,SAAY,SAAwB;CACzC,MAAM,WAAW,SAAS,YAAY;CAEtC,IAAI,MACF,OAAO,MAAM;CAGf,OAAO;;;;;;;;;;;;;;;;;;;;ACnBX,MAAa,kBAIX,gBACG;CACH,QAAQ,SAAY,SAAwB;EAC1C,QAAQ,OAAO,QAAQ,YAAY,QAAQ,OAAO,SAAS,EAAE,EAAE;GAC7D;GACA,GAAG;GACJ,CAAC;EAEF,IAAI,MACF,OAAO,MAAM,CAAC,WAAW,QAAQ;EAGnC,OAAO;;;;;;;;;;;;;;;;;;;;;ACAX,MAAa,mBAET,aACA,aAED,SAAY,SACX,aAAa,SAAS,aAAa;CACjC;CACA,UAAU,SAAS;CACpB,CAAC"}