@react-querybuilder/core 8.14.4 → 8.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +114 -53
  2. package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +288 -22
  3. package/dist/cjs/react-querybuilder_core.cjs.development.js +796 -77
  4. package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -1
  5. package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +288 -22
  6. package/dist/cjs/react-querybuilder_core.cjs.production.js +1 -1
  7. package/dist/cjs/react-querybuilder_core.cjs.production.js.map +1 -1
  8. package/dist/{convertQuery-CeJSNn37.mjs → convertQuery-BeJJH9BI.mjs} +2 -2
  9. package/dist/convertQuery-BeJJH9BI.mjs.map +1 -0
  10. package/dist/{convertQuery-J8LpTG-7.js → convertQuery-Lx2HQa0m.js} +2 -2
  11. package/dist/convertQuery-Lx2HQa0m.js.map +1 -0
  12. package/dist/formatQuery.d.mts +89 -2
  13. package/dist/formatQuery.d.ts +89 -2
  14. package/dist/formatQuery.js +775 -66
  15. package/dist/formatQuery.js.map +1 -1
  16. package/dist/formatQuery.mjs +768 -67
  17. package/dist/formatQuery.mjs.map +1 -1
  18. package/dist/{import-BwQqExpO.d.mts → import-BHlzBLM_.d.mts} +2 -2
  19. package/dist/{import-CrJf23Nf.d.ts → import-C6imciDf.d.ts} +2 -2
  20. package/dist/{index-CYT4Saz-.d.mts → index-Cjapnb-H.d.ts} +161 -10
  21. package/dist/{index-DBlQeLax.d.ts → index-D-Iej37L.d.mts} +161 -10
  22. package/dist/{objectUtils-ButT0Mng.js → objectUtils-Bzug_QfX.js} +2 -2
  23. package/dist/objectUtils-Bzug_QfX.js.map +1 -0
  24. package/dist/{objectUtils-C0WB-8ex.mjs → objectUtils-D96eEEzL.mjs} +2 -2
  25. package/dist/objectUtils-D96eEEzL.mjs.map +1 -0
  26. package/dist/parseCEL.d.mts +2 -2
  27. package/dist/parseCEL.d.ts +2 -2
  28. package/dist/parseCEL.js +35 -35
  29. package/dist/parseCEL.js.map +1 -1
  30. package/dist/parseCEL.mjs +35 -35
  31. package/dist/parseCEL.mjs.map +1 -1
  32. package/dist/parseCypher.d.mts +49 -0
  33. package/dist/parseCypher.d.ts +49 -0
  34. package/dist/parseCypher.js +578 -0
  35. package/dist/parseCypher.js.map +1 -0
  36. package/dist/parseCypher.mjs +575 -0
  37. package/dist/parseCypher.mjs.map +1 -0
  38. package/dist/parseGremlin.d.mts +35 -0
  39. package/dist/parseGremlin.d.ts +35 -0
  40. package/dist/parseGremlin.js +192 -0
  41. package/dist/parseGremlin.js.map +1 -0
  42. package/dist/parseGremlin.mjs +191 -0
  43. package/dist/parseGremlin.mjs.map +1 -0
  44. package/dist/parseJSONata.d.mts +2 -2
  45. package/dist/parseJSONata.d.ts +2 -2
  46. package/dist/parseJSONata.js +11 -11
  47. package/dist/parseJSONata.js.map +1 -1
  48. package/dist/parseJSONata.mjs +11 -11
  49. package/dist/parseJSONata.mjs.map +1 -1
  50. package/dist/parseJsonLogic.d.mts +2 -2
  51. package/dist/parseJsonLogic.d.ts +2 -2
  52. package/dist/parseJsonLogic.js +6 -6
  53. package/dist/parseJsonLogic.js.map +1 -1
  54. package/dist/parseJsonLogic.mjs +6 -6
  55. package/dist/parseJsonLogic.mjs.map +1 -1
  56. package/dist/parseMongoDB.d.mts +2 -2
  57. package/dist/parseMongoDB.d.ts +2 -2
  58. package/dist/parseMongoDB.js +6 -6
  59. package/dist/parseMongoDB.js.map +1 -1
  60. package/dist/parseMongoDB.mjs +6 -6
  61. package/dist/parseMongoDB.mjs.map +1 -1
  62. package/dist/parseSPARQL.d.mts +34 -0
  63. package/dist/parseSPARQL.d.ts +34 -0
  64. package/dist/parseSPARQL.js +253 -0
  65. package/dist/parseSPARQL.js.map +1 -0
  66. package/dist/parseSPARQL.mjs +251 -0
  67. package/dist/parseSPARQL.mjs.map +1 -0
  68. package/dist/parseSQL.d.mts +2 -2
  69. package/dist/parseSQL.d.ts +2 -2
  70. package/dist/parseSQL.js +16 -16
  71. package/dist/parseSQL.js.map +1 -1
  72. package/dist/parseSQL.mjs +16 -16
  73. package/dist/parseSQL.mjs.map +1 -1
  74. package/dist/parseSpEL.d.mts +2 -2
  75. package/dist/parseSpEL.d.ts +2 -2
  76. package/dist/parseSpEL.js +10 -10
  77. package/dist/parseSpEL.js.map +1 -1
  78. package/dist/parseSpEL.mjs +10 -10
  79. package/dist/parseSpEL.mjs.map +1 -1
  80. package/dist/{prepareQueryObjects-DO3qXriW.js → prepareQueryObjects-BoG5Rt8z.js} +6 -6
  81. package/dist/prepareQueryObjects-BoG5Rt8z.js.map +1 -0
  82. package/dist/{prepareQueryObjects-BfMlS4ql.mjs → prepareQueryObjects-uA10ZpZX.mjs} +6 -6
  83. package/dist/prepareQueryObjects-uA10ZpZX.mjs.map +1 -0
  84. package/dist/query-builder.css +1 -1
  85. package/dist/query-builder.css.map +1 -1
  86. package/dist/react-querybuilder_core.d.mts +288 -22
  87. package/dist/react-querybuilder_core.legacy-esm.d.ts +288 -22
  88. package/dist/react-querybuilder_core.legacy-esm.js +833 -108
  89. package/dist/react-querybuilder_core.legacy-esm.js.map +1 -1
  90. package/dist/react-querybuilder_core.mjs +788 -78
  91. package/dist/react-querybuilder_core.mjs.map +1 -1
  92. package/dist/react-querybuilder_core.production.d.mts +288 -22
  93. package/dist/react-querybuilder_core.production.mjs +1 -1
  94. package/dist/react-querybuilder_core.production.mjs.map +1 -1
  95. package/dist/styles/_main.scss +4 -0
  96. package/dist/transformQuery.d.mts +1 -1
  97. package/dist/transformQuery.d.ts +1 -1
  98. package/dist/transformQuery.js +1 -1
  99. package/dist/transformQuery.mjs +1 -1
  100. package/dist/{utils-BlMGIhvx.mjs → utils-ChLG90DP.mjs} +3 -3
  101. package/dist/utils-ChLG90DP.mjs.map +1 -0
  102. package/dist/{utils-CZRhzje-.js → utils-Qwkq2Q0F.js} +3 -3
  103. package/dist/utils-Qwkq2Q0F.js.map +1 -0
  104. package/formatQuery/package.json +1 -1
  105. package/package.json +53 -14
  106. package/parseCEL/package.json +1 -1
  107. package/parseCypher/package.json +4 -0
  108. package/parseGremlin/package.json +4 -0
  109. package/parseJSONata/package.json +1 -1
  110. package/parseJsonLogic/package.json +1 -1
  111. package/parseMongoDB/package.json +1 -1
  112. package/parseSPARQL/package.json +4 -0
  113. package/parseSQL/package.json +1 -1
  114. package/parseSpEL/package.json +1 -1
  115. package/transformQuery/package.json +1 -1
  116. package/dist/convertQuery-CeJSNn37.mjs.map +0 -1
  117. package/dist/convertQuery-J8LpTG-7.js.map +0 -1
  118. package/dist/objectUtils-ButT0Mng.js.map +0 -1
  119. package/dist/objectUtils-C0WB-8ex.mjs.map +0 -1
  120. package/dist/prepareQueryObjects-BfMlS4ql.mjs.map +0 -1
  121. package/dist/prepareQueryObjects-DO3qXriW.js.map +0 -1
  122. package/dist/utils-BlMGIhvx.mjs.map +0 -1
  123. package/dist/utils-CZRhzje-.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { D as toArray, O as trimIfString, S as toFlatOptionArray, T as parseNumber, _ as shouldRenderAsNumber, a as getNLTranslataion, c as isValidValue, d as mapSQLOperator, f as mongoOperators, g as processMatchMode, h as prismaOperators, i as defaultNLTranslations, l as isValueProcessorLegacy, m as numerifyValues, n as bigIntJsonStringifyReplacer, o as getQuoteFieldNamesWithArray, p as normalizeConstituentWordOrder, r as celCombinatorMap, s as getQuotedFieldName, t as bigIntJsonParseReviver, u as jsonLogicAdditionalOperators, v as getParseNumberMethod, w as toFullOptionList, y as getOption } from "./utils-BlMGIhvx.mjs";
2
- import { a as isRuleGroupTypeIC, c as nullOrUndefinedOrEmpty, i as isRuleGroupType, o as isPojo, r as isRuleGroup, s as lc } from "./objectUtils-C0WB-8ex.mjs";
1
+ import { D as toArray, O as trimIfString, S as toFlatOptionArray, T as parseNumber, _ as shouldRenderAsNumber, a as getNLTranslataion, c as isValidValue, d as mapSQLOperator, f as mongoOperators, g as processMatchMode, h as prismaOperators, i as defaultNLTranslations, l as isValueProcessorLegacy, m as numerifyValues, n as bigIntJsonStringifyReplacer, o as getQuoteFieldNamesWithArray, p as normalizeConstituentWordOrder, r as celCombinatorMap, s as getQuotedFieldName, t as bigIntJsonParseReviver, u as jsonLogicAdditionalOperators, v as getParseNumberMethod, w as toFullOptionList, y as getOption } from "./utils-ChLG90DP.mjs";
2
+ import { a as isRuleGroupTypeIC, c as nullOrUndefinedOrEmpty, i as isRuleGroupType, l as numericRegex, o as isPojo, r as isRuleGroup, s as lc } from "./objectUtils-D96eEEzL.mjs";
3
3
  import { transformQuery } from "./transformQuery.mjs";
