node.js 如何使 GraphQL 中的 InputType 变得灵活?

How make InputType flexible in GraphQL in node.js?

关于使用 Node.js 实现 GraphQL,我的问题很简单明了。

有两个突变。一个是 createUser,另一个是 updateUser。两个突变都有参数 userUserInputType.

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 值。

如果 createUserupdateUser 所需的数据集相同,则单一输入类型即可。在这种情况下,客户端是否提供了所有参数都必须检查 createUser,这可以在以下示例代码中的 mutateAndGetPayload 函数中完成。另一种方法是让客户端对此进行检查(如果您编写客户端)。这种方法的优点是可以避免相同字段的重复代码。

另一种方法是定义两个独立但大部分重复的类型。唯一的区别是 updateUser 的输入对象类型具有 GraphQLString,而 createUser 的另一个对象类型具有 GraphQLNonNull(GraphQLString)。这种方法的优点是可以避免检查空参数。但是,我认为,在某些时候检查输入有效性是明智的。 Null 值只是众多无效值之一。

按照第一种方法,我用一个字段id扩展了你的UserInputType(通常用于更新操作来识别用户)并实现了createUserMutationupdateUserMutation.

在代码中,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
    }
  }
}