@absolunet/ioc2.1.0

View on GitHub

database/services/ORM/drivers/Driver.js

//--------------------------------------------------------
//-- Node IoC - Database - Services - ORM - Drivers - Driver
//--------------------------------------------------------

import __                  from '@absolunet/private-registry';
import hasEngine           from '../../../../support/mixins/hasEngine';
import NotImplementedError from '../../../../foundation/exceptions/NotImplementedError';

/* istanbul ignore next */
/**
 * Abstract ORM driver.
 *
 * @abstract
 * @memberof database.services.ORM.drivers
 * @augments support.mixins.HasEngine
 * @hideconstructor
 */
class Driver extends hasEngine() {

	/**
	 * Class dependencies: <code>['app', 'connection', 'db.resolver', 'file', 'helper.string']</code>.
	 *
	 * @type {Array<string>}
	 */
	static get dependencies() {
		return (super.dependencies || []).concat(['app', 'connection', 'db.resolver', 'file', 'helper.string']);
	}

	/**
	 * @inheritdoc
	 * @private
	 */
	init() {
		this.setEngine(this.buildEngine(this.connection));
		const models = __(this.constructor).get('models') || {};
		__(this.constructor).set('models', models);
		Object.entries(models).forEach(([name, model]) => {
			this.model(name, model);
		});
	}

	/**
	 * Build an engine with given connection.
	 *
	 * @param {Knex} connection - The Knex connection instance.
	 * @returns {*} The ORM engine.
	 * @abstract
	 */
	buildEngine(connection) { // eslint-disable-line no-unused-vars
		throw new NotImplementedError(this, 'buildEngine', 'ORM engine');
	}

	/**
	 * Get ORM driver with given connection.
	 *
	 * @param {Knex} connection - The Knex connection instance.
	 * @returns {translation.services.Translator.drivers.Driver} The current driver instance.
	 */
	withConnection(connection) {
		return this.app.make(this.constructor, { connection });
	}

	/**
	 * Get and/or set model.
	 * If name and model are provided, the model is registered as name in the engine.
	 *
	 * @param {string} name - The model name.
	 * @param {database.Model} [Model] - The model class.
	 * @returns {database.Model} Model instance.
	 */
	model(name, Model) {
		if (!Model) {
			return this.getModel(name);
		}

		__(this.constructor).get('models')[name] = Model;

		const model = this.buildModel(Model);
		this.setModel(name, model);

		return model;
	}

	/**
	 * Get model by name.
	 *
	 * @param {string} name - The model name.
	 * @returns {database.Model|null} The model instance, or null if it was not found.
	 */
	getModel(name) {
		return this.engine.model(name);
	}

	/**
	 * Set model with given name.
	 *
	 * @param {string} name - The model name.
	 * @param {database.Model} model - The model instance.
	 */
	setModel(name, model) {
		this.engine.model(name, model);
	}

	/**
	 * Resolve model instance by name from the models path in the database resolver.
	 *
	 * @param {string} name - The model name.
	 * @returns {database.Model|null} A model instance.
	 */
	resolveModel(name) {
		const fullModelPath = this.app.formatPath(this.dbResolver.resolvePath('models'), `${this.getFormattedModelClassName(name)}.js`);

		return this.file.exists(fullModelPath) ? this.buildModel(this.file.load(fullModelPath)) : null;
	}

	/**
	 * Build model.
	 *
	 * @param {database.Model} model - The model instance.
	 * @returns {database.Model} The built model instance.
	 */
	buildModel(model) {
		return model;
	}

	/**
	 * Get formatted model class name.
	 *
	 * @param {string} name - The model name.
	 * @returns {string} The formatted model name.
	 */
	getFormattedModelClassName(name) {
		return this.stringHelper.pascal(name);
	}

	/**
	 * String helper instance.
	 *
	 * @type {support.helpers.StringHelper}
	 */
	get stringHelper() {
		return this.helperString;
	}

}


export default Driver;