GraphQL avec Apollo

GraphQL avec Apollo


Création du type Query

Avant de mettre en place les resolvers pour les query en lecture, vous devez créer le type query.

Il faut ensuite créer un type avec l'ensemble des fonctions que vous souhaitez avoir. Nous allons :

  • récupérer l'ensemble des astronautes
  • récupérer un astronaute
  • récupérer une planète

Ajoutez le fichier schemas.js à la racine de votre projet. Importez l'ensemble des types que nous avons défini à l'étape précédente :

import Astronaute from './typedefs/astronaute'; import Planet from './typedefs/planet'; import Grade from './typedefs/grade'; const RootQuery = ` type RootQuery { astronaute(id: Int!): Astronaute, astronautes: [Astronaute] planet(id: Int!): Planet } `; const SchemaDefinition = ` schema { query: RootQuery } `;

Configuration de GraphQL

Toujours dans le même fichier schemas.js vous devez dire à votre serveur GraphQL où est votre schéma. Pour cela vous devez ajouter le module graphql-tools :

yarn add graphql-tools

Ce module expose la fonction makeExecutableSchema qui prend en paramètre vos types.

Vous devriez avoir le code suivant :

import { makeExecutableSchema } from 'graphql-tools'; import { resolvers } from './resolver'; import Astronaute from './typedefs/astronaute'; import Planet from './typedefs/planet'; import Grade from './typedefs/grade'; const RootQuery = ` type RootQuery { astronaute(id: Int!): Astronaute, astronautes: [Astronaute] planet(id: Int!): Planet } `; const SchemaDefinition = ` schema { query: RootQuery } `; export default makeExecutableSchema({ typeDefs: [SchemaDefinition, RootQuery, Astronaute, Planet, Grade], resolvers: resolvers, });

Ajoutez le resolver

Ajoutez un fichier resolver.js contenant seulement :

export const resolvers = {}

Activez le serveur

Il nous reste à indiquer à GraphQL comment récupérer notre schéma. Dans le fichier index.js vous devez importer ledit schéma :

import express from 'express'; import bodyParser from 'body-parser'; import { graphqlExpress, graphiqlExpress } from 'apollo-server-express'; import schema from './schemas'; const PORT = 3000; const app = express(); app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' })); app.use('/graphql', bodyParser.json(), graphqlExpress({ schema })); app.listen(PORT);

Nous ajoutons au même moment l'IDE GraphiQL qui est contenu dans la librairie Apollo. L'IDE permet d'afficher directement la documentation, ainsi que d'effectuer les query.

Si tout est ok, vous devriez avoir accès à l'url suivante http://127.0.0.1:3000/graphiql et voir la doucmentation (à droite).

Documentation

Création des resolvers

Si vous essayez la query :

{ astronautes { id } }

Vous devriez voir la réponse suivante :

{ "data": { "astronautes": null } }

Et oui, pour l'instant vous n'avez aucun resolver !

Le resolver est le code qui permet de récuperer la donnée dans la base.

Dans un dossier resolvers vous devez ajouter le fichier astronautes.js avec le code suivant :

import pg from './../pg'; import Astronaute from '../typedefs/astronaute'; const resolvers = { RootQuery: { async astronautes() { return await pg.select().table('astronaute'); } }, }; export default resolvers;

Dans le fichier resolver.js il vous faut ajouter le resolver que nous venons de définir :

import AstronauteResolver from './resolvers/astronaute'; export const resolvers = AstronauteResolver;

Si tout est ok la réponse à votre requête est :

{ "data": { "astronautes": [] } }

Et si vous ajoutez des astronautes dans votre base de donnnées et changer la requête en :

{ astronautes { id, pseudo } }

la réponse est donc :

{ "data": { "astronautes": [ { "id": 1, "pseudo": "CaptainJojo" }, { "id": 2, "pseudo": "Pouzor" }, { "id": 3, "pseudo": "Franky" } ] } }

