1.5: Schema Language
1.5: Schema Language
Thus far, we have focused on the GraphQL query language, and we've noted at various points the imaginary types we presume to be part of the schema for our application, defined at the server. Let's delve into the specifics of how such a schema would be defined.
It's appropriate to emphasize again that GraphQL is a specification only. The data structures in backend storage (e.g., in MySQL), and the way that data is resolved into a query response, is up to the particular application and its implementation of the specification. What we're discussing here is an agnostic language (itself part of the specification) for expressing a type system, which any GraphQL runtime can consume in order to validate queries and responses.
Let's look at a type schema that would support the imaginary queries and mutations we've looked at:
enum MythEnum {
GREEK
EGYPTIAN
CHINESE
NORSE
CELTIC
BABYLONIAN
}
enum DomainEnum {
THUNDER
SUN
WAR
LOVE
WISDOM
}
enum HeightUnitEnum {
INCH
FOOT
METER
}
type God {
id: ID!
name: String!
domain: DomainEnum
mythology: MythEnum!
}
type PageInfo {
currentPage: Int!,
totalPages: Int!
}
type AllGodsPage {
pageInfo: PageInfo,
gods: [God!]!
}
type Food {
id: ID!
label: String!
cuisine: String
}
type Person {
id: ID!
name: String!
height(unit: HeightUnitEnum = INCH): Float
favoriteFoods(limit: Int = 10): [Food!]!
friends: [Person!]!
createdAt: String!
}
type Query {
person(id: ID!): Person
allGods(domain: DomainEnum, page: Int, limit: Int): AllGodsPage
}
input PersonInput {
name: String!
height: Float
}
type Mutation {
createPerson(
person: PersonInput!,
favoriteFoodIds: [ID],
friendIds: [ID]
): Person
}
You can delve into the GraphQL documentation to learn about the details of the type system, including syntax for some concepts not represented here. The above example, however, is likely fairly self-explanatory. (And a major detail to note is how similar the syntax is to query syntax!) Here are some highlights:
- True to the concept we've discussed of fields nested in other fields, the main definitions are
type
s with fields, each of which has a defined scalar type or another complex type. Note the definitions of the rootQuery
andMutation
types. - Note the
enum
declaration that can define the values of an enumeration. - Also note the
input
declaration, which is in all respects like atype
but defines a type that can be used as input for an argument. - The syntax
[Person!]!
looks tricky but is fairly intuitive in the end. The!
inside the bracket declares that every value in the array must be non-null, while the one outside declares that the array value itself must be non-null (e.g., an empty array).
Type Resolution
The logic for how data is fetched and formatted according to a schema, and how such logic is mapped to particular types, is up to the GraphQL runtime implementation. Any implementation, however, follows a conceptual flow that should make sense in light of our understanding of nested fields: A "resolve" operation associated with the root
Query
orMutation
type is performed, which examines each field specified in the request. For each field that resolves to a complex type, a similar "resolve" is done for that type, and so on until everything has resolved into scalar values.We'll see how Magento integrates directives into the schema definition language itself, with "resolver" classes defined inline.
Interfaces and Unions
Interfaces and Unions are schema language constructs that Magento customizes with specific new functionality, so you should familiarize yourself with them.