graphql-directives-middlewares

0.2.2 • Public • Published

graphql-directives-middlewares

GraphQL directives as middlewares

npm bundle size GitHub Workflow Status NPM Version Coveralls github

install

yarn add graphql-directives-middlewares

You need to have graphql and graphql-tools installed on your project.

why

We create this library because we needed our directives to be sorted at runtime. We were on the case we needed to execute our @auth directive BEFORE our @api directive take place.

With graphql-directives-middlewares you just have to declare, in your schema, the directives in order you want them to take place.

With this declaration:

type Query {
  users: [User] @auth(requires: ADMIN) @api(name: "users")
}

Your @auth directive will be called BEFORE the @api one.

If you invert @auth and @api, then @api directive will be called BEFORE the @auth, without changing your implementation!

API

createVisitFieldDefinition

createVisitFieldDefinition(name: string, impl: (params, next) -> (...args))

  • name: the directive name you use in your gql schema
  • impl: is a function that take params and next and return a function that is your graphql custom resolver
    • params are your directives arguments
    • next is the next resolver to call, like in a middleware engine

createVisitObject

createVisitObject(name: string, impl: (params, next) -> (...args))

  • name: the directive name you use in your gql schema
  • impl: is a function that take params and next and return a function that is your graphql custom resolver
    • params are your directives arguments
    • next is the next resolver to call, like in a middleware engine

usage

Example with a @auth directive

  1. define your directive in the schema
export default `
  enum Role {
    ADMIN
    USER
    VIEWER
  }
 
  directive @auth(requires: Role = ADMIN) on FIELD_DEFINITION
`
  1. create your directive implementation
import { GraphQLList } from 'graphql'
import { createVisitFieldDefinition } from 'graphql-directives-middlewares'
 
export default createVisitFieldDefinition(
  'auth',
  (params, next) => async (...args) => {
    const { requires: requiredRole } = params
 
    if (!requiredRole) {
      return next()
    }
 
    const [, , context, definition] = args
    const { role } = context
 
    if (!role.includes(requiredRole)) {
      if (definition.returnType instanceof GraphQLList) return []
      throw new Error('Unauthorized')
    }
 
    return next()
  },
)
  1. bind your directives implementation to your schema
import { makeExecutableSchema } from 'graphql-tools'
import typeDefs from './types'
import auth from './auth'
 
export default () => {
  const resolvers = {
    Query: {
      users: () => [
        {
          id: 'fabien-juif-1',
          fullName: 'Fabien JUIF',
        },
      ],
    },
  }
 
  return makeExecutableSchema({
    typeDefs,
    resolvers,
    schemaDirectives: {
      auth,
    },
  })
}
  1. use your directives
import { gql } from 'apollo-server'
import user from './user'
 
export default gql`
  ${user}
 
  type Query {
    users: [User] @auth(requires: ADMIN)
  }
`

Package Sidebar

Install

npm i graphql-directives-middlewares

Weekly Downloads

0

Version

0.2.2

License

MIT

Unpacked Size

7.68 kB

Total Files

3

Last publish

Collaborators

  • fabienjuif