[英]graphql-compose, trigger resolver of a nested field
我是 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
},
})
作为您的问题,您可以使用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
},
})
我建议使用解析器包装器。 这些用于检查身份验证/权限之类的事情,但适用于您正在寻找的某种通用类型验证。
我相信这篇文档将帮助您获得更高层次的理解-
https://graphql-compose.github.io/docs/basics/what-is-resolver.html#wrapping-resolver
您需要了解的是 resolverParams 是如何工作的 (rp)。 您可以通过调查 rps 获得很多关于查询中发生的事情的信息,并使用包装器做很多事情。
本文档特定于 MongoDB 实现,但可以更改代码以适应任何 DB。 https://graphql-compose.github.io/docs/plugins/plugin-mongoose.html#access-and-modify-mongoose-doc-before-save
这将是我提到的包装器 function 的一般布局。 该代码是从上面提到的 MongoDB 实现中抽象出来的。
function 可能看起来像这样:
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
}
实现这一点的最佳方法将基于您的应用程序结构以及您如何组成全局模式。 我建议通读解析器文档以找出对您有意义的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.