4
- import { t as convertFromIC } from "./convertQuery-CeJSNn37.mjs";
4
+ import { t as convertFromIC } from "./convertQuery-BeJJH9BI.mjs";
5
5
  //#region src/utils/isRuleOrGroupValid.ts
6
6
  /**
7
7
  * Determines if an object is useful as a validation result.
@@ -19,7 +19,7 @@ const isRuleOrGroupValid = (rg, validationResult, validator) => {
19
19
  if (typeof validator === "function" && !isRuleGroup(rg)) {
20
20
  const vr = validator(rg);
21
21
  if (typeof vr === "boolean") return vr;
22
- // istanbul ignore else
22
+ // v8 ignore else
23
23
  if (isValidationResult(vr)) return vr.valid;
24
24
  }
25
25
  return true;
@@ -82,7 +82,7 @@ const defaultRuleGroupProcessorCEL = (ruleGroup, options) => {
82
82
  //#endregion
83
83
  //#region src/utils/formatQuery/defaultRuleProcessorCEL.ts
84
84
  const shouldNegate$2 = (op) => op.startsWith("not") || op.startsWith("doesnot");
85
- const escapeDoubleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`);
85
+ const escapeDoubleQuotes$1 = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`);
86
86
  /**
87
87
  * Default rule processor used by {@link formatQuery} for "cel" format.
88
88
  *
@@ -124,19 +124,19 @@ const defaultRuleProcessorCEL = (rule, opts = {}) => {
124
124
  case "==":
125
125
  case "!=":
126
126
  case ">":
127
- case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`}`;
127
+ case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `"${escapeDoubleQuotes$1(value, escapeQuotes)}"`}`;
128
128
  case "contains":
129
- case "doesnotcontain": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.contains(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
129
+ case "doesnotcontain": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.contains(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes$1(value, escapeQuotes)}"`})`;
130
130
  case "beginswith":
131
- case "doesnotbeginwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.startsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
131
+ case "doesnotbeginwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.startsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes$1(value, escapeQuotes)}"`})`;
132
132
  case "endswith":
133
- case "doesnotendwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.endsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
133
+ case "doesnotendwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.endsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes$1(value, escapeQuotes)}"`})`;
134
134
  case "null": return `${field} == null`;
135
135
  case "notnull": return `${field} != null`;
136
136
  case "in":
137
137
  case "notin": {
138
138
  const [prefix, suffix] = shouldNegate$2(operatorTL) ? ["!(", ")"] : ["", ""];
139
- return `${prefix}${field} in [${toArray(value).map((val) => valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `"${escapeDoubleQuotes(val, escapeQuotes)}"`).join(", ")}]${suffix}`;
139
+ return `${prefix}${field} in [${toArray(value).map((val) => valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `"${escapeDoubleQuotes$1(val, escapeQuotes)}"`).join(", ")}]${suffix}`;
140
140
  }
141
141
  case "between":
142
142
  case "notbetween": {
@@ -146,8 +146,8 @@ const defaultRuleProcessorCEL = (rule, opts = {}) => {
146
146
  const shouldParseNumbers = !(parseNumbers === false);
147
147
  const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
148
148
  const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
149
- let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `"${escapeDoubleQuotes(first, escapeQuotes)}"` : firstNum;
150
- let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `"${escapeDoubleQuotes(second, escapeQuotes)}"` : secondNum;
149
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `"${escapeDoubleQuotes$1(first, escapeQuotes)}"` : firstNum;
150
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `"${escapeDoubleQuotes$1(second, escapeQuotes)}"` : secondNum;
151
151
  if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
152
152
  const tempNum = secondNum;
153
153
  secondValue = firstNum;
@@ -403,7 +403,7 @@ const defaultRuleGroupProcessorSpEL = (ruleGroup, options) => {
403
403
  //#region src/utils/formatQuery/defaultRuleProcessorSpEL.ts
404
404
  const shouldNegate$1 = (op) => op.startsWith("not") || op.startsWith("doesnot");
405
405
  const wrapInNegation = (clause, negate) => negate ? `!(${clause})` : clause;
406
- const escapeSingleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`'`, `\\'`);
406
+ const escapeSingleQuotes$2 = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`'`, `\\'`);
407
407
  /**
408
408
  * Default rule processor used by {@link formatQuery} for "spel" format.
409
409
  *
@@ -444,20 +444,20 @@ const defaultRuleProcessorSpEL = (rule, opts = {}) => {
444
444
  case "==":
445
445
  case "!=":
446
446
  case ">":
447
- case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`;
447
+ case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes$2(value, escapeQuotes)}'`}`;
448
448
  case "contains":
449
- case "doesnotcontain": return wrapInNegation(`${field} matches ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
449
+ case "doesnotcontain": return wrapInNegation(`${field} matches ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes$2(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
450
450
  case "beginswith":
451
- case "doesnotbeginwith": return wrapInNegation(`${field} matches ${valueIsField ? `'^'.concat(${trimIfString(value)})` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
451
+ case "doesnotbeginwith": return wrapInNegation(`${field} matches ${valueIsField ? `'^'.concat(${trimIfString(value)})` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes$2(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
452
452
  case "endswith":
453
- case "doesnotendwith": return wrapInNegation(`${field} matches ${valueIsField ? `${trimIfString(value)}.concat('$')` : `'${escapeSingleQuotes(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`}`, shouldNegate$1(operatorTL));
453
+ case "doesnotendwith": return wrapInNegation(`${field} matches ${valueIsField ? `${trimIfString(value)}.concat('$')` : `'${escapeSingleQuotes$2(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`}`, shouldNegate$1(operatorTL));
454
454
  case "null": return `${field} == null`;
455
455
  case "notnull": return `${field} != null`;
456
456
  case "in":
457
457
  case "notin": {
458
458
  const negate = shouldNegate$1(operatorTL) ? "!" : "";
459
459
  const valueAsArray = toArray(value);
460
- return valueAsArray.length > 0 ? `${negate}(${valueAsArray.map((val) => `${field} == ${valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `'${escapeSingleQuotes(val, escapeQuotes)}'`}`).join(" or ")})` : "";
460
+ return valueAsArray.length > 0 ? `${negate}(${valueAsArray.map((val) => `${field} == ${valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `'${escapeSingleQuotes$2(val, escapeQuotes)}'`}`).join(" or ")})` : "";
461
461
  }
462
462
  case "between":
463
463
  case "notbetween": {
@@ -467,8 +467,8 @@ const defaultRuleProcessorSpEL = (rule, opts = {}) => {
467
467
  const shouldParseNumbers = !(parseNumbers === false);
468
468
  const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
469
469
  const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
470
- let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `'${escapeSingleQuotes(first, escapeQuotes)}'` : firstNum;
471
- let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `'${escapeSingleQuotes(second, escapeQuotes)}'` : secondNum;
470
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `'${escapeSingleQuotes$2(first, escapeQuotes)}'` : firstNum;
471
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `'${escapeSingleQuotes$2(second, escapeQuotes)}'` : secondNum;
472
472
  if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
473
473
  const tempNum = secondNum;
474
474
  secondValue = firstNum;
@@ -536,6 +536,70 @@ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQ
536
536
  return valueIsField ? wrapFieldName(value) : shouldRenderAsNumber(value, parseNumbers) ? `${trimIfString(value)}` : `${wrapAndEscape(value)}`;
537
537
  };
538
538
  //#endregion
539
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorCypher.ts
540
+ /**
541
+ * Maps a {@link DefaultCombinatorName} to a Cypher combinator keyword.
542
+ *
543
+ * @group Export
544
+ */
545
+ const cypherCombinatorMap = {
546
+ and: "AND",
547
+ or: "OR"
548
+ };
549
+ /**
550
+ * Rule group processor used by {@link formatQuery} for "cypher" and "gql" formats.
551
+ *
552
+ * @group Export
553
+ */
554
+ const defaultRuleGroupProcessorCypher = (ruleGroup, options) => {
555
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
556
+ const processRuleGroup = (rg, outermost) => {
557
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
558
+ const processedRules = [];
559
+ let precedingCombinator = "";
560
+ let firstRule = true;
561
+ for (const rule of rg.rules) {
562
+ if (typeof rule === "string") {
563
+ precedingCombinator = cypherCombinatorMap[rule];
564
+ continue;
565
+ }
566
+ if (isRuleGroup(rule)) {
567
+ const processedGroup = processRuleGroup(rule);
568
+ if (processedGroup) {
569
+ if (!firstRule && precedingCombinator) {
570
+ processedRules.push(precedingCombinator);
571
+ precedingCombinator = "";
572
+ }
573
+ firstRule = false;
574
+ processedRules.push(processedGroup);
575
+ }
576
+ continue;
577
+ }
578
+ const [validationResult, fieldValidator] = validateRule(rule);
579
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
580
+ const fieldData = getOption(fields, rule.field);
581
+ const processedRule = ruleProcessor(rule, {
582
+ ...options,
583
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
584
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
585
+ fieldData
586
+ });
587
+ if (processedRule) {
588
+ if (!firstRule && precedingCombinator) {
589
+ processedRules.push(precedingCombinator);
590
+ precedingCombinator = "";
591
+ }
592
+ firstRule = false;
593
+ processedRules.push(processedRule);
594
+ }
595
+ }
596
+ const expression = processedRules.join(isRuleGroupType(rg) ? ` ${cypherCombinatorMap[rg.combinator]} ` : " ");
597
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "NOT " : ""}(`, ")"] : ["", ""];
598
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
599
+ };
600
+ return processRuleGroup(ruleGroup, true);
601
+ };
602
+ //#endregion
539
603
  //#region src/utils/formatQuery/defaultRuleProcessorDrizzle.ts
540
604
  /**
541
605
  * Default rule processor used by {@link formatQuery} for the "drizzle" format.
@@ -543,22 +607,22 @@ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQ
543
607
  * @group Export
544
608
  */
545
609
  const defaultRuleProcessorDrizzle = (rule, _options) => {
546
- const opts = _options ?? ( /* istanbul ignore next */ {});
547
- // istanbul ignore next
610
+ const opts = _options ?? ( /* v8 ignore start -- @preserve */ {});
611
+ // v8 ignore next
548
612
  const { parseNumbers, preserveValueOrder, context = {} } = opts;
549
613
  const { columns, drizzleOperators, useRawFields } = context;
550
- if (!columns || !drizzleOperators) return;
614
+ if (!columns || !drizzleOperators) return void 0;
551
615
  const { between, eq, gt, gte, inArray, isNotNull, isNull, like, lt, lte, ne, notBetween, notInArray, notLike, sql } = drizzleOperators;
552
616
  const { field, operator, value, valueSource } = rule;
553
617
  const column = useRawFields && /[a-z][a-z0-9]*/i.test(field) ? sql.raw(field) : columns[field];
554
618
  const operatorLC = lc(operator);
555
619
  const valueIsField = valueSource === "field";
556
620
  const asFieldOrValue = (v) => valueIsField ? columns[v] : v;
557
- if (!column) return;
621
+ if (!column) return void 0;
558
622
  const matchEval = processMatchMode(rule);
559
623
  if (matchEval === false) return;
560
624
  else if (matchEval) {
561
- if (opts.preset !== "postgresql") return;
625
+ if (opts.preset !== "postgresql") return void 0;
562
626
  const { mode, threshold } = matchEval;
563
627
  const arrayElementAlias = "elem_alias";
564
628
  const nestedArrayFilter = defaultRuleGroupProcessorDrizzle(transformQuery(rule.value, { ruleProcessor: (r) => ({
@@ -647,7 +711,7 @@ const defaultRuleProcessorDrizzle = (rule, _options) => {
647
711
  */
648
712
  const defaultRuleGroupProcessorDrizzle = (ruleGroup, options, _meta) => (columns, drizzleOperators) => {
649
713
  const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, validateRule, validationMap } = options;
650
- if (!columns || !drizzleOperators) return;
714
+ if (!columns || !drizzleOperators) return void 0;
651
715
  const { and, not, or } = drizzleOperators;
652
716
  const ruleProcessor = defaultRuleProcessorDrizzle;
653
717
  const processRuleGroup = (rg, _outermost) => {
@@ -703,6 +767,67 @@ const defaultRuleGroupProcessorElasticSearch = (ruleGroup, options) => {
703
767
  return processedRuleGroup === false ? {} : processedRuleGroup;
704
768
  };
705
769
  //#endregion
770
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorGremlin.ts
771
+ /**
772
+ * Rule group processor used by {@link formatQuery} for "gremlin" format.
773
+ *
774
+ * At the top level, filter rules produce chained `.has()` steps (implicit AND).
775
+ * Nested groups use `.and()` / `.or()` / `.not()` compound traversals with
776
+ * `__` anonymous traversal prefixes.
777
+ *
778
+ * @group Export
779
+ */
780
+ const defaultRuleGroupProcessorGremlin = (ruleGroup, options) => {
781
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
782
+ const validateAndProcess = (rule) => {
783
+ // v8 ignore next -- @preserve
784
+ if (typeof rule === "string" || isRuleGroup(rule)) return void 0;
785
+ const [validationResult, fieldValidator] = validateRule(rule);
786
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
787
+ const fieldData = getOption(fields, rule.field);
788
+ return ruleProcessor(rule, {
789
+ ...options,
790
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
791
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
792
+ fieldData
793
+ });
794
+ };
795
+ /** Recursively processes a nested group into `.and()`/`.or()`/`.not()` form. */
796
+ const processNested = (rg) => {
797
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return "";
798
+ const predicates = [];
799
+ for (const rule of rg.rules) {
800
+ if (typeof rule === "string") continue;
801
+ if (isRuleGroup(rule)) {
802
+ const nested = processNested(rule);
803
+ if (nested) predicates.push(nested);
804
+ continue;
805
+ }
806
+ const processed = validateAndProcess(rule);
807
+ if (processed) predicates.push(processed);
808
+ }
809
+ if (predicates.length === 0) return "";
810
+ const combinator = rg.combinator ?? "and";
811
+ const prefix = rg.not ? "not" : combinator;
812
+ if (predicates.length === 1 && !rg.not) return predicates[0];
813
+ return `.${prefix}(${predicates.map((p) => p.startsWith(".") ? `__${p}` : p).join(", ")})`;
814
+ };
815
+ if (!isRuleOrGroupValid(ruleGroup, validationMap[ruleGroup.id ?? ""])) return fallbackExpression;
816
+ const steps = [];
817
+ for (const rule of ruleGroup.rules) {
818
+ if (typeof rule === "string") continue;
819
+ if (isRuleGroup(rule)) {
820
+ const compound = processNested(rule);
821
+ if (compound) steps.push(compound);
822
+ continue;
823
+ }
824
+ const processed = validateAndProcess(rule);
825
+ if (processed) steps.push(processed);
826
+ }
827
+ if (steps.length === 0) return fallbackExpression;
828
+ return steps.join("");
829
+ };
830
+ //#endregion
706
831
  //#region src/utils/formatQuery/defaultRuleGroupProcessorJSONata.ts
707
832
  /**
708
833
  * Rule group processor used by {@link formatQuery} for "jsonata" format.
@@ -866,7 +991,7 @@ const defaultRuleGroupProcessorMongoDB = (ruleGroup, options, meta) => {
866
991
  const defaultRuleGroupProcessorNL = (ruleGroup, options) => {
867
992
  const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, translations, validateRule, validationMap } = options;
868
993
  const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
869
- if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
994
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : /* v8 ignore next -- @preserve */ "";
870
995
  const rg2 = isRuleGroupTypeIC(rg) && rg.rules.some((r) => typeof r === "string" && lc(r) === "xor") ? convertFromIC(rg) : rg;
871
996
  const processedRules = [];
872
997
  let precedingCombinator = "";
@@ -878,7 +1003,7 @@ const defaultRuleGroupProcessorNL = (ruleGroup, options) => {
878
1003
  }
879
1004
  if (isRuleGroup(rule)) {
880
1005
  const processedGroup = processRuleGroup(rule, rg2.rules.length === 1 && !(rg2.not || /^xor$/i.test(rg2.combinator ?? "")));
881
- // istanbul ignore else
1006
+ // v8 ignore else
882
1007
  if (processedGroup) {
883
1008
  if (!firstRule && precedingCombinator) {
884
1009
  processedRules.push(precedingCombinator);
@@ -954,7 +1079,7 @@ const defaultRuleGroupProcessorParameterized = (ruleGroup, options) => {
954
1079
  if (!isPojo(processedRule)) return "";
955
1080
  const { sql, params: customParams } = processedRule;
956
1081
  if (typeof sql !== "string" || !sql) return "";
957
- // istanbul ignore else
1082
+ // v8 ignore else
958
1083
  if (format === "parameterized" && Array.isArray(customParams)) params.push(...customParams);
959
1084
  else if (format === "parameterized_named" && isPojo(customParams)) {
960
1085
  Object.assign(paramsNamed, customParams);
@@ -963,7 +1088,7 @@ const defaultRuleGroupProcessorParameterized = (ruleGroup, options) => {
963
1088
  return sql;
964
1089
  };
965
1090
  const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
966
- if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
1091
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : /* v8 ignore next -- @preserve */ "";
967
1092
  const processedRules = [];
968
1093
  let precedingCombinator = "";
969
1094
  let firstRule = true;
@@ -974,7 +1099,7 @@ const defaultRuleGroupProcessorParameterized = (ruleGroup, options) => {
974
1099
  }
975
1100
  if (isRuleGroup(rule)) {
976
1101
  const processedGroup = processRuleGroup(rule, rg.rules.length === 1);
977
- // istanbul ignore else
1102
+ // v8 ignore else
978
1103
  if (processedGroup) {
979
1104
  if (!firstRule && precedingCombinator) {
980
1105
  processedRules.push(precedingCombinator);
@@ -1057,10 +1182,10 @@ const defaultRuleGroupProcessorPrisma = (ruleGroup, options) => {
1057
1182
  * @group Export
1058
1183
  */
1059
1184
  const defaultRuleGroupProcessorSequelize = (ruleGroup, options) => {
1060
- // istanbul ignore next
1185
+ // v8 ignore next
1061
1186
  const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap, context = {} } = options;
1062
1187
  const { sequelizeOperators: Op } = context;
1063
- if (!Op) return;
1188
+ if (!Op) return void 0;
1064
1189
  const processRuleGroup = (rg, _outermost) => {
1065
1190
  if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return;
1066
1191
  const combinator = rg.combinator.toUpperCase();
@@ -1083,13 +1208,70 @@ const defaultRuleGroupProcessorSequelize = (ruleGroup, options) => {
1083
1208
  fieldData
1084
1209
  });
1085
1210
  }).filter(Boolean);
1086
- if (expressions.length === 0) return;
1211
+ if (expressions.length === 0) return void 0;
1087
1212
  const result = expressions.length === 1 && !hasChildRules ? expressions[0] : { [lc(combinator) === "or" ? Op.or : Op.and]: expressions };
1088
1213
  return rg.not ? { [Op.not]: result } : result;
1089
1214
  };
1090
1215
  return processRuleGroup(convertFromIC(ruleGroup), true);
1091
1216
  };
1092
1217
  //#endregion
1218
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSPARQL.ts
1219
+ /**
1220
+ * Rule group processor used by {@link formatQuery} for "sparql" format.
1221
+ *
1222
+ * SPARQL uses the same combinators as CEL (`&&` / `||`) and `!()` for negation.
1223
+ *
1224
+ * @group Export
1225
+ */
1226
+ const defaultRuleGroupProcessorSPARQL = (ruleGroup, options) => {
1227
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1228
+ const processRuleGroup = (rg, outermost) => {
1229
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1230
+ const processedRules = [];
1231
+ let precedingCombinator = "";
1232
+ let firstRule = true;
1233
+ for (const rule of rg.rules) {
1234
+ if (typeof rule === "string") {
1235
+ precedingCombinator = celCombinatorMap[rule];
1236
+ continue;
1237
+ }
1238
+ if (isRuleGroup(rule)) {
1239
+ const processedGroup = processRuleGroup(rule);
1240
+ if (processedGroup) {
1241
+ if (!firstRule && precedingCombinator) {
1242
+ processedRules.push(precedingCombinator);
1243
+ precedingCombinator = "";
1244
+ }
1245
+ firstRule = false;
1246
+ processedRules.push(processedGroup);
1247
+ }
1248
+ continue;
1249
+ }
1250
+ const [validationResult, fieldValidator] = validateRule(rule);
1251
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
1252
+ const fieldData = getOption(fields, rule.field);
1253
+ const processedRule = ruleProcessor(rule, {
1254
+ ...options,
1255
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1256
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1257
+ fieldData
1258
+ });
1259
+ if (processedRule) {
1260
+ if (!firstRule && precedingCombinator) {
1261
+ processedRules.push(precedingCombinator);
1262
+ precedingCombinator = "";
1263
+ }
1264
+ firstRule = false;
1265
+ processedRules.push(processedRule);
1266
+ }
1267
+ }
1268
+ const expression = processedRules.join(isRuleGroupType(rg) ? ` ${celCombinatorMap[rg.combinator]} ` : " ");
1269
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "!" : ""}(`, ")"] : ["", ""];
1270
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1271
+ };
1272
+ return processRuleGroup(ruleGroup, true);
1273
+ };
1274
+ //#endregion
1093
1275
  //#region src/utils/formatQuery/defaultRuleGroupProcessorSQL.ts
