UNPKG

igo

Version:

Igo is a Node.js Web Framework based on Express

272 lines (212 loc) 6.31 kB
const _ = require('lodash'); const CachedQuery = require('./CachedQuery'); const Query = require('./Query'); const PaginatedOptimizedQuery = require('./PaginatedOptimizedQuery'); const Schema = require('./Schema'); const { error } = require('../connect/errorhandler'); const newQuery = (constructor, verb) => { if (constructor.schema.cache) { return new CachedQuery(constructor, verb); } return new Query(constructor, verb); }; // Simple mixin implementation to set the schema as a static attribute module.exports = function(schema) { class Model { constructor(values) { _.assign(this, values); } // assignValues(values) { const keys = _.keys(Model.schema.colsByAttr); _.assign(this, _.pick(values, keys)); } // returns object with primary keys primaryObject() { return _.pick(this, this.constructor.schema.primary); } // update async update(values) { values.updated_at = new Date(); await this.beforeUpdate(values); await newQuery(this.constructor, 'update') .unscoped() .values(values) .where(this.primaryObject()) .execute(); if (this.constructor.schema.cache) { const cache = require('../cache'); await cache.del('_cached.' + this.constructor.schema.table); } this.assignValues(values); return this; } // reload async reload(includes) { const query = this.constructor.unscoped(); includes && query.includes(includes); return await query.find(this.id); } // delete delete() { return newQuery(this.constructor, 'delete').unscoped().where(this.primaryObject()).execute(); } // destroy destroy() { console.log('* Model.destroy() deprecated. Please use Model.delete() instead'); return this.delete(); } async beforeCreate() { } async beforeUpdate(values) { } // find by id static async find(id) { return await newQuery(this).find(id); } // create static async create(values, options) { const _this = this; const now = new Date(); const obj = new this(values); if (this.schema.subclasses && !obj[this.schema.subclass_column]) { obj[this.schema.subclass_column] = _.findKey(this.schema.subclasses, { name: this.name }); } obj.created_at = obj.created_at || now; obj.updated_at = obj.updated_at || now; const create = async () => { await obj.beforeCreate(); const query = newQuery(_this, 'insert').values(obj).options(options); const result = await query.execute(); if (result.err) { throw result.err; } const { insertId } = result; if (insertId) { return _this.unscoped().find(insertId); } return _this.unscoped().find(obj.primaryObject()); }; return await create(); } // return first static first() { return newQuery(this).first(); } // return last static last() { return newQuery(this).last(); } // return list static list() { return newQuery(this).list(); } /** * @deprecated Please use Model.list() instead */ static all() { return this.list(); } // static select(select) { return newQuery(this).select(select); } // filter static where(where, params) { return newQuery(this).where(where, params); } // filter static whereNot(whereNot) { return newQuery(this).whereNot(whereNot); } // limit static limit(limit) { return newQuery(this).limit(limit); } // offset static offset(offset) { return newQuery(this).offset(offset); } // page static page(page, nb) { return newQuery(this).page(page, nb); } // order static order(order) { return newQuery(this).order(order); } // distinct static distinct(columns) { return newQuery(this).distinct(columns); } // group static group(columns) { return newQuery(this).group(columns); } // count static count() { return newQuery(this).count(); } // join static join(association, columns, type, name) { return newQuery(this).join(association, columns, type, name); } // delete static delete(id, ) { return newQuery(this, 'delete').unscoped().where({ id: id }).execute(); } // destroy static destroy(id, ) { console.log('* Model.destroy() deprecated. Please use Model.delete() instead'); return this.delete(id); } // delete all static async deleteAll() { return newQuery(this, 'delete').unscoped().execute(); } // destroy all static destroyAll() { return this.deleteAll(); } // static update(values, ) { values.updated_at = new Date(); return newQuery(this).unscoped().update(values, ); } // includes static includes(includes) { return newQuery(this).includes(includes); } // includes static join(associationName, columns, type='LEFT') { const query = newQuery(this); if (_.isString(associationName)) { return query.joinOne(associationName, columns, type); } else if (_.isArray(associationName)) { return query.joinMany(associationName, columns, type); } else if (_.isObject(associationName)) { return query.joinNested(associationName); } throw new Error('Invalid join argument for Model.join(). Must be a string, array, or object.'); } //unscoped static unscoped() { return newQuery(this).unscoped(); } //scope static scope(scope) { return newQuery(this).scope(scope); } /** * @deprecated Le pattern optimisé COUNT/IDS/FULL s'active automatiquement * quand .page() et .join() sont utilisés ensemble. Utilisez simplement : * * Model.where({ ... }).join('assoc').page(1, 50).list() * * @returns {PaginatedOptimizedQuery} */ static paginatedOptimized() { return new PaginatedOptimizedQuery(this); } } Model.schema = new Schema(schema); return Model; };