gerard2p/koaton

View on GitHub
src/middleware/orm.js

Summary

Maintainability
B
5 hrs
Test Coverage
import * as fs from 'fs';
import * as path from 'upath';
import { sync as glob } from 'glob';
import * as caminte from 'caminte';
import { line2 } from '../support/consoleLines';
import inflector from '../support/inflector';
import exendModel from '../support/extend_caminte';
import debug from '../support/debug';
 
TODO found
// TODO: Create your own ORM, caminte worked but is not enough, remember LORM?
/** @ignore */
const connection = configuration.connections[configuration.server.database.connection],
exp = { databases: {} };
/** @ignore */
let schema = new caminte.Schema(connection.driver, connection),
relations = {};
 
schema.Integer = schema.Number;
schema.Email = schema.Text;
schema.Password = schema.Text;
 
/**
* This middleware decodes the query param filterset which is expected in a jsurl format
* and appends jsurl to ctx.state
* @param {KoaContext} ctx
* @param {KoaNext} next
* @param {JSURL} ctx.state.db - reference attached.
* @param {JSURL} ctx.db - old reference attached this is now DEPRECATED.
*/
export async function ormMiddleware (ctx, next) {
ctx.db = exp.databases;
ctx.state.db = exp.databases;
await next();
}
/** @ignore */
function relation (mode, dest) {
let [parent, key] = dest.split('.');
relations[this].push({
Children: parent,
key: key,
Rel: mode,
As: ''
});
return relations[this].length - 1;
}
/**
* This function extends the CaminteJS relations, adding Many to Many support
*/
Function `makerelation` has 29 lines of code (exceeds 25 allowed). Consider refactoring.
function makerelation (model, relation) {
let options = {
as: relation.As,
foreignKey: relation.key
};
let target = exp.databases[inflector.pluralize(relation.Children)];
if (relation.Rel !== 'manyToMany') {
exp.databases[model][relation.Rel](target, options);
} else {
exp.databases[model].prototype.many2many = exp.databases[model].prototype.many2many || {};
exp.databases[model].prototype.many2many[relation.Parent] = function (id, id2) {
if (id && id2) {
return exp.databases[relation.Children].findcre({
[`${model}ID`]: id,
[`${relation.Parent}ID`]: id2
});
}
return exp.databases[relation.Children].find({
where: {
[`${model}ID`]: id
}
}).then(records => {
let all = [];
for (const record of records) {
all.push(exp.databases[relation.Parent].findById(record[`${relation.Parent}ID`]));
}
return Promise.all(all);
});
};
}
}
/**
* Make avaliable all the model definitions for various propurses
* @private
*/
export let models = exp.databases;
/**
* This function allow to insert models to the database definition only during
* system setup should not be use while returning a requeset and only used during
* setup
* @param {string} modelName The name of the new model
* @param {KoatonModelv1} definition a version 1 model (based on CaminteJS)
*/
Function `addModel` has 53 lines of code (exceeds 25 allowed). Consider refactoring.
export function addModel (modelName, definition) {
relations[modelName] = [];
const rel = {
belongsTo: relation.bind(modelName, 'belongsTo'),
hasMany: relation.bind(modelName, 'hasMany'),
Function `manyToMany` has 33 lines of code (exceeds 25 allowed). Consider refactoring.
manyToMany (configuration) {
let targetModel = inflector.pluralize(configuration.targetModel);
let intermediateTable = `${modelName}_${targetModel}`;
let key1 = `${modelName}ID`;
let key2 = `${targetModel}ID`;
let Model = {
[key1]: {
type: schema.String
},
[key2]: {
type: schema.String
}
};
let Extra = {
indexes: {
idx_1: {
columns: `${key1}, ${key2}`
}
}
};
let MODEL = schema.define(intermediateTable, Model, Extra);
MODEL.rawAPI = {};
exp.databases[intermediateTable] = exendModel(MODEL);
relations[modelName].push({
Children: intermediateTable,
Rel: 'manyToMany',
Parent: targetModel
});
relations[targetModel] = relations[targetModel] || /* istanbul ignore next */[];
relations[targetModel].push({
Parent: modelName,
Rel: 'manyToMany',
Children: intermediateTable
});
return relations[modelName].length - 1;
}
};
definition = definition(schema, rel);
for (let prop in definition.relations) {
relations[modelName][definition.relations[prop]].As = prop;
}
definition.model.created = {
type: schema.Date
};
definition.model.updated = {
type: schema.Date
};
let model = schema.define(modelName, definition.model, Object.assign({}, definition.extra));
model.rawAPI = {};
exp.databases[modelName] = exendModel(model);
}
/**
* Initialize the database registering all te model to the CaminteJS ORM
* and seeds all the models
* @param {boolean} [seed=false] if true reads the files in seed to populate database on start
* @return {boolean} Tells if the seed process was correctly executed
*/
Function `initializeORM` has 33 lines of code (exceeds 25 allowed). Consider refactoring.
export function initializeORM (seed) {
let res = null;
/* istanbul ignore next */
schema.on('error', (err) => {
debug(err.stack);
});
const models = glob('koaton_modules/**/models/*.js').concat(glob('models/*.js'));
for (const model of models) {
let file = path.basename(model).replace('.js', '');
addModel(
inflector.pluralize(file),
require(ProyPath(model)).default
);
}
for (let model in relations) {
relations[model].forEach(makerelation.bind(null, model));
}
/* istanbul ignore else */
if (process.env.NODE_ENV === 'development') {
res = (async function () {
let files = fs.readdirSync(ProyPath('seeds'));
for (let index in files) {
let file = files[index].replace('.js', '');
try {
debug(`Sedding ${file}`);
let model = exp.databases[inflector.pluralize(file.toLowerCase())];
await require(ProyPath('seeds', file)).default(model.findcre);
} catch (err) /* istanbul ignore next */ {
debug(err);
}
}
/* istanbul ignore next */
if (files.length === 0) {
debug('Nothing to seed');
}
line2(true);
})();
}
/* istanbul ignore if */
return res;
}