graphql-go icon indicating copy to clipboard operation
graphql-go copied to clipboard

Ability to add our own directives

Open renoirb opened this issue 7 years ago • 10 comments

May be related to #116.

CONTEXT

Author of this request is proficient JavaScript, but not in Go. Some statements in this issue may skewed perceptions based as a total beginner in Go.

REQUEST/QUESTION

Assuming we have a schema that supports Time scalar (like you've done in TestTime), and we want to use a custom formatter using GraphQL directives.

Is there plans for our own neelance/graphql-go GraphQL server implementation to create our own directives?

For example, we could get a n days ago, by defining our own @date(...) directive;

query {
  ago: addHour("2001-02-03T04:05:06Z") @date(as: "days ago")
}
// => { "ago": "6189 days ago" }

I'm aware not all types of Directives would be useful to ALL packages extending neelance/graphql-go.

It wouldn't make sense to have scalar Time exported by default.

But what I enjoyed in tests/, and the file time.go, was that I could see how I could implement my own scalar.

That would be awesome to have another example where one could see how to implement properly his own directive (e.g. @date).

OBSERVATIONS

As said in #116, it looks like the place we could append our own directives would be implemented are hidden away. I assume it's because lowerCased functions aren't exported in Go.

I see in internal/exec/selected/selected.go at line 194 how you’ve implemented @skip directive

And also how (black magic?) you’ve implemented @onQuery at internal/tests/testdata/tests.json {"schemas": []}, and ran from internal/tests/all_test.go TestAll

LINKS

Maybe you'd like to see some directives implemented in JavaScript, here is one implementation sample I found useful; lirown/graphql-custom-directives Date Formatting Directives

renoirb avatar Jan 14 '18 18:01 renoirb

I've forked the project and started experimenting on how to make it happen

See renoirb/graphql-go, at branch issue-151

Desired outcome: Use field as type date, for example, as-is, but allow directive to tamper output.

Unless that's not a good idea.

Thoughts:

  • I'm aware that anything in the schema can be seen as a "directive" (type, enum, query, ... are "directives", right?)
  • Maybe FIELD directives could be attached or bound somehow
  • Maybe use ImplementsGraphQLType => "directive", how?

renoirb avatar Jan 15 '18 01:01 renoirb

Why use a directive rather than some input field in the arguments?

tonyghita avatar Jan 15 '18 03:01 tonyghita

That can work, @tonyghita.

It would require making methods to return a String instead of an intended type. For example, we know lastModified is a date, but GraphQL will always return a string. But I would then have all fields I want with formatters to exist from two methods, the original and the formatted...able.

I was hoping I could find a way to create a type (e.g. like time.go does for new scalar) on which I could tell it's a Field Directive, where I could tell what return type it can format, and what options I can tell to use via enum.

I guess, at the moment, there is no way to attach to execution context (i.e. not at the same place we attach the schema, resolvers).

renoirb avatar Jan 15 '18 15:01 renoirb

I'm curious tonsee if something is planned in that regard.

One thing I enjoy most about GraphQL is that we have something to really separate formatting logic from frontend. Having each field, once per bounded context, to fulfill their types is great, It would be awesome we could have ways to pipe a formatter.

Maybe this project will allow this. That's why I'm asking.

renoirb avatar Jan 15 '18 15:01 renoirb

I would think this functionality is best kept in the resolver, right? I can see the use-case of having custom directives but I would imagine this project abstracting over that a bit to allow you (the developer) to write your own custom directives & implementations without forcing the lib to take care of those custom directives & implementations.

@renoirb - What are your thoughts on that? I may not completely understand.

iamclaytonray avatar Jan 18 '18 22:01 iamclaytonray

Hey @iamclaytonray, I haven't looked at this since my last comment.

You are right, in JavaScript Directives are attached at the resolver, at least the ones we want to use around the schema.

Here is a JavaScript module that allows this (implemented here).

I'm sure neelance is aware of how/where to implement this, and that's likely part of his plans. As I understand it (I can't find the reference for this, sorry) work has to be done to support directives because they can be used at many places in a schema (fragments, etc.) and there is no exposed functions, it is deep within "src/internals/".

I am currently designing a system, and had been analyzing the language we'll write our own GraphQL resolvers. We may pick this Go implementation of GraphQL, and we may be OK without Directives, my recommendation and the decision of my team aren't set in stone yet.

renoirb avatar Jan 29 '18 22:01 renoirb

Hi guys. Any news on this? Directives are useful in a lot of cases, looking forward to seeing the public API in this package!

namnm avatar Nov 10 '18 11:11 namnm

+1 Wanted to solve our role based backend calls with custom directives in the schema but found out the hard way that these are not supported? Can't think of another way without repeating a check inside each of the resolvers 😥. Guess with a directive based "middleware" (or interceptor) we could simply resolve the custom directive and block or pass the request.

PepijnK avatar Dec 05 '18 13:12 PepijnK

Any news here? I found the PR#370, is it related to this issue?

mistricky avatar Jan 02 '21 09:01 mistricky

is this something that can be supported I am looking for something similar like @hasScope(scope: ["test"]) that could be applied to Query & Mutation as well? @PepijnK did you find a workaround for that?

abebars avatar Feb 19 '21 18:02 abebars