UNPKG

test-rxdb

Version:

A local realtime NoSQL Database for JavaScript applications -

488 lines (465 loc) 14.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.OTHER_MANGO_OPERATORS = exports.OTHER_MANGO_ATTRIBUTES = exports.NoSqlQueryBuilderClass = void 0; exports.canMerge = canMerge; exports.createQueryBuilder = createQueryBuilder; exports.mQuerySortToRxDBSort = mQuerySortToRxDBSort; var _readOnlyError2 = _interopRequireDefault(require("@babel/runtime/helpers/readOnlyError")); var _mqueryUtils = require("./mquery-utils.js"); var _rxError = require("../../../rx-error.js"); /** * this is based on * @link https://github.com/aheckmann/mquery/blob/master/lib/mquery.js */ var NoSqlQueryBuilderClass = exports.NoSqlQueryBuilderClass = /*#__PURE__*/function () { /** * MQuery constructor used for building queries. * * ####Example: * var query = new MQuery({ name: 'mquery' }); * query.where('age').gte(21).exec(callback); * */ function NoSqlQueryBuilderClass(mangoQuery, _path) { this.options = {}; this._conditions = {}; this._fields = {}; this._path = _path; if (mangoQuery) { var queryBuilder = this; if (mangoQuery.selector) { queryBuilder.find(mangoQuery.selector); } if (mangoQuery.limit) { queryBuilder.limit(mangoQuery.limit); } if (mangoQuery.skip) { queryBuilder.skip(mangoQuery.skip); } if (mangoQuery.sort) { mangoQuery.sort.forEach(s => queryBuilder.sort(s)); } } } /** * Specifies a `path` for use with chaining. */ var _proto = NoSqlQueryBuilderClass.prototype; _proto.where = function where(_path, _val) { if (!arguments.length) return this; var type = typeof arguments[0]; if ('string' === type) { this._path = arguments[0]; if (2 === arguments.length) { this._conditions[this._path] = arguments[1]; } return this; } if ('object' === type && !Array.isArray(arguments[0])) { return this.merge(arguments[0]); } throw (0, _rxError.newRxTypeError)('MQ1', { path: arguments[0] }); } /** * Specifies the complementary comparison value for paths specified with `where()` * ####Example * User.where('age').equals(49); */; _proto.equals = function equals(val) { this._ensurePath('equals'); var path = this._path; this._conditions[path] = val; return this; } /** * Specifies the complementary comparison value for paths specified with `where()` * This is alias of `equals` */; _proto.eq = function eq(val) { this._ensurePath('eq'); var path = this._path; this._conditions[path] = val; return this; } /** * Specifies arguments for an `$or` condition. * ####Example * query.or([{ color: 'red' }, { status: 'emergency' }]) */; _proto.or = function or(array) { var or = this._conditions.$or || (this._conditions.$or = []); if (!Array.isArray(array)) array = [array]; or.push.apply(or, array); return this; } /** * Specifies arguments for a `$nor` condition. * ####Example * query.nor([{ color: 'green' }, { status: 'ok' }]) */; _proto.nor = function nor(array) { var nor = this._conditions.$nor || (this._conditions.$nor = []); if (!Array.isArray(array)) array = [array]; nor.push.apply(nor, array); return this; } /** * Specifies arguments for a `$and` condition. * ####Example * query.and([{ color: 'green' }, { status: 'ok' }]) * @see $and http://docs.mongodb.org/manual/reference/operator/and/ */; _proto.and = function and(array) { var and = this._conditions.$and || (this._conditions.$and = []); if (!Array.isArray(array)) array = [array]; and.push.apply(and, array); return this; } /** * Specifies a `$mod` condition */; _proto.mod = function mod(_path, _val) { var val; var path; if (1 === arguments.length) { this._ensurePath('mod'); val = arguments[0]; path = this._path; } else if (2 === arguments.length && !Array.isArray(arguments[1])) { this._ensurePath('mod'); val = arguments.slice(); path = this._path; } else if (3 === arguments.length) { val = arguments.slice(1); path = arguments[0]; } else { val = arguments[1]; path = arguments[0]; } var conds = this._conditions[path] || (this._conditions[path] = {}); conds.$mod = val; return this; } /** * Specifies an `$exists` condition * ####Example * // { name: { $exists: true }} * Thing.where('name').exists() * Thing.where('name').exists(true) * Thing.find().exists('name') */; _proto.exists = function exists(_path, _val) { var path; var val; if (0 === arguments.length) { this._ensurePath('exists'); path = this._path; val = true; } else if (1 === arguments.length) { if ('boolean' === typeof arguments[0]) { this._ensurePath('exists'); path = this._path; val = arguments[0]; } else { path = arguments[0]; val = true; } } else if (2 === arguments.length) { path = arguments[0]; val = arguments[1]; } var conds = this._conditions[path] || (this._conditions[path] = {}); conds.$exists = val; return this; } /** * Specifies an `$elemMatch` condition * ####Example * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}}) * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}}) * query.elemMatch('comment', function (elem) { * elem.where('author').equals('autobot'); * elem.where('votes').gte(5); * }) * query.where('comment').elemMatch(function (elem) { * elem.where({ author: 'autobot' }); * elem.where('votes').gte(5); * }) */; _proto.elemMatch = function elemMatch(_path, _criteria) { if (null === arguments[0]) throw (0, _rxError.newRxTypeError)('MQ2'); var fn; var path; var criteria; if ('function' === typeof arguments[0]) { this._ensurePath('elemMatch'); path = this._path; fn = arguments[0]; } else if ((0, _mqueryUtils.isObject)(arguments[0])) { this._ensurePath('elemMatch'); path = this._path; criteria = arguments[0]; } else if ('function' === typeof arguments[1]) { path = arguments[0]; fn = arguments[1]; } else if (arguments[1] && (0, _mqueryUtils.isObject)(arguments[1])) { path = arguments[0]; criteria = arguments[1]; } else throw (0, _rxError.newRxTypeError)('MQ2'); if (fn) { criteria = new NoSqlQueryBuilderClass(); fn(criteria); criteria = criteria._conditions; } var conds = this._conditions[path] || (this._conditions[path] = {}); conds.$elemMatch = criteria; return this; } /** * Sets the sort order * If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1. * If a string is passed, it must be a space delimited list of path names. * The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending. * ####Example * query.sort({ field: 'asc', test: -1 }); * query.sort('field -test'); * query.sort([['field', 1], ['test', -1]]); */; _proto.sort = function sort(arg) { if (!arg) return this; var len; var type = typeof arg; // .sort([['field', 1], ['test', -1]]) if (Array.isArray(arg)) { len = arg.length; for (var i = 0; i < arg.length; ++i) { _pushArr(this.options, arg[i][0], arg[i][1]); } return this; } // .sort('field -test') if (1 === arguments.length && 'string' === type) { arg = arg.split(/\s+/); len = arg.length; for (var _i = 0; _i < len; ++_i) { var field = arg[_i]; if (!field) continue; var ascend = '-' === field[0] ? -1 : 1; if (ascend === -1) field = field.substring(1); push(this.options, field, ascend); } return this; } // .sort({ field: 1, test: -1 }) if ((0, _mqueryUtils.isObject)(arg)) { var keys = Object.keys(arg); keys.forEach(field => push(this.options, field, arg[field])); return this; } throw (0, _rxError.newRxTypeError)('MQ3', { args: arguments }); } /** * Merges another MQuery or conditions object into this one. * * When a MQuery is passed, conditions, field selection and options are merged. * */; _proto.merge = function merge(source) { if (!source) { return this; } if (!canMerge(source)) { throw (0, _rxError.newRxTypeError)('MQ4', { source }); } if (source instanceof NoSqlQueryBuilderClass) { // if source has a feature, apply it to ourselves if (source._conditions) (0, _mqueryUtils.merge)(this._conditions, source._conditions); if (source._fields) { if (!this._fields) this._fields = {}; (0, _mqueryUtils.merge)(this._fields, source._fields); } if (source.options) { if (!this.options) this.options = {}; (0, _mqueryUtils.merge)(this.options, source.options); } if (source._distinct) this._distinct = source._distinct; return this; } // plain object (0, _mqueryUtils.merge)(this._conditions, source); return this; } /** * Finds documents. * ####Example * query.find() * query.find({ name: 'Burning Lights' }) */; _proto.find = function find(criteria) { if (canMerge(criteria)) { this.merge(criteria); } return this; } /** * Make sure _path is set. * * @param {String} method */; _proto._ensurePath = function _ensurePath(method) { if (!this._path) { throw (0, _rxError.newRxError)('MQ5', { method }); } }; _proto.toJSON = function toJSON() { var query = { selector: this._conditions }; if (this.options.skip) { query.skip = this.options.skip; } if (this.options.limit) { query.limit = this.options.limit; } if (this.options.sort) { query.sort = mQuerySortToRxDBSort(this.options.sort); } return { query, path: this._path }; }; return NoSqlQueryBuilderClass; }(); function mQuerySortToRxDBSort(sort) { return Object.entries(sort).map(([k, v]) => { var direction = v === 1 ? 'asc' : 'desc'; var part = { [k]: direction }; return part; }); } /** * Because some prototype-methods are generated, * we have to define the type of NoSqlQueryBuilder here */ /** * limit, skip, maxScan, batchSize, comment * * Sets these associated options. * * query.comment('feed query'); */ var OTHER_MANGO_ATTRIBUTES = exports.OTHER_MANGO_ATTRIBUTES = ['limit', 'skip', 'maxScan', 'batchSize', 'comment']; OTHER_MANGO_ATTRIBUTES.forEach(function (method) { NoSqlQueryBuilderClass.prototype[method] = function (v) { this.options[method] = v; return this; }; }); /** * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance * * Thing.where('type').nin(array) */ var OTHER_MANGO_OPERATORS = exports.OTHER_MANGO_OPERATORS = ['gt', 'gte', 'lt', 'lte', 'ne', 'in', 'nin', 'all', 'regex', 'size']; OTHER_MANGO_OPERATORS.forEach(function ($conditional) { NoSqlQueryBuilderClass.prototype[$conditional] = function () { var path; var val; if (1 === arguments.length) { this._ensurePath($conditional); val = arguments[0]; path = this._path; } else { val = arguments[1]; path = arguments[0]; } var conds = this._conditions[path] === null || typeof this._conditions[path] === 'object' ? this._conditions[path] : this._conditions[path] = {}; if ($conditional === 'regex') { if (val instanceof RegExp) { throw (0, _rxError.newRxError)('QU16', { field: path, query: this._conditions }); } if (typeof val === 'string') { conds['$' + $conditional] = val; } else { conds['$' + $conditional] = val.$regex; if (val.$options) { conds.$options = val.$options; } } } else { conds['$' + $conditional] = val; } return this; }; }); function push(opts, field, value) { if (Array.isArray(opts.sort)) { throw (0, _rxError.newRxTypeError)('MQ6', { opts, field, value }); } if (value && value.$meta) { var sort = opts.sort || (opts.sort = {}); sort[field] = { $meta: value.$meta }; return; } var val = String(value || 1).toLowerCase(); if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) { if (Array.isArray(value)) value = '[' + value + ']'; throw (0, _rxError.newRxTypeError)('MQ7', { field, value }); } // store `sort` in a sane format var s = opts.sort || (opts.sort = {}); var valueStr = value.toString().replace('asc', '1').replace('ascending', '1').replace('desc', '-1').replace('descending', '-1'); s[field] = parseInt(valueStr, 10); } function _pushArr(opts, field, value) { opts.sort = opts.sort || []; if (!Array.isArray(opts.sort)) { throw (0, _rxError.newRxTypeError)('MQ8', { opts, field, value }); } /* const valueStr = value.toString() .replace('asc', '1') .replace('ascending', '1') .replace('desc', '-1') .replace('descending', '-1');*/ opts.sort.push([field, value]); } /** * Determines if `conds` can be merged using `mquery().merge()` */ function canMerge(conds) { return conds instanceof NoSqlQueryBuilderClass || (0, _mqueryUtils.isObject)(conds); } function createQueryBuilder(query, path) { return new NoSqlQueryBuilderClass(query, path); } //# sourceMappingURL=nosql-query-builder.js.map