Mutación (Mutation)
Una consulta en GraphQL solo realiza operaciones de lectura (READ), las mutaciones nos permiten realizar otras operaciones tales como crear (CREATE), actualizar (UPDATE) y eliminar (DELETE).
Creando una mutación simple
import express from 'express'
import graphqlHTTP from 'express-graphql'
import { GraphQLSchema,
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLInt,
GraphQLBoolean,
GraphQLNonNull,
GraphQLList } from 'graphql'
const Authors = [{
id: '8dlx7ak38fd39dv79ad',
name: 'Isiah Hamilton',
twitterHandle: '@isiah2000'
},
{
id: 'jd3kd03d0w9a0l35rh74',
name: 'Giovanni Harvey',
twitterHandle: '@gio_har'
},
{
id: '0hy894hf0dlkfh9oinv',
name: 'Lawrence Rhodes',
twitterHandle: '@rhodes'
}]
const Videos = [{
id: '1',
title: 'Mattis ullamcorper velit sed ullamcorper',
duration: 180,
watched: false,
author_id :'0hy894hf0dlkfh9oinv'
},
{
id: '2',
title: 'Habitasse platea dictumst vestibulum',
duration: 240,
watched: true,
author_id :'jd3kd03d0w9a0l35rh74'
},
{
id: '3',
title: 'Urna et pharetra pharetra massa massa',
duration: 160,
watched: false,
author_id :'8dlx7ak38fd39dv79ad'
},
{
id: '4',
title: 'Eu facilisis sed odio morbi',
duration: 260,
watched: true,
author_id :'0hy894hf0dlkfh9oinv'
}]
const getVideoById = (id) => new Promise((resolve) => {
const [video] = Videos.filter((video) => {
return video.id === id
})
resolve(video)
})
const getVideos = () => new Promise((resolve) => resolve(Videos))
const createVideo =({ title, duration, watched, author_id }) => {
const
id = Videos.length + 1,
video = {
id : id.toString(),
title,
duration,
watched,
author_id
};
// Save on memory
Videos.push(video)
return video
}
const app = express()
const AuthorType = new GraphQLObjectType({
name: 'Author',
description: 'Represent a Author.',
fields: {
id: {
type: new GraphQLNonNull(GraphQLString),
description: 'Id of the author.'
},
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'Name of the author.'
},
twitterHandle: {
type: GraphQLString,
description: 'Twitter name account.'
}
}
})
const VideoType = new GraphQLObjectType({
name: 'Video',
description: 'Represent a Video.',
fields: {
id: {
type: GraphQLID,
description: 'Id of the video.'
},
title: {
type: GraphQLString,
description: 'Title of the video.'
},
duration: {
type: GraphQLInt,
description: 'Duration of the video.'
},
watched: {
type: GraphQLBoolean,
description: 'Whether or not the viewer has watch the video.'
},
author: {
type: AuthorType,
description: 'Author information.',
resolve: (parent) => {
return Authors.find(author => author.id == parent.author_id)
}
}
}
})
const query = new GraphQLObjectType({
name: 'Query',
description: 'Application Schema Query Root.',
fields: () => ({
authors: {
type: new GraphQLList(AuthorType),
description: 'List of all Authors.',
resolve: function() {
return Authors
}
},
videos: {
type: new GraphQLList(VideoType),
description: 'List of all Videos.',
resolve: getVideos
},
video: {
type: VideoType,
description: 'Single video.',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'Id of the video.'
}
},
resolve: (_, args) => {
return getVideoById(args.id)
}
}
})
})
const mutation = new GraphQLObjectType({
name: 'Mutation',
description: 'The root mutation type.',
fields: {
createVideo: {
type: VideoType,
args: {
title: {
type: new GraphQLNonNull(GraphQLString),
description: 'The title of the video.'
},
duration: {
type: new GraphQLNonNull(GraphQLInt),
description: 'The duration of the video (in seconds).'
},
watched: {
type: new GraphQLNonNull(GraphQLBoolean),
description: 'Whether or not the video is released.'
},
author_id: {
type: new GraphQLNonNull(GraphQLID),
description: 'Author id.'
}
},
resolve: (_, args) => {
return createVideo(args)
}
}
}
})
const schema = new GraphQLSchema({
query,
mutation
})
app.use('/graphql', graphqlHTTP({
schema,
rootValue: root,
graphiql: true
}))
app.listen(3000, () => {
console.log(`Server listening on port ${PORT}`)
})
Query:
mutation {
createVideo(
title: "Foo",
duration: 300,
watched: false,
author_id: "8dlx7ak38fd39dv79ad"
) {
title
duration
watched
author {
name
}
}
}
Utilizando GraphQLInputObjectType
Este método nos permite definir mutaciones mas complejas, por ejemplo aquellas entradas de datos el cual nosotros en el diseño de aplicación tienen que ser mandatorias.
const VideoInputType = new GraphQLInputObjectType({
name: 'VideoInput',
fields: {
title: {
type: new GraphQLNonNull(GraphQLString),
description: 'The title of the video.'
},
duration: {
type: new GraphQLNonNull(GraphQLInt),
description: 'The duration of the video (in seconds).'
},
watched: {
type: new GraphQLNonNull(GraphQLBoolean),
description: 'Whether or not the video is released.'
},
author_id: {
type: new GraphQLNonNull(GraphQLID),
description: 'Author id.'
}
}
})
const mutation = new GraphQLObjectType({
name: 'Mutation',
description: 'The root mutation type.',
fields: {
createVideo: {
type: VideoType,
args: {
// common used the word "input" instead "video"
video : {
type: new GraphQLNonNull(VideoInputType)
}
},
resolve: (_, args) => {
return createVideo(args.video)
}
}
}
})
Query:
mutation {
createVideo(video: {
title: "Foo",
duration: 300,
watched: false,
author_id: "8dlx7ak38fd39dv79ad"
}) {
title
duration
watched
author {
name
}
}
}
Nombres de mutaciones
Nombrar mutaciones puede ser un desafío. Es de buena practica utilizar verbo primero o la acción. Ejemplo: createUser, updateStories.