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