1094
1276
  /**
1095
1277
  * Default rule processor used by {@link formatQuery} for "sql" format.
@@ -1099,7 +1281,7 @@ const defaultRuleGroupProcessorSequelize = (ruleGroup, options) => {
1099
1281
  const defaultRuleGroupProcessorSQL = (ruleGroup, options) => {
1100
1282
  const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1101
1283
  const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
1102
- if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
1284
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : /* v8 ignore next -- @preserve */ "";
1103
1285
  const processedRules = [];
1104
1286
  let precedingCombinator = "";
1105
1287
  let firstRule = true;
@@ -1110,7 +1292,7 @@ const defaultRuleGroupProcessorSQL = (ruleGroup, options) => {
1110
1292
  }
1111
1293
  if (isRuleGroup(rule)) {
1112
1294
  const processedGroup = processRuleGroup(rule, rg.rules.length === 1);
1113
- // istanbul ignore else
1295
+ // v8 ignore else
1114
1296
  if (processedGroup) {
1115
1297
  if (!firstRule && precedingCombinator) {
1116
1298
  processedRules.push(precedingCombinator);
@@ -1146,6 +1328,378 @@ const defaultRuleGroupProcessorSQL = (ruleGroup, options) => {
1146
1328
  return processRuleGroup(ruleGroup, true);
1147
1329
  };
1148
1330
  //#endregion
1331
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorDiagnostics.ts
1332
+ const numericInputTypes = new Set([
1333
+ "number",
1334
+ "range",
1335
+ "bigint"
1336
+ ]);
1337
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
1338
+ const timeRegex = /^\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/;
1339
+ const monthRegex = /^\d{4}-\d{2}$/;
1340
+ const weekRegex = /^\d{4}-W\d{2}$/;
1341
+ const colorRegex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
1342
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1343
+ const isValidDateComponents = (y, m, d) => {
1344
+ const date = new Date(Date.UTC(y, m - 1, d));
1345
+ return date.getUTCFullYear() === y && date.getUTCMonth() === m - 1 && date.getUTCDate() === d;
1346
+ };
1347
+ const isValidTimeComponents = (s) => {
1348
+ const parts = s.split(":");
1349
+ const h = Number(parts[0]);
1350
+ const m = Number(parts[1]);
1351
+ const sec = parts[2] ? Number.parseFloat(parts[2]) : 0;
1352
+ return h >= 0 && h <= 23 && m >= 0 && m <= 59 && sec >= 0 && sec < 60;
1353
+ };
1354
+ /**
1355
+ * Checks whether a value is compatible with the given {@link FullField.inputType}.
1356
+ * Returns a diagnostic code string if there is a mismatch, or `undefined` if OK.
1357
+ */
1358
+ const checkValueTypeMismatch = (value, inputType) => {
1359
+ if (value === null || value === void 0 || value === "") return void 0;
1360
+ if (numericInputTypes.has(inputType)) {
1361
+ const v = typeof value === "string" ? value.trim() : value;
1362
+ if (typeof v === "number" || typeof v === "bigint") return void 0;
1363
+ if (typeof v === "string" && numericRegex.test(v)) return void 0;
1364
+ return "VALUE_TYPE_MISMATCH";
1365
+ }
1366
+ if (inputType === "date") {
1367
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1368
+ const v = value.trim();
1369
+ if (!dateRegex.test(v)) return "VALUE_TYPE_MISMATCH";
1370
+ const [y, m, d] = v.split("-").map(Number);
1371
+ return isValidDateComponents(y, m, d) ? void 0 : "VALUE_TYPE_MISMATCH";
1372
+ }
1373
+ if (inputType === "datetime-local") {
1374
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1375
+ const base = value.trim().replace(/(Z|[+-]\d{2}:?\d{2}|[+-]\d{2})$/, "");
1376
+ const tIndex = base.indexOf("T");
1377
+ if (tIndex === -1) return "VALUE_TYPE_MISMATCH";
1378
+ const datePart = base.slice(0, tIndex);
1379
+ const timePart = base.slice(tIndex + 1);
1380
+ if (!dateRegex.test(datePart) || !timeRegex.test(timePart)) return "VALUE_TYPE_MISMATCH";
1381
+ const [y, m, d] = datePart.split("-").map(Number);
1382
+ if (!isValidDateComponents(y, m, d)) return "VALUE_TYPE_MISMATCH";
1383
+ return isValidTimeComponents(timePart) ? void 0 : "VALUE_TYPE_MISMATCH";
1384
+ }
1385
+ if (inputType === "time") {
1386
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1387
+ const v = value.trim();
1388
+ if (!timeRegex.test(v)) return "VALUE_TYPE_MISMATCH";
1389
+ return isValidTimeComponents(v) ? void 0 : "VALUE_TYPE_MISMATCH";
1390
+ }
1391
+ if (inputType === "month") {
1392
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1393
+ const v = value.trim();
1394
+ if (!monthRegex.test(v)) return "VALUE_TYPE_MISMATCH";
1395
+ const m = Number(v.slice(5));
1396
+ return m >= 1 && m <= 12 ? void 0 : "VALUE_TYPE_MISMATCH";
1397
+ }
1398
+ if (inputType === "week") {
1399
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1400
+ const v = value.trim();
1401
+ if (!weekRegex.test(v)) return "VALUE_TYPE_MISMATCH";
1402
+ const w = Number(v.slice(6));
1403
+ return w >= 1 && w <= 53 ? void 0 : "VALUE_TYPE_MISMATCH";
1404
+ }
1405
+ if (inputType === "color") {
1406
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1407
+ return colorRegex.test(value.trim()) ? void 0 : "VALUE_TYPE_MISMATCH";
1408
+ }
1409
+ if (inputType === "url") {
1410
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1411
+ try {
1412
+ new URL(value.trim());
1413
+ return;
1414
+ } catch {
1415
+ return "VALUE_TYPE_MISMATCH";
1416
+ }
1417
+ }
1418
+ if (inputType === "email") {
1419
+ if (typeof value !== "string") return "VALUE_TYPE_MISMATCH";
1420
+ return emailRegex.test(value.trim()) ? void 0 : "VALUE_TYPE_MISMATCH";
1421
+ }
1422
+ };
1423
+ /**
1424
+ * Rule group processor used by {@link formatQuery} for "diagnostics" format.
1425
+ *
1426
+ * Produces a {@link DiagnosticsResult} containing an annotated copy of the query
1427
+ * tree (`query`) with `valid`, `reasons`, `path`, and `level` properties on every
1428
+ * rule and group; a flat `diagnostics` array; aggregate `stats`; and a per-field
1429
+ * `fieldSummary`.
1430
+ *
1431
+ * @group Export
1432
+ */
1433
+ const defaultRuleGroupProcessorDiagnostics = (ruleGroup, options) => {
1434
+ const { fields: fieldsOption, placeholderFieldName, placeholderOperatorName, placeholderValueName, validateRule, validationMap } = options;
1435
+ const diagnostics = [];
1436
+ const stats = {
1437
+ totalRules: 0,
1438
+ totalGroups: 0,
1439
+ validRules: 0,
1440
+ invalidRules: 0,
1441
+ validGroups: 0,
1442
+ invalidGroups: 0
1443
+ };
1444
+ const fieldSummary = {};
1445
+ const uniqueFields = toFlatOptionArray(fieldsOption);
1446
+ const fieldsByName = /* @__PURE__ */ new Map();
1447
+ for (const f of uniqueFields) fieldsByName.set(f.name, f);
1448
+ const hasFieldsConfig = fieldsByName.size > 0;
1449
+ const processRuleGroup = (rg, path) => {
1450
+ stats.totalGroups++;
1451
+ const level = path.length;
1452
+ const groupValidationEntry = validationMap[rg.id ?? ""];
1453
+ const groupSelfValid = isRuleOrGroupValid(rg, groupValidationEntry);
1454
+ const groupReasons = getReasons(groupValidationEntry);
1455
+ if (rg.muted) diagnostics.push({
1456
+ id: rg.id ?? "",
1457
+ path,
1458
+ code: "MUTED",
1459
+ message: "Group is muted",
1460
+ source: "muted"
1461
+ });
1462
+ else if (!groupSelfValid && groupValidationEntry !== void 0) diagnostics.push({
1463
+ id: rg.id ?? "",
1464
+ path,
1465
+ code: "CUSTOM_VALIDATOR",
1466
+ message: groupReasons ? `Invalid: ${groupReasons.join(", ")}` : "Group failed validation",
1467
+ source: "query-validator"
1468
+ });
1469
+ let allChildrenValid = true;
1470
+ let ruleIndex = 0;
1471
+ const annotatedRules = [];
1472
+ for (const rule of rg.rules) {
1473
+ if (typeof rule === "string") {
1474
+ annotatedRules.push(rule);
1475
+ ruleIndex++;
1476
+ continue;
1477
+ }
1478
+ const childPath = [...path, ruleIndex];
1479
+ if (isRuleGroup(rule)) {
1480
+ const annotatedGroup = processRuleGroup(rule, childPath);
1481
+ if (!annotatedGroup.valid) allChildrenValid = false;
1482
+ annotatedRules.push(annotatedGroup);
1483
+ ruleIndex++;
1484
+ continue;
1485
+ }
1486
+ stats.totalRules++;
1487
+ const childLevel = childPath.length;
1488
+ const [validationResult, fieldValidator] = validateRule(rule);
1489
+ const ruleValid = isRuleOrGroupValid(rule, validationResult, fieldValidator) && rule.field !== placeholderFieldName && rule.operator !== placeholderOperatorName && !(placeholderValueName !== void 0 && rule.value === placeholderValueName);
1490
+ collectRuleDiagnostics(rule, childPath, validationResult, fieldValidator, ruleValid, diagnostics, placeholderFieldName, placeholderOperatorName, placeholderValueName, hasFieldsConfig, fieldsByName);
1491
+ if (!ruleValid) {
1492
+ allChildrenValid = false;
1493
+ stats.invalidRules++;
1494
+ } else stats.validRules++;
1495
+ const fieldName = rule.field;
1496
+ if (!fieldSummary[fieldName]) fieldSummary[fieldName] = {
1497
+ ruleCount: 0,
1498
+ invalidCount: 0
1499
+ };
1500
+ fieldSummary[fieldName].ruleCount++;
1501
+ if (!ruleValid) fieldSummary[fieldName].invalidCount++;
1502
+ const ruleReasons = getReasons(validationResult) ?? getFieldValidatorReasons(rule, fieldValidator);
1503
+ const annotatedRule = {
1504
+ ...rule,
1505
+ valid: ruleValid,
1506
+ ...ruleReasons ? { reasons: ruleReasons } : null,
1507
+ path: childPath,
1508
+ level: childLevel
1509
+ };
1510
+ annotatedRules.push(annotatedRule);
1511
+ ruleIndex++;
1512
+ }
1513
+ const groupValid = groupSelfValid && allChildrenValid;
1514
+ if (groupValid) stats.validGroups++;
1515
+ else stats.invalidGroups++;
1516
+ if (isRuleGroupType(rg)) return {
1517
+ ...rg,
1518
+ valid: groupValid,
1519
+ ...groupReasons ? { reasons: groupReasons } : null,
1520
+ path,
1521
+ level,
1522
+ rules: annotatedRules
1523
+ };
1524
+ return {
1525
+ ...rg,
1526
+ valid: groupValid,
1527
+ ...groupReasons ? { reasons: groupReasons } : null,
1528
+ path,
1529
+ level,
1530
+ rules: annotatedRules
1531
+ };
1532
+ };
1533
+ const query = processRuleGroup(ruleGroup, []);
1534
+ if (hasFieldsConfig) {
1535
+ const referencedFields = new Set(Object.keys(fieldSummary));
1536
+ for (const [fieldName] of fieldsByName) if (!referencedFields.has(fieldName)) diagnostics.push({
1537
+ id: "",
1538
+ path: [],
1539
+ code: "UNREFERENCED_FIELD",
1540
+ message: `Field "${fieldName}" is defined in the fields config but not used in the query`,
1541
+ source: "field-check"
1542
+ });
1543
+ }
1544
+ return {
1545
+ query,
1546
+ diagnostics,
1547
+ stats,
1548
+ fieldSummary
1549
+ };
1550
+ };
1551
+ /**
1552
+ * Collects diagnostic entries for a single rule.
1553
+ */
1554
+ const collectRuleDiagnostics = (rule, path, validationResult, fieldValidator, ruleValid, diagnostics, placeholderFieldName, placeholderOperatorName, placeholderValueName, hasFieldsConfig, fieldsByName) => {
1555
+ const id = rule.id ?? "";
1556
+ if (rule.muted) diagnostics.push({
1557
+ id,
1558
+ path,
1559
+ code: "MUTED",
1560
+ message: "Rule is muted",
1561
+ source: "muted"
1562
+ });
1563
+ if (rule.field === placeholderFieldName) diagnostics.push({
1564
+ id,
1565
+ path,
1566
+ code: "PLACEHOLDER_FIELD",
1567
+ message: "Rule has a placeholder field",
1568
+ source: "placeholder"
1569
+ });
1570
+ if (rule.operator === placeholderOperatorName) diagnostics.push({
1571
+ id,
1572
+ path,
1573
+ code: "PLACEHOLDER_OPERATOR",
1574
+ message: "Rule has a placeholder operator",
1575
+ source: "placeholder"
1576
+ });
1577
+ if (placeholderValueName !== void 0 && rule.value === placeholderValueName) diagnostics.push({
1578
+ id,
1579
+ path,
1580
+ code: "PLACEHOLDER_VALUE",
1581
+ message: "Rule has a placeholder value",
1582
+ source: "placeholder"
1583
+ });
1584
+ if (!rule.muted && rule.field !== placeholderFieldName && rule.operator !== placeholderOperatorName && !(placeholderValueName !== void 0 && rule.value === placeholderValueName)) {
1585
+ if (typeof validationResult === "boolean" && !validationResult) diagnostics.push({
1586
+ id,
1587
+ path,
1588
+ code: "CUSTOM_VALIDATOR",
1589
+ message: "Rule failed validation",
1590
+ source: "query-validator"
1591
+ });
1592
+ else if (typeof validationResult !== "boolean" && isValidationResult(validationResult) && !validationResult.valid) {
1593
+ const reasons = validationResult.reasons;
1594
+ diagnostics.push({
1595
+ id,
1596
+ path,
1597
+ code: "CUSTOM_VALIDATOR",
1598
+ message: reasons ? `Invalid: ${reasons.join(", ")}` : "Rule failed validation",
1599
+ source: "query-validator"
1600
+ });
1601
+ } else if (!ruleValid && typeof fieldValidator === "function") {
1602
+ const vr = fieldValidator(rule);
1603
+ const reasons = typeof vr !== "boolean" && isValidationResult(vr) && !vr.valid ? vr.reasons : void 0;
1604
+ diagnostics.push({
1605
+ id,
1606
+ path,
1607
+ code: "CUSTOM_VALIDATOR",
1608
+ message: reasons ? `Invalid: ${reasons.join(", ")}` : "Rule failed field validation",
1609
+ source: "field-validator"
1610
+ });
1611
+ }
1612
+ }
1613
+ if (hasFieldsConfig && !fieldsByName.has(rule.field) && rule.field !== placeholderFieldName) diagnostics.push({
1614
+ id,
1615
+ path,
1616
+ code: "UNDEFINED_FIELD",
1617
+ message: `Field "${rule.field}" is not defined in the fields config`,
1618
+ source: "field-check"
1619
+ });
1620
+ if (hasFieldsConfig) {
1621
+ const fieldDef = fieldsByName.get(rule.field);
1622
+ if (fieldDef?.inputType) {
1623
+ const mismatchCode = checkValueTypeMismatch(rule.value, fieldDef.inputType);
1624
+ if (mismatchCode) diagnostics.push({
1625
+ id,
1626
+ path,
1627
+ code: mismatchCode,
1628
+ message: `Value "${rule.value}" is not compatible with input type "${fieldDef.inputType}"`,
1629
+ source: "type-check"
1630
+ });
1631
+ }
1632
+ }
1633
+ };
1634
+ /**
1635
+ * Extracts `reasons` from a validation result, if present.
1636
+ */
1637
+ const getReasons = (validationResult) => {
1638
+ if (typeof validationResult !== "boolean" && isValidationResult(validationResult) && !validationResult.valid && validationResult.reasons) return validationResult.reasons;
1639
+ };
1640
+ /**
1641
+ * Runs a field-level validator and extracts `reasons` if present.
1642
+ */
1643
+ const getFieldValidatorReasons = (rule, fieldValidator) => {
1644
+ if (typeof fieldValidator === "function") {
1645
+ const vr = fieldValidator(rule);
1646
+ if (typeof vr !== "boolean" && isValidationResult(vr) && !vr.valid && vr.reasons) return vr.reasons;
1647
+ }
1648
+ };
1649
+ //#endregion
1650
+ //#region src/utils/formatQuery/defaultRuleProcessorCypher.ts
1651
+ const escapeSingleQuotes$1 = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll("'", "\\'");
1652
+ /**
1653
+ * Default rule processor used by {@link formatQuery} for "cypher" and "gql" formats.
1654
+ *
1655
+ * @group Export
1656
+ */
1657
+ const defaultRuleProcessorCypher = (rule, opts = {}) => {
1658
+ const { escapeQuotes, parseNumbers } = opts;
1659
+ const { field, operator, value, valueSource } = rule;
1660
+ const valueIsField = valueSource === "field";
1661
+ const operatorTL = operator.toLowerCase();
1662
+ const fmtVal = (v) => {
1663
+ if (v === null || v === void 0) return "null";
1664
+ if (typeof v === "boolean" || typeof v === "bigint") return String(v);
1665
+ if (valueIsField) return trimIfString(v);
1666
+ if (typeof v === "number" || shouldRenderAsNumber(v, parseNumbers)) return trimIfString(v);
1667
+ return `'${escapeSingleQuotes$1(v, escapeQuotes)}'`;
1668
+ };
1669
+ switch (operatorTL) {
1670
+ case "=": return `${field} = ${fmtVal(value)}`;
1671
+ case "!=":
1672
+ case "<>": return `${field} <> ${fmtVal(value)}`;
1673
+ case "<":
1674
+ case ">":
1675
+ case "<=":
1676
+ case ">=": return `${field} ${operatorTL} ${fmtVal(value)}`;
1677
+ case "contains": return `${field} CONTAINS ${fmtVal(value)}`;
1678
+ case "doesnotcontain": return `NOT ${field} CONTAINS ${fmtVal(value)}`;
1679
+ case "beginswith": return `${field} STARTS WITH ${fmtVal(value)}`;
1680
+ case "doesnotbeginwith": return `NOT ${field} STARTS WITH ${fmtVal(value)}`;
1681
+ case "endswith": return `${field} ENDS WITH ${fmtVal(value)}`;
1682
+ case "doesnotendwith": return `NOT ${field} ENDS WITH ${fmtVal(value)}`;
1683
+ case "null": return `${field} IS NULL`;
1684
+ case "notnull": return `${field} IS NOT NULL`;
1685
+ case "in":
1686
+ case "notin": {
1687
+ const values = toArray(value).map(fmtVal);
1688
+ if (!values.length) return "";
1689
+ return `${operatorTL === "notin" ? "NOT " : ""}${field} IN [${values.join(", ")}]`;
1690
+ }
1691
+ case "between":
1692
+ case "notbetween": {
1693
+ const arr = toArray(value);
1694
+ if (arr.length < 2) return "";
1695
+ const [low, high] = [fmtVal(arr[0]), fmtVal(arr[1])];
1696
+ const expr = `${low} <= ${field} AND ${field} <= ${high}`;
1697
+ return operatorTL === "notbetween" ? `NOT (${expr})` : expr;
1698
+ }
1699
+ default: return `${field} ${operator} ${fmtVal(value)}`;
1700
+ }
1701
+ };
1702
+ //#endregion
1149
1703
  //#region src/utils/formatQuery/defaultRuleProcessorElasticSearch.ts
1150
1704
  const rangeOperatorMap = {
1151
1705
  "<": "lt",
@@ -1297,6 +1851,68 @@ const defaultRuleProcessorElasticSearch = (rule, options = {}) => {
1297
1851
  return false;
1298
1852
  };
1299
1853
  //#endregion
1854
+ //#region src/utils/formatQuery/defaultRuleProcessorGremlin.ts
1855
+ const escapeSingleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll("'", "\\'");
1856
+ /**
1857
+ * Default rule processor used by {@link formatQuery} for "gremlin" format.
1858
+ *
1859
+ * Each rule becomes a `.has()` step (or `.hasNot()`/`.has()` for null checks).
1860
+ *
1861
+ * @group Export
1862
+ */
1863
+ const defaultRuleProcessorGremlin = (rule, opts = {}) => {
1864
+ const { escapeQuotes, parseNumbers } = opts;
1865
+ const { field, operator, value, valueSource } = rule;
1866
+ const valueIsField = valueSource === "field";
1867
+ const operatorTL = operator.toLowerCase();
1868
+ const prop = field.includes(".") ? field.split(".").pop() : field;
1869
+ const fmtVal = (v) => {
1870
+ if (v === null || v === void 0) return "null";
1871
+ if (typeof v === "boolean" || typeof v === "bigint") return String(v);
1872
+ if (valueIsField) return trimIfString(v);
1873
+ if (typeof v === "number" || shouldRenderAsNumber(v, parseNumbers)) return trimIfString(v);
1874
+ return `'${escapeSingleQuotes(v, escapeQuotes)}'`;
1875
+ };
1876
+ switch (operatorTL) {
1877
+ case "=": return `.has('${prop}', ${fmtVal(value)})`;
1878
+ case "!=":
1879
+ case "<>": return `.has('${prop}', neq(${fmtVal(value)}))`;
1880
+ case "<": return `.has('${prop}', lt(${fmtVal(value)}))`;
1881
+ case ">": return `.has('${prop}', gt(${fmtVal(value)}))`;
1882
+ case "<=": return `.has('${prop}', lte(${fmtVal(value)}))`;
1883
+ case ">=": return `.has('${prop}', gte(${fmtVal(value)}))`;
1884
+ case "contains": return `.has('${prop}', containing(${fmtVal(value)}))`;
1885
+ case "doesnotcontain": return `.has('${prop}', notContaining(${fmtVal(value)}))`;
1886
+ case "beginswith": return `.has('${prop}', startingWith(${fmtVal(value)}))`;
1887
+ case "doesnotbeginwith": return `.has('${prop}', notStartingWith(${fmtVal(value)}))`;
1888
+ case "endswith": return `.has('${prop}', endingWith(${fmtVal(value)}))`;
1889
+ case "doesnotendwith": return `.has('${prop}', notEndingWith(${fmtVal(value)}))`;
1890
+ case "null": return `.hasNot('${prop}')`;
1891
+ case "notnull": return `.has('${prop}')`;
1892
+ case "in": {
1893
+ const items = toArray(value).map(fmtVal);
1894
+ if (!items.length) return "";
1895
+ return `.has('${prop}', within(${items.join(", ")}))`;
1896
+ }
1897
+ case "notin": {
1898
+ const items = toArray(value).map(fmtVal);
1899
+ if (!items.length) return "";
1900
+ return `.has('${prop}', without(${items.join(", ")}))`;
1901
+ }
1902
+ case "between": {
1903
+ const arr = toArray(value);
1904
+ if (arr.length < 2) return "";
1905
+ return `.has('${prop}', between(${fmtVal(arr[0])}, ${fmtVal(arr[1])}))`;
1906
+ }
1907
+ case "notbetween": {
1908
+ const arr = toArray(value);
1909
+ if (arr.length < 2) return "";
1910
+ return `.has('${prop}', outside(${fmtVal(arr[0])}, ${fmtVal(arr[1])}))`;
1911
+ }
1912
+ default: return `.has('${prop}', ${fmtVal(value)})`;
1913
+ }
1914
+ };
1915
+ //#endregion
1300
1916
  //#region src/utils/formatQuery/defaultRuleProcessorJSONata.ts
1301
1917
  const shouldNegate = (op) => op.startsWith("not") || op.startsWith("doesnot");
1302
1918
  const quote = (v, escapeQuotes) => `"${typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`)}"`;
@@ -1524,12 +2140,12 @@ const defaultRuleProcessorLDAP = (rule, options = {}) => {
1524
2140
  return negateIf(`(&(${field}>=${ldapEscape(firstValue)})(${field}<=${ldapEscape(secondValue)}))`, operatorLC === "notbetween");
1525
2141
  }
1526
2142
  }
1527
- // istanbul ignore next
2143
+ // v8 ignore next
1528
2144
  return "";
1529
2145
  };
