graphql icon indicating copy to clipboard operation
graphql copied to clipboard

Create custom directives

Open conord33 opened this issue 7 years ago • 12 comments

Is there a way to create custom directives? I was looking to implement authentication using directives by following this blog post, but could not figure out how to define a custom directive from the source code or godocs.

Here is an example from the blog post.

type Vehicle {
  id: ID!
  year: Int!
  make: String!
  model: Int!
  askingPrice: Float
  costBasis: Float @hasRole(role: “MANAGER”)
  numberOfOffers: Int @isAuthenticated
}

It would be nice to be able to define an isAuthenticated directive that will determine whether or not a field should resolve.

Is there currently a way to implement this?

conord33 avatar Apr 10 '18 12:04 conord33

currently, i think graphql-go only supports '''include''' and '''skip''' directives.

1046102779 avatar Apr 10 '18 14:04 1046102779

@1046102779 do you know if there are any examples of using the include or skip directives in a graphql.ObjectConfig?

conord33 avatar Apr 11 '18 14:04 conord33

Hi guys, any news on this? The example @conord33 provided shows how useful directives are. Looking forward to seeing custom directives in this package.

namnm avatar Nov 10 '18 11:11 namnm

I'm working on a go version of makeExecutableSchema that might help with this https://github.com/bhoriuchi/graphql-go-tools.

bhoriuchi avatar Jun 13 '19 07:06 bhoriuchi

Any news or progress on when graphql-go/graphql is going to support custom directives? I see in the godocs you can create new directives but there's nothing about implementing the logic for them anywhere.

callensm avatar Feb 04 '20 17:02 callensm

I do not understand why the lib is restrictive about creating custom directives. // SpecifiedRules The full list of specified directives. var SpecifiedDirectives = []*Directive{ IncludeDirective, SkipDirective, DeprecatedDirective, }

susamn avatar May 15 '20 04:05 susamn

It has been more than 3 years, let's make this happen

namnm avatar May 29 '21 16:05 namnm

any news about this question?

codebdy avatar Feb 28 '22 07:02 codebdy

Is there a way to create custom directives? I was looking to implement authentication using directives by following this blog post, but could not figure out how to define a custom directive from the source code or godocs.

Here is an example from the blog post.

type Vehicle {
  id: ID!
  year: Int!
  make: String!
  model: Int!
  askingPrice: Float
  costBasis: Float @hasRole(role: “MANAGER”)
  numberOfOffers: Int @isAuthenticated
}

It would be nice to be able to define an isAuthenticated directive that will determine whether or not a field should resolve.

Is there currently a way to implement this?

I found that, you can get the directive informations in resolve function:

	func(p graphql.ResolveParams) (interface{}, error) {
...
		for _, iSelection := range p.Info.Operation.GetSelectionSet().Selections {
			switch selection := iSelection.(type) {
			case *ast.Field:
				fmt.Println(selection.Directives[len(selection.Directives)-1].Name.Value)
			case *ast.InlineFragment:
			case *ast.FragmentSpread:
			}
		}
...
	}

codebdy avatar Mar 02 '22 03:03 codebdy

May i have example? Directive os Schema type like @hasRole(role: __)

bakatest-me avatar Jun 17 '22 07:06 bakatest-me

i try to thing about this all day and i found this solution can use middleware pattern

example product resolve

type Product struct {}
func (m *Product) Resolve(p graphql.ResolveParams) (interface{}, error) {
	return "ggg", nil
}

custom go type for short typing ><

type GqlResolver func(p graphql.ResolveParams) (interface{}, error)

create middleware function like this

	usePermission := func(role string, next GqlResolver) func(p graphql.ResolveParams) (interface{}, error) {
		return func(p graphql.ResolveParams) (interface{}, error) {
			if p.Context.Value("role") == nil {
				return nil, errors.New("role not found")
			}
			return next(p)
		}
	}

use middleware function on graphql resolve

	p := Product{}
	fields := graphql.Fields{
		"product": &graphql.Field{
			Type:    graphql.String,
			Resolve: usePermission("user", p.Resolve),
		},
	}

i think this solution can do feature like custom directive @hasRole(role: __)

i hope this solution can be good idea for everyone ><

bakatest-me avatar Jun 18 '22 09:06 bakatest-me

I mentioned this a bit ago, but I have integrated this functionality into https://github.com/bhoriuchi/graphql-go-tools

See test code for example usage. https://github.com/bhoriuchi/graphql-go-tools/blob/master/directives_test.go#L18-L22 https://github.com/bhoriuchi/graphql-go-tools/blob/master/directives_test.go#L47-L66

At its core it uses the same middleware pattern @bakatest-me describes but uses the graphql mechanics

bhoriuchi avatar Jun 18 '22 15:06 bhoriuchi