Ariadne 0.22 update
Mirumee Software
Python and JS experts delivering complex solutions with simplicity. Open source evangelists and the creators of Saleor.
Author: Rafa? Pitoń
Last week, we shipped Ariadne 0.22!
This release focuses on fixing one tiny bug that affected developers using the “query over the websocket” feature that some GraphQL clients support. But it also changed how Ariadne handles enums during the schema instantiation.
Enums in GraphQL
GraphQL lets developers include enums in their schemas:
enum Role {
USER
MODERATOR
ADMIN
}
Those enums can then be used as fields return values:
type User {
role: Role!
}
Enums can also be inputs:
type Query {
users(role: Role): [User!]!
}
One of the problems that GraphQL server libraries are addressing is the conversion between the enum’s representation in Schema/JSON and the programming language used by the server. For example, the “USER” role may be represented as the “UserRole.USER” enum value in the business logic implemented using Python.
Both GraphQL’s reference implementation (made in JavaScript), and its Python port (“graphql-core”) come with dedicated places that the GraphQL servers can populate to enable this conversion automatically on the query execution and result serialization boundaries.
Filling in the blanks
Currently, available GraphQL standard implementations are tested and mature. But some use cases are not yet handled “out of the box”. This is where server libraries like Ariadne step in.
One such blank is in the treatment of enums as input default values. For example:
领英推荐
type Query {
users(role: Role = USER): [User!]!
}
This schema specifies that if the “role” argument has no value set for it, “USER” should be used as a default.
Default enum values handling is one such blank in GraphQL. While conversion between GraphQL and the programming language’s enum’s representation is done automatically once the server library (or developer) sets the mapping for those in the enum’s GraphQL object in the data structure with schema, default values are excluded from this mapping.
Instead, server libraries need to recursively walk all fields' arguments and inputs in the schema to find ones that are enums, find if those inputs have default values, and then set those default values mappings. This process is simple at first glance, but GraphQL supports default values like those:
input UserSearch {
username: String
role: User
}
input UsersInput {
search: UserSearch
}
type Query {
users(input: UsersInput = {search: {role: USER}}): [User!]!
}
The server library needs to find the “USER” within this GraphQL object and set its mapping.
There is another problem too: GraphQL reference implementation and its ports currently skip enums default values during schema validation. This schema is valid according to GraphQL’s “validateSchema()”, but it shouldn’t be:
enum Role {
USER
MODERATOR
ADMIN
}
type Query {
users(role: Role = MEMBER): [User!]!
}
Ariadne implements custom schema validation logic that extends the standard one to find places like this (even for complex use cases like the one we’ve illustrated previously).
However, until Ariadne 0.22, this logic was part of the library's private API.
Ariadne GraphQL Modules
Ariadne is not a single library anymore. It is now a set of Python libraries solving different GraphQL-related tasks:
While working on a new version of Ariadne GraphQL Modules that supports a code-first approach, we’ve found a need for making Ariadne’s enum handling logic part of the public API. This necessitated refactoring in Ariadne that was completed as part of the changes in Ariadne 0.22. This work is now completed and we are now unblocked to continue working on the next Ariadne GraphQL Modules release.