@dominion-framework/dominion
Version:
Declarative Promise based Node.js framework for REST API with zero dependencies.
90 lines (73 loc) • 3.17 kB
JavaScript
const Errors = require("./../errors");
const ModelFactoryPrototype = require("./modelFactoryPrototype");
const ModelPrototype = require("./modelPrototype");
const factoryCollection = new Map();
const Factories = function (factoryName) {
const factory = factoryCollection.get(factoryName.toLowerCase());
if(factory) {
return factory;
} else {
throw new Errors.Fatal(`Factory '${factoryName}' is not defined.`);
}
};
Factories.define = function (factoryDescription) {
let factoryName = factoryDescription.name.toLowerCase();
if (factoryName.trim() === "") {
throw new Errors.Fatal(`Factory name can not be empty.`);
}
if (factoryCollection.has(factoryName)) {
throw new Errors.Fatal(`Factory with name '${factoryName}' already defined.`);
} else {
factoryCollection.set(factoryName, createModelsFactory(factoryDescription));
}
return factoryCollection.get(factoryName);
};
let createModelsFactory = function (factoryDescription) {
let ModelFactory = class extends ModelFactoryPrototype {
constructor() {
super();
this.__cache__ = new Map();
this.__cacheDuration__ = 10 * 1000 /*ms */;
}
};
Object.assign(ModelFactory.prototype, factoryDescription.factory, {
repo: factoryDescription.repository
});
let ModelFactoryInstance = new ModelFactory();
let Model ={[factoryDescription.name]: class extends ModelPrototype {
constructor(props) {
super();
this.__properties__ = {};
props && this.populate(props);
}
} }[factoryDescription.name];
Object.assign(Model.prototype, factoryDescription.instance, {
repo: factoryDescription.repository,
scheme: factoryDescription.properties,
__name__: factoryDescription.name
});
Object.defineProperties(Model.prototype, Object.keys(factoryDescription.properties).reduce((propertyDefinition, propertyName) => {
if (Model.prototype.hasOwnProperty(propertyName)) {
throw new Errors.Fatal("Incorrect factory definition. Note, factory could not contain 'repo' and 'scheme' property names.");
}
propertyDefinition[propertyName] = {
set(value) {
value = this.scheme[propertyName]._inputModification(value);
this.scheme[propertyName]._validate(value, propertyName, factoryDescription.name);
Object.defineProperty(this.__properties__, propertyName, {
value: value,
writable: false,
configurable: true,
enumerable: !this.scheme[propertyName].isImmutable,
});
},
get() {
return this.__properties__[propertyName];
}
};
return propertyDefinition;
}, {}));
ModelFactoryInstance.__model__ = Model;
return ModelFactoryInstance;
};
module.exports = Factories;