meteor - Apollo/GraphQl-El tipo debe ser Tipo de entrada
(2)
Llegando a todos ustedes en el proceso de aprendizaje e integración de Apollo y graphQL en uno de mis proyectos. Hasta ahora todo va bien, pero ahora estoy tratando de tener algunas mutaciones y estoy teniendo problemas con el tipo de entrada y el tipo de consulta. Siento que es mucho más complicado de lo que debería ser y, por lo tanto, estoy buscando consejos sobre cómo debo manejar mi situación. Los ejemplos que encontré en línea son siempre con esquemas muy básicos, pero la realidad siempre es más compleja, ya que mi esquema es bastante grande y tiene el siguiente aspecto (copiaré solo una parte):
type Calculation {
_id: String!
userId: String!
data: CalculationData
lastUpdated: Int
name: String
}
type CalculationData {
Loads: [Load]
validated: Boolean
x: Float
y: Float
z: Float
Inputs: [Input]
metric: Boolean
}
Luego se definen las entradas y las cargas, y así sucesivamente ...
Para esto quiero una mutación para guardar el "Cálculo", así que en el mismo archivo tengo esto:
type Mutation {
saveCalculation(data: CalculationData!, name: String!): Calculation
}
Mi resolver es como sigue:
export default resolvers = {
Mutation: {
saveCalculation(obj, args, context) {
if(context.user && context.user._id){
const calculationId = Calculations.insert({
userId: context.user._id,
data: args.data,
name: args.name
})
return Calculations.findOne({ _id: calculationId})
}
throw new Error(''Need an account to save a calculation'')
}
}
}
Entonces mi mutación es la siguiente: importar gql desde ''graphql-tag'';
export const SAVE_CALCULATION = gql`
mutation saveCalculation($data: CalculationData!, $name: String!){
saveCalculation(data: $data, name: $name){
_id
}
}
`
Finalmente estoy usando el componente Mutación para intentar guardar los datos:
<Mutation mutation={SAVE_CALCULATION}>
{(saveCalculation, { data }) => (
<div onClick={() => saveCalculation({ variables : { data: this.state, name:''name calcul'' }})}>SAVE</div>
}}
</Mutation>
Ahora me sale el siguiente error:
[Error de GraphQL]: Mensaje: El tipo de Mutation.saveCalculation (data :) debe ser Tipo de entrada pero obtenido: CalculationData!., Ubicación: undefined, Ruta: undefined
De mi investigación y algunas otras publicaciones de SO, obtengo que debo definir el tipo de entrada además del tipo de consulta, pero el tipo de entrada solo puede avecinar tipos escalares, pero mi esquema depende de otros esquemas (y eso no es escalar). ¿Puedo crear tipos de entrada en función de otros tipos de entrada, etc. cuando el último tiene solo tipos escalares? Estoy un poco perdido porque parece mucha redundancia. Apreciaría mucho alguna orientación sobre las mejores prácticas. Estoy convencido de que Apollo / graphql podría brindarme una buena ayuda con el tiempo en mi proyecto, pero debo admitir que es más complicado de lo que pensé para implementarlo cuando los Esquemas son un poco complejos. Los ejemplos en línea generalmente se adhieren a una cadena y un booleano.
De la spec :
Los campos pueden aceptar argumentos para configurar su comportamiento. Estas entradas son a menudo escalares o enumeraciones, pero a veces necesitan representar valores más complejos.
Un objeto de entrada GraphQL define un conjunto de campos de entrada; los campos de entrada son escalares, enumeraciones u otros objetos de entrada. Esto permite que los argumentos acepten estructuras complejas arbitrariamente.
En otras palabras, no puede usar
GraphQLObjectType
como el tipo para un campo
GraphQLInputObjectType
; debe usar otro
GraphQLInputObjectType
.
Cuando escribe su esquema usando SDL, puede parecer redundante tener que crear un tipo de
Load
y una entrada
LoadInput
, especialmente si tienen los mismos campos.
Sin embargo, bajo el capó, los tipos y entradas que define se convierten en clases de objeto muy diferentes, cada una con diferentes propiedades y métodos.
Existe una funcionalidad que es específica para un
GraphQLObjectType
(como aceptar argumentos) que no existe en un
GraphQLInputObjectType
y viceversa.
Tratar de usar en lugar de otro es como intentar colocar una clavija cuadrada en un agujero redondo. "No sé por qué necesito un círculo. Tengo un cuadrado. Ambos tienen un diámetro. ¿Por qué necesito los dos?"
Fuera de eso, hay una buena razón práctica para mantener los tipos y las entradas por separado. Esto se debe a que en muchos escenarios, expondrá muchos campos en el tipo que no expondrá en la entrada.
Por ejemplo, su tipo podría incluir campos derivados que en realidad son una combinación de los datos subyacentes.
O podría incluir campos para relacionarse con otros datos (como un campo de
friends
en un
User
).
En ambos casos, no tendría sentido hacer que estos campos formen parte de los datos que se envían como argumento para algún campo.
Del mismo modo, es posible que tenga algún campo de entrada que no querría exponer en su contraparte de tipo (un campo de
password
viene a la mente).
Sí tu puedes:
Los campos en un tipo de objeto de entrada pueden referirse a los tipos de objeto de entrada, pero no puede mezclar los tipos de entrada y salida en su esquema. Los tipos de objetos de entrada tampoco pueden tener argumentos en sus campos.
Los tipos de entrada se deben definir además de los tipos normales. Por lo general, tendrán algunas diferencias, por ejemplo, la entrada no tendrá un id o un campo createdAt.