@schukai/monster
Version:
Monster is a simple library for creating fast, robust and lightweight websites.
122 lines (119 loc) • 5.3 kB
JavaScript
/**
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
* Node module: @schukai/monster
*
* This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
* The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
*
* For those who do not wish to adhere to the AGPLv3, a commercial license is available.
* Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
* For more information about purchasing a commercial license, please contact schukai GmbH.
*
* SPDX-License-Identifier: AGPL-3.0
*/
export { generateRangeComparisonExpression };
/**
* The `generateRangeComparisonExpression()` function is function that generates a string representation
* of a comparison expression based on a range of values. It takes three arguments:
*
* - expression (required): a string representation of a range of values in the format of start1-end1,start2-end2,value3....
* - valueName (required): a string representing the name of the value that is being compared to the range of values.
* - options (optional): an object containing additional options to customize the comparison expression.
*
* The generateRangeComparisonExpression() function returns a string representation of the comparison expression.
*
* ## Options
* The option parameter is an object that can have the following properties:
*
* urlEncode (boolean, default: false): if set to true, URL encodes the comparison operators.
* andOp (string, default: '&&'): the logical AND operator to use in the expression.
* orOp (string, default: '||'): the logical OR operator to use in the expression.
* eqOp (string, default: '=='): the equality operator to use in the expression.
* geOp (string, default: '>='): the greater than or equal to operator to use in the expression.
* leOp (string, default: '<='): the less than or equal to operator to use in the expression.
*
* Examples
*
* ```javascript
* const expression = '0-10,20-30';
* const valueName = 'age';
* const options = { urlEncode: true, andOp: 'and', orOp: 'or', eqOp: '=', geOp: '>=', leOp: '<=' };
* const comparisonExpression = generateRangeComparisonExpression(expression, valueName, options);
*
* console.log(comparisonExpression); // age%3E%3D0%20and%20age%3C%3D10%20or%20age%3E%3D20%20and%20age%3C%3D30
* ```
*
* In this example, the generateRangeComparisonExpression() function generates a string representation of the comparison
* expression for the expression and valueName parameters with the specified options. The resulting comparison
* expression is 'age>=0 and age<=10 or age>=20 and age<=30', URL encoded according to the urlEncode option.
*
* @param {string} expression - The string expression to generate the comparison for.
* @param {string} valueName - The name of the value to compare against.
* @param {Object} [options] - The optional parameters.
* @param {boolean} [options.urlEncode=false] - Whether to encode comparison operators for use in a URL.
* @param {string} [options.andOp='&&'] - The logical AND operator to use.
* @param {string} [options.orOp='||'] - The logical OR operator to use.
* @param {string} [options.eqOp='=='] - The comparison operator for equality to use.
* @param {string} [options.geOp='>='] - The comparison operator for greater than or equal to to use.
* @param {string} [options.leOp='<='] - The comparison operator for less than or equal to to use.
* @return {string} The generated comparison expression.
* @throws {Error} If the input is invalid.
* @summary Generates a comparison expression based on a range of values.
*/
function generateRangeComparisonExpression(
expression,
valueName,
options = {},
) {
const {
urlEncode = false,
andOp = "&&",
orOp = "||",
eqOp = "==",
geOp = ">=",
leOp = "<=",
} = options;
const ranges = expression.split(",");
let comparison = "";
for (let i = 0; i < ranges.length; i++) {
const range = ranges[i].trim();
if (range === "") {
throw new Error(`Invalid range '${range}'`);
} else if (range.includes("-")) {
const [start, end] = range
.split("-")
.map((s) => (s === "" ? null : parseFloat(s)));
if ((start !== null && isNaN(start)) || (end !== null && isNaN(end))) {
throw new Error(`Invalid value in range '${range}'`);
}
if (start !== null && end !== null && start > end) {
throw new Error(`Invalid range '${range}'`);
}
const compStart =
start !== null
? `${valueName}${urlEncode ? encodeURIComponent(geOp) : geOp}${start}`
: "";
const compEnd =
end !== null
? `${valueName}${urlEncode ? encodeURIComponent(leOp) : leOp}${end}`
: "";
const compRange = `${compStart}${
compStart && compEnd ? ` ${andOp} ` : ""
}${compEnd}`;
comparison += ranges.length > 1 ? `(${compRange})` : compRange;
} else {
const value = parseFloat(range);
if (isNaN(value)) {
throw new Error(`Invalid value '${range}'`);
}
const compValue = `${valueName}${
urlEncode ? encodeURIComponent(eqOp) : eqOp
}${value}`;
comparison += ranges.length > 1 ? `(${compValue})` : compValue;
}
if (i < ranges.length - 1) {
comparison += ` ${orOp} `;
}
}
return comparison;
}