UNPKG

sutando

Version:

A modern Node.js ORM. Makes it enjoyable to interact with your database. Support Mysql, MSSql, MariaDB, Sqlite.

171 lines (136 loc) 5.39 kB
const unset = require('lodash/unset'); const snakeCase = require('lodash/snakeCase'); const { getRelationName, getRelationMethod } = require('../../utils'); const { RelationNotFoundError } = require('../../errors'); const HasRelations = (Model) => { return class extends Model { relations = {}; getRelation(relation) { return this.relations[relation]; } setRelation(relation, value) { this.relations[relation] = value; return this; } unsetRelation(relation) { unset(this.relations, relation); return this; } relationLoaded(relation) { return this.relations[relation] !== undefined; } related(relation) { if (typeof this[getRelationMethod(relation)] !== 'function') { const message = `Model [${this.constructor.name}]'s relation [${relation}] doesn't exist.`; throw new RelationNotFoundError(message); } return this[getRelationMethod(relation)](); } async getRelated(relation) { return await this.related(relation).getResults(); } relationsToData() { const data = {}; for (const key in this.relations) { if (this.hidden.includes(key)) { continue; } if (this.visible.length > 0 && this.visible.includes(key) === false) { continue; } data[key] = this.relations[key] instanceof Array ? this.relations[key].map(item => item.toData()) : this.relations[key] === null ? null : this.relations[key].toData(); } return data; } guessBelongsToRelation() { let e = new Error(); let frame = e.stack.split("\n")[2]; // let lineNumber = frame.split(":").reverse()[1]; let functionName = frame.split(" ")[5]; return getRelationName(functionName); } joiningTable(related, instance = null) { const segments = [ instance ? instance.joiningTableSegment() : snakeCase(related.name), this.joiningTableSegment(), ]; return segments.sort().join('_').toLocaleLowerCase(); } joiningTableSegment() { return snakeCase(this.constructor.name); } hasOne(related, foreignKey = null, localKey = null) { const instance = new related; foreignKey = foreignKey || this.getForeignKey(); localKey = localKey || this.getKeyName(); return (new HasOne(related, this, instance.getTable() + '.' + foreignKey, localKey)); } hasMany(related, foreignKey = null, localKey = null) { const instance = new related; foreignKey = foreignKey || this.getForeignKey(); localKey = localKey || this.getKeyName(); return (new HasMany(related, this, instance.getTable() + '.' + foreignKey, localKey)); } belongsTo(related, foreignKey = null, ownerKey = null, relation = null) { const instance = new related; foreignKey = foreignKey || instance.getForeignKey(); ownerKey = ownerKey || instance.getKeyName(); relation = relation || this.guessBelongsToRelation(); return (new BelongsTo(related, this, foreignKey, ownerKey, relation)); } belongsToMany(related, table = null, foreignPivotKey = null, relatedPivotKey = null, parentKey = null, relatedKey = null) { const instance = new related; table = table || this.joiningTable(related, instance); foreignPivotKey = foreignPivotKey || this.getForeignKey(); relatedPivotKey = relatedPivotKey || instance.getForeignKey(); parentKey = parentKey || this.getKeyName(); relatedKey = relatedKey || instance.getKeyName(); return (new BelongsToMany( query, this, table, foreignPivotKey, relatedPivotKey, parentKey, relatedKey )); } hasOneThrough(related, through, firstKey = null, secondKey = null, localKey = null, secondLocalKey = null) { through = new through; const query = related.query(); firstKey = firstKey || this.getForeignKey(); secondKey = secondKey || through.getForeignKey(); return (new HasOneThrough( query, this, through, firstKey, secondKey, localKey || this.getKeyName(), secondLocalKey || through.getKeyName() )); } hasManyThrough(related, through, firstKey = null, secondKey = null, localKey = null, secondLocalKey = null) { through = new through; const query = related.query(); firstKey = firstKey || this.getForeignKey(); secondKey = secondKey || through.getForeignKey(); return (new HasManyThrough( query, this, through, firstKey, secondKey, localKey || this.getKeyName(), secondLocalKey || through.getKeyName() )); } } } module.exports = HasRelations; const HasOne = require('../relations/has-one'); const HasMany = require('../relations/has-many'); const BelongsTo = require('../relations/belongs-to'); const BelongsToMany = require('../relations/belongs-to-many'); const HasOneThrough = require('../relations/has-one-through'); const HasManyThrough = require('../relations/has-many-through');