UNPKG

rn-async-database

Version:

A simple database base on react-native AsyncStorage.

144 lines (136 loc) 7.97 kB
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Filter = function () { function Filter() { _classCallCheck(this, Filter); this.comparisonOperators = ['gt', 'gte', 'lt', 'lte', 'between', 'inq', 'nin', 'regexp']; this.logicalOperators = ['and', 'or']; } _createClass(Filter, [{ key: 'apply', value: function apply(set, settings) { var where = settings.where || null; var fields = settings.fields || {}; var order = settings.order || {}; var offset = settings.offset || 0; var limit = settings.limit; var result = []; //Elements that satisfy where filter if (where != null) { for (var i in set) { var element = set[i]; //Empty filter includes everything if (this.evaluate(where, element)) result.push(this.applyFieldsFilter(element, fields)); } } else { //result needs to be in an array, set can be an object //so you cant just result = set for (var i in set) { var element = set[i]; result.push(this.applyFieldsFilter(element, fields)); } } //Found a lot of conflicting info on whether Array.sort() is stable, //but in testing so far it seems to be. //Reverse the arrays of keys to get the desired weight var orderKeys = Object.keys(order).reverse(); for (var key in orderKeys) { //If for some reason the value of the order is not ASC or DESC, //sort by ASC var greater = order[orderKeys[key]] === 'DESC' ? -1 : 1; var lesser = greater * -1; var keySort = function keySort(a, b) { if (a[orderKeys[key]] < b[orderKeys[key]]) return lesser; if (a[orderKeys[key]] > b[orderKeys[key]]) return greater; if (a[orderKeys[key]] == b[orderKeys[key]]) return 0; }; result.sort(keySort); } //Apply limit and offset filters through results.slice(offset, offset + limit) if (typeof limit === 'number' && limit > 0) return result.slice(offset, offset + limit);else if (offset !== 0) return result.slice(offset); return result; } }, { key: 'evaluate', value: function evaluate(filter, element) { var filterKeys = Object.keys(filter); if ((typeof filter === 'undefined' ? 'undefined' : _typeof(filter)) == 'object') { for (var i in filterKeys) { var key = filterKeys[i]; //key is either a property name, or logical operator if (this.logicalOperators.indexOf(key) > -1) { if (!this.evaluateLogicalOperator(key, filter[key], element)) return false; } else if (this.comparisonOperators.indexOf(key) > -1) { if (!this.evaluateComparisonOperator(key, filter[key], element)) return false; } else if (_typeof(filter[key]) == 'object') { if (!this.evaluate(filter[key], element[key])) return false; } else if (filter[key] != element[key]) return false; } return true; } //It technically should never reach here, but just to be safe return a == b; } }, { key: 'evaluateLogicalOperator', value: function evaluateLogicalOperator(operator, filter, element) { if (operator == 'and') { for (var i in filter) { var comp = filter[i]; if (!this.evaluate(comp, element)) return false; } return true; } else if (operator == 'or') { for (var i in filter) { var comp = filter[i]; if (this.evaluate(comp, element)) return true; } } return false; } }, { key: 'evaluateComparisonOperator', value: function evaluateComparisonOperator(operator, filter, element) { if (operator == 'neq') return element != filter;else if (operator == 'gt') return element > filter;else if (operator == 'gte') return element >= filter;else if (operator == 'lt') return element < filter;else if (operator == 'lte') return element <= filter;else if (operator == 'between' && filter[0] != null && filter[1] != null) return element >= filter[0] && element <= filter[1];else if (operator == 'inq') return filter.indexOf(element) > -1 ? true : false;else if (operator == 'nin') return filter.indexOf(element) > -1 ? false : true;else if (operator == 'regexp') { var regexper = (typeof filter === 'undefined' ? 'undefined' : _typeof(filter)) == 'object' ? filter : new RegExp(filter, 'i'); return regexper.exec(element) == null ? false : true; } return false; } }, { key: 'applyFieldsFilter', value: function applyFieldsFilter(element, fields) { //Fields filter will exclude all keys from the element for which there //is a corresponding key in the fields object with a value of false. //However, if one key in the fields filter has a value of true, all //keys in element that do not have a corresponding key with a value of //true will be excluded. //If strict = false, the former behavior occurs, if strict = true, the //latter behavior occurs var strict = false; var result = {}; var fieldKeys = Object.keys(fields); var elementKeys = Object.keys(element); for (var key in fieldKeys) { if (fields[fieldKeys[key]] === true) strict = true; } //NOTE: This is only for react-native-storage, which needs a _id key //to function correctly. If we are on strict mode, we must add in the //_id key, if we are not, we much make sure that there is no false //value for it if (strict) fields._id = true;else delete fields._id; for (var key in elementKeys) { //Applying the above described behavior. Add the property if //we are being strict and the filter contains the key, or if //we are not being strict and our filter does not want to remove //the property. if (strict && fields[elementKeys[key]] === true || !strict && !(fields[elementKeys[key]] === false)) result[elementKeys[key]] = element[elementKeys[key]]; } return result; } }]); return Filter; }(); module.exports = Filter;