1530
2146
  //#endregion
1531
2147
  //#region src/utils/formatQuery/defaultValueProcessorNL.ts
1532
- const escapeStringValueQuotes = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : v;
2148
+ const escapeStringValueQuotes = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : /* v8 ignore next -- @preserve */ v;
1533
2149
  /**
1534
2150
  * Default value processor used by {@link formatQuery} for "natural_language" format.
1535
2151
  *
@@ -1547,7 +2163,7 @@ const defaultValueProcessorNL = (rule, opts = {}) => {
1547
2163
  quoteFieldNamesWith,
1548
2164
  fieldIdentifierSeparator
1549
2165
  });
1550
- const t = translations ?? ( /* istanbul ignore next */ {});
2166
+ const t = translations ?? ( /* v8 ignore start -- @preserve */ {});
1551
2167
  const orTL = t.or ?? "or";
1552
2168
  const trueTL = t.true ?? "true";
1553
2169
  const falseTL = t.false ?? "false";
@@ -1603,7 +2219,7 @@ const defaultExportOperatorMap = {
1603
2219
  between: ["is between", "is between the values in"],
1604
2220
  notbetween: ["is not between", "is not between the values in"]
1605
2221
  };
1606
- /* istanbul ignore next */
2222
+ /* v8 ignore next -- @preserve */
1607
2223
  const defaultGetOperators = () => [];
