Maîtrisez React

Découvrez React et son écosystème, quel que soit votre niveau.

Découverte de GraphQL : création d’une API avec Graphcool

May 4, 2019

Second article de la série consacrée à GraphQL. À présent que nous avons vu les concepts de base et le langage de requêtes, nous allons créer notre propre API GraphQL à l’aide du service Graphcool.

Graphcool est un service proposant de créer une API GraphQL sans écrire la moindre ligne de code. En effet comme nous l’avons vu dans le premier article, GraphQL n’est qu’un langage, la responsabilité de récupérer les données, de les filtrer, de faire les jointures, etc. reste celle du serveur (et donc du développeur).

Graphcool permet de réaliser tout cela de manière automatique, ce qui est idéal pour débuter avec GraphQL, surtout quand le but est comme ici d’aboutir le plus rapidement possible à un front-end travaillant avec l’API.

Installation et création du projet Graphcool

Pour le développement, Graphcool se présente comme un outil en ligne de commande que vous pouvez installer avec NPM: npm install -g graphcool. Il propose un moyen d’initialiser rapidement un projet, mais pour faire encore plus simple, créons les fichiers nécessaires à la main avec le strict minimum.

Tout d’abord le fichier package.json:

{
  "name": "hello-graphcool",
  "version": "0.1.0"
}

Puis le fichier graphcool.yml, manifeste qui indique comment Graphcool va devoir gérer notre application:

# Chemin vers le fichier de définition des types disponibles dans notre API
types: ./types.graphql
# Permissions: par défaut tout est accessible à tout le monde
permissions:
  - operation: '*'

Et enfin le plus intéressant, le fichier types.graphql, qui permet de définir les types qui seront disponibles dans notre API:

type User @model {
  id: ID! @isUnique
  name: String
}

Il s’agit bien d’un fichier GraphQL, contenant des annotations permettant d’ajouter des informations sur des attributs (isUnique) ou des types (@model). Une surcouche à GraphQL en quelque sorte : il s’agit du GraphQL Schema Definition Language.

La magie de Graphcool est de parvenir, à partir de ce fichier, à proposer une API permettant d’interroger une base de données reproduisant les modèles décrits. Ici, il est probable que quelque part sera générée une base disposant d’une table ou collection User permettant de stocker des entités disposant d’un ID et d’un nom.

Voyons dès à présent comment générer et utiliser cette API. Une fois les fichiers créés, la commande graphcool deploy permet de déployer chez Graphcool une instance de notre API. Quelques questions vous seront posées quand à l’emplacement où déployer l’API, les choix par défaut devraient très bien convenir.

Une fois la commande exécutée, Graphcool vous indique les URL de l’API, mais pour pouvoir jouer avec, le plus simple est de lancer la commande graphcool playground, qui ouvrira une interface permettant de faire des requêtes, similaire à celle que nous avons vu pour l’API GitHub dans le premier article.

Dans le playground, commençons par ouvrir la documentation (onglet « Docs » à droite):

playground doc
Documentation de notre API

Vous pouvez constater que Graphcool a généré énormément de choses à partir de notre simple modèle User et de ses deux attributs id et name:

  • des queries: allUsers pour récupérer plusieurs utilisateurs, user pour en récupérer un seul…
  • les paramètres de ces queries, permettant le filtrage, la pagination…
  • des mutations: createUser, updateUser, deleteUser
  • des subscriptions, dont nous n’avons pas encore parlé, pour être avertis des mises à jour des utilisateurs, etc.

Commençons par créer un utilisateur grâce à la mutation createUser:

mutation {
  createUser(name: "Sébastien") {
    id
    name
  }
}

Après cela vérifions qu’il nous est bien renvoyé si nous appelons la query allUsers:

{
  allUsers {
    id
    name
  }
}

Félicitations, vous venez de créer votre première API GraphQL! Voyons maintenant comment ajouter d’autres modèles, ainsi que des relations entre eux.

Ajout de nouveaux modèles et relations

Notre but pour aujourd’hui est de créer une API permettant de stocker des données pour un services similaire à Instagram, en beaucoup plus minimaliste. Les utilisateurs peuvent poster des photos (en fournissant directement l’URL), et d’autres utilisateurs peuvent y ajouter des commentaires. Nous réutiliserons notre API dans le prochain article lorsque nous créerons le front-end de notre application avec React.

