Skip to content

Latest commit

 

History

History
265 lines (189 loc) · 8.46 KB

hooks.md

File metadata and controls

265 lines (189 loc) · 8.46 KB

Hooks

Hooks are registered with the fastify.graphql.addHook method and allow you to listen to specific events in the GraphQL request/response lifecycle. You have to register a hook before the event is triggered, otherwise the event is lost.

By using hooks you can interact directly with the GraphQL lifecycle of Mercurius. There are GraphQL Request and Subscription hooks:

Notice: these hooks are only supported with async/await or returning a Promise.

GraphQL Request Hooks

It is pretty easy to understand where each hook is executed by looking at the lifecycle page.

There are five different hooks that you can use in a GraphQL Request (in order of execution):

When registering hooks, you must wait for Mercurius to be registered in Fastify.

await fastify.ready()

preParsing

If you are using the preParsing hook, you can access the GraphQL query string before it is parsed. It receives the schema and context objects as other hooks.

For instance, you can register some tracing events:

fastify.graphql.addHook('preParsing', async (schema, source, context) => {
  await registerTraceEvent()
})

preValidation

By the time the preValidation hook triggers, the query string has been parsed into a GraphQL Document AST. The hook will not be triggered for cached queries, as they are not validated.

fastify.graphql.addHook('preValidation', async (schema, document, context) => {
  await asyncMethod()
})

preExecution

In the preExecution hook, you can modify the following items by returning them in the hook definition:

  • document
  • schema
  • errors

Note that if you modify the schema or the document object, the jit compilation will be disabled for the request.

fastify.graphql.addHook('preExecution', async (schema, document, context) => {
  const { modifiedSchema, modifiedDocument, errors } = await asyncMethod(document)

  return {
    schema: modifiedSchema, // ⚠️ changing the schema may break the query execution. Use it carefully.
    document: modifiedDocument,
    errors
  }
})

preGatewayExecution

In the preGatewayExecution hook, you can modify the following items by returning them in the hook definition:

  • document
  • errors

This hook will only be triggered in gateway mode. When in gateway mode, each hook definition will trigger multiple times in a single request just before executing remote GraphQL queries on the federated services.

Note, this hook contains service metadata in the service parameter:

  • name: service name
fastify.graphql.addHook('preGatewayExecution', async (schema, document, context, service) => {
  const { modifiedDocument, errors } = await asyncMethod(document)

  return {
    document: modifiedDocument,
    errors
  }
})

onResolution

The onResolution hooks run after the GraphQL query execution and you can access the result via the execution argument.

fastify.graphql.addHook('onResolution', async (execution, context) => {
  await asyncMethod()
})

Manage Errors from a request hook

If you get an error during the execution of your hook, you can just throw an error and Mercurius will automatically close the GraphQL request and send the appropriate errors to the user.`

Notice: there is one exception to this with the preGatewayExecution hook, which will continue execution of the rest of the query and append the error to the errors array in the response.

fastify.graphql.addHook('preParsing', async (schema, source, context) => {
  throw new Error('Some error')
})

Add errors to the GraphQL response from a hook

The following hooks support adding errors to the GraphQL response. These are:

  • preExecution
  • preGatewayExecution
fastify.graphql.addHook('preExecution', async (schema, document, context) => {
  return {
    errors: [new Error('foo')]
  }
})

fastify.graphql.addHook('preExecution', async (schema, document, context) => {
  return {
    errors: [new Error('bar')]
  }
})

Note, the original query will still execute. Adding the above will result in the following response:

{
  "data": {
    "foo": "bar"
  },
  "errors": [
    {
      "message": "foo"
    },
    {
      "message": "bar"
    }
  ]
}

GraphQL Subscription Hooks

It is pretty easy to understand where each hook is executed by looking at the lifecycle page.

There are five different hooks that you can use in GraphQL Subscriptions (in order of execution):

When registering hooks, you must make sure that subscriptions are enabled and you must wait for Mercurius to be registered in Fastify.

await fastify.ready()

preSubscriptionParsing

If you are using the preSubscriptionParsing hook, you can access the GraphQL subscription query string before it is parsed. It receives the schema and context objects as other hooks.

For instance, you can register some tracing events:

fastify.graphql.addHook('preSubscriptionParsing', async (schema, source, context) => {
  await registerTraceEvent()
})

preSubscriptionExecution

By the time the preSubscriptionExecution hook triggers, the subscription query string has been parsed into a GraphQL Document AST.

fastify.graphql.addHook('preSubscriptionExecution', async (schema, document, context) => {
  await asyncMethod()
})

preGatewaySubscriptionExecution

This hook will only be triggered in gateway mode. When in gateway mode, each hook definition will trigger when creating a subscription with a federated service.

Note, this hook contains service metadata in the service parameter:

  • name: service name
fastify.graphql.addHook('preGatewaySubscriptionExecution', async (schema, document, context, service) => {
  await asyncMethod()
})

onSubscriptionResolution

fastify.graphql.addHook('onSubscriptionResolution', async (execution, context) => {
  await asyncMethod()
})

onSubscriptionEnd

This hook will be triggered when a subscription ends.

fastify.graphql.addHook('onSubscriptionEnd', async (context) => {
  await asyncMethod()
})

Manage Errors from a subscription hook

If you get an error during the execution of your subscription hook, you can just throw an error and Mercurius will send the appropriate errors to the user along the websocket.`

Notice: there are exceptions to this with the onSubscriptionResolution and onSubscriptionEnd hooks, which will close the subscription connection if an error occurs.

fastify.graphql.addHook('preSubscriptionParsing', async (schema, source, context) => {
  throw new Error('Some error')
})

GraphQL Application lifecycle Hooks

There is one hook that you can use in a GraphQL application.

When registering hooks, you must wait for Mercurius to be registered in Fastify.

await fastify.ready()

onGatewayReplaceSchema

When the Gateway service obtains new versions of federated schemas within a defined polling interval, the onGatewayReplaceSchema hook will be triggered every time a new schema is built. It is called just before the old schema is replaced with the new one.

This hook will only be triggered in gateway mode. It has the following parameters:

  • instance - The gateway server FastifyInstance (this contains the old schema).
  • schema - The new schema that has been built from the gateway refresh.
fastify.graphql.addHook('onGatewayReplaceSchema', async (instance, schema) => {
  await someSchemaTraversalFn()
})

If this hook throws, the error will be caught and logged using the FastifyInstance logger. Subsequent onGatewayReplaceSchema hooks that are registered will not be run for this interval.