Как правильно делиться схемами валидации Hapi Joi между моделями без циклической зависимости

Я создаю API с использованием HAPI и Joi для проверки входных данных, и у меня возникают проблемы с совместным использованием моей схемы проверки между различными модулями. Я использую компонентно-ориентированную архитектуру, которая выглядит так

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;

Итак, как лучше всего справиться с проблемой?

Я обнаружил, что самым простым способом было бы централизовать все схемы в одном файле, который может потребоваться во всех валидаторах, но я чувствую, что это будет противоречить архитектуре компонентов.


person ChrisV    schedule 09.11.2015    source источник


Ответы (2)


Лучшим способом было бы иметь центральную точку, где общие части схем хранятся в центральном месте и загружаются в требуемые схемы при необходимости.

person simon-p-r    schedule 09.11.2015

В конце концов я решил решить проблему курицы и яйца с помощью инъекции зависимостей. В приведенном выше примере я бы сделал что-то вроде

//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;
person ChrisV    schedule 16.11.2015