Une spécification de communication pour API
Made in Facebook
Créé en 2012
Publié en 2015
Over HTTP, typé Fortement
REST :
RPC :
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
Rdv à cette adresse :
Lisez le readme jusqu'au chapitre "Exercice"
GraphiQL : Outil de visualisation/manipulation d'une API GraphQL
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;
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;
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;
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
}
`);
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
})
);
Les articles sont disponibles
Comment y avoir accès en dehors ?
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ posts { id title } }"}' \
http://localhost:3001/graphql
const result = await axios.post("/graphql", { query : `{ users { lastnames } }` });
console.log(result);
/*
{
data : {
data : {
users : [
{firstnames: ['Winston', 'Leonard', 'Spencer']},
{firstnames: ['Nelson ', 'Rolihlahla ']}
]
}
}
}
*/
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
}
}
Paramètre d'entré d'une Query GraphQL
posts(id:"abc1234") {
title
content
}
Variable typée d'une opération
query getPostById($id: ID!){
posts(id: $id) {
title
content
}
}
Variable
Paramètre
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
}
Comme les Query, on doit lui fournir un resolver correspondant
const resolvers = {
Mutation: {
createUser(parentValue, args) {
return addNewUser(args);
}
}
};
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
}
`);
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é.