node.js 如何使 GraphQL 中的 InputType 变得灵活?
How make InputType flexible in GraphQL in node.js?
关于使用 Node.js 实现 GraphQL,我的问题很简单明了。
有两个突变。一个是 createUser
,另一个是 updateUser
。两个突变都有参数 user
即 UserInputType
.
const UserInputType = new GraphQLInputObjectType({
name: 'UserInputType',
description: 'a user input type',
fields: () => {
return {
username: {
type: GraphQLString,
description: 'a unique username for a user',
},
email: {
type: GraphQLString,
description: 'a unique email for a user',
},
password: {
type: GraphQLString,
description: 'a strong password for a user',
},
};
},
});
问题是,createUser
突变需要 所有参数 用户名、电子邮件和密码。
updateUser
至少需要一个参数。我必须为每个突变实现两个 UserInputType
吗?我觉得这不是个好办法。
希望得到线索!
调用突变时可以省略输入类型的字段。处理该突变的代码将为缺少的字段提供 undefined
值。
如果 createUser
和 updateUser
所需的数据集相同,则单一输入类型即可。在这种情况下,客户端是否提供了所有参数都必须检查 createUser
,这可以在以下示例代码中的 mutateAndGetPayload
函数中完成。另一种方法是让客户端对此进行检查(如果您编写客户端)。这种方法的优点是可以避免相同字段的重复代码。
另一种方法是定义两个独立但大部分重复的类型。唯一的区别是 updateUser
的输入对象类型具有 GraphQLString
,而 createUser
的另一个对象类型具有 GraphQLNonNull(GraphQLString)
。这种方法的优点是可以避免检查空参数。但是,我认为,在某些时候检查输入有效性是明智的。 Null 值只是众多无效值之一。
按照第一种方法,我用一个字段id
扩展了你的UserInputType
(通常用于更新操作来识别用户)并实现了createUserMutation
和updateUserMutation
.
在代码中,mutationWithClientMutationId
是来自 graphql-relay 库的辅助函数。
const UserInputType = new GraphQLInputObjectType({
name: 'UserInputType',
description: 'a user input type',
fields: {
id: { type: GraphQLID },
.....
.....
},
});
const createUserMutation = mutationWithClientMutationId({
name: 'CreateUser',
inputFields: {
user: { type: UserInputType },
},
outputFields: {
id: {
type: GraphQLID,
resolve: ({id}) => id,
},
},
mutateAndGetPayload: ({user}) => {
console.log('@ createUserMutation: Received user input:');
console.log(`id: ${user.id}, username: ${user.username}, email: ${user.email}, password: ${user.password}`);
if (hasValidInputs(user.username, user.email, user.password)) {
return {id: '9999999'};
} else {
return {id: '-1'}
}
},
});
const updateUserMutation = mutationWithClientMutationId({
name: 'UpdateUser',
inputFields: {
user: { type: UserInputType },
},
outputFields: {
status: {
type: GraphQLBoolean,
resolve: ({status}) => status,
},
},
mutateAndGetPayload: ({user}) => {
console.log('@ updateUserMutation: Received user input:');
console.log(`id: ${user.id}, username: ${user.username}, email: ${user.email}, password: ${user.password}`);
return {status: true};
},
});
运行 使用 express-graphql 的 GraphQL 服务器,updateMutation
可以使用以下内容进行测试:
mutation {
updateUser(input: {
clientMutationId:"12344",
user: {
username: "new username"
}
}) {
clientMutationId,
status,
}
}
GraphQL 服务器响应:
{
"data": {
"updateUser": {
"clientMutationId": "12344",
"status": true
}
}
}
关于使用 Node.js 实现 GraphQL,我的问题很简单明了。
有两个突变。一个是 createUser
,另一个是 updateUser
。两个突变都有参数 user
即 UserInputType
.
const UserInputType = new GraphQLInputObjectType({
name: 'UserInputType',
description: 'a user input type',
fields: () => {
return {
username: {
type: GraphQLString,
description: 'a unique username for a user',
},
email: {
type: GraphQLString,
description: 'a unique email for a user',
},
password: {
type: GraphQLString,
description: 'a strong password for a user',
},
};
},
});
问题是,createUser
突变需要 所有参数 用户名、电子邮件和密码。
updateUser
至少需要一个参数。我必须为每个突变实现两个 UserInputType
吗?我觉得这不是个好办法。
希望得到线索!
调用突变时可以省略输入类型的字段。处理该突变的代码将为缺少的字段提供 undefined
值。
如果 createUser
和 updateUser
所需的数据集相同,则单一输入类型即可。在这种情况下,客户端是否提供了所有参数都必须检查 createUser
,这可以在以下示例代码中的 mutateAndGetPayload
函数中完成。另一种方法是让客户端对此进行检查(如果您编写客户端)。这种方法的优点是可以避免相同字段的重复代码。
另一种方法是定义两个独立但大部分重复的类型。唯一的区别是 updateUser
的输入对象类型具有 GraphQLString
,而 createUser
的另一个对象类型具有 GraphQLNonNull(GraphQLString)
。这种方法的优点是可以避免检查空参数。但是,我认为,在某些时候检查输入有效性是明智的。 Null 值只是众多无效值之一。
按照第一种方法,我用一个字段id
扩展了你的UserInputType
(通常用于更新操作来识别用户)并实现了createUserMutation
和updateUserMutation
.
在代码中,mutationWithClientMutationId
是来自 graphql-relay 库的辅助函数。
const UserInputType = new GraphQLInputObjectType({
name: 'UserInputType',
description: 'a user input type',
fields: {
id: { type: GraphQLID },
.....
.....
},
});
const createUserMutation = mutationWithClientMutationId({
name: 'CreateUser',
inputFields: {
user: { type: UserInputType },
},
outputFields: {
id: {
type: GraphQLID,
resolve: ({id}) => id,
},
},
mutateAndGetPayload: ({user}) => {
console.log('@ createUserMutation: Received user input:');
console.log(`id: ${user.id}, username: ${user.username}, email: ${user.email}, password: ${user.password}`);
if (hasValidInputs(user.username, user.email, user.password)) {
return {id: '9999999'};
} else {
return {id: '-1'}
}
},
});
const updateUserMutation = mutationWithClientMutationId({
name: 'UpdateUser',
inputFields: {
user: { type: UserInputType },
},
outputFields: {
status: {
type: GraphQLBoolean,
resolve: ({status}) => status,
},
},
mutateAndGetPayload: ({user}) => {
console.log('@ updateUserMutation: Received user input:');
console.log(`id: ${user.id}, username: ${user.username}, email: ${user.email}, password: ${user.password}`);
return {status: true};
},
});
运行 使用 express-graphql 的 GraphQL 服务器,updateMutation
可以使用以下内容进行测试:
mutation {
updateUser(input: {
clientMutationId:"12344",
user: {
username: "new username"
}
}) {
clientMutationId,
status,
}
}
GraphQL 服务器响应:
{
"data": {
"updateUser": {
"clientMutationId": "12344",
"status": true
}
}
}