Maintenant nous allons modifer le resolver pour récupérer via l'id :

import pg from './../pg'; import Astronaute from '../typedefs/astronaute'; const resolvers = { RootQuery: { async astronautes() { return await pg.select().table('astronaute'); }, async astronaute(obj, args, context, info) { return (await pg .select() .table('astronaute') .where('id', args.id) .limit(1)).pop(); }, }, }; export default resolvers;

Puis nous allons résoudre la récupération du grade et de la planet :

import pg from './../pg'; import Astronaute from '../typedefs/astronaute'; const resolvers = { RootQuery: { async astronautes() { return await pg.select().table('astronaute'); }, async astronaute(obj, args, context, info) { return (await pg .select() .table('astronaute') .where('id', args.id) .limit(1)).pop(); }, }, Astronaute: { async grade(astronaute) { return (await pg .select() .table('grade') .where('id', astronaute.grade_id) .limit(1)).pop(); }, async planet(astronaute) { return ( await pg .select() .table('planet') .innerJoin('planet-astronaute', 'planet-astronaute.planet_id', '=', 'planet.id') .where('planet-astronaute.astronaute_id', astronaute.id) .limit(1)).pop(); } }, }; export default resolvers;

Comme vous pouvez le voir, c'est assez simple, il suffit de spécifier pour chaque attribut comment le récupérer.

Enfin créons le resolver pour la planet.

Ajouter le fichier planet.js au dossier resolvers :

import pg from './../pg'; import Planet from '../typedefs/planet'; const resolvers = { RootQuery: { async planet(obj, args, context, info) { return (await pg .select() .table('planet') .where('id', args.id) .limit(1)).pop(); }, }, Planet: { async astronautes(planet) { return (await pg .select() .table('astronaute') .innerJoin('planet-astronaute', 'planet-astronaute.astronaute_id', '=', 'astronaute.id') .where('planet-astronaute.planet_id', planet.id) ); } }, }; export default resolvers;

Puis dans le fichier resolver.js vous devez ajouter le resolver :

import { merge } from 'lodash'; import AstronauteResolver from './resolvers/astronaute'; import PlanetResolver from './resolvers/planet'; export const resolvers = merge(AstronauteResolver, PlanetResolver);

Si tout est ok, la requête suivante doit fonctionner :

{ astronautes { id, pseudo }, astronaute(id: 1) { id, pseudo grade { id, name }, planet { id, name } }, planet(id: 2) { id, astronautes { id, pseudo, grade { name } } } }

La réponse doit ressembler à cela :

{ "data": { "astronautes": [ { "id": 1, "pseudo": "CaptainJojo" }, { "id": 2, "pseudo": "Pouzor" }, { "id": 3, "pseudo": "Franky" } ], "astronaute": { "id": 1, "pseudo": "CaptainJojo", "grade": { "id": 1, "name": "admiral" }, "planet": { "id": 1, "name": "duck" } }, "planet": { "id": 2, "astronautes": [ { "id": 2, "pseudo": "Pouzor", "grade": { "name": "rookie" } }, { "id": 3, "pseudo": "Franky", "grade": { "name": "rookie" } } ] } } }

Retrouvez le code directement ici

Auteur(s)

Jonathan Jalouzot

Jonathan Jalouzot

Lead développeur au @lemondefr, mes technologies sont le symfony depuis 2009, le nodejs, l'angularjs, rabbitMq etc ... J'adore les médias et aimerai continuer dans ce secteur plein de surprise. Vous pouvez me retrouver sur les réseaux sociaux: Twitter: @captainjojo42 Instagram: @captainjojo42 Linkedin: https://fr.linkedin.com/in/jonathanjalouzot Github: https://github.com/captainjojo

Voir le profil

Vous souhaitez en savoir plus sur le sujet ?
Organisons un échange !

Notre équipe d'experts répond à toutes vos questions.

Nous contacter

Découvrez nos autres contenus dans le même thème