Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Directive and specifying the same on a Field and Type #1006

Closed
prashanthellina opened this issue Jun 11, 2019 · 5 comments
Closed

Custom Directive and specifying the same on a Field and Type #1006

prashanthellina opened this issue Jun 11, 2019 · 5 comments

Comments

@prashanthellina
Copy link

I've tried looking at the documentation to figure out how to accomplish this but got no where.

How do I define a schema like this using Graphene?

directive @unique(
  info: String = "Blah blah"
) on FIELD_DEFINITION | ENUM_VALUE

directive @ignore(
  info: String = Blah blah"
) on OBJECT

type ExampleType @ignore(info: "Blah"){
  newField: String
  oldField: String @unique(info: "Blah")
}
@jkimbo
Copy link
Member

jkimbo commented Jun 12, 2019

@prashanthellina it's not documented but you can pass directives when you create your schema:

from graphql.types.directives import specified_directives  # <== default directives
from graphene import Schema

schema = Schema(query=Query, directives=specified_directives + [MyDirective])

You'll have to define your own directives but you can see how the @skip and @include and defined here: https://github.com/graphql-python/graphql-core/blob/8f7c8f3351dd0a4580b87f293aed7bfcf9126bc4/graphql/type/directives.py#L69-L98

@prashanthellina
Copy link
Author

Thank you @jkimbo for the example above. I can understand how this will help in accomplishing this part of the schema.

directive @unique(
  info: String = "Blah blah"
) on FIELD_DEFINITION | ENUM_VALUE

directive @ignore(
  info: String = Blah blah"
) on OBJECT

What do I do to get this part:

type ExampleType @ignore(info: "Blah"){
  newField: String
  oldField: String @unique(info: "Blah")
}

i.e. Telling Graphene to apply the custom directives I defined, at a field / object / enum level.

@dvndrsn
Copy link
Contributor

dvndrsn commented Jun 14, 2019

I believe decorating on the Query would be supported by the resolver argument info. You can get the arguments from the resolve info parameter:

https://docs.graphene-python.org/en/latest/api/#execution-metadata

You'd have to write your logic in a decorating function or in the resolver itself.

I don't think that there is currently support for applying decorators on Schema, but you can definitely emulate the desired behavior through a wrapping class (kind of like List and NonNull in graphene). I'd love to dig into this a bit more though!

Here's an example of how directives are implemented in graphql-tools for Js.

https://www.apollographql.com/docs/graphql-tools/schema-directives/

@jkimbo
Copy link
Member

jkimbo commented Jun 24, 2019

@prashanthellina thanks for your patience. So I've looked into this a bit more and it looks like it's not possible to apply directives on a field/object level. This is a conscious limitation of the reference GraphQL server implementation graphql-js. You can read more about the reasoning here: graphql/graphql-js#746 (comment) and follow the ongoing discussion about it here: graphql/graphql-js#1343

The relevant comments from leebyron are:

Right now directives are purely a feature of the GraphQL language and IDL, so a schema not created using IDL definitionally won't contain directives. When building a schema in code, you have the full power of the host programming environment, so directives shouldn't be necessary. Directives are a tool for supplying additional intent to be later interpreted by the host programming environment.

and

Directives are purely a feature of the GraphQL language and are not part of type definitions - this is because different tools will use and interpret directives in different ways.

(there is also a great long comment which explains things in detail)

Since Graphene is based on graphql-core which is a direct port of the graphql-js implementation, support for directives on fields/objects won't happen until that support is available in graphql-js.

I hope that's helpful. You might also want to checkout ariadne which is an alternative way of building a GraphQL server using the SDL.


I'm going to create an new issue to document adding custom directives to the schema and then close this one.

@prashanthellina
Copy link
Author

@jkimbo Thank you for the confirmation. I thought I was missing something. I believe there is merit in implementing directives as I find that a good way to signal behavior formally (rather than in comments) to both the user of the schema/service and the implementer of the resolver logic.

I quite liked the way that prisma (https://www.prisma.io/) uses directives to provide more expressiveness when using the SDL to describe ORM like interactions with a database.

For the moment, I am exploring using GraphQLS2S for defining the schema in an SDL superset (that support inheritance, generics etc to help reduce verbosity) and then transpiling it to standard SDL. After I have the final schema, I am using ariadne to implement the actual resolver logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants