@react-querybuilder/core 8.15.0 → 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 (84) hide show
  1. package/README.md +114 -53
  2. package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +89 -16
  3. package/dist/cjs/react-querybuilder_core.cjs.development.js +402 -19
  4. package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -1
  5. package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +89 -16
  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/formatQuery.d.mts +67 -2
  9. package/dist/formatQuery.d.ts +67 -2
  10. package/dist/formatQuery.js +402 -19
  11. package/dist/formatQuery.js.map +1 -1
  12. package/dist/formatQuery.mjs +396 -20
  13. package/dist/formatQuery.mjs.map +1 -1
  14. package/dist/{import-0wp72lLT.d.mts → import-BHlzBLM_.d.mts} +2 -2
  15. package/dist/{import-yRVJh7E1.d.ts → import-C6imciDf.d.ts} +2 -2
  16. package/dist/{index-D5TXNIzF.d.ts → index-Cjapnb-H.d.ts} +14 -7
  17. package/dist/{index-Lht_Wq3V.d.mts → index-D-Iej37L.d.mts} +14 -7
  18. package/dist/parseCEL.d.mts +2 -2
  19. package/dist/parseCEL.d.ts +2 -2
  20. package/dist/parseCEL.js.map +1 -1
  21. package/dist/parseCEL.mjs.map +1 -1
  22. package/dist/parseCypher.d.mts +49 -0
  23. package/dist/parseCypher.d.ts +49 -0
  24. package/dist/parseCypher.js +578 -0
  25. package/dist/parseCypher.js.map +1 -0
  26. package/dist/parseCypher.mjs +575 -0
  27. package/dist/parseCypher.mjs.map +1 -0
  28. package/dist/parseGremlin.d.mts +35 -0
  29. package/dist/parseGremlin.d.ts +35 -0
  30. package/dist/parseGremlin.js +192 -0
  31. package/dist/parseGremlin.js.map +1 -0
  32. package/dist/parseGremlin.mjs +191 -0
  33. package/dist/parseGremlin.mjs.map +1 -0
  34. package/dist/parseJSONata.d.mts +2 -2
  35. package/dist/parseJSONata.d.ts +2 -2
  36. package/dist/parseJSONata.js.map +1 -1
  37. package/dist/parseJSONata.mjs.map +1 -1
  38. package/dist/parseJsonLogic.d.mts +2 -2
  39. package/dist/parseJsonLogic.d.ts +2 -2
  40. package/dist/parseJsonLogic.js.map +1 -1
  41. package/dist/parseJsonLogic.mjs.map +1 -1
  42. package/dist/parseMongoDB.d.mts +2 -2
  43. package/dist/parseMongoDB.d.ts +2 -2
  44. package/dist/parseMongoDB.js.map +1 -1
  45. package/dist/parseMongoDB.mjs.map +1 -1
  46. package/dist/parseSPARQL.d.mts +34 -0
  47. package/dist/parseSPARQL.d.ts +34 -0
  48. package/dist/parseSPARQL.js +253 -0
  49. package/dist/parseSPARQL.js.map +1 -0
  50. package/dist/parseSPARQL.mjs +251 -0
  51. package/dist/parseSPARQL.mjs.map +1 -0
  52. package/dist/parseSQL.d.mts +2 -2
  53. package/dist/parseSQL.d.ts +2 -2
  54. package/dist/parseSQL.js.map +1 -1
  55. package/dist/parseSQL.mjs.map +1 -1
  56. package/dist/parseSpEL.d.mts +2 -2
  57. package/dist/parseSpEL.d.ts +2 -2
  58. package/dist/parseSpEL.js.map +1 -1
  59. package/dist/parseSpEL.mjs.map +1 -1
  60. package/dist/prepareQueryObjects-BoG5Rt8z.js.map +1 -1
  61. package/dist/prepareQueryObjects-uA10ZpZX.mjs.map +1 -1
  62. package/dist/react-querybuilder_core.d.mts +89 -16
  63. package/dist/react-querybuilder_core.legacy-esm.d.ts +89 -16
  64. package/dist/react-querybuilder_core.legacy-esm.js +408 -27
  65. package/dist/react-querybuilder_core.legacy-esm.js.map +1 -1
  66. package/dist/react-querybuilder_core.mjs +396 -20
  67. package/dist/react-querybuilder_core.mjs.map +1 -1
  68. package/dist/react-querybuilder_core.production.d.mts +89 -16
  69. package/dist/react-querybuilder_core.production.mjs +1 -1
  70. package/dist/react-querybuilder_core.production.mjs.map +1 -1
  71. package/dist/transformQuery.d.mts +1 -1
  72. package/dist/transformQuery.d.ts +1 -1
  73. package/formatQuery/package.json +1 -1
  74. package/package.json +47 -3
  75. package/parseCEL/package.json +1 -1
  76. package/parseCypher/package.json +4 -0
  77. package/parseGremlin/package.json +4 -0
  78. package/parseJSONata/package.json +1 -1
  79. package/parseJsonLogic/package.json +1 -1
  80. package/parseMongoDB/package.json +1 -1
  81. package/parseSPARQL/package.json +4 -0
  82. package/parseSQL/package.json +1 -1
  83. package/parseSpEL/package.json +1 -1
  84. package/transformQuery/package.json +1 -1
@@ -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.
@@ -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.
@@ -1090,6 +1215,63 @@ const defaultRuleGroupProcessorSequelize = (ruleGroup, options) => {
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.
@@ -1465,6 +1647,59 @@ const getFieldValidatorReasons = (rule, fieldValidator) => {
1465
1647
  }
1466
1648
  };
