@webiny/api-headless-cms-ddb
Version:
DynamoDB storage operations plugin for Headless CMS API.
158 lines (154 loc) • 4.42 kB
JavaScript
"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