With GraphQL, everything is a field and every field can accept arguments. Fields are either scalar types or objects.
So, with every field being able to take arguments you can do something like (not implemented, for illustration only):
{
loan(id:<someid>) {
posted_date(format:"mm/dd/yyyy")
}
}
"loan" is just a field on Query. "posted_date" is a field on Loan.
So, in the case of KL's GraphQL interface, I could just make my own type (used only for graphQL queries) called "formattableDate" where it has all the smarts built in to return the default date string when no arguments or format using the string given. That type could then be used for all of the dates so every date field of every type has that ability.
Additionally, you could make queries, like this ...
{
loan(id:<someid>){
terms {
scheduled_payments(lastOnly:true) { due_date(format:"mm/yyyy") }
}
}
}
Or:
{
loan(id:<someid>){
terms {
scheduled_payments(greaterThan:"now") { due_date }
}
}
}
Then just have some code to interpret the incoming arguments when processing the query.
Another Kiva-domain example, would be descriptions. Have a "description" field that when it has no arguments returns a description object (with a field for the language and the text) where it defaults to english but falls back to the original language when no english translation, if you pass it a language as an argument "description(lang:"en")" you could have it return only the matching description and "null" if none match. Then you could also have a "descriptions" field that returns an array of description objects. Since most users would probably only ever want the "description" field, it reduces data transfer by allowing it to be specified but doesn't restrict the more advanced apps from having access to the full descriptions array if they want it. Behind the scenes, Kiva's KC objects don't change at all, you're just introducing a thin layer to access that data. You could then also have a "description_text" field that returns a string and takes arguments for preferred language and to tell it to truncate after X characters (for use in a list of results).
One of the things GraphQL hopes to achieve is to remove the need to version an API, you just add new stuff and people use it or they don't. Like you can initially support just the simple "scheduled_payments" field that returns an array of payment objects (due_date, amount) and then later add the ability to pass optional arguments (like those shown above) and no existing users would get broken. There's no penalty for adding anything new or adding more arguments to an existing field. You just can't change types or remove stuff once people are using it.
It has support for deprecating fields as well, where you indicate that it's deprecated and what the reason is, and that will show up in tools like GraphiQL (where it won't show up in the auto-complete and will give warnings if you use it and you can choose to return results or just null if it's removed permanently).
As GraphQL continues to expand, you'll see more options for different execution strategies, where I know that for Ruby, there are parallel execution
libraries where the field resolution can all happen asynchronously, but then all fields must be resolved before the result (outer promise) is resolved. I'm sure there are many queries on Kiva's pages where the execution is just sequential, where parallel execution would greatly reduce response times.
Side note: If you look at Kiva's "similar" loans endpoint, that feature was obviously intended only for use for the block of loans that display at the top when looking at a loan that is no longer fundraising, because the algorithm will most times return the loan being queried as another loan similar to itself. (Loan A's similar loans are A, B, C... it really shouldn't include itself.)
Paul