1467
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
1468
1703
  //#region src/utils/formatQuery/defaultRuleProcessorElasticSearch.ts
1469
1704
  const rangeOperatorMap = {
1470
1705
  "<": "lt",
@@ -1616,6 +1851,68 @@ const defaultRuleProcessorElasticSearch = (rule, options = {}) => {
1616
1851
  return false;
1617
1852
  };
1618
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
1619
1916
  //#region src/utils/formatQuery/defaultRuleProcessorJSONata.ts
1620
1917
  const shouldNegate = (op) => op.startsWith("not") || op.startsWith("doesnot");
1621
1918
  const quote = (v, escapeQuotes) => `"${typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`)}"`;
@@ -2238,8 +2535,11 @@ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder,
2238
2535
  const valueIsField = valueSource === "field";
2239
2536
  const operatorLC = lc(operator);
2240
2537
  if (!Op || valueIsField && (!col || !fn && [
2538
+ "contains",
2241
2539
  "doesnotcontain",
2540
+ "beginswith",
2242
2541
  "doesnotbeginwith",
2542
+ "endswith",
2243
2543
  "doesnotendwith"
2244
2544
  ].includes(operatorLC))) return;
2245
2545
  switch (operatorLC) {
@@ -2259,9 +2559,9 @@ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder,
2259
2559
  }[operatorLC];
2260
2560
  return { [field]: valueIsField && operatorLC === "=" ? { [Op.col]: value } : { [sequelizeOperator]: valueIsField ? col(value) : shouldRenderAsNumber(value, parseNumbers) ? parseNumber(value, { parseNumbers: "strict" }) : value } };
2261
2561
  }
2262
- case "contains": return { [field]: { [Op.substring]: valueIsField ? col(value) : `${value}` } };
2263
- case "beginswith": return { [field]: { [Op.startsWith]: valueIsField ? col(value) : `${value}` } };
2264
- 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}` } };
2265
2565
  case "doesnotcontain": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value), "%") : `%${value}%` } };
2266
2566
  case "doesnotbeginwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", col(value), "%") : `${value}%` } };
2267
2567
  case "doesnotendwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value)) : `%${value}` } };
@@ -2291,6 +2591,68 @@ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder,
2291
2591
  }
2292
2592
  };
2293
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
2294
2656
  //#region src/utils/formatQuery/formatQuery.ts
2295
2657
  /**
2296
2658
  * A collection of option presets for {@link formatQuery}, specifically for SQL-based formats.
@@ -2338,6 +2700,10 @@ const defaultRuleProcessors = {
2338
2700
  sequelize: defaultRuleProcessorSequelize,
2339
2701
  spel: defaultRuleProcessorSpEL,
2340
2702
  sql: defaultRuleProcessorSQL,
2703
+ cypher: defaultRuleProcessorCypher,
2704
+ gql: defaultRuleProcessorCypher,
2705
+ sparql: defaultRuleProcessorSPARQL,
2706
+ gremlin: defaultRuleProcessorGremlin,
2341
2707
  diagnostics: defaultRuleProcessorSQL
2342
2708
  };
2343
2709
  /* v8 ignore next -- @preserve */
@@ -2360,6 +2726,10 @@ const defaultOperatorProcessors = {
2360
2726
  sequelize: defaultOperatorProcessor,
2361
2727
  spel: defaultOperatorProcessor,
2362
2728
  sql: defaultOperatorProcessorSQL,
2729
+ cypher: defaultOperatorProcessor,
2730
+ gql: defaultOperatorProcessor,
2731
+ sparql: defaultOperatorProcessor,
2732
+ gremlin: defaultOperatorProcessor,
2363
2733
  diagnostics: defaultOperatorProcessor
2364
2734
  };
2365
2735
  const defaultFallbackExpressions = {
@@ -2367,6 +2737,8 @@ const defaultFallbackExpressions = {
2367
2737
  ldap: "",
2368
2738
  mongodb: "\"$and\":[{\"$expr\":true}]",
2369
2739
  natural_language: "1 is 1",
2740
+ sparql: "1 = 1",
2741
+ gremlin: "",
2370
2742
  spel: "1 == 1",
2371
2743
  sql: "(1 = 1)"
2372
2744
  };
@@ -2507,6 +2879,10 @@ function formatQuery(ruleGroup, optionParam = {}) {
2507
2879
  case "prisma": return defaultRuleGroupProcessorPrisma(ruleGroup, finalOptions);
2508
2880
  case "drizzle": return defaultRuleGroupProcessorDrizzle(ruleGroup, finalOptions);
2509
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);
2510
2886
  case "diagnostics": return defaultRuleGroupProcessorDiagnostics(ruleGroup, finalOptions);
2511
2887
  default: return "";
2512
2888
  }
@@ -2562,6 +2938,6 @@ const defaultValueProcessorMongoDBByRule = defaultRuleProcessorMongoDB;
2562
2938
  */
2563
2939
  const defaultValueProcessorSpELByRule = defaultRuleProcessorSpEL;
2564
2940
  //#endregion
2565
- export { bigIntJsonParseReviver, bigIntJsonStringifyReplacer, celCombinatorMap, defaultCELValueProcessor, defaultExportOperatorMap, defaultMongoDBValueProcessor, defaultNLTranslations, defaultOperatorProcessorNL, defaultOperatorProcessorSQL, defaultRuleGroupProcessorCEL, defaultRuleGroupProcessorDiagnostics, 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 };
2566
2942
 
2567
2943
  //# sourceMappingURL=formatQuery.mjs.map