πͺ Scripting capabilities in non-standard GraphQL server
Last week I made a proposal to add embeddable fields to GraphQL, but it didn't get a lot of support. I got the feedback that the extra complexity added to the server doesn't justify the benefits of this new feature, as in this comment on Reddit (which I replied to through this post).
My proposed feature then appears to be not about GraphQL as we know it nowadays, but about an ΓΌber GraphQL, or what GraphQL could possibly be. That's either a problem, or an opportunity. In this write-up, Alan Johnson says:
[...] the execution model of GraphQL is in many ways just like a scripting language interpreter. The limitations of its model are strategic, to keep the technology focused on client-server interaction. What's interesting is that you as a developer provide nearly all of the definition of what operations exist, what they mean, and how they compose. For this reason, I consider GraphQL to be a meta-scripting language, or, in other words, a toolkit for building scripting languages.
I agree with this observation, but then I wonder: Where do these limitations start? What should be allowed, and what not? If any feature made GraphQL's scripting capabilities a bit more visible, gave a bit more control to the developer, and made the query a bit more powerful, should that be straightforward rejected? Or could it be given a chance?
Show me the stuff! permalink
Let's talk business now. Here is something that GraphQL is not good at.
Say that you have a @translate
directive that is applied on a String
, as in this query:
{
posts {
id
title @translate(from: "en", to: "es")
}
}
You cannot apply @translate
on a field different than a String
. If you need to, you must then create a new directive, which involves extra effort (often being ad-hoc) and pollutes the schema:
If a field returns
[String]
, you'd need to create another directive@translateArrays
If only some entries from the array must be translated, you need to add an optional argument
$keys: [String]
to specify which keys to translateIf the keys are not strings, but are numeric, you need another argument
$numericKeys: [Int]
as to avoid type conflictsIf instead of an array, you get an array of arrays, you need yet another directive
And so on, concerning any random requirement from your clients.
As a result, the schema might eventually become unwieldy.
So, how could this situation be improved for GraphQL?
If GraphQL had capabilities to compose or manipulate fields, then a few elements could already satisfy all possible combinations.
GraphQL by PoP (the engine powering the recently launched GraphQL API for WordPress) is a GraphQL server because it respects the GraphQL spec, but is also a non-standard API server that provides other capabilities, including composable fields and composable directives.
Let's see how this server can satisfy all combinations described above, with just a few elements:
Notes:
- GraphQL by PoP relies on the URL-based PQL syntax, so you can click on the links to execute the query and see its response
- Field
Root.echo
is used to build the arraysforEach
andadvancePointerInArray
are directives that composes another directive
Translating posts as strings (run query):
posts.title<
translate(from:en, to:es)
>
Translating a list of strings (run query):
echo([
hello,
world,
how are you today?
])<
forEach<
translate(from:en,to:es)
>
>
Translating only one element from the list of strings, with numeric keys (run query):
echo([
hello,
world,
how are you today?
])<
advancePointerInArray(path: 0)<
translate(from:en,to:es)
>
>
Translating only one element from the list of strings, with keys as strings (run query):
echo([
first:hello,
second:world,
third:how are you today?
])<
advancePointerInArray(path:second)<
translate(from:en,to:es)
>
>
Translating an array of arrays (run query):
echo([[
one,
two,
three
], [
four,
five,
six
], [
seven,
eight,
nine
]])<
forEach<
forEach<
translate(from:en,to:es)
>
>
>
And so on, concerning any random requirement from your clients.
In my opinion, these features make the queries more powerful, and the schema more elegant. So they could be perfectly considered to be added to GraphQL.
Should consider adding extra scripting capabilities to GraphQL? permalink
Bringing these additional scripting capabilities to GraphQL, wouldn't it be more valuable than not?
I understand that there is more complexity added to the server. But that's a one-time off. The GraphQL server maintainers can implement these features in a few months, and developers would be able to use them forever.
Isn't that a good tradeoff?