@react-querybuilder/core 8.9.1 → 8.10.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 (106) hide show
  1. package/dist/arrayUtils-C9sO4qLO.mjs +50 -0
  2. package/dist/arrayUtils-C9sO4qLO.mjs.map +1 -0
  3. package/dist/arrayUtils-QxZOZTf6.js +73 -0
  4. package/dist/arrayUtils-QxZOZTf6.js.map +1 -0
  5. package/dist/basic-BmpEwexQ.d.mts +363 -0
  6. package/dist/basic-CDDA-KZa.d.ts +363 -0
  7. package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +569 -1252
  8. package/dist/cjs/react-querybuilder_core.cjs.development.js +430 -140
  9. package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -1
  10. package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +569 -1252
  11. package/dist/cjs/react-querybuilder_core.cjs.production.js +1 -1
  12. package/dist/cjs/react-querybuilder_core.cjs.production.js.map +1 -1
  13. package/dist/convertQuery-BUgyz1GA.mjs +75 -0
  14. package/dist/convertQuery-BUgyz1GA.mjs.map +1 -0
  15. package/dist/export-Ccjfea21.d.mts +453 -0
  16. package/dist/{export-DyrnTh6K.d.ts → export-GUuxJ7zR.d.ts} +3 -2
  17. package/dist/formatQuery.d.mts +668 -0
  18. package/dist/formatQuery.d.ts +3 -2
  19. package/dist/formatQuery.js +217 -87
  20. package/dist/formatQuery.js.map +1 -1
  21. package/dist/formatQuery.mjs +2496 -0
  22. package/dist/formatQuery.mjs.map +1 -0
  23. package/dist/{import-Cksobmln.d.ts → import-D-hm1phN.d.ts} +2 -2
  24. package/dist/import-Dxevzw_-.d.mts +28 -0
  25. package/dist/isRuleGroup-CGe_rb2w.mjs +40 -0
  26. package/dist/isRuleGroup-CGe_rb2w.mjs.map +1 -0
  27. package/dist/isRuleGroup-DqAs2x4E.js.map +1 -1
  28. package/dist/{optGroupUtils-CXLgyg2i.js → optGroupUtils-B0hTpodo.js} +114 -1
  29. package/dist/optGroupUtils-B0hTpodo.js.map +1 -0
  30. package/dist/optGroupUtils-DrubUpx0.mjs +185 -0
  31. package/dist/optGroupUtils-DrubUpx0.mjs.map +1 -0
  32. package/dist/parseCEL.d.mts +315 -0
  33. package/dist/parseCEL.d.ts +292 -11
  34. package/dist/parseCEL.js +114 -30
  35. package/dist/parseCEL.js.map +1 -1
  36. package/dist/parseCEL.mjs +2631 -0
  37. package/dist/parseCEL.mjs.map +1 -0
  38. package/dist/parseJSONata.d.mts +37 -0
  39. package/dist/parseJSONata.d.ts +3 -2
  40. package/dist/parseJSONata.js +49 -77
  41. package/dist/parseJSONata.js.map +1 -1
  42. package/dist/parseJSONata.mjs +267 -0
  43. package/dist/parseJSONata.mjs.map +1 -0
  44. package/dist/parseJsonLogic.d.mts +37 -0
  45. package/dist/parseJsonLogic.d.ts +4 -3
  46. package/dist/parseJsonLogic.js +5 -6
  47. package/dist/parseJsonLogic.js.map +1 -1
  48. package/dist/parseJsonLogic.mjs +190 -0
  49. package/dist/parseJsonLogic.mjs.map +1 -0
  50. package/dist/parseMongoDB.d.mts +80 -0
  51. package/dist/parseMongoDB.d.ts +3 -2
  52. package/dist/parseMongoDB.js +15 -16
  53. package/dist/parseMongoDB.js.map +1 -1
  54. package/dist/parseMongoDB.mjs +266 -0
  55. package/dist/parseMongoDB.mjs.map +1 -0
  56. package/dist/parseNumber-B_-sR6d5.mjs +24 -0
  57. package/dist/parseNumber-B_-sR6d5.mjs.map +1 -0
  58. package/dist/{parseNumber-Bcys1kOH.js → parseNumber-D4iQDxK-.js} +1 -1
  59. package/dist/{parseNumber-Bcys1kOH.js.map → parseNumber-D4iQDxK-.js.map} +1 -1
  60. package/dist/parseSQL.d.mts +38 -0
  61. package/dist/parseSQL.d.ts +3 -2
  62. package/dist/parseSQL.js +11 -15
  63. package/dist/parseSQL.js.map +1 -1
  64. package/dist/parseSQL.mjs +6622 -0
  65. package/dist/parseSQL.mjs.map +1 -0
  66. package/dist/parseSpEL.d.mts +35 -0
  67. package/dist/parseSpEL.d.ts +3 -2
  68. package/dist/parseSpEL.js +7 -9
  69. package/dist/parseSpEL.js.map +1 -1
  70. package/dist/parseSpEL.mjs +272 -0
  71. package/dist/parseSpEL.mjs.map +1 -0
  72. package/dist/{prepareQueryObjects-BqFEs4eV.js → prepareQueryObjects-BOUWfel5.js} +4 -5
  73. package/dist/prepareQueryObjects-BOUWfel5.js.map +1 -0
  74. package/dist/prepareQueryObjects-CJNpnGcJ.mjs +153 -0
  75. package/dist/prepareQueryObjects-CJNpnGcJ.mjs.map +1 -0
  76. package/dist/query-builder-layout.css +1 -1
  77. package/dist/query-builder-layout.css.map +1 -1
  78. package/dist/query-builder.css +1 -1
  79. package/dist/query-builder.css.map +1 -1
  80. package/dist/react-querybuilder_core.d.mts +569 -1252
  81. package/dist/react-querybuilder_core.legacy-esm.d.ts +569 -1252
  82. package/dist/react-querybuilder_core.legacy-esm.js +430 -136
  83. package/dist/react-querybuilder_core.legacy-esm.js.map +1 -1
  84. package/dist/react-querybuilder_core.mjs +426 -141
  85. package/dist/react-querybuilder_core.mjs.map +1 -1
  86. package/dist/react-querybuilder_core.production.d.mts +569 -1252
  87. package/dist/react-querybuilder_core.production.mjs +1 -1
  88. package/dist/react-querybuilder_core.production.mjs.map +1 -1
  89. package/dist/styles/_layout.scss +61 -17
  90. package/dist/styles/_main.scss +17 -4
  91. package/dist/{transformQuery-FL_nlpp5.js → transformQuery-CWDPogO5.js} +1 -1
  92. package/dist/{transformQuery-FL_nlpp5.js.map → transformQuery-CWDPogO5.js.map} +1 -1
  93. package/dist/transformQuery-DHvtgDgZ.mjs +41 -0
  94. package/dist/transformQuery-DHvtgDgZ.mjs.map +1 -0
  95. package/dist/transformQuery.d.mts +118 -0
  96. package/dist/transformQuery.d.ts +1 -1
  97. package/dist/transformQuery.js +1 -1
  98. package/dist/transformQuery.mjs +4 -0
  99. package/package.json +78 -28
  100. package/dist/arrayUtils-D5EoIsKP.js +0 -164
  101. package/dist/arrayUtils-D5EoIsKP.js.map +0 -1
  102. package/dist/basic-C8xXKHIA.d.ts +0 -1235
  103. package/dist/objectUtils-BBZSfZJz.js +0 -17
  104. package/dist/objectUtils-BBZSfZJz.js.map +0 -1
  105. package/dist/optGroupUtils-CXLgyg2i.js.map +0 -1
  106. package/dist/prepareQueryObjects-BqFEs4eV.js.map +0 -1
