UNPKG

shyft-storage-connector

Version:
413 lines (333 loc) 14.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.buildWhereQuery = exports.buildWhereTypeQuery = exports.processAndConvertFilter = exports.purifyFilter = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _shyft = require("shyft"); var _typeorm = require("typeorm"); var _util = require("./util"); var noResultClause = 'TRUE IS FALSE'; var purifyFilter = function purifyFilter(filter) { if ((0, _shyft.isMap)(filter)) { if ((0, _shyft.isMap)(filter, true)) { var ret = {}; Object.keys(filter).map(function (key) { var isOperator = key.indexOf('$') === 0; if (['$in', '$notIn'].includes(key) && (0, _shyft.isArray)(filter[key])) { ret[key] = filter[key]; } else if (filter[key] === null && (key === '$ne' || !isOperator)) { ret[key] = filter[key]; } else { var pureFilter = purifyFilter(filter[key]); if (pureFilter !== null && typeof pureFilter !== 'undefined') { ret[key] = pureFilter; } } }); if ((0, _shyft.isMap)(ret, true)) { return ret; } } } else if ((0, _shyft.isArray)(filter)) { if ((0, _shyft.isArray)(filter, true)) { var _ret = []; filter.map(function (subFilter) { var pureFilter = purifyFilter(subFilter); if (pureFilter !== null && typeof pureFilter !== 'undefined') { _ret.push(pureFilter); } }); if (_ret.length) { return _ret; } } } else if (filter !== null && typeof filter !== 'undefined') { return filter; } return null; }; exports.purifyFilter = purifyFilter; var processAndConvertFilter = function processAndConvertFilter(entity, filterShaper, args, StorageTypePostgres) { var where = (0, _shyft.processFilter)(entity, args, StorageTypePostgres); var convertedWhere = (0, _shyft.convertFilterLevel)(filterShaper, where); return convertedWhere; }; exports.processAndConvertFilter = processAndConvertFilter; var escapeILikePattern = function escapeILikePattern(pattern) { return pattern.replace(/%/g, '\\%').replace(/_/g, '\\_'); }; var defaultTransformFilterAttributeName = function defaultTransformFilterAttributeName(attributeName) { return attributeName; }; var buildWhereAttributeOperatorConditionQuery = function buildWhereAttributeOperatorConditionQuery(qBuilder, attributeName, operator, value) { var transformFilterAttributeNameFn = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : defaultTransformFilterAttributeName; var _placeholderIdx = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; var placeholderIdx = _placeholderIdx || { idx: 0 }; placeholderIdx.idx++; var placeholderName = "".concat(attributeName, "__").concat(placeholderIdx.idx).replace('.', '__'); var data = (0, _defineProperty2["default"])({}, placeholderName, value); var leftExpression = (0, _util.quote)(transformFilterAttributeNameFn(attributeName)); switch (operator) { case '$eq': if (value === null) { qBuilder.andWhere("".concat(leftExpression, " IS NULL")); } else { qBuilder.andWhere("".concat(leftExpression, " = :").concat(placeholderName), data); } break; case '$ne': if (value === null) { qBuilder.andWhere("".concat(leftExpression, " IS NOT NULL"), data); } else { qBuilder.andWhere("".concat(leftExpression, " <> :").concat(placeholderName), data); } break; case '$in': if (!value || !value.length) { qBuilder.andWhere(noResultClause); } else { qBuilder.andWhere("".concat(leftExpression, " IN (:...").concat(placeholderName, ")"), data); } break; case '$notIn': if (!value || !value.length) { qBuilder.andWhere(noResultClause); } else { qBuilder.andWhere("".concat(leftExpression, " NOT IN (:...").concat(placeholderName, ")"), data); } break; case '$lt': qBuilder.andWhere("".concat(leftExpression, " < :").concat(placeholderName), data); break; case '$lte': qBuilder.andWhere("".concat(leftExpression, " <= :").concat(placeholderName), data); break; case '$gt': qBuilder.andWhere("".concat(leftExpression, " > :").concat(placeholderName), data); break; case '$gte': qBuilder.andWhere("".concat(leftExpression, " >= :").concat(placeholderName), data); break; case '$contains': qBuilder.andWhere("".concat(leftExpression, " ILIKE :").concat(placeholderName), (0, _defineProperty2["default"])({}, placeholderName, "%".concat(escapeILikePattern(value), "%"))); break; case '$startsWith': qBuilder.andWhere("".concat(leftExpression, " ILIKE :").concat(placeholderName), (0, _defineProperty2["default"])({}, placeholderName, "".concat(escapeILikePattern(value), "%"))); break; case '$endsWith': qBuilder.andWhere("".concat(leftExpression, " ILIKE :").concat(placeholderName), (0, _defineProperty2["default"])({}, placeholderName, "%".concat(escapeILikePattern(value)))); break; case '$notContains': qBuilder.andWhere("".concat(leftExpression, " NOT ILIKE :").concat(placeholderName), (0, _defineProperty2["default"])({}, placeholderName, "%".concat(escapeILikePattern(value), "%"))); break; case '$notStartsWith': qBuilder.andWhere("".concat(leftExpression, " NOT ILIKE :").concat(placeholderName), (0, _defineProperty2["default"])({}, placeholderName, "".concat(escapeILikePattern(value), "%"))); break; case '$notEndsWith': qBuilder.andWhere("".concat(leftExpression, " NOT ILIKE :").concat(placeholderName), (0, _defineProperty2["default"])({}, placeholderName, "%".concat(escapeILikePattern(value)))); break; case '$includes': qBuilder.andWhere("".concat(leftExpression, " ? :").concat(placeholderName), data); break; case '$notIncludes': qBuilder.andWhere("NOT ".concat(leftExpression, " ? :").concat(placeholderName), data); break; case '$isNull': if (!!value) { qBuilder.andWhere("".concat(leftExpression, " IS NULL"), data); } else { qBuilder.andWhere("".concat(leftExpression, " IS NOT NULL"), data); } break; case '$noResult': qBuilder.andWhere(noResultClause); break; default: throw new Error("Unknown filter operator: ".concat(operator)); } }; var buildWhereAttributeConditionQuery = function buildWhereAttributeConditionQuery(qBuilder, attributeName, filter, transformFilterAttributeNameFn, _placeholderIdx) { var placeholderIdx = _placeholderIdx || { idx: 0 }; placeholderIdx.idx++; if ((0, _shyft.isMap)(filter)) { var operators = Object.keys(filter); operators.map(function (operator) { var value = filter[operator]; buildWhereAttributeOperatorConditionQuery(qBuilder, attributeName, operator, value, transformFilterAttributeNameFn, placeholderIdx); }); } else { buildWhereAttributeOperatorConditionQuery(qBuilder, attributeName, '$eq', filter, transformFilterAttributeNameFn, placeholderIdx); } }; var buildWhereTypeSubQuery = function buildWhereTypeSubQuery(qBuilder, filter, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn, _placeholderIdx) { if (!filter.entity) { throw new Error('$sub expects an entity name'); } if (!(0, _shyft.isArray)(filter.condition, true)) { throw new Error('$sub expects an array of conditions'); } var dataShaperMap = modelRegistry[entityName].dataShaperMap; var _modelRegistry$filter = modelRegistry[filter.entity], targetDataShaperMap = _modelRegistry$filter.dataShaperMap, filterEntityStorageTableName = _modelRegistry$filter.storageTableName; var isSelfLookup = entityName === filter.entity; var inOperatorLink; if (isGetMany) { inOperatorLink = filter.condition.find(function (_ref) { var sourceAttribute = _ref.sourceAttribute; return !!sourceAttribute; }); if (!inOperatorLink && isSelfLookup) { inOperatorLink = { targetAttribute: 'id', operator: '$eq', sourceAttribute: 'id' }; } } qBuilder.andWhere(function (qbSub) { var subQuery; if (qbSub.subQuery) { subQuery = qbSub.subQuery(); } else { // typeorm cannot run subqueries on delete queries so we need to create a fresh query, // which will be injected in to the outer query at the end subQuery = qbSub.connection.manager.createQueryBuilder(); } if (isGetMany && inOperatorLink) { var targetAttributeName = targetDataShaperMap[inOperatorLink.targetAttribute] || inOperatorLink.targetAttribute; subQuery.select(targetAttributeName).from(filterEntityStorageTableName, filterEntityStorageTableName); } else { subQuery.select('COUNT(*) > 0', 'found').from(filterEntityStorageTableName, filterEntityStorageTableName); } var conditions = isGetMany && inOperatorLink ? filter.condition.filter(function (condition) { return condition !== inOperatorLink; }) : filter.condition; conditions.map(function (_ref2) { var targetAttribute = _ref2.targetAttribute, operator = _ref2.operator, sourceAttribute = _ref2.sourceAttribute, value = _ref2.value; var targetAttributeName = targetDataShaperMap[targetAttribute] || targetAttribute; if (sourceAttribute) { var storageTableName = modelRegistry[entityName].storageTableName; var sourceAttributeName = "".concat(storageTableName, ".").concat(dataShaperMap[sourceAttribute] || sourceAttribute); subQuery.andWhere("".concat((0, _util.quote)(targetAttributeName), " = ").concat((0, _util.quote)(sourceAttributeName))); } else { buildWhereAttributeOperatorConditionQuery(subQuery, targetAttributeName, operator, value, transformFilterAttributeNameFn, _placeholderIdx); } }); var query = subQuery.getQuery(); if (isGetMany && inOperatorLink) { var sourceAttributeName = dataShaperMap[inOperatorLink.sourceAttribute] || inOperatorLink.sourceAttribute; query = "".concat((0, _util.quote)(sourceAttributeName), " IN ").concat(query); } // inject query params into outer query (as typeorm cannot run subqueries on delete queries) if (!qbSub.subQuery) { qbSub.setParameters(subQuery.getParameters()); } return query; }); }; var buildWhereTypeQuery = function buildWhereTypeQuery(filter, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn, _placeholderIdx) { var placeholderIdx = _placeholderIdx || { idx: 0 }; placeholderIdx.idx++; var dataShaperMap = modelRegistry[entityName].dataShaperMap; if ((0, _shyft.isMap)(filter)) { if ((0, _shyft.isMap)(filter, true)) { return new _typeorm.Brackets(function (qbAnd) { var keys = Object.keys(filter); keys.map(function (key) { var newFilter = filter[key]; if (key === '$and') { if (!(0, _shyft.isArray)(newFilter)) { throw new Error('$and expects an array of filters'); } var andFilters = []; newFilter.map(function (andFilter) { if ((0, _shyft.isMap)(andFilter, true)) { andFilters.push(andFilter); } }); if (andFilters.length) { newFilter.map(function (val) { var where = buildWhereTypeQuery(val, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn, placeholderIdx); if (where) { qbAnd.andWhere(where); } }); } } else if (key === '$or') { if (!(0, _shyft.isArray)(newFilter)) { throw new Error('$or expects an array of filters'); } var orFilters = []; newFilter.map(function (orFilter) { if ((0, _shyft.isMap)(orFilter, true)) { orFilters.push(orFilter); } }); if (orFilters.length) { var orBrackets = new _typeorm.Brackets(function (qbOr) { newFilter.map(function (val) { var where = buildWhereTypeQuery(val, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn, placeholderIdx); if (where) { qbOr.orWhere(where); } }); }); qbAnd.andWhere(orBrackets); } } else if (key === '$sub') { buildWhereTypeSubQuery(qbAnd, newFilter, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn, _placeholderIdx); } else if (key === '$not') { if (!(0, _shyft.isMap)(newFilter)) { throw new Error('$not expects a filter'); } if ((0, _shyft.isMap)(newFilter, true)) { var where = buildWhereTypeQuery(newFilter, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn, placeholderIdx); if (where) { var notBrackets = new _typeorm.Brackets(function (qbNot) { qbNot.andWhere(where); }); // tiny workaround to get the brackets conditions negated qbAnd.expressionMap.wheres.push({ type: 'simple', condition: 'NOT' }); qbAnd.expressionMap.wheres.push({ type: 'simple', condition: qbAnd.computeWhereParameter(notBrackets) }); } } } else if (key.indexOf('$') === 0) { throw new Error('missing attribute name for filter operator'); } else { var attributeName = dataShaperMap[key] || key; buildWhereAttributeConditionQuery(qbAnd, attributeName, newFilter, transformFilterAttributeNameFn, placeholderIdx); } }); }); } } return null; }; exports.buildWhereTypeQuery = buildWhereTypeQuery; var buildWhereQuery = function buildWhereQuery(qBuilder, filter, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn) { if (!modelRegistry || !modelRegistry[entityName]) { throw new Error('buildWhereQuery() is missing a valid modelRegistry parameter'); } var pureFilter = purifyFilter(filter); var where = buildWhereTypeQuery(pureFilter, entityName, modelRegistry, isGetMany, transformFilterAttributeNameFn); if (where) { qBuilder.andWhere(where); } }; exports.buildWhereQuery = buildWhereQuery;