Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
[FR] GraphQL: Customize (add/hide) available fields #4850
This is a follow up of #4832
Currently the data available via GraphQL is de facto a 1:1 representation of raw db content.
There are some reasons to customize that behavior:
An additional field could be registered with:
[redone from the phone email result, so you can possibly read it. Do not email github from phones...]
Thank you, gentlemen.
Points of design:
I suspect this would fit the considerable range Werner's excellently thought-out list opens to, and it does fit what I need to get one or more normal Craft primitives to work.
What do you think?
@brandonkelly -inclusive, of course, if he's a little busy right now.
@narration-sd I mean... I'm a sucker for over-engineering myself, but I have a lot of issues with that plan.
The elegance of GraphQL is in the fact that you look at the schema and you know what you can query for.
Instead, it really, really, should just be an event.
Every data entity returned by GraphQL is going to be content. And we've yet to encounter where that is not an Element. So, knowing that Craft's implementation has a generator for each element type (https://github.com/craftcms/cms/tree/develop/src/gql/types/generators), it's trivial to implement an event firing before each GraphQL type for different pieces of content is created and added to the schema. At which point a plugin or a module can just remove unneeded fields or add their own fields, complete with a resolver function (https://webonyx.github.io/graphql-php/type-system/object-types/#field-configuration-options).
That would include less moving parts (a lot less), doesn't involve magically manipulating the query and ensures that schema always shows the available content.
Well, right on time as I was dropping off, but what the heck, and this time I fire up the laptop rather than try to uncoil Github's misbehavior.
Andris, I'm not quite sure I follow any of your slam about 'over-engineering'. The AST stuff is all there within webonyx's portion of your package, and in principle is simple. Rules to define what happens are also straightforward. Connecting the two so that directives with their attractions to provide functionality while serving the wider needs which can't directly call them would seem to be win-win. And slams -- that's pretty out of court, isn't it?
Now. In my brief read of your counter-proposal, no doubt humanly flawed, and skipping my own linguistic tendencies, what I don't see happening is solution to where I began. How is the query written so that it satisfies the js-package's no-custom-directives style going to specify what directive, and what the directive would do? Or if it's something other than a directive?
To whit, how do we pass the identity of a transform for an image out of that Gridsome etc. box and into also-yours Craft Asset's hands? I am probably really missing something.
Then, that you can introduce Events into your resolvers, ok. I actually began in thinking there. But to attract coding for them in addition to, duplicating directives you've now enticed just everybody to write? And again, quite possibly I mistake, but it sounds like you are talking about sprinkling these Events around in so many resolvers of types -- each Event being a code you will have to approve for internality, and then support.
Related, I was a while ago beginning to think towards how resolvers might be made externally available for other custom writing, and maybe this is what you are talking about. But again, that's kind of a support issue, would think, if the flexibility sounds attractive. Issues -- and alternatives -- seem to fill the imagination, so I'll stop with this line, just consider it needs a thoughtful balancing.
Back to go. Events to alter resolvers haven't shown me how to push modifiers on fields up through the local js-framework minimal-GraphQL stone wall. Perhaps it's in there; let's see.
But anyway. I put a lot of effort into coming up with something workable, so that this issue wouldn't get buried in the 'someday' bin as it was headed for by discussion being shut off. Backed off from whatever's appearing to tend towards sparks, I'd think you'd appreciate if not respect that, Andris.
And, I guess I should underline -- I'm not doing any of this, front-channel or back, to critique anyone else's thinking, design styles, etc.. I'm doing it because I have front-and-center need, that product that has waited to be fully practical. There are other issues as you know, but this is one of the fully technical ones that needs to get resolved.
And yes, also out of a tendency to want to help.
One more thought occurs as my own keyboard cools :) and I cool by reading a photo site and seeing people with too much crabbing there as ever, the better to shake my head at self.
The thought is that you seem to be talking about adding fields etc. not in the Schema.
That's not what's happening. The Schema is always the Schema -- the only thing the query can operate on. It's the query that gets rearranged. Maybe code would be a lingua franca that helps.
Asset field specified with transform in CraftQL -- passes through js-package GraphQLs
Asset field specified with transform in Craft GraphQL-- blocked by js-package GraphQLs
Conversion explained would be to alter the first style so that the re-formed query, the thing your GraphQL execute sees, becomes the second. That's all.
The conversion is proposed via the AST is because a parse is necessary to discover the argument on the Field type, with a structured result able to modify it -- and webonyx provides that for us.
Another shake of the head at self: sure, I don't like to go to such an extent either, of course. And if there's a better way around it...very open.
But in any case, you probably have no idea of the wryness surrounding all of this project here anyway, none of it aimed your direction whatsoever...! Cheers, Andris, good thoughts -- Clive
Well. I had a grumpy morning, it seems, and I've come across harsher than I intended. Sorry about that - I'll try to encompass in a few sentences what I propose.
So, if you felt so inclined, you could modify the
So, you could solve a Directive issue in two ways:
Everybody wins, and complexity isn't increased, no?
Without being able to understand this discussion in detail, having an event beforehand sounds perfectly fine for me.
Wanted to add that it may be additionally possible to define schema fields in a config file, optionally including a twig template string as a resolver instead of a php function.
Just looked at real live element-api transformers, there is a lot of trivial stuff like
Would be great to be able to implement such easy things without writing php code.
Ok, going back to sleep for beauty (age hath its privileges), but up for just the moment to get both you guys' good thoughts, with maybe inspiration on how phone can do decent answer.
Ok, bis vraiment Morgen, to mix a few...
FYI: Just played around a bit using a simple custom field type as a workaround for those trival requirements (the last thing before holidays, i'm off for the next 6 weeks. Really off.)
Just takes a twig template as a setting that is evaluated at runtime.
(Maybe something like this already exists, but i didn't see it at first glance. Preparse plugin may also work if evaluation at runtime is not needed.)
As 'normal' fields they perfectly show up in the schema, (checked in gridsome's playground) without any further effort. And they can be also used in twig and element-api.
Also they can be edited in the CP (ok, that may also be a disadvantage...)
@andris-sevcenko I wanted to rest concerning this approach, so gave it some of my long-weekend-here time.
In fact, it's powerful, as you suggest, and very easy...once you figure out how much you don't need to do, which means digging around in the endless Type machine just as with the AST you mention, until the layering is understood.
And then figure out how this can be sensibly inserted...more of the same.
However, the coding result is indeed cleaner, once arrived, and in discovery prototype I have image
Here's a bit of how I may see the rest playing out.
Ok. It's a lot later, and many more hours in than I intended, but it's done as a preplay. You can see how you feel.
I suspect you'll reckon how expansion on this method could do a lot more, given that opening such would in some future be sensible. For now, looks like it will solve my popular-spas requirement...
Cheerio, and don't mind me -- it's late...
Ok, in some kind of exercise of solidarity or judgement(!?) it's done I think. I'll let it rest overnight, and PR it tomorrow.
I'm running it fully from an Event, within Live Vue, which only has to pass back a simple nested array of config changes for any fields per Element Type, as the code-inline doc illustrates.
Let's see if I can post that doc:
It's working on code here, and the principles are simple, after less-simple work to discover what those principles should be. I've added the ability for all GraphQL Interfaces in the PR, and I'm using some of them on my prototypes that you know about.