GraphQL
Un lenguaje de consultas para APIs
Repositorio: https://github.com/dimax/que-es-graphql
Una alternativa más eficiente a REST
Secciones de la APP
- Nombre del autor.
- Títulos de sus últimos post.
- Últimos tres seguidores.
Proceso de comunicación con la API REST
Proceso de comunicación con la API GraphQL
GraphQL: SDL
Lenguaje de Definición de Esquemas
Schema Definition Language
GraphQL SDL: Tipos de datos
type User {
id: ID!
name: String!
age: Int!
posts: [Post]!
followers: [Person]!
}
type Post {
id: ID!
title: String!
author: Person!
}
GraphQL SDL: Definición de las posibles consultas
# `Query` es una palabra clave que describe las posibles consultas que tiene la API
type Query {
users(id: ID): [User]!
# Recupera los seguidores de un usuario o,
# si se pasa el parámetro \`last\`, recupera los últimos \`last\` seguidores
followers(user: ID!, last: Int): [User]!
posts(user: ID): [Post]!
}
# Ejemplo de una consulta donde se recuperan
# únicamente el nombre de todas las personas
{
users {
name
}
}
# JSON resultante
{
"data": {
"users": [
{ "name": "Johnny" },
{ "name": "Sarah" },
{ "name": "Alice" }
]
}
}
GraphQL SDL: Definición de las posibles mutaciones
# `Mutation` es una palabra clave que describe el conjunto de métodos para modificar datos
type Mutation {
# Agrega un nuevo Usuario
createUser(name: String!, age: Int!): User!
}
# Ejemplo de una inserción que como resultado
# devuelve los datos de un nuevo usuario
{
mutation {
# Se llama Bob y tiene 36 años
createUser(name: "Bob", age: 36) {
name
age
}
}
}
# JSON resultante
{
"data": {
"createUser": {
"name": "Bob",
"age": 36
}
}
}
GraphQL: Implementación en el servidor
Definición del esquema
// Archivo `server/schemas/index.js`
const typeDefs = /* GraphQL */`
type Query {
users(id: ID): [User]!
# Recupera los seguidores de un usuario o,
# si se pasa el parámetro \`last\`, recupera los últimos \`last\` seguidores
followers(user: ID!, last: Int): [User]!
posts(user: ID): [Post]!
}
type Mutation {
# Agrega un nuevo Usuario
createUser(name: String!, age: Int!): User!
}
type User {
id: ID!
name: String!
age: Int!
posts: [Post]!
followers: [User]!
}
type Post {
id: ID!
title: String!
user: User!
}
`
Implementación del esquema: Tipos de datos
// Archivo `server/schemas/index.js`
const User = {
id: (root) => root.id,
name: (root) => root.name,
age: (root) => root.age,
posts: (root) => datosDePrueba.posts.filter(post => post.id === root.id),
followers: (root) => root.followers,
};
const Post = {
id: (root) => root.id,
title: (root) => root.title,
// Considere la función `reduce` como un `findById` de una librería de consulta de DB
user: (root) => datosDePrueba.users.reduce((user, actual) => (
user || actual.id === root.user_id && actual
)),
};
Implementación del esquema: Consultas
// Archivo `server/schemas/index.js`
const Query = {
// Este método se encarga de manejar las dos posibles
// consultas de `users`
users: (last) => (
!last
? datosDePrueba.users
: datosDePrueba.users.slice(datosDePrueba.users.length - last, datosDePrueba.users.length)
),
followers: (id, last) => (
datosDePrueba.users
.filter(user => user.id === id)
.slice(
!last ? 0 : datosDePrueba.users.length - last,
datosDePrueba.users.length
)
),
posts: (id) => (
!id
? datosDePrueba.posts
: datosDePrueba.posts.filter(post => post.user_id === id)
),
};
Implementación del esquema: Mutaciones
// Archivo `server/schemas/index.js`
const Mutation = {
createUser: (_, { name, age }) => {
const user = {
id: datosDePrueba.users.length + 1,
name,
age,
followers: [],
};
datosDePrueba.users.push(user);
return user;
},
};
Implementación del esquema: Exportar configuración
// Archivo `server/schemas/index.js`
const resolvers = {
Query,
Mutation,
Person,
Post,
};
module.exports = makeExecutableSchema({
typeDefs,
resolvers,
});
GraphQL: Implementación en el cliente
Creación de una consulta
// Archivo `client/components/App.vue`
<template>
<div id="app">
<h4 v-if="loading">Loading...</h4>
<h4 v-if="!loading">Listado de autores</h4>
<ul>
<li
v-for="user in users"
:key="user.id"
>{{user.name}}
</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag';
const USERS = gql`
query AllUsersQuery {
users {
id
name
}
}
`
export default {
data() {
return {
users: [],
loading: 0,
};
},
apollo: {
users: {
query: USERS,
},
},
};
</script>
Creación de una mutación
// Archivo `client/components/App.vue`
<template>
<div id="app">
+ <h4 v-if="!loading">Alta de autor</h4>
+ <div>
+ <input
+ v-model="user.name"
+ type="text"
+ >
+ <input
+ v-model="user.age"
+ type="number"
+ >
+ </div>
<h4 v-if="loading">Loading...</h4>
<h4 v-if="!loading">Listado de autores</h4>
<ul>
<li
v-for="user in users"
:key="user.id"
>{{user.name}}
</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag';
const USERS = gql`
query AllUsersQuery {
users {
id
name
}
}
`
+ const CREATE_USER = gql`
+ mutation CreateUserMutation($name: String!, $age: Int!) {
+ createUser(
+ name: $name,
+ age: $age,
+ ) {
+ id
+ }
+ }
+ `
export default {
data() {
return {
users: [],
+ user: {
+ name: '',
+ age: 0,
+ },
loading: 0,
};
},
apollo: {
users: {
query: USERS,
},
},
+ methods: {
+ createUser() {
+ const { user: { name, age } } = this.$data;
+
+ this.$apollo.mutate({
+ mutation: CREATE_USER,
+ variables: {
+ name,
+ age,
+ },
+ }).then(({ data: { createUser: { id }}}) => {
+ const user = {
+ id,
+ name,
+ age,
+ };
+
+ this.users = [...this.users, user];
+ this.user = {
+ name: '',
+ age: 0,
+ };
+ });
+ },
+ },
};
</script>
¿Qué es GraphQL?
By Luciano Graziani
¿Qué es GraphQL?
Introduce los conceptos claves de GraphQL de forma general para poder compararlo con REST. A su vez ofrece un ejemplo de cómo implementar una API.
- 757