UNPKG

@webiny/api-headless-cms-ddb

Version:

DynamoDB storage operations plugin for Headless CMS API.

158 lines (154 loc) 4.42 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.filter = void 0; var _ValueFilterPlugin = require("@webiny/db-dynamodb/plugins/definitions/ValueFilterPlugin"); var _error = _interopRequireDefault(require("@webiny/error")); var _fullTextSearch = require("./fullTextSearch"); var _createExpressions = require("./createExpressions"); var _transform = require("./transform"); var _getValue = require("./getValue"); const executeFilter = params => { const { value, filter } = params; /** * We need to check if the filter can be used. * If it cannot, we will just return true. */ const canUse = filter.plugin.canUse({ value, compareValue: filter.compareValue }); if (!canUse) { return true; } const matched = filter.plugin.matches({ value, compareValue: filter.compareValue }); if (filter.negate) { return matched === false; } return matched; }; const executeExpressions = params => { const { expressions, getCachedValue, filters, condition } = params; if (expressions.length === 0 && filters.length === 0) { return true; } /** * Always run filters first as they might trigger an early return. */ for (const filter of filters) { const value = getCachedValue(filter); const result = executeFilter({ value, filter }); /** * Filters are ALWAYS executed as an AND. * So if even one is false, everything false. */ if (!result) { return false; } } /** * Then we move onto expressions, which are basically nested upon nested filters with different conditions. */ for (const expression of expressions) { const result = executeExpressions({ ...expression, getCachedValue }); if (result && condition === "OR") { return true; } else if (!result && condition == "AND") { return false; } } /** * If condition is an OR, we can fail the expressions check because the code would return a lot earlier than this line. * * Also, if condition is not an OR, we can say that the expressions check is ok, because it would fail a lot earlier than this line. */ return condition === "OR" ? false : true; }; const filter = params => { const { items: records, where, plugins, fields, fullTextSearch } = params; const keys = Object.keys(where); if (keys.length === 0 && !fullTextSearch) { return records; } const expression = (0, _createExpressions.createExpressions)({ plugins, where, fields }); /** * No point in going further if there are no expressions to be applied and no full text search to be executed. */ if (expression.filters.length === 0 && expression.expressions.length === 0 && !fullTextSearch?.term) { return records; } /** * We need the contains plugin to run the full text search. */ const fullTextSearchPlugin = plugins.byType(_ValueFilterPlugin.ValueFilterPlugin.type).find(plugin => plugin.getOperation() === "contains"); if (!fullTextSearchPlugin) { throw new _error.default(`Missing "contains" plugin to run the full-text search.`, "MISSING_PLUGIN"); } const search = (0, _fullTextSearch.createFullTextSearch)({ term: fullTextSearch?.term, targetFields: fullTextSearch?.fields, fields, plugin: fullTextSearchPlugin }); return records.filter(record => { const cachedValues = {}; const getCachedValue = filter => { const { path } = filter; if (cachedValues[path] !== undefined) { return cachedValues[path]; } const plainValue = (0, _getValue.getValue)(record, path); const rawValue = (0, _transform.transformValue)({ value: plainValue, transform: filter.transformValue }); cachedValues[path] = rawValue; return rawValue; }; const exprResult = executeExpressions({ ...expression, getCachedValue }); /** * If expression result is false we do not need to continue further. * Also, if there is no full text search defined, just return the expression result. */ if (!exprResult || !search) { return exprResult; } return search(record); }); }; exports.filter = filter; //# sourceMappingURL=filter.js.map