Is anyone in here super experienced with gql?
# random
t
Is anyone in here super experienced with gql?
a
I was until figured it was hard to use with ORM.
o
Like GraphQL in general? Or the
graphql-tag
lib?
t
in general
o
Fragment’s public API is graphql, learnt a bunch of stuff implementing it and running it at scale
t
Been trying to get an answer to this: https://github.com/FormidableLabs/urql/discussions/2055
o
So in my API I expose the equivalent of authorId and author - which then lets me handle those two cases differently
t
for my usecase I'm heavily using a normalized cache on the frontend, it'll see those as 2 different things right
o
yeah
Also there’s logic that means if you only query author.id it doesn’t actually go fetch the author
t
yeah I don't want to allow clients to query all the authors details when listing posts
o
because of perf or security?
t
Performance
this is a contrived example
maybe I just want to limit it to
id
and
name
. And the only way I can find to do that is by creating a different type for it. But then it confuses my clientside cache because it doesn't know TinyAuthor and Author are the same thing unless I setup a bunch of mapping
And then to go further, maybe I don't want clients listing all 100 fields in post when listing posts and restrict them to just 10 of them. Now I have TinyPost and Post too. Feels really inelegant
o
yeah I err of the side of giving my clients as much flexibility as I can give them - if they want that data, and I don
t
in my case Post and Author are in 2 different data sources so I can't easily join them
o
don’t let them get it, they’ll just make more API calls anyway - so best to get the full query they want, and optimise things to make that work
t
I guess I can leave it as the full data type and appsync will just error if they ask for fields I haven't implemented a way to resolve
o
yeah I have a few different data sources (search index, dynamo, qldb). But doing it as one big query is more efficient than many smaller ones as things like authorisation checks can be cached
On your thing - I don’t think there’s a way around having two different types. You could implement the server to check the parent type and return things differently, but that would poison your cache. I don’t think introducing a union type of TinyPost | Post helps either
t
Yeah I guess I have to lean towards what's simplest for the client to understand
cool thanks
o
You could just reject queries with too much complexity - so instead of returning nulls for properties you don’t want to fetch, you explicitly error out and return null for author
t
Yeah that's what I'm doing currently
makes sense
I know people love gql and I'm trying to be open minded but it feels really inelegant in a lot of places coming from jsonapi
o
I think there’s a big philosophical shift between those styles from server is king to client is king
t
jsonapi operates client first as well. It just felt like a more elegant implementation of all the same concepts and you can see it in the client libraries (eg orbit) since they tend to be way more simple all while supporting the same advanced features
o
I built an API like that before (I remember it being called HATEOS back then, not sure what relation that has with jsonapi) - but we had to invent stuff on top of it to get some of the same features as graphql (e.g. fetching multiple levels deeper into the graph in one network request, serving schemas alongside the data to autogenerate UI)
It became a big pain to implement things authorisation and send get requests like
/users/34?expansions=department.name,department,manager.name,manager.id,manager.department.id,manager.department.id
was a bad DX
t
Well raw gql over the wire looks just as ugly - it's not as much a problem if you have good clients typed to build it + receive it
o
Yeah those didn’t exist at the time, we can ran into issues where get requests got too long, had to implement our own normalised cache - and web server frameworks weren’t designed for those use cases
t
Yeah ultimately what we're trying to do is complex so can't get rid of that
btw I noticed fragment's public api is in gql. Your customers are probably more savvy but have you had any pushback on that from people looking for a normal rest api?
o
One thing that is fundamentally different is mutations vs state changes for updates
I go back and forth on it, where CRUD works much better on jsonapi, but if you need to invent new nouns to represent more complex updates. Like we had a use case where the API to terminate an employee needed extra info sent in. The basic update would be
{status: 'terminated'}
but we also needed to send
{moveDirectReportsTo: 'some other user'}
t
Yeah you usually end up having to create another resource for that which you're "creating"
o
Right - UserTerminationFlow - which ends up being practically being same as gql with terminateUser(), and the fact that the users status changed is implicit in both
t
yeah
I guess I was hoping given how much gql ripped up, all the tooling required, and the fact they were starting ground up that all this would feel better to use. Maybe I need to get more practiced with it
o
More than anything having standardised tooling, nomenclature and APIs across different APIs, and having all these problems solved - with batteries built-in - is the biggest benefit. That there is one approach to solving this class of problems, that historically REST and the tooling around it never took a strong opinion on
My API would be far harder to understand and use if it was a REST API - because the tooling isn’t as good. Would be interesting to see what the REST version of this API call would look like:
Copy code
query GetBalanceSheet ($ledgerId: ID!, $filter: LedgerAccountFilter) {
  ledger(id: $ledgerId) {
    ledgerAccounts(filter: $filter) {
      nodes {
        id
        name
        type
        end_of_year: balance(at: "2021")
        end_of_month: balance(at: "2021-06")
        end_of_day: balance(at: "2021-06-15")
        end_of_hour: balance(at: "2021-06-15T06")
      }
    }
  }
}
Copy code
{
  "ledgerId": "some-ledger-id",
  "filter": {
    "type": {
      "in": [
        "asset",
        "liability"
      ]
    }
  }
}
Your customers are probably more savvy but have you had any pushback on that from people looking for a normal rest api?
Not really, initially most people are indifferent or “cool!” - and then they become converts once they setup code-generated SDKs and start creating API calls like the above
d
What you are trying to do is completely incompatible with GraphQL :) But there’s nothing preventing you from having caching for the entire graphql api and in the server as well, so not sure it’s really a problem. Assuming data only changes via mutations, it’s also easy to know when and what to cache bust