Skip to content

Hooks ​

Generating a hook ​

A new hook can be generated via

npx feathers generate hook

Hook name ​

The hook generator will first ask for a name. Based on the name it will create a kebab-cased filename in the hooks/ folder that exports a camelCased hook function. For example a name of my fancy Hook will create a src/my-fancy-hook.ts file that exports a myFancyHook hook function.

Hook types ​

There are two hook types that can be generated.

tip

For more information see the hooks API documentation.

Around hooks ​

Around hooks allow to control the entire before, after and error flow in a single function. An around hook is an async function that accepts two arguments:

  • The hook context
  • An asynchronous next function. Somewhere in the body of the hook function, there is a call to await next(), which calls the next hooks OR the original function if all other hooks have run.
ts
import type { HookContext, NextFunction } from '../declarations'

export const myFancyHook = async (context: HookContext, next: NextFunction) => {
  console.log(`Running hook ${name} on ${context.path}.${context.method}`)
  await next()
  // Do things after here
}

You can wrap the await next() in a try/catch block to also handle errors.

Before, after, error ​

Before, after or error hooks are async functions that take the hook context as the parameter.

ts
import type { HookContext } from '../declarations'

export const myFancyHook = async (context: HookContext) => {
  console.log(`Running hook ${name} on ${context.path}.${context.method}`)
}

Context types ​

If the hook is for a specific service, you can pass the service as a generic to the HookContext type which will give you the correct types for context.data, context.result and context.params:

ts
import type { UserService } from '../services/users/users'
import type { HookContext } from '../declarations'

export const myFancyUserHook = async (context: HookContext<UserService>) => {
  console.log(`Running hook ${name} on ${context.path}.${context.method}`)
}

Registering hooks ​

A generated hook can be registered as an application hook or as a service hook. Also see the hook registration API documentation.

Profiling example ​

To log some basic profiling information like which method was called and how long it took to run you can create a new around hook called profiler via

npx feathers generate hook

Then update src/hooks/profiler.ts as follows:

ts
import type { HookContext, NextFunction } from '../declarations'
import { logger } from '../logger'

export const profiler = async (context: HookContext, next: NextFunction) => {
  const startTime = Date.now()

  await next()

  const runtime = Date.now() - startTime

  console.log(`Calling ${context.method} on service ${context.path} took ${runtime}ms`)
}

And add it in src/app.ts as an application hook after the logError hook as follows:

ts
import { profiler } from './hooks/profiler'

//...

// Register hooks that run on all service methods
app.hooks({
  around: {
    all: [ logError, profiler ]
  },
  before: {},
  after: {},
  error: {}
})

Released under the MIT License.