Middlewares

Middlewares are similar to the Adonis Middlewares but they work in the context of a GraphQL operation.

There are executed in series before reaching the resolver. Every middleare can end the request or forward it to the next middleware.

You can find more information about Middlewares on the Official TypeGraphQL documentation

Examples

Logging

app/graphql/middlewares/access_logger_middleware.ts
import {  } from '@adonisjs/core'
import {  } from '@adonisjs/core/logger'
import { ,  } from '@foadonis/graphql'

@()
export default class  {
  constructor(private readonly : ) {}

  ({ ,  }: , : ) {
    const  = .auth.user
    if () {
      this..(`Access: ${.fullName} -> ${..}.${.}`)
    }

    return ()
  }
}

Execution timing

The second argument of the use method will execute the rest of the stack allowing you to run actions after the execution of your operations. For example you could log the execution time.

app/graphql/middlewares/performance_logger_middleware.ts
import {  } from '@adonisjs/core'
import {  } from '@adonisjs/core/logger'
import { ,  } from '@foadonis/graphql'

@()
export default class  {
  constructor(private readonly : ) {}

  async ({  }: , : ) {
    const  = .()
    await ()
    const  = .() - 
    this..(`${..}.${.} [${}ms]`)
  }
}

Intercepting the result

Middleware also has the ability to intercept the result of a resolver's execution. It's not only able to e.g. create a log but also replace the result with a new value:

app/graphql/middlewares/competitor_middleware.ts
import { ,  } from '@foadonis/graphql'
import {  } from '@adonisjs/core'

export default class  {
  async ({  }: , : ) {
    const  = await ()

    if ( === 'ts.ed') {
      return 'adonis'
    }

    return 
  }
}

Guards

Guards are simply middlewares that does not call the next function so it never reaches the resolver. This is useful when you want to block access on specific conditions.

app/graphql/middlewares/competitor_middleware.ts
import { ,  } from '@foadonis/graphql'
import {  } from '@adonisjs/core'

export default class  {
  ({  }, ) {
    if (.frameworkName === 'ts.ed') {
      throw new ('Adonis is better')
    }

    if (.frameworkName === 'adonis') {
      return 'AdonisJS'
    }

    return ()
  }
}

Attaching Middlewares

Resolver method

To attach middleware to a resolver method, use the @UseMiddleware decorator above the method declaration. It accepts an array of middleware that will be called in the provided order. You can also pass them without an array as it supports rest parameters:

app/graphql/resolvers/recipe_resolver.ts
import { , ,  } from '@foadonis/graphql'
import  from '#graphql/middlewares/performance_logger_middleware'
import  from '#graphql/middlewares/access_logger_middleware'

@()
export default class  {
  @(, )
  @()
  () {}
}

Resolver

If you want to apply the middlewares to all the resolver's class methods, you can put the decorator on top of the class declaration:

app/graphql/resolvers/recipe_resolver.ts
import { , ,  } from '@foadonis/graphql'
import  from '#graphql/middlewares/performance_logger_middleware'
import  from '#graphql/middlewares/access_logger_middleware'

@(, )
@()
export default class  {
  @()
  () {}
}

ObjectType Field

You can also attach the middleware to the ObjectType fields, the same way as with the @Authorized decorator.

import { , ,  } from '@foadonis/graphql'
import  from '#graphql/middlewares/access_logger_middleware'

@()
export default class  {
  @()
  : string

  @()
  @UseMiddleware()
  : string
}

Global

You can apply middlewares globally using the globalMiddlewares option in your GraphQL configuration:

config/graphql.ts
import {  } from '@foadonis/graphql'
import  from '#graphql/middlewares/access_logger_middleware'

export default ({
  : [],
})

On this page