我正在使用HAPI和Joi创建API来验证输入,我在不同模块之间共享验证模式时遇到了麻烦。 我正在使用面向组件的架构,看起来像那样
components
|_ moduleA
|_ moduleAController
|_ moduleAModel
|_ moduleARoute
|_ moduleAValidate
|_ moduleB
|_ moduleBController
|_ moduleBModel
|_ moduleBRoute
|_ moduleBValidate
|_ moduleC
...
在每个模块中,moduleXRoute
创建一个路由,该路由将moduleXController
的处理程序与moduleXValidate
的验证程序相关联。
当我使用Joi时,我正在对输入数据执行一些测试,问题出在哪里,我的moduleA
保留了moduleB
的列表,而moduleB
保留了对moduleA
的引用var moduleASchema = {
_id: Joi.objectId(),
name: Joi.string().required(),
moduleB: Joi.array().items(Joi.alternatives().try(Joi.objectId(), moduleBSchema)),
};
var moduleBSchema = {
_id: Joi.objectId(),
name: Joi.string().required(),
moduleA: Joi.alternatives().try(Joi.objectId(), moduleASchema),
};
,因此在验证器中暗示:
moduleAValidate
这就是为什么,我认为moduleBValidate
和moduleASchema
公开其他模块可以使用的moduleBSchema
和//moduleAValidate.js
var moduleBSchema = require('../moduleBValidate').moduleBschema;
//moduleBValidate.js
var moduleASchema = require('../moduleAValidate').moduleAschema;
是个好主意。
问题在于它产生循环依赖问题,因为在上面的例子中,我会:
<form name="ImportBulkAttendance" target="uploadFileJava" type="upload" default-map-name="content" focus-field-name="contentTypeId" header-row-style="header-row" default-table-style="basic-table">
<field name="filename" title="filename">
<file name="filename"/>
</field>
<field name="createButton">
<submit button-type="button" />
</field>
</form>
因此,处理问题的好方法是什么?
我发现简单的方法是将所有模式集中在一个文件中,这可能是所有验证器中都需要的,但我觉得它只是与组件体系结构相矛盾。
答案 0 :(得分:0)
最好的方法是建立一个中心点,将模式的公共部分保存在中心位置,并在需要时加载到所需的模式中。
答案 1 :(得分:0)
我终于决定通过使用依赖注入解决鸡和蛋的问题。 在上面的例子中,我会做类似
的事情//moduleBValidate.js
var moduleBSchema = new (require('moduleBSchema.js'))();
var moduleASchema = new (require('moduleASchema.js'))(moduleBSchema); // Here I use dependency injection for injecting moduleBSchema in moduleASchema
//moduleAValidate.js
var moduleASchema = new (require('moduleASchema.js'))();
var moduleBSchema = new (require('moduleBSchema.js'))(moduleASchema);
我用这种方式构建了joi架构:
function moduleASchema(moduleBSchema, moduleCSchema...) { // Here we put all dependencies of moduleASChema
moduleBSchema = moduleBSchema || Joi.object();
moduleCSchema = moduleCSchema || Joi.object();
...
this.schema = {
name: Joi.string().required(),
moduleBRef: Joi.alternatives().try(Joi.objectId(), moduleBSchema),
moduleCRef: Joi.alternatives().try(Joi.objectId(), moduleCSchema)
};
return this.schema;
}
module.exports = SiteSchema;