Skip to content

Utilities

Utils are utility functions that can be used in hooks or anywhere else in your Feathers application. They can be used to perform common tasks such as mutating data, validating input, or formatting output.

UtilityDescription
addSkip

Adds hook names to context.params.skipHooks so that skippable-wrapped hooks will be bypassed for the current service call. Accepts a single name or an array. Duplicates are automatically removed.

addToQuery

Safely merges properties into a Feathers query object. If a property already exists with a different value, it wraps both in a $and array to preserve both conditions. If the exact same key-value pair already exists, no changes are made. When the added query is itself a pure $and ({ $and: [...] }), its branches are flattened into the target's $and rather than nested.

checkContext

Validates that the hook context matches the expected type(s) and method(s). Throws an error if the context is invalid, preventing hooks from running in unsupported configurations. Typically used internally by other hooks. Also narrows the context type based on the passed options.

chunkFind

Use for await to iterate over chunks (pages) of results from a find method.

This function is useful for processing large datasets in batches without loading everything into memory at once. It uses pagination to fetch results in chunks, yielding each page's data array.

contextToJson

Converts a FeathersJS HookContext to a plain JSON object by calling toJSON() if available. This is important when using lodash get/has on the context, since the HookContext class uses getters that may not be enumerable.

defineHooks

TypeScript helper that provides full type inference and autocompletion when defining service hooks. It is an identity function that simply returns its input, but enables your IDE to infer the correct hook context types.

gateParams

Selects and/or projects params keys according to a declarative path schema, returning a NEW object. General-purpose — no cache knowledge. Typically composed into the cache hook's transformParams option as (p) => gateParams(p, schema, opts).

Paths are resolved with lodash get/has and written with set, so nested values can be picked declaratively ('user.id': true).

params is never mutated: kept values are copied over by reference into the fresh result (safe, since the result is only read/serialized). The one exception is combining a top-level rule with a nested path under the SAME parent in one schema (e.g. { query: true, 'query.x': ... }) — the nested set would then write into the shared parent. Pick one granularity per parent to avoid it.

query is included as-is by DEFAULT (it is always relevant), unless the schema addresses it explicitly — either as query or a nested query.* path.

Keys not mentioned in the schema are KEPT by default, so forgetting a relevant key can only cause a harmless cache miss, never a false hit. Pass dropUnknownParams: true to keep only query and the schema paths.

getDataIsArray

Normalizes context.data into an array for uniform processing. Returns { data, isArray } where data is always an array and isArray indicates whether the original value was already an array.

getExposedMethods

Returns the list of method names that are publicly exposed by a Feathers service. Reads the internal [SERVICE].methods property set during service registration. Throws if the service does not have any exposed methods configured.

getPaginate

Resolves the active pagination options for the current hook context. Checks (in order): context.params.paginate, service.options.paginate, and context.params.adapter.paginate. Returns undefined if pagination is disabled.

getResultIsArray

Normalizes context.result (or context.dispatch) into an array for uniform processing. Handles paginated results by extracting the data array. Returns { result, isArray, key } where key indicates whether 'result' or 'dispatch' was used.

iterateFind

Use for await to iterate over the results of a find method.

This function is useful for iterating over large datasets without loading everything into memory at once. It uses pagination to fetch results in chunks, allowing you to process each item as it is retrieved.

mergeQuery

Properties are combined with a logical operator rather than merged at the value level, so the result is always a valid query: combine always wraps the two queries in $or (broaden — OR has no flat form), while intersect merges non-conflicting properties flat and wraps conflicts in $and (narrow). The special filters $select, $limit, $skip and $sort are merged separately. Inputs are never mutated.

This is well suited to merging a client-provided query with a server-side restriction inside a hook.

mutateData

Applies a transformer function to each item in context.data, updating it in place. If the transformer returns a new object, it replaces the original item. Correctly handles both single-item and array data, preserving the original shape.

mutateResult

Applies a transformer function to each item in context.result (and optionally context.dispatch). Handles paginated results, single items, and arrays transparently. Use the dispatch option to control whether result, dispatch, or both are transformed.

patchBatch

Batch patching utility that takes an array of items to be changed and returns an array of arguments to be called with the patch method.

This utility is useful when you need to patch multiple items with varying data in as few requests as possible.

queryDefaults

Adds default properties to a Feathers query — but only for fields the query does not already constrain. Presence is checked with {@link queryHasProperty}, so a field referenced anywhere (including nested in $and/$or/$nor) is left untouched and the caller keeps control over it. The query is treated as the data equivalent of the defaults transformer. Each default is applied independently (per-field).

queryHasProperty

Checks whether a Feathers query contains one or more properties — including properties nested inside $and/$or/$nor arrays. Returns true as soon as any of the given property names is found. The query is not mutated.

simplifyQuery

Normalizes the logical structure of a Feathers query without changing what it matches: empty $and/$or are dropped, duplicate branches removed, nested same-operator branches hoisted ($and-in-$and, pure $or-in-$or), and branches merged up into the parent where it is safe — all of an $and when no key collides, a single-branch $or. Runs recursively. Inputs are not mutated; a query with nothing to simplify is returned unchanged.

skipResult

Sets context.result to an appropriate empty value based on the hook method. Returns an empty paginated object for paginated find, an empty array for multi operations, or null for single-item operations. Does nothing if a result already exists.

sortQueryProperties

Recursively normalizes a Feathers query object for order-independent comparison. Sorts object keys and sorts arrays within $or, $and, $nor, $not, $in, and $nin operators so that different orderings produce the same result.

This is useful for generating stable cache keys where { $or: [{ a: 1 }, { b: 2 }] } and { $or: [{ b: 2 }, { a: 1 }] } should be treated as equivalent.

stringifyParams

Serializes Feathers params into a stable, deterministic string — built for generating cache keys.

Two normalizations make semantically-equal params produce the same string:

  • sortObject: object keys are sorted recursively.
  • sortArray: elements of query array operators ($or, $and, $nor, $not, $in, $nin) are order-normalized.

Serialization is crash-safe and never throws on values that leak through a params whitelist: circular references become [Circular], functions/undefined/symbol are dropped (like JSON.stringify), BigInt is stringified, and objects with toJSON (e.g. Date, bson ObjectId) are serialized via it.

toPaginated

Ensures a result is in Feathers paginated format ({ total, limit, skip, data }). If the input is already paginated, it is returned as-is. If it is a plain array, it is wrapped in a paginated object with total and limit set to the array length.

transformParams

Safely applies a transformParams function to a params object. If no function is provided, the original params are returned unchanged. The function receives a shallow copy of params, so the original is not mutated.

waitForServiceEvent

Wait for a service event to fire and resolve with the emitted record. Useful in tests to await the result of an asynchronous service event, a bit like promisify for Feathers events.

Curried: bind the app (and optional defaults) once, then call the returned function per service/event. Resolves with a [data, { event, context }] tuple: data is typed as the service's record type, and event is the union of the requested events.

Feathers emits events as emit(event, record, context) and fires one event per record, so each resolution carries a single record and its HookContext.

walkQuery

Walks every property of a Feathers query (including nested $and/$or/$nor arrays) and calls the walker function for each one. The walker receives the property name, operator, value, path, and a stop function, and can return a replacement value. Calling stop() halts the traversal early. Returns a new query only if changes were made.

zipDataResult

Pairs each item in context.data with its corresponding item in context.result by index. Handles both single-item and array data, normalizing them into an array of { data, result } pairs. Only works in after/around hooks for create, update, and patch methods.

Released under the MIT License.