GraphQL workshop

Principe de GRAPHQL

RAPPELS

Une spécification de communication pour API 

 

Made in Facebook
 

Créé en 2012
 

Publié en 2015

 

Over HTTP, typé Fortement

Le client decide DE ce qu'il veut récupérer

Pourquoi l'avoir créé

REST :

  • Trop de requête
  • Trop lourd

 

RPC :

  • Trop spécialisé pour chaque écran
  • Pas de cache

Pourquoi l'avoir créé

  • Mettre à disposition la bonne quantité de donné pour chaque device
     
  • Alléger les échanges
     
  • Faciliter la mise à disposition de donnée pour différentes versions de client.

Quelques
CONCEPTS
CLés

QUelques concepts clés

  • Une API GraphQL n'a qu'un seul end-point (une url)
     
  • On communique uniquement en POST
     
  • Pour définir la structure d'une API GraphQL on définie un schéma
type Project {
  name: String
  tagline: String
  contributors: [User]
}
{
  project(name: "GraphQL") {
    tagline
  }
}
{
  "project": {
    "tagline": "A query language for APIs"
  }
}

Describe your data

Ask for what you want

Get predictable results

github.com/mbreton/graphql-workshop

Rdv à cette adresse :

Lisez le readme jusqu'au chapitre "Exercice"

Familliarisation avec GraphQL

Excercice n°1

localhost:3001/graphQL

GraphiQL  : Outil de visualisation/manipulation d'une API GraphQL

server/route/graphql.js

Contient la déclaration de l'API GraphQL.

 

 

const Router = require("express").Router;
const graphqlHTTP = require("express-graphql");
const { makeExecutableSchema } = require("graphql-tools");
const service = require("../service");

const router = Router();

const typeDefs = `
type Post {
  id: ID!
  title: String!
  content: String!
}
`;

const resolvers = {};

router.use(
  graphqlHTTP({
    schema: makeExecutableSchema({ typeDefs, resolvers }),
    graphiql: true
  })
);

module.exports = router;

End-point GraphQL

Un end-point GraphQL contient le schéma qui déclare l'API et la manière d'interagir avec.

 

Il  contient les resolvers, responsables d'exécuter les comportements attachées correspondant à l'API. (rootValue)

 

const Router = require("express").Router;
const graphqlHTTP = require("express-graphql");
const { makeExecutableSchema } = require("graphql-tools");
const service = require("../service");

const router = Router();

const typeDefs = `
type Post {
  id: ID!
  title: String!
  content: String!
}
`;

const resolvers = {};

router.use(
  graphqlHTTP({
    schema: makeExecutableSchema({ typeDefs, resolvers }),
    graphiql: true
  })
);

module.exports = router;

server/route/graphql.js

le schéma correspond à la déclaration de l'API GraphQL.

 

Actuellement, seulement le type d'objet Post est déclaré


 

Les types sont omniprésents :

const Router = require("express").Router;
const graphqlHTTP = require("express-graphql");
const { makeExecutableSchema } = require("graphql-tools");
const service = require("../service");

const router = Router();

const typeDefs = `
type Post {
  id: ID!
  title: String!
  content: String!
}
`;

const resolvers = {};

router.use(
  graphqlHTTP({
    schema: makeExecutableSchema({ typeDefs, resolvers }),
    graphiql: true
  })
);

module.exports = router;

TRois TYPES PRINCIPAUX

type permet de déclarer la forme des modèles qu'on manipule

 

les requêtes pour récupérer les données : Query

 

et les actions pour transformer les données :  Mutation

 

 

const typeDefs = `
type User {
    fistnames: [String]
    lastname: String!
    age: Int
    gender: Gender!
}
enum Gender {
  FEMALE
  MALE
  OTHER
}
type Query {
  users : [User]
}
type Mutation {
  createUser(UserInput): User
}
`);

Les resolvers

Leur nom doit correspondre à une Query, ou une Mutation 

 

La fonction resolver sera exécutée à l'appel de type correspondant.

const resolvers = {
    Query: {
        users (parentValue, args, context) {
            return [
                {firstnames: ['Winston', 'Leonard', 'Spencer'] /*...*/},
                {firstnames: ['Nelson ', 'Rolihlahla '] /*...*/}
            ];
        }
    }
};

router.use(
  graphqlHTTP({
    schema: makeExecutableSchema({ typeDefs, resolvers }),
    graphiql: true
  })
);

retour à l'exercice 1

GraphQL, PARTIE CLIENT

Excercice n°2

Les articles sont disponibles

Comment y avoir accès en dehors ?

GRAPHQL reste du HTTP

curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ posts { id title } }"}' \
http://localhost:3001/graphql

Dummy with axios

const result = await axios.post("/graphql", { query : `{ users { lastnames } }` });
console.log(result);
/*
{
  data : {
    data : {
      users : [
        {firstnames: ['Winston', 'Leonard', 'Spencer']},
        {firstnames: ['Nelson ', 'Rolihlahla ']}
      ]
    }
  }
}
*/

retour à l'exercice 2

Création d'un Comment via GraphQL

Excercice n°3

Operation Name

Pour nommer les requêtes envoyées à une API GraphQL.
 

Très utile pour débugger et pour la lisibilité du code

query getPosts {
  posts {
    id
    title
    content
  }
}

Argument

Paramètre d'entré d'une Query GraphQL

posts(id:"abc1234") {
    title
    content
}

Variables

Variable typée d'une opération

query getPostById($id: ID!){
    posts(id: $id) {
        title
        content
    }
}

Variable

Paramètre

MUtations

La Mutation, et très semblable à la Query car elle représente une opération executable sur le graph.

 

Par convention
Mutation = modification

Query = lecture

type Mutation {
  createUser(UserInput): User
}

MUtations

Comme les Query, on doit lui fournir un resolver correspondant

 

const resolvers = {
    Mutation: {
        createUser(parentValue, args) {
            return addNewUser(args);
        }
    }
};

retour à l'exercice 3

Création d'un Post via GraphQL

Excercice n°4

Input TYPE

Fait pour représenter des objets complexes en paramètre de mutation

const typeDefs = `
type User {
    id: ID!
    fistnames: [String]!
    lastname: String!
    age: Int
}
input UserInput {
    fistnames: [String]!
    lastname: String!
    age: Int
}

type Mutation {
  createUser(UserInput): User
}
`);

retour à l'exercice 4

Conclusion

Vous savez faire un CRUD en GraphQL


Pour les projets de plus grande envergure Apollo devient vite nécessaire
 

Peu de désavantage comparé à REST, excepté le caching encore dure à gérer finement, et reste moins utilisé par la majorité.

Merci

GraphQL workshop

By Mathieu Breton

GraphQL workshop

  • 1,851