UNPKG

forerunnerdb

Version:

A NoSQL document store database for browsers and Node.js.

415 lines (346 loc) 9.98 kB
"use strict"; var Overload = require('./Overload'); var Triggers = { /** * Add a trigger by id. * @param {String} id The id of the trigger. This must be unique to the type and * phase of the trigger. Only one trigger may be added with this id per type and * phase. * @param {Number} type The type of operation to apply the trigger to. See * Mixin.Constants for constants to use. * @param {Number} phase The phase of an operation to fire the trigger on. See * Mixin.Constants for constants to use. * @param {Function} method The method to call when the trigger is fired. * @returns {boolean} True if the trigger was added successfully, false if not. */ addTrigger: function (id, type, phase, method) { var self = this, triggerIndex; // Check if the trigger already exists triggerIndex = self._triggerIndexOf(id, type, phase); if (triggerIndex === -1) { // The trigger does not exist, create it self._trigger = self._trigger || {}; self._trigger[type] = self._trigger[type] || {}; self._trigger[type][phase] = self._trigger[type][phase] || []; self._trigger[type][phase].push({ id: id, method: method, enabled: true }); return true; } return false; }, /** * * @param {String} id The id of the trigger to remove. * @param {Number} type The type of operation to remove the trigger from. See * Mixin.Constants for constants to use. * @param {Number} phase The phase of the operation to remove the trigger from. * See Mixin.Constants for constants to use. * @returns {boolean} True if removed successfully, false if not. */ removeTrigger: function (id, type, phase) { var self = this, triggerIndex; // Check if the trigger already exists triggerIndex = self._triggerIndexOf(id, type, phase); if (triggerIndex > -1) { // The trigger exists, remove it self._trigger[type][phase].splice(triggerIndex, 1); } return false; }, enableTrigger: new Overload({ 'string': function (id) { // Alter all triggers of this type var self = this, types = self._trigger, phases, triggers, result = false, i, k, j; if (types) { for (j in types) { if (types.hasOwnProperty(j)) { phases = types[j]; if (phases) { for (i in phases) { if (phases.hasOwnProperty(i)) { triggers = phases[i]; // Loop triggers and set enabled flag for (k = 0; k < triggers.length; k++) { if (triggers[k].id === id) { triggers[k].enabled = true; result = true; } } } } } } } } return result; }, 'number': function (type) { // Alter all triggers of this type var self = this, phases = self._trigger[type], triggers, result = false, i, k; if (phases) { for (i in phases) { if (phases.hasOwnProperty(i)) { triggers = phases[i]; // Loop triggers and set to enabled for (k = 0; k < triggers.length; k++) { triggers[k].enabled = true; result = true; } } } } return result; }, 'number, number': function (type, phase) { // Alter all triggers of this type and phase var self = this, phases = self._trigger[type], triggers, result = false, k; if (phases) { triggers = phases[phase]; if (triggers) { // Loop triggers and set to enabled for (k = 0; k < triggers.length; k++) { triggers[k].enabled = true; result = true; } } } return result; }, 'string, number, number': function (id, type, phase) { // Check if the trigger already exists var self = this, triggerIndex = self._triggerIndexOf(id, type, phase); if (triggerIndex > -1) { // Update the trigger self._trigger[type][phase][triggerIndex].enabled = true; return true; } return false; } }), disableTrigger: new Overload({ 'string': function (id) { // Alter all triggers of this type var self = this, types = self._trigger, phases, triggers, result = false, i, k, j; if (types) { for (j in types) { if (types.hasOwnProperty(j)) { phases = types[j]; if (phases) { for (i in phases) { if (phases.hasOwnProperty(i)) { triggers = phases[i]; // Loop triggers and set enabled flag for (k = 0; k < triggers.length; k++) { if (triggers[k].id === id) { triggers[k].enabled = false; result = true; } } } } } } } } return result; }, 'number': function (type) { // Alter all triggers of this type var self = this, phases = self._trigger[type], triggers, result = false, i, k; if (phases) { for (i in phases) { if (phases.hasOwnProperty(i)) { triggers = phases[i]; // Loop triggers and set to disabled for (k = 0; k < triggers.length; k++) { triggers[k].enabled = false; result = true; } } } } return result; }, 'number, number': function (type, phase) { // Alter all triggers of this type and phase var self = this, phases = self._trigger[type], triggers, result = false, k; if (phases) { triggers = phases[phase]; if (triggers) { // Loop triggers and set to disabled for (k = 0; k < triggers.length; k++) { triggers[k].enabled = false; result = true; } } } return result; }, 'string, number, number': function (id, type, phase) { // Check if the trigger already exists var self = this, triggerIndex = self._triggerIndexOf(id, type, phase); if (triggerIndex > -1) { // Update the trigger self._trigger[type][phase][triggerIndex].enabled = false; return true; } return false; } }), /** * Checks if a trigger will fire based on the type and phase provided. * @param {Number} type The type of operation. See Mixin.Constants for * constants to use. * @param {Number} phase The phase of the operation. See Mixin.Constants * for constants to use. * @returns {Boolean} True if the trigger will fire, false otherwise. */ willTrigger: function (type, phase) { if (this._trigger && this._trigger[type] && this._trigger[type][phase] && this._trigger[type][phase].length) { // Check if a trigger in this array is enabled var arr = this._trigger[type][phase], i; for (i = 0; i < arr.length; i++) { if (arr[i].enabled) { return true; } } } return false; }, /** * Processes trigger actions based on the operation, type and phase. * @param {Object} operation Operation data to pass to the trigger. * @param {Number} type The type of operation. See Mixin.Constants for * constants to use. * @param {Number} phase The phase of the operation. See Mixin.Constants * for constants to use. * @param {Object} oldDoc The document snapshot before operations are * carried out against the data. * @param {Object} newDoc The document snapshot after operations are * carried out against the data. * @returns {boolean} */ processTrigger: function (operation, type, phase, oldDoc, newDoc) { var self = this, triggerArr, triggerIndex, triggerCount, triggerItem, response; if (self._trigger && self._trigger[type] && self._trigger[type][phase]) { triggerArr = self._trigger[type][phase]; triggerCount = triggerArr.length; for (triggerIndex = 0; triggerIndex < triggerCount; triggerIndex++) { triggerItem = triggerArr[triggerIndex]; // Check if the trigger is enabled if (triggerItem.enabled) { if (this.debug()) { var typeName, phaseName; switch (type) { case this.TYPE_INSERT: typeName = 'insert'; break; case this.TYPE_UPDATE: typeName = 'update'; break; case this.TYPE_REMOVE: typeName = 'remove'; break; default: typeName = ''; break; } switch (phase) { case this.PHASE_BEFORE: phaseName = 'before'; break; case this.PHASE_AFTER: phaseName = 'after'; break; default: phaseName = ''; break; } //console.log('Triggers: Processing trigger "' + id + '" for ' + typeName + ' in phase "' + phaseName + '"'); } // Run the trigger's method and store the response response = triggerItem.method.call(self, operation, oldDoc, newDoc); // Check the response for a non-expected result (anything other than // undefined, true or false is considered a throwable error) if (response === false) { // The trigger wants us to cancel operations return false; } if (response !== undefined && response !== true && response !== false) { // Trigger responded with error, throw the error throw('ForerunnerDB.Mixin.Triggers: Trigger error: ' + response); } } } // Triggers all ran without issue, return a success (true) return true; } }, /** * Returns the index of a trigger by id based on type and phase. * @param {String} id The id of the trigger to find the index of. * @param {Number} type The type of operation. See Mixin.Constants for * constants to use. * @param {Number} phase The phase of the operation. See Mixin.Constants * for constants to use. * @returns {number} * @private */ _triggerIndexOf: function (id, type, phase) { var self = this, triggerArr, triggerCount, triggerIndex; if (self._trigger && self._trigger[type] && self._trigger[type][phase]) { triggerArr = self._trigger[type][phase]; triggerCount = triggerArr.length; for (triggerIndex = 0; triggerIndex < triggerCount; triggerIndex++) { if (triggerArr[triggerIndex].id === id) { return triggerIndex; } } } return -1; } }; module.exports = Triggers;