2015-11-09 49 views
0

我正在使用HAPI和Joi創建一個API來驗證輸入,並且在不同模塊之間共享我的驗證模式時遇到麻煩。 我使用的是基於組件的架構,看起來像如何在沒有循環依賴的模型之間正確共享Hapi Joi驗證模式

components 
|_ moduleA 
    |_ moduleAController 
    |_ moduleAModel 
    |_ moduleARoute 
    |_ moduleAValidate 
|_ moduleB 
    |_ moduleBController 
    |_ moduleBModel 
    |_ moduleBRoute 
    |_ moduleBValidate 
|_ moduleC 
... 

在每個模塊中,moduleXRoute創建關聯從moduleXController處理程序,並從moduleXValidate一個驗證的路由。

由於我使用淳佳,我對輸入數據執行一些測試,但如問題來了,我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), 
}; 

這就是爲什麼我認爲這將是一個很好的想法,moduleAValidatemoduleBValidate暴露moduleASchemamoduleBSchema其他模塊可以使用。

的問題是,它使一個循環依賴問題,因爲在上述情況下,我會:

//moduleAValidate.js 
var moduleBSchema = require('../moduleBValidate').moduleBschema; 

//moduleBValidate.js 
var moduleASchema = require('../moduleAValidate').moduleAschema; 

因此,這將是處理這個問題的好辦法嗎?

我發現簡單的方法是將所有模式集中在單個文件中,這可能在所有驗證器中都需要,但是我覺得它會與組件體系結構相沖突。

回答

0

最好的方法是建立一箇中心點,將模式的公共部分保存在中心位置,並在需要時加載到所需的模式中。

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); 

我建的淳佳模式是這樣的:

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;