【问题标题】:graphql-compose, trigger resolver of a nested fieldgraphql-compose,嵌套字段的触发解析器
【发布时间】:2021-07-20 02:37:20
【问题描述】:

我是 GraphQL 的初学者,将它与 Node 和 graphql-compose 一起使用来创建模式。

我不确定这样做是否正确:AddressTC 是可重用类型,当创建或更新UserTC 或其他类型时,我想自动触发AddressTC 的验证。如果你知道更好的方法,我会接受的。

// userType.js
// In this example we'll use UserTC but this can another type which also use AdressTC.

const UserTC = schemaComposer.createObjectTC({
    name: 'User',
    fields: {
        id: 'String',
        name: 'String',
        slug: 'String',
        actived: 'Boolean',
        registered: 'Boolean',
        address: AddressTC,
    }
});

const UserITC = UserTC.getInputTypeComposer()

UserTC.addResolver({
    kind: 'mutation',
    name: 'create',
    args: {
        data: UserITC
    },
    type: UserTC,
    resolve: async ({args: {data}, context}) => {
        // Need to trigger validation and geocode of AddressTC
        // do something...
        // save in database
    },
})

// addressType.js
// reusable Address Type

const AddressTC = schemaComposer.createObjectTC({
    name: 'Address',
    description: 'Type of address',
    fields: {
        street: 'String',
        number: 'String',
        postcode: 'String',
        city: 'String',
        comment: 'String',
        country: 'String',
        quality: QualityETC
    }
});

const AddressITC = AddressTC.getInputTypeComposer()

AddressTC.addResolver({
    kind: 'mutation',
    name: 'validation',
    args: {
        data: AddressITC
    },
    type: AddressTC,
    resolve: async ({args: {data}, context}) => {
        // When address is puted or updated :
        // Make validation
        // Geocode {Lat,Lng} with map provider 
        // Save in DB           
    },
})

【问题讨论】:

    标签: node.js graphql graphql-compose


    【解决方案1】:

    我建议使用解析器包装器。 这些用于检查身份验证/权限之类的事情,但也适用于您正在寻找的某种通用类型验证。

    我相信这篇文档将帮助您获得更高层次的理解 -
    https://graphql-compose.github.io/docs/basics/what-is-resolver.html#wrapping-resolver

    您需要了解的是 resolverParams 的工作原理 (rp)。您可以通过调查 rps 获得有关查询中发生的事情的大量信息,并使用包装器做很多事情。

    本文档专门针对 MongoDB 实现,但可以更改代码以适应任何数据库。 https://graphql-compose.github.io/docs/plugins/plugin-mongoose.html#access-and-modify-mongoose-doc-before-save

    这将是我提到的包装函数的一般布局。代码是从上面提到的MongoDB实现中抽象出来的。

    函数可能看起来像这样:

    function addressValidationWrapper(resolvers){
      Object.keys(resolvers).forEach((k) => {
        resolvers[k] = resolvers[k].wrapResolve(next => async rp => {
          // check if has address field/type
             // validate address
                // if address valid - resolve
                // else throw error
          return next(rp)
        })
      })
     return resolvers
    }
    

    实现这一点的最佳方式将基于您的应用程序结构以及您如何组成全局架构。我建议通读解析器文档以找出对您有意义的内容。

    【讨论】:

      【解决方案2】:

      作为您的问题,您可以使用 joi 等验证库,并在解析器中应用您的验证架构。

      import joi from 'joi'
      
      const UserTC = schemaComposer.createObjectTC({
          name: 'User',
          fields: {
              id: 'String',
              name: 'String',
              slug: 'String',
              actived: 'Boolean',
              registered: 'Boolean',
              address: AddressTC,
          }
      });
      
      const UserITC = UserTC.getInputTypeComposer()
      
      /* Create it here, or in the address file and import it here.
         Personally, I place the validation schemas in separate files
      */
      const addressTCSchema = Joi.object().keys({
          street: Joi.string().required(),
          number: Joi.number().required(),
          city: Joi.string().required(),
          postcode: Joi.string().required(),
          comment: Joi.string().required(),
          country: Joi.string().required(),
      })
      
      const userTCSchema = Joi.object({
          id: Joi.number().integer().required(),
          name: Joi.string()
              .pattern(new RegExp('^[a-zA-Z]')).required(),
          slug: Joi.string()
              .pattern(new RegExp('^[a-zA-Z]')).required(),
          actived: Joi.boolean().required(),
          registered: Joi.boolean().required(),
          address: addressTCSchema
      })
      
      UserTC.addResolver({
          kind: 'mutation',
          name: 'create',
          args: {
              data: UserITC
          },
          type: UserTC,
          resolve: async ({args: {data}, context}) => {
              // Need to trigger validation and geocode of AddressTC
              const { error } = userTCSchema.validate(data);
              if (error) {
                  // return or send 400 bad request
              }
              // do someting...
              // save in database
          },
      })
      

      【讨论】:

      • 这不是验证的问题,我已经知道Joi并使用它。我需要一个结构和可重用代码的解决方案。
      猜你喜欢
      • 2021-07-28
      • 2018-08-25
      • 1970-01-01
      • 2019-08-16
      • 2021-01-25
      • 2019-10-14
      • 2020-10-07
      • 2021-09-25
      • 1970-01-01
      相关资源
      最近更新 更多