New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add design guide for graphql naming conventions #31
Conversation
73dfd86
to
0b80909
Compare
0b80909
to
e354d06
Compare
Great! I prefer namespace prefixing. It is closer to this proposal, which is being discussed and considered (tldr, they are weighing implementation complexity vs letting the community handle namespacing on their own). Type:
Top level field (I guess nested fields don't need namespacing unless they refer to types from another namespace):
Mutation:
My preference is #1 because:
We'll also have to consider versioning at some point, that could follow a similar namespacing rule, e.g. |
We'll probably add more sections to this as time goes by, but I'd like to document one important best practice for future compatibility, to never resolve arrays directly. Always wrap arrays in some kind of payload object. |
Yeah agree with the prefix after seeing the article. Can you elaborate on:
|
I'd prefer a slash, but it's not a supported symbol in identifiers, which is why they're proposing it for the standard. The only non-alphanumerical symbol is "_". :( Regarding arrays, it's mainly about pagination. It's classic to start with arrays and return all items and then having no way to add cursor-based pagination with backwards compatibility. Worth having a naming convention for pagination? |
I guess this guide should be implementation independent, but practically, in NestJS, I think this involves always passing explicit names to type and resolver decorators:
We should consider creating an eslint rule to enforce this naming convention, as it is easy to forget during implementation and review. |
Yeah I see! My vote would be query {
dog {
id
owners(first: 10, after: "TYU468HG7") {
count
edges {
cursor
node {
id
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
} Here we could then later decide if we wanted a cursor based pagination vs. offset based pagination. |
Yeah, my original thought was to prefix it at runtime. |
That would be ideal, but it'd be an exercise in NestJS. There is a We'd have to implement the code-first schema generation logic from scratch, or create a GraphQLModule in each domain and somehow merge them manually. :/ |
What's your thought on |
I've never gone for it before because the pattern feels a bit bloated, with two types per connection (Connection type and Edge type), and extra wrapping/unwrapping needed both on server and client. I would personally base our convention on the Connection pattern but simplify, skipping the Edge type, unless:
For #1 and #2, we might also want to discuss the |
How about simplifying namespacing rules and skip the namespace symbol. Just prefix the namespace and follow casing rules? E.g. Type: SearchArticle instead of search_Article Pros:
Cons:
|
This answer sums it quite well why there's a per-edge cursor:
Regarding But IMO the mutation names would have to have a pretty specific rule. Like Not sure how we'd enforce that ^? |
IMHO those feel like very specific edge cases (pun intended), which is tricky to get right unless we're using Relay. Meanwhile spending more bytes and compute cycles for the general cases. But I won't die on this hill. I think your mutation naming suggestion is fair. Regarding enforcement, custom eslint rule to the rescue: :)
It can visit graphql resolvers, types and enums based on the nestjs directives, and verify that they have one of the namespace prefixes (ignores the verb for mutations). It can also read the valid namespace names from the repo somehow. |
Ready for re-review. |
Fixed based on Conversation, and due to parental leave (Congrats!) I'm gonna merge this in so it won't become stale |
https://github.com/island-is/handbook/blob/graphql-naming-conventions/docs/api-design-guide/graphql-naming-conventions.md