UNPKG

hydrate-mongodb

Version:
193 lines (192 loc) 8.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var RegExpUtil = require("../core/regExpUtil"); var mappingModel_1 = require("../mapping/mappingModel"); var writeContext_1 = require("../mapping/writeContext"); var persistenceError_1 = require("../persistenceError"); var CriteriaBuilder = (function () { function CriteriaBuilder(mapping) { this.mapping = mapping; } CriteriaBuilder.prototype.build = function (criteria) { this.error = undefined; var preparedCriteria = this.prepareQueryDocument(criteria, this.mapping); if (!preparedCriteria) { return null; } this.mapping.setQueryDocumentDiscriminator(preparedCriteria); return preparedCriteria; }; CriteriaBuilder.prototype.prepareQueryDocument = function (query, mapping, withinField) { if (!query) return {}; var result = {}; for (var key in query) { if (query.hasOwnProperty(key)) { var value = query[key], preparedKey = key, preparedValue = value; if (key[0] == "$") { if (key == "$and" || key == "$or" || key == "$nor") { if (!Array.isArray(value)) { this.error = new persistenceError_1.PersistenceError("Value of '" + key + "' operator should be an array."); return null; } var arr = new Array(value.length); for (var i = 0, l = value.length; i < l; i++) { arr[i] = this.prepareQueryDocument(value[i], mapping); } preparedValue = arr; } else if (key == "$where" || key == "$text") { if (withinField) { this.error = new persistenceError_1.PersistenceError("Operator '" + key + "' is not allowed in $elemMatch."); return null; } preparedValue = value; } else if (withinField) { return this._prepareQueryExpression(key, query, mapping); } else { this.error = new persistenceError_1.PersistenceError("Unknown top-level operator '" + key + "'."); return null; } } else { if (key == "_id") { if (typeof value === "string") { preparedValue = this.mapping.inheritanceRoot.identity.fromString(value); } if (value == null || preparedValue == null) { this.error = new persistenceError_1.PersistenceError("Missing or invalid identifier for '_id'."); return null; } } else { var context = mapping.resolve(key); if (context.error) { this.error = context.error; return null; } var resolvedMapping = context.resolvedMapping; if (this.isQueryExpression(value)) { if (resolvedMapping.flags & 1) { resolvedMapping = resolvedMapping.elementMapping; } preparedValue = this._prepareQueryExpression(key, value, resolvedMapping); } else { if (resolvedMapping.flags & 1) { var arrayMapping = resolvedMapping; if (!Array.isArray(value) || (arrayMapping.nestedDepth > 1 && arrayMapping.nestedDepth > this._findArrayDepth(value))) { resolvedMapping = arrayMapping.elementMapping; } } preparedValue = this.prepareQueryValue(context.resolvedPath, value, resolvedMapping); } preparedKey = context.resolvedPath; } } (result || (result = {}))[preparedKey] = preparedValue; } } return result; }; CriteriaBuilder.prototype._prepareQueryExpression = function (operator, query, mapping) { if (!query) { this.error = new persistenceError_1.PersistenceError("Missing value for operator '" + operator + "'."); return null; } var result = {}; for (var key in query) { if (query.hasOwnProperty(key)) { if (key[0] != "$") { this.error = new persistenceError_1.PersistenceError("Unexpected value '" + key + "' in query expression."); return null; } var value = query[key], preparedValue; switch (key) { case '$gt': case '$gte': case '$lt': case '$lte': case '$ne': preparedValue = this.prepareQueryValue(key, value, mapping); break; case '$in': case '$nin': case '$all': preparedValue = this.prepareArrayOfValues(key, value, mapping); break; case '$not': preparedValue = this._prepareQueryExpression(key, value, mapping); break; case '$elemMatch': preparedValue = this.prepareQueryDocument(value, mapping, true); break; case '$exists': case '$type': case '$mod': case '$regex': case '$options': case '$geoIntersects': case '$geoWithin': case '$nearSphere': case '$near': case '$size': case '$comment': preparedValue = value; break; default: this.error = new persistenceError_1.PersistenceError("Unknown query operator '" + key + "'."); return null; } result[key] = preparedValue; } } return result; }; CriteriaBuilder.prototype.prepareArrayOfValues = function (operator, value, mapping) { if (!Array.isArray(value)) { this.error = new persistenceError_1.PersistenceError("Expected array for '" + operator + "' operator."); return null; } var result = new Array(value.length); for (var i = 0, l = value.length; i < l; i++) { result[i] = this.prepareQueryValue(operator, value[i], mapping); } return result; }; CriteriaBuilder.prototype.prepareQueryValue = function (path, value, mapping) { if ((mapping.flags & 256) && (value instanceof RegExp)) { return RegExpUtil.clone(value); } var context = new writeContext_1.WriteContext(path); var preparedValue = mapping.write(context, value); if (context.hasErrors) { this.error = new persistenceError_1.PersistenceError("Bad value: " + context.getErrorMessage()); return null; } return preparedValue; }; CriteriaBuilder.prototype._findArrayDepth = function (value, depth) { if (depth === void 0) { depth = 0; } if (value && Array.isArray(value)) { for (var i = 0, l = value.length; i < l; i++) { depth = Math.max(depth, this._findArrayDepth(value[i], depth + 1)); } } return depth; }; CriteriaBuilder.prototype.isQueryExpression = function (value) { if (typeof value === "object") { for (var key in value) { if (value.hasOwnProperty(key)) { return key[0] == "$"; } } } return false; }; return CriteriaBuilder; }()); exports.CriteriaBuilder = CriteriaBuilder;