UNPKG

sails-factory-multitenant

Version:

Simple model factory for Sails.js 1.X with multitenancy features. Based on sails-factory and inspired on Factory-Girl.

234 lines (192 loc) 12.2 kB
const _ = require('@sailshq/lodash'); // ███╗ ███╗ ███████╗ █████╗ ██████╗████████╗ ██████╗ ██████╗ ██╗ ██╗ // ████╗ ████║ ██╔════╝██╔══██╗██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗╚██╗ ██╔╝ // ██╔████╔██║ █████╗ ███████║██║ ██║ ██║ ██║██████╔╝ ╚████╔╝ // ██║╚██╔╝██║ ██╔══╝ ██╔══██║██║ ██║ ██║ ██║██╔══██╗ ╚██╔╝ // ██║ ╚═╝ ██║██╗ ██║ ██║ ██║╚██████╗ ██║ ╚██████╔╝██║ ██║ ██║ // ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ class Factory { constructor(name, modelName, sFactory = null) { const modelId = _.camelCase(modelName).toLowerCase(); this.oParent = null; const attrs = {}; Object.defineProperties(this, { name: { value: name }, modelName: { value: modelName }, modelId: { value: modelId }, sFactory: { value: sFactory }, attrs: { value: attrs } }); } // ███████╗ █████╗ ████████╗████████╗██████╗ ██╗██████╗ ██╗ ██╗████████╗███████╗███████╗ // ██╔════╝ ██╔══██╗╚══██╔══╝╚══██╔══╝██╔══██╗██║██╔══██╗██║ ██║╚══██╔══╝██╔════╝██╔════╝ // ███████╗ ███████║ ██║ ██║ ██████╔╝██║██████╔╝██║ ██║ ██║ █████╗ ███████╗ // ╚════██║ ██╔══██║ ██║ ██║ ██╔══██╗██║██╔══██╗██║ ██║ ██║ ██╔══╝ ╚════██║ // ███████║██╗ ██║ ██║ ██║ ██║ ██║ ██║██║██████╔╝╚██████╔╝ ██║ ███████╗███████║ // ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚══════╝ attr(name, value, options) { if (options) { value = _.merge({}, options, { value: value }); } _.set(this.attrs, name, value); return this; } // ██████╗ ██╗ ██╗██╗██╗ ██████╗ // ██╔══██╗██║ ██║██║██║ ██╔══██╗ // ██████╔╝██║ ██║██║██║ ██║ ██║ // ██╔══██╗██║ ██║██║██║ ██║ ██║ // ██████╔╝╚██████╔╝██║███████╗██████╔╝ // ╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ build(attrs, callback) { const attrSet = this.processData(this.attrs); const _attrs = _.merge({}, attrSet, attrs); const promise = new Promise((resolve, reject) => { resolve(_attrs); }); _.isFunction(callback) && callback(_attrs); this.updateData(); return promise; } // ███████╗███████╗████████╗ ██████╗ █████╗ ██████╗ ███████╗███╗ ██╗████████╗ // ██╔════╝██╔════╝╚══██╔══╝ ██╔══██╗██╔══██╗██╔══██╗██╔════╝████╗ ██║╚══██╔══╝ // ███████╗█████╗ ██║ ██████╔╝███████║██████╔╝█████╗ ██╔██╗ ██║ ██║ // ╚════██║██╔══╝ ██║ ██╔═══╝ ██╔══██║██╔══██╗██╔══╝ ██║╚██╗██║ ██║ // ███████║███████╗ ██║ ██║ ██║ ██║██║ ██║███████╗██║ ╚████║ ██║ // ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ parent(factory) { if (this.sFactory) { const parent = this.sFactory.getFactory(factory); if (parent) { this.oParent = parent; } } else { throw new Error("No Sails Factory defined in constructor"); } } // ██████╗ █████╗ ████████╗ █████╗ ███╗ ███╗███████╗████████╗██╗ ██╗ ██████╗ // ██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗ ████╗ ████║██╔════╝╚══██╔══╝██║ ██║██╔═══██╗ // ██║ ██║███████║ ██║ ███████║ ██╔████╔██║█████╗ ██║ ███████║██║ ██║ // ██║ ██║██╔══██║ ██║ ██╔══██║ ██║╚██╔╝██║██╔══╝ ██║ ██╔══██║██║ ██║ // ██████╔╝██║ ██║ ██║ ██║ ██║ ██║ ╚═╝ ██║███████╗ ██║ ██║ ██║╚██████╔╝██╗ // ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ // // 1. processData // 2. updateData // 3. updateId processData(attrs) { if (this.oParent) { let idP = this.oParent.attrs.id; attrs = _.merge({}, this.oParent.attrs, attrs); attrs.id = idP; } let attributes = {}; _.each(attrs, (attr, key) => { if (typeof attr === 'object') { let value = attr.value; let counter = attr.counter || 0; let increment = (attr.auto_increment && typeof attr.auto_increment === 'boolean') ? 1 : attr.auto_increment; if (increment) { counter += increment; if (typeof value === 'string') { value = value.replace('%d', counter); if (attr.value === value) { value = value + counter; } } else if (typeof value === 'number'){ value += counter; } } attributes[key] = value; } else if (typeof attr === 'function') { attributes[key] = attr(); } else { attributes[key] = attr; } }); return attributes } updateData(query, oAttrs, parent) { let attributes = oAttrs || this.attrs; _.each(attributes, (attr, key) => { if (key === 'id' && typeof attributes[key] === 'object') { this.updateId(query, attributes, parent); return; } if (typeof attr === 'object' && this.attrs[key]) { let counter = attr.counter || 0; let increment = (attr.auto_increment && typeof attr.auto_increment === 'boolean') ? 1 : attr.auto_increment; if (increment) { counter += increment; this.attrs[key].counter = counter; } } }); if (this.oParent) { this.oParent.updateData(null, this.attrs, true); } } updateId(query, attributes, parent) { // Check id value exists if (!this.attrs.id) { this.attrs.id = { value: 0, counter: 0, auto_increment: 1 }; } let increment = (!parent) ? this.attrs.id.auto_increment : 0; if (increment && typeof increment === 'boolean') { increment = 1; } // Update id value this.attrs.id.value = (query && query.id) ? query.id : attributes.id.value + increment; } // ██████╗██████╗ ███████╗ █████╗ ████████╗███████╗ // ██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██╔════╝ // ██║ ██████╔╝█████╗ ███████║ ██║ █████╗ // ██║ ██╔══██╗██╔══╝ ██╔══██║ ██║ ██╔══╝ // ╚██████╗██║ ██║███████╗██║ ██║ ██║ ███████╗ // ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ async create(req, attrs, callback) { // Check Sails if (typeof sails === "undefined") { throw new Error("Sails is not available."); } const Model = (!this.oParent) ? _.get(sails.models, this.modelId) : _.get(sails.models, this.oParent.modelId); if (!Model) { throw new Error("Sails model '" + this.modelId + "' is undefined."); } const attrSet = this.processData(this.attrs); if (!this.attrs.id) { delete attrSet.id; } const _attrs = _.merge({}, attrSet, attrs); // ██████╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗ ███████╗██╗ ██╗███████╗ ██████╗ // ██╔═══██╗██║ ██║██╔════╝██╔══██╗╚██╗ ██╔╝ ██╔════╝╚██╗██╔╝██╔════╝██╔════╝ // ██║ ██║██║ ██║█████╗ ██████╔╝ ╚████╔╝ █████╗ ╚███╔╝ █████╗ ██║ // ██║▄▄ ██║██║ ██║██╔══╝ ██╔══██╗ ╚██╔╝ ██╔══╝ ██╔██╗ ██╔══╝ ██║ // ╚██████╔╝╚██████╔╝███████╗██║ ██║ ██║ ███████╗██╔╝ ██╗███████╗╚██████╗██╗ // ╚══▀▀═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ let query; if (req === null) { query = await Model.create(_attrs).fetch(); } else { query = await Model.create(req, _attrs).fetch(); } if (query) { this.updateData(query); } if (_.isFunction(callback)) { callback(query); } return query; } } module.exports = Factory;