1608
2224
  /**
1609
2225
  * Default operator processor used by {@link formatQuery} for "natural_language" format.
@@ -1612,7 +2228,7 @@ const defaultGetOperators = () => [];
1612
2228
  */
1613
2229
  const defaultOperatorProcessorNL = (rule, opts = {}) => {
1614
2230
  const { field, operator, valueSource = "value" } = rule;
1615
- // istanbul ignore next
2231
+ // v8 ignore next
1616
2232
  const { getOperators = defaultGetOperators, operatorMap: operatorMapParam = defaultExportOperatorMap } = opts;
1617
2233
  const mergedOperatorMap = new Map(Object.entries(defaultExportOperatorMap));
1618
2234
  for (const [key, value] of Object.entries(operatorMapParam)) mergedOperatorMap.set(lc(key), value);
@@ -1641,8 +2257,8 @@ const defaultOperatorProcessorNL = (rule, opts = {}) => {
1641
2257
  */
1642
2258
  const defaultRuleProcessorNL = (rule, opts) => {
1643
2259
  const { field, operator } = rule;
1644
- // istanbul ignore next
1645
- const { fieldData, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", quoteValuesWith = `'`, operatorProcessor = defaultOperatorProcessorNL, valueProcessor = defaultValueProcessorNL, concatOperator = "||", wordOrder = "SVO" } = opts ?? ( /* istanbul ignore next */ {});
2260
+ // v8 ignore next
2261
+ const { fieldData, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", quoteValuesWith = `'`, operatorProcessor = defaultOperatorProcessorNL, valueProcessor = defaultValueProcessorNL, concatOperator = "||", wordOrder = "SVO" } = opts ?? ( /* v8 ignore start -- @preserve */ {});
1646
2262
  const processedField = getQuotedFieldName(fieldData?.label ?? field, {
1647
2263
  quoteFieldNamesWith,
1648
2264
  fieldIdentifierSeparator
@@ -1748,7 +2364,7 @@ const defaultRuleProcessorSQL = (rule, opts = {}) => {
1748
2364
  * @group Export
1749
2365
  */
1750
2366
  const defaultRuleProcessorParameterized = (rule, opts, meta) => {
1751
- // istanbul ignore next
2367
+ // v8 ignore next
1752
2368
  const { fieldData, format, getNextNamedParam, parseNumbers, paramPrefix, paramsKeepPrefix, numberedParams, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator, concatOperator, operatorProcessor = defaultOperatorProcessorSQL, valueProcessor = defaultValueProcessorByRule } = opts ?? {};
1753
2369
  const { processedParams = [] } = meta ?? {};
1754
2370
  const parameterized = format === "parameterized";
@@ -1767,6 +2383,7 @@ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
1767
2383
  });
1768
2384
  const ruleField = wrapFieldName(rule.field);
1769
2385
  const matchEval = processMatchMode(rule);
2386
+ /* v8 ignore start -- @preserve */
1770
2387
  if (matchEval === false) return;
1771
2388
  else if (matchEval) {
1772
2389
  if (opts?.preset !== "postgresql") return finalize("");
@@ -1779,7 +2396,6 @@ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
1779
2396
  ...opts,
1780
2397
  fields: []
1781
2398
  });
1782
- // istanbul ignore else
1783
2399
  if (Array.isArray(nestedParams)) params.push(...nestedParams);
1784
2400
  else Object.assign(paramsNamed, nestedParams);
1785
2401
  switch (mode) {
@@ -1794,6 +2410,7 @@ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
1794
2410
  }
1795
2411
  }
1796
2412
  }
2413
+ /* v8 ignore stop -- @preserve */
1797
2414
  const value = valueProcessor(rule, {
1798
2415
  parseNumbers,
1799
2416
  quoteFieldNamesWith,
@@ -1834,7 +2451,7 @@ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
1834
2451
  }
1835
2452
  let paramValue = rule.value;
1836
2453
  if (typeof rule.value === "string") if (shouldRenderAsNumber(rule.value, parseNumbers)) paramValue = parseNumber(rule.value, { parseNumbers });
1837
- else paramValue = /^'.*'$/g.test(value) ? value.replaceAll(/(^'|'$)/g, "") : value;
2454
+ else paramValue = /^'.*'$/g.test(value) ? value.replaceAll(/(^'|'$)/g, "") : /* v8 ignore next -- @preserve */ value;
1838
2455
  let paramName = "";
1839
2456
  if (parameterized) params.push(paramValue);
1840
2457
  else {
@@ -1853,9 +2470,9 @@ const processNumber = (value, fallback, parseNumbers) => shouldRenderAsNumber(va
1853
2470
  */
1854
2471
  const defaultRuleProcessorPrisma = (rule, options = {}) => {
1855
2472
  const { field, operator, value, valueSource } = rule;
1856
- // istanbul ignore next
2473
+ // v8 ignore next
1857
2474
  const { parseNumbers, preserveValueOrder } = options;
1858
- if (valueSource === "field" || processMatchMode(rule)) return;
2475
+ if (valueSource === "field" || processMatchMode(rule)) return void 0;
1859
2476
  const operatorLC = lc(operator);
1860
2477
  switch (operatorLC) {
1861
2478
  case "=": return { [field]: processNumber(value, value, parseNumbers) };
@@ -1913,13 +2530,16 @@ const defaultRuleProcessorPrisma = (rule, options = {}) => {
1913
2530
  */
1914
2531
  const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder, context = {} } = {}) => {
1915
2532
  const { sequelizeOperators: Op, sequelizeCol: col, sequelizeFn: fn } = context;
1916
- if (processMatchMode(rule)) return;
2533
+ if (processMatchMode(rule)) return void 0;
1917
2534
  const { field, operator, value, valueSource } = rule;
1918
2535
  const valueIsField = valueSource === "field";
1919
2536
  const operatorLC = lc(operator);
1920
2537
  if (!Op || valueIsField && (!col || !fn && [
2538
+ "contains",
1921
2539
  "doesnotcontain",
2540
+ "beginswith",
1922
2541
  "doesnotbeginwith",
2542
+ "endswith",
1923
2543
  "doesnotendwith"
1924
2544
  ].includes(operatorLC))) return;
1925
2545
  switch (operatorLC) {
@@ -1939,9 +2559,9 @@ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder,
1939
2559
  }[operatorLC];
1940
2560
  return { [field]: valueIsField && operatorLC === "=" ? { [Op.col]: value } : { [sequelizeOperator]: valueIsField ? col(value) : shouldRenderAsNumber(value, parseNumbers) ? parseNumber(value, { parseNumbers: "strict" }) : value } };
1941
2561
  }
1942
- case "contains": return { [field]: { [Op.substring]: valueIsField ? col(value) : `${value}` } };
1943
- case "beginswith": return { [field]: { [Op.startsWith]: valueIsField ? col(value) : `${value}` } };
1944
- case "endswith": return { [field]: { [Op.endsWith]: valueIsField ? col(value) : `${value}` } };
2562
+ case "contains": return { [field]: { [valueIsField ? Op.like : Op.substring]: valueIsField ? fn("CONCAT", "%", col(value), "%") : `${value}` } };
2563
+ case "beginswith": return { [field]: { [valueIsField ? Op.like : Op.startsWith]: valueIsField ? fn("CONCAT", col(value), "%") : `${value}` } };
2564
+ case "endswith": return { [field]: { [valueIsField ? Op.like : Op.endsWith]: valueIsField ? fn("CONCAT", "%", col(value)) : `${value}` } };
1945
2565
  case "doesnotcontain": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value), "%") : `%${value}%` } };
1946
2566
  case "doesnotbeginwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", col(value), "%") : `${value}%` } };
1947
2567
  case "doesnotendwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value)) : `%${value}` } };
@@ -1971,6 +2591,68 @@ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder,
1971
2591
  }
