GraphQL
GraphQL est un langage de requête pour les APIs, souvent présenté comme une alternative à REST. Son avantage principal est de permettre au client de demander exactement les données dont il a besoin, ni plus, ni moins, en une seule requête, ce qui résout les problèmes de sur-récupération (over-fetching) ou de sous-récupération (under-fetching) de données
Types GraphQL
Il existe différentes familles de type en GraphQL:
Scalar Types
Il s'agit des types primitifs:
Int: 357Float: 3.57String: "bonsoir"Boolean: true | falseID: "001" (serialisé en tant que String)
Object Types
La plupart des types que l'on va définir font parti de cette famille.
2 object types peuvent s'inclure l'un dans l'autre comme dans l'exemple précédent.
type Address {
street: String
city: String
postalCode: String
doctors: [Doctor]
}
type Doctor {
name: String
speciality: OPHTALMOLIGST | PSYCHOLOGIST
addresses: [Address]
}Le champs __typename
Tous les object types de votre schéma contienne un champs __typename.
Celui ci retourne le nom de votre Object Type en tant que String.
Vous n'aurez pas besoin de le spécifier.
On verra par la suite que ce champs est très utile pour identifier quel type d'object type le client récupère.
Query GraphQL
Fields
GraphQL permet de requêter des champs spécifiques sur des objets.
Voici un exemple:
{
doctors {
name
addresses {
street
city
}
}
}La requête ci dessus fournira une réponse sous la forme suivante:
{
"data": {
"doctors": [
{
"name": "Dr Samia Mekamene",
"addresses": [
{
"street": "2 Avenue Ambroise Croizat",
"city": "Garges-lès-Gonesse"
}
]
}
]
}
}Arguments
Il est possible d'ajouter des arguments à une resolver si le resolver le permet.
Par exemple:
{
doctor(id: "001") {
name
}
}pourrait fournir la réponse:
{
"data": {
"doctor": {
"name": "Dr Samia Mekamene",
"addresses": [
{
"street": "2 Avenue Ambroise Croizat",
"city": "Garges-lès-Gonesse"
}
]
}
}
}Aliases
Vous aurez pu remarquer que dans le résultat, l'objet retourné correspond au champs demandé.
Dans l'exemple précédent il nous serait donc pas possible de récupérer 2 docteurs ayant des ids différents.
Dans ce cas là vous devrez utiliser des alias pour renommer les champs que vous avez requêté.
{
closestOphtalmogists: doctors(speciality: OPHTALMOLIGST) {
name
}
closestPsychologists: doctors(speciality: PSYCHOLOGIST) {
name
}
}{
"data": {
"closestOphtalmogists": [
{
"name": "Dr. Clara Legrand"
}
],
"closestPsychologists": [
{
"name": "Dr. Alexis Martin"
}
]
}
}Fragments
Supposons qu'en utilisant l'exemple précédent vous souhaitez maintenant ajouter le champs speciality dans la liste des docteurs récupérés.
Vous devrez alors l'ajouter dans les 2 listes.
{
closestOphtalmogists: doctors(speciality: OPHTALMOLIGST) {
name
speciality
}
closestPsychologists: doctors(speciality: PSYCHOLOGIST) {
name
speciality
}
}Pour ce genre de cas GraphQL permet grâce au fragments de pouvoir réutiliser un ensemble de champs sur un object type.
{
closestOphtalmogists: doctors(speciality: OPHTALMOLIGST) {
...doctorFields
}
closestPsychologists: doctors(speciality: PSYCHOLOGIST) {
...doctorFields
}
}
fragment doctorFields on Doctor {
name
speciality
}Operation name
Vous avez sûrement remarqué que dans les exemples précédents nous utilisions une syntaxe raccourci pour écrire une query en omettant le mot clé query et le nom de la query.
query GetDoctorByID {
doctor(id: "001") {
name
}
}Il est important de les ajouter pour faciliter le debuggage que ce soit en local ou dans un environnement de production.
Cela permet de garder une certaine tracabilité et une signature à votre query.
On verra par la suite que l'utilisation du mot clé query et de l'operationName sera obligatoire pour pouvoir générer des types (typescript) avec l'outil graphql-codegen.
Variables
Une query, tout comme une mutation peut prendre des paramètres (qu'on appelle Variables).
Dans l'exemple précédent on remarque que le paramètre est passé statiquement (en dur).
Ces paramètres seront dans la plupart des cas passés de manière dynamique dans votre application.
GraphQL permet de passer un objet sous forme de clés valeur en même temps que la query.
query GetDoctorBy($id: ID!) {
doctor(id: $id) {
name
}
}{"id": "001"}Dans le cas d'une requête à une API GraphQL en POST, le body ressemblerait donc à:
{
"query": "query GetDoctorBy($id: ID!) {\n doctor(id: $id) {\n name\n }\n",
"variables": {
"id": "001"
}
}