Notre application devra donc manipuler trois types d’entités: les utilisateurs (que nous avons déjà vus), les posts, et les commentaires. Commençons par créer le type Post dans notre fichier types.graphql:

type Post @model {
  id: ID! @isUnique
  createdAt: DateTime!

  author: User! @relation(name: "UserPosts")
  imageUrl: String!
}

Par rapport au type User que nous avions vu, vous pouvez remarquer:

  • que nous avons ici un champ createAt, qui est en lecture seule et est géré par Graphcool (nous ne pouvons que l’utiliser dans les queries, pas le modifier) ;
  • qu’un attribut author permet de faire une liaison avec le modèle User.

La relation avec l’utilisateur est de type 1:n, c’est-à-dire qu’à un post correspond un utilisateur, mais qu’un utilisateur peut avoir plusieurs posts. Pour réaliser la liaison dans l’autre sens, ajoutons un attribut posts au modèle User:

type User @model {
  # ...
  posts: [Post!]! @relation(name: "UserPosts")
}

Le nom de la relation « UserPosts » permet d’indiquer à Graphcool la correspondance entre les deux attributs dans User et Post. En effet rien ne nous empêcherait d’avoir plusieurs relations entre ces deux modèles.

De la même manière créons un nouveau type Comment pour définir les commentaires:

type Comment @model {
  id: ID! @isUnique
  createdAt: DateTime!
  content: String!

  post: Post! @relation(name: "PostComments")
  author: User! @relation(name: "UserComments")
}

Nous avons ici deux relations, l’une permettant de définir le post associé au commentaire, et l’autre permettant d’y associer un auteur. À titre d’exercice vous pouvez ajouter les attributs nécessaires pour ces deux relations dans Post et User. Ou bien vous pouvez récupérer l’intégralité du fichier types.graphql en version définitive.

Après avoir redéployé notre API sur Graphqlcool (graphcool deploy), nous pouvons créer des utilisateurs, des posts et des commentaires.

Par exemple pour créer un nouveau post avec la mutation createPost: (pensez à remplacer l’ID de l’utilisateur par celui d’un utilisateur que vous avez créé)

mutation {
  createPost(
    authorId: "cjur4185307sq0106c5uy3wyh"
    imageUrl: "https://images.unsplash.com/photo-1555706195-38f133d1419f"
  ) {
    id
    author {
      id
      name
    }
    imageUrl
  }
}

Pour créer un commentaire, même principe avec la mutation createComment:

mutation {
  createComment(
    postId: "cjur4y17m0asx01234iwn30rv"
    authorId: "cjur4wgyl0b94014663afke1p"
    content: "Great picture!"
  ) {
    id
    createdAt
    content
  }
}

Vous pourrez retrouver diverses requêtes de création de données sur ce Gist. Après avoir créé quelques utilisateurs, posts et commentaires, nous pouvons par exemple écrire une requête permettant de récupérer:

  • les posts avec les URL des images, par ordre décroissant de date de création,
  • avec pour chaque post le nom de son auteur,
  • ainsi que les commentaires associés, par ordre croissant de date de création, et avec le nom de son auteur également.

Avec une API REST, cette requête nécessiterait généralement plusieurs appels réseaux, à moins de fournir une route permettant d’exécuter spécifiquement cette requête. Avec GraphQL, c’est le client (le front-end) qui peut choisir exactement quelles données récupérer.

Voici finalement notre requête finale, très proche de cette que nous utiliserons dans le prochain article pour afficher dans notre application React les images postées 😉 :

{
  allPosts(orderBy: createdAt_DESC) {
    id
    createdAt
    imageUrl
    author {
      id
      name
    }
    comments(orderBy: createdAt_ASC) {
      id
      createdAt
      author {
        id
        name
      }
      content
    }
  }
}

Remarquez comme il est facile de comprendre ce que renvoie cette requête sans être expert du GraphQL. Avec un peu d’habitude, les requêtes GraphQL ne sont pas beaucoup plus difficiles à écrire qu’à lire.

Mais maintenant que nous avons créé notre API GraphQL et que nous savons dialoguer avec elles par les queries et mutations, nous n’avons pourtant vu qu’une partie de la magie qu’apporte GraphQL. Il nous reste à appeler cette API dans une application React, et encore une fois des outils vont rendre ceci extrêmement simple.

Gardons cela pour le prochain article de la série 😉