1972
2592
  };
1973
2593
  //#endregion
2594
+ //#region src/utils/formatQuery/defaultRuleProcessorSPARQL.ts
2595
+ const escapeDoubleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`);
2596
+ /**
2597
+ * Default rule processor used by {@link formatQuery} for "sparql" format.
2598
+ *
2599
+ * @group Export
2600
+ */
2601
+ const defaultRuleProcessorSPARQL = (rule, opts = {}) => {
2602
+ const { escapeQuotes, parseNumbers } = opts;
2603
+ const { field, operator, value, valueSource } = rule;
2604
+ const valueIsField = valueSource === "field";
2605
+ const operatorTL = operator.toLowerCase();
2606
+ const fmtVal = (v) => {
2607
+ if (v === null || v === void 0) return "\"\"";
2608
+ if (typeof v === "boolean") return `"${v}"^^xsd:boolean`;
2609
+ if (typeof v === "bigint") return String(v);
2610
+ if (valueIsField) return trimIfString(v);
2611
+ if (typeof v === "number" || shouldRenderAsNumber(v, parseNumbers)) return trimIfString(v);
2612
+ const s = typeof v === "string" ? v : JSON.stringify(v) ?? "";
2613
+ if (s.startsWith("?") || s.startsWith("<") || s.includes(":")) return s;
2614
+ return `"${escapeDoubleQuotes(s, escapeQuotes)}"`;
2615
+ };
2616
+ switch (operatorTL) {
2617
+ case "=":
2618
+ case "!=":
2619
+ case "<":
2620
+ case ">":
2621
+ case "<=":
2622
+ case ">=": return `${field} ${operatorTL} ${fmtVal(value)}`;
2623
+ case "<>": return `${field} != ${fmtVal(value)}`;
2624
+ case "contains": return `CONTAINS(${field}, ${fmtVal(value)})`;
2625
+ case "doesnotcontain": return `!CONTAINS(${field}, ${fmtVal(value)})`;
2626
+ case "beginswith": return `STRSTARTS(${field}, ${fmtVal(value)})`;
2627
+ case "doesnotbeginwith": return `!STRSTARTS(${field}, ${fmtVal(value)})`;
2628
+ case "endswith": return `STRENDS(${field}, ${fmtVal(value)})`;
2629
+ case "doesnotendwith": return `!STRENDS(${field}, ${fmtVal(value)})`;
2630
+ case "null": return `!BOUND(${field})`;
2631
+ case "notnull": return `BOUND(${field})`;
2632
+ case "in": {
2633
+ const items = toArray(value).map(fmtVal);
2634
+ if (!items.length) return "";
2635
+ return items.map((item) => `${field} = ${item}`).join(" || ");
2636
+ }
2637
+ case "notin": {
2638
+ const items = toArray(value).map(fmtVal);
2639
+ if (!items.length) return "";
2640
+ return items.map((item) => `${field} != ${item}`).join(" && ");
2641
+ }
2642
+ case "between": {
2643
+ const arr = toArray(value);
2644
+ if (arr.length < 2) return "";
2645
+ return `${field} >= ${fmtVal(arr[0])} && ${field} <= ${fmtVal(arr[1])}`;
2646
+ }
2647
+ case "notbetween": {
2648
+ const arr = toArray(value);
2649
+ if (arr.length < 2) return "";
2650
+ return `(${field} < ${fmtVal(arr[0])} || ${field} > ${fmtVal(arr[1])})`;
2651
+ }
2652
+ default: return `${field} ${operator} ${fmtVal(value)}`;
2653
+ }
2654
+ };
2655
+ //#endregion
1974
2656
  //#region src/utils/formatQuery/formatQuery.ts
1975
2657
  /**
1976
2658
  * A collection of option presets for {@link formatQuery}, specifically for SQL-based formats.
@@ -2017,9 +2699,14 @@ const defaultRuleProcessors = {
2017
2699
  prisma: defaultRuleProcessorPrisma,
2018
2700
  sequelize: defaultRuleProcessorSequelize,
2019
2701
  spel: defaultRuleProcessorSpEL,
2020
- sql: defaultRuleProcessorSQL
2702
+ sql: defaultRuleProcessorSQL,
2703
+ cypher: defaultRuleProcessorCypher,
2704
+ gql: defaultRuleProcessorCypher,
2705
+ sparql: defaultRuleProcessorSPARQL,
2706
+ gremlin: defaultRuleProcessorGremlin,
2707
+ diagnostics: defaultRuleProcessorSQL
2021
2708
  };
2022
- /* istanbul ignore next */
2709
+ /* v8 ignore next -- @preserve */
2023
2710
  const defaultOperatorProcessor = (r) => r.operator;
2024
2711
  const defaultOperatorProcessors = {
2025
2712
  cel: defaultOperatorProcessor,
@@ -2038,13 +2725,20 @@ const defaultOperatorProcessors = {
2038
2725
  prisma: defaultOperatorProcessor,
2039
2726
  sequelize: defaultOperatorProcessor,
2040
2727
  spel: defaultOperatorProcessor,
2041
- sql: defaultOperatorProcessorSQL
2728
+ sql: defaultOperatorProcessorSQL,
2729
+ cypher: defaultOperatorProcessor,
2730
+ gql: defaultOperatorProcessor,
2731
+ sparql: defaultOperatorProcessor,
2732
+ gremlin: defaultOperatorProcessor,
2733
+ diagnostics: defaultOperatorProcessor
2042
2734
  };
2043
2735
  const defaultFallbackExpressions = {
2044
2736
  cel: "1 == 1",
2045
2737
  ldap: "",
2046
2738
  mongodb: "\"$and\":[{\"$expr\":true}]",
2047
2739
  natural_language: "1 is 1",
2740
+ sparql: "1 = 1",
2741
+ gremlin: "",
2048
2742
  spel: "1 == 1",
2049
2743
  sql: "(1 = 1)"
2050
2744
  };
@@ -2112,24 +2806,26 @@ function formatQuery(ruleGroup, optionParam = {}) {
2112
2806
  const getOperators = (f, m) => toFullOptionList(getOperators_option(f, m) ?? []);
2113
2807
  const fallbackExpression = fallbackExpression_option ?? defaultFallbackExpressions[format] ?? defaultFallbackExpressions.sql;
2114
2808
  let validationMap = {};
2115
- // istanbul ignore else
2809
+ // v8 ignore else
2116
2810
  if (typeof validator === "function") {
2117
2811
  const validationResult = validator(ruleGroup);
2118
2812
  if (typeof validationResult === "boolean") {
2119
- // istanbul ignore else
2120
- if (!validationResult) return format === "parameterized" ? {
2121
- sql: fallbackExpression,
2122
- params: []
2123
- } : format === "parameterized_named" ? {
2124
- sql: fallbackExpression,
2125
- params: {}
2126
- } : format === "mongodb" ? `{${fallbackExpression}}` : format === "mongodb_query" ? mongoDbFallback : format === "prisma" ? prismaFallback : format === "jsonlogic" ? false : format === "elasticsearch" ? {} : format === "drizzle" || format === "sequelize" ? void 0 : fallbackExpression;
2813
+ // v8 ignore else
2814
+ if (!validationResult) {
2815
+ if (format !== "diagnostics") return format === "parameterized" ? {
2816
+ sql: fallbackExpression,
2817
+ params: []
2818
+ } : format === "parameterized_named" ? {
2819
+ sql: fallbackExpression,
2820
+ params: {}
2821
+ } : format === "mongodb" ? `{${fallbackExpression}}` : format === "mongodb_query" ? mongoDbFallback : format === "prisma" ? prismaFallback : format === "jsonlogic" ? false : format === "elasticsearch" ? {} : format === "drizzle" || format === "sequelize" ? void 0 : fallbackExpression;
2822
+ }
2127
2823
  } else validationMap = validationResult;
2128
2824
  }
2129
2825
  const validatorMap = {};
2130
2826
  const uniqueFields = toFlatOptionArray(fields);
2131
2827
  for (const f of uniqueFields)
2132
- // istanbul ignore else
2828
+ // v8 ignore else
2133
2829
  if (typeof f.validator === "function") validatorMap[f.value ?? f.name] = f.validator;
2134
2830
  const validateRule = (rule) => {
2135
2831
  let validationResult;
@@ -2139,7 +2835,7 @@ function formatQuery(ruleGroup, optionParam = {}) {
2139
2835
  const fieldArr = uniqueFields.filter((f) => f.name === rule.field);
2140
2836
  if (fieldArr.length > 0) {
2141
2837
  const field = fieldArr[0];
2142
- // istanbul ignore else
2838
+ // v8 ignore else
2143
2839
  if (typeof field.validator === "function") fieldValidator = field.validator;
2144
2840
  }
2145
2841
  }
@@ -2183,6 +2879,11 @@ function formatQuery(ruleGroup, optionParam = {}) {
2183
2879
  case "prisma": return defaultRuleGroupProcessorPrisma(ruleGroup, finalOptions);
2184
2880
  case "drizzle": return defaultRuleGroupProcessorDrizzle(ruleGroup, finalOptions);
2185
2881
  case "sequelize": return defaultRuleGroupProcessorSequelize(ruleGroup, finalOptions);
2882
+ case "cypher":
2883
+ case "gql": return defaultRuleGroupProcessorCypher(ruleGroup, finalOptions);
2884
+ case "sparql": return defaultRuleGroupProcessorSPARQL(ruleGroup, finalOptions);
2885
+ case "gremlin": return defaultRuleGroupProcessorGremlin(ruleGroup, finalOptions);
2886
+ case "diagnostics": return defaultRuleGroupProcessorDiagnostics(ruleGroup, finalOptions);
2186
2887
  default: return "";
2187
2888
  }
2188
2889
  }
@@ -2237,6 +2938,6 @@ const defaultValueProcessorMongoDBByRule = defaultRuleProcessorMongoDB;
2237
2938
  */
2238
2939
  const defaultValueProcessorSpELByRule = defaultRuleProcessorSpEL;
2239
2940
  //#endregion
2240
- export { bigIntJsonParseReviver, bigIntJsonStringifyReplacer, celCombinatorMap, defaultCELValueProcessor, defaultExportOperatorMap, defaultMongoDBValueProcessor, defaultNLTranslations, defaultOperatorProcessorNL, defaultOperatorProcessorSQL, defaultRuleGroupProcessorCEL, defaultRuleGroupProcessorDrizzle, defaultRuleGroupProcessorElasticSearch, defaultRuleGroupProcessorJSONata, defaultRuleGroupProcessorJsonLogic, defaultRuleGroupProcessorLDAP, defaultRuleGroupProcessorMongoDB, defaultRuleGroupProcessorMongoDBQuery, defaultRuleGroupProcessorNL, defaultRuleGroupProcessorParameterized, defaultRuleGroupProcessorPrisma, defaultRuleGroupProcessorSQL, defaultRuleGroupProcessorSequelize, defaultRuleGroupProcessorSpEL, defaultRuleProcessorCEL, defaultRuleProcessorDrizzle, defaultRuleProcessorElasticSearch, defaultRuleProcessorJSONata, defaultRuleProcessorJsonLogic, defaultRuleProcessorLDAP, defaultRuleProcessorMongoDB, defaultRuleProcessorMongoDBQuery, defaultRuleProcessorNL, defaultRuleProcessorParameterized, defaultRuleProcessorPrisma, defaultRuleProcessorSQL, defaultRuleProcessorSequelize, defaultRuleProcessorSpEL, defaultSpELValueProcessor, defaultValueProcessor, defaultValueProcessorByRule, defaultValueProcessorCELByRule, defaultValueProcessorMongoDBByRule, defaultValueProcessorNL, defaultValueProcessorSpELByRule, formatQuery, formatQueryOptionPresets, getNLTranslataion, getQuoteFieldNamesWithArray, getQuotedFieldName, isValidValue, isValueProcessorLegacy, jsonLogicAdditionalOperators, mapSQLOperator, mongoDbFallback, mongoOperators, normalizeConstituentWordOrder, numerifyValues, prismaFallback, prismaOperators, processMatchMode, shouldRenderAsNumber, sqlDialectPresets };
2941
+ export { bigIntJsonParseReviver, bigIntJsonStringifyReplacer, celCombinatorMap, cypherCombinatorMap, defaultCELValueProcessor, defaultExportOperatorMap, defaultMongoDBValueProcessor, defaultNLTranslations, defaultOperatorProcessorNL, defaultOperatorProcessorSQL, defaultRuleGroupProcessorCEL, defaultRuleGroupProcessorCypher, defaultRuleGroupProcessorDiagnostics, defaultRuleGroupProcessorDrizzle, defaultRuleGroupProcessorElasticSearch, defaultRuleGroupProcessorGremlin, defaultRuleGroupProcessorJSONata, defaultRuleGroupProcessorJsonLogic, defaultRuleGroupProcessorLDAP, defaultRuleGroupProcessorMongoDB, defaultRuleGroupProcessorMongoDBQuery, defaultRuleGroupProcessorNL, defaultRuleGroupProcessorParameterized, defaultRuleGroupProcessorPrisma, defaultRuleGroupProcessorSPARQL, defaultRuleGroupProcessorSQL, defaultRuleGroupProcessorSequelize, defaultRuleGroupProcessorSpEL, defaultRuleProcessorCEL, defaultRuleProcessorCypher, defaultRuleProcessorDrizzle, defaultRuleProcessorElasticSearch, defaultRuleProcessorGremlin, defaultRuleProcessorJSONata, defaultRuleProcessorJsonLogic, defaultRuleProcessorLDAP, defaultRuleProcessorMongoDB, defaultRuleProcessorMongoDBQuery, defaultRuleProcessorNL, defaultRuleProcessorParameterized, defaultRuleProcessorPrisma, defaultRuleProcessorSPARQL, defaultRuleProcessorSQL, defaultRuleProcessorSequelize, defaultRuleProcessorSpEL, defaultSpELValueProcessor, defaultValueProcessor, defaultValueProcessorByRule, defaultValueProcessorCELByRule, defaultValueProcessorMongoDBByRule, defaultValueProcessorNL, defaultValueProcessorSpELByRule, formatQuery, formatQueryOptionPresets, getNLTranslataion, getQuoteFieldNamesWithArray, getQuotedFieldName, isValidValue, isValueProcessorLegacy, jsonLogicAdditionalOperators, mapSQLOperator, mongoDbFallback, mongoOperators, normalizeConstituentWordOrder, numerifyValues, prismaFallback, prismaOperators, processMatchMode, shouldRenderAsNumber, sqlDialectPresets };
2241
2942
 
2242
2943
  //# sourceMappingURL=formatQuery.mjs.map