UNPKG

@rsql/emitter

Version:
225 lines (217 loc) 6.65 kB
(function (global, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : ((global = global || self), factory((global.RSQLEmitter = {}))); })(this, function (exports) { "use strict"; var EQ = "=="; var NEQ = "!="; var LE = "<="; var GE = ">="; var LT = "<"; var GT = ">"; var IN = "=in="; var OUT = "=out="; var LE_VERBOSE = "=le="; var GE_VERBOSE = "=ge="; var LT_VERBOSE = "=lt="; var GT_VERBOSE = "=gt="; function mapToCanonicalComparisonOperator(operator) { switch (operator) { case LE_VERBOSE: return LE; case LT_VERBOSE: return LT; case GE_VERBOSE: return GE; case GT_VERBOSE: return GT; default: return operator; } } var CUSTOM_OPERATOR_REGEXP = /^=[a-z]+=$/; function isCustomComparisonOperator(candidate) { return candidate.length > 2 && CUSTOM_OPERATOR_REGEXP.test(candidate); } function isComparisonOperator(candidate, operator) { switch (candidate) { case EQ: case NEQ: case LE: case GE: case LT: case GT: case IN: case OUT: case LE_VERBOSE: case GE_VERBOSE: case LT_VERBOSE: case GT_VERBOSE: return ( operator === undefined || mapToCanonicalComparisonOperator(candidate) === mapToCanonicalComparisonOperator(operator) ); default: if (isCustomComparisonOperator(candidate)) { return operator === undefined || candidate === operator; } else { return false; } } } var AND = ";"; var OR = ","; var AND_VERBOSE = "and"; var OR_VERBOSE = "or"; function mapToCanonicalLogicOperator(operator) { switch (operator) { case AND_VERBOSE: return AND; case OR_VERBOSE: return OR; default: return operator; } } function isLogicOperator(candidate, operator) { switch (candidate) { case AND: case OR: case AND_VERBOSE: case OR_VERBOSE: return ( operator === undefined || mapToCanonicalLogicOperator(candidate) === mapToCanonicalLogicOperator(operator) ); default: return false; } } var ReservedChars = ['"', "'", "(", ")", ";", ",", "=", "!", "~", "<", ">", " ", "\n", "\t", "\r"]; var NodeType = { SELECTOR: "SELECTOR", VALUE: "VALUE", COMPARISON: "COMPARISON", LOGIC: "LOGIC", }; function isNode(candidate) { return candidate !== undefined && candidate !== null && Object.prototype.hasOwnProperty.call(candidate, "type"); } function isComparisonNode(candidate, operator) { return ( isNode(candidate) && candidate.type === NodeType.COMPARISON && (operator === undefined || isComparisonOperator(candidate.operator, operator)) ); } function isLogicNode(candidate, operator) { return ( isNode(candidate) && candidate.type === NodeType.LOGIC && (operator === undefined || isLogicOperator(candidate.operator, operator)) ); } var DEFAULT_EMIT_OPTIONS = { preferredQuote: '"', optimizeQuotes: true, }; var NEEDS_ESCAPING = { '"': /"|\\/g, "'": /'|\\/g, }; function escapeQuotes(value, quote) { return value.replace(NEEDS_ESCAPING[quote], "\\$&"); } function countQuote(value, quote) { var count = 0; for (var i = 0; i < value.length; ++i) { if (value[i] === quote) { count++; } } return count; } function selectQuote(value, _a) { var _b = _a.preferredQuote, preferredQuote = _b === void 0 ? DEFAULT_EMIT_OPTIONS.preferredQuote : _b, _c = _a.optimizeQuotes, optimizeQuotes = _c === void 0 ? DEFAULT_EMIT_OPTIONS.optimizeQuotes : _c; if (optimizeQuotes) { var otherQuote = preferredQuote === '"' ? "'" : '"'; return countQuote(value, otherQuote) < countQuote(value, preferredQuote) ? otherQuote : preferredQuote; } else { return preferredQuote; } } function escapeValue(value, options) { if ( value === "" || ReservedChars.some(function (reservedChar) { return value.includes(reservedChar); }) ) { var quote = selectQuote(value, options); return "" + quote + escapeQuotes(value, quote) + quote; } return value; } function emitSelector(node) { return node.selector; } function emitValue(node, options) { return Array.isArray(node.value) ? "(" + node.value .map(function (value) { return escapeValue(value, options); }) .join(",") + ")" : escapeValue(node.value, options); } function emitComparison(node, options) { return "" + emitSelector(node.left) + node.operator + emitValue(node.right, options); } function emitLogic(node, options) { var left = emitWithoutOptionsValidation(node.left, options); var right = emitWithoutOptionsValidation(node.right, options); // handle operator precedence - as it's only the case for AND operator, we don't need a generic logic for that if (isLogicOperator(node.operator, AND)) { if (isLogicNode(node.left, OR)) { left = "(" + left + ")"; } if (isLogicNode(node.right, OR)) { right = "(" + right + ")"; } } // for verbose operator add space before and after operator var operator = node.operator === AND_VERBOSE || node.operator === OR_VERBOSE ? " " + node.operator + " " : node.operator; return "" + left + operator + right; } function emitWithoutOptionsValidation(expression, options) { if (isComparisonNode(expression)) { return emitComparison(expression, options); } else if (isLogicNode(expression)) { return emitLogic(expression, options); } throw new TypeError('The "expression" has to be a valid "ExpressionNode", ' + String(expression) + " passed."); } function emit(expression, options) { if (options === void 0) { options = {}; } if (options.preferredQuote !== undefined && options.preferredQuote !== '"' && options.preferredQuote !== "'") { throw new TypeError( 'Invalid "preferredQuote" option: ' + options.preferredQuote + ". Must be either \" (the ASCII double quote character) or ' (the ASCII single quote character)." ); } return emitWithoutOptionsValidation(expression, options); } exports.emit = emit; Object.defineProperty(exports, "__esModule", { value: true }); });