@@ -0,0 +1,2496 @@
1
+ import { defaultPlaceholderFieldName, defaultPlaceholderOperatorName, getOption, toFlatOptionArray, toFullOptionList } from "./optGroupUtils-DrubUpx0.mjs";
2
+ import { joinWith, splitBy, toArray, trimIfString } from "./arrayUtils-C9sO4qLO.mjs";
3
+ import { isPojo, isRuleGroup, isRuleGroupType, isRuleGroupTypeIC, lc, nullOrUndefinedOrEmpty, numericRegex } from "./isRuleGroup-CGe_rb2w.mjs";
4
+ import { parseNumber } from "./parseNumber-B_-sR6d5.mjs";
5
+ import { transformQuery } from "./transformQuery-DHvtgDgZ.mjs";
6
+ import { convertFromIC } from "./convertQuery-BUgyz1GA.mjs";
7
+ import { produce } from "immer";
8
+
9
+ //#region src/utils/isRuleOrGroupValid.ts
10
+ /**
11
+ * Determines if an object is useful as a validation result.
12
+ */
13
+ const isValidationResult = (vr) => isPojo(vr) && typeof vr.valid === "boolean";
14
+ /**
15
+ * Determines if a rule or group is valid based on a validation result (if defined)
16
+ * or a validator function. Returns `true` if neither are defined and the `muted`
17
+ * property is not `true`.
18
+ */
19
+ const isRuleOrGroupValid = (rg, validationResult, validator) => {
20
+ if (rg.muted) return false;
21
+ if (typeof validationResult === "boolean") return validationResult;
22
+ if (isValidationResult(validationResult)) return validationResult.valid;
23
+ if (typeof validator === "function" && !isRuleGroup(rg)) {
24
+ const vr = validator(rg);
25
+ if (typeof vr === "boolean") return vr;
26
+ // istanbul ignore else
27
+ if (isValidationResult(vr)) return vr.valid;
28
+ }
29
+ return true;
30
+ };
31
+
32
+ //#endregion
33
+ //#region src/utils/getParseNumberMethod.ts
34
+ const getParseNumberMethod = ({ parseNumbers, inputType }) => {
35
+ if (typeof parseNumbers === "string") {
36
+ const [method, level] = parseNumbers.split("-");
37
+ if (level === "limited") return inputType === "number" ? method : false;
38
+ return method;
39
+ }
40
+ return parseNumbers ? "strict" : false;
41
+ };
42
+
43
+ //#endregion
44
+ //#region src/utils/formatQuery/utils.ts
45
+ /**
46
+ * Maps a {@link DefaultOperatorName} to a SQL operator.
47
+ *
48
+ * @group Export
49
+ */
50
+ const mapSQLOperator = (rqbOperator) => {
51
+ switch (lc(rqbOperator)) {
52
+ case "null": return "is null";
53
+ case "notnull": return "is not null";
54
+ case "notin": return "not in";
55
+ case "notbetween": return "not between";
56
+ case "contains":
57
+ case "beginswith":
58
+ case "endswith": return "like";
59
+ case "doesnotcontain":
60
+ case "doesnotbeginwith":
61
+ case "doesnotendwith": return "not like";
62
+ default: return rqbOperator;
63
+ }
64
+ };
65
+ /**
66
+ * Maps a (lowercase) {@link DefaultOperatorName} to a MongoDB operator.
67
+ *
68
+ * @group Export
69
+ */
70
+ const mongoOperators = {
71
+ "=": "$eq",
72
+ "!=": "$ne",
73
+ "<": "$lt",
74
+ "<=": "$lte",
75
+ ">": "$gt",
76
+ ">=": "$gte",
77
+ in: "$in",
78
+ notin: "$nin",
79
+ notIn: "$nin"
80
+ };
81
+ /**
82
+ * Maps a (lowercase) {@link DefaultOperatorName} to a Prisma ORM operator.
83
+ *
84
+ * @group Export
85
+ */
86
+ const prismaOperators = {
87
+ "=": "equals",
88
+ "!=": "not",
89
+ "<": "lt",
90
+ "<=": "lte",
91
+ ">": "gt",
92
+ ">=": "gte",
93
+ in: "in",
94
+ notin: "notIn"
95
+ };
96
+ /**
97
+ * Maps a {@link DefaultCombinatorName} to a CEL combinator.
98
+ *
99
+ * @group Export
100
+ */
101
+ const celCombinatorMap = {
102
+ and: "&&",
103
+ or: "||"
104
+ };
105
+ /**
106
+ * Register these operators with `jsonLogic` before applying the result
107
+ * of `formatQuery(query, 'jsonlogic')`.
108
+ *
109
+ * @example
110
+ * ```
111
+ * for (const [op, func] of Object.entries(jsonLogicAdditionalOperators)) {
112
+ * jsonLogic.add_operation(op, func);
113
+ * }
114
+ * jsonLogic.apply({ "startsWith": [{ "var": "firstName" }, "Stev"] }, data);
115
+ * ```
116
+ *
117
+ * @group Export
118
+ */
119
+ const jsonLogicAdditionalOperators = {
120
+ startsWith: (a, b) => typeof a === "string" && a.startsWith(b),
121
+ endsWith: (a, b) => typeof a === "string" && a.endsWith(b)
122
+ };
123
+ /**
124
+ * Converts all `string`-type `value` properties of a query object into `number` where appropriate.
125
+ *
126
+ * Used by {@link formatQuery} for the `json*` formats when `parseNumbers` is `true`.
127
+ *
128
+ * @group Export
129
+ */
130
+ const numerifyValues = (rg, options) => ({
131
+ ...rg,
132
+ rules: rg.rules.map((r) => {
133
+ if (typeof r === "string") return r;
134
+ if (isRuleGroup(r)) return numerifyValues(r, options);
135
+ const fieldData = getOption(options.fields, r.field);
136
+ const parseNumbers = getParseNumberMethod({
137
+ parseNumbers: options.parseNumbers,
138
+ inputType: fieldData?.inputType
139
+ });
140
+ if (Array.isArray(r.value)) return {
141
+ ...r,
142
+ value: r.value.map((v) => parseNumber(v, { parseNumbers }))
143
+ };
144
+ const valAsArray = toArray(r.value, { retainEmptyStrings: true }).map((v) => parseNumber(v, { parseNumbers }));
145
+ if (valAsArray.every((v) => typeof v === "number")) {
146
+ // istanbul ignore else
147
+ if (valAsArray.length > 1) return {
148
+ ...r,
149
+ value: valAsArray
150
+ };
151
+ else if (valAsArray.length === 1) return {
152
+ ...r,
153
+ value: valAsArray[0]
154
+ };
155
+ }
156
+ return r;
157
+ })
158
+ });
159
+ /**
160
+ * Determines whether a value is _anything_ except an empty `string` or `NaN`.
161
+ *
162
+ * @group Export
163
+ */
164
+ const isValidValue = (value) => typeof value === "string" && value.length > 0 || typeof value === "number" && !Number.isNaN(value) || typeof value !== "string" && typeof value !== "number";
165
+ /**
166
+ * Determines whether {@link formatQuery} should render the given value as a number.
167
+ * As long as `parseNumbers` is `true`, `number` and `bigint` values will return `true` and
168
+ * `string` values will return `true` if they test positive against {@link numericRegex}.
169
+ *
170
+ * @group Export
171
+ */
172
+ const shouldRenderAsNumber = (value, parseNumbers) => !!parseNumbers && (typeof value === "number" || typeof value === "bigint" || typeof value === "string" && numericRegex.test(value));
173
+ /**
174
+ * Used by {@link formatQuery} to determine whether the given value processor is a
175
+ * "legacy" value processor by counting the number of arguments. Legacy value
176
+ * processors take 3 arguments (not counting any arguments with default values), while
177
+ * rule-based value processors take no more than 2 arguments.
178
+ *
179
+ * @group Export
180
+ */
181
+ const isValueProcessorLegacy = (valueProcessor) => valueProcessor.length >= 3;
182
+ /**
183
+ * Converts the `quoteFieldNamesWith` option into an array of two strings.
184
+ * If the option is a string, the array elements are both that string.
185
+ *
186
+ * @default
187
+ * ['', '']
188
+ *
189
+ * @group Export
190
+ */
191
+ const getQuoteFieldNamesWithArray = (quoteFieldNamesWith = ["", ""]) => Array.isArray(quoteFieldNamesWith) ? quoteFieldNamesWith : typeof quoteFieldNamesWith === "string" ? [quoteFieldNamesWith, quoteFieldNamesWith] : quoteFieldNamesWith ?? ["", ""];
192
+ /**
193
+ * Given a field name and relevant {@link ValueProcessorOptions}, returns the field name
194
+ * wrapped in the configured quote character(s).
195
+ *
196
+ * @group Export
197
+ */
198
+ const getQuotedFieldName = (fieldName, { quoteFieldNamesWith, fieldIdentifierSeparator }) => {
199
+ const [qPre, qPost] = getQuoteFieldNamesWithArray(quoteFieldNamesWith);
200
+ return typeof fieldIdentifierSeparator === "string" && fieldIdentifierSeparator.length > 0 ? joinWith(splitBy(fieldName, fieldIdentifierSeparator).map((part) => `${qPre}${part}${qPost}`), fieldIdentifierSeparator) : `${qPre}${fieldName}${qPost}`;
201
+ };
202
+ const defaultWordOrder = [
203
+ "S",
204
+ "V",
205
+ "O"
206
+ ];
207
+ /**
208
+ * Given a [Constituent word order](https://en.wikipedia.org/wiki/Word_order#Constituent_word_orders)
209
+ * like "svo" or "sov", returns a permutation of `["S", "V", "O"]` based on the first occurrence of
210
+ * each letter in the input string (case insensitive). This widens the valid input from abbreviations
211
+ * like "svo" to more expressive strings like "subject-verb-object" or "sub ver obj". Any missing
212
+ * letters are appended in the default order "SVO" (e.g., "object" would yield `["O", "S", "V"]`).
213
+ *
214
+ * @group Export
215
+ */
216
+ const normalizeConstituentWordOrder = (input) => {
217
+ const result = [];
218
+ const letterSet = new Set(defaultWordOrder);
219
+ for (const char of input.toUpperCase()) if (letterSet.has(char)) {
220
+ result.push(char);
221
+ letterSet.delete(char);
222
+ if (letterSet.size === 0) break;
223
+ }
224
+ for (const letter of defaultWordOrder) if (letterSet.has(letter)) result.push(letter);
225
+ return result;
226
+ };
227
+ /**
228
+ * Default translations used by {@link formatQuery} for "natural_language" format.
229
+ *
230
+ * @group Export
231
+ */
232
+ const defaultNLTranslations = {
233
+ groupPrefix: "",
234
+ groupPrefix_not_xor: "either zero or more than one of",
235
+ groupPrefix_xor: "exactly one of",
236
+ groupSuffix: "is true",
237
+ groupSuffix_not: "is not true"
238
+ };
239
+ /**
240
+ * Note: This function assumes `conditions.length > 0`
241
+ */
242
+ const translationMatchFilter = (key, keyToTest, conditions) => keyToTest.startsWith(key) && conditions.every((c) => keyToTest.includes(`_${c}`) && keyToTest.match(/_/g)?.length === conditions.length);
243
+ /**
244
+ * Used by {@link formatQuery} to get a translation based on certain conditions
245
+ * for the "natural_language" format.
246
+ *
247
+ * @group Export
248
+ */
249
+ const getNLTranslataion = (key, translations, conditions = []) => conditions.length === 0 ? translations[key] ?? defaultNLTranslations[key] ?? "" : Object.entries(translations).find(([keyToTest]) => translationMatchFilter(key, keyToTest, conditions))?.[1] ?? Object.entries(defaultNLTranslations).find(([keyToTest]) => translationMatchFilter(key, keyToTest, conditions))?.[1] ?? defaultNLTranslations[key] ?? "";
250
+ const processMatchMode = (rule) => {
251
+ const { mode, threshold } = rule.match ?? {};
252
+ if (mode) {
253
+ if (!isRuleGroup(rule.value)) return false;
254
+ const matchModeLC = lc(mode);
255
+ const matchModeCoerced = matchModeLC === "atleast" && threshold === 1 ? "some" : matchModeLC === "atmost" && threshold === 0 ? "none" : matchModeLC;
256
+ if ((matchModeCoerced === "atleast" || matchModeCoerced === "atmost" || matchModeCoerced === "exactly") && (typeof threshold !== "number" || threshold < 0)) return false;
257
+ return {
258
+ mode: matchModeCoerced,
259
+ threshold
260
+ };
261
+ }
262
+ };
263
+ /**
264
+ * "Replacer" method for JSON.stringify's second argument. Converts `bigint` values to
265
+ * objects with a `$bigint` property having a value of a string representation of
266
+ * the actual `bigint`-type value.
267
+ *
268
+ * Inverse of {@link bigIntJsonParseReviver}.
269
+ *
270
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json
271
+ */
272
+ const bigIntJsonStringifyReplacer = (_key, value) => typeof value === "bigint" ? { $bigint: value.toString() } : value;
273
+ /**
274
+ * "Reviver" method for JSON.parse's second argument. Converts objects having a single
275
+ * `$bigint: string` property to an actual `bigint` value.
276
+ *
277
+ * Inverse of {@link bigIntJsonStringifyReplacer}.
278
+ *
279
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json
280
+ */
281
+ const bigIntJsonParseReviver = (_key, value) => isPojo(value) && Object.keys(value).length === 1 && typeof value.$bigint === "string" ? BigInt(value.$bigint) : value;
282
+
283
+ //#endregion
284
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorCEL.ts
285
+ /**
286
+ * Rule group processor used by {@link formatQuery} for "cel" format.
287
+ *
288
+ * @group Export
289
+ */
290
+ const defaultRuleGroupProcessorCEL = (ruleGroup, options) => {
291
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
292
+ const processRuleGroup = (rg, outermost) => {
293
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
294
+ const processedRules = [];
295
+ let precedingCombinator = "";
296
+ let firstRule = true;
297
+ for (const rule of rg.rules) {
298
+ if (typeof rule === "string") {
299
+ precedingCombinator = celCombinatorMap[rule];
300
+ continue;
301
+ }
302
+ if (isRuleGroup(rule)) {
303
+ const processedGroup = processRuleGroup(rule);
304
+ if (processedGroup) {
305
+ if (!firstRule && precedingCombinator) {
306
+ processedRules.push(precedingCombinator);
307
+ precedingCombinator = "";
308
+ }
309
+ firstRule = false;
310
+ processedRules.push(processedGroup);
311
+ }
312
+ continue;
313
+ }
314
+ const [validationResult, fieldValidator] = validateRule(rule);
315
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
316
+ const fieldData = getOption(fields, rule.field);
317
+ const processedRule = ruleProcessor(rule, {
318
+ ...options,
319
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
320
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
321
+ fieldData
322
+ });
323
+ if (processedRule) {
324
+ if (!firstRule && precedingCombinator) {
325
+ processedRules.push(precedingCombinator);
326
+ precedingCombinator = "";
327
+ }
328
+ firstRule = false;
329
+ processedRules.push(processedRule);
330
+ }
331
+ }
332
+ const expression = processedRules.join(isRuleGroupType(rg) ? ` ${celCombinatorMap[rg.combinator]} ` : " ");
333
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "!" : ""}(`, ")"] : ["", ""];
334
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
335
+ };
336
+ return processRuleGroup(ruleGroup, true);
337
+ };
338
+
339
+ //#endregion
340
+ //#region src/utils/formatQuery/defaultRuleProcessorCEL.ts
341
+ const shouldNegate$2 = (op) => op.startsWith("not") || op.startsWith("doesnot");
342
+ const escapeDoubleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`);
343
+ /**
344
+ * Default rule processor used by {@link formatQuery} for "cel" format.
345
+ *
346
+ * @group Export
347
+ */
348
+ const defaultRuleProcessorCEL = (rule, opts = {}) => {
349
+ const { escapeQuotes, parseNumbers, preserveValueOrder } = opts;
350
+ const { field, operator, value, valueSource } = rule;
351
+ const valueIsField = valueSource === "field";
352
+ const operatorTL = lc(operator === "=" ? "==" : operator);
353
+ const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
354
+ const matchEval = processMatchMode(rule);
355
+ if (matchEval === false) return "";
356
+ else if (matchEval) {
357
+ const { mode, threshold } = matchEval;
358
+ const arrayElementAlias = "elem_alias";
359
+ const nestedArrayFilter = defaultRuleGroupProcessorCEL(transformQuery(rule.value, { ruleProcessor: (r) => ({
360
+ ...r,
361
+ field: `${arrayElementAlias}${r.field ? `.${r.field}` : ""}`
362
+ }) }), opts);
363
+ switch (mode) {
364
+ case "all": return `${field}.all(${arrayElementAlias}, ${nestedArrayFilter})`;
365
+ case "none":
366
+ case "some": return `${mode === "none" ? "!" : ""}${field}.exists(${arrayElementAlias}, ${nestedArrayFilter})`;
367
+ case "atleast":
368
+ case "atmost":
369
+ case "exactly": {
370
+ const totalCount = `double(${field}.size())`;
371
+ const filteredCount = `${field}.filter(${arrayElementAlias}, ${nestedArrayFilter}).size()`;
372
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "==";
373
+ if (threshold > 0 && threshold < 1) return `${filteredCount} ${op} (${totalCount} * ${threshold})`;
374
+ return `${filteredCount} ${op} ${threshold}`;
375
+ }
376
+ }
377
+ }
378
+ switch (operatorTL) {
379
+ case "<":
380
+ case "<=":
381
+ case "==":
382
+ case "!=":
383
+ case ">":
384
+ case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`}`;
385
+ case "contains":
386
+ case "doesnotcontain": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.contains(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
387
+ case "beginswith":
388
+ case "doesnotbeginwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.startsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
389
+ case "endswith":
390
+ case "doesnotendwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.endsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
391
+ case "null": return `${field} == null`;
392
+ case "notnull": return `${field} != null`;
393
+ case "in":
394
+ case "notin": {
395
+ const [prefix, suffix] = shouldNegate$2(operatorTL) ? ["!(", ")"] : ["", ""];
396
+ return `${prefix}${field} in [${toArray(value).map((val) => valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `"${escapeDoubleQuotes(val, escapeQuotes)}"`).join(", ")}]${suffix}`;
397
+ }
398
+ case "between":
399
+ case "notbetween": {
400
+ const valueAsArray = toArray(value);
401
+ if (valueAsArray.length >= 2 && !nullOrUndefinedOrEmpty(valueAsArray[0]) && !nullOrUndefinedOrEmpty(valueAsArray[1])) {
402
+ const [first, second] = valueAsArray;
403
+ const shouldParseNumbers = !(parseNumbers === false);
404
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
405
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
406
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `"${escapeDoubleQuotes(first, escapeQuotes)}"` : firstNum;
407
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `"${escapeDoubleQuotes(second, escapeQuotes)}"` : secondNum;
408
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
409
+ const tempNum = secondNum;
410
+ secondValue = firstNum;
411
+ firstValue = tempNum;
412
+ }
413
+ return operatorTL === "between" ? `(${field} >= ${firstValue} && ${field} <= ${secondValue})` : `(${field} < ${firstValue} || ${field} > ${secondValue})`;
414
+ } else return "";
415
+ }
416
+ }
417
+ return "";
418
+ };
419
+
420
+ //#endregion
421
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorMongoDBQuery.ts
422
+ /**
423
+ * Default fallback object used by {@link formatQuery} for "mongodb_query" format.
424
+ *
425
+ * @group Export
426
+ */
427
+ const mongoDbFallback = { $and: [{ $expr: true }] };
428
+ /**
429
+ * Rule group processor used by {@link formatQuery} for "mongodb_query" format.
430
+ *
431
+ * @group Export
432
+ */
433
+ const defaultRuleGroupProcessorMongoDBQuery = (ruleGroup, options, meta) => {
434
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
435
+ const processRuleGroup = (rg, outermost) => {
436
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? mongoDbFallback : false;
437
+ const combinator = `$${lc(rg.combinator)}`;
438
+ let hasChildRules = false;
439
+ const expressions = rg.rules.map((rule) => {
440
+ if (isRuleGroup(rule)) {
441
+ const processedRuleGroup = processRuleGroup(rule);
442
+ if (processedRuleGroup) {
443
+ hasChildRules = true;
444
+ return processedRuleGroup;
445
+ }
446
+ return false;
447
+ }
448
+ const [validationResult, fieldValidator] = validateRule(rule);
449
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return false;
450
+ const fieldData = getOption(fields, rule.field);
451
+ return ruleProcessor(rule, {
452
+ ...options,
453
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
454
+ fieldData
455
+ }, meta);
456
+ }).filter(Boolean);
457
+ return expressions.length > 0 ? expressions.length === 1 && !hasChildRules ? expressions[0] : { [combinator]: expressions } : mongoDbFallback;
458
+ };
459
+ return processRuleGroup(convertFromIC(ruleGroup), true);
460
+ };
461
+
462
+ //#endregion
463
+ //#region src/utils/formatQuery/defaultRuleProcessorMongoDBQuery.ts
464
+ const processNumber$1 = (value, fallback, parseNumbers = false) => shouldRenderAsNumber(value, parseNumbers || typeof value === "bigint") ? Number(parseNumber(value, { parseNumbers: "strict" })) : fallback;
465
+ /**
466
+ * Default rule processor used by {@link formatQuery} for "mongodb_query" format.
467
+ *
468
+ * @group Export
469
+ */
470
+ const defaultRuleProcessorMongoDBQuery = (rule, options = {}) => {
471
+ const { field, operator, value, valueSource } = rule;
472
+ const { parseNumbers, preserveValueOrder, context } = options;
473
+ const valueIsField = valueSource === "field";
474
+ const { avoidFieldsAsKeys } = context ?? {};
475
+ const matchEval = processMatchMode(rule);
476
+ if (matchEval === false) return;
477
+ else if (matchEval) {
478
+ const { mode, threshold } = matchEval;
479
+ const totalCount = { $size: { $ifNull: [`$${field}`, []] } };
480
+ const subQueryNoAggCtx = defaultRuleGroupProcessorMongoDBQuery(transformQuery(value, { ruleProcessor: (r) => ({
481
+ ...r,
482
+ field: r.field ? `${field}.${r.field}` : field
483
+ }) }), {
484
+ ...options,
485
+ ruleProcessor: defaultRuleProcessorMongoDBQuery,
486
+ context: {
487
+ ...options.context,
488
+ avoidFieldsAsKeys: false
489
+ }
490
+ });
491
+ const subQueryWithAggCtx = defaultRuleGroupProcessorMongoDBQuery(transformQuery(value, { ruleProcessor: (r) => ({
492
+ ...r,
493
+ field: r.field ? `$item.${r.field}` : "$item"
494
+ }) }), {
495
+ ...options,
496
+ ruleProcessor: defaultRuleProcessorMongoDBQuery,
497
+ context: {
498
+ ...options.context,
499
+ avoidFieldsAsKeys: true
500
+ }
501
+ });
502
+ const filteredCount = { $size: { $ifNull: [{ $filter: {
503
+ input: `$${field}`,
504
+ as: "item",
505
+ cond: { $and: [subQueryWithAggCtx] }
506
+ } }, []] } };
507
+ switch (mode) {
508
+ case "all": return { $expr: { $eq: [filteredCount, totalCount] } };
509
+ case "none": return { $nor: [subQueryNoAggCtx] };
510
+ case "some": return subQueryNoAggCtx;
511
+ case "atleast":
512
+ case "atmost":
513
+ case "exactly": {
514
+ const op = mode === "atleast" ? mongoOperators[">="] : mode === "atmost" ? mongoOperators["<="] : mongoOperators["="];
515
+ if (threshold > 0 && threshold < 1) return { $expr: { [op]: [filteredCount, { $multiply: [totalCount, threshold] }] } };
516
+ return { $expr: { [op]: [filteredCount, threshold] } };
517
+ }
518
+ }
519
+ }
520
+ if (operator === "=" && !valueIsField) return avoidFieldsAsKeys ? { $eq: [`$${field}`, processNumber$1(value, value, parseNumbers)] } : { [field]: processNumber$1(value, value, parseNumbers) };
521
+ const operatorLC = lc(operator);
522
+ switch (operatorLC) {
523
+ case "<":
524
+ case "<=":
525
+ case "=":
526
+ case "!=":
527
+ case ">":
528
+ case ">=": {
529
+ const mongoOperator = mongoOperators[operatorLC];
530
+ return valueIsField ? { [mongoOperator]: [`$${field}`, `$${value}`] } : avoidFieldsAsKeys ? { $and: [{ $ne: [`$${field}`, null] }, { [mongoOperator]: [`$${field}`, processNumber$1(value, value, parseNumbers)] }] } : { [field]: { [mongoOperator]: processNumber$1(value, value, parseNumbers) } };
531
+ }
532
+ case "contains": return valueIsField ? { $where: `this.${field}.includes(this.${value})` } : avoidFieldsAsKeys ? { $regexMatch: {
533
+ input: `$${field}`,
534
+ regex: value
535
+ } } : { [field]: { $regex: value } };
536
+ case "beginswith": return valueIsField ? { $where: `this.${field}.startsWith(this.${value})` } : avoidFieldsAsKeys ? { $regexMatch: {
537
+ input: `$${field}`,
538
+ regex: `^${value}`
539
+ } } : { [field]: { $regex: `^${value}` } };
540
+ case "endswith": return valueIsField ? { $where: `this.${field}.endsWith(this.${value})` } : avoidFieldsAsKeys ? { $regexMatch: {
541
+ input: `$${field}`,
542
+ regex: `${value}$`
543
+ } } : { [field]: { $regex: `${value}$` } };
544
+ case "doesnotcontain": return valueIsField ? { $where: `!this.${field}.includes(this.${value})` } : avoidFieldsAsKeys ? { $not: { $regexMatch: {
545
+ input: `$${field}`,
546
+ regex: value
547
+ } } } : { [field]: { $not: { $regex: value } } };
548
+ case "doesnotbeginwith": return valueIsField ? { $where: `!this.${field}.startsWith(this.${value})` } : avoidFieldsAsKeys ? { $not: { $regexMatch: {
549
+ input: `$${field}`,
550
+ regex: `^${value}`
551
+ } } } : { [field]: { $not: { $regex: `^${value}` } } };
552
+ case "doesnotendwith": return valueIsField ? { $where: `!this.${field}.endsWith(this.${value})` } : avoidFieldsAsKeys ? { $not: { $regexMatch: {
553
+ input: `$${field}`,
554
+ regex: `${value}$`
555
+ } } } : { [field]: { $not: { $regex: `${value}$` } } };
556
+ case "null": return avoidFieldsAsKeys ? { $eq: [`$${field}`, null] } : { [field]: null };
557
+ case "notnull": return avoidFieldsAsKeys ? { $ne: [`$${field}`, null] } : { [field]: { $ne: null } };
558
+ case "in":
559
+ case "notin": {
560
+ const valueAsArray = toArray(value);
561
+ return valueIsField ? { $where: `${operatorLC === "notin" ? "!" : ""}[${valueAsArray.map((val) => `this.${val}`).join(",")}].includes(this.${field})` } : avoidFieldsAsKeys ? operatorLC === "notin" ? { $not: { [mongoOperators.in]: [`$${field}`, valueAsArray.map((val) => processNumber$1(val, val, parseNumbers))] } } : { [mongoOperators[operatorLC]]: [`$${field}`, valueAsArray.map((val) => processNumber$1(val, val, parseNumbers))] } : { [field]: { [mongoOperators[operatorLC]]: valueAsArray.map((val) => processNumber$1(val, val, parseNumbers)) } };
562
+ }
563
+ case "between":
564
+ case "notbetween": {
565
+ const valueAsArray = toArray(value);
566
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
567
+ const [first, second] = valueAsArray;
568
+ const firstNum = processNumber$1(first, NaN, true);
569
+ const secondNum = processNumber$1(second, NaN, true);
570
+ let firstValue = valueIsField ? first : Number.isNaN(firstNum) ? first : firstNum;
571
+ let secondValue = valueIsField ? second : Number.isNaN(secondNum) ? second : secondNum;
572
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
573
+ const tempNum = secondNum;
574
+ secondValue = firstNum;
575
+ firstValue = tempNum;
576
+ }
577
+ if (operatorLC === "between") return valueIsField ? {
578
+ $gte: [`$${field}`, `$${firstValue}`],
579
+ $lte: [`$${field}`, `$${secondValue}`]
580
+ } : avoidFieldsAsKeys ? { $and: [{ $gte: [`$${field}`, firstValue] }, { $lte: [`$${field}`, secondValue] }] } : { [field]: {
581
+ $gte: firstValue,
582
+ $lte: secondValue
583
+ } };
584
+ else return valueIsField ? { $or: [{ $lt: [`$${field}`, `$${firstValue}`] }, { $gt: [`$${field}`, `$${secondValue}`] }] } : avoidFieldsAsKeys ? { $or: [{ $lt: [`$${field}`, firstValue] }, { $gt: [`$${field}`, secondValue] }] } : { $or: [{ [field]: { $lt: firstValue } }, { [field]: { $gt: secondValue } }] };
585
+ } else return "";
586
+ }
587
+ }
588
+ return "";
589
+ };
590
+
591
+ //#endregion
592
+ //#region src/utils/formatQuery/defaultRuleProcessorMongoDB.ts
593
+ /**
594
+ * Default rule processor used by {@link formatQuery} for "mongodb" format.
595
+ *
596
+ * Note that the "mongodb" format is deprecated in favor of the "mongodb_query" format.
597
+ *
598
+ * @group Export
599
+ */
600
+ const defaultRuleProcessorMongoDB = (rule, options) => {
601
+ const queryObj = defaultRuleProcessorMongoDBQuery(rule, options);
602
+ return queryObj ? JSON.stringify(queryObj) : "";
603
+ };
604
+
605
+ //#endregion
606
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSpEL.ts
607
+ /**
608
+ * Default rule processor used by {@link formatQuery} for "spel" format.
609
+ *
610
+ * @group Export
611
+ */
612
+ const defaultRuleGroupProcessorSpEL = (ruleGroup, options) => {
613
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
614
+ const processRuleGroup = (rg, outermost) => {
615
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
616
+ const processedRules = [];
617
+ let precedingCombinator = "";
618
+ let firstRule = true;
619
+ for (const rule of rg.rules) {
620
+ if (typeof rule === "string") {
621
+ precedingCombinator = rule;
622
+ continue;
623
+ }
624
+ if (isRuleGroup(rule)) {
625
+ const processedGroup = processRuleGroup(rule);
626
+ if (processedGroup) {
627
+ if (!firstRule && precedingCombinator) {
628
+ processedRules.push(precedingCombinator);
629
+ precedingCombinator = "";
630
+ }
631
+ firstRule = false;
632
+ processedRules.push(processedGroup);
633
+ }
634
+ continue;
635
+ }
636
+ const [validationResult, fieldValidator] = validateRule(rule);
637
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
638
+ const fieldData = getOption(fields, rule.field);
639
+ const processedRule = ruleProcessor(rule, {
640
+ ...options,
641
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
642
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
643
+ fieldData
644
+ });
645
+ if (processedRule) {
646
+ if (!firstRule && precedingCombinator) {
647
+ processedRules.push(precedingCombinator);
648
+ precedingCombinator = "";
649
+ }
650
+ firstRule = false;
651
+ processedRules.push(processedRule);
652
+ }
653
+ }
654
+ const expression = processedRules.join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ");
655
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "!" : ""}(`, ")"] : ["", ""];
656
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
657
+ };
658
+ return processRuleGroup(ruleGroup, true);
659
+ };
660
+
661
+ //#endregion
662
+ //#region src/utils/formatQuery/defaultRuleProcessorSpEL.ts
663
+ const shouldNegate$1 = (op) => op.startsWith("not") || op.startsWith("doesnot");
664
+ const wrapInNegation = (clause, negate$1) => negate$1 ? `!(${clause})` : clause;
665
+ const escapeSingleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`'`, `\\'`);
666
+ /**
667
+ * Default rule processor used by {@link formatQuery} for "spel" format.
668
+ *
669
+ * @group Export
670
+ */
671
+ const defaultRuleProcessorSpEL = (rule, opts = {}) => {
672
+ const { field, operator, value, valueSource } = rule;
673
+ const { escapeQuotes, parseNumbers, preserveValueOrder } = opts;
674
+ const valueIsField = valueSource === "field";
675
+ const operatorTL = lc(operator === "=" ? "==" : operator);
676
+ const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
677
+ const matchEval = processMatchMode(rule);
678
+ if (matchEval === false) return "";
679
+ else if (matchEval) {
680
+ const { mode, threshold } = matchEval;
681
+ const nestedArrayFilter = defaultRuleGroupProcessorSpEL(transformQuery(rule.value, { ruleProcessor: (r) => ({
682
+ ...r,
683
+ field: r.field || "#this"
684
+ }) }), opts);
685
+ const totalCount = `${field}.size()`;
686
+ const filteredCount = `${field}.?[${nestedArrayFilter}].size()`;
687
+ switch (mode) {
688
+ case "all": return `${filteredCount} == ${totalCount}`;
689
+ case "none": return `${filteredCount} == 0`;
690
+ case "some": return `${filteredCount} >= 1`;
691
+ case "atleast":
692
+ case "atmost":
693
+ case "exactly": {
694
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "==";
695
+ if (threshold > 0 && threshold < 1) return `${filteredCount} ${op} (${totalCount} * ${threshold})`;
696
+ return `${filteredCount} ${op} ${threshold}`;
697
+ }
698
+ }
699
+ }
700
+ switch (operatorTL) {
701
+ case "<":
702
+ case "<=":
703
+ case "==":
704
+ case "!=":
705
+ case ">":
706
+ case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`;
707
+ case "contains":
708
+ case "doesnotcontain": return wrapInNegation(`${field} matches ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
709
+ case "beginswith":
710
+ case "doesnotbeginwith": return wrapInNegation(`${field} matches ${valueIsField ? `'^'.concat(${trimIfString(value)})` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
711
+ case "endswith":
712
+ case "doesnotendwith": return wrapInNegation(`${field} matches ${valueIsField ? `${trimIfString(value)}.concat('$')` : `'${escapeSingleQuotes(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`}`, shouldNegate$1(operatorTL));
713
+ case "null": return `${field} == null`;
714
+ case "notnull": return `${field} != null`;
715
+ case "in":
716
+ case "notin": {
717
+ const negate$1 = shouldNegate$1(operatorTL) ? "!" : "";
718
+ const valueAsArray = toArray(value);
719
+ return valueAsArray.length > 0 ? `${negate$1}(${valueAsArray.map((val) => `${field} == ${valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `'${escapeSingleQuotes(val, escapeQuotes)}'`}`).join(" or ")})` : "";
720
+ }
721
+ case "between":
722
+ case "notbetween": {
723
+ const valueAsArray = toArray(value);
724
+ if (valueAsArray.length >= 2 && !nullOrUndefinedOrEmpty(valueAsArray[0]) && !nullOrUndefinedOrEmpty(valueAsArray[1])) {
725
+ const [first, second] = valueAsArray;
726
+ const shouldParseNumbers = !(parseNumbers === false);
727
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
728
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
729
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `'${escapeSingleQuotes(first, escapeQuotes)}'` : firstNum;
730
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `'${escapeSingleQuotes(second, escapeQuotes)}'` : secondNum;
731
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
732
+ const tempNum = secondNum;
733
+ secondValue = firstNum;
734
+ firstValue = tempNum;
735
+ }
736
+ return operatorTL === "between" ? `(${field} >= ${firstValue} and ${field} <= ${secondValue})` : `(${field} < ${firstValue} or ${field} > ${secondValue})`;
737
+ } else return "";
738
+ }
739
+ }
740
+ return "";
741
+ };
742
+
743
+ //#endregion
744
+ //#region src/utils/formatQuery/defaultValueProcessorByRule.ts
745
+ const escapeStringValueQuotes$1 = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : v;
746
+ /**
747
+ * Default value processor used by {@link formatQuery} for "sql" format.
748
+ *
749
+ * @group Export
750
+ */
751
+ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQuotes, parseNumbers, preserveValueOrder, quoteFieldNamesWith, quoteValuesWith, concatOperator = "||", fieldIdentifierSeparator, wrapValueWith = ["", ""], translations } = {}) => {
752
+ const valueIsField = valueSource === "field";
753
+ const operatorLowerCase = lc(operator);
754
+ const quoteChar = quoteValuesWith || "'";
755
+ const quoteValue = (v) => `${wrapValueWith[0]}${quoteChar}${v}${quoteChar}${wrapValueWith[1]}`;
756
+ const escapeValue = (v) => escapeStringValueQuotes$1(v, quoteChar, escapeQuotes);
757
+ const wrapAndEscape = (v) => quoteValue(escapeValue(v));
758
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
759
+ quoteFieldNamesWith,
760
+ fieldIdentifierSeparator
761
+ });
762
+ const concat = (...values) => concatOperator.toUpperCase() === "CONCAT" ? `CONCAT(${values.join(", ")})` : values.join(` ${concatOperator} `);
763
+ switch (operatorLowerCase) {
764
+ case "null":
765
+ case "notnull": return "";
766
+ case "in":
767
+ case "notin": {
768
+ const valueAsArray = toArray(value);
769
+ if (valueAsArray.length > 0) return `(${valueAsArray.map((v) => valueIsField ? wrapFieldName(v) : shouldRenderAsNumber(v, parseNumbers) ? `${trimIfString(v)}` : `${wrapAndEscape(v)}`).join(", ")})`;
770
+ return "";
771
+ }
772
+ case "between":
773
+ case "notbetween": {
774
+ const valueAsArray = toArray(value, { retainEmptyStrings: true });
775
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return "";
776
+ const [first, second] = valueAsArray;
777
+ const firstNum = shouldRenderAsNumber(first, parseNumbers) ? parseNumber(first, { parseNumbers: "strict" }) : NaN;
778
+ const secondNum = shouldRenderAsNumber(second, parseNumbers) ? parseNumber(second, { parseNumbers: "strict" }) : NaN;
779
+ const firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : first : firstNum;
780
+ const secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : second : secondNum;
781
+ const valsOneAndTwoOnly = [firstValue, secondValue];
782
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
783
+ valsOneAndTwoOnly[0] = secondNum;
784
+ valsOneAndTwoOnly[1] = firstNum;
785
+ }
786
+ return (valueIsField ? valsOneAndTwoOnly.map((v) => wrapFieldName(v)) : valsOneAndTwoOnly.every((v) => shouldRenderAsNumber(v, parseNumbers)) ? valsOneAndTwoOnly.map((v) => parseNumber(v, { parseNumbers: "strict" })) : valsOneAndTwoOnly.map((v) => wrapAndEscape(v))).join(` ${translations?.and ?? "and"} `);
787
+ }
788
+ case "contains":
789
+ case "doesnotcontain": return valueIsField ? concat(quoteValue("%"), wrapFieldName(value), quoteValue("%")) : quoteValue(`%${escapeValue(value)}%`);
790
+ case "beginswith":
791
+ case "doesnotbeginwith": return valueIsField ? concat(wrapFieldName(value), quoteValue("%")) : quoteValue(`${escapeValue(value)}%`);
792
+ case "endswith":
793
+ case "doesnotendwith": return valueIsField ? concat(quoteValue("%"), wrapFieldName(value)) : quoteValue(`%${escapeValue(value)}`);
794
+ }
795
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
796
+ return valueIsField ? wrapFieldName(value) : shouldRenderAsNumber(value, parseNumbers) ? `${trimIfString(value)}` : `${wrapAndEscape(value)}`;
797
+ };
798
+
799
+ //#endregion
800
+ //#region src/utils/formatQuery/defaultRuleProcessorDrizzle.ts
801
+ /**
802
+ * Default rule processor used by {@link formatQuery} for the "drizzle" format.
803
+ *
804
+ * @group Export
805
+ */
806
+ const defaultRuleProcessorDrizzle = (rule, _options) => {
807
+ const opts = _options ?? ( /* istanbul ignore next */ {});
808
+ // istanbul ignore next
809
+ const { parseNumbers, preserveValueOrder, context = {} } = opts;
810
+ const { columns, drizzleOperators, useRawFields } = context;
811
+ if (!columns || !drizzleOperators) return;
812
+ const { between, eq, gt, gte, inArray, isNotNull, isNull, like, lt, lte, ne, notBetween, notInArray, notLike, sql } = drizzleOperators;
813
+ const { field, operator, value, valueSource } = rule;
814
+ const column = useRawFields && /[a-z][a-z0-9]*/i.test(field) ? sql.raw(field) : columns[field];
815
+ const operatorLC = lc(operator);
816
+ const valueIsField = valueSource === "field";
817
+ const asFieldOrValue = (v) => valueIsField ? columns[v] : v;
818
+ if (!column) return;
819
+ const matchEval = processMatchMode(rule);
820
+ if (matchEval === false) return;
821
+ else if (matchEval) {
822
+ if (opts.preset !== "postgresql") return;
823
+ const { mode, threshold } = matchEval;
824
+ const arrayElementAlias = "elem_alias";
825
+ const nestedArrayFilter = defaultRuleGroupProcessorDrizzle(transformQuery(rule.value, { ruleProcessor: (r) => ({
826
+ ...r,
827
+ field: arrayElementAlias
828
+ }) }), {
829
+ ...opts,
830
+ context: {
831
+ ...opts.context,
832
+ useRawFields: true
833
+ }
834
+ });
835
+ switch (mode) {
836
+ case "all": return sql`(select count(*) from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)}) = array_length(${column}, 1)`;
837
+ case "none": return sql`not exists (select 1 from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)})`;
838
+ case "some": return sql`exists (select 1 from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)})`;
839
+ case "atleast":
840
+ case "atmost":
841
+ case "exactly": {
842
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
843
+ return threshold > 0 && threshold < 1 ? sql`(select count(*) / array_length(${column}, 1) from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)}) ${sql.raw(`${op} ${threshold}`)}` : sql`(select count(*) from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)}) ${sql.raw(`${op} ${threshold}`)}`;
844
+ }
845
+ }
846
+ }
847
+ switch (operatorLC) {
848
+ case "=": return eq(column, asFieldOrValue(value));
849
+ case "!=": return ne(column, asFieldOrValue(value));
850
+ case ">": return gt(column, asFieldOrValue(value));
851
+ case "<": return lt(column, asFieldOrValue(value));
852
+ case ">=": return gte(column, asFieldOrValue(value));
853
+ case "<=": return lte(column, asFieldOrValue(value));
854
+ case "beginswith":
855
+ case "doesnotbeginwith": return (operatorLC === "doesnotbeginwith" ? notLike : like)(column, valueIsField ? sql`${asFieldOrValue(value)} || '%'` : `${value}%`);
856
+ case "contains":
857
+ case "doesnotcontain": return (operatorLC === "doesnotcontain" ? notLike : like)(column, valueIsField ? sql`'%' || ${asFieldOrValue(value)} || '%'` : `%${value}%`);
858
+ case "endswith":
859
+ case "doesnotendwith": return (operatorLC === "doesnotendwith" ? notLike : like)(column, valueIsField ? sql`'%' || ${asFieldOrValue(value)}` : `%${value}`);
860
+ case "null": return isNull(column);
861
+ case "notnull": return isNotNull(column);
862
+ case "in":
863
+ case "notin": {
864
+ const valueAsArray = toArray(value).map((v) => asFieldOrValue(v));
865
+ return operatorLC === "notin" ? notInArray(column, valueAsArray) : inArray(column, valueAsArray);
866
+ }
867
+ case "between":
868
+ case "notbetween": {
869
+ const valueAsArray = toArray(value);
870
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
871
+ let [first, second] = valueAsArray;
872
+ const shouldParseNumbers = !(parseNumbers === false);
873
+ if (!valueIsField && shouldRenderAsNumber(first, shouldParseNumbers) && shouldRenderAsNumber(second, shouldParseNumbers)) {
874
+ const firstNum = parseNumber(first, { parseNumbers: shouldParseNumbers });
875
+ const secondNum = parseNumber(second, { parseNumbers: shouldParseNumbers });
876
+ if (!preserveValueOrder && secondNum < firstNum) {
877
+ const tempNum = secondNum;
878
+ second = firstNum;
879
+ first = tempNum;
880
+ } else {
881
+ first = firstNum;
882
+ second = secondNum;
883
+ }
884
+ } else if (valueIsField) {
885
+ first = asFieldOrValue(first);
886
+ second = asFieldOrValue(second);
887
+ }
888
+ return operatorLC === "notbetween" ? notBetween(column, first, second) : between(column, first, second);
889
+ }
890
+ return;
891
+ }
892
+ default: return;
893
+ }
894
+ };
895
+
896
+ //#endregion
897
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorDrizzle.ts
898
+ /**
899
+ * Default rule group processor used by {@link formatQuery} for the "drizzle" format. The returned
900
+ * function can be assigned to the `where` property in the Drizzle relational queries API.
901
+ *
902
+ * @example
903
+ * const where = formatQuery(query, 'drizzle');
904
+ * const results = db.query.users.findMany({ where });
905
+ *
906
+ * @returns Function that takes a Drizzle table config and an object of Drizzle operators.
907
+ *
908
+ * @group Export
909
+ */
910
+ const defaultRuleGroupProcessorDrizzle = (ruleGroup, options, _meta) => (columns, drizzleOperators) => {
911
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, validateRule, validationMap } = options;
912
+ if (!columns || !drizzleOperators) return;
913
+ const { and, not, or } = drizzleOperators;
914
+ const ruleProcessor = defaultRuleProcessorDrizzle;
915
+ const processRuleGroup = (rg, _outermost) => {
916
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return;
917
+ const processedRules = rg.rules.map((rule) => {
918
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
919
+ const [validationResult, fieldValidator] = validateRule(rule);
920
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
921
+ const fieldData = getOption(fields, rule.field);
922
+ return ruleProcessor(rule, {
923
+ ...options,
924
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
925
+ fieldData,
926
+ context: {
927
+ ...options.context,
928
+ columns,
929
+ drizzleOperators
930
+ }
931
+ });
932
+ }).filter(Boolean);
933
+ if (processedRules.length === 0) return;
934
+ const ruleGroupSQL = rg.combinator === "or" ? or(...processedRules) : and(...processedRules);
935
+ return rg.not ? not(ruleGroupSQL) : ruleGroupSQL;
936
+ };
937
+ return processRuleGroup(convertFromIC(ruleGroup), true);
938
+ };
939
+
940
+ //#endregion
941
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorElasticSearch.ts
942
+ /**
943
+ * Rule group processor used by {@link formatQuery} for "elasticsearch" format.
944
+ *
945
+ * @group Export
946
+ */
947
+ const defaultRuleGroupProcessorElasticSearch = (ruleGroup, options) => {
948
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
949
+ const processRuleGroup = (rg) => {
950
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return false;
951
+ const processedRules = rg.rules.map((rule) => {
952
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
953
+ const [validationResult, fieldValidator] = validateRule(rule);
954
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return false;
955
+ const fieldData = getOption(fields, rule.field);
956
+ return ruleProcessor(rule, {
957
+ ...options,
958
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
959
+ fieldData
960
+ });
961
+ }).filter(Boolean);
962
+ if (processedRules.length === 0) return false;
963
+ return { bool: rg.not ? { must_not: /^or$/i.test(rg.combinator) ? { bool: { should: processedRules } } : processedRules } : { [/^or$/i.test(rg.combinator) ? "should" : "must"]: processedRules } };
964
+ };
965
+ const processedRuleGroup = processRuleGroup(convertFromIC(ruleGroup));
966
+ return processedRuleGroup === false ? {} : processedRuleGroup;
967
+ };
968
+
969
+ //#endregion
970
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorJSONata.ts
971
+ /**
972
+ * Rule group processor used by {@link formatQuery} for "jsonata" format.
973
+ *
974
+ * @group Export
975
+ */
976
+ const defaultRuleGroupProcessorJSONata = (ruleGroup, options) => {
977
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
978
+ const processRuleGroup = (rg, outermost) => {
979
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
980
+ const processedRules = [];
981
+ let precedingCombinator = "";
982
+ let firstRule = true;
983
+ for (const rule of rg.rules) {
984
+ if (typeof rule === "string") {
985
+ precedingCombinator = rule;
986
+ continue;
987
+ }
988
+ if (isRuleGroup(rule)) {
989
+ const processedGroup = processRuleGroup(rule);
990
+ if (processedGroup) {
991
+ if (!firstRule && precedingCombinator) {
992
+ processedRules.push(precedingCombinator);
993
+ precedingCombinator = "";
994
+ }
995
+ firstRule = false;
996
+ processedRules.push(processedGroup);
997
+ }
998
+ continue;
999
+ }
1000
+ const [validationResult, fieldValidator] = validateRule(rule);
1001
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
1002
+ const fieldData = getOption(fields, rule.field);
1003
+ const processedRule = ruleProcessor(rule, {
1004
+ ...options,
1005
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1006
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1007
+ fieldData
1008
+ });
1009
+ if (processedRule) {
1010
+ if (!firstRule && precedingCombinator) {
1011
+ processedRules.push(precedingCombinator);
1012
+ precedingCombinator = "";
1013
+ }
1014
+ firstRule = false;
1015
+ processedRules.push(processedRule);
1016
+ }
1017
+ }
1018
+ const expression = processedRules.join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ");
1019
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "$not" : ""}(`, ")"] : ["", ""];
1020
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1021
+ };
1022
+ return processRuleGroup(ruleGroup, true);
1023
+ };
1024
+
1025
+ //#endregion
1026
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorJsonLogic.ts
1027
+ /**
1028
+ * Rule group processor used by {@link formatQuery} for "jsonlogic" format.
1029
+ *
1030
+ * @group Export
1031
+ */
1032
+ const defaultRuleGroupProcessorJsonLogic = (ruleGroup, options) => {
1033
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1034
+ const query = convertFromIC(ruleGroup);
1035
+ const processRuleGroup = (rg, _outermost) => {
1036
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return false;
1037
+ const processedRules = rg.rules.map((rule) => {
1038
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1039
+ const [validationResult, fieldValidator] = validateRule(rule);
1040
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return false;
1041
+ const fieldData = getOption(fields, rule.field);
1042
+ return ruleProcessor(rule, {
1043
+ ...options,
1044
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1045
+ fieldData
1046
+ });
1047
+ }).filter(Boolean);
1048
+ if (processedRules.length === 0) return false;
1049
+ const jsonRuleGroup = { [rg.combinator]: processedRules };
1050
+ return rg.not ? { "!": jsonRuleGroup } : jsonRuleGroup;
1051
+ };
1052
+ return processRuleGroup(query, true);
1053
+ };
1054
+
1055
+ //#endregion
1056
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorLDAP.ts
1057
+ /**
1058
+ * Rule group processor used by {@link formatQuery} for "ldap" format.
1059
+ *
1060
+ * @group Export
1061
+ */
1062
+ const defaultRuleGroupProcessorLDAP = (ruleGroup, options) => {
1063
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1064
+ const processRuleGroup = (rg, outermost) => {
1065
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1066
+ const rules = rg.rules.map((rule) => {
1067
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1068
+ const [validationResult, fieldValidator] = validateRule(rule);
1069
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1070
+ const fieldData = getOption(fields, rule.field);
1071
+ return ruleProcessor(rule, {
1072
+ ...options,
1073
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1074
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1075
+ fieldData
1076
+ });
1077
+ }).filter(Boolean);
1078
+ const expression = rules.join("");
1079
+ const [notPrefix, notSuffix] = rg.not ? ["(!", ")"] : ["", ""];
1080
+ const [prefix, suffix] = rules.length > 1 ? [`${notPrefix}(${rg.combinator === "or" ? "|" : "&"}`, `)${notSuffix}`] : [notPrefix, notSuffix];
1081
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1082
+ };
1083
+ return processRuleGroup(convertFromIC(ruleGroup), true);
1084
+ };
1085
+
1086
+ //#endregion
1087
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorMongoDB.ts
1088
+ const isBracketed = (str) => str.startsWith("{") && str.endsWith("}");
1089
+ /**
1090
+ * Rule group processor used by {@link formatQuery} for "mongodb" format.
1091
+ *
1092
+ * Note that the "mongodb" format is deprecated in favor of the "mongodb_query" format.
1093
+ *
1094
+ * @group Export
1095
+ */
1096
+ const defaultRuleGroupProcessorMongoDB = (ruleGroup, options, meta) => {
1097
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1098
+ const processRuleGroup = (rg, outermost) => {
1099
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1100
+ const combinator = `"$${lc(rg.combinator)}"`;
1101
+ let hasChildRules = false;
1102
+ const expressions = rg.rules.map((rule) => {
1103
+ if (isRuleGroup(rule)) {
1104
+ const processedRuleGroup = processRuleGroup(rule);
1105
+ if (processedRuleGroup) {
1106
+ hasChildRules = true;
1107
+ return isBracketed(processedRuleGroup) ? processedRuleGroup : `{${processedRuleGroup}}`;
1108
+ }
1109
+ return "";
1110
+ }
1111
+ const [validationResult, fieldValidator] = validateRule(rule);
1112
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1113
+ const fieldData = getOption(fields, rule.field);
1114
+ return ruleProcessor(rule, {
1115
+ ...options,
1116
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1117
+ fieldData
1118
+ }, meta);
1119
+ }).filter(Boolean);
1120
+ return expressions.length > 0 ? expressions.length === 1 && !hasChildRules ? expressions[0] : `${combinator}:[${expressions.join(",")}]` : fallbackExpression;
1121
+ };
1122
+ const processedQuery = processRuleGroup(convertFromIC(ruleGroup), true);
1123
+ return isBracketed(processedQuery) ? processedQuery : `{${processedQuery}}`;
1124
+ };
1125
+
1126
+ //#endregion
1127
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorNL.ts
1128
+ /**
1129
+ * Rule group processor used by {@link formatQuery} for "natural_language" format.
1130
+ *
1131
+ * @group Export
1132
+ */
1133
+ const defaultRuleGroupProcessorNL = (ruleGroup, options) => {
1134
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, translations, validateRule, validationMap } = options;
1135
+ const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
1136
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
1137
+ const rg2 = isRuleGroupTypeIC(rg) && rg.rules.some((r) => typeof r === "string" && lc(r) === "xor") ? convertFromIC(rg) : rg;
1138
+ const processedRules = [];
1139
+ let precedingCombinator = "";
1140
+ let firstRule = true;
1141
+ for (const rule of rg2.rules) {
1142
+ if (typeof rule === "string") {
1143
+ precedingCombinator = `, ${translations[rule] ?? rule} `;
1144
+ continue;
1145
+ }
1146
+ if (isRuleGroup(rule)) {
1147
+ const processedGroup = processRuleGroup(rule, rg2.rules.length === 1 && !(rg2.not || /^xor$/i.test(rg2.combinator ?? "")));
1148
+ // istanbul ignore else
1149
+ if (processedGroup) {
1150
+ if (!firstRule && precedingCombinator) {
1151
+ processedRules.push(precedingCombinator);
1152
+ precedingCombinator = "";
1153
+ }
1154
+ firstRule = false;
1155
+ processedRules.push(processedGroup);
1156
+ }
1157
+ continue;
1158
+ }
1159
+ const [validationResult, fieldValidator] = validateRule(rule);
1160
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
1161
+ const escapeQuotes = (rule.valueSource ?? "value") === "value";
1162
+ const fieldData = getOption(fields, rule.field);
1163
+ const processedRule = ruleProcessor(rule, {
1164
+ ...options,
1165
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1166
+ escapeQuotes,
1167
+ fieldData
1168
+ });
1169
+ if (processedRule) {
1170
+ if (!firstRule && precedingCombinator) {
1171
+ processedRules.push(precedingCombinator);
1172
+ precedingCombinator = "";
1173
+ }
1174
+ firstRule = false;
1175
+ processedRules.push(processedRule);
1176
+ }
1177
+ }
1178
+ if (processedRules.length === 0) return fallbackExpression;
1179
+ const isXOR = lc(rg2.combinator ?? "") === "xor";
1180
+ const combinator = isXOR ? rg2.combinator.slice(1) : rg2.combinator;
1181
+ const mustWrap = rg2.not || !outermostOrLonelyInGroup || isXOR && processedRules.length > 1;
1182
+ const [prefixTL, suffixTL] = ["groupPrefix", "groupSuffix"].map((key) => rg2.not ? isXOR ? getNLTranslataion(key, translations, ["not", "xor"]) : getNLTranslataion(key, translations, ["not"]) : isXOR ? getNLTranslataion(key, translations, ["xor"]) : getNLTranslataion(key, translations));
1183
+ const prefix = mustWrap ? `${prefixTL} (`.trim() : "";
1184
+ const suffix = mustWrap ? `) ${suffixTL}`.trim() : "";
1185
+ return `${prefix}${processedRules.join(isRuleGroupType(rg2) ? `, ${translations[combinator] ?? combinator} ` : "")}${suffix}`;
1186
+ };
1187
+ return processRuleGroup(ruleGroup, true);
1188
+ };
1189
+
1190
+ //#endregion
1191
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorParameterized.ts
1192
+ /**
1193
+ * Rule group processor used by {@link formatQuery} for "parameterized" and
1194
+ * "parameterized_named" formats.
1195
+ *
1196
+ * @group Export
1197
+ */
1198
+ const defaultRuleGroupProcessorParameterized = (ruleGroup, options) => {
1199
+ const { format, fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1200
+ const parameterized = format === "parameterized";
1201
+ const params = [];
1202
+ const paramsNamed = {};
1203
+ const fieldParams = /* @__PURE__ */ new Map();
1204
+ const getNextNamedParam = (field) => {
1205
+ if (!fieldParams.has(field)) fieldParams.set(field, /* @__PURE__ */ new Set());
1206
+ const nextNamedParam = `${field}_${fieldParams.get(field).size + 1}`;
1207
+ fieldParams.get(field).add(nextNamedParam);
1208
+ return nextNamedParam;
1209
+ };
1210
+ const processRule = (rule) => {
1211
+ const [validationResult, fieldValidator] = validateRule(rule);
1212
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1213
+ const fieldData = getOption(fields, rule.field);
1214
+ const fieldParamNames = Object.fromEntries([...fieldParams.entries()].map(([f, s]) => [f, [...s]]));
1215
+ const processedRule = ruleProcessor(rule, {
1216
+ ...options,
1217
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1218
+ getNextNamedParam,
1219
+ fieldParamNames,
1220
+ fieldData
1221
+ }, { processedParams: params });
1222
+ if (!isPojo(processedRule)) return "";
1223
+ const { sql, params: customParams } = processedRule;
1224
+ if (typeof sql !== "string" || !sql) return "";
1225
+ // istanbul ignore else
1226
+ if (format === "parameterized" && Array.isArray(customParams)) params.push(...customParams);
1227
+ else if (format === "parameterized_named" && isPojo(customParams)) {
1228
+ Object.assign(paramsNamed, customParams);
1229
+ for (const p of Object.keys(customParams)) fieldParams.get(rule.field)?.add(p);
1230
+ }
1231
+ return sql;
1232
+ };
1233
+ const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
1234
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
1235
+ const processedRules = [];
1236
+ let precedingCombinator = "";
1237
+ let firstRule = true;
1238
+ for (const rule of rg.rules) {
1239
+ if (typeof rule === "string") {
1240
+ precedingCombinator = rule;
1241
+ continue;
1242
+ }
1243
+ if (isRuleGroup(rule)) {
1244
+ const processedGroup = processRuleGroup(rule, rg.rules.length === 1);
1245
+ // istanbul ignore else
1246
+ if (processedGroup) {
1247
+ if (!firstRule && precedingCombinator) {
1248
+ processedRules.push(precedingCombinator);
1249
+ precedingCombinator = "";
1250
+ }
1251
+ firstRule = false;
1252
+ processedRules.push(processedGroup);
1253
+ }
1254
+ continue;
1255
+ }
1256
+ const processedRule = processRule(rule);
1257
+ if (processedRule) {
1258
+ if (!firstRule && precedingCombinator) {
1259
+ processedRules.push(precedingCombinator);
1260
+ precedingCombinator = "";
1261
+ }
1262
+ firstRule = false;
1263
+ processedRules.push(processedRule);
1264
+ }
1265
+ }
1266
+ if (processedRules.length === 0) return fallbackExpression;
1267
+ return `${rg.not ? "NOT " : ""}(${processedRules.join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ")})`;
1268
+ };
1269
+ if (parameterized) return {
1270
+ sql: processRuleGroup(ruleGroup, true),
1271
+ params
1272
+ };
1273
+ return {
1274
+ sql: processRuleGroup(ruleGroup, true),
1275
+ params: paramsNamed
1276
+ };
1277
+ };
1278
+
1279
+ //#endregion
1280
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorPrisma.ts
1281
+ /**
1282
+ * Default fallback object used by {@link formatQuery} for "prisma" format.
1283
+ *
1284
+ * @group Export
1285
+ */
1286
+ const prismaFallback = {};
1287
+ /**
1288
+ * Rule group processor used by {@link formatQuery} for "prisma" format.
1289
+ *
1290
+ * @group Export
1291
+ */
1292
+ const defaultRuleGroupProcessorPrisma = (ruleGroup, options) => {
1293
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1294
+ const processRuleGroup = (rg, outermost) => {
1295
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? prismaFallback : void 0;
1296
+ const combinator = rg.combinator.toUpperCase();
1297
+ let hasChildRules = false;
1298
+ const expressions = rg.rules.map((rule) => {
1299
+ if (isRuleGroup(rule)) {
1300
+ const processedRuleGroup = processRuleGroup(rule);
1301
+ if (processedRuleGroup) {
1302
+ hasChildRules = true;
1303
+ return processedRuleGroup;
1304
+ }
1305
+ return;
1306
+ }
1307
+ const [validationResult, fieldValidator] = validateRule(rule);
1308
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
1309
+ const fieldData = getOption(fields, rule.field);
1310
+ return ruleProcessor(rule, {
1311
+ ...options,
1312
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1313
+ fieldData
1314
+ });
1315
+ }).filter(Boolean);
1316
+ return expressions.length > 0 ? expressions.length === 1 && !hasChildRules ? expressions[0] : { [combinator]: expressions } : prismaFallback;
1317
+ };
1318
+ const result = processRuleGroup(convertFromIC(ruleGroup), true);
1319
+ return ruleGroup.not ? { NOT: result } : result;
1320
+ };
1321
+
1322
+ //#endregion
1323
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSequelize.ts
1324
+ /**
1325
+ * Rule group processor used by {@link formatQuery} for "sequelize" format.
1326
+ *
1327
+ * @group Export
1328
+ */
1329
+ const defaultRuleGroupProcessorSequelize = (ruleGroup, options) => {
1330
+ // istanbul ignore next
1331
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap, context = {} } = options;
1332
+ const { sequelizeOperators: Op } = context;
1333
+ if (!Op) return;
1334
+ const processRuleGroup = (rg, _outermost) => {
1335
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return;
1336
+ const combinator = rg.combinator.toUpperCase();
1337
+ let hasChildRules = false;
1338
+ const expressions = rg.rules.map((rule) => {
1339
+ if (isRuleGroup(rule)) {
1340
+ const processedRuleGroup = processRuleGroup(rule);
1341
+ if (processedRuleGroup) {
1342
+ hasChildRules = true;
1343
+ return processedRuleGroup;
1344
+ }
1345
+ return;
1346
+ }
1347
+ const [validationResult, fieldValidator] = validateRule(rule);
1348
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
1349
+ const fieldData = getOption(fields, rule.field);
1350
+ return ruleProcessor(rule, {
1351
+ ...options,
1352
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1353
+ fieldData
1354
+ });
1355
+ }).filter(Boolean);
1356
+ if (expressions.length === 0) return;
1357
+ const result = expressions.length === 1 && !hasChildRules ? expressions[0] : { [lc(combinator) === "or" ? Op.or : Op.and]: expressions };
1358
+ return rg.not ? { [Op.not]: result } : result;
1359
+ };
1360
+ return processRuleGroup(convertFromIC(ruleGroup), true);
1361
+ };
1362
+
1363
+ //#endregion
1364
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSQL.ts
1365
+ /**
1366
+ * Default rule processor used by {@link formatQuery} for "sql" format.
1367
+ *
1368
+ * @group Export
1369
+ */
1370
+ const defaultRuleGroupProcessorSQL = (ruleGroup, options) => {
1371
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1372
+ const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
1373
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
1374
+ const processedRules = [];
1375
+ let precedingCombinator = "";
1376
+ let firstRule = true;
1377
+ for (const rule of rg.rules) {
1378
+ if (typeof rule === "string") {
1379
+ precedingCombinator = rule;
1380
+ continue;
1381
+ }
1382
+ if (isRuleGroup(rule)) {
1383
+ const processedGroup = processRuleGroup(rule, rg.rules.length === 1);
1384
+ // istanbul ignore else
1385
+ if (processedGroup) {
1386
+ if (!firstRule && precedingCombinator) {
1387
+ processedRules.push(precedingCombinator);
1388
+ precedingCombinator = "";
1389
+ }
1390
+ firstRule = false;
1391
+ processedRules.push(processedGroup);
1392
+ }
1393
+ continue;
1394
+ }
1395
+ const [validationResult, fieldValidator] = validateRule(rule);
1396
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) continue;
1397
+ const escapeQuotes = (rule.valueSource ?? "value") === "value";
1398
+ const fieldData = getOption(fields, rule.field);
1399
+ const processedRule = ruleProcessor(rule, {
1400
+ ...options,
1401
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1402
+ escapeQuotes,
1403
+ fieldData
1404
+ });
1405
+ if (processedRule) {
1406
+ if (!firstRule && precedingCombinator) {
1407
+ processedRules.push(precedingCombinator);
1408
+ precedingCombinator = "";
1409
+ }
1410
+ firstRule = false;
1411
+ processedRules.push(processedRule);
1412
+ }
1413
+ }
1414
+ if (processedRules.length === 0) return fallbackExpression;
1415
+ return `${rg.not ? "NOT " : ""}(${processedRules.join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ")})`;
1416
+ };
1417
+ return processRuleGroup(ruleGroup, true);
1418
+ };
1419
+
1420
+ //#endregion
1421
+ //#region src/utils/formatQuery/defaultRuleProcessorElasticSearch.ts
1422
+ const rangeOperatorMap = {
1423
+ "<": "lt",
1424
+ "<=": "lte",
1425
+ ">": "gt",
1426
+ ">=": "gte"
1427
+ };
1428
+ const negateIfNotOp$1 = (op, elasticSearchRule) => op.startsWith("not") || op.startsWith("doesnot") ? { bool: { must_not: elasticSearchRule } } : elasticSearchRule;
1429
+ const escapeSQ = (s) => s?.replace(/('|\\)/g, `\\$1`);
1430
+ const textFunctionMap = {
1431
+ beginswith: "startsWith",
1432
+ doesnotbeginwith: "startsWith",
1433
+ doesnotcontain: "contains",
1434
+ doesnotendwith: "endsWith",
1435
+ endswith: "endsWith"
1436
+ };
1437
+ const getTextScript = (f, o, v) => {
1438
+ const script = `doc['${f}'].value.${textFunctionMap[o] ?? o}(doc['${v}'].value)`;
1439
+ return o.startsWith("d") ? `!${script}` : script;
1440
+ };
1441
+ const valueRenderer = (v, parseNumbers) => typeof v === "boolean" ? v : shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
1442
+ /**
1443
+ * Default rule processor used by {@link formatQuery} for "elasticsearch" format.
1444
+ *
1445
+ * @group Export
1446
+ */
1447
+ const defaultRuleProcessorElasticSearch = (rule, options = {}) => {
1448
+ const { field, operator, value, valueSource } = rule;
1449
+ const { parseNumbers, preserveValueOrder } = options;
1450
+ const operatorLC = lc(operator);
1451
+ if (processMatchMode(rule)) return false;
1452
+ if (valueSource === "field") {
1453
+ if (toArray(value).some((v) => typeof v !== "string")) return false;
1454
+ const fieldForScript = escapeSQ(field);
1455
+ switch (operatorLC) {
1456
+ case "=":
1457
+ case "!=":
1458
+ case ">":
1459
+ case ">=":
1460
+ case "<":
1461
+ case "<=": {
1462
+ const operatorForScript = operatorLC === "=" ? "==" : operatorLC;
1463
+ const valueForScript = escapeSQ(value);
1464
+ return valueForScript ? { bool: { filter: { script: { script: `doc['${fieldForScript}'].value ${operatorForScript} doc['${valueForScript}'].value` } } } } : false;
1465
+ }
1466
+ case "in":
1467
+ case "notin": {
1468
+ const valueAsArray = toArray(value);
1469
+ if (valueAsArray.length > 0) {
1470
+ const arr = valueAsArray.map((v) => ({ bool: { filter: { script: { script: `doc['${fieldForScript}'].value == doc['${v}'].value` } } } }));
1471
+ return { bool: operatorLC === "in" ? { should: arr } : { must_not: arr } };
1472
+ }
1473
+ return false;
1474
+ }
1475
+ case "between":
1476
+ case "notbetween": {
1477
+ const valueAsArray = toArray(value);
1478
+ if (valueAsArray.length >= 2 && valueAsArray[0] && valueAsArray[1]) {
1479
+ const script = `doc['${fieldForScript}'].value >= doc['${valueAsArray[0]}'].value && doc['${fieldForScript}'].value <= doc['${valueAsArray[1]}'].value`;
1480
+ return { bool: { filter: { script: { script: operatorLC === "notbetween" ? `!(${script})` : script } } } };
1481
+ }
1482
+ return false;
1483
+ }
1484
+ case "contains":
1485
+ case "doesnotcontain":
1486
+ case "beginswith":
1487
+ case "doesnotbeginwith":
1488
+ case "endswith":
1489
+ case "doesnotendwith": {
1490
+ const valueForScript = escapeSQ(value);
1491
+ if (!valueForScript) return false;
1492
+ return { bool: { filter: { script: { script: getTextScript(fieldForScript, operatorLC, valueForScript) } } } };
1493
+ }
1494
+ }
1495
+ }
1496
+ switch (operatorLC) {
1497
+ case "<":
1498
+ case "<=":
1499
+ case ">":
1500
+ case ">=": return { range: { [field]: { [rangeOperatorMap[operatorLC]]: valueRenderer(value, parseNumbers) } } };
1501
+ case "=": return { term: { [field]: valueRenderer(value, parseNumbers) } };
1502
+ case "!=": return { bool: { must_not: { term: { [field]: valueRenderer(value, parseNumbers) } } } };
1503
+ case "null": return { bool: { must_not: { exists: { field } } } };
1504
+ case "notnull": return { exists: { field } };
1505
+ case "in":
1506
+ case "notin": {
1507
+ const valueAsArray = toArray(value).map((v) => valueRenderer(v, parseNumbers));
1508
+ if (valueAsArray.length > 0) {
1509
+ const arr = valueAsArray.map((v) => ({ term: { [field]: valueRenderer(v, parseNumbers) } }));
1510
+ return { bool: operatorLC === "in" ? { should: arr } : { must_not: arr } };
1511
+ }
1512
+ return false;
1513
+ }
1514
+ case "between":
1515
+ case "notbetween": {
1516
+ const valueAsArray = toArray(value);
1517
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
1518
+ let [first, second] = valueAsArray;
1519
+ const shouldParseNumbers = !(parseNumbers === false);
1520
+ if (shouldRenderAsNumber(first, shouldParseNumbers) && shouldRenderAsNumber(second, shouldParseNumbers)) {
1521
+ const firstNum = parseNumber(first, { parseNumbers: shouldParseNumbers });
1522
+ const secondNum = parseNumber(second, { parseNumbers: shouldParseNumbers });
1523
+ if (!preserveValueOrder && secondNum < firstNum) {
1524
+ const tempNum = secondNum;
1525
+ second = firstNum;
1526
+ first = tempNum;
1527
+ } else {
1528
+ first = firstNum;
1529
+ second = secondNum;
1530
+ }
1531
+ }
1532
+ return negateIfNotOp$1(operatorLC, { range: { [field]: {
1533
+ gte: first,
1534
+ lte: second
1535
+ } } });
1536
+ }
1537
+ return false;
1538
+ }
1539
+ case "contains":
1540
+ case "doesnotcontain": return negateIfNotOp$1(operatorLC, { regexp: { [field]: { value: `.*${value}.*` } } });
1541
+ case "beginswith":
1542
+ case "doesnotbeginwith": return negateIfNotOp$1(operatorLC, { regexp: { [field]: { value: `${value}.*` } } });
1543
+ case "endswith":
1544
+ case "doesnotendwith": return negateIfNotOp$1(operatorLC, { regexp: { [field]: { value: `.*${value}` } } });
1545
+ }
1546
+ return false;
1547
+ };
1548
+
1549
+ //#endregion
1550
+ //#region src/utils/formatQuery/defaultRuleProcessorJSONata.ts
1551
+ const shouldNegate = (op) => op.startsWith("not") || op.startsWith("doesnot");
1552
+ const quote = (v, escapeQuotes) => `"${typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`)}"`;
1553
+ const negate = (clause, negate$1) => negate$1 ? `$not(${clause})` : clause;
1554
+ const escapeStringRegex = (s) => `${s}`.replaceAll(/[/$()*+.?[\\\]^{|}]/g, String.raw`\$&`).replaceAll("-", String.raw`\x2d`);
1555
+ /**
1556
+ * Default rule processor used by {@link formatQuery} for "jsonata" format.
1557
+ *
1558
+ * @group Export
1559
+ */
1560
+ const defaultRuleProcessorJSONata = (rule, options = {}) => {
1561
+ const { field, operator, value, valueSource } = rule;
1562
+ const { escapeQuotes, parseNumbers, preserveValueOrder, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "" } = options;
1563
+ const valueIsField = valueSource === "field";
1564
+ const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
1565
+ const qfn = (f) => getQuotedFieldName(f, {
1566
+ quoteFieldNamesWith,
1567
+ fieldIdentifierSeparator
1568
+ });
1569
+ const matchEval = processMatchMode(rule);
1570
+ if (matchEval === false) return;
1571
+ else if (matchEval) {
1572
+ const { mode, threshold } = matchEval;
1573
+ const totalCount = `$count(${qfn(field)})`;
1574
+ const filteredCount = `$count($filter(${qfn(field)}, function($v) {${defaultRuleGroupProcessorJSONata(transformQuery(value, { ruleProcessor: (r) => ({
1575
+ ...r,
1576
+ field: r.field ? `$v.${r.field}` : "$v"
1577
+ }) }), options)}}))`;
1578
+ switch (mode) {
1579
+ case "all": return `${filteredCount} = ${totalCount}`;
1580
+ case "none": return `${filteredCount} = 0`;
1581
+ case "some": return `${filteredCount} > 0`;
1582
+ case "atleast":
1583
+ case "atmost":
1584
+ case "exactly": {
1585
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
1586
+ if (threshold > 0 && threshold < 1) return `${filteredCount} ${op} (${totalCount} * ${threshold})`;
1587
+ return `${filteredCount} ${op} ${threshold}`;
1588
+ }
1589
+ }
1590
+ }
1591
+ const operatorLC = lc(operator);
1592
+ switch (operatorLC) {
1593
+ case "<":
1594
+ case "<=":
1595
+ case "=":
1596
+ case "!=":
1597
+ case ">":
1598
+ case ">=": return `${qfn(field)} ${operatorLC} ${valueIsField ? qfn(trimIfString(value)) : useBareValue ? trimIfString(value) : quote(value, escapeQuotes)}`;
1599
+ case "contains":
1600
+ case "doesnotcontain": return negate(`$contains(${qfn(field)}, ${valueIsField ? qfn(trimIfString(value)) : quote(value, escapeQuotes)})`, shouldNegate(operatorLC));
1601
+ case "beginswith":
1602
+ case "doesnotbeginwith": return negate(valueIsField ? `$substring(${qfn(field)}, 0, $length(${qfn(trimIfString(value))})) = ${qfn(trimIfString(value))}` : `$contains(${qfn(field)}, /^${escapeStringRegex(value)}/)`, shouldNegate(operatorLC));
1603
+ case "endswith":
1604
+ case "doesnotendwith": return negate(valueIsField ? `$substring(${qfn(field)}, $length(${qfn(field)}) - $length(${qfn(trimIfString(value))})) = ${qfn(trimIfString(value))}` : `$contains(${qfn(field)}, /${escapeStringRegex(value)}$/)`, shouldNegate(operatorLC));
1605
+ case "null": return `${qfn(field)} = null`;
1606
+ case "notnull": return `${qfn(field)} != null`;
1607
+ case "in":
1608
+ case "notin": {
1609
+ const valueAsArray = toArray(value);
1610
+ return negate(`${qfn(field)} in [${valueAsArray.map((val) => valueIsField ? `${qfn(trimIfString(val))}` : shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : quote(val, escapeQuotes)).join(", ")}]`, shouldNegate(operatorLC));
1611
+ }
1612
+ case "between":
1613
+ case "notbetween": {
1614
+ const valueAsArray = toArray(value);
1615
+ if (valueAsArray.length < 2 || nullOrUndefinedOrEmpty(valueAsArray[0]) || nullOrUndefinedOrEmpty(valueAsArray[1])) return "";
1616
+ const [first, second] = valueAsArray;
1617
+ const shouldParseNumbers = !(parseNumbers === false);
1618
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
1619
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
1620
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : first : firstNum;
1621
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : second : secondNum;
1622
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
1623
+ const tempNum = secondNum;
1624
+ secondValue = firstNum;
1625
+ firstValue = tempNum;
1626
+ }
1627
+ const renderAsNumbers = shouldRenderAsNumber(first, parseNumbers) && shouldRenderAsNumber(second, parseNumbers);
1628
+ const getValueString = (raw, val) => valueIsField ? qfn(raw) : renderAsNumbers ? val : quote(val, escapeQuotes);
1629
+ const expression = `${qfn(field)} >= ${getValueString(first, firstValue)} and ${qfn(field)} <= ${getValueString(second, secondValue)}`;
1630
+ return operatorLC === "between" ? `(${expression})` : negate(expression, true);
1631
+ }
1632
+ }
1633
+ return "";
1634
+ };
1635
+
1636
+ //#endregion
1637
+ //#region src/utils/formatQuery/defaultRuleProcessorJsonLogic.ts
1638
+ const convertOperator = (op) => op.replace(/^(=)$/, "$1=").replace(/^notnull$/i, "!=").replace(/^null$/i, "==");
1639
+ const negateIfNotOp = (op, jsonRule) => op.startsWith("not") || op.startsWith("doesnot") ? { "!": jsonRule } : jsonRule;
1640
+ /**
1641
+ * Default rule processor used by {@link formatQuery} for "jsonlogic" format.
1642
+ *
1643
+ * @group Export
1644
+ */
1645
+ const defaultRuleProcessorJsonLogic = (rule, options = {}) => {
1646
+ const { field, operator, value, valueSource } = rule;
1647
+ const { parseNumbers, preserveValueOrder } = options;
1648
+ const valueIsField = valueSource === "field";
1649
+ const fieldObject = { var: field };
1650
+ const fieldOrNumberRenderer = (v) => valueIsField ? { var: `${v}` } : shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
1651
+ const matchEval = processMatchMode(rule);
1652
+ if (matchEval === false) return false;
1653
+ else if (matchEval) {
1654
+ const { mode, threshold } = matchEval;
1655
+ switch (mode) {
1656
+ case "all":
1657
+ case "none":
1658
+ case "some": return { [mode]: [{ var: field }, value.rules.length === 1 && !isRuleGroup(value.rules[0]) ? defaultRuleProcessorJsonLogic(value.rules[0], options) : defaultRuleGroupProcessorJsonLogic(value, options)] };
1659
+ case "atleast":
1660
+ case "atmost":
1661
+ case "exactly": {
1662
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "==";
1663
+ const filteredCount = { reduce: [
1664
+ { filter: [{ var: field }, value.rules.length === 1 && !isRuleGroup(value.rules[0]) ? defaultRuleProcessorJsonLogic(value.rules[0], options) : defaultRuleGroupProcessorJsonLogic(value, options)] },
1665
+ { "+": [1, { var: "accumulator" }] },
1666
+ 0
1667
+ ] };
1668
+ if (threshold > 0 && threshold < 1) {
1669
+ const totalCount = { reduce: [
1670
+ { var: field },
1671
+ { "+": [1, { var: "accumulator" }] },
1672
+ 0
1673
+ ] };
1674
+ return { [op]: [filteredCount, { "*": [totalCount, threshold] }] };
1675
+ }
1676
+ return { [op]: [filteredCount, threshold] };
1677
+ }
1678
+ }
1679
+ }
1680
+ const operatorLC = lc(operator);
1681
+ switch (operatorLC) {
1682
+ case "<":
1683
+ case "<=":
1684
+ case "=":
1685
+ case "!=":
1686
+ case ">":
1687
+ case ">=": return { [convertOperator(operatorLC)]: [fieldObject, fieldOrNumberRenderer(value)] };
1688
+ case "null":
1689
+ case "notnull": return { [`${operatorLC === "notnull" ? "!" : "="}=`]: [fieldObject, null] };
1690
+ case "in":
1691
+ case "notin": return negateIfNotOp(operatorLC, { in: [fieldObject, toArray(value).map((v) => fieldOrNumberRenderer(v))] });
1692
+ case "between":
1693
+ case "notbetween": {
1694
+ const valueAsArray = toArray(value);
1695
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
1696
+ let [first, second] = valueAsArray;
1697
+ const shouldParseNumbers = !(parseNumbers === false);
1698
+ if (!valueIsField && shouldRenderAsNumber(first, shouldParseNumbers) && shouldRenderAsNumber(second, shouldParseNumbers)) {
1699
+ const firstNum = parseNumber(first, { parseNumbers: shouldParseNumbers });
1700
+ const secondNum = parseNumber(second, { parseNumbers: shouldParseNumbers });
1701
+ if (!preserveValueOrder && secondNum < firstNum) {
1702
+ const tempNum = secondNum;
1703
+ second = firstNum;
1704
+ first = tempNum;
1705
+ } else {
1706
+ first = firstNum;
1707
+ second = secondNum;
1708
+ }
1709
+ } else if (valueIsField) {
1710
+ first = { var: first };
1711
+ second = { var: second };
1712
+ }
1713
+ return negateIfNotOp(operatorLC, { "<=": [
1714
+ first,
1715
+ fieldObject,
1716
+ second
1717
+ ] });
1718
+ }
1719
+ return false;
1720
+ }
1721
+ case "contains":
1722
+ case "doesnotcontain": return negateIfNotOp(operatorLC, { in: [fieldOrNumberRenderer(value), fieldObject] });
1723
+ case "beginswith":
1724
+ case "doesnotbeginwith": return negateIfNotOp(operatorLC, { startsWith: [fieldObject, fieldOrNumberRenderer(value)] });
1725
+ case "endswith":
1726
+ case "doesnotendwith": return negateIfNotOp(operatorLC, { endsWith: [fieldObject, fieldOrNumberRenderer(value)] });
1727
+ }
1728
+ return false;
1729
+ };
1730
+
1731
+ //#endregion
1732
+ //#region src/utils/formatQuery/defaultRuleProcessorLDAP.ts
1733
+ const negateIf = (clause, negate$1) => negate$1 ? `(!${clause})` : `${clause}`;
1734
+ const ldapEscape = (s) => `${trimIfString(s)}`.replaceAll(/[()&|=<>~*\\/]/g, (m) => `\\${m.codePointAt(0).toString(16)}`);
1735
+ /**
1736
+ * Default rule processor used by {@link formatQuery} for "ldap" format.
1737
+ *
1738
+ * @group Export
1739
+ */
1740
+ const defaultRuleProcessorLDAP = (rule, options = {}) => {
1741
+ const { field, operator, value, valueSource } = rule;
1742
+ const { preserveValueOrder } = options;
1743
+ const operatorLC = lc(operator);
1744
+ if (valueSource === "field" || nullOrUndefinedOrEmpty(value) && operatorLC !== "null" && operatorLC !== "notnull" || processMatchMode(rule)) return "";
1745
+ switch (operatorLC) {
1746
+ case "=":
1747
+ case "!=": return negateIf(`(${field}=${ldapEscape(value)})`, operatorLC === "!=");
1748
+ case ">":
1749
+ case ">=": return `(${field}>=${ldapEscape(value)})`;
1750
+ case "<":
1751
+ case "<=": return `(${field}<=${ldapEscape(value)})`;
1752
+ case "contains":
1753
+ case "doesnotcontain": return negateIf(`(${field}=*${ldapEscape(value)}*)`, operatorLC === "doesnotcontain");
1754
+ case "beginswith":
1755
+ case "doesnotbeginwith": return negateIf(`(${field}=${ldapEscape(value)}*)`, operatorLC === "doesnotbeginwith");
1756
+ case "endswith":
1757
+ case "doesnotendwith": return negateIf(`(${field}=*${ldapEscape(value)})`, operatorLC === "doesnotendwith");
1758
+ case "null":
1759
+ case "notnull": return negateIf(`(${field}=*)`, operatorLC === "notnull");
1760
+ case "in":
1761
+ case "notin": return negateIf(`(|${toArray(value).map((val) => `(${field}=${ldapEscape(val)})`).join("")})`, operatorLC === "notin");
1762
+ case "between":
1763
+ case "notbetween": {
1764
+ const valueAsArray = toArray(value);
1765
+ if (valueAsArray.length < 2 || nullOrUndefinedOrEmpty(valueAsArray[0]) || nullOrUndefinedOrEmpty(valueAsArray[1])) return "";
1766
+ const [first, second] = valueAsArray;
1767
+ const firstNum = shouldRenderAsNumber(first, true) ? parseNumber(first, { parseNumbers: true }) : NaN;
1768
+ const secondNum = shouldRenderAsNumber(second, true) ? parseNumber(second, { parseNumbers: true }) : NaN;
1769
+ let firstValue = Number.isNaN(firstNum) ? first : firstNum;
1770
+ let secondValue = Number.isNaN(secondNum) ? second : secondNum;
1771
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
1772
+ const tempNum = secondNum;
1773
+ secondValue = firstNum;
1774
+ firstValue = tempNum;
1775
+ }
1776
+ return negateIf(`(&(${field}>=${ldapEscape(firstValue)})(${field}<=${ldapEscape(secondValue)}))`, operatorLC === "notbetween");
1777
+ }
1778
+ }
1779
+ // istanbul ignore next
1780
+ return "";
1781
+ };
1782
+
1783
+ //#endregion
1784
+ //#region src/utils/formatQuery/defaultValueProcessorNL.ts
1785
+ const escapeStringValueQuotes = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : v;
1786
+ /**
1787
+ * Default value processor used by {@link formatQuery} for "natural_language" format.
1788
+ *
1789
+ * @group Export
1790
+ */
1791
+ const defaultValueProcessorNL = (rule, opts = {}) => {
1792
+ const { escapeQuotes, fields, parseNumbers, quoteFieldNamesWith, quoteValuesWith, fieldIdentifierSeparator, translations } = opts;
1793
+ const valueIsField = rule.valueSource === "field";
1794
+ const operatorLowerCase = lc(rule.operator);
1795
+ const quoteChar = quoteValuesWith || "'";
1796
+ const quoteValue = (v) => `${quoteChar}${v}${quoteChar}`;
1797
+ const escapeValue = (v) => escapeStringValueQuotes(v, quoteChar, escapeQuotes);
1798
+ const wrapAndEscape = (v) => quoteValue(escapeValue(v));
1799
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
1800
+ quoteFieldNamesWith,
1801
+ fieldIdentifierSeparator
1802
+ });
1803
+ const t = translations ?? ( /* istanbul ignore next */ {});
1804
+ const orTL = t.or ?? "or";
1805
+ const trueTL = t.true ?? "true";
1806
+ const falseTL = t.false ?? "false";
1807
+ switch (operatorLowerCase) {
1808
+ case "null":
1809
+ case "notnull": return "";
1810
+ case "between":
1811
+ case "notbetween": {
1812
+ if (!valueIsField) return defaultValueProcessorByRule(rule, opts);
1813
+ const valueAsArray = toArray(rule.value, { retainEmptyStrings: true }).slice(0, 2).map((v) => wrapFieldName(getOption(fields ?? [], v)?.label ?? v));
1814
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return "";
1815
+ return defaultValueProcessorByRule({
1816
+ ...rule,
1817
+ value: valueAsArray
1818
+ }, opts);
1819
+ }
1820
+ case "in":
1821
+ case "notin": {
1822
+ const valueAsArray = toArray(rule.value);
1823
+ if (valueAsArray.length === 0) return "";
1824
+ const valStringArray = valueAsArray.map((v) => valueIsField ? wrapFieldName(getOption(fields ?? [], v)?.label ?? v) : shouldRenderAsNumber(v, parseNumbers) ? `${trimIfString(v)}` : `${wrapAndEscape(v)}`);
1825
+ return `${valStringArray.slice(0, -1).join(", ")}${valStringArray.length > 2 ? "," : ""} ${orTL} ${valStringArray.at(-1)}`;
1826
+ }
1827
+ }
1828
+ if (typeof rule.value === "boolean") return rule.value ? trueTL : falseTL;
1829
+ return valueIsField ? wrapFieldName(getOption(fields ?? [], rule.value)?.label ?? rule.value) : shouldRenderAsNumber(rule.value, parseNumbers) ? `${trimIfString(rule.value)}` : `${wrapAndEscape(rule.value)}`;
1830
+ };
1831
+
1832
+ //#endregion
1833
+ //#region src/utils/formatQuery/defaultRuleProcessorNL.ts
1834
+ /**
1835
+ * Default operator map used by {@link formatQuery} for "natural_language" format.
1836
+ *
1837
+ * @group Export
1838
+ */
1839
+ const defaultExportOperatorMap = {
1840
+ "=": ["is", "is the same as the value in"],
1841
+ "!=": ["is not", "is not the same as the value in"],
1842
+ "<": ["is less than", "is less than the value in"],
1843
+ ">": ["is greater than", "is greater than the value in"],
1844
+ "<=": ["is less than or equal to", "is less than or equal to the value in"],
1845
+ ">=": ["is greater than or equal to", "is greater than or equal to the value in"],
1846
+ contains: ["contains", "contains the value in"],
1847
+ beginswith: ["starts with", "starts with the value in"],
1848
+ endswith: ["ends with", "ends with the value in"],
1849
+ doesnotcontain: ["does not contain", "does not contain the value in"],
1850
+ doesnotbeginwith: ["does not start with", "does not start with the value in"],
1851
+ doesnotendwith: ["does not end with", "does not end with the value in"],
1852
+ null: "is null",
1853
+ notnull: "is not null",
1854
+ in: ["is one of the values", "is the same as a value in"],
1855
+ notin: ["is not one of the values", "is not the same as any value in"],
1856
+ between: ["is between", "is between the values in"],
1857
+ notbetween: ["is not between", "is not between the values in"]
1858
+ };
1859
+ /* istanbul ignore next */
1860
+ const defaultGetOperators = () => [];
1861
+ /**
1862
+ * Default operator processor used by {@link formatQuery} for "natural_language" format.
1863
+ *
1864
+ * @group Export
1865
+ */
1866
+ const defaultOperatorProcessorNL = (rule, opts = {}) => {
1867
+ const { field, operator, valueSource = "value" } = rule;
1868
+ // istanbul ignore next
1869
+ const { getOperators = defaultGetOperators, operatorMap: operatorMapParam = defaultExportOperatorMap } = opts;
1870
+ const mapOperatorMap = new Map(Object.entries(defaultExportOperatorMap));
1871
+ for (const [key, value] of Object.entries(operatorMapParam)) mapOperatorMap.set(lc(key), value);
1872
+ const operatorMap = Object.fromEntries(mapOperatorMap);
1873
+ const { value: operatorNL, label } = getOption(toFullOptionList(getOperators(field, { fieldData: opts.fieldData ?? {
1874
+ name: field,
1875
+ value: field,
1876
+ label: field
1877
+ } }) ?? []), operator) ?? {
1878
+ name: operator,
1879
+ value: operator,
1880
+ label: operator
1881
+ };
1882
+ const operatorTL = operatorMap[operatorNL] ?? operatorMap[lc(operatorNL)] ?? [label, label];
1883
+ return typeof operatorTL === "string" ? operatorTL : operatorTL[valueSource === "field" ? 1 : 0];
1884
+ };
1885
+ /**
1886
+ * Default rule processor used by {@link formatQuery} for "natural_language" format.
1887
+ *
1888
+ * @group Export
1889
+ */
1890
+ const defaultRuleProcessorNL = (rule, opts) => {
1891
+ const { field, operator } = rule;
1892
+ // istanbul ignore next
1893
+ const { fieldData, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", quoteValuesWith = `'`, operatorProcessor = defaultOperatorProcessorNL, valueProcessor = defaultValueProcessorNL, concatOperator = "||", wordOrder = "SVO" } = opts ?? ( /* istanbul ignore next */ {});
1894
+ const processedField = getQuotedFieldName(fieldData?.label ?? field, {
1895
+ quoteFieldNamesWith,
1896
+ fieldIdentifierSeparator
1897
+ });
1898
+ const matchEval = processMatchMode(rule);
1899
+ if (matchEval === false) return "";
1900
+ else if (matchEval) {
1901
+ const { mode, threshold } = matchEval;
1902
+ const nestedArrayFilter = defaultRuleGroupProcessorNL(rule.value, {
1903
+ ...opts,
1904
+ fields: toFullOptionList(fieldData?.subproperties ?? [])
1905
+ });
1906
+ const hsp = (fieldData?.subproperties?.length ?? 0) > 0;
1907
+ switch (mode) {
1908
+ case "all": return `(${hsp ? "for " : ""}every item in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
1909
+ case "none": return `(${hsp ? "for " : ""}no item in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
1910
+ case "some": return `(${hsp ? "for " : ""}at least one item in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
1911
+ case "atleast":
1912
+ case "atmost":
1913
+ case "exactly": {
1914
+ const mm = mode.replace("at", "at ");
1915
+ if (threshold > 0 && threshold < 1) return `(${hsp ? "for " : ""}${mm} ${threshold * 100}% of the items in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
1916
+ return `(${hsp ? "for " : ""}${mm} ${threshold} of the items in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
1917
+ }
1918
+ }
1919
+ }
1920
+ const value = valueProcessor(rule, {
1921
+ ...opts,
1922
+ quoteFieldNamesWith,
1923
+ fieldIdentifierSeparator,
1924
+ quoteValuesWith,
1925
+ concatOperator
1926
+ });
1927
+ const operatorLC = lc(operator);
1928
+ if ((operatorLC === "in" || operatorLC === "notin" || operatorLC === "between" || operatorLC === "notbetween") && !value) return "";
1929
+ const wordOrderMap = {
1930
+ S: processedField,
1931
+ V: operatorProcessor(rule, opts),
1932
+ O: value
1933
+ };
1934
+ return normalizeConstituentWordOrder(wordOrder).map((term) => `${wordOrderMap[term]}`).join(" ").trim();
1935
+ };
1936
+
1937
+ //#endregion
1938
+ //#region src/utils/formatQuery/defaultRuleProcessorSQL.ts
1939
+ /**
1940
+ * Default operator processor used by {@link formatQuery} for "sql" and "parameterized*" formats.
1941
+ *
1942
+ * @group Export
1943
+ */
1944
+ const defaultOperatorProcessorSQL = (rule) => lc(mapSQLOperator(rule.operator));
1945
+ /**
1946
+ * Default rule processor used by {@link formatQuery} for "sql" format.
1947
+ *
1948
+ * @group Export
1949
+ */
1950
+ const defaultRuleProcessorSQL = (rule, opts = {}) => {
1951
+ const { quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", quoteValuesWith = `'`, operatorProcessor = defaultOperatorProcessorSQL, valueProcessor = defaultValueProcessorByRule, concatOperator = "||" } = opts;
1952
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
1953
+ quoteFieldNamesWith,
1954
+ fieldIdentifierSeparator
1955
+ });
1956
+ const ruleField = wrapFieldName(rule.field);
1957
+ const matchEval = processMatchMode(rule);
1958
+ if (matchEval === false) return;
1959
+ else if (matchEval) {
1960
+ if (opts?.preset !== "postgresql") return "";
1961
+ const { mode, threshold } = matchEval;
1962
+ const arrayElementAlias = "elem_alias";
1963
+ const nestedArrayFilter = defaultRuleGroupProcessorSQL(transformQuery(rule.value, { ruleProcessor: (r) => ({
1964
+ ...r,
1965
+ field: arrayElementAlias
1966
+ }) }), opts);
1967
+ switch (mode) {
1968
+ case "all": return `(select count(*) from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter}) = array_length(${ruleField}, 1)`;
1969
+ case "none": return `not exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter})`;
1970
+ case "some": return `exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter})`;
1971
+ case "atleast":
1972
+ case "atmost":
1973
+ case "exactly": {
1974
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
1975
+ return `(select count(*)${threshold > 0 && threshold < 1 ? ` / array_length(${ruleField}, 1)` : ""} from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter}) ${op} ${threshold}`;
1976
+ }
1977
+ }
1978
+ }
1979
+ const value = valueProcessor(rule, {
1980
+ ...opts,
1981
+ quoteFieldNamesWith,
1982
+ fieldIdentifierSeparator,
1983
+ quoteValuesWith,
1984
+ concatOperator
1985
+ });
1986
+ const operator = operatorProcessor(rule, opts);
1987
+ const operatorLowerCase = lc(operator);
1988
+ if ((operatorLowerCase === "in" || operatorLowerCase === "not in" || operatorLowerCase === "between" || operatorLowerCase === "not between") && !value) return "";
1989
+ return `${ruleField} ${operator} ${value}`.trim();
1990
+ };
1991
+
1992
+ //#endregion
1993
+ //#region src/utils/formatQuery/defaultRuleProcessorParameterized.ts
1994
+ /**
1995
+ * Default rule processor used by {@link formatQuery} for "parameterized" and
1996
+ * "parameterized_named" formats.
1997
+ *
1998
+ * @group Export
1999
+ */
2000
+ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
2001
+ // istanbul ignore next
2002
+ const { fieldData, format, getNextNamedParam, parseNumbers, paramPrefix, paramsKeepPrefix, numberedParams, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator, concatOperator, operatorProcessor = defaultOperatorProcessorSQL, valueProcessor = defaultValueProcessorByRule } = opts ?? {};
2003
+ const { processedParams = [] } = meta ?? {};
2004
+ const parameterized = format === "parameterized";
2005
+ const params = [];
2006
+ const paramsNamed = {};
2007
+ const finalize = (sql) => parameterized ? {
2008
+ sql,
2009
+ params
2010
+ } : {
2011
+ sql,
2012
+ params: paramsNamed
2013
+ };
2014
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
2015
+ quoteFieldNamesWith,
2016
+ fieldIdentifierSeparator
2017
+ });
2018
+ const ruleField = wrapFieldName(rule.field);
2019
+ const matchEval = processMatchMode(rule);
2020
+ if (matchEval === false) return;
2021
+ else if (matchEval) {
2022
+ if (opts?.preset !== "postgresql") return finalize("");
2023
+ const { mode, threshold } = matchEval;
2024
+ const arrayElementAlias = "elem_alias";
2025
+ const { sql: nestedSQL, params: nestedParams } = defaultRuleGroupProcessorParameterized(transformQuery(rule.value, { ruleProcessor: (r) => ({
2026
+ ...r,
2027
+ field: arrayElementAlias
2028
+ }) }), {
2029
+ ...opts,
2030
+ fields: []
2031
+ });
2032
+ // istanbul ignore else
2033
+ if (Array.isArray(nestedParams)) params.push(...nestedParams);
2034
+ else Object.assign(paramsNamed, nestedParams);
2035
+ switch (mode) {
2036
+ case "all": return finalize(`(select count(*) from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL}) = array_length(${ruleField}, 1)`);
2037
+ case "none": return finalize(`not exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL})`);
2038
+ case "some": return finalize(`exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL})`);
2039
+ case "atleast":
2040
+ case "atmost":
2041
+ case "exactly": {
2042
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
2043
+ return finalize(`(select count(*)${threshold > 0 && threshold < 1 ? ` / array_length(${ruleField}, 1)` : ""} from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL}) ${op} ${threshold}`);
2044
+ }
2045
+ }
2046
+ }
2047
+ const value = valueProcessor(rule, {
2048
+ parseNumbers,
2049
+ quoteFieldNamesWith,
2050
+ concatOperator,
2051
+ fieldData,
2052
+ format
2053
+ });
2054
+ const sqlOperator = operatorProcessor(rule, opts);
2055
+ const sqlOperatorLowerCase = lc(sqlOperator);
2056
+ const [qPre, qPost] = quoteFieldNamesWith;
2057
+ if ((sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in" || sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") && !value) return finalize("");
2058
+ else if (sqlOperatorLowerCase === "is null" || sqlOperatorLowerCase === "is not null") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator}`);
2059
+ else if (rule.valueSource === "field") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${value}`.trim());
2060
+ else if (sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in") {
2061
+ const splitValue = toArray(rule.value);
2062
+ if (parameterized) {
2063
+ for (const v of splitValue) params.push(shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v);
2064
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} (${splitValue.map((_v, i) => numberedParams ? `${paramPrefix}${processedParams.length + 1 + splitValue.length - (splitValue.length - i)}` : "?").join(", ")})`);
2065
+ }
2066
+ const inParams = [];
2067
+ for (const v of splitValue) {
2068
+ const thisParamName = getNextNamedParam(rule.field);
2069
+ inParams.push(`${paramPrefix}${thisParamName}`);
2070
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${thisParamName}`] = shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
2071
+ }
2072
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} (${inParams.join(", ")})`);
2073
+ } else if (sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") {
2074
+ const [first, second] = toArray(rule.value, { retainEmptyStrings: true }).slice(0, 2).map((v) => shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v);
2075
+ if (parameterized) {
2076
+ params.push(first, second);
2077
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${numberedParams ? `${paramPrefix}${processedParams.length + 1}` : "?"} and ${numberedParams ? `${paramPrefix}${processedParams.length + 2}` : "?"}`);
2078
+ }
2079
+ const firstParamName = getNextNamedParam(rule.field);
2080
+ const secondParamName = getNextNamedParam(rule.field);
2081
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${firstParamName}`] = first;
2082
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${secondParamName}`] = second;
2083
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${paramPrefix}${firstParamName} and ${paramPrefix}${secondParamName}`);
2084
+ }
2085
+ let paramValue = rule.value;
2086
+ if (typeof rule.value === "string") if (shouldRenderAsNumber(rule.value, parseNumbers)) paramValue = parseNumber(rule.value, { parseNumbers });
2087
+ else paramValue = /^'.*'$/g.test(value) ? value.replaceAll(/(^'|'$)/g, "") : value;
2088
+ let paramName = "";
2089
+ if (parameterized) params.push(paramValue);
2090
+ else {
2091
+ paramName = getNextNamedParam(rule.field);
2092
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${paramName}`] = paramValue;
2093
+ }
2094
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${parameterized ? numberedParams ? `${paramPrefix}${processedParams.length + 1}` : "?" : `${paramPrefix}${paramName}`}`.trim());
2095
+ };
2096
+
2097
+ //#endregion
2098
+ //#region src/utils/formatQuery/defaultRuleProcessorPrisma.ts
2099
+ const processNumber = (value, fallback, parseNumbers) => shouldRenderAsNumber(value, !!parseNumbers || typeof value === "bigint") ? Number(parseNumber(value, { parseNumbers: !!parseNumbers })) : fallback;
2100
+ /**
2101
+ * Default rule processor used by {@link formatQuery} for "prisma" format.
2102
+ *
2103
+ * @group Export
2104
+ */
2105
+ const defaultRuleProcessorPrisma = (rule, options = {}) => {
2106
+ const { field, operator, value, valueSource } = rule;
2107
+ // istanbul ignore next
2108
+ const { parseNumbers, preserveValueOrder } = options;
2109
+ if (valueSource === "field" || processMatchMode(rule)) return;
2110
+ const operatorLC = lc(operator);
2111
+ switch (operatorLC) {
2112
+ case "=": return { [field]: processNumber(value, value, parseNumbers) };
2113
+ case "!=":
2114
+ case "<":
2115
+ case "<=":
2116
+ case ">":
2117
+ case ">=": {
2118
+ const prismaOperator = prismaOperators[operatorLC];
2119
+ return { [field]: { [prismaOperator]: processNumber(value, value, parseNumbers) } };
2120
+ }
2121
+ case "contains": return { [field]: { contains: value } };
2122
+ case "beginswith": return { [field]: { startsWith: value } };
2123
+ case "endswith": return { [field]: { endsWith: value } };
2124
+ case "doesnotcontain": return { NOT: { [field]: { contains: value } } };
2125
+ case "doesnotbeginwith": return { NOT: { [field]: { startsWith: value } } };
2126
+ case "doesnotendwith": return { NOT: { [field]: { endsWith: value } } };
2127
+ case "null": return { [field]: null };
2128
+ case "notnull": return { [field]: { not: null } };
2129
+ case "in":
2130
+ case "notin": {
2131
+ const valueAsArray = toArray(value);
2132
+ return { [field]: { [prismaOperators[operatorLC]]: valueAsArray.map((val) => processNumber(val, val, parseNumbers)) } };
2133
+ }
2134
+ case "between":
2135
+ case "notbetween": {
2136
+ const valueAsArray = toArray(value);
2137
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
2138
+ const [first, second] = valueAsArray;
2139
+ const shouldParseNumbers = !(parseNumbers === false);
2140
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers }) : NaN;
2141
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers }) : NaN;
2142
+ let firstValue = Number.isNaN(firstNum) ? first : firstNum;
2143
+ let secondValue = Number.isNaN(secondNum) ? second : secondNum;
2144
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
2145
+ const tempNum = secondNum;
2146
+ secondValue = firstNum;
2147
+ firstValue = tempNum;
2148
+ }
2149
+ return operatorLC === "between" ? { [field]: {
2150
+ gte: firstValue,
2151
+ lte: secondValue
2152
+ } } : { OR: [{ [field]: { lt: firstValue } }, { [field]: { gt: secondValue } }] };
2153
+ } else return "";
2154
+ }
2155
+ }
2156
+ return "";
2157
+ };
2158
+
2159
+ //#endregion
2160
+ //#region src/utils/formatQuery/defaultRuleProcessorSequelize.ts
2161
+ /**
2162
+ * Default rule processor used by {@link formatQuery} for the "sequelize" format.
2163
+ *
2164
+ * @group Export
2165
+ */
2166
+ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder, context = {} } = {}) => {
2167
+ const { sequelizeOperators: Op, sequelizeCol: col, sequelizeFn: fn } = context;
2168
+ if (processMatchMode(rule)) return;
2169
+ const { field, operator, value, valueSource } = rule;
2170
+ const valueIsField = valueSource === "field";
2171
+ const operatorLC = lc(operator);
2172
+ if (!Op || valueIsField && (!col || !fn && [
2173
+ "doesnotcontain",
2174
+ "doesnotbeginwith",
2175
+ "doesnotendwith"
2176
+ ].includes(operatorLC))) return;
2177
+ switch (operatorLC) {
2178
+ case "=":
2179
+ case "!=":
2180
+ case "<":
2181
+ case "<=":
2182
+ case ">":
2183
+ case ">=": {
2184
+ const sequelizeOperator = {
2185
+ "=": Op.eq,
2186
+ "!=": Op.ne,
2187
+ "<": Op.lt,
2188
+ "<=": Op.lte,
2189
+ ">": Op.gt,
2190
+ ">=": Op.gte
2191
+ }[operatorLC];
2192
+ return { [field]: valueIsField && operatorLC === "=" ? { [Op.col]: value } : { [sequelizeOperator]: valueIsField ? col(value) : shouldRenderAsNumber(value, parseNumbers) ? parseNumber(value, { parseNumbers: "strict" }) : value } };
2193
+ }
2194
+ case "contains": return { [field]: { [Op.substring]: valueIsField ? col(value) : `${value}` } };
2195
+ case "beginswith": return { [field]: { [Op.startsWith]: valueIsField ? col(value) : `${value}` } };
2196
+ case "endswith": return { [field]: { [Op.endsWith]: valueIsField ? col(value) : `${value}` } };
2197
+ case "doesnotcontain": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value), "%") : `%${value}%` } };
2198
+ case "doesnotbeginwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", col(value), "%") : `${value}%` } };
2199
+ case "doesnotendwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value)) : `%${value}` } };
2200
+ case "null": return { [field]: { [Op.is]: null } };
2201
+ case "notnull": return { [field]: { [Op.not]: null } };
2202
+ case "in":
2203
+ case "notin": {
2204
+ const valueAsArray = toArray(value);
2205
+ return { [field]: { [operatorLC === "in" ? Op.in : Op.notIn]: valueAsArray.map((val) => valueIsField ? col(val) : shouldRenderAsNumber(val, parseNumbers) ? parseNumber(val, { parseNumbers: "strict" }) : val) } };
2206
+ }
2207
+ case "between":
2208
+ case "notbetween": {
2209
+ const valueAsArray = toArray(value, { retainEmptyStrings: true });
2210
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return;
2211
+ const [first, second] = valueAsArray;
2212
+ const firstNum = shouldRenderAsNumber(first, parseNumbers) ? parseNumber(first, { parseNumbers: "strict" }) : NaN;
2213
+ const secondNum = shouldRenderAsNumber(second, parseNumbers) ? parseNumber(second, { parseNumbers: "strict" }) : NaN;
2214
+ const firstValue = Number.isNaN(firstNum) ? first : firstNum;
2215
+ const secondValue = Number.isNaN(secondNum) ? second : secondNum;
2216
+ const valsOneAndTwoOnly = [firstValue, secondValue];
2217
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
2218
+ valsOneAndTwoOnly[0] = secondNum;
2219
+ valsOneAndTwoOnly[1] = firstNum;
2220
+ }
2221
+ return { [field]: { [operatorLC === "between" ? Op.between : Op.notBetween]: valueIsField ? valsOneAndTwoOnly.map((v) => col(v)) : valsOneAndTwoOnly.every((v) => shouldRenderAsNumber(v, parseNumbers)) ? valsOneAndTwoOnly.map((v) => parseNumber(v, { parseNumbers: "strict" })) : valsOneAndTwoOnly } };
2222
+ }
2223
+ }
2224
+ };
2225
+
2226
+ //#endregion
2227
+ //#region src/utils/formatQuery/formatQuery.ts
2228
+ /**
2229
+ * A collection of option presets for {@link formatQuery}, specifically for SQL-based formats.
2230
+ *
2231
+ * @group Export
2232
+ */
2233
+ const sqlDialectPresets = {
2234
+ ansi: {},
2235
+ sqlite: { paramsKeepPrefix: true },
2236
+ oracle: {},
2237
+ mssql: {
2238
+ concatOperator: "+",
2239
+ quoteFieldNamesWith: ["[", "]"],
2240
+ fieldIdentifierSeparator: ".",
2241
+ paramPrefix: "@"
2242
+ },
2243
+ mysql: { concatOperator: "CONCAT" },
2244
+ postgresql: {
2245
+ quoteFieldNamesWith: "\"",
2246
+ numberedParams: true,
2247
+ paramPrefix: "$"
2248
+ }
2249
+ };
2250
+ /**
2251
+ * A collection of option presets for {@link formatQuery}.
2252
+ *
2253
+ * @group Export
2254
+ */
2255
+ const formatQueryOptionPresets = { ...sqlDialectPresets };
2256
+ const defaultRuleProcessors = {
2257
+ cel: defaultRuleProcessorCEL,
2258
+ drizzle: defaultRuleProcessorDrizzle,
2259
+ elasticsearch: defaultRuleProcessorElasticSearch,
2260
+ json_without_ids: defaultRuleProcessorSQL,
2261
+ json: defaultRuleProcessorSQL,
2262
+ jsonata: defaultRuleProcessorJSONata,
2263
+ jsonlogic: defaultRuleProcessorJsonLogic,
2264
+ ldap: defaultRuleProcessorLDAP,
2265
+ mongodb_query: defaultRuleProcessorMongoDBQuery,
2266
+ mongodb: defaultRuleProcessorMongoDB,
2267
+ natural_language: defaultRuleProcessorNL,
2268
+ parameterized_named: defaultRuleProcessorParameterized,
2269
+ parameterized: defaultRuleProcessorParameterized,
2270
+ prisma: defaultRuleProcessorPrisma,
2271
+ sequelize: defaultRuleProcessorSequelize,
2272
+ spel: defaultRuleProcessorSpEL,
2273
+ sql: defaultRuleProcessorSQL
2274
+ };
2275
+ /* istanbul ignore next */
2276
+ const defaultOperatorProcessor = (r) => r.operator;
2277
+ const defaultOperatorProcessors = {
2278
+ cel: defaultOperatorProcessor,
2279
+ drizzle: defaultOperatorProcessor,
2280
+ elasticsearch: defaultOperatorProcessor,
2281
+ json_without_ids: defaultOperatorProcessor,
2282
+ json: defaultOperatorProcessor,
2283
+ jsonata: defaultOperatorProcessor,
2284
+ jsonlogic: defaultOperatorProcessor,
2285
+ ldap: defaultOperatorProcessor,
2286
+ mongodb_query: defaultOperatorProcessor,
2287
+ mongodb: defaultOperatorProcessor,
2288
+ natural_language: defaultOperatorProcessorNL,
2289
+ parameterized_named: defaultOperatorProcessorSQL,
2290
+ parameterized: defaultOperatorProcessorSQL,
2291
+ prisma: defaultOperatorProcessor,
2292
+ sequelize: defaultOperatorProcessor,
2293
+ spel: defaultOperatorProcessor,
2294
+ sql: defaultOperatorProcessorSQL
2295
+ };
2296
+ const defaultFallbackExpressions = {
2297
+ cel: "1 == 1",
2298
+ ldap: "",
2299
+ mongodb: "\"$and\":[{\"$expr\":true}]",
2300
+ natural_language: "1 is 1",
2301
+ spel: "1 == 1",
2302
+ sql: "(1 = 1)"
2303
+ };
2304
+ const defaultFormatQueryOptions = {
2305
+ format: "json",
2306
+ fields: [],
2307
+ quoteFieldNamesWith: ["", ""],
2308
+ fieldIdentifierSeparator: "",
2309
+ getOperators: () => [],
2310
+ paramPrefix: ":",
2311
+ paramsKeepPrefix: false,
2312
+ numberedParams: false,
2313
+ preserveValueOrder: false,
2314
+ placeholderFieldName: defaultPlaceholderFieldName,
2315
+ placeholderOperatorName: defaultPlaceholderOperatorName,
2316
+ quoteValuesWith: "'",
2317
+ concatOperator: "||",
2318
+ preset: "ansi",
2319
+ wordOrder: "SVO",
2320
+ translations: {},
2321
+ operatorMap: {}
2322
+ };
2323
+ const valueProcessorCanActAsRuleProcessor = new Set([
2324
+ "cel",
2325
+ "drizzle",
2326
+ "elasticsearch",
2327
+ "jsonata",
2328
+ "jsonlogic",
2329
+ "ldap",
2330
+ "mongodb_query",
2331
+ "mongodb",
2332
+ "prisma",
2333
+ "sequelize",
2334
+ "spel"
2335
+ ]);
2336
+ const sqlFormats = new Set([
2337
+ "sql",
2338
+ "parameterized",
2339
+ "parameterized_named",
2340
+ "drizzle",
2341
+ "prisma",
2342
+ "sequelize"
2343
+ ]);
2344
+ function formatQuery(ruleGroup, optionParam = {}) {
2345
+ const options = typeof optionParam === "string" ? { format: lc(optionParam) } : optionParam;
2346
+ const optObj = {
2347
+ ...defaultFormatQueryOptions,
2348
+ ...!options.format || sqlFormats.has(options.format) ? sqlDialectPresets[options.preset ?? "ansi"] ?? null : null,
2349
+ ...options,
2350
+ ...!options.format && (Object.keys(sqlDialectPresets).includes(options.preset ?? "") ? { format: "sql" } : null)
2351
+ };
2352
+ const format = lc(optObj.format);
2353
+ const { fallbackExpression: fallbackExpression_option, getOperators: getOperators_option, operatorProcessor: operatorProcessor_option, parseNumbers, quoteFieldNamesWith: quoteFieldNamesWith_option, ruleGroupProcessor: ruleGroupProcessor_option, ruleProcessor: ruleProcessor_option, validator, valueProcessor: valueProcessor_option, context } = optObj;
2354
+ const getParseNumberBoolean = (inputType) => {
2355
+ return typeof getParseNumberMethod({
2356
+ parseNumbers,
2357
+ inputType
2358
+ }) === "string" ? true : typeof parseNumbers === "boolean" ? parseNumbers : void 0;
2359
+ };
2360
+ const operatorProcessor = typeof operatorProcessor_option === "function" ? operatorProcessor_option : defaultOperatorProcessors[format] ?? defaultOperatorProcessor;
2361
+ const valueProcessor = typeof valueProcessor_option === "function" ? isValueProcessorLegacy(valueProcessor_option) ? (r) => valueProcessor_option(r.field, r.operator, r.value, r.valueSource) : valueProcessor_option : format === "natural_language" ? defaultValueProcessorNL : valueProcessorCanActAsRuleProcessor.has(format) ? ruleProcessor_option ?? defaultRuleProcessors[format] : defaultValueProcessorByRule;
2362
+ const ruleProcessor = (typeof ruleProcessor_option === "function" ? ruleProcessor_option : null) ?? (valueProcessorCanActAsRuleProcessor.has(format) && typeof ruleProcessor_option !== "function" && valueProcessor_option ? valueProcessor : null) ?? defaultRuleProcessors[format] ?? defaultRuleProcessorSQL;
2363
+ const quoteFieldNamesWith = getQuoteFieldNamesWithArray(quoteFieldNamesWith_option);
2364
+ const fields = toFullOptionList(optObj.fields);
2365
+ const getOperators = (f, m) => toFullOptionList(getOperators_option(f, m) ?? []);
2366
+ const fallbackExpression = fallbackExpression_option ?? defaultFallbackExpressions[format] ?? defaultFallbackExpressions.sql;
2367
+ let validationMap = {};
2368
+ // istanbul ignore else
2369
+ if (typeof validator === "function") {
2370
+ const validationResult = validator(ruleGroup);
2371
+ if (typeof validationResult === "boolean") {
2372
+ // istanbul ignore else
2373
+ if (!validationResult) return format === "parameterized" ? {
2374
+ sql: fallbackExpression,
2375
+ params: []
2376
+ } : format === "parameterized_named" ? {
2377
+ sql: fallbackExpression,
2378
+ params: {}
2379
+ } : format === "mongodb" ? `{${fallbackExpression}}` : format === "mongodb_query" ? mongoDbFallback : format === "prisma" ? prismaFallback : format === "jsonlogic" ? false : format === "elasticsearch" ? {} : format === "drizzle" || format === "sequelize" ? void 0 : fallbackExpression;
2380
+ } else validationMap = validationResult;
2381
+ }
2382
+ const validatorMap = {};
2383
+ const uniqueFields = toFlatOptionArray(fields);
2384
+ for (const f of uniqueFields)
2385
+ // istanbul ignore else
2386
+ if (typeof f.validator === "function") validatorMap[f.value ?? f.name] = f.validator;
2387
+ const validateRule = (rule) => {
2388
+ let validationResult;
2389
+ let fieldValidator;
2390
+ if (rule.id) validationResult = validationMap[rule.id];
2391
+ if (uniqueFields.length > 0) {
2392
+ const fieldArr = uniqueFields.filter((f) => f.name === rule.field);
2393
+ if (fieldArr.length > 0) {
2394
+ const field = fieldArr[0];
2395
+ // istanbul ignore else
2396
+ if (typeof field.validator === "function") fieldValidator = field.validator;
2397
+ }
2398
+ }
2399
+ return [validationResult, fieldValidator];
2400
+ };
2401
+ const finalOptions = {
2402
+ ...optObj,
2403
+ fallbackExpression,
2404
+ fields,
2405
+ format,
2406
+ getOperators,
2407
+ getParseNumberBoolean,
2408
+ quoteFieldNamesWith,
2409
+ operatorProcessor,
2410
+ ruleProcessor,
2411
+ valueProcessor,
2412
+ validateRule,
2413
+ validationMap,
2414
+ context
2415
+ };
2416
+ if (typeof ruleGroupProcessor_option === "function") return ruleGroupProcessor_option(ruleGroup, finalOptions);
2417
+ switch (format) {
2418
+ case "json":
2419
+ case "json_without_ids": {
2420
+ const rg = parseNumbers ? produce(ruleGroup, (g) => numerifyValues(g, finalOptions)) : ruleGroup;
2421
+ if (format === "json_without_ids") return JSON.stringify(rg, (key, value) => key === "id" || key === "path" ? void 0 : bigIntJsonStringifyReplacer(key, value));
2422
+ return JSON.stringify(rg, bigIntJsonStringifyReplacer, 2);
2423
+ }
2424
+ case "sql": return defaultRuleGroupProcessorSQL(ruleGroup, finalOptions);
2425
+ case "parameterized":
2426
+ case "parameterized_named": return defaultRuleGroupProcessorParameterized(ruleGroup, finalOptions);
2427
+ case "mongodb": return defaultRuleGroupProcessorMongoDB(ruleGroup, finalOptions);
2428
+ case "mongodb_query": return defaultRuleGroupProcessorMongoDBQuery(ruleGroup, finalOptions);
2429
+ case "cel": return defaultRuleGroupProcessorCEL(ruleGroup, finalOptions);
2430
+ case "spel": return defaultRuleGroupProcessorSpEL(ruleGroup, finalOptions);
2431
+ case "jsonata": return defaultRuleGroupProcessorJSONata(ruleGroup, finalOptions);
2432
+ case "jsonlogic": return defaultRuleGroupProcessorJsonLogic(ruleGroup, finalOptions);
2433
+ case "elasticsearch": return defaultRuleGroupProcessorElasticSearch(ruleGroup, finalOptions);
2434
+ case "natural_language": return defaultRuleGroupProcessorNL(ruleGroup, finalOptions);
2435
+ case "ldap": return defaultRuleGroupProcessorLDAP(ruleGroup, finalOptions);
2436
+ case "prisma": return defaultRuleGroupProcessorPrisma(ruleGroup, finalOptions);
2437
+ case "drizzle": return defaultRuleGroupProcessorDrizzle(ruleGroup, finalOptions);
2438
+ case "sequelize": return defaultRuleGroupProcessorSequelize(ruleGroup, finalOptions);
2439
+ default: return "";
2440
+ }
2441
+ }
2442
+
2443
+ //#endregion
2444
+ //#region src/utils/formatQuery/index.ts
2445
+ const generateValueProcessor = (vpbr) => (field, operator, value, valueSource) => vpbr({
2446
+ field,
2447
+ operator,
2448
+ value,
2449
+ valueSource
2450
+ }, { parseNumbers: false });
2451
+ /**
2452
+ * Default value processor used by {@link formatQuery} for "sql" format.
2453
+ *
2454
+ * @group Export
2455
+ */
2456
+ const defaultValueProcessor = generateValueProcessor(defaultValueProcessorByRule);
2457
+ /**
2458
+ * @deprecated Prefer {@link defaultRuleProcessorMongoDB}.
2459
+ *
2460
+ * @group Export
2461
+ */
2462
+ const defaultMongoDBValueProcessor = generateValueProcessor(defaultRuleProcessorMongoDB);
2463
+ /**
2464
+ * @deprecated Prefer {@link defaultRuleProcessorCEL}.
2465
+ *
2466
+ * @group Export
2467
+ */
2468
+ const defaultCELValueProcessor = generateValueProcessor(defaultRuleProcessorCEL);
2469
+ /**
2470
+ * @deprecated Prefer {@link defaultRuleProcessorSpEL}.
2471
+ *
2472
+ * @group Export
2473
+ */
2474
+ const defaultSpELValueProcessor = generateValueProcessor(defaultRuleProcessorSpEL);
2475
+ /**
2476
+ * @deprecated Renamed to {@link defaultRuleProcessorCEL}.
2477
+ *
2478
+ * @group Export
2479
+ */
2480
+ const defaultValueProcessorCELByRule = defaultRuleProcessorCEL;
2481
+ /**
2482
+ * @deprecated Renamed to {@link defaultRuleProcessorMongoDB}.
2483
+ *
2484
+ * @group Export
2485
+ */
2486
+ const defaultValueProcessorMongoDBByRule = defaultRuleProcessorMongoDB;
2487
+ /**
2488
+ * @deprecated Renamed to {@link defaultRuleProcessorSpEL}.
2489
+ *
2490
+ * @group Export
2491
+ */
2492
+ const defaultValueProcessorSpELByRule = defaultRuleProcessorSpEL;
2493
+
2494
+ //#endregion
2495
+ 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 };
2496
+ //# sourceMappingURL=formatQuery.mjs.map