react-querybuilder
Version:
React Query Builder component for constructing queries and filters, with utilities for executing them in various database and evaluation contexts
1,194 lines (1,173 loc) • 81.2 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/utils/formatQuery/index.ts
var formatQuery_exports = {};
__export(formatQuery_exports, {
celCombinatorMap: () => celCombinatorMap,
defaultCELValueProcessor: () => defaultCELValueProcessor,
defaultExportOperatorMap: () => defaultExportOperatorMap,
defaultMongoDBValueProcessor: () => defaultMongoDBValueProcessor,
defaultNLTranslations: () => defaultNLTranslations,
defaultOperatorProcessorNL: () => defaultOperatorProcessorNL,
defaultRuleProcessorCEL: () => defaultRuleProcessorCEL,
defaultRuleProcessorElasticSearch: () => defaultRuleProcessorElasticSearch,
defaultRuleProcessorJSONata: () => defaultRuleProcessorJSONata,
defaultRuleProcessorJsonLogic: () => defaultRuleProcessorJsonLogic,
defaultRuleProcessorMongoDB: () => defaultRuleProcessorMongoDB,
defaultRuleProcessorMongoDBQuery: () => defaultRuleProcessorMongoDBQuery,
defaultRuleProcessorNL: () => defaultRuleProcessorNL,
defaultRuleProcessorParameterized: () => defaultRuleProcessorParameterized,
defaultRuleProcessorSQL: () => defaultRuleProcessorSQL,
defaultRuleProcessorSpEL: () => defaultRuleProcessorSpEL,
defaultSpELValueProcessor: () => defaultSpELValueProcessor,
defaultValueProcessor: () => defaultValueProcessor,
defaultValueProcessorByRule: () => defaultValueProcessorByRule,
defaultValueProcessorCELByRule: () => defaultValueProcessorCELByRule,
defaultValueProcessorMongoDBByRule: () => defaultValueProcessorMongoDBByRule,
defaultValueProcessorNL: () => defaultValueProcessorNL,
defaultValueProcessorSpELByRule: () => defaultValueProcessorSpELByRule,
formatQuery: () => formatQuery,
getNLTranslataion: () => getNLTranslataion,
getQuoteFieldNamesWithArray: () => getQuoteFieldNamesWithArray,
getQuotedFieldName: () => getQuotedFieldName,
isValidValue: () => isValidValue,
isValueProcessorLegacy: () => isValueProcessorLegacy,
jsonLogicAdditionalOperators: () => jsonLogicAdditionalOperators,
mapSQLOperator: () => mapSQLOperator,
mongoOperators: () => mongoOperators,
normalizeConstituentWordOrder: () => normalizeConstituentWordOrder,
numerifyValues: () => numerifyValues,
shouldRenderAsNumber: () => shouldRenderAsNumber,
sqlDialectPresets: () => sqlDialectPresets
});
module.exports = __toCommonJS(formatQuery_exports);
// src/defaults.ts
var defaultPlaceholderName = "~";
var defaultPlaceholderFieldName = defaultPlaceholderName;
var defaultPlaceholderOperatorName = defaultPlaceholderName;
var defaultJoinChar = ",";
var defaultCombinators = [
{ name: "and", value: "and", label: "AND" },
{ name: "or", value: "or", label: "OR" }
];
var defaultCombinatorsExtended = [
...defaultCombinators,
{ name: "xor", value: "xor", label: "XOR" }
];
// src/utils/arrayUtils.ts
var splitBy = (str, splitChar = defaultJoinChar) => typeof str === "string" ? str.split(`\\${splitChar}`).map((c) => c.split(splitChar)).reduce((prev, curr, idx) => {
if (idx === 0) {
return curr;
}
return [...prev.slice(0, -1), `${prev.at(-1)}${splitChar}${curr[0]}`, ...curr.slice(1)];
}, []) : [];
var joinWith = (strArr, joinChar = defaultJoinChar) => strArr.map((str) => `${str ?? ""}`.replaceAll(joinChar[0], `\\${joinChar[0]}`)).join(joinChar);
var trimIfString = (val) => typeof val === "string" ? val.trim() : val;
var toArray = (v, { retainEmptyStrings } = {}) => Array.isArray(v) ? v.map((v2) => trimIfString(v2)) : typeof v === "string" ? splitBy(v, defaultJoinChar).filter(retainEmptyStrings ? () => true : (s) => !/^\s*$/.test(s)).map((s) => s.trim()) : typeof v === "number" ? [v] : [];
// src/utils/misc.ts
var import_numeric_quantity = require("numeric-quantity");
var numericRegex = new RegExp(
import_numeric_quantity.numericRegex.source.replace(/^\^/, String.raw`^\s*`).replace(/\$$/, String.raw`\s*$`)
);
var isPojo = (obj) => obj === null || typeof obj !== "object" ? false : Object.getPrototypeOf(obj) === Object.prototype;
var nullOrUndefinedOrEmpty = (value) => value === null || value === void 0 || value === "";
// src/utils/parseNumber.ts
var import_numeric_quantity2 = require("numeric-quantity");
var parseNumber = (val, { parseNumbers } = {}) => {
if (!parseNumbers || typeof val === "bigint" || typeof val === "number") {
return val;
}
if (parseNumbers === "native") {
return parseFloat(val);
}
const valAsNum = (
// TODO: Should these options be configurable?
(0, import_numeric_quantity2.numericQuantity)(val, {
allowTrailingInvalid: parseNumbers === "enhanced",
romanNumerals: false,
round: false
})
);
return isNaN(valAsNum) ? val : valAsNum;
};
// src/utils/getParseNumberMethod.ts
var getParseNumberMethod = ({
parseNumbers,
inputType
}) => {
if (typeof parseNumbers === "string") {
const [method, level] = parseNumbers.split("-");
if (level === "limited") {
return inputType === "number" ? method : false;
}
return method;
}
return parseNumbers ? "strict" : false;
};
// src/utils/isRuleGroup.ts
var isRuleGroup = (rg) => isPojo(rg) && Array.isArray(rg.rules);
var isRuleGroupType = (rg) => isRuleGroup(rg) && typeof rg.combinator === "string";
var isRuleGroupTypeIC = (rg) => isRuleGroup(rg) && rg.combinator === void 0;
// src/utils/optGroupUtils.ts
var import_immer = require("immer");
var isOptionWithName = (opt) => isPojo(opt) && "name" in opt && typeof opt.name === "string";
var isOptionWithValue = (opt) => isPojo(opt) && "value" in opt && typeof opt.value === "string";
function toFullOption(opt, baseProperties) {
const recipe = (0, import_immer.produce)((draft) => {
const idObj = {};
let needsUpdating = !!baseProperties;
if (isOptionWithName(draft) && !isOptionWithValue(draft)) {
idObj.value = draft.name;
needsUpdating = true;
} else if (!isOptionWithName(draft) && isOptionWithValue(draft)) {
idObj.name = draft.value;
needsUpdating = true;
}
if (needsUpdating) {
return Object.assign({}, baseProperties, draft, idObj);
}
});
return recipe(opt);
}
function toFullOptionList(optList, baseProperties) {
if (!Array.isArray(optList)) {
return [];
}
const recipe = (0, import_immer.produce)((draft) => {
if (isFlexibleOptionGroupArray(draft)) {
for (const optGroup of draft) {
for (const [idx, opt] of optGroup.options.entries())
optGroup.options[idx] = toFullOption(opt, baseProperties);
}
} else {
for (const [idx, opt] of draft.entries())
draft[idx] = toFullOption(opt, baseProperties);
}
});
return recipe(optList);
}
var uniqByIdentifier = (originalArray) => {
const names = /* @__PURE__ */ new Set();
const newArray = [];
for (const el of originalArray) {
if (!names.has(el.value ?? el.name)) {
names.add(el.value ?? el.name);
newArray.push(el);
}
}
return originalArray.length === newArray.length ? originalArray : newArray;
};
var isOptionGroupArray = (arr) => Array.isArray(arr) && arr.length > 0 && isPojo(arr[0]) && "options" in arr[0] && Array.isArray(arr[0].options);
var isFlexibleOptionArray = (arr) => {
let isFOA = false;
if (Array.isArray(arr)) {
for (const o of arr) {
if (isOptionWithName(o) || isOptionWithValue(o)) {
isFOA = true;
} else {
return false;
}
}
}
return isFOA;
};
var isFlexibleOptionGroupArray = (arr, { allowEmpty = false } = {}) => {
let isFOGA = false;
if (Array.isArray(arr)) {
for (const og of arr) {
if (isPojo(og) && "options" in og && (isFlexibleOptionArray(og.options) || allowEmpty && Array.isArray(og.options) && og.options.length === 0)) {
isFOGA = true;
} else {
return false;
}
}
}
return isFOGA;
};
var getOption = (arr, name) => (isFlexibleOptionGroupArray(arr, { allowEmpty: true }) ? arr.flatMap((og) => og.options) : arr).find((op) => op.value === name || op.name === name);
var toFlatOptionArray = (arr) => uniqByIdentifier(isOptionGroupArray(arr) ? arr.flatMap((og) => og.options) : arr);
// src/utils/formatQuery/utils.ts
var mapSQLOperator = (rqbOperator) => {
switch (rqbOperator.toLowerCase()) {
case "null":
return "is null";
case "notnull":
return "is not null";
case "notin":
return "not in";
case "notbetween":
return "not between";
case "contains":
case "beginswith":
case "endswith":
return "like";
case "doesnotcontain":
case "doesnotbeginwith":
case "doesnotendwith":
return "not like";
default:
return rqbOperator;
}
};
var mongoOperators = {
"=": "$eq",
"!=": "$ne",
"<": "$lt",
"<=": "$lte",
">": "$gt",
">=": "$gte",
in: "$in",
notin: "$nin",
notIn: "$nin"
// only here for backwards compatibility
};
var celCombinatorMap = {
and: "&&",
or: "||"
};
var jsonLogicAdditionalOperators = {
startsWith: (a, b) => typeof a === "string" && a.startsWith(b),
endsWith: (a, b) => typeof a === "string" && a.endsWith(b)
};
var numerifyValues = (rg, options) => ({
...rg,
// @ts-expect-error TS doesn't keep track of odd/even indexes here
rules: rg.rules.map((r) => {
if (typeof r === "string") {
return r;
}
if (isRuleGroup(r)) {
return numerifyValues(r, options);
}
const fieldData = getOption(options.fields, r.field);
const parseNumbers = getParseNumberMethod({
parseNumbers: options.parseNumbers,
inputType: fieldData?.inputType
});
if (Array.isArray(r.value)) {
return { ...r, value: r.value.map((v) => parseNumber(v, { parseNumbers })) };
}
const valAsArray = toArray(r.value, { retainEmptyStrings: true }).map(
(v) => parseNumber(v, { parseNumbers })
);
if (valAsArray.every((v) => typeof v === "number")) {
if (valAsArray.length > 1) {
return { ...r, value: valAsArray };
} else if (valAsArray.length === 1) {
return { ...r, value: valAsArray[0] };
}
}
return r;
})
});
var isValidValue = (value) => typeof value === "string" && value.length > 0 || typeof value === "number" && !isNaN(value) || typeof value !== "string" && typeof value !== "number";
var shouldRenderAsNumber = (value, parseNumbers) => !!parseNumbers && (typeof value === "number" || typeof value === "bigint" || typeof value === "string" && numericRegex.test(value));
var isValueProcessorLegacy = (valueProcessor) => valueProcessor.length >= 3;
var getQuoteFieldNamesWithArray = (quoteFieldNamesWith = ["", ""]) => Array.isArray(quoteFieldNamesWith) ? quoteFieldNamesWith : typeof quoteFieldNamesWith === "string" ? [quoteFieldNamesWith, quoteFieldNamesWith] : quoteFieldNamesWith ?? ["", ""];
var getQuotedFieldName = (fieldName, { quoteFieldNamesWith, fieldIdentifierSeparator }) => {
const [qPre, qPost] = getQuoteFieldNamesWithArray(quoteFieldNamesWith);
return typeof fieldIdentifierSeparator === "string" && fieldIdentifierSeparator.length > 0 ? joinWith(
splitBy(fieldName, fieldIdentifierSeparator).map((part) => `${qPre}${part}${qPost}`),
fieldIdentifierSeparator
) : `${qPre}${fieldName}${qPost}`;
};
var defaultWordOrder = ["S", "V", "O"];
var normalizeConstituentWordOrder = (input) => {
const result = [];
const letterSet = new Set(defaultWordOrder);
for (const char of input.toUpperCase()) {
if (letterSet.has(char)) {
result.push(char);
letterSet.delete(char);
if (letterSet.size === 0) break;
}
}
for (const letter of defaultWordOrder) {
if (letterSet.has(letter)) {
result.push(letter);
}
}
return result;
};
var defaultNLTranslations = {
// and: 'and',
// or: 'or',
// true: 'true',
// false: 'false',
groupPrefix: "",
// groupPrefix_not: '',
groupPrefix_not_xor: "either zero or more than one of",
groupPrefix_xor: "exactly one of",
groupSuffix: "is true",
groupSuffix_not: "is not true"
// groupSuffix_not_xor: 'is true',
// groupSuffix_xor: 'is true',
};
var translationMatchFilter = (key, keyToTest, conditions) => (
// The translation matches the base key
keyToTest.startsWith(key) && // The translation specifies all conditions
conditions.every(
(c) => (
// This translation specifies _this_ condition
keyToTest.includes(`_${c}`) && // This translation specifies the same _total number_ of conditions
keyToTest.match(/_/g)?.length === conditions.length
)
)
);
var getNLTranslataion = (key, translations, conditions = []) => conditions.length === 0 ? translations[key] ?? defaultNLTranslations[key] ?? /* istanbul ignore next */
"" : Object.entries(translations).find(
([keyToTest]) => translationMatchFilter(key, keyToTest, conditions)
)?.[1] ?? Object.entries(defaultNLTranslations).find(
([keyToTest]) => translationMatchFilter(key, keyToTest, conditions)
)?.[1] ?? defaultNLTranslations[key] ?? /* istanbul ignore next */
"";
// src/utils/formatQuery/defaultRuleProcessorCEL.ts
var shouldNegate = (op) => op.startsWith("not") || op.startsWith("doesnot");
var escapeDoubleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? v : v.replaceAll(`"`, `\\"`);
var defaultRuleProcessorCEL = ({ field, operator, value, valueSource }, { escapeQuotes, parseNumbers, preserveValueOrder } = {}) => {
const valueIsField = valueSource === "field";
const operatorTL = (operator === "=" ? "==" : operator).toLowerCase();
const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
switch (operatorTL) {
case "<":
case "<=":
case "==":
case "!=":
case ">":
case ">=":
return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`}`;
case "contains":
case "doesnotcontain": {
const negate2 = shouldNegate(operatorTL) ? "!" : "";
return `${negate2}${field}.contains(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
}
case "beginswith":
case "doesnotbeginwith": {
const negate2 = shouldNegate(operatorTL) ? "!" : "";
return `${negate2}${field}.startsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
}
case "endswith":
case "doesnotendwith": {
const negate2 = shouldNegate(operatorTL) ? "!" : "";
return `${negate2}${field}.endsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
}
case "null":
return `${field} == null`;
case "notnull":
return `${field} != null`;
case "in":
case "notin": {
const [prefix, suffix] = shouldNegate(operatorTL) ? ["!(", ")"] : ["", ""];
const valueAsArray = toArray(value);
return `${prefix}${field} in [${valueAsArray.map(
(val) => valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `"${escapeDoubleQuotes(val, escapeQuotes)}"`
).join(", ")}]${suffix}`;
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length >= 2 && !nullOrUndefinedOrEmpty(valueAsArray[0]) && !nullOrUndefinedOrEmpty(valueAsArray[1])) {
const [first, second] = valueAsArray;
const firstNum = shouldRenderAsNumber(first, true) ? parseNumber(first, { parseNumbers: true }) : NaN;
const secondNum = shouldRenderAsNumber(second, true) ? parseNumber(second, { parseNumbers: true }) : NaN;
let firstValue = isNaN(firstNum) ? valueIsField ? `${first}` : `"${escapeDoubleQuotes(first, escapeQuotes)}"` : firstNum;
let secondValue = isNaN(secondNum) ? valueIsField ? `${second}` : `"${escapeDoubleQuotes(second, escapeQuotes)}"` : secondNum;
if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
const tempNum = secondNum;
secondValue = firstNum;
firstValue = tempNum;
}
return operatorTL === "between" ? `(${field} >= ${firstValue} && ${field} <= ${secondValue})` : `(${field} < ${firstValue} || ${field} > ${secondValue})`;
} else {
return "";
}
}
}
return "";
};
// src/utils/formatQuery/defaultRuleProcessorMongoDBQuery.ts
var defaultRuleProcessorMongoDBQuery = ({ field, operator, value, valueSource }, { parseNumbers, preserveValueOrder } = {}) => {
const valueIsField = valueSource === "field";
if (operator === "=" && !valueIsField) {
return {
[field]: shouldRenderAsNumber(value, parseNumbers) ? parseNumber(value, { parseNumbers: "strict" }) : value
};
}
const operatorLC = operator.toLowerCase();
switch (operatorLC) {
case "<":
case "<=":
case "=":
case "!=":
case ">":
case ">=": {
const mongoOperator = mongoOperators[operatorLC];
return valueIsField ? { $expr: { [mongoOperator]: [`$${field}`, `$${value}`] } } : {
[field]: {
[mongoOperator]: shouldRenderAsNumber(value, parseNumbers) ? parseNumber(value, { parseNumbers: "strict" }) : value
}
};
}
case "contains":
return valueIsField ? { $where: `this.${field}.includes(this.${value})` } : { [field]: { $regex: value } };
case "beginswith":
return valueIsField ? { $where: `this.${field}.startsWith(this.${value})` } : { [field]: { $regex: `^${value}` } };
case "endswith":
return valueIsField ? { $where: `this.${field}.endsWith(this.${value})` } : { [field]: { $regex: `${value}$` } };
case "doesnotcontain":
return valueIsField ? { $where: `!this.${field}.includes(this.${value})` } : { [field]: { $not: { $regex: value } } };
case "doesnotbeginwith":
return valueIsField ? { $where: `!this.${field}.startsWith(this.${value})` } : { [field]: { $not: { $regex: `^${value}` } } };
case "doesnotendwith":
return valueIsField ? { $where: `!this.${field}.endsWith(this.${value})` } : { [field]: { $not: { $regex: `${value}$` } } };
case "null":
return { [field]: null };
case "notnull":
return { [field]: { $ne: null } };
case "in":
case "notin": {
const valueAsArray = toArray(value);
return valueIsField ? {
$where: `${operatorLC === "notin" ? "!" : ""}[${valueAsArray.map((val) => `this.${val}`).join(",")}].includes(this.${field})`
} : {
[field]: {
[mongoOperators[operatorLC]]: valueAsArray.map(
(val) => shouldRenderAsNumber(val, parseNumbers) ? parseNumber(val, { parseNumbers: "strict" }) : val
)
}
};
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
const [first, second] = valueAsArray;
const firstNum = shouldRenderAsNumber(first, true) ? parseNumber(first, { parseNumbers: "strict" }) : NaN;
const secondNum = shouldRenderAsNumber(second, true) ? parseNumber(second, { parseNumbers: "strict" }) : NaN;
let firstValue = valueIsField ? first : isNaN(firstNum) ? first : firstNum;
let secondValue = valueIsField ? second : isNaN(secondNum) ? second : secondNum;
if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
const tempNum = secondNum;
secondValue = firstNum;
firstValue = tempNum;
}
if (operatorLC === "between") {
return valueIsField ? {
$and: [
{ $expr: { $gte: [`$${field}`, `$${firstValue}`] } },
{ $expr: { $lte: [`$${field}`, `$${secondValue}`] } }
]
} : { [field]: { $gte: firstValue, $lte: secondValue } };
} else {
return valueIsField ? {
$or: [
{ $expr: { $lt: [`$${field}`, `$${firstValue}`] } },
{ $expr: { $gt: [`$${field}`, `$${secondValue}`] } }
]
} : { $or: [{ [field]: { $lt: firstValue } }, { [field]: { $gt: secondValue } }] };
}
} else {
return "";
}
}
}
return "";
};
// src/utils/formatQuery/defaultRuleProcessorMongoDB.ts
var defaultRuleProcessorMongoDB = (rule, options) => {
const queryObj = defaultRuleProcessorMongoDBQuery(rule, options);
return queryObj ? JSON.stringify(queryObj) : "";
};
// src/utils/formatQuery/defaultRuleProcessorSpEL.ts
var shouldNegate2 = (op) => op.startsWith("not") || op.startsWith("doesnot");
var wrapInNegation = (clause, negate2) => negate2 ? `!(${clause})` : `${clause}`;
var escapeSingleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? v : v.replaceAll(`'`, `\\'`);
var defaultRuleProcessorSpEL = ({ field, operator, value, valueSource }, { escapeQuotes, parseNumbers, preserveValueOrder } = {}) => {
const valueIsField = valueSource === "field";
const operatorTL = (operator === "=" ? "==" : operator).toLowerCase();
const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
switch (operatorTL) {
case "<":
case "<=":
case "==":
case "!=":
case ">":
case ">=":
return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`;
case "contains":
case "doesnotcontain":
return wrapInNegation(
`${field} matches ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`,
shouldNegate2(operatorTL)
);
case "beginswith":
case "doesnotbeginwith": {
const valueTL = valueIsField ? `'^'.concat(${trimIfString(value)})` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes(value, escapeQuotes)}'`;
return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate2(operatorTL));
}
case "endswith":
case "doesnotendwith": {
const valueTL = valueIsField ? `${trimIfString(value)}.concat('$')` : `'${escapeSingleQuotes(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`;
return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate2(operatorTL));
}
case "null":
return `${field} == null`;
case "notnull":
return `${field} != null`;
case "in":
case "notin": {
const negate2 = shouldNegate2(operatorTL) ? "!" : "";
const valueAsArray = toArray(value);
return valueAsArray.length > 0 ? `${negate2}(${valueAsArray.map(
(val) => `${field} == ${valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `'${escapeSingleQuotes(val, escapeQuotes)}'`}`
).join(" or ")})` : "";
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length >= 2 && !nullOrUndefinedOrEmpty(valueAsArray[0]) && !nullOrUndefinedOrEmpty(valueAsArray[1])) {
const [first, second] = valueAsArray;
const firstNum = shouldRenderAsNumber(first, true) ? parseNumber(first, { parseNumbers: true }) : NaN;
const secondNum = shouldRenderAsNumber(second, true) ? parseNumber(second, { parseNumbers: true }) : NaN;
let firstValue = isNaN(firstNum) ? valueIsField ? `${first}` : `'${escapeSingleQuotes(first, escapeQuotes)}'` : firstNum;
let secondValue = isNaN(secondNum) ? valueIsField ? `${second}` : `'${escapeSingleQuotes(second, escapeQuotes)}'` : secondNum;
if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
const tempNum = secondNum;
secondValue = firstNum;
firstValue = tempNum;
}
return operatorTL === "between" ? `(${field} >= ${firstValue} and ${field} <= ${secondValue})` : `(${field} < ${firstValue} or ${field} > ${secondValue})`;
} else {
return "";
}
}
}
return "";
};
// src/utils/formatQuery/defaultValueProcessorByRule.ts
var escapeStringValueQuotes = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : v;
var defaultValueProcessorByRule = ({ operator, value, valueSource }, {
escapeQuotes,
parseNumbers,
preserveValueOrder,
quoteFieldNamesWith,
quoteValuesWith,
concatOperator = "||",
fieldIdentifierSeparator,
wrapValueWith = ["", ""],
translations
} = {}) => {
const valueIsField = valueSource === "field";
const operatorLowerCase = operator.toLowerCase();
const quoteChar = quoteValuesWith || "'";
const quoteValue = (v) => `${wrapValueWith[0]}${quoteChar}${v}${quoteChar}${wrapValueWith[1]}`;
const escapeValue = (v) => escapeStringValueQuotes(v, quoteChar, escapeQuotes);
const wrapAndEscape = (v) => quoteValue(escapeValue(v));
const wrapFieldName = (v) => getQuotedFieldName(v, { quoteFieldNamesWith, fieldIdentifierSeparator });
const concat = (...values) => concatOperator.toUpperCase() === "CONCAT" ? `CONCAT(${values.join(", ")})` : values.join(` ${concatOperator} `);
switch (operatorLowerCase) {
case "null":
case "notnull": {
return "";
}
case "in":
case "notin": {
const valueAsArray = toArray(value);
if (valueAsArray.length > 0) {
return `(${valueAsArray.map(
(v) => valueIsField ? wrapFieldName(v) : shouldRenderAsNumber(v, parseNumbers) ? `${trimIfString(v)}` : `${wrapAndEscape(v)}`
).join(", ")})`;
}
return "";
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value, { retainEmptyStrings: true });
if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) {
return "";
}
const [first, second] = valueAsArray;
const firstNum = shouldRenderAsNumber(first, parseNumbers) ? parseNumber(first, { parseNumbers: "strict" }) : NaN;
const secondNum = shouldRenderAsNumber(second, parseNumbers) ? parseNumber(second, { parseNumbers: "strict" }) : NaN;
const firstValue = isNaN(firstNum) ? valueIsField ? `${first}` : first : firstNum;
const secondValue = isNaN(secondNum) ? valueIsField ? `${second}` : second : secondNum;
const valsOneAndTwoOnly = [firstValue, secondValue];
if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
valsOneAndTwoOnly[0] = secondNum;
valsOneAndTwoOnly[1] = firstNum;
}
return (valueIsField ? valsOneAndTwoOnly.map((v) => wrapFieldName(v)) : valsOneAndTwoOnly.every((v) => shouldRenderAsNumber(v, parseNumbers)) ? valsOneAndTwoOnly.map((v) => parseNumber(v, { parseNumbers: "strict" })) : valsOneAndTwoOnly.map((v) => wrapAndEscape(v))).join(` ${translations?.and ?? "and"} `);
}
case "contains":
case "doesnotcontain":
return valueIsField ? concat(quoteValue("%"), wrapFieldName(value), quoteValue("%")) : quoteValue(`%${escapeValue(value)}%`);
case "beginswith":
case "doesnotbeginwith":
return valueIsField ? concat(wrapFieldName(value), quoteValue("%")) : quoteValue(`${escapeValue(value)}%`);
case "endswith":
case "doesnotendwith":
return valueIsField ? concat(quoteValue("%"), wrapFieldName(value)) : quoteValue(`%${escapeValue(value)}`);
}
if (typeof value === "boolean") {
return value ? "TRUE" : "FALSE";
}
return valueIsField ? wrapFieldName(value) : shouldRenderAsNumber(value, parseNumbers) ? `${trimIfString(value)}` : `${wrapAndEscape(value)}`;
};
// src/utils/formatQuery/defaultRuleProcessorElasticSearch.ts
var rangeOperatorMap = { "<": "lt", "<=": "lte", ">": "gt", ">=": "gte" };
var negateIfNotOp = (op, elasticSearchRule) => op.startsWith("not") || op.startsWith("doesnot") ? { bool: { must_not: elasticSearchRule } } : elasticSearchRule;
var escapeSQ = (s) => s?.replace(/('|\\)/g, `\\$1`);
var textFunctionMap = {
beginswith: "startsWith",
doesnotbeginwith: "startsWith",
doesnotcontain: "contains",
doesnotendwith: "endsWith",
endswith: "endsWith"
};
var getTextScript = (f, o, v) => {
const script = `doc['${f}'].value.${textFunctionMap[o] ?? o}(doc['${v}'].value)`;
return o.startsWith("d") ? `!${script}` : script;
};
var valueRenderer = (v, parseNumbers) => typeof v === "boolean" ? v : shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
var defaultRuleProcessorElasticSearch = ({ field, operator, value, valueSource }, { parseNumbers, preserveValueOrder } = {}) => {
const operatorLC = operator.toLowerCase();
if (valueSource === "field") {
if (toArray(value).some((v) => typeof v !== "string")) return false;
const fieldForScript = escapeSQ(field);
switch (operatorLC) {
case "=":
case "!=":
case ">":
case ">=":
case "<":
case "<=": {
const operatorForScript = operatorLC === "=" ? "==" : operatorLC;
const valueForScript = escapeSQ(value);
return valueForScript ? {
bool: {
filter: {
script: {
script: `doc['${fieldForScript}'].value ${operatorForScript} doc['${valueForScript}'].value`
}
}
}
} : false;
}
case "in":
case "notin": {
const valueAsArray = toArray(value);
if (valueAsArray.length > 0) {
const arr = valueAsArray.map((v) => ({
bool: {
filter: { script: { script: `doc['${fieldForScript}'].value == doc['${v}'].value` } }
}
}));
return { bool: operatorLC === "in" ? { should: arr } : { must_not: arr } };
}
return false;
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length >= 2 && valueAsArray[0] && valueAsArray[1]) {
const script = `doc['${fieldForScript}'].value >= doc['${valueAsArray[0]}'].value && doc['${fieldForScript}'].value <= doc['${valueAsArray[1]}'].value`;
return {
bool: {
filter: { script: { script: operatorLC === "notbetween" ? `!(${script})` : script } }
}
};
}
return false;
}
case "contains":
case "doesnotcontain":
case "beginswith":
case "doesnotbeginwith":
case "endswith":
case "doesnotendwith": {
const valueForScript = escapeSQ(value);
if (!valueForScript) return false;
const script = getTextScript(fieldForScript, operatorLC, valueForScript);
return {
bool: {
filter: {
script: {
script
}
}
}
};
}
}
}
switch (operatorLC) {
case "<":
case "<=":
case ">":
case ">=":
return {
range: {
[field]: {
[rangeOperatorMap[operatorLC]]: valueRenderer(value, parseNumbers)
}
}
};
case "=":
return { term: { [field]: valueRenderer(value, parseNumbers) } };
case "!=":
return { bool: { must_not: { term: { [field]: valueRenderer(value, parseNumbers) } } } };
case "null":
return { bool: { must_not: { exists: { field } } } };
case "notnull":
return { exists: { field } };
case "in":
case "notin": {
const valueAsArray = toArray(value).map((v) => valueRenderer(v, parseNumbers));
if (valueAsArray.length > 0) {
const arr = valueAsArray.map((v) => ({ term: { [field]: valueRenderer(v, parseNumbers) } }));
return { bool: operatorLC === "in" ? { should: arr } : { must_not: arr } };
}
return false;
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
let [first, second] = valueAsArray;
if (shouldRenderAsNumber(first, true) && shouldRenderAsNumber(second, true)) {
const firstNum = parseNumber(first, { parseNumbers: true });
const secondNum = parseNumber(second, { parseNumbers: true });
if (!preserveValueOrder && secondNum < firstNum) {
const tempNum = secondNum;
second = firstNum;
first = tempNum;
} else {
first = firstNum;
second = secondNum;
}
}
return negateIfNotOp(operatorLC, { range: { [field]: { gte: first, lte: second } } });
}
return false;
}
case "contains":
case "doesnotcontain":
return negateIfNotOp(operatorLC, { regexp: { [field]: { value: `.*${value}.*` } } });
case "beginswith":
case "doesnotbeginwith":
return negateIfNotOp(operatorLC, { regexp: { [field]: { value: `${value}.*` } } });
case "endswith":
case "doesnotendwith":
return negateIfNotOp(operatorLC, { regexp: { [field]: { value: `.*${value}` } } });
}
return false;
};
// src/utils/formatQuery/defaultRuleProcessorJSONata.ts
var shouldNegate3 = (op) => op.startsWith("not") || op.startsWith("doesnot");
var quote = (v, escapeQuotes) => `"${typeof v !== "string" || !escapeQuotes ? v : v.replaceAll(`"`, `\\"`)}"`;
var negate = (clause, negate2) => negate2 ? `$not(${clause})` : `${clause}`;
var escapeStringRegex = (s) => `${s}`.replaceAll(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`).replaceAll("-", String.raw`\x2d`);
var defaultRuleProcessorJSONata = ({ field, operator, value, valueSource }, {
escapeQuotes,
parseNumbers = true,
preserveValueOrder,
quoteFieldNamesWith = ["", ""],
fieldIdentifierSeparator = ""
} = {}) => {
const valueIsField = valueSource === "field";
const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
const qfn = (f) => getQuotedFieldName(f, { quoteFieldNamesWith, fieldIdentifierSeparator });
const operatorLC = operator.toLowerCase();
switch (operatorLC) {
case "<":
case "<=":
case "=":
case "!=":
case ">":
case ">=":
return `${qfn(field)} ${operatorLC} ${valueIsField ? qfn(trimIfString(value)) : useBareValue ? trimIfString(value) : quote(value, escapeQuotes)}`;
case "contains":
case "doesnotcontain":
return negate(
`$contains(${qfn(field)}, ${valueIsField ? qfn(trimIfString(value)) : quote(value, escapeQuotes)})`,
shouldNegate3(operatorLC)
);
case "beginswith":
case "doesnotbeginwith":
return negate(
valueIsField ? `$substring(${qfn(field)}, 0, $length(${qfn(trimIfString(value))})) = ${qfn(trimIfString(value))}` : `$contains(${qfn(field)}, /^${escapeStringRegex(value)}/)`,
shouldNegate3(operatorLC)
);
case "endswith":
case "doesnotendwith":
return negate(
valueIsField ? `$substring(${qfn(field)}, $length(${qfn(field)}) - $length(${qfn(trimIfString(value))})) = ${qfn(trimIfString(value))}` : `$contains(${qfn(field)}, /${escapeStringRegex(value)}$/)`,
shouldNegate3(operatorLC)
);
case "null":
return `${qfn(field)} = null`;
case "notnull":
return `${qfn(field)} != null`;
case "in":
case "notin": {
const valueAsArray = toArray(value);
return negate(
`${qfn(field)} in [${valueAsArray.map(
(val) => valueIsField ? `${qfn(trimIfString(val))}` : shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : quote(val, escapeQuotes)
).join(", ")}]`,
shouldNegate3(operatorLC)
);
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length < 2 || nullOrUndefinedOrEmpty(valueAsArray[0]) || nullOrUndefinedOrEmpty(valueAsArray[1])) {
return "";
}
const [first, second] = valueAsArray;
const firstNum = shouldRenderAsNumber(first, true) ? parseNumber(first, { parseNumbers: true }) : NaN;
const secondNum = shouldRenderAsNumber(second, true) ? parseNumber(second, { parseNumbers: true }) : NaN;
let firstValue = isNaN(firstNum) ? valueIsField ? `${first}` : first : firstNum;
let secondValue = isNaN(secondNum) ? valueIsField ? `${second}` : second : secondNum;
if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
const tempNum = secondNum;
secondValue = firstNum;
firstValue = tempNum;
}
const renderAsNumbers = shouldRenderAsNumber(first, parseNumbers) && shouldRenderAsNumber(second, parseNumbers);
const expression = `${qfn(field)} >= ${valueIsField ? qfn(first) : renderAsNumbers ? firstValue : quote(firstValue, escapeQuotes)} and ${qfn(field)} <= ${valueIsField ? qfn(second) : renderAsNumbers ? secondValue : quote(secondValue, escapeQuotes)}`;
return operatorLC === "between" ? `(${expression})` : negate(expression, true);
}
}
return "";
};
// src/utils/formatQuery/defaultRuleProcessorJsonLogic.ts
var convertOperator = (op) => op.replace(/^(=)$/, "$1=").replace(/^notnull$/i, "!=").replace(/^null$/i, "==");
var negateIfNotOp2 = (op, jsonRule) => op.startsWith("not") || op.startsWith("doesnot") ? { "!": jsonRule } : jsonRule;
var defaultRuleProcessorJsonLogic = ({ field, operator, value, valueSource }, { parseNumbers, preserveValueOrder } = {}) => {
const valueIsField = valueSource === "field";
const fieldObject = { var: field };
const fieldOrNumberRenderer = (v) => valueIsField ? { var: `${v}` } : shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
const operatorLC = operator.toLowerCase();
switch (operatorLC) {
case "<":
case "<=":
case "=":
case "!=":
case ">":
case ">=":
return {
[convertOperator(operatorLC)]: [fieldObject, fieldOrNumberRenderer(value)]
};
case "null":
case "notnull": {
return {
[`${operatorLC === "notnull" ? "!" : "="}=`]: [fieldObject, null]
};
}
case "in":
case "notin": {
const valueAsArray = toArray(value).map((v) => fieldOrNumberRenderer(v));
return negateIfNotOp2(operatorLC, { in: [fieldObject, valueAsArray] });
}
case "between":
case "notbetween": {
const valueAsArray = toArray(value);
if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
let [first, second] = valueAsArray;
if (!valueIsField && shouldRenderAsNumber(first, true) && shouldRenderAsNumber(second, true)) {
const firstNum = parseNumber(first, { parseNumbers: true });
const secondNum = parseNumber(second, { parseNumbers: true });
if (!preserveValueOrder && secondNum < firstNum) {
const tempNum = secondNum;
second = firstNum;
first = tempNum;
} else {
first = firstNum;
second = secondNum;
}
} else if (valueIsField) {
first = { var: first };
second = { var: second };
}
const jsonRule = { "<=": [first, fieldObject, second] };
return negateIfNotOp2(operatorLC, jsonRule);
}
return false;
}
case "contains":
case "doesnotcontain": {
const jsonRule = {
in: [fieldOrNumberRenderer(value), fieldObject]
};
return negateIfNotOp2(operatorLC, jsonRule);
}
case "beginswith":
case "doesnotbeginwith": {
const jsonRule = {
startsWith: [fieldObject, fieldOrNumberRenderer(value)]
};
return negateIfNotOp2(operatorLC, jsonRule);
}
case "endswith":
case "doesnotendwith": {
const jsonRule = {
endsWith: [fieldObject, fieldOrNumberRenderer(value)]
};
return negateIfNotOp2(operatorLC, jsonRule);
}
}
return false;
};
// src/utils/formatQuery/defaultValueProcessorNL.ts
var escapeStringValueQuotes2 = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : (
/* istanbul ignore next */
v
);
var defaultValueProcessorNL = (rule, opts = {}) => {
const {
escapeQuotes,
fields,
parseNumbers,
quoteFieldNamesWith,
quoteValuesWith,
fieldIdentifierSeparator,
translations
} = opts;
const valueIsField = rule.valueSource === "field";
const operatorLowerCase = rule.operator.toLowerCase();
const quoteChar = quoteValuesWith || /* istanbul ignore next */
"'";
const quoteValue = (v) => `${quoteChar}${v}${quoteChar}`;
const escapeValue = (v) => escapeStringValueQuotes2(v, quoteChar, escapeQuotes);
const wrapAndEscape = (v) => quoteValue(escapeValue(v));
const wrapFieldName = (v) => getQuotedFieldName(v, { quoteFieldNamesWith, fieldIdentifierSeparator });
const t = translations ?? /* istanbul ignore next */
{};
const orTL = t.or ?? "or";
const trueTL = t.true ?? "true";
const falseTL = t.false ?? "false";
switch (operatorLowerCase) {
case "null":
case "notnull": {
return "";
}
case "between":
case "notbetween": {
if (!valueIsField) {
return defaultValueProcessorByRule(rule, opts);
}
const valueAsArray = toArray(rule.value, { retainEmptyStrings: true }).slice(0, 2).map(
(v) => wrapFieldName(
getOption(fields ?? /* istanbul ignore next */
[], v)?.label ?? v
)
);
if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) {
return "";
}
return defaultValueProcessorByRule({ ...rule, value: valueAsArray }, opts);
}
case "in":
case "notin": {
const valueAsArray = toArray(rule.value);
if (valueAsArray.length === 0) return "";
const valStringArray = valueAsArray.map(
(v) => valueIsField ? wrapFieldName(
getOption(fields ?? /* istanbul ignore next */
[], v)?.label ?? v
) : shouldRenderAsNumber(v, parseNumbers) ? `${trimIfString(v)}` : `${wrapAndEscape(v)}`
);
return `${valStringArray.slice(0, -1).join(", ")}${valStringArray.length > 2 ? "," : ""} ${orTL} ${valStringArray.at(-1)}`;
}
}
if (typeof rule.value === "boolean") {
return rule.value ? trueTL : falseTL;
}
return valueIsField ? wrapFieldName(
getOption(fields ?? /* istanbul ignore next */
[], rule.value)?.label ?? rule.value
) : shouldRenderAsNumber(rule.value, parseNumbers) ? `${trimIfString(rule.value)}` : `${wrapAndEscape(rule.value)}`;
};
// src/utils/formatQuery/defaultRuleProcessorNL.ts
var defaultExportOperatorMap = {
"=": ["is", "is the same as the value in"],
"!=": ["is not", "is not the same as the value in"],
"<": ["is less than", "is less than the value in"],
">": ["is greater than", "is greater than the value in"],
"<=": ["is less than or equal to", "is less than or equal to the value in"],
">=": ["is greater than or equal to", "is greater than or equal to the value in"],
contains: ["contains", "contains the value in"],
beginswith: ["starts with", "starts with the value in"],
endswith: ["ends with", "ends with the value in"],
doesnotcontain: ["does not contain", "does not contain the value in"],
doesnotbeginwith: ["does not start with", "does not start with the value in"],
doesnotendwith: ["does not end with", "does not end with the value in"],
null: "is null",
notnull: "is not null",
in: ["is one of the values", "is the same as a value in"],
notin: ["is not one of the values", "is not the same as any value in"],
between: ["is between", "is between the values in"],
notbetween: ["is not between", "is not between the values in"]
};
var defaultGetOperators = () => [];
var defaultOperatorProcessorNL = (rule, opts = {}) => {
const { valueSource = "value" } = rule;
const {
getOperators = defaultGetOperators,
operatorMap: operatorMapParam = defaultExportOperatorMap
} = opts;
const mapOperatorMap = new Map(
Object.entries(defaultExportOperatorMap)
);
for (const [key, value] of Object.entries(operatorMapParam)) {
mapOperatorMap.set(key.toLowerCase(), value);
}
const operatorMap = Object.fromEntries(mapOperatorMap);
const { value: operator, label } = getOption(
toFullOptionList(
getOperators(rule.field, {
fieldData: opts.fieldData ?? {
name: rule.field,
value: rule.field,
label: rule.field
}
}) ?? /* istanbul ignore next */
[]
),
rule.operator
) ?? {
name: rule.operator,
value: rule.operator,
label: rule.operator
};
const operatorTL = operatorMap[operator] ?? operatorMap[operator.toLowerCase()] ?? [label, label];
return typeof operatorTL === "string" ? operatorTL : operatorTL[valueSource === "field" ? 1 : 0];
};
var defaultRuleProcessorNL = (rule, opts) => {
const {
fieldData,
quoteFieldNamesWith = ["", ""],
fieldIdentifierSeparator = "",
quoteValuesWith = `'`,
operatorProcessor = defaultOperatorProcessorNL,
valueProcessor = defaultValueProcessorNL,
concatOperator = "||",
wordOrder = "SVO"
} = opts ?? /* istanbul ignore next */
{};
const value = valueProcessor(rule, {
...opts,
quoteFieldNamesWith,
fieldIdentifierSeparator,
quoteValuesWith,
concatOperator
});
const operatorLC = rule.operator.toLowerCase();
if ((operatorLC === "in" || operatorLC === "notin" || operatorLC === "between" || operatorLC === "notbetween") && !value) {
return "";
}
const processedField = getQuotedFieldName(fieldData?.label ?? rule.field, {
quoteFieldNamesWith,
fieldIdentifierSeparator
});
const processedOperator = operatorProcessor(rule, opts);
const wordOrderMap = {
S: processedField,
V: processedOperator,
O: value
};
return normalizeConstituentWordOrder(wordOrder).map((term) => `${wordOrderMap[term]}`).join(" ").trim();
};
// src/utils/formatQuery/defaultRuleProcessorSQL.ts
var defaultOperatorProcessorSQL = (rule) => mapSQLOperator(rule.operator).toLowerCase();
var defaultRuleProcessorSQL = (rule, opts = {}) => {
const {
quoteFieldNamesWith = ["", ""],
fieldIdentifierSeparator = "",
quoteValuesWith = `'`,
operatorProcessor = defaultOperatorProcessorSQL,
valueProcessor = defaultValueProcessorByRule,
concatOperator = "||"
} = opts;
const value = valueProcessor(rule, {
...opts,
quoteFieldNamesWith,
fieldIdentifierSeparator,
quoteValuesWith,
concatOperator
});
const operator = operatorProcessor(rule, opts);
const operatorLowerCase = operator.toLowerCase();
if ((operatorLowerCase === "in" || operatorLowerCase === "not in" || operatorLowerCase === "between" || operatorLowerCase === "not between") && !value) {
return "";
}
return `${getQuotedFieldName(rule.field, { quoteFieldNamesWith, fieldIdentifierSeparator })} ${operator} ${value}`.trim();
};
// src/utils/formatQuery/defaultRuleProcessorParameterized.ts
var defaultRuleProcessorParameterized = (rule, opts, meta) => {
const {
fieldData,
format,
getNextNamedParam,
parseNumbers,
paramPrefix,
paramsKeepPrefix,
numberedParams,
quoteFieldNamesWith = ["", ""],
concatOperator,
operatorProcessor = defaultOperatorProcessorSQL,
valueProcessor = defaultValueProcessorByRule
} = opts ?? {};
const { processedParams = [] } = meta ?? {};
const parameterized = format === "parameterized";
const params = [];
const paramsNamed = {};
const finalize = (sql) => parameterized ? { sql, params } : { sql, params: paramsNamed };
const value = valueProcessor(rule, {
parseNumbers,
quoteFieldNamesWith,
concatOperator,
fieldData,
format
});
const sqlOperator = operatorProcessor(rule, opts);
const sqlOperatorLowerCase = sqlOperator.toLowerCase();
const [qPre, qPost] = quoteFieldNamesWith;
if ((sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in" || sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") && !value) {
return finalize("");
} else if (sqlOperatorLowerCase === "is null" || sqlOperatorLowerCase === "is not null") {
return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator}`);
} else if (rule.valueSource === "field") {
return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${value}`.trim());
} else if (sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in") {
const splitValue = toArray(rule.value);
if (parameterized) {
for (const v of splitValue) {
params.push(shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v);
}
return finalize(
`${qPre}${rule.field}${qPost} ${sqlOperator} (${splitValue.map(
(_v, i) => numberedParams ? `${paramPrefix}${processedParams.length + 1 + splitValue.length - (splitValue.length - i)}` : "?"
).join(", ")})`
);
}
const inParams = [];
for (const v of splitValue) {
const thisParamName = getNextNamedParam(rule.field)