graphql apollo apollo-server

graphql - ¿Se requiere que los métodos de mutación estén en el nivel superior?



apollo apollo-server (2)

¡Absolutamente en desacuerdo con Daniel!

Este es un enfoque sorprendente que ayuda a los defensores a comprender rápidamente qué operaciones tienen uno u otro recurso / modelo. Y no enumerar listas loooong de mutaciones.

Llamar a múltiples mutaciones en una solicitud es antipattern común. Para tales casos es mejor crear una mutación compleja.

Pero incluso si necesita realizar dicha operación con varias mutaciones, puede usar alias:

await graphql({ schema, source: ` mutation { op1: article { like(id: 1) } op2: article { like(id: 2) } op3: article { unlike(id: 3) } op4: article { like(id: 4) } } `, }); expect(serialResults).toEqual([ ''like 1 executed with timeout 100ms'', ''like 2 executed with timeout 100ms'', ''unlike 3 executed with timeout 5ms'', ''like 4 executed with timeout 100ms'', ]);

Consulte el siguiente caso de prueba: https://github.com/nodkz/conf-talks/blob/master/articles/graphql/schema-design/ tests /mutations-test.js

Los métodos como / desemejante son asíncronos con los tiempos de espera y funcionan secuencialmente

Todos los documentos y tutoriales suelen mostrar ejemplos simples de mutaciones que se parecen a esto:

extend type Mutation { edit(postId: String): String }

Pero de esta manera, el método de edit debe ser único en todas las entidades, lo que para mí no parece ser una forma muy robusta de escribir cosas. Me gustaría describir la mutación similar a cómo describimos las consultas, algo como esto:

type PostMutation { edit(postId: String): String } extend type Mutation { post: PostMutation }

Esto parece ser un esquema válido (se compila y puedo verlo reflejado en los documentos de graph-i-ql generados). Pero no puedo encontrar una manera de hacer que los resolutores funcionen con este esquema.

¿Es este un caso soportado para GraphQL?


Es posible, pero en general no es una buena idea porque:

Se rompe la convención. Por convención, las mutaciones están siempre en la raíz. Para distinguir entre realizar la misma acción en diferentes tipos, debe nombrar sus mutaciones, por ejemplo, editPost y editComment , en lugar de solo edit .

Tener las mutaciones en la raíz tiene sentido conceptualmente. Cualquiera que sea la acción que esté realizando (le gusta una publicación, verifica un correo electrónico, envía un pedido, etc.) no depende de que GraphQL tenga que resolver campos adicionales antes de tomar la acción. Esto es diferente cuando en realidad estás consultando datos. Por ejemplo, para obtener comentarios sobre una publicación, es posible que tengamos que resolver un campo de user , luego un campo de posts y, finalmente, el campo de comments de cada publicación. En cada "nivel", el contenido del campo depende del valor que el campo principal resolvió. Esto normalmente no es el caso con mutaciones.

Bajo el capó, las mutaciones se resuelven secuencialmente . Esto es contrario a la resolución de campo normal que ocurre en paralelo. Eso significa, por ejemplo, que el primer nombre y el lastName de un tipo de User se resuelven al mismo tiempo. Sin embargo, si su tipo de operación es una mutation , todos los campos raíz se resolverán de uno en uno. Así que en una consulta como esta:

mutation SomeOperationName { createUser editUser deleteUser }

Cada mutación se producirá de una en una, en el orden en que aparecen en el documento. Sin embargo, esto solo funciona para la raíz y solo cuando la operación es una mutation , por lo que estos tres campos se resolverán en paralelo:

mutation SomeOperationName { user { create edit delete } }

Si aún quieres hacerlo, a pesar de lo anterior, así es como lo haces cuando usas makeExecutableSchema , que es lo que Apollo usa debajo del capó:

const resolvers = { Mutation: { post: () => ({}), // return an empty object, }, PostMutation: { edit: () => editPost(), }, // Other types here }

Su esquema definió PostMutation como un tipo de objeto, por lo que GraphQL espera que ese campo devuelva un objeto. Si omite la resolución para post , devolverá un valor nulo, lo que significa que no se activará ninguna de las resoluciones para el tipo de devolución ( PostMutation ). Eso también significa, también podemos escribir:

mutation { post }

que no hace nada pero sigue siendo una consulta válida. Lo cual es otra razón más para evitar este tipo de estructura de esquema.