"use strict";
const ModelFactory = require("./ModelFactory");
let instance;
/**
* Holds all Mappings and converts them to Bookshelf Models
*/
class DBMappingRegistry {
constructor(ModelFactory) {
this.mappings = {};
this.compiled = {};
this.ModelFactory = ModelFactory;
}
static getInstance() {
if (!instance) {
instance = new DBMappingRegistry(ModelFactory);
}
return instance;
}
/**
* Register a Mapping
* @param {string} name - Name of the mapping
* @param {string} dbContextName - DB context / connection name
* @param {BookshelfMapping} mapping - Mapping description of columns, relations etc.
*/
register(name, dbContextName, mapping) {
if (this.isRegistered(name)) {
throw new Error(`A mapping with name '${name}' is already registered`);
}
this.mappings[name] = {
dbContextName: dbContextName,
mapping: mapping
};
}
get(name) {
return this.mappings[name].mapping;
}
isRegistered(name) {
return name in this.mappings;
}
/**
* Compile a BookshelfMapping for use with an EntityRepository
* @param {string} name - Name of a registered Mapping
* @returns {EntityRepository} compiled Mapping, ready to use
*/
compile(name) {
if (!this.isCached(name)) {
this.compileAndCache(name);
}
return this.compiled[name];
}
compileAndCache(name) {
if (!this.isRegistered(name)) {
throw new Error(name + " is not a registered mapping");
}
const factory = this.ModelFactory.context[this.mappings[name].dbContextName];
const mapping = Object.create(this.get(name));
if (mapping.relations) {
mapping.relations.forEach((relation) => {
const getCompiled = this.compile.bind(this, relation.references.mapping);
Object.defineProperty(relation.references, "mapping", {
get() {
return getCompiled();
}
});
});
}
this.compiled[name] = factory.createModel(mapping);
}
isCached(name) {
return name in this.compiled;
}
}
module.exports = DBMappingRegistry;