@react-querybuilder/core 8.9.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 (80) hide show
  1. package/README.md +84 -0
  2. package/dist/arrayUtils-D5EoIsKP.js +164 -0
  3. package/dist/arrayUtils-D5EoIsKP.js.map +1 -0
  4. package/dist/basic-C8xXKHIA.d.ts +1235 -0
  5. package/dist/cjs/index.d.ts +1 -0
  6. package/dist/cjs/index.js +6 -0
  7. package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +4786 -0
  8. package/dist/cjs/react-querybuilder_core.cjs.development.js +4033 -0
  9. package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -0
  10. package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +4786 -0
  11. package/dist/cjs/react-querybuilder_core.cjs.production.js +2 -0
  12. package/dist/cjs/react-querybuilder_core.cjs.production.js.map +1 -0
  13. package/dist/convertQuery-DAqoID3O.js +87 -0
  14. package/dist/convertQuery-DAqoID3O.js.map +1 -0
  15. package/dist/export-DyrnTh6K.d.ts +452 -0
  16. package/dist/formatQuery.d.ts +667 -0
  17. package/dist/formatQuery.js +2428 -0
  18. package/dist/formatQuery.js.map +1 -0
  19. package/dist/import-Cksobmln.d.ts +28 -0
  20. package/dist/isRuleGroup-DqAs2x4E.js +120 -0
  21. package/dist/isRuleGroup-DqAs2x4E.js.map +1 -0
  22. package/dist/objectUtils-BBZSfZJz.js +17 -0
  23. package/dist/objectUtils-BBZSfZJz.js.map +1 -0
  24. package/dist/optGroupUtils-CXLgyg2i.js +138 -0
  25. package/dist/optGroupUtils-CXLgyg2i.js.map +1 -0
  26. package/dist/parseCEL.d.ts +34 -0
  27. package/dist/parseCEL.js +2593 -0
  28. package/dist/parseCEL.js.map +1 -0
  29. package/dist/parseJSONata.d.ts +36 -0
  30. package/dist/parseJSONata.js +5884 -0
  31. package/dist/parseJSONata.js.map +1 -0
  32. package/dist/parseJsonLogic.d.ts +36 -0
  33. package/dist/parseJsonLogic.js +191 -0
  34. package/dist/parseJsonLogic.js.map +1 -0
  35. package/dist/parseMongoDB.d.ts +79 -0
  36. package/dist/parseMongoDB.js +267 -0
  37. package/dist/parseMongoDB.js.map +1 -0
  38. package/dist/parseNumber-Bcys1kOH.js +31 -0
  39. package/dist/parseNumber-Bcys1kOH.js.map +1 -0
  40. package/dist/parseSQL.d.ts +37 -0
  41. package/dist/parseSQL.js +6626 -0
  42. package/dist/parseSQL.js.map +1 -0
  43. package/dist/parseSpEL.d.ts +34 -0
  44. package/dist/parseSpEL.js +2911 -0
  45. package/dist/parseSpEL.js.map +1 -0
  46. package/dist/prepareQueryObjects-BqFEs4eV.js +172 -0
  47. package/dist/prepareQueryObjects-BqFEs4eV.js.map +1 -0
  48. package/dist/query-builder-layout.css +1 -0
  49. package/dist/query-builder-layout.css.map +1 -0
  50. package/dist/query-builder-layout.scss +4 -0
  51. package/dist/query-builder.css +1 -0
  52. package/dist/query-builder.css.map +1 -0
  53. package/dist/query-builder.scss +2 -0
  54. package/dist/react-querybuilder_core.d.mts +4786 -0
  55. package/dist/react-querybuilder_core.legacy-esm.d.ts +4786 -0
  56. package/dist/react-querybuilder_core.legacy-esm.js +3916 -0
  57. package/dist/react-querybuilder_core.legacy-esm.js.map +1 -0
  58. package/dist/react-querybuilder_core.mjs +3852 -0
  59. package/dist/react-querybuilder_core.mjs.map +1 -0
  60. package/dist/react-querybuilder_core.production.d.mts +4786 -0
  61. package/dist/react-querybuilder_core.production.mjs +2 -0
  62. package/dist/react-querybuilder_core.production.mjs.map +1 -0
  63. package/dist/styles/_functions.scss +14 -0
  64. package/dist/styles/_layout.scss +201 -0
  65. package/dist/styles/_main.scss +114 -0
  66. package/dist/styles/_root.scss +66 -0
  67. package/dist/styles/_variables.scss +66 -0
  68. package/dist/transformQuery-FL_nlpp5.js +47 -0
  69. package/dist/transformQuery-FL_nlpp5.js.map +1 -0
  70. package/dist/transformQuery.d.ts +118 -0
  71. package/dist/transformQuery.js +4 -0
  72. package/formatQuery/package.json +4 -0
  73. package/package.json +146 -0
  74. package/parseCEL/package.json +4 -0
  75. package/parseJSONata/package.json +4 -0
  76. package/parseJsonLogic/package.json +4 -0
  77. package/parseMongoDB/package.json +4 -0
  78. package/parseSQL/package.json +4 -0
  79. package/parseSpEL/package.json +4 -0
  80. package/transformQuery/package.json +4 -0
@@ -0,0 +1,3852 @@
1
+ import { produce } from "immer";
2
+ import { numericQuantity, numericRegex as numericRegex$1 } from "numeric-quantity";
3
+
4
+ //#region src/defaults.ts
5
+ /**
6
+ * @group Defaults
7
+ */
8
+ const defaultPlaceholderName = "~";
9
+ /**
10
+ * @group Defaults
11
+ */
12
+ const defaultPlaceholderLabel = "------";
13
+ /**
14
+ * Default `name` for placeholder option in the `fields` array.
15
+ *
16
+ * @group Defaults
17
+ */
18
+ const defaultPlaceholderFieldName = defaultPlaceholderName;
19
+ /**
20
+ * Default `label` for placeholder option in the `fields` array.
21
+ *
22
+ * @group Defaults
23
+ */
24
+ const defaultPlaceholderFieldLabel = defaultPlaceholderLabel;
25
+ /**
26
+ * Default `label` for placeholder option group in the `fields` array.
27
+ *
28
+ * @group Defaults
29
+ */
30
+ const defaultPlaceholderFieldGroupLabel = defaultPlaceholderLabel;
31
+ /**
32
+ * Default `name` for placeholder option in the `operators` array.
33
+ *
34
+ * @group Defaults
35
+ */
36
+ const defaultPlaceholderOperatorName = defaultPlaceholderName;
37
+ /**
38
+ * Default `label` for placeholder option in the `operators` array.
39
+ *
40
+ * @group Defaults
41
+ */
42
+ const defaultPlaceholderOperatorLabel = defaultPlaceholderLabel;
43
+ /**
44
+ * Default `label` for placeholder option group in the `operators` array.
45
+ *
46
+ * @group Defaults
47
+ */
48
+ const defaultPlaceholderOperatorGroupLabel = defaultPlaceholderLabel;
49
+ /**
50
+ * Default `name` for placeholder option in the `values` array.
51
+ *
52
+ * @group Defaults
53
+ */
54
+ const defaultPlaceholderValueName = defaultPlaceholderName;
55
+ /**
56
+ * Default `label` for placeholder option in the `values` array.
57
+ *
58
+ * @group Defaults
59
+ */
60
+ const defaultPlaceholderValueLabel = defaultPlaceholderLabel;
61
+ /**
62
+ * Default `label` for placeholder option group in the `values` array.
63
+ *
64
+ * @group Defaults
65
+ */
66
+ const defaultPlaceholderValueGroupLabel = defaultPlaceholderLabel;
67
+ /**
68
+ * Default character used to `.join` and `.split` arrays.
69
+ *
70
+ * @group Defaults
71
+ */
72
+ const defaultJoinChar = ",";
73
+ const defaultOperatorLabelMap = {
74
+ "=": "=",
75
+ "!=": "!=",
76
+ "<": "<",
77
+ ">": ">",
78
+ "<=": "<=",
79
+ ">=": ">=",
80
+ contains: "contains",
81
+ beginsWith: "begins with",
82
+ endsWith: "ends with",
83
+ doesNotContain: "does not contain",
84
+ doesNotBeginWith: "does not begin with",
85
+ doesNotEndWith: "does not end with",
86
+ null: "is null",
87
+ notNull: "is not null",
88
+ in: "in",
89
+ notIn: "not in",
90
+ between: "between",
91
+ notBetween: "not between"
92
+ };
93
+ const defaultCombinatorLabelMap = {
94
+ and: "AND",
95
+ or: "OR",
96
+ xor: "XOR"
97
+ };
98
+ /**
99
+ * Default operator list.
100
+ *
101
+ * @group Defaults
102
+ */
103
+ const defaultOperators = [
104
+ {
105
+ name: "=",
106
+ value: "=",
107
+ label: "="
108
+ },
109
+ {
110
+ name: "!=",
111
+ value: "!=",
112
+ label: "!="
113
+ },
114
+ {
115
+ name: "<",
116
+ value: "<",
117
+ label: "<"
118
+ },
119
+ {
120
+ name: ">",
121
+ value: ">",
122
+ label: ">"
123
+ },
124
+ {
125
+ name: "<=",
126
+ value: "<=",
127
+ label: "<="
128
+ },
129
+ {
130
+ name: ">=",
131
+ value: ">=",
132
+ label: ">="
133
+ },
134
+ {
135
+ name: "contains",
136
+ value: "contains",
137
+ label: "contains"
138
+ },
139
+ {
140
+ name: "beginsWith",
141
+ value: "beginsWith",
142
+ label: "begins with"
143
+ },
144
+ {
145
+ name: "endsWith",
146
+ value: "endsWith",
147
+ label: "ends with"
148
+ },
149
+ {
150
+ name: "doesNotContain",
151
+ value: "doesNotContain",
152
+ label: "does not contain"
153
+ },
154
+ {
155
+ name: "doesNotBeginWith",
156
+ value: "doesNotBeginWith",
157
+ label: "does not begin with"
158
+ },
159
+ {
160
+ name: "doesNotEndWith",
161
+ value: "doesNotEndWith",
162
+ label: "does not end with"
163
+ },
164
+ {
165
+ name: "null",
166
+ value: "null",
167
+ label: "is null"
168
+ },
169
+ {
170
+ name: "notNull",
171
+ value: "notNull",
172
+ label: "is not null"
173
+ },
174
+ {
175
+ name: "in",
176
+ value: "in",
177
+ label: "in"
178
+ },
179
+ {
180
+ name: "notIn",
181
+ value: "notIn",
182
+ label: "not in"
183
+ },
184
+ {
185
+ name: "between",
186
+ value: "between",
187
+ label: "between"
188
+ },
189
+ {
190
+ name: "notBetween",
191
+ value: "notBetween",
192
+ label: "not between"
193
+ }
194
+ ];
195
+ /**
196
+ * Map of default operators to their respective opposite/negating operators.
197
+ *
198
+ * @group Defaults
199
+ */
200
+ const defaultOperatorNegationMap = {
201
+ "=": "!=",
202
+ "!=": "=",
203
+ "<": ">=",
204
+ "<=": ">",
205
+ ">": "<=",
206
+ ">=": "<",
207
+ beginsWith: "doesNotBeginWith",
208
+ doesNotBeginWith: "beginsWith",
209
+ endsWith: "doesNotEndWith",
210
+ doesNotEndWith: "endsWith",
211
+ contains: "doesNotContain",
212
+ doesNotContain: "contains",
213
+ between: "notBetween",
214
+ notBetween: "between",
215
+ in: "notIn",
216
+ notIn: "in",
217
+ notNull: "null",
218
+ null: "notNull"
219
+ };
220
+ /**
221
+ * Default combinator list.
222
+ *
223
+ * @group Defaults
224
+ */
225
+ const defaultCombinators = [{
226
+ name: "and",
227
+ value: "and",
228
+ label: "AND"
229
+ }, {
230
+ name: "or",
231
+ value: "or",
232
+ label: "OR"
233
+ }];
234
+ /**
235
+ * Default combinator list, with `XOR` added.
236
+ *
237
+ * @group Defaults
238
+ */
239
+ const defaultCombinatorsExtended = [...defaultCombinators, {
240
+ name: "xor",
241
+ value: "xor",
242
+ label: "XOR"
243
+ }];
244
+ /**
245
+ * Default match modes.
246
+ *
247
+ * @group Defaults
248
+ */
249
+ const defaultMatchModes = [
250
+ {
251
+ name: "all",
252
+ value: "all",
253
+ label: "all"
254
+ },
255
+ {
256
+ name: "some",
257
+ value: "some",
258
+ label: "some"
259
+ },
260
+ {
261
+ name: "none",
262
+ value: "none",
263
+ label: "none"
264
+ },
265
+ {
266
+ name: "atLeast",
267
+ value: "atLeast",
268
+ label: "at least"
269
+ },
270
+ {
271
+ name: "atMost",
272
+ value: "atMost",
273
+ label: "at most"
274
+ },
275
+ {
276
+ name: "exactly",
277
+ value: "exactly",
278
+ label: "exactly"
279
+ }
280
+ ];
281
+ /**
282
+ * Standard classnames applied to each component.
283
+ *
284
+ * @group Defaults
285
+ */
286
+ const standardClassnames = {
287
+ queryBuilder: "queryBuilder",
288
+ ruleGroup: "ruleGroup",
289
+ header: "ruleGroup-header",
290
+ body: "ruleGroup-body",
291
+ combinators: "ruleGroup-combinators",
292
+ addRule: "ruleGroup-addRule",
293
+ addGroup: "ruleGroup-addGroup",
294
+ cloneRule: "rule-cloneRule",
295
+ cloneGroup: "ruleGroup-cloneGroup",
296
+ removeGroup: "ruleGroup-remove",
297
+ notToggle: "ruleGroup-notToggle",
298
+ rule: "rule",
299
+ fields: "rule-fields",
300
+ matchMode: "rule-matchMode",
301
+ matchThreshold: "rule-matchThreshold",
302
+ operators: "rule-operators",
303
+ value: "rule-value",
304
+ removeRule: "rule-remove",
305
+ betweenRules: "betweenRules",
306
+ valid: "queryBuilder-valid",
307
+ invalid: "queryBuilder-invalid",
308
+ shiftActions: "shiftActions",
309
+ dndDragging: "dndDragging",
310
+ dndOver: "dndOver",
311
+ dndCopy: "dndCopy",
312
+ dndGroup: "dndGroup",
313
+ dndDropNotAllowed: "dndDropNotAllowed",
314
+ dragHandle: "queryBuilder-dragHandle",
315
+ disabled: "queryBuilder-disabled",
316
+ lockRule: "rule-lock",
317
+ lockGroup: "ruleGroup-lock",
318
+ valueSource: "rule-valueSource",
319
+ valueListItem: "rule-value-list-item",
320
+ branches: "queryBuilder-branches",
321
+ justified: "queryBuilder-justified",
322
+ hasSubQuery: "rule-hasSubQuery"
323
+ };
324
+ /**
325
+ * Default classnames for each component.
326
+ *
327
+ * @group Defaults
328
+ */
329
+ const defaultControlClassnames = {
330
+ queryBuilder: "",
331
+ ruleGroup: "",
332
+ header: "",
333
+ body: "",
334
+ combinators: "",
335
+ addRule: "",
336
+ addGroup: "",
337
+ cloneRule: "",
338
+ cloneGroup: "",
339
+ removeGroup: "",
340
+ notToggle: "",
341
+ rule: "",
342
+ fields: "",
343
+ matchMode: "",
344
+ matchThreshold: "",
345
+ operators: "",
346
+ value: "",
347
+ removeRule: "",
348
+ shiftActions: "",
349
+ dragHandle: "",
350
+ lockRule: "",
351
+ lockGroup: "",
352
+ valueSource: "",
353
+ actionElement: "",
354
+ valueSelector: "",
355
+ betweenRules: "",
356
+ valid: "",
357
+ invalid: "",
358
+ dndDragging: "",
359
+ dndOver: "",
360
+ dndGroup: "",
361
+ dndCopy: "",
362
+ dndDropNotAllowed: "",
363
+ disabled: "",
364
+ valueListItem: "",
365
+ branches: "",
366
+ hasSubQuery: ""
367
+ };
368
+ /**
369
+ * Default reason codes for a group being invalid.
370
+ *
371
+ * @group Defaults
372
+ */
373
+ const groupInvalidReasons = {
374
+ empty: "empty",
375
+ invalidCombinator: "invalid combinator",
376
+ invalidIndependentCombinators: "invalid independent combinators"
377
+ };
378
+ /**
379
+ * Component identifiers for testing.
380
+ *
381
+ * @group Defaults
382
+ */
383
+ const TestID = {
384
+ rule: "rule",
385
+ ruleGroup: "rule-group",
386
+ inlineCombinator: "inline-combinator",
387
+ addGroup: "add-group",
388
+ removeGroup: "remove-group",
389
+ cloneGroup: "clone-group",
390
+ cloneRule: "clone-rule",
391
+ addRule: "add-rule",
392
+ removeRule: "remove-rule",
393
+ combinators: "combinators",
394
+ fields: "fields",
395
+ operators: "operators",
396
+ valueEditor: "value-editor",
397
+ notToggle: "not-toggle",
398
+ shiftActions: "shift-actions",
399
+ dragHandle: "drag-handle",
400
+ lockRule: "lock-rule",
401
+ lockGroup: "lock-group",
402
+ valueSourceSelector: "value-source-selector",
403
+ matchModeEditor: "match-mode-editor"
404
+ };
405
+ const LogType = {
406
+ parentPathDisabled: "action aborted: parent path disabled",
407
+ pathDisabled: "action aborted: path is disabled",
408
+ queryUpdate: "query updated",
409
+ onAddRuleFalse: "onAddRule callback returned false",
410
+ onAddGroupFalse: "onAddGroup callback returned false",
411
+ onGroupRuleFalse: "onGroupRule callback returned false",
412
+ onGroupGroupFalse: "onGroupGroup callback returned false",
413
+ onMoveRuleFalse: "onMoveRule callback returned false",
414
+ onMoveGroupFalse: "onMoveGroup callback returned false",
415
+ onRemoveFalse: "onRemove callback returned false",
416
+ add: "rule or group added",
417
+ remove: "rule or group removed",
418
+ update: "rule or group updated",
419
+ move: "rule or group moved",
420
+ group: "rule or group grouped with another"
421
+ };
422
+ /**
423
+ * The {@link Path} of the root group.
424
+ *
425
+ * @group Defaults
426
+ */
427
+ const rootPath = [];
428
+
429
+ //#endregion
430
+ //#region src/utils/arrayUtils.ts
431
+ /**
432
+ * Splits a string by a given character (see {@link defaultJoinChar}). Escaped characters
433
+ * (characters preceded by a backslash) will not apply to the split, and the backslash will
434
+ * be removed in the array element. Inverse of {@link joinWith}.
435
+ *
436
+ * @example
437
+ * splitBy('this\\,\\,that,,the other,,,\\,')
438
+ * // or
439
+ * splitBy('this\\,\\,that,,the other,,,\\,', ',')
440
+ * // would return
441
+ * ['this,,that', '', 'the other', '', '', ',']
442
+ */
443
+ const splitBy = (str, splitChar = defaultJoinChar) => typeof str === "string" ? str.split(`\\${splitChar}`).map((c) => c.split(splitChar)).reduce((prev, curr, idx) => {
444
+ if (idx === 0) return curr;
445
+ return [
446
+ ...prev.slice(0, -1),
447
+ `${prev.at(-1)}${splitChar}${curr[0]}`,
448
+ ...curr.slice(1)
449
+ ];
450
+ }, []) : [];
451
+ /**
452
+ * Joins an array of strings using the given character (see {@link defaultJoinChar}). When
453
+ * the given character appears in an array element, a backslash will be added just before it
454
+ * to distinguish it from the join character. Effectively the inverse of {@link splitBy}.
455
+ *
456
+ * TIP: The join character can actually be a string of any length. Only the first character
457
+ * will be searched for in the array elements and preceded by a backslash.
458
+ *
459
+ * @example
460
+ * joinWith(['this,,that', '', 'the other', '', '', ','], ', ')
461
+ * // would return
462
+ * 'this\\,\\,that, , the other, , , \\,'
463
+ */
464
+ const joinWith = (strArr, joinChar = defaultJoinChar) => strArr.map((str) => `${str ?? ""}`.replaceAll(joinChar[0], `\\${joinChar[0]}`)).join(joinChar);
465
+ /**
466
+ * Trims the value if it is a string. Otherwise returns the value as is.
467
+ */
468
+ const trimIfString = (val) => typeof val === "string" ? val.trim() : val;
469
+ /**
470
+ * Splits a string by comma then trims each element. Arrays are returned as is except
471
+ * any string elements are trimmed.
472
+ */
473
+ const toArray = (v, { retainEmptyStrings } = {}) => Array.isArray(v) ? v.map((v$1) => trimIfString(v$1)) : typeof v === "string" ? splitBy(v, defaultJoinChar).filter(retainEmptyStrings ? () => true : (s) => !/^\s*$/.test(s)).map((s) => s.trim()) : typeof v === "number" ? [v] : [];
474
+ /**
475
+ * Determines if an array is free of `null`/`undefined`.
476
+ */
477
+ const nullFreeArray = (arr) => arr.every((el) => el === false || (el ?? false) !== false);
478
+
479
+ //#endregion
480
+ //#region src/utils/clsx.ts
481
+ // istanbul ignore next
482
+ function toVal(mix) {
483
+ let k;
484
+ let y;
485
+ let str = "";
486
+ if (typeof mix === "string" || typeof mix === "number") str += mix;
487
+ else if (typeof mix === "object") {
488
+ if (Array.isArray(mix)) {
489
+ const len = mix.length;
490
+ for (k = 0; k < len; k++) if (mix[k] && (y = toVal(mix[k]))) {
491
+ str && (str += " ");
492
+ str += y;
493
+ }
494
+ } else for (y in mix) if (mix[y]) {
495
+ str && (str += " ");
496
+ str += y;
497
+ }
498
+ }
499
+ return str;
500
+ }
501
+ // istanbul ignore next
502
+ function clsx(...args) {
503
+ let i = 0;
504
+ let tmp;
505
+ let x;
506
+ let str = "";
507
+ const len = args.length;
508
+ for (; i < len; i++) if ((tmp = args[i]) && (x = toVal(tmp))) {
509
+ str && (str += " ");
510
+ str += x;
511
+ }
512
+ return str;
513
+ }
514
+
515
+ //#endregion
516
+ //#region src/utils/misc.ts
517
+ /**
518
+ * Converts a value to lowercase if it's a string, otherwise returns the value as is.
519
+ */
520
+ // istanbul ignore next
521
+ const lc = (v) => typeof v === "string" ? v.toLowerCase() : v;
522
+ /**
523
+ * Regex matching numeric strings. Passes for positive/negative integers, decimals,
524
+ * and E notation, with optional surrounding whitespace.
525
+ */
526
+ const numericRegex = new RegExp(numericRegex$1.source.replace(/^\^/, String.raw`^\s*`).replace(/\$$/, String.raw`\s*$`));
527
+ /**
528
+ * Determines if a variable is a plain old JavaScript object, aka POJO.
529
+ */
530
+ const isPojo = (obj) => obj === null || typeof obj !== "object" ? false : Object.getPrototypeOf(obj) === Object.prototype;
531
+ /**
532
+ * Simple helper to determine whether a value is null, undefined, or an empty string.
533
+ */
534
+ const nullOrUndefinedOrEmpty = (value) => value === null || value === void 0 || value === "";
535
+
536
+ //#endregion
537
+ //#region src/utils/isRuleGroup.ts
538
+ /**
539
+ * Determines if an object is a {@link RuleGroupType} or {@link RuleGroupTypeIC}.
540
+ */
541
+ const isRuleGroup = (rg) => isPojo(rg) && Array.isArray(rg.rules);
542
+ /**
543
+ * Determines if an object is a {@link RuleGroupType}.
544
+ */
545
+ const isRuleGroupType = (rg) => isRuleGroup(rg) && typeof rg.combinator === "string";
546
+ /**
547
+ * Determines if an object is a {@link RuleGroupTypeIC}.
548
+ */
549
+ const isRuleGroupTypeIC = (rg) => isRuleGroup(rg) && rg.combinator === void 0;
550
+
551
+ //#endregion
552
+ //#region src/utils/convertQuery.ts
553
+ const combinatorLevels = [
554
+ "or",
555
+ "xor",
556
+ "and"
557
+ ];
558
+ const isSameString = (a, b) => lc(a) === b;
559
+ const generateRuleGroupICWithConsistentCombinators = (rg, baseCombinatorLevel = 0) => {
560
+ const baseCombinator = combinatorLevels[baseCombinatorLevel];
561
+ if (!rg.rules.includes(baseCombinator)) return baseCombinatorLevel < combinatorLevels.length - 2 ? generateRuleGroupICWithConsistentCombinators(rg, baseCombinatorLevel + 1) : rg;
562
+ return produce(rg, (draft) => {
563
+ let cursor = 0;
564
+ while (cursor < draft.rules.length - 2) {
565
+ if (isSameString(draft.rules[cursor + 1], baseCombinator)) {
566
+ cursor += 2;
567
+ continue;
568
+ }
569
+ const nextBaseCombinatorIndex = draft.rules.findIndex((r, i) => i > cursor && typeof r === "string" && lc(r) === baseCombinator);
570
+ if (nextBaseCombinatorIndex === -1) {
571
+ draft.rules.splice(cursor, draft.rules.length, generateRuleGroupICWithConsistentCombinators({ rules: draft.rules.slice(cursor) }, baseCombinatorLevel + 1));
572
+ break;
573
+ } else draft.rules.splice(cursor, nextBaseCombinatorIndex - cursor, generateRuleGroupICWithConsistentCombinators({ rules: draft.rules.slice(cursor, nextBaseCombinatorIndex) }, baseCombinatorLevel + 1));
574
+ }
575
+ });
576
+ };
577
+ /**
578
+ * Converts a {@link RuleGroupTypeIC} to {@link RuleGroupType}.
579
+ *
580
+ * This function is idempotent: {@link RuleGroupType} queries will be
581
+ * returned as-is.
582
+ *
583
+ * @group Query Tools
584
+ */
585
+ const convertFromIC = (rg) => {
586
+ if (isRuleGroupType(rg)) return rg;
587
+ const processedRG = generateRuleGroupICWithConsistentCombinators(rg);
588
+ const rulesAsMixedList = processedRG.rules.map((r) => typeof r === "string" || !isRuleGroup(r) ? r : convertFromIC(r));
589
+ const combinator = rulesAsMixedList.length < 2 ? "and" : rulesAsMixedList[1];
590
+ const rules = rulesAsMixedList.filter((r) => typeof r !== "string");
591
+ return {
592
+ ...processedRG,
593
+ combinator,
594
+ rules
595
+ };
596
+ };
597
+ /**
598
+ * Converts a {@link RuleGroupType} to {@link RuleGroupTypeIC}.
599
+ *
600
+ * This function is idempotent: {@link RuleGroupTypeIC} queries will be
601
+ * returned as-is.
602
+ *
603
+ * @group Query Tools
604
+ */
605
+ const convertToIC = (rg) => {
606
+ if (isRuleGroupTypeIC(rg)) return rg;
607
+ const { combinator,...queryWithoutCombinator } = rg;
608
+ const rules = [];
609
+ const { length } = rg.rules;
610
+ for (const [idx, r] of rg.rules.entries()) {
611
+ if (isRuleGroup(r)) rules.push(convertToIC(r));
612
+ else rules.push(r);
613
+ if (combinator && idx < length - 1) rules.push(combinator);
614
+ }
615
+ return {
616
+ ...queryWithoutCombinator,
617
+ rules
618
+ };
619
+ };
620
+ function convertQuery(query) {
621
+ return isRuleGroupTypeIC(query) ? convertFromIC(query) : convertToIC(query);
622
+ }
623
+
624
+ //#endregion
625
+ //#region src/utils/defaultValidator.ts
626
+ /**
627
+ * This is an example validation function you can pass to {@link QueryBuilder} in the
628
+ * `validator` prop. It assumes that you want to validate groups, and has a no-op
629
+ * for validating rules which you can replace with your own implementation.
630
+ */
631
+ const defaultValidator = (query) => {
632
+ const result = {};
633
+ /**
634
+ * Replace this with your custom rule validator.
635
+ */
636
+ const validateRule = (rule) => {
637
+ // istanbul ignore else
638
+ if (rule.id) result[rule.id];
639
+ };
640
+ const validateGroup = (rg) => {
641
+ const reasons = [];
642
+ if (rg.rules.length === 0) reasons.push(groupInvalidReasons.empty);
643
+ else if (!isRuleGroupType(rg)) {
644
+ let invalidICs = false;
645
+ for (let i = 0; i < rg.rules.length && !invalidICs; i++) if (i % 2 === 0 && typeof rg.rules[i] === "string" || i % 2 === 1 && typeof rg.rules[i] !== "string" || i % 2 === 1 && typeof rg.rules[i] === "string" && !defaultCombinators.map((c) => c.name).includes(rg.rules[i])) invalidICs = true;
646
+ if (invalidICs) reasons.push(groupInvalidReasons.invalidIndependentCombinators);
647
+ }
648
+ if (isRuleGroupType(rg) && !defaultCombinators.map((c) => c.name).includes(rg.combinator) && rg.rules.length > 1) reasons.push(groupInvalidReasons.invalidCombinator);
649
+ /* istanbul ignore else */
650
+ if (rg.id) result[rg.id] = reasons.length > 0 ? {
651
+ valid: false,
652
+ reasons
653
+ } : true;
654
+ for (const r of rg.rules) if (typeof r === "string") {} else if (isRuleGroup(r)) validateGroup(r);
655
+ else validateRule(r);
656
+ };
657
+ validateGroup(query);
658
+ return result;
659
+ };
660
+
661
+ //#endregion
662
+ //#region src/utils/optGroupUtils.ts
663
+ const isOptionWithName = (opt) => isPojo(opt) && "name" in opt && typeof opt.name === "string";
664
+ const isOptionWithValue = (opt) => isPojo(opt) && "value" in opt && typeof opt.value === "string";
665
+ /**
666
+ * Converts an {@link Option} or {@link ValueOption} (i.e., {@link BaseOption})
667
+ * into a {@link FullOption}. Full options are left unchanged.
668
+ *
669
+ * @group Option Lists
670
+ */
671
+ function toFullOption(opt, baseProperties, labelMap) {
672
+ return produce((draft) => {
673
+ const idObj = {};
674
+ let needsUpdating = !!baseProperties;
675
+ if (typeof draft === "string") return {
676
+ ...baseProperties,
677
+ name: draft,
678
+ value: draft,
679
+ label: labelMap?.[draft] ?? draft
680
+ };
681
+ if (isOptionWithName(draft) && !isOptionWithValue(draft)) {
682
+ idObj.value = draft.name;
683
+ needsUpdating = true;
684
+ } else if (!isOptionWithName(draft) && isOptionWithValue(draft)) {
685
+ idObj.name = draft.value;
686
+ needsUpdating = true;
687
+ }
688
+ if (needsUpdating) return Object.assign({}, baseProperties, draft, idObj);
689
+ })(opt);
690
+ }
691
+ /**
692
+ * Converts an {@link OptionList} or {@link FlexibleOptionList} into a {@link FullOptionList}.
693
+ * Lists of full options are left unchanged.
694
+ *
695
+ * @group Option Lists
696
+ */
697
+ function toFullOptionList(optList, baseProperties, labelMap) {
698
+ if (!Array.isArray(optList)) return [];
699
+ return produce((draft) => {
700
+ if (isFlexibleOptionGroupArray(draft)) for (const optGroup of draft) for (const [idx, opt] of optGroup.options.entries()) optGroup.options[idx] = toFullOption(opt, baseProperties, labelMap);
701
+ else for (const [idx, opt] of draft.entries()) draft[idx] = toFullOption(opt, baseProperties, labelMap);
702
+ })(optList);
703
+ }
704
+ /**
705
+ * Converts a {@link FlexibleOptionList} into a {@link FullOptionList}.
706
+ * Lists of full options are left unchanged.
707
+ *
708
+ * @group Option Lists
709
+ */
710
+ function toFullOptionMap(optMap, baseProperties) {
711
+ return Object.fromEntries(Object.entries(optMap).map(([k, v]) => [k, toFullOption(v, baseProperties)]));
712
+ }
713
+ /**
714
+ * @deprecated Renamed to {@link uniqByIdentifier}.
715
+ *
716
+ * @group Option Lists
717
+ */
718
+ const uniqByName = (originalArray) => uniqByIdentifier(originalArray);
719
+ /**
720
+ * Generates a new array of objects with duplicates removed based
721
+ * on the identifying property (`value` or `name`)
722
+ *
723
+ * @group Option Lists
724
+ */
725
+ const uniqByIdentifier = (originalArray) => {
726
+ const names = /* @__PURE__ */ new Set();
727
+ const newArray = [];
728
+ for (const el of originalArray) if (!names.has(el.value ?? el.name)) {
729
+ names.add(el.value ?? el.name);
730
+ newArray.push(el);
731
+ }
732
+ return originalArray.length === newArray.length ? originalArray : newArray;
733
+ };
734
+ /**
735
+ * Determines if an {@link OptionList} is an {@link OptionGroup} array.
736
+ *
737
+ * @group Option Lists
738
+ */
739
+ const isOptionGroupArray = (arr) => Array.isArray(arr) && arr.length > 0 && isPojo(arr[0]) && "options" in arr[0] && Array.isArray(arr[0].options);
740
+ /**
741
+ * Determines if an array is a flat array of {@link FlexibleOption}.
742
+ *
743
+ * @group Option Lists
744
+ */
745
+ const isFlexibleOptionArray = (arr) => {
746
+ let isFOA = false;
747
+ if (Array.isArray(arr)) for (const o of arr) if (isOptionWithName(o) || isOptionWithValue(o)) isFOA = true;
748
+ else return false;
749
+ return isFOA;
750
+ };
751
+ /**
752
+ * Determines if an array is a flat array of {@link FullOption}.
753
+ *
754
+ * @group Option Lists
755
+ */
756
+ const isFullOptionArray = (arr) => {
757
+ let isFOA = false;
758
+ if (Array.isArray(arr)) for (const o of arr) if (isOptionWithName(o) && isOptionWithValue(o)) isFOA = true;
759
+ else return false;
760
+ return isFOA;
761
+ };
762
+ /**
763
+ * Determines if a {@link FlexibleOptionList} is a {@link FlexibleOptionGroup} array.
764
+ *
765
+ * @group Option Lists
766
+ */
767
+ const isFlexibleOptionGroupArray = (arr, { allowEmpty = false } = {}) => {
768
+ let isFOGA = false;
769
+ if (Array.isArray(arr)) for (const og of arr) if (isPojo(og) && "options" in og && (isFlexibleOptionArray(og.options) || allowEmpty && Array.isArray(og.options) && og.options.length === 0)) isFOGA = true;
770
+ else return false;
771
+ return isFOGA;
772
+ };
773
+ /**
774
+ * Determines if a {@link FlexibleOptionList} is a {@link OptionGroup} array of {@link FullOption}.
775
+ *
776
+ * @group Option Lists
777
+ */
778
+ const isFullOptionGroupArray = (arr, { allowEmpty = false } = {}) => {
779
+ let isFOGA = false;
780
+ if (Array.isArray(arr)) for (const og of arr) if (isPojo(og) && "options" in og && (isFullOptionArray(og.options) || allowEmpty && Array.isArray(og.options) && og.options.length === 0)) isFOGA = true;
781
+ else return false;
782
+ return isFOGA;
783
+ };
784
+ function getOption(arr, name) {
785
+ return (isFlexibleOptionGroupArray(arr, { allowEmpty: true }) ? arr.flatMap((og) => og.options) : arr).find((op) => op.value === name || op.name === name);
786
+ }
787
+ function getFirstOption(arr) {
788
+ if (!Array.isArray(arr) || arr.length === 0) return null;
789
+ else if (isFlexibleOptionGroupArray(arr, { allowEmpty: true })) {
790
+ for (const og of arr) if (og.options.length > 0) return og.options[0].value ?? og.options[0].name;
791
+ // istanbul ignore next
792
+ return null;
793
+ }
794
+ return arr[0].value ?? arr[0].name;
795
+ }
796
+ /**
797
+ * Flattens {@link FlexibleOptionGroup} arrays into {@link BaseOption} arrays.
798
+ * If the array is already flat, it is returned as is.
799
+ *
800
+ * @group Option Lists
801
+ */
802
+ const toFlatOptionArray = (arr) => uniqByIdentifier(isOptionGroupArray(arr) ? arr.flatMap((og) => og.options) : arr);
803
+ /**
804
+ * Generates a new {@link OptionGroup} array with duplicates
805
+ * removed based on the identifying property (`value` or `name`).
806
+ *
807
+ * @group Option Lists
808
+ */
809
+ const uniqOptGroups = (originalArray) => {
810
+ const labels = /* @__PURE__ */ new Set();
811
+ const names = /* @__PURE__ */ new Set();
812
+ const newArray = [];
813
+ for (const el of originalArray) if (!labels.has(el.label)) {
814
+ labels.add(el.label);
815
+ const optionsForThisGroup = [];
816
+ for (const opt of el.options) if (!names.has(opt.value ?? opt.name)) {
817
+ names.add(opt.value ?? opt.name);
818
+ optionsForThisGroup.push(toFullOption(opt));
819
+ }
820
+ newArray.push({
821
+ ...el,
822
+ options: optionsForThisGroup
823
+ });
824
+ }
825
+ return newArray;
826
+ };
827
+ /**
828
+ * Generates a new {@link Option} or {@link OptionGroup} array with duplicates
829
+ * removed based on the identifier property (`value` or `name`).
830
+ *
831
+ * @group Option Lists
832
+ */
833
+ const uniqOptList = (originalArray) => {
834
+ if (isFlexibleOptionGroupArray(originalArray)) return uniqOptGroups(originalArray);
835
+ return uniqByIdentifier(originalArray.map((o) => toFullOption(o)));
836
+ };
837
+
838
+ //#endregion
839
+ //#region src/utils/filterFieldsByComparator.ts
840
+ const filterByComparator = (field, operator, fieldToCompare) => {
841
+ const fullField = toFullOption(field);
842
+ const fullFieldToCompare = toFullOption(fieldToCompare);
843
+ if (fullField.value === fullFieldToCompare.value) return false;
844
+ if (typeof fullField.comparator === "string") return fullField[fullField.comparator] === fullFieldToCompare[fullField.comparator];
845
+ return fullField.comparator?.(fullFieldToCompare, operator) ?? false;
846
+ };
847
+ /**
848
+ * For a given {@link FullField}, returns the `fields` list filtered for
849
+ * other fields that match by `comparator`. Only fields *other than the
850
+ * one in question* will ever be included, even if `comparator` is `null`
851
+ * or `undefined`. If `comparator` is a string, fields with the same value
852
+ * for that property will be included. If `comparator` is a function, each
853
+ * field will be passed to the function along with the `operator` and fields
854
+ * for which the function returns `true` will be included.
855
+ *
856
+ * @group Option Lists
857
+ */
858
+ const filterFieldsByComparator = (field, fields, operator) => {
859
+ if (!field.comparator) {
860
+ const filterOutSameField = (f) => (f.value ?? f.name) !== (field.value ?? field.name);
861
+ if (isFlexibleOptionGroupArray(fields)) return fields.map((og) => ({
862
+ ...og,
863
+ options: og.options.filter((v) => filterOutSameField(v))
864
+ }));
865
+ return fields.filter((v) => filterOutSameField(v));
866
+ }
867
+ if (isFlexibleOptionGroupArray(fields)) return fields.map((og) => ({
868
+ ...og,
869
+ options: og.options.filter((f) => filterByComparator(field, operator, f))
870
+ })).filter((og) => og.options.length > 0);
871
+ return fields.filter((f) => filterByComparator(field, operator, f));
872
+ };
873
+
874
+ //#endregion
875
+ //#region src/utils/parseNumber.ts
876
+ /**
877
+ * Converts a string to a number. Uses native `parseFloat` if `parseNumbers` is "native",
878
+ * otherwise uses [`numeric-quantity`](https://jakeboone02.github.io/numeric-quantity/).
879
+ * If that returns `NaN`, the string is returned unchanged. Numeric values are returned
880
+ * as-is regardless of the `parseNumbers` option.
881
+ */
882
+ const parseNumber = (val, { parseNumbers, bigIntOnOverflow } = {}) => {
883
+ if (!parseNumbers || typeof val === "bigint" || typeof val === "number") return val;
884
+ if (parseNumbers === "native") return Number.parseFloat(val);
885
+ const valAsNum = numericQuantity(val, {
886
+ allowTrailingInvalid: parseNumbers === "enhanced",
887
+ bigIntOnOverflow,
888
+ romanNumerals: false,
889
+ round: false
890
+ });
891
+ return typeof valAsNum === "bigint" || !Number.isNaN(valAsNum) ? valAsNum : val;
892
+ };
893
+
894
+ //#endregion
895
+ //#region src/utils/transformQuery.ts
896
+ const remapProperties = (obj, propertyMap, deleteRemappedProperties) => produce(obj, (draft) => {
897
+ for (const [k, v] of Object.entries(propertyMap)) if (v === false) delete draft[k];
898
+ else if (!!v && k !== v && k in draft) {
899
+ draft[v] = draft[k];
900
+ if (deleteRemappedProperties) delete draft[k];
901
+ }
902
+ });
903
+ function transformQuery(query, options = {}) {
904
+ const { ruleProcessor = (r) => r, ruleGroupProcessor = (rg) => rg, propertyMap = {}, combinatorMap = {}, operatorMap = {}, omitPath = false, deleteRemappedProperties = true } = options;
905
+ const processGroup = (rg) => ({
906
+ ...ruleGroupProcessor(remapProperties({
907
+ ...rg,
908
+ ...isRuleGroupType(rg) ? { combinator: combinatorMap[rg.combinator] ?? rg.combinator } : {}
909
+ }, propertyMap, deleteRemappedProperties)),
910
+ ...propertyMap["rules"] === false ? null : { [propertyMap["rules"] ?? "rules"]: rg.rules.map((r, idx) => {
911
+ const pathObject = omitPath ? null : { path: [...rg.path, idx] };
912
+ if (typeof r === "string") return combinatorMap[r] ?? r;
913
+ else if (isRuleGroup(r)) return processGroup({
914
+ ...r,
915
+ ...pathObject
916
+ });
917
+ return ruleProcessor(remapProperties({
918
+ ...r,
919
+ ...pathObject,
920
+ ..."operator" in r ? { operator: operatorMap[r.operator] ?? r.operator } : {}
921
+ }, propertyMap, deleteRemappedProperties));
922
+ }) }
923
+ });
924
+ return processGroup({
925
+ ...query,
926
+ ...omitPath ? null : { path: [] }
927
+ });
928
+ }
929
+
930
+ //#endregion
931
+ //#region src/utils/isRuleOrGroupValid.ts
932
+ /**
933
+ * Determines if an object is useful as a validation result.
934
+ */
935
+ const isValidationResult = (vr) => isPojo(vr) && typeof vr.valid === "boolean";
936
+ /**
937
+ * Determines if a rule or group is valid based on a validation result (if defined)
938
+ * or a validator function. Returns `true` if neither are defined.
939
+ */
940
+ const isRuleOrGroupValid = (rg, validationResult, validator) => {
941
+ if (typeof validationResult === "boolean") return validationResult;
942
+ if (isValidationResult(validationResult)) return validationResult.valid;
943
+ if (typeof validator === "function" && !isRuleGroup(rg)) {
944
+ const vr = validator(rg);
945
+ if (typeof vr === "boolean") return vr;
946
+ // istanbul ignore else
947
+ if (isValidationResult(vr)) return vr.valid;
948
+ }
949
+ return true;
950
+ };
951
+
952
+ //#endregion
953
+ //#region src/utils/getParseNumberMethod.ts
954
+ const getParseNumberMethod = ({ parseNumbers, inputType }) => {
955
+ if (typeof parseNumbers === "string") {
956
+ const [method, level] = parseNumbers.split("-");
957
+ if (level === "limited") return inputType === "number" ? method : false;
958
+ return method;
959
+ }
960
+ return parseNumbers ? "strict" : false;
961
+ };
962
+
963
+ //#endregion
964
+ //#region src/utils/formatQuery/utils.ts
965
+ /**
966
+ * Maps a {@link DefaultOperatorName} to a SQL operator.
967
+ *
968
+ * @group Export
969
+ */
970
+ const mapSQLOperator = (rqbOperator) => {
971
+ switch (lc(rqbOperator)) {
972
+ case "null": return "is null";
973
+ case "notnull": return "is not null";
974
+ case "notin": return "not in";
975
+ case "notbetween": return "not between";
976
+ case "contains":
977
+ case "beginswith":
978
+ case "endswith": return "like";
979
+ case "doesnotcontain":
980
+ case "doesnotbeginwith":
981
+ case "doesnotendwith": return "not like";
982
+ default: return rqbOperator;
983
+ }
984
+ };
985
+ /**
986
+ * Maps a (lowercase) {@link DefaultOperatorName} to a MongoDB operator.
987
+ *
988
+ * @group Export
989
+ */
990
+ const mongoOperators = {
991
+ "=": "$eq",
992
+ "!=": "$ne",
993
+ "<": "$lt",
994
+ "<=": "$lte",
995
+ ">": "$gt",
996
+ ">=": "$gte",
997
+ in: "$in",
998
+ notin: "$nin",
999
+ notIn: "$nin"
1000
+ };
1001
+ /**
1002
+ * Maps a (lowercase) {@link DefaultOperatorName} to a Prisma ORM operator.
1003
+ *
1004
+ * @group Export
1005
+ */
1006
+ const prismaOperators = {
1007
+ "=": "equals",
1008
+ "!=": "not",
1009
+ "<": "lt",
1010
+ "<=": "lte",
1011
+ ">": "gt",
1012
+ ">=": "gte",
1013
+ in: "in",
1014
+ notin: "notIn"
1015
+ };
1016
+ /**
1017
+ * Maps a {@link DefaultCombinatorName} to a CEL combinator.
1018
+ *
1019
+ * @group Export
1020
+ */
1021
+ const celCombinatorMap = {
1022
+ and: "&&",
1023
+ or: "||"
1024
+ };
1025
+ /**
1026
+ * Register these operators with `jsonLogic` before applying the result
1027
+ * of `formatQuery(query, 'jsonlogic')`.
1028
+ *
1029
+ * @example
1030
+ * ```
1031
+ * for (const [op, func] of Object.entries(jsonLogicAdditionalOperators)) {
1032
+ * jsonLogic.add_operation(op, func);
1033
+ * }
1034
+ * jsonLogic.apply({ "startsWith": [{ "var": "firstName" }, "Stev"] }, data);
1035
+ * ```
1036
+ *
1037
+ * @group Export
1038
+ */
1039
+ const jsonLogicAdditionalOperators = {
1040
+ startsWith: (a, b) => typeof a === "string" && a.startsWith(b),
1041
+ endsWith: (a, b) => typeof a === "string" && a.endsWith(b)
1042
+ };
1043
+ /**
1044
+ * Converts all `string`-type `value` properties of a query object into `number` where appropriate.
1045
+ *
1046
+ * Used by {@link formatQuery} for the `json*` formats when `parseNumbers` is `true`.
1047
+ *
1048
+ * @group Export
1049
+ */
1050
+ const numerifyValues = (rg, options) => ({
1051
+ ...rg,
1052
+ rules: rg.rules.map((r) => {
1053
+ if (typeof r === "string") return r;
1054
+ if (isRuleGroup(r)) return numerifyValues(r, options);
1055
+ const fieldData = getOption(options.fields, r.field);
1056
+ const parseNumbers = getParseNumberMethod({
1057
+ parseNumbers: options.parseNumbers,
1058
+ inputType: fieldData?.inputType
1059
+ });
1060
+ if (Array.isArray(r.value)) return {
1061
+ ...r,
1062
+ value: r.value.map((v) => parseNumber(v, { parseNumbers }))
1063
+ };
1064
+ const valAsArray = toArray(r.value, { retainEmptyStrings: true }).map((v) => parseNumber(v, { parseNumbers }));
1065
+ if (valAsArray.every((v) => typeof v === "number")) {
1066
+ // istanbul ignore else
1067
+ if (valAsArray.length > 1) return {
1068
+ ...r,
1069
+ value: valAsArray
1070
+ };
1071
+ else if (valAsArray.length === 1) return {
1072
+ ...r,
1073
+ value: valAsArray[0]
1074
+ };
1075
+ }
1076
+ return r;
1077
+ })
1078
+ });
1079
+ /**
1080
+ * Determines whether a value is _anything_ except an empty `string` or `NaN`.
1081
+ *
1082
+ * @group Export
1083
+ */
1084
+ const isValidValue = (value) => typeof value === "string" && value.length > 0 || typeof value === "number" && !Number.isNaN(value) || typeof value !== "string" && typeof value !== "number";
1085
+ /**
1086
+ * Determines whether {@link formatQuery} should render the given value as a number.
1087
+ * As long as `parseNumbers` is `true`, `number` and `bigint` values will return `true` and
1088
+ * `string` values will return `true` if they test positive against {@link numericRegex}.
1089
+ *
1090
+ * @group Export
1091
+ */
1092
+ const shouldRenderAsNumber = (value, parseNumbers) => !!parseNumbers && (typeof value === "number" || typeof value === "bigint" || typeof value === "string" && numericRegex.test(value));
1093
+ /**
1094
+ * Used by {@link formatQuery} to determine whether the given value processor is a
1095
+ * "legacy" value processor by counting the number of arguments. Legacy value
1096
+ * processors take 3 arguments (not counting any arguments with default values), while
1097
+ * rule-based value processors take no more than 2 arguments.
1098
+ *
1099
+ * @group Export
1100
+ */
1101
+ const isValueProcessorLegacy = (valueProcessor) => valueProcessor.length >= 3;
1102
+ /**
1103
+ * Converts the `quoteFieldNamesWith` option into an array of two strings.
1104
+ * If the option is a string, the array elements are both that string.
1105
+ *
1106
+ * @default
1107
+ * ['', '']
1108
+ *
1109
+ * @group Export
1110
+ */
1111
+ const getQuoteFieldNamesWithArray = (quoteFieldNamesWith = ["", ""]) => Array.isArray(quoteFieldNamesWith) ? quoteFieldNamesWith : typeof quoteFieldNamesWith === "string" ? [quoteFieldNamesWith, quoteFieldNamesWith] : quoteFieldNamesWith ?? ["", ""];
1112
+ /**
1113
+ * Given a field name and relevant {@link ValueProcessorOptions}, returns the field name
1114
+ * wrapped in the configured quote character(s).
1115
+ *
1116
+ * @group Export
1117
+ */
1118
+ const getQuotedFieldName = (fieldName, { quoteFieldNamesWith, fieldIdentifierSeparator }) => {
1119
+ const [qPre, qPost] = getQuoteFieldNamesWithArray(quoteFieldNamesWith);
1120
+ return typeof fieldIdentifierSeparator === "string" && fieldIdentifierSeparator.length > 0 ? joinWith(splitBy(fieldName, fieldIdentifierSeparator).map((part) => `${qPre}${part}${qPost}`), fieldIdentifierSeparator) : `${qPre}${fieldName}${qPost}`;
1121
+ };
1122
+ const defaultWordOrder = [
1123
+ "S",
1124
+ "V",
1125
+ "O"
1126
+ ];
1127
+ /**
1128
+ * Given a [Constituent word order](https://en.wikipedia.org/wiki/Word_order#Constituent_word_orders)
1129
+ * like "svo" or "sov", returns a permutation of `["S", "V", "O"]` based on the first occurrence of
1130
+ * each letter in the input string (case insensitive). This widens the valid input from abbreviations
1131
+ * like "svo" to more expressive strings like "subject-verb-object" or "sub ver obj". Any missing
1132
+ * letters are appended in the default order "SVO" (e.g., "object" would yield `["O", "S", "V"]`).
1133
+ *
1134
+ * @group Export
1135
+ */
1136
+ const normalizeConstituentWordOrder = (input) => {
1137
+ const result = [];
1138
+ const letterSet = new Set(defaultWordOrder);
1139
+ for (const char of input.toUpperCase()) if (letterSet.has(char)) {
1140
+ result.push(char);
1141
+ letterSet.delete(char);
1142
+ if (letterSet.size === 0) break;
1143
+ }
1144
+ for (const letter of defaultWordOrder) if (letterSet.has(letter)) result.push(letter);
1145
+ return result;
1146
+ };
1147
+ /**
1148
+ * Default translations used by {@link formatQuery} for "natural_language" format.
1149
+ *
1150
+ * @group Export
1151
+ */
1152
+ const defaultNLTranslations = {
1153
+ groupPrefix: "",
1154
+ groupPrefix_not_xor: "either zero or more than one of",
1155
+ groupPrefix_xor: "exactly one of",
1156
+ groupSuffix: "is true",
1157
+ groupSuffix_not: "is not true"
1158
+ };
1159
+ /**
1160
+ * Note: This function assumes `conditions.length > 0`
1161
+ */
1162
+ const translationMatchFilter = (key, keyToTest, conditions) => keyToTest.startsWith(key) && conditions.every((c) => keyToTest.includes(`_${c}`) && keyToTest.match(/_/g)?.length === conditions.length);
1163
+ /**
1164
+ * Used by {@link formatQuery} to get a translation based on certain conditions
1165
+ * for the "natural_language" format.
1166
+ *
1167
+ * @group Export
1168
+ */
1169
+ 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] ?? "";
1170
+ const processMatchMode = (rule) => {
1171
+ const { mode, threshold } = rule.match ?? {};
1172
+ if (mode) {
1173
+ if (!isRuleGroup(rule.value)) return false;
1174
+ const matchModeLC = lc(mode);
1175
+ const matchModeCoerced = matchModeLC === "atleast" && threshold === 1 ? "some" : matchModeLC === "atmost" && threshold === 0 ? "none" : matchModeLC;
1176
+ if ((matchModeCoerced === "atleast" || matchModeCoerced === "atmost" || matchModeCoerced === "exactly") && (typeof threshold !== "number" || threshold < 0)) return false;
1177
+ return {
1178
+ mode: matchModeCoerced,
1179
+ threshold
1180
+ };
1181
+ }
1182
+ };
1183
+ /**
1184
+ * "Replacer" method for JSON.stringify's second argument. Converts `bigint` values to
1185
+ * objects with a `$bigint` property having a value of a string representation of
1186
+ * the actual `bigint`-type value.
1187
+ *
1188
+ * Inverse of {@link bigIntJsonParseReviver}.
1189
+ *
1190
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json
1191
+ */
1192
+ const bigIntJsonStringifyReplacer = (_key, value) => typeof value === "bigint" ? { $bigint: value.toString() } : value;
1193
+ /**
1194
+ * "Reviver" method for JSON.parse's second argument. Converts objects having a single
1195
+ * `$bigint: string` property to an actual `bigint` value.
1196
+ *
1197
+ * Inverse of {@link bigIntJsonStringifyReplacer}.
1198
+ *
1199
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json
1200
+ */
1201
+ const bigIntJsonParseReviver = (_key, value) => isPojo(value) && Object.keys(value).length === 1 && typeof value.$bigint === "string" ? BigInt(value.$bigint) : value;
1202
+
1203
+ //#endregion
1204
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorCEL.ts
1205
+ /**
1206
+ * Rule group processor used by {@link formatQuery} for "cel" format.
1207
+ *
1208
+ * @group Export
1209
+ */
1210
+ const defaultRuleGroupProcessorCEL = (ruleGroup, options) => {
1211
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1212
+ const processRuleGroup = (rg, outermost) => {
1213
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1214
+ const expression = rg.rules.map((rule) => {
1215
+ if (typeof rule === "string") return celCombinatorMap[rule];
1216
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1217
+ const [validationResult, fieldValidator] = validateRule(rule);
1218
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1219
+ const fieldData = getOption(fields, rule.field);
1220
+ return ruleProcessor(rule, {
1221
+ ...options,
1222
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1223
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1224
+ fieldData
1225
+ });
1226
+ }).filter(Boolean).join(isRuleGroupType(rg) ? ` ${celCombinatorMap[rg.combinator]} ` : " ");
1227
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "!" : ""}(`, ")"] : ["", ""];
1228
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1229
+ };
1230
+ return processRuleGroup(ruleGroup, true);
1231
+ };
1232
+
1233
+ //#endregion
1234
+ //#region src/utils/formatQuery/defaultRuleProcessorCEL.ts
1235
+ const shouldNegate$2 = (op) => op.startsWith("not") || op.startsWith("doesnot");
1236
+ const escapeDoubleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`);
1237
+ /**
1238
+ * Default rule processor used by {@link formatQuery} for "cel" format.
1239
+ *
1240
+ * @group Export
1241
+ */
1242
+ const defaultRuleProcessorCEL = (rule, opts = {}) => {
1243
+ const { escapeQuotes, parseNumbers, preserveValueOrder } = opts;
1244
+ const { field, operator, value, valueSource } = rule;
1245
+ const valueIsField = valueSource === "field";
1246
+ const operatorTL = lc(operator === "=" ? "==" : operator);
1247
+ const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
1248
+ const matchEval = processMatchMode(rule);
1249
+ if (matchEval === false) return "";
1250
+ else if (matchEval) {
1251
+ const { mode, threshold } = matchEval;
1252
+ const arrayElementAlias = "elem_alias";
1253
+ const celQuery = transformQuery(rule.value, { ruleProcessor: (r) => ({
1254
+ ...r,
1255
+ field: `${arrayElementAlias}${r.field ? `.${r.field}` : ""}`
1256
+ }) });
1257
+ const nestedArrayFilter = defaultRuleGroupProcessorCEL(celQuery, opts);
1258
+ switch (mode) {
1259
+ case "all": return `${field}.all(${arrayElementAlias}, ${nestedArrayFilter})`;
1260
+ case "none":
1261
+ case "some": return `${mode === "none" ? "!" : ""}${field}.exists(${arrayElementAlias}, ${nestedArrayFilter})`;
1262
+ case "atleast":
1263
+ case "atmost":
1264
+ case "exactly": {
1265
+ const totalCount = `double(${field}.size())`;
1266
+ const filteredCount = `${field}.filter(${arrayElementAlias}, ${nestedArrayFilter}).size()`;
1267
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "==";
1268
+ if (threshold > 0 && threshold < 1) return `${filteredCount} ${op} (${totalCount} * ${threshold})`;
1269
+ return `${filteredCount} ${op} ${threshold}`;
1270
+ }
1271
+ }
1272
+ }
1273
+ switch (operatorTL) {
1274
+ case "<":
1275
+ case "<=":
1276
+ case "==":
1277
+ case "!=":
1278
+ case ">":
1279
+ case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`}`;
1280
+ case "contains":
1281
+ case "doesnotcontain": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.contains(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
1282
+ case "beginswith":
1283
+ case "doesnotbeginwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.startsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
1284
+ case "endswith":
1285
+ case "doesnotendwith": return `${shouldNegate$2(operatorTL) ? "!" : ""}${field}.endsWith(${valueIsField ? trimIfString(value) : `"${escapeDoubleQuotes(value, escapeQuotes)}"`})`;
1286
+ case "null": return `${field} == null`;
1287
+ case "notnull": return `${field} != null`;
1288
+ case "in":
1289
+ case "notin": {
1290
+ const [prefix, suffix] = shouldNegate$2(operatorTL) ? ["!(", ")"] : ["", ""];
1291
+ const valueAsArray = toArray(value);
1292
+ return `${prefix}${field} in [${valueAsArray.map((val) => valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `"${escapeDoubleQuotes(val, escapeQuotes)}"`).join(", ")}]${suffix}`;
1293
+ }
1294
+ case "between":
1295
+ case "notbetween": {
1296
+ const valueAsArray = toArray(value);
1297
+ if (valueAsArray.length >= 2 && !nullOrUndefinedOrEmpty(valueAsArray[0]) && !nullOrUndefinedOrEmpty(valueAsArray[1])) {
1298
+ const [first, second] = valueAsArray;
1299
+ const shouldParseNumbers = !(parseNumbers === false);
1300
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
1301
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
1302
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `"${escapeDoubleQuotes(first, escapeQuotes)}"` : firstNum;
1303
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `"${escapeDoubleQuotes(second, escapeQuotes)}"` : secondNum;
1304
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
1305
+ const tempNum = secondNum;
1306
+ secondValue = firstNum;
1307
+ firstValue = tempNum;
1308
+ }
1309
+ return operatorTL === "between" ? `(${field} >= ${firstValue} && ${field} <= ${secondValue})` : `(${field} < ${firstValue} || ${field} > ${secondValue})`;
1310
+ } else return "";
1311
+ }
1312
+ }
1313
+ return "";
1314
+ };
1315
+
1316
+ //#endregion
1317
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorMongoDBQuery.ts
1318
+ /**
1319
+ * Default fallback object used by {@link formatQuery} for "mongodb_query" format.
1320
+ *
1321
+ * @group Export
1322
+ */
1323
+ const mongoDbFallback = { $and: [{ $expr: true }] };
1324
+ /**
1325
+ * Rule group processor used by {@link formatQuery} for "mongodb_query" format.
1326
+ *
1327
+ * @group Export
1328
+ */
1329
+ const defaultRuleGroupProcessorMongoDBQuery = (ruleGroup, options, meta) => {
1330
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1331
+ const processRuleGroup = (rg, outermost) => {
1332
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? mongoDbFallback : false;
1333
+ const combinator = `$${lc(rg.combinator)}`;
1334
+ let hasChildRules = false;
1335
+ const expressions = rg.rules.map((rule) => {
1336
+ if (isRuleGroup(rule)) {
1337
+ const processedRuleGroup = processRuleGroup(rule);
1338
+ if (processedRuleGroup) {
1339
+ hasChildRules = true;
1340
+ return processedRuleGroup;
1341
+ }
1342
+ return false;
1343
+ }
1344
+ const [validationResult, fieldValidator] = validateRule(rule);
1345
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return false;
1346
+ const fieldData = getOption(fields, rule.field);
1347
+ return ruleProcessor(rule, {
1348
+ ...options,
1349
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1350
+ fieldData
1351
+ }, meta);
1352
+ }).filter(Boolean);
1353
+ return expressions.length > 0 ? expressions.length === 1 && !hasChildRules ? expressions[0] : { [combinator]: expressions } : mongoDbFallback;
1354
+ };
1355
+ return processRuleGroup(convertFromIC(ruleGroup), true);
1356
+ };
1357
+
1358
+ //#endregion
1359
+ //#region src/utils/formatQuery/defaultRuleProcessorMongoDBQuery.ts
1360
+ const processNumber$1 = (value, fallback, parseNumbers = false) => shouldRenderAsNumber(value, parseNumbers || typeof value === "bigint") ? Number(parseNumber(value, { parseNumbers: "strict" })) : fallback;
1361
+ /**
1362
+ * Default rule processor used by {@link formatQuery} for "mongodb_query" format.
1363
+ *
1364
+ * @group Export
1365
+ */
1366
+ const defaultRuleProcessorMongoDBQuery = (rule, options = {}) => {
1367
+ const { field, operator, value, valueSource } = rule;
1368
+ const { parseNumbers, preserveValueOrder, context } = options;
1369
+ const valueIsField = valueSource === "field";
1370
+ const { avoidFieldsAsKeys } = context ?? {};
1371
+ const matchEval = processMatchMode(rule);
1372
+ if (matchEval === false) return;
1373
+ else if (matchEval) {
1374
+ const { mode, threshold } = matchEval;
1375
+ const totalCount = { $size: { $ifNull: [`$${field}`, []] } };
1376
+ const subQueryNoAggCtx = defaultRuleGroupProcessorMongoDBQuery(transformQuery(value, { ruleProcessor: (r) => ({
1377
+ ...r,
1378
+ field: r.field ? `${field}.${r.field}` : field
1379
+ }) }), {
1380
+ ...options,
1381
+ ruleProcessor: defaultRuleProcessorMongoDBQuery,
1382
+ context: {
1383
+ ...options.context,
1384
+ avoidFieldsAsKeys: false
1385
+ }
1386
+ });
1387
+ const subQueryWithAggCtx = defaultRuleGroupProcessorMongoDBQuery(transformQuery(value, { ruleProcessor: (r) => ({
1388
+ ...r,
1389
+ field: r.field ? `$item.${r.field}` : "$item"
1390
+ }) }), {
1391
+ ...options,
1392
+ ruleProcessor: defaultRuleProcessorMongoDBQuery,
1393
+ context: {
1394
+ ...options.context,
1395
+ avoidFieldsAsKeys: true
1396
+ }
1397
+ });
1398
+ const filteredCount = { $size: { $ifNull: [{ $filter: {
1399
+ input: `$${field}`,
1400
+ as: "item",
1401
+ cond: { $and: [subQueryWithAggCtx] }
1402
+ } }, []] } };
1403
+ switch (mode) {
1404
+ case "all": return { $expr: { $eq: [filteredCount, totalCount] } };
1405
+ case "none": return { $nor: [subQueryNoAggCtx] };
1406
+ case "some": return subQueryNoAggCtx;
1407
+ case "atleast":
1408
+ case "atmost":
1409
+ case "exactly": {
1410
+ const op = mode === "atleast" ? mongoOperators[">="] : mode === "atmost" ? mongoOperators["<="] : mongoOperators["="];
1411
+ if (threshold > 0 && threshold < 1) return { $expr: { [op]: [filteredCount, { $multiply: [totalCount, threshold] }] } };
1412
+ return { $expr: { [op]: [filteredCount, threshold] } };
1413
+ }
1414
+ }
1415
+ }
1416
+ if (operator === "=" && !valueIsField) return avoidFieldsAsKeys ? { $eq: [`$${field}`, processNumber$1(value, value, parseNumbers)] } : { [field]: processNumber$1(value, value, parseNumbers) };
1417
+ const operatorLC = lc(operator);
1418
+ switch (operatorLC) {
1419
+ case "<":
1420
+ case "<=":
1421
+ case "=":
1422
+ case "!=":
1423
+ case ">":
1424
+ case ">=": {
1425
+ const mongoOperator = mongoOperators[operatorLC];
1426
+ return valueIsField ? { [mongoOperator]: [`$${field}`, `$${value}`] } : avoidFieldsAsKeys ? { $and: [{ $ne: [`$${field}`, null] }, { [mongoOperator]: [`$${field}`, processNumber$1(value, value, parseNumbers)] }] } : { [field]: { [mongoOperator]: processNumber$1(value, value, parseNumbers) } };
1427
+ }
1428
+ case "contains": return valueIsField ? { $where: `this.${field}.includes(this.${value})` } : avoidFieldsAsKeys ? { $regexMatch: {
1429
+ input: `$${field}`,
1430
+ regex: value
1431
+ } } : { [field]: { $regex: value } };
1432
+ case "beginswith": return valueIsField ? { $where: `this.${field}.startsWith(this.${value})` } : avoidFieldsAsKeys ? { $regexMatch: {
1433
+ input: `$${field}`,
1434
+ regex: `^${value}`
1435
+ } } : { [field]: { $regex: `^${value}` } };
1436
+ case "endswith": return valueIsField ? { $where: `this.${field}.endsWith(this.${value})` } : avoidFieldsAsKeys ? { $regexMatch: {
1437
+ input: `$${field}`,
1438
+ regex: `${value}$`
1439
+ } } : { [field]: { $regex: `${value}$` } };
1440
+ case "doesnotcontain": return valueIsField ? { $where: `!this.${field}.includes(this.${value})` } : avoidFieldsAsKeys ? { $not: { $regexMatch: {
1441
+ input: `$${field}`,
1442
+ regex: value
1443
+ } } } : { [field]: { $not: { $regex: value } } };
1444
+ case "doesnotbeginwith": return valueIsField ? { $where: `!this.${field}.startsWith(this.${value})` } : avoidFieldsAsKeys ? { $not: { $regexMatch: {
1445
+ input: `$${field}`,
1446
+ regex: `^${value}`
1447
+ } } } : { [field]: { $not: { $regex: `^${value}` } } };
1448
+ case "doesnotendwith": return valueIsField ? { $where: `!this.${field}.endsWith(this.${value})` } : avoidFieldsAsKeys ? { $not: { $regexMatch: {
1449
+ input: `$${field}`,
1450
+ regex: `${value}$`
1451
+ } } } : { [field]: { $not: { $regex: `${value}$` } } };
1452
+ case "null": return avoidFieldsAsKeys ? { $eq: [`$${field}`, null] } : { [field]: null };
1453
+ case "notnull": return avoidFieldsAsKeys ? { $ne: [`$${field}`, null] } : { [field]: { $ne: null } };
1454
+ case "in":
1455
+ case "notin": {
1456
+ const valueAsArray = toArray(value);
1457
+ 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)) } };
1458
+ }
1459
+ case "between":
1460
+ case "notbetween": {
1461
+ const valueAsArray = toArray(value);
1462
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
1463
+ const [first, second] = valueAsArray;
1464
+ const firstNum = processNumber$1(first, NaN, true);
1465
+ const secondNum = processNumber$1(second, NaN, true);
1466
+ let firstValue = valueIsField ? first : Number.isNaN(firstNum) ? first : firstNum;
1467
+ let secondValue = valueIsField ? second : Number.isNaN(secondNum) ? second : secondNum;
1468
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
1469
+ const tempNum = secondNum;
1470
+ secondValue = firstNum;
1471
+ firstValue = tempNum;
1472
+ }
1473
+ if (operatorLC === "between") return valueIsField ? {
1474
+ $gte: [`$${field}`, `$${firstValue}`],
1475
+ $lte: [`$${field}`, `$${secondValue}`]
1476
+ } : avoidFieldsAsKeys ? { $and: [{ $gte: [`$${field}`, firstValue] }, { $lte: [`$${field}`, secondValue] }] } : { [field]: {
1477
+ $gte: firstValue,
1478
+ $lte: secondValue
1479
+ } };
1480
+ 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 } }] };
1481
+ } else return "";
1482
+ }
1483
+ }
1484
+ return "";
1485
+ };
1486
+
1487
+ //#endregion
1488
+ //#region src/utils/formatQuery/defaultRuleProcessorMongoDB.ts
1489
+ /**
1490
+ * Default rule processor used by {@link formatQuery} for "mongodb" format.
1491
+ *
1492
+ * Note that the "mongodb" format is deprecated in favor of the "mongodb_query" format.
1493
+ *
1494
+ * @group Export
1495
+ */
1496
+ const defaultRuleProcessorMongoDB = (rule, options) => {
1497
+ const queryObj = defaultRuleProcessorMongoDBQuery(rule, options);
1498
+ return queryObj ? JSON.stringify(queryObj) : "";
1499
+ };
1500
+
1501
+ //#endregion
1502
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSpEL.ts
1503
+ /**
1504
+ * Default rule processor used by {@link formatQuery} for "spel" format.
1505
+ *
1506
+ * @group Export
1507
+ */
1508
+ const defaultRuleGroupProcessorSpEL = (ruleGroup, options) => {
1509
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1510
+ const processRuleGroup = (rg, outermost) => {
1511
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1512
+ const expression = rg.rules.map((rule) => {
1513
+ if (typeof rule === "string") return rule;
1514
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1515
+ const [validationResult, fieldValidator] = validateRule(rule);
1516
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1517
+ const fieldData = getOption(fields, rule.field);
1518
+ return ruleProcessor(rule, {
1519
+ ...options,
1520
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1521
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1522
+ fieldData
1523
+ });
1524
+ }).filter(Boolean).join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ");
1525
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "!" : ""}(`, ")"] : ["", ""];
1526
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1527
+ };
1528
+ return processRuleGroup(ruleGroup, true);
1529
+ };
1530
+
1531
+ //#endregion
1532
+ //#region src/utils/formatQuery/defaultRuleProcessorSpEL.ts
1533
+ const shouldNegate$1 = (op) => op.startsWith("not") || op.startsWith("doesnot");
1534
+ const wrapInNegation = (clause, negate$1) => negate$1 ? `!(${clause})` : clause;
1535
+ const escapeSingleQuotes = (v, escapeQuotes) => typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`'`, `\\'`);
1536
+ /**
1537
+ * Default rule processor used by {@link formatQuery} for "spel" format.
1538
+ *
1539
+ * @group Export
1540
+ */
1541
+ const defaultRuleProcessorSpEL = (rule, opts = {}) => {
1542
+ const { field, operator, value, valueSource } = rule;
1543
+ const { escapeQuotes, parseNumbers, preserveValueOrder } = opts;
1544
+ const valueIsField = valueSource === "field";
1545
+ const operatorTL = lc(operator === "=" ? "==" : operator);
1546
+ const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
1547
+ const matchEval = processMatchMode(rule);
1548
+ if (matchEval === false) return "";
1549
+ else if (matchEval) {
1550
+ const { mode, threshold } = matchEval;
1551
+ const nestedArrayFilter = defaultRuleGroupProcessorSpEL(transformQuery(rule.value, { ruleProcessor: (r) => ({
1552
+ ...r,
1553
+ field: r.field || "#this"
1554
+ }) }), opts);
1555
+ const totalCount = `${field}.size()`;
1556
+ const filteredCount = `${field}.?[${nestedArrayFilter}].size()`;
1557
+ switch (mode) {
1558
+ case "all": return `${filteredCount} == ${totalCount}`;
1559
+ case "none": return `${filteredCount} == 0`;
1560
+ case "some": return `${filteredCount} >= 1`;
1561
+ case "atleast":
1562
+ case "atmost":
1563
+ case "exactly": {
1564
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "==";
1565
+ if (threshold > 0 && threshold < 1) return `${filteredCount} ${op} (${totalCount} * ${threshold})`;
1566
+ return `${filteredCount} ${op} ${threshold}`;
1567
+ }
1568
+ }
1569
+ }
1570
+ switch (operatorTL) {
1571
+ case "<":
1572
+ case "<=":
1573
+ case "==":
1574
+ case "!=":
1575
+ case ">":
1576
+ case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`;
1577
+ case "contains":
1578
+ case "doesnotcontain": return wrapInNegation(`${field} matches ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
1579
+ case "beginswith":
1580
+ case "doesnotbeginwith": {
1581
+ const valueTL = valueIsField ? `'^'.concat(${trimIfString(value)})` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes(value, escapeQuotes)}'`;
1582
+ return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate$1(operatorTL));
1583
+ }
1584
+ case "endswith":
1585
+ case "doesnotendwith": {
1586
+ const valueTL = valueIsField ? `${trimIfString(value)}.concat('$')` : `'${escapeSingleQuotes(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`;
1587
+ return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate$1(operatorTL));
1588
+ }
1589
+ case "null": return `${field} == null`;
1590
+ case "notnull": return `${field} != null`;
1591
+ case "in":
1592
+ case "notin": {
1593
+ const negate$1 = shouldNegate$1(operatorTL) ? "!" : "";
1594
+ const valueAsArray = toArray(value);
1595
+ return valueAsArray.length > 0 ? `${negate$1}(${valueAsArray.map((val) => `${field} == ${valueIsField || shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : `'${escapeSingleQuotes(val, escapeQuotes)}'`}`).join(" or ")})` : "";
1596
+ }
1597
+ case "between":
1598
+ case "notbetween": {
1599
+ const valueAsArray = toArray(value);
1600
+ if (valueAsArray.length >= 2 && !nullOrUndefinedOrEmpty(valueAsArray[0]) && !nullOrUndefinedOrEmpty(valueAsArray[1])) {
1601
+ const [first, second] = valueAsArray;
1602
+ const shouldParseNumbers = !(parseNumbers === false);
1603
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
1604
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
1605
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : `'${escapeSingleQuotes(first, escapeQuotes)}'` : firstNum;
1606
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : `'${escapeSingleQuotes(second, escapeQuotes)}'` : secondNum;
1607
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
1608
+ const tempNum = secondNum;
1609
+ secondValue = firstNum;
1610
+ firstValue = tempNum;
1611
+ }
1612
+ return operatorTL === "between" ? `(${field} >= ${firstValue} and ${field} <= ${secondValue})` : `(${field} < ${firstValue} or ${field} > ${secondValue})`;
1613
+ } else return "";
1614
+ }
1615
+ }
1616
+ return "";
1617
+ };
1618
+
1619
+ //#endregion
1620
+ //#region src/utils/formatQuery/defaultValueProcessorByRule.ts
1621
+ const escapeStringValueQuotes$1 = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : v;
1622
+ /**
1623
+ * Default value processor used by {@link formatQuery} for "sql" format.
1624
+ *
1625
+ * @group Export
1626
+ */
1627
+ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQuotes, parseNumbers, preserveValueOrder, quoteFieldNamesWith, quoteValuesWith, concatOperator = "||", fieldIdentifierSeparator, wrapValueWith = ["", ""], translations } = {}) => {
1628
+ const valueIsField = valueSource === "field";
1629
+ const operatorLowerCase = lc(operator);
1630
+ const quoteChar = quoteValuesWith || "'";
1631
+ const quoteValue = (v) => `${wrapValueWith[0]}${quoteChar}${v}${quoteChar}${wrapValueWith[1]}`;
1632
+ const escapeValue = (v) => escapeStringValueQuotes$1(v, quoteChar, escapeQuotes);
1633
+ const wrapAndEscape = (v) => quoteValue(escapeValue(v));
1634
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
1635
+ quoteFieldNamesWith,
1636
+ fieldIdentifierSeparator
1637
+ });
1638
+ const concat = (...values) => concatOperator.toUpperCase() === "CONCAT" ? `CONCAT(${values.join(", ")})` : values.join(` ${concatOperator} `);
1639
+ switch (operatorLowerCase) {
1640
+ case "null":
1641
+ case "notnull": return "";
1642
+ case "in":
1643
+ case "notin": {
1644
+ const valueAsArray = toArray(value);
1645
+ if (valueAsArray.length > 0) return `(${valueAsArray.map((v) => valueIsField ? wrapFieldName(v) : shouldRenderAsNumber(v, parseNumbers) ? `${trimIfString(v)}` : `${wrapAndEscape(v)}`).join(", ")})`;
1646
+ return "";
1647
+ }
1648
+ case "between":
1649
+ case "notbetween": {
1650
+ const valueAsArray = toArray(value, { retainEmptyStrings: true });
1651
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return "";
1652
+ const [first, second] = valueAsArray;
1653
+ const firstNum = shouldRenderAsNumber(first, parseNumbers) ? parseNumber(first, { parseNumbers: "strict" }) : NaN;
1654
+ const secondNum = shouldRenderAsNumber(second, parseNumbers) ? parseNumber(second, { parseNumbers: "strict" }) : NaN;
1655
+ const firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : first : firstNum;
1656
+ const secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : second : secondNum;
1657
+ const valsOneAndTwoOnly = [firstValue, secondValue];
1658
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
1659
+ valsOneAndTwoOnly[0] = secondNum;
1660
+ valsOneAndTwoOnly[1] = firstNum;
1661
+ }
1662
+ 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"} `);
1663
+ }
1664
+ case "contains":
1665
+ case "doesnotcontain": return valueIsField ? concat(quoteValue("%"), wrapFieldName(value), quoteValue("%")) : quoteValue(`%${escapeValue(value)}%`);
1666
+ case "beginswith":
1667
+ case "doesnotbeginwith": return valueIsField ? concat(wrapFieldName(value), quoteValue("%")) : quoteValue(`${escapeValue(value)}%`);
1668
+ case "endswith":
1669
+ case "doesnotendwith": return valueIsField ? concat(quoteValue("%"), wrapFieldName(value)) : quoteValue(`%${escapeValue(value)}`);
1670
+ }
1671
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
1672
+ return valueIsField ? wrapFieldName(value) : shouldRenderAsNumber(value, parseNumbers) ? `${trimIfString(value)}` : `${wrapAndEscape(value)}`;
1673
+ };
1674
+
1675
+ //#endregion
1676
+ //#region src/utils/formatQuery/defaultRuleProcessorDrizzle.ts
1677
+ /**
1678
+ * Default rule processor used by {@link formatQuery} for the "drizzle" format.
1679
+ *
1680
+ * @group Export
1681
+ */
1682
+ const defaultRuleProcessorDrizzle = (rule, _options) => {
1683
+ const opts = _options ?? ( /* istanbul ignore next */ {});
1684
+ // istanbul ignore next
1685
+ const { parseNumbers, preserveValueOrder, context = {} } = opts;
1686
+ const { columns, drizzleOperators, useRawFields } = context;
1687
+ if (!columns || !drizzleOperators) return;
1688
+ const { between, eq, gt, gte, inArray, isNotNull, isNull, like, lt, lte, ne, notBetween, notInArray, notLike, sql } = drizzleOperators;
1689
+ const { field, operator, value, valueSource } = rule;
1690
+ const column = useRawFields && /[a-z][a-z0-9]*/i.test(field) ? sql.raw(field) : columns[field];
1691
+ const operatorLC = lc(operator);
1692
+ const valueIsField = valueSource === "field";
1693
+ const asFieldOrValue = (v) => valueIsField ? columns[v] : v;
1694
+ if (!column) return;
1695
+ const matchEval = processMatchMode(rule);
1696
+ if (matchEval === false) return;
1697
+ else if (matchEval) {
1698
+ if (opts.preset !== "postgresql") return;
1699
+ const { mode, threshold } = matchEval;
1700
+ const arrayElementAlias = "elem_alias";
1701
+ const sqlQuery = transformQuery(rule.value, { ruleProcessor: (r) => ({
1702
+ ...r,
1703
+ field: arrayElementAlias
1704
+ }) });
1705
+ const nestedArrayFilter = defaultRuleGroupProcessorDrizzle(sqlQuery, {
1706
+ ...opts,
1707
+ context: {
1708
+ ...opts.context,
1709
+ useRawFields: true
1710
+ }
1711
+ });
1712
+ switch (mode) {
1713
+ case "all": return sql`(select count(*) from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)}) = array_length(${column}, 1)`;
1714
+ case "none": return sql`not exists (select 1 from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)})`;
1715
+ case "some": return sql`exists (select 1 from unnest(${column}) as ${sql.raw(arrayElementAlias)} where ${nestedArrayFilter({}, drizzleOperators)})`;
1716
+ case "atleast":
1717
+ case "atmost":
1718
+ case "exactly": {
1719
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
1720
+ 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}`)}`;
1721
+ }
1722
+ }
1723
+ }
1724
+ switch (operatorLC) {
1725
+ case "=": return eq(column, asFieldOrValue(value));
1726
+ case "!=": return ne(column, asFieldOrValue(value));
1727
+ case ">": return gt(column, asFieldOrValue(value));
1728
+ case "<": return lt(column, asFieldOrValue(value));
1729
+ case ">=": return gte(column, asFieldOrValue(value));
1730
+ case "<=": return lte(column, asFieldOrValue(value));
1731
+ case "beginswith":
1732
+ case "doesnotbeginwith": return (operatorLC === "doesnotbeginwith" ? notLike : like)(column, valueIsField ? sql`${asFieldOrValue(value)} || '%'` : `${value}%`);
1733
+ case "contains":
1734
+ case "doesnotcontain": return (operatorLC === "doesnotcontain" ? notLike : like)(column, valueIsField ? sql`'%' || ${asFieldOrValue(value)} || '%'` : `%${value}%`);
1735
+ case "endswith":
1736
+ case "doesnotendwith": return (operatorLC === "doesnotendwith" ? notLike : like)(column, valueIsField ? sql`'%' || ${asFieldOrValue(value)}` : `%${value}`);
1737
+ case "null": return isNull(column);
1738
+ case "notnull": return isNotNull(column);
1739
+ case "in":
1740
+ case "notin": {
1741
+ const valueAsArray = toArray(value).map((v) => asFieldOrValue(v));
1742
+ return operatorLC === "notin" ? notInArray(column, valueAsArray) : inArray(column, valueAsArray);
1743
+ }
1744
+ case "between":
1745
+ case "notbetween": {
1746
+ const valueAsArray = toArray(value);
1747
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
1748
+ let [first, second] = valueAsArray;
1749
+ const shouldParseNumbers = !(parseNumbers === false);
1750
+ if (!valueIsField && shouldRenderAsNumber(first, shouldParseNumbers) && shouldRenderAsNumber(second, shouldParseNumbers)) {
1751
+ const firstNum = parseNumber(first, { parseNumbers: shouldParseNumbers });
1752
+ const secondNum = parseNumber(second, { parseNumbers: shouldParseNumbers });
1753
+ if (!preserveValueOrder && secondNum < firstNum) {
1754
+ const tempNum = secondNum;
1755
+ second = firstNum;
1756
+ first = tempNum;
1757
+ } else {
1758
+ first = firstNum;
1759
+ second = secondNum;
1760
+ }
1761
+ } else if (valueIsField) {
1762
+ first = asFieldOrValue(first);
1763
+ second = asFieldOrValue(second);
1764
+ }
1765
+ return operatorLC === "notbetween" ? notBetween(column, first, second) : between(column, first, second);
1766
+ }
1767
+ return;
1768
+ }
1769
+ default: return;
1770
+ }
1771
+ };
1772
+
1773
+ //#endregion
1774
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorDrizzle.ts
1775
+ /**
1776
+ * Default rule group processor used by {@link formatQuery} for the "drizzle" format. The returned
1777
+ * function can be assigned to the `where` property in the Drizzle relational queries API.
1778
+ *
1779
+ * @example
1780
+ * const where = formatQuery(query, 'drizzle');
1781
+ * const results = db.query.users.findMany({ where });
1782
+ *
1783
+ * @returns Function that takes a Drizzle table config and an object of Drizzle operators.
1784
+ *
1785
+ * @group Export
1786
+ */
1787
+ const defaultRuleGroupProcessorDrizzle = (ruleGroup, options, _meta) => (columns, drizzleOperators) => {
1788
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, validateRule, validationMap } = options;
1789
+ if (!columns || !drizzleOperators) return;
1790
+ const { and, not, or } = drizzleOperators;
1791
+ const query = isRuleGroupType(ruleGroup) ? ruleGroup : convertFromIC(ruleGroup);
1792
+ const ruleProcessor = defaultRuleProcessorDrizzle;
1793
+ const processRuleGroup = (rg, _outermost) => {
1794
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return;
1795
+ const processedRules = rg.rules.map((rule) => {
1796
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1797
+ const [validationResult, fieldValidator] = validateRule(rule);
1798
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
1799
+ const fieldData = getOption(fields, rule.field);
1800
+ return ruleProcessor(rule, {
1801
+ ...options,
1802
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1803
+ fieldData,
1804
+ context: {
1805
+ ...options.context,
1806
+ columns,
1807
+ drizzleOperators
1808
+ }
1809
+ });
1810
+ }).filter(Boolean);
1811
+ if (processedRules.length === 0) return;
1812
+ const ruleGroupSQL = rg.combinator === "or" ? or(...processedRules) : and(...processedRules);
1813
+ return rg.not ? not(ruleGroupSQL) : ruleGroupSQL;
1814
+ };
1815
+ return processRuleGroup(query, true);
1816
+ };
1817
+
1818
+ //#endregion
1819
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorElasticSearch.ts
1820
+ /**
1821
+ * Rule group processor used by {@link formatQuery} for "elasticsearch" format.
1822
+ *
1823
+ * @group Export
1824
+ */
1825
+ const defaultRuleGroupProcessorElasticSearch = (ruleGroup, options) => {
1826
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1827
+ const query = convertFromIC(ruleGroup);
1828
+ const processRuleGroup = (rg) => {
1829
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return false;
1830
+ const processedRules = rg.rules.map((rule) => {
1831
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1832
+ const [validationResult, fieldValidator] = validateRule(rule);
1833
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return false;
1834
+ const fieldData = getOption(fields, rule.field);
1835
+ return ruleProcessor(rule, {
1836
+ ...options,
1837
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1838
+ fieldData
1839
+ });
1840
+ }).filter(Boolean);
1841
+ if (processedRules.length === 0) return false;
1842
+ return { bool: rg.not ? { must_not: /^or$/i.test(rg.combinator) ? { bool: { should: processedRules } } : processedRules } : { [/^or$/i.test(rg.combinator) ? "should" : "must"]: processedRules } };
1843
+ };
1844
+ const processedRuleGroup = processRuleGroup(query);
1845
+ return processedRuleGroup === false ? {} : processedRuleGroup;
1846
+ };
1847
+
1848
+ //#endregion
1849
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorJSONata.ts
1850
+ /**
1851
+ * Rule group processor used by {@link formatQuery} for "jsonata" format.
1852
+ *
1853
+ * @group Export
1854
+ */
1855
+ const defaultRuleGroupProcessorJSONata = (ruleGroup, options) => {
1856
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1857
+ const processRuleGroup = (rg, outermost) => {
1858
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1859
+ const expression = rg.rules.map((rule) => {
1860
+ if (typeof rule === "string") return rule;
1861
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1862
+ const [validationResult, fieldValidator] = validateRule(rule);
1863
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1864
+ const fieldData = getOption(fields, rule.field);
1865
+ return ruleProcessor(rule, {
1866
+ ...options,
1867
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1868
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1869
+ fieldData
1870
+ });
1871
+ }).filter(Boolean).join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ");
1872
+ const [prefix, suffix] = rg.not || !outermost ? [`${rg.not ? "$not" : ""}(`, ")"] : ["", ""];
1873
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1874
+ };
1875
+ return processRuleGroup(ruleGroup, true);
1876
+ };
1877
+
1878
+ //#endregion
1879
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorJsonLogic.ts
1880
+ /**
1881
+ * Rule group processor used by {@link formatQuery} for "jsonlogic" format.
1882
+ *
1883
+ * @group Export
1884
+ */
1885
+ const defaultRuleGroupProcessorJsonLogic = (ruleGroup, options) => {
1886
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1887
+ const query = convertFromIC(ruleGroup);
1888
+ const processRuleGroup = (rg, _outermost) => {
1889
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return false;
1890
+ const processedRules = rg.rules.map((rule) => {
1891
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1892
+ const [validationResult, fieldValidator] = validateRule(rule);
1893
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return false;
1894
+ const fieldData = getOption(fields, rule.field);
1895
+ return ruleProcessor(rule, {
1896
+ ...options,
1897
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1898
+ fieldData
1899
+ });
1900
+ }).filter(Boolean);
1901
+ if (processedRules.length === 0) return false;
1902
+ const jsonRuleGroup = { [rg.combinator]: processedRules };
1903
+ return rg.not ? { "!": jsonRuleGroup } : jsonRuleGroup;
1904
+ };
1905
+ return processRuleGroup(query, true);
1906
+ };
1907
+
1908
+ //#endregion
1909
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorLDAP.ts
1910
+ /**
1911
+ * Rule group processor used by {@link formatQuery} for "ldap" format.
1912
+ *
1913
+ * @group Export
1914
+ */
1915
+ const defaultRuleGroupProcessorLDAP = (ruleGroup, options) => {
1916
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1917
+ const query = convertFromIC(ruleGroup);
1918
+ const processRuleGroup = (rg, outermost) => {
1919
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1920
+ const rules = rg.rules.map((rule) => {
1921
+ if (isRuleGroup(rule)) return processRuleGroup(rule);
1922
+ const [validationResult, fieldValidator] = validateRule(rule);
1923
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1924
+ const fieldData = getOption(fields, rule.field);
1925
+ return ruleProcessor(rule, {
1926
+ ...options,
1927
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1928
+ escapeQuotes: (rule.valueSource ?? "value") === "value",
1929
+ fieldData
1930
+ });
1931
+ }).filter(Boolean);
1932
+ const expression = rules.join("");
1933
+ const [notPrefix, notSuffix] = rg.not ? ["(!", ")"] : ["", ""];
1934
+ const [prefix, suffix] = rules.length > 1 ? [`${notPrefix}(${rg.combinator === "or" ? "|" : "&"}`, `)${notSuffix}`] : [notPrefix, notSuffix];
1935
+ return expression ? `${prefix}${expression}${suffix}` : fallbackExpression;
1936
+ };
1937
+ return processRuleGroup(query, true);
1938
+ };
1939
+
1940
+ //#endregion
1941
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorMongoDB.ts
1942
+ const isBracketed = (str) => str.startsWith("{") && str.endsWith("}");
1943
+ /**
1944
+ * Rule group processor used by {@link formatQuery} for "mongodb" format.
1945
+ *
1946
+ * Note that the "mongodb" format is deprecated in favor of the "mongodb_query" format.
1947
+ *
1948
+ * @group Export
1949
+ */
1950
+ const defaultRuleGroupProcessorMongoDB = (ruleGroup, options, meta) => {
1951
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
1952
+ const processRuleGroup = (rg, outermost) => {
1953
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? fallbackExpression : "";
1954
+ const combinator = `"$${lc(rg.combinator)}"`;
1955
+ let hasChildRules = false;
1956
+ const expressions = rg.rules.map((rule) => {
1957
+ if (isRuleGroup(rule)) {
1958
+ const processedRuleGroup = processRuleGroup(rule);
1959
+ if (processedRuleGroup) {
1960
+ hasChildRules = true;
1961
+ return isBracketed(processedRuleGroup) ? processedRuleGroup : `{${processedRuleGroup}}`;
1962
+ }
1963
+ return "";
1964
+ }
1965
+ const [validationResult, fieldValidator] = validateRule(rule);
1966
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1967
+ const fieldData = getOption(fields, rule.field);
1968
+ return ruleProcessor(rule, {
1969
+ ...options,
1970
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
1971
+ fieldData
1972
+ }, meta);
1973
+ }).filter(Boolean);
1974
+ return expressions.length > 0 ? expressions.length === 1 && !hasChildRules ? expressions[0] : `${combinator}:[${expressions.join(",")}]` : fallbackExpression;
1975
+ };
1976
+ const processedQuery = processRuleGroup(convertFromIC(ruleGroup), true);
1977
+ return isBracketed(processedQuery) ? processedQuery : `{${processedQuery}}`;
1978
+ };
1979
+
1980
+ //#endregion
1981
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorNL.ts
1982
+ /**
1983
+ * Rule group processor used by {@link formatQuery} for "natural_language" format.
1984
+ *
1985
+ * @group Export
1986
+ */
1987
+ const defaultRuleGroupProcessorNL = (ruleGroup, options) => {
1988
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, translations, validateRule, validationMap } = options;
1989
+ const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
1990
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
1991
+ const rg2 = isRuleGroupTypeIC(rg) && rg.rules.some((r) => typeof r === "string" && lc(r) === "xor") ? convertFromIC(rg) : rg;
1992
+ const processedRules = rg2.rules.map((rule) => {
1993
+ if (typeof rule === "string") return `, ${translations[rule] ?? rule} `;
1994
+ if (isRuleGroup(rule)) return processRuleGroup(rule, rg2.rules.length === 1 && !(rg2.not || /^xor$/i.test(rg2.combinator ?? "")));
1995
+ const [validationResult, fieldValidator] = validateRule(rule);
1996
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
1997
+ const escapeQuotes = (rule.valueSource ?? "value") === "value";
1998
+ const fieldData = getOption(fields, rule.field);
1999
+ return ruleProcessor(rule, {
2000
+ ...options,
2001
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
2002
+ escapeQuotes,
2003
+ fieldData
2004
+ });
2005
+ });
2006
+ if (processedRules.length === 0) return fallbackExpression;
2007
+ const isXOR = lc(rg2.combinator ?? "") === "xor";
2008
+ const combinator = isXOR ? rg2.combinator.slice(1) : rg2.combinator;
2009
+ const mustWrap = rg2.not || !outermostOrLonelyInGroup || isXOR && processedRules.length > 1;
2010
+ 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));
2011
+ const prefix = mustWrap ? `${prefixTL} (`.trim() : "";
2012
+ const suffix = mustWrap ? `) ${suffixTL}`.trim() : "";
2013
+ return `${prefix}${processedRules.filter(Boolean).join(isRuleGroupType(rg2) ? `, ${translations[combinator] ?? combinator} ` : "")}${suffix}`;
2014
+ };
2015
+ return processRuleGroup(ruleGroup, true);
2016
+ };
2017
+
2018
+ //#endregion
2019
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorParameterized.ts
2020
+ /**
2021
+ * Rule group processor used by {@link formatQuery} for "parameterized" and
2022
+ * "parameterized_named" formats.
2023
+ *
2024
+ * @group Export
2025
+ */
2026
+ const defaultRuleGroupProcessorParameterized = (ruleGroup, options) => {
2027
+ const { format, fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
2028
+ const parameterized = format === "parameterized";
2029
+ const params = [];
2030
+ const paramsNamed = {};
2031
+ const fieldParams = /* @__PURE__ */ new Map();
2032
+ const getNextNamedParam = (field) => {
2033
+ if (!fieldParams.has(field)) fieldParams.set(field, /* @__PURE__ */ new Set());
2034
+ const nextNamedParam = `${field}_${fieldParams.get(field).size + 1}`;
2035
+ fieldParams.get(field).add(nextNamedParam);
2036
+ return nextNamedParam;
2037
+ };
2038
+ const processRule = (rule) => {
2039
+ const [validationResult, fieldValidator] = validateRule(rule);
2040
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
2041
+ const fieldData = getOption(fields, rule.field);
2042
+ const fieldParamNames = Object.fromEntries([...fieldParams.entries()].map(([f, s]) => [f, [...s]]));
2043
+ const processedRule = ruleProcessor(rule, {
2044
+ ...options,
2045
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
2046
+ getNextNamedParam,
2047
+ fieldParamNames,
2048
+ fieldData
2049
+ }, { processedParams: params });
2050
+ if (!isPojo(processedRule)) return "";
2051
+ const { sql, params: customParams } = processedRule;
2052
+ if (typeof sql !== "string" || !sql) return "";
2053
+ // istanbul ignore else
2054
+ if (format === "parameterized" && Array.isArray(customParams)) params.push(...customParams);
2055
+ else if (format === "parameterized_named" && isPojo(customParams)) {
2056
+ Object.assign(paramsNamed, customParams);
2057
+ for (const p of Object.keys(customParams)) fieldParams.get(rule.field)?.add(p);
2058
+ }
2059
+ return sql;
2060
+ };
2061
+ const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
2062
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
2063
+ const processedRules = rg.rules.map((rule) => {
2064
+ if (typeof rule === "string") return rule;
2065
+ if (isRuleGroup(rule)) return processRuleGroup(rule, rg.rules.length === 1);
2066
+ return processRule(rule);
2067
+ }).filter(Boolean);
2068
+ if (processedRules.length === 0) return fallbackExpression;
2069
+ return `${rg.not ? "NOT " : ""}(${processedRules.join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ")})`;
2070
+ };
2071
+ if (parameterized) return {
2072
+ sql: processRuleGroup(ruleGroup, true),
2073
+ params
2074
+ };
2075
+ return {
2076
+ sql: processRuleGroup(ruleGroup, true),
2077
+ params: paramsNamed
2078
+ };
2079
+ };
2080
+
2081
+ //#endregion
2082
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorPrisma.ts
2083
+ /**
2084
+ * Default fallback object used by {@link formatQuery} for "prisma" format.
2085
+ *
2086
+ * @group Export
2087
+ */
2088
+ const prismaFallback = {};
2089
+ /**
2090
+ * Rule group processor used by {@link formatQuery} for "prisma" format.
2091
+ *
2092
+ * @group Export
2093
+ */
2094
+ const defaultRuleGroupProcessorPrisma = (ruleGroup, options) => {
2095
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
2096
+ const processRuleGroup = (rg, outermost) => {
2097
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermost ? prismaFallback : void 0;
2098
+ const combinator = rg.combinator.toUpperCase();
2099
+ let hasChildRules = false;
2100
+ const expressions = rg.rules.map((rule) => {
2101
+ if (isRuleGroup(rule)) {
2102
+ const processedRuleGroup = processRuleGroup(rule);
2103
+ if (processedRuleGroup) {
2104
+ hasChildRules = true;
2105
+ return processedRuleGroup;
2106
+ }
2107
+ return;
2108
+ }
2109
+ const [validationResult, fieldValidator] = validateRule(rule);
2110
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
2111
+ const fieldData = getOption(fields, rule.field);
2112
+ return ruleProcessor(rule, {
2113
+ ...options,
2114
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
2115
+ fieldData
2116
+ });
2117
+ }).filter(Boolean);
2118
+ return expressions.length > 0 ? expressions.length === 1 && !hasChildRules ? expressions[0] : { [combinator]: expressions } : prismaFallback;
2119
+ };
2120
+ const result = processRuleGroup(convertFromIC(ruleGroup), true);
2121
+ return ruleGroup.not ? { NOT: result } : result;
2122
+ };
2123
+
2124
+ //#endregion
2125
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSequelize.ts
2126
+ /**
2127
+ * Rule group processor used by {@link formatQuery} for "sequelize" format.
2128
+ *
2129
+ * @group Export
2130
+ */
2131
+ const defaultRuleGroupProcessorSequelize = (ruleGroup, options) => {
2132
+ // istanbul ignore next
2133
+ const { fields, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap, context = {} } = options;
2134
+ const { sequelizeOperators: Op } = context;
2135
+ if (!Op) return;
2136
+ const processRuleGroup = (rg, _outermost) => {
2137
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return;
2138
+ const combinator = rg.combinator.toUpperCase();
2139
+ let hasChildRules = false;
2140
+ const expressions = rg.rules.map((rule) => {
2141
+ if (isRuleGroup(rule)) {
2142
+ const processedRuleGroup = processRuleGroup(rule);
2143
+ if (processedRuleGroup) {
2144
+ hasChildRules = true;
2145
+ return processedRuleGroup;
2146
+ }
2147
+ return;
2148
+ }
2149
+ const [validationResult, fieldValidator] = validateRule(rule);
2150
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return;
2151
+ const fieldData = getOption(fields, rule.field);
2152
+ return ruleProcessor(rule, {
2153
+ ...options,
2154
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
2155
+ fieldData
2156
+ });
2157
+ }).filter(Boolean);
2158
+ if (expressions.length === 0) return;
2159
+ const result = expressions.length === 1 && !hasChildRules ? expressions[0] : { [lc(combinator) === "or" ? Op.or : Op.and]: expressions };
2160
+ return rg.not ? { [Op.not]: result } : result;
2161
+ };
2162
+ return processRuleGroup(convertFromIC(ruleGroup), true);
2163
+ };
2164
+
2165
+ //#endregion
2166
+ //#region src/utils/formatQuery/defaultRuleGroupProcessorSQL.ts
2167
+ /**
2168
+ * Default rule processor used by {@link formatQuery} for "sql" format.
2169
+ *
2170
+ * @group Export
2171
+ */
2172
+ const defaultRuleGroupProcessorSQL = (ruleGroup, options) => {
2173
+ const { fields, fallbackExpression, getParseNumberBoolean, placeholderFieldName, placeholderOperatorName, placeholderValueName, ruleProcessor, validateRule, validationMap } = options;
2174
+ const processRuleGroup = (rg, outermostOrLonelyInGroup) => {
2175
+ if (!isRuleOrGroupValid(rg, validationMap[rg.id ?? ""])) return outermostOrLonelyInGroup ? fallbackExpression : "";
2176
+ const processedRules = rg.rules.map((rule) => {
2177
+ if (typeof rule === "string") return rule;
2178
+ if (isRuleGroup(rule)) return processRuleGroup(rule, rg.rules.length === 1);
2179
+ const [validationResult, fieldValidator] = validateRule(rule);
2180
+ if (!isRuleOrGroupValid(rule, validationResult, fieldValidator) || rule.field === placeholderFieldName || rule.operator === placeholderOperatorName || placeholderValueName !== void 0 && rule.value === placeholderValueName) return "";
2181
+ const escapeQuotes = (rule.valueSource ?? "value") === "value";
2182
+ const fieldData = getOption(fields, rule.field);
2183
+ return ruleProcessor(rule, {
2184
+ ...options,
2185
+ parseNumbers: getParseNumberBoolean(fieldData?.inputType),
2186
+ escapeQuotes,
2187
+ fieldData
2188
+ });
2189
+ }).filter(Boolean);
2190
+ if (processedRules.length === 0) return fallbackExpression;
2191
+ return `${rg.not ? "NOT " : ""}(${processedRules.join(isRuleGroupType(rg) ? ` ${rg.combinator} ` : " ")})`;
2192
+ };
2193
+ return processRuleGroup(ruleGroup, true);
2194
+ };
2195
+
2196
+ //#endregion
2197
+ //#region src/utils/formatQuery/defaultRuleProcessorElasticSearch.ts
2198
+ const rangeOperatorMap = {
2199
+ "<": "lt",
2200
+ "<=": "lte",
2201
+ ">": "gt",
2202
+ ">=": "gte"
2203
+ };
2204
+ const negateIfNotOp$1 = (op, elasticSearchRule) => op.startsWith("not") || op.startsWith("doesnot") ? { bool: { must_not: elasticSearchRule } } : elasticSearchRule;
2205
+ const escapeSQ = (s) => s?.replace(/('|\\)/g, `\\$1`);
2206
+ const textFunctionMap = {
2207
+ beginswith: "startsWith",
2208
+ doesnotbeginwith: "startsWith",
2209
+ doesnotcontain: "contains",
2210
+ doesnotendwith: "endsWith",
2211
+ endswith: "endsWith"
2212
+ };
2213
+ const getTextScript = (f, o, v) => {
2214
+ const script = `doc['${f}'].value.${textFunctionMap[o] ?? o}(doc['${v}'].value)`;
2215
+ return o.startsWith("d") ? `!${script}` : script;
2216
+ };
2217
+ const valueRenderer = (v, parseNumbers) => typeof v === "boolean" ? v : shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
2218
+ /**
2219
+ * Default rule processor used by {@link formatQuery} for "elasticsearch" format.
2220
+ *
2221
+ * @group Export
2222
+ */
2223
+ const defaultRuleProcessorElasticSearch = (rule, options = {}) => {
2224
+ const { field, operator, value, valueSource } = rule;
2225
+ const { parseNumbers, preserveValueOrder } = options;
2226
+ const operatorLC = lc(operator);
2227
+ if (processMatchMode(rule)) return false;
2228
+ if (valueSource === "field") {
2229
+ if (toArray(value).some((v) => typeof v !== "string")) return false;
2230
+ const fieldForScript = escapeSQ(field);
2231
+ switch (operatorLC) {
2232
+ case "=":
2233
+ case "!=":
2234
+ case ">":
2235
+ case ">=":
2236
+ case "<":
2237
+ case "<=": {
2238
+ const operatorForScript = operatorLC === "=" ? "==" : operatorLC;
2239
+ const valueForScript = escapeSQ(value);
2240
+ return valueForScript ? { bool: { filter: { script: { script: `doc['${fieldForScript}'].value ${operatorForScript} doc['${valueForScript}'].value` } } } } : false;
2241
+ }
2242
+ case "in":
2243
+ case "notin": {
2244
+ const valueAsArray = toArray(value);
2245
+ if (valueAsArray.length > 0) {
2246
+ const arr = valueAsArray.map((v) => ({ bool: { filter: { script: { script: `doc['${fieldForScript}'].value == doc['${v}'].value` } } } }));
2247
+ return { bool: operatorLC === "in" ? { should: arr } : { must_not: arr } };
2248
+ }
2249
+ return false;
2250
+ }
2251
+ case "between":
2252
+ case "notbetween": {
2253
+ const valueAsArray = toArray(value);
2254
+ if (valueAsArray.length >= 2 && valueAsArray[0] && valueAsArray[1]) {
2255
+ const script = `doc['${fieldForScript}'].value >= doc['${valueAsArray[0]}'].value && doc['${fieldForScript}'].value <= doc['${valueAsArray[1]}'].value`;
2256
+ return { bool: { filter: { script: { script: operatorLC === "notbetween" ? `!(${script})` : script } } } };
2257
+ }
2258
+ return false;
2259
+ }
2260
+ case "contains":
2261
+ case "doesnotcontain":
2262
+ case "beginswith":
2263
+ case "doesnotbeginwith":
2264
+ case "endswith":
2265
+ case "doesnotendwith": {
2266
+ const valueForScript = escapeSQ(value);
2267
+ if (!valueForScript) return false;
2268
+ return { bool: { filter: { script: { script: getTextScript(fieldForScript, operatorLC, valueForScript) } } } };
2269
+ }
2270
+ }
2271
+ }
2272
+ switch (operatorLC) {
2273
+ case "<":
2274
+ case "<=":
2275
+ case ">":
2276
+ case ">=": return { range: { [field]: { [rangeOperatorMap[operatorLC]]: valueRenderer(value, parseNumbers) } } };
2277
+ case "=": return { term: { [field]: valueRenderer(value, parseNumbers) } };
2278
+ case "!=": return { bool: { must_not: { term: { [field]: valueRenderer(value, parseNumbers) } } } };
2279
+ case "null": return { bool: { must_not: { exists: { field } } } };
2280
+ case "notnull": return { exists: { field } };
2281
+ case "in":
2282
+ case "notin": {
2283
+ const valueAsArray = toArray(value).map((v) => valueRenderer(v, parseNumbers));
2284
+ if (valueAsArray.length > 0) {
2285
+ const arr = valueAsArray.map((v) => ({ term: { [field]: valueRenderer(v, parseNumbers) } }));
2286
+ return { bool: operatorLC === "in" ? { should: arr } : { must_not: arr } };
2287
+ }
2288
+ return false;
2289
+ }
2290
+ case "between":
2291
+ case "notbetween": {
2292
+ const valueAsArray = toArray(value);
2293
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
2294
+ let [first, second] = valueAsArray;
2295
+ const shouldParseNumbers = !(parseNumbers === false);
2296
+ if (shouldRenderAsNumber(first, shouldParseNumbers) && shouldRenderAsNumber(second, shouldParseNumbers)) {
2297
+ const firstNum = parseNumber(first, { parseNumbers: shouldParseNumbers });
2298
+ const secondNum = parseNumber(second, { parseNumbers: shouldParseNumbers });
2299
+ if (!preserveValueOrder && secondNum < firstNum) {
2300
+ const tempNum = secondNum;
2301
+ second = firstNum;
2302
+ first = tempNum;
2303
+ } else {
2304
+ first = firstNum;
2305
+ second = secondNum;
2306
+ }
2307
+ }
2308
+ return negateIfNotOp$1(operatorLC, { range: { [field]: {
2309
+ gte: first,
2310
+ lte: second
2311
+ } } });
2312
+ }
2313
+ return false;
2314
+ }
2315
+ case "contains":
2316
+ case "doesnotcontain": return negateIfNotOp$1(operatorLC, { regexp: { [field]: { value: `.*${value}.*` } } });
2317
+ case "beginswith":
2318
+ case "doesnotbeginwith": return negateIfNotOp$1(operatorLC, { regexp: { [field]: { value: `${value}.*` } } });
2319
+ case "endswith":
2320
+ case "doesnotendwith": return negateIfNotOp$1(operatorLC, { regexp: { [field]: { value: `.*${value}` } } });
2321
+ }
2322
+ return false;
2323
+ };
2324
+
2325
+ //#endregion
2326
+ //#region src/utils/formatQuery/defaultRuleProcessorJSONata.ts
2327
+ const shouldNegate = (op) => op.startsWith("not") || op.startsWith("doesnot");
2328
+ const quote = (v, escapeQuotes) => `"${typeof v !== "string" || !escapeQuotes ? `${v}` : v.replaceAll(`"`, `\\"`)}"`;
2329
+ const negate = (clause, negate$1) => negate$1 ? `$not(${clause})` : clause;
2330
+ const escapeStringRegex = (s) => `${s}`.replaceAll(/[/$()*+.?[\\\]^{|}]/g, String.raw`\$&`).replaceAll("-", String.raw`\x2d`);
2331
+ /**
2332
+ * Default rule processor used by {@link formatQuery} for "jsonata" format.
2333
+ *
2334
+ * @group Export
2335
+ */
2336
+ const defaultRuleProcessorJSONata = (rule, options = {}) => {
2337
+ const { field, operator, value, valueSource } = rule;
2338
+ const { escapeQuotes, parseNumbers, preserveValueOrder, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "" } = options;
2339
+ const valueIsField = valueSource === "field";
2340
+ const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
2341
+ const qfn = (f) => getQuotedFieldName(f, {
2342
+ quoteFieldNamesWith,
2343
+ fieldIdentifierSeparator
2344
+ });
2345
+ const matchEval = processMatchMode(rule);
2346
+ if (matchEval === false) return;
2347
+ else if (matchEval) {
2348
+ const { mode, threshold } = matchEval;
2349
+ const totalCount = `$count(${qfn(field)})`;
2350
+ const filteredCount = `$count($filter(${qfn(field)}, function($v) {${defaultRuleGroupProcessorJSONata(transformQuery(value, { ruleProcessor: (r) => ({
2351
+ ...r,
2352
+ field: r.field ? `$v.${r.field}` : "$v"
2353
+ }) }), options)}}))`;
2354
+ switch (mode) {
2355
+ case "all": return `${filteredCount} = ${totalCount}`;
2356
+ case "none": return `${filteredCount} = 0`;
2357
+ case "some": return `${filteredCount} > 0`;
2358
+ case "atleast":
2359
+ case "atmost":
2360
+ case "exactly": {
2361
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
2362
+ if (threshold > 0 && threshold < 1) return `${filteredCount} ${op} (${totalCount} * ${threshold})`;
2363
+ return `${filteredCount} ${op} ${threshold}`;
2364
+ }
2365
+ }
2366
+ }
2367
+ const operatorLC = lc(operator);
2368
+ switch (operatorLC) {
2369
+ case "<":
2370
+ case "<=":
2371
+ case "=":
2372
+ case "!=":
2373
+ case ">":
2374
+ case ">=": return `${qfn(field)} ${operatorLC} ${valueIsField ? qfn(trimIfString(value)) : useBareValue ? trimIfString(value) : quote(value, escapeQuotes)}`;
2375
+ case "contains":
2376
+ case "doesnotcontain": return negate(`$contains(${qfn(field)}, ${valueIsField ? qfn(trimIfString(value)) : quote(value, escapeQuotes)})`, shouldNegate(operatorLC));
2377
+ case "beginswith":
2378
+ case "doesnotbeginwith": return negate(valueIsField ? `$substring(${qfn(field)}, 0, $length(${qfn(trimIfString(value))})) = ${qfn(trimIfString(value))}` : `$contains(${qfn(field)}, /^${escapeStringRegex(value)}/)`, shouldNegate(operatorLC));
2379
+ case "endswith":
2380
+ 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));
2381
+ case "null": return `${qfn(field)} = null`;
2382
+ case "notnull": return `${qfn(field)} != null`;
2383
+ case "in":
2384
+ case "notin": {
2385
+ const valueAsArray = toArray(value);
2386
+ return negate(`${qfn(field)} in [${valueAsArray.map((val) => valueIsField ? `${qfn(trimIfString(val))}` : shouldRenderAsNumber(val, parseNumbers) ? `${trimIfString(val)}` : quote(val, escapeQuotes)).join(", ")}]`, shouldNegate(operatorLC));
2387
+ }
2388
+ case "between":
2389
+ case "notbetween": {
2390
+ const valueAsArray = toArray(value);
2391
+ if (valueAsArray.length < 2 || nullOrUndefinedOrEmpty(valueAsArray[0]) || nullOrUndefinedOrEmpty(valueAsArray[1])) return "";
2392
+ const [first, second] = valueAsArray;
2393
+ const shouldParseNumbers = !(parseNumbers === false);
2394
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers: shouldParseNumbers }) : NaN;
2395
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers: shouldParseNumbers }) : NaN;
2396
+ let firstValue = Number.isNaN(firstNum) ? valueIsField ? `${first}` : first : firstNum;
2397
+ let secondValue = Number.isNaN(secondNum) ? valueIsField ? `${second}` : second : secondNum;
2398
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
2399
+ const tempNum = secondNum;
2400
+ secondValue = firstNum;
2401
+ firstValue = tempNum;
2402
+ }
2403
+ const renderAsNumbers = shouldRenderAsNumber(first, parseNumbers) && shouldRenderAsNumber(second, parseNumbers);
2404
+ const getValueString = (raw, val) => valueIsField ? qfn(raw) : renderAsNumbers ? val : quote(val, escapeQuotes);
2405
+ const expression = `${qfn(field)} >= ${getValueString(first, firstValue)} and ${qfn(field)} <= ${getValueString(second, secondValue)}`;
2406
+ return operatorLC === "between" ? `(${expression})` : negate(expression, true);
2407
+ }
2408
+ }
2409
+ return "";
2410
+ };
2411
+
2412
+ //#endregion
2413
+ //#region src/utils/formatQuery/defaultRuleProcessorJsonLogic.ts
2414
+ const convertOperator = (op) => op.replace(/^(=)$/, "$1=").replace(/^notnull$/i, "!=").replace(/^null$/i, "==");
2415
+ const negateIfNotOp = (op, jsonRule) => op.startsWith("not") || op.startsWith("doesnot") ? { "!": jsonRule } : jsonRule;
2416
+ /**
2417
+ * Default rule processor used by {@link formatQuery} for "jsonlogic" format.
2418
+ *
2419
+ * @group Export
2420
+ */
2421
+ const defaultRuleProcessorJsonLogic = (rule, options = {}) => {
2422
+ const { field, operator, value, valueSource } = rule;
2423
+ const { parseNumbers, preserveValueOrder } = options;
2424
+ const valueIsField = valueSource === "field";
2425
+ const fieldObject = { var: field };
2426
+ const fieldOrNumberRenderer = (v) => valueIsField ? { var: `${v}` } : shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
2427
+ const matchEval = processMatchMode(rule);
2428
+ if (matchEval === false) return false;
2429
+ else if (matchEval) {
2430
+ const { mode, threshold } = matchEval;
2431
+ switch (mode) {
2432
+ case "all":
2433
+ case "none":
2434
+ case "some": return { [mode]: [{ var: field }, value.rules.length === 1 && !isRuleGroup(value.rules[0]) ? defaultRuleProcessorJsonLogic(value.rules[0], options) : defaultRuleGroupProcessorJsonLogic(value, options)] };
2435
+ case "atleast":
2436
+ case "atmost":
2437
+ case "exactly": {
2438
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "==";
2439
+ const filteredCount = { reduce: [
2440
+ { filter: [{ var: field }, value.rules.length === 1 && !isRuleGroup(value.rules[0]) ? defaultRuleProcessorJsonLogic(value.rules[0], options) : defaultRuleGroupProcessorJsonLogic(value, options)] },
2441
+ { "+": [1, { var: "accumulator" }] },
2442
+ 0
2443
+ ] };
2444
+ if (threshold > 0 && threshold < 1) {
2445
+ const totalCount = { reduce: [
2446
+ { var: field },
2447
+ { "+": [1, { var: "accumulator" }] },
2448
+ 0
2449
+ ] };
2450
+ return { [op]: [filteredCount, { "*": [totalCount, threshold] }] };
2451
+ }
2452
+ return { [op]: [filteredCount, threshold] };
2453
+ }
2454
+ }
2455
+ }
2456
+ const operatorLC = lc(operator);
2457
+ switch (operatorLC) {
2458
+ case "<":
2459
+ case "<=":
2460
+ case "=":
2461
+ case "!=":
2462
+ case ">":
2463
+ case ">=": return { [convertOperator(operatorLC)]: [fieldObject, fieldOrNumberRenderer(value)] };
2464
+ case "null":
2465
+ case "notnull": return { [`${operatorLC === "notnull" ? "!" : "="}=`]: [fieldObject, null] };
2466
+ case "in":
2467
+ case "notin": {
2468
+ const valueAsArray = toArray(value).map((v) => fieldOrNumberRenderer(v));
2469
+ return negateIfNotOp(operatorLC, { in: [fieldObject, valueAsArray] });
2470
+ }
2471
+ case "between":
2472
+ case "notbetween": {
2473
+ const valueAsArray = toArray(value);
2474
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
2475
+ let [first, second] = valueAsArray;
2476
+ const shouldParseNumbers = !(parseNumbers === false);
2477
+ if (!valueIsField && shouldRenderAsNumber(first, shouldParseNumbers) && shouldRenderAsNumber(second, shouldParseNumbers)) {
2478
+ const firstNum = parseNumber(first, { parseNumbers: shouldParseNumbers });
2479
+ const secondNum = parseNumber(second, { parseNumbers: shouldParseNumbers });
2480
+ if (!preserveValueOrder && secondNum < firstNum) {
2481
+ const tempNum = secondNum;
2482
+ second = firstNum;
2483
+ first = tempNum;
2484
+ } else {
2485
+ first = firstNum;
2486
+ second = secondNum;
2487
+ }
2488
+ } else if (valueIsField) {
2489
+ first = { var: first };
2490
+ second = { var: second };
2491
+ }
2492
+ return negateIfNotOp(operatorLC, { "<=": [
2493
+ first,
2494
+ fieldObject,
2495
+ second
2496
+ ] });
2497
+ }
2498
+ return false;
2499
+ }
2500
+ case "contains":
2501
+ case "doesnotcontain": {
2502
+ const jsonRule = { in: [fieldOrNumberRenderer(value), fieldObject] };
2503
+ return negateIfNotOp(operatorLC, jsonRule);
2504
+ }
2505
+ case "beginswith":
2506
+ case "doesnotbeginwith": {
2507
+ const jsonRule = { startsWith: [fieldObject, fieldOrNumberRenderer(value)] };
2508
+ return negateIfNotOp(operatorLC, jsonRule);
2509
+ }
2510
+ case "endswith":
2511
+ case "doesnotendwith": {
2512
+ const jsonRule = { endsWith: [fieldObject, fieldOrNumberRenderer(value)] };
2513
+ return negateIfNotOp(operatorLC, jsonRule);
2514
+ }
2515
+ }
2516
+ return false;
2517
+ };
2518
+
2519
+ //#endregion
2520
+ //#region src/utils/formatQuery/defaultRuleProcessorLDAP.ts
2521
+ const negateIf = (clause, negate$1) => negate$1 ? `(!${clause})` : `${clause}`;
2522
+ const ldapEscape = (s) => `${trimIfString(s)}`.replaceAll(/[()&|=<>~*\\/]/g, (m) => `\\${m.codePointAt(0).toString(16)}`);
2523
+ /**
2524
+ * Default rule processor used by {@link formatQuery} for "ldap" format.
2525
+ *
2526
+ * @group Export
2527
+ */
2528
+ const defaultRuleProcessorLDAP = (rule, options = {}) => {
2529
+ const { field, operator, value, valueSource } = rule;
2530
+ const { preserveValueOrder } = options;
2531
+ const operatorLC = lc(operator);
2532
+ if (valueSource === "field" || nullOrUndefinedOrEmpty(value) && operatorLC !== "null" && operatorLC !== "notnull" || processMatchMode(rule)) return "";
2533
+ switch (operatorLC) {
2534
+ case "=":
2535
+ case "!=": return negateIf(`(${field}=${ldapEscape(value)})`, operatorLC === "!=");
2536
+ case ">":
2537
+ case ">=": return `(${field}>=${ldapEscape(value)})`;
2538
+ case "<":
2539
+ case "<=": return `(${field}<=${ldapEscape(value)})`;
2540
+ case "contains":
2541
+ case "doesnotcontain": return negateIf(`(${field}=*${ldapEscape(value)}*)`, operatorLC === "doesnotcontain");
2542
+ case "beginswith":
2543
+ case "doesnotbeginwith": return negateIf(`(${field}=${ldapEscape(value)}*)`, operatorLC === "doesnotbeginwith");
2544
+ case "endswith":
2545
+ case "doesnotendwith": return negateIf(`(${field}=*${ldapEscape(value)})`, operatorLC === "doesnotendwith");
2546
+ case "null":
2547
+ case "notnull": return negateIf(`(${field}=*)`, operatorLC === "notnull");
2548
+ case "in":
2549
+ case "notin": {
2550
+ const valueAsArray = toArray(value);
2551
+ return negateIf(`(|${valueAsArray.map((val) => `(${field}=${ldapEscape(val)})`).join("")})`, operatorLC === "notin");
2552
+ }
2553
+ case "between":
2554
+ case "notbetween": {
2555
+ const valueAsArray = toArray(value);
2556
+ if (valueAsArray.length < 2 || nullOrUndefinedOrEmpty(valueAsArray[0]) || nullOrUndefinedOrEmpty(valueAsArray[1])) return "";
2557
+ const [first, second] = valueAsArray;
2558
+ const firstNum = shouldRenderAsNumber(first, true) ? parseNumber(first, { parseNumbers: true }) : NaN;
2559
+ const secondNum = shouldRenderAsNumber(second, true) ? parseNumber(second, { parseNumbers: true }) : NaN;
2560
+ let firstValue = Number.isNaN(firstNum) ? first : firstNum;
2561
+ let secondValue = Number.isNaN(secondNum) ? second : secondNum;
2562
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
2563
+ const tempNum = secondNum;
2564
+ secondValue = firstNum;
2565
+ firstValue = tempNum;
2566
+ }
2567
+ return negateIf(`(&(${field}>=${ldapEscape(firstValue)})(${field}<=${ldapEscape(secondValue)}))`, operatorLC === "notbetween");
2568
+ }
2569
+ }
2570
+ // istanbul ignore next
2571
+ return "";
2572
+ };
2573
+
2574
+ //#endregion
2575
+ //#region src/utils/formatQuery/defaultValueProcessorNL.ts
2576
+ const escapeStringValueQuotes = (v, quoteChar, escapeQuotes) => escapeQuotes && typeof v === "string" ? v.replaceAll(`${quoteChar}`, `${quoteChar}${quoteChar}`) : v;
2577
+ /**
2578
+ * Default value processor used by {@link formatQuery} for "natural_language" format.
2579
+ *
2580
+ * @group Export
2581
+ */
2582
+ const defaultValueProcessorNL = (rule, opts = {}) => {
2583
+ const { escapeQuotes, fields, parseNumbers, quoteFieldNamesWith, quoteValuesWith, fieldIdentifierSeparator, translations } = opts;
2584
+ const valueIsField = rule.valueSource === "field";
2585
+ const operatorLowerCase = lc(rule.operator);
2586
+ const quoteChar = quoteValuesWith || "'";
2587
+ const quoteValue = (v) => `${quoteChar}${v}${quoteChar}`;
2588
+ const escapeValue = (v) => escapeStringValueQuotes(v, quoteChar, escapeQuotes);
2589
+ const wrapAndEscape = (v) => quoteValue(escapeValue(v));
2590
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
2591
+ quoteFieldNamesWith,
2592
+ fieldIdentifierSeparator
2593
+ });
2594
+ const t = translations ?? ( /* istanbul ignore next */ {});
2595
+ const orTL = t.or ?? "or";
2596
+ const trueTL = t.true ?? "true";
2597
+ const falseTL = t.false ?? "false";
2598
+ switch (operatorLowerCase) {
2599
+ case "null":
2600
+ case "notnull": return "";
2601
+ case "between":
2602
+ case "notbetween": {
2603
+ if (!valueIsField) return defaultValueProcessorByRule(rule, opts);
2604
+ const valueAsArray = toArray(rule.value, { retainEmptyStrings: true }).slice(0, 2).map((v) => wrapFieldName(getOption(fields ?? [], v)?.label ?? v));
2605
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return "";
2606
+ return defaultValueProcessorByRule({
2607
+ ...rule,
2608
+ value: valueAsArray
2609
+ }, opts);
2610
+ }
2611
+ case "in":
2612
+ case "notin": {
2613
+ const valueAsArray = toArray(rule.value);
2614
+ if (valueAsArray.length === 0) return "";
2615
+ const valStringArray = valueAsArray.map((v) => valueIsField ? wrapFieldName(getOption(fields ?? [], v)?.label ?? v) : shouldRenderAsNumber(v, parseNumbers) ? `${trimIfString(v)}` : `${wrapAndEscape(v)}`);
2616
+ return `${valStringArray.slice(0, -1).join(", ")}${valStringArray.length > 2 ? "," : ""} ${orTL} ${valStringArray.at(-1)}`;
2617
+ }
2618
+ }
2619
+ if (typeof rule.value === "boolean") return rule.value ? trueTL : falseTL;
2620
+ return valueIsField ? wrapFieldName(getOption(fields ?? [], rule.value)?.label ?? rule.value) : shouldRenderAsNumber(rule.value, parseNumbers) ? `${trimIfString(rule.value)}` : `${wrapAndEscape(rule.value)}`;
2621
+ };
2622
+
2623
+ //#endregion
2624
+ //#region src/utils/formatQuery/defaultRuleProcessorNL.ts
2625
+ /**
2626
+ * Default operator map used by {@link formatQuery} for "natural_language" format.
2627
+ *
2628
+ * @group Export
2629
+ */
2630
+ const defaultExportOperatorMap = {
2631
+ "=": ["is", "is the same as the value in"],
2632
+ "!=": ["is not", "is not the same as the value in"],
2633
+ "<": ["is less than", "is less than the value in"],
2634
+ ">": ["is greater than", "is greater than the value in"],
2635
+ "<=": ["is less than or equal to", "is less than or equal to the value in"],
2636
+ ">=": ["is greater than or equal to", "is greater than or equal to the value in"],
2637
+ contains: ["contains", "contains the value in"],
2638
+ beginswith: ["starts with", "starts with the value in"],
2639
+ endswith: ["ends with", "ends with the value in"],
2640
+ doesnotcontain: ["does not contain", "does not contain the value in"],
2641
+ doesnotbeginwith: ["does not start with", "does not start with the value in"],
2642
+ doesnotendwith: ["does not end with", "does not end with the value in"],
2643
+ null: "is null",
2644
+ notnull: "is not null",
2645
+ in: ["is one of the values", "is the same as a value in"],
2646
+ notin: ["is not one of the values", "is not the same as any value in"],
2647
+ between: ["is between", "is between the values in"],
2648
+ notbetween: ["is not between", "is not between the values in"]
2649
+ };
2650
+ /* istanbul ignore next */
2651
+ const defaultGetOperators = () => [];
2652
+ /**
2653
+ * Default operator processor used by {@link formatQuery} for "natural_language" format.
2654
+ *
2655
+ * @group Export
2656
+ */
2657
+ const defaultOperatorProcessorNL = (rule, opts = {}) => {
2658
+ const { field, operator, valueSource = "value" } = rule;
2659
+ // istanbul ignore next
2660
+ const { getOperators = defaultGetOperators, operatorMap: operatorMapParam = defaultExportOperatorMap } = opts;
2661
+ const mapOperatorMap = new Map(Object.entries(defaultExportOperatorMap));
2662
+ for (const [key, value] of Object.entries(operatorMapParam)) mapOperatorMap.set(lc(key), value);
2663
+ const operatorMap = Object.fromEntries(mapOperatorMap);
2664
+ const { value: operatorNL, label } = getOption(toFullOptionList(getOperators(field, { fieldData: opts.fieldData ?? {
2665
+ name: field,
2666
+ value: field,
2667
+ label: field
2668
+ } }) ?? []), operator) ?? {
2669
+ name: operator,
2670
+ value: operator,
2671
+ label: operator
2672
+ };
2673
+ const operatorTL = operatorMap[operatorNL] ?? operatorMap[lc(operatorNL)] ?? [label, label];
2674
+ return typeof operatorTL === "string" ? operatorTL : operatorTL[valueSource === "field" ? 1 : 0];
2675
+ };
2676
+ /**
2677
+ * Default rule processor used by {@link formatQuery} for "natural_language" format.
2678
+ *
2679
+ * @group Export
2680
+ */
2681
+ const defaultRuleProcessorNL = (rule, opts) => {
2682
+ const { field, operator } = rule;
2683
+ // istanbul ignore next
2684
+ const { fieldData, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", quoteValuesWith = `'`, operatorProcessor = defaultOperatorProcessorNL, valueProcessor = defaultValueProcessorNL, concatOperator = "||", wordOrder = "SVO" } = opts ?? ( /* istanbul ignore next */ {});
2685
+ const processedField = getQuotedFieldName(fieldData?.label ?? field, {
2686
+ quoteFieldNamesWith,
2687
+ fieldIdentifierSeparator
2688
+ });
2689
+ const matchEval = processMatchMode(rule);
2690
+ if (matchEval === false) return "";
2691
+ else if (matchEval) {
2692
+ const { mode, threshold } = matchEval;
2693
+ const nestedArrayFilter = defaultRuleGroupProcessorNL(rule.value, {
2694
+ ...opts,
2695
+ fields: toFullOptionList(fieldData?.subproperties ?? [])
2696
+ });
2697
+ const hsp = (fieldData?.subproperties?.length ?? 0) > 0;
2698
+ switch (mode) {
2699
+ case "all": return `(${hsp ? "for " : ""}every item in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
2700
+ case "none": return `(${hsp ? "for " : ""}no item in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
2701
+ case "some": return `(${hsp ? "for " : ""}at least one item in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
2702
+ case "atleast":
2703
+ case "atmost":
2704
+ case "exactly": {
2705
+ const mm = mode.replace("at", "at ");
2706
+ if (threshold > 0 && threshold < 1) return `(${hsp ? "for " : ""}${mm} ${threshold * 100}% of the items in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
2707
+ return `(${hsp ? "for " : ""}${mm} ${threshold} of the items in ${processedField}${hsp ? "," : ""} ${nestedArrayFilter})`;
2708
+ }
2709
+ }
2710
+ }
2711
+ const value = valueProcessor(rule, {
2712
+ ...opts,
2713
+ quoteFieldNamesWith,
2714
+ fieldIdentifierSeparator,
2715
+ quoteValuesWith,
2716
+ concatOperator
2717
+ });
2718
+ const operatorLC = lc(operator);
2719
+ if ((operatorLC === "in" || operatorLC === "notin" || operatorLC === "between" || operatorLC === "notbetween") && !value) return "";
2720
+ const processedOperator = operatorProcessor(rule, opts);
2721
+ const wordOrderMap = {
2722
+ S: processedField,
2723
+ V: processedOperator,
2724
+ O: value
2725
+ };
2726
+ return normalizeConstituentWordOrder(wordOrder).map((term) => `${wordOrderMap[term]}`).join(" ").trim();
2727
+ };
2728
+
2729
+ //#endregion
2730
+ //#region src/utils/formatQuery/defaultRuleProcessorSQL.ts
2731
+ /**
2732
+ * Default operator processor used by {@link formatQuery} for "sql" and "parameterized*" formats.
2733
+ *
2734
+ * @group Export
2735
+ */
2736
+ const defaultOperatorProcessorSQL = (rule) => lc(mapSQLOperator(rule.operator));
2737
+ /**
2738
+ * Default rule processor used by {@link formatQuery} for "sql" format.
2739
+ *
2740
+ * @group Export
2741
+ */
2742
+ const defaultRuleProcessorSQL = (rule, opts = {}) => {
2743
+ const { quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", quoteValuesWith = `'`, operatorProcessor = defaultOperatorProcessorSQL, valueProcessor = defaultValueProcessorByRule, concatOperator = "||" } = opts;
2744
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
2745
+ quoteFieldNamesWith,
2746
+ fieldIdentifierSeparator
2747
+ });
2748
+ const ruleField = wrapFieldName(rule.field);
2749
+ const matchEval = processMatchMode(rule);
2750
+ if (matchEval === false) return;
2751
+ else if (matchEval) {
2752
+ if (opts?.preset !== "postgresql") return "";
2753
+ const { mode, threshold } = matchEval;
2754
+ const arrayElementAlias = "elem_alias";
2755
+ const nestedArrayFilter = defaultRuleGroupProcessorSQL(transformQuery(rule.value, { ruleProcessor: (r) => ({
2756
+ ...r,
2757
+ field: arrayElementAlias
2758
+ }) }), opts);
2759
+ switch (mode) {
2760
+ case "all": return `(select count(*) from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter}) = array_length(${ruleField}, 1)`;
2761
+ case "none": return `not exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter})`;
2762
+ case "some": return `exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter})`;
2763
+ case "atleast":
2764
+ case "atmost":
2765
+ case "exactly": {
2766
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
2767
+ return `(select count(*)${threshold > 0 && threshold < 1 ? ` / array_length(${ruleField}, 1)` : ""} from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedArrayFilter}) ${op} ${threshold}`;
2768
+ }
2769
+ }
2770
+ }
2771
+ const value = valueProcessor(rule, {
2772
+ ...opts,
2773
+ quoteFieldNamesWith,
2774
+ fieldIdentifierSeparator,
2775
+ quoteValuesWith,
2776
+ concatOperator
2777
+ });
2778
+ const operator = operatorProcessor(rule, opts);
2779
+ const operatorLowerCase = lc(operator);
2780
+ if ((operatorLowerCase === "in" || operatorLowerCase === "not in" || operatorLowerCase === "between" || operatorLowerCase === "not between") && !value) return "";
2781
+ return `${ruleField} ${operator} ${value}`.trim();
2782
+ };
2783
+
2784
+ //#endregion
2785
+ //#region src/utils/formatQuery/defaultRuleProcessorParameterized.ts
2786
+ /**
2787
+ * Default rule processor used by {@link formatQuery} for "parameterized" and
2788
+ * "parameterized_named" formats.
2789
+ *
2790
+ * @group Export
2791
+ */
2792
+ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
2793
+ // istanbul ignore next
2794
+ const { fieldData, format, getNextNamedParam, parseNumbers, paramPrefix, paramsKeepPrefix, numberedParams, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator, concatOperator, operatorProcessor = defaultOperatorProcessorSQL, valueProcessor = defaultValueProcessorByRule } = opts ?? {};
2795
+ const { processedParams = [] } = meta ?? {};
2796
+ const parameterized = format === "parameterized";
2797
+ const params = [];
2798
+ const paramsNamed = {};
2799
+ const finalize = (sql) => parameterized ? {
2800
+ sql,
2801
+ params
2802
+ } : {
2803
+ sql,
2804
+ params: paramsNamed
2805
+ };
2806
+ const wrapFieldName = (v) => getQuotedFieldName(v, {
2807
+ quoteFieldNamesWith,
2808
+ fieldIdentifierSeparator
2809
+ });
2810
+ const ruleField = wrapFieldName(rule.field);
2811
+ const matchEval = processMatchMode(rule);
2812
+ if (matchEval === false) return;
2813
+ else if (matchEval) {
2814
+ if (opts?.preset !== "postgresql") return finalize("");
2815
+ const { mode, threshold } = matchEval;
2816
+ const arrayElementAlias = "elem_alias";
2817
+ const { sql: nestedSQL, params: nestedParams } = defaultRuleGroupProcessorParameterized(transformQuery(rule.value, { ruleProcessor: (r) => ({
2818
+ ...r,
2819
+ field: arrayElementAlias
2820
+ }) }), {
2821
+ ...opts,
2822
+ fields: []
2823
+ });
2824
+ // istanbul ignore else
2825
+ if (Array.isArray(nestedParams)) params.push(...nestedParams);
2826
+ else Object.assign(paramsNamed, nestedParams);
2827
+ switch (mode) {
2828
+ case "all": return finalize(`(select count(*) from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL}) = array_length(${ruleField}, 1)`);
2829
+ case "none": return finalize(`not exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL})`);
2830
+ case "some": return finalize(`exists (select 1 from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL})`);
2831
+ case "atleast":
2832
+ case "atmost":
2833
+ case "exactly": {
2834
+ const op = mode === "atleast" ? ">=" : mode === "atmost" ? "<=" : "=";
2835
+ return finalize(`(select count(*)${threshold > 0 && threshold < 1 ? ` / array_length(${ruleField}, 1)` : ""} from unnest(${ruleField}) as ${wrapFieldName(arrayElementAlias)} where ${nestedSQL}) ${op} ${threshold}`);
2836
+ }
2837
+ }
2838
+ }
2839
+ const value = valueProcessor(rule, {
2840
+ parseNumbers,
2841
+ quoteFieldNamesWith,
2842
+ concatOperator,
2843
+ fieldData,
2844
+ format
2845
+ });
2846
+ const sqlOperator = operatorProcessor(rule, opts);
2847
+ const sqlOperatorLowerCase = lc(sqlOperator);
2848
+ const [qPre, qPost] = quoteFieldNamesWith;
2849
+ if ((sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in" || sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") && !value) return finalize("");
2850
+ else if (sqlOperatorLowerCase === "is null" || sqlOperatorLowerCase === "is not null") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator}`);
2851
+ else if (rule.valueSource === "field") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${value}`.trim());
2852
+ else if (sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in") {
2853
+ const splitValue = toArray(rule.value);
2854
+ if (parameterized) {
2855
+ for (const v of splitValue) params.push(shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v);
2856
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} (${splitValue.map((_v, i) => numberedParams ? `${paramPrefix}${processedParams.length + 1 + splitValue.length - (splitValue.length - i)}` : "?").join(", ")})`);
2857
+ }
2858
+ const inParams = [];
2859
+ for (const v of splitValue) {
2860
+ const thisParamName = getNextNamedParam(rule.field);
2861
+ inParams.push(`${paramPrefix}${thisParamName}`);
2862
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${thisParamName}`] = shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v;
2863
+ }
2864
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} (${inParams.join(", ")})`);
2865
+ } else if (sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") {
2866
+ const [first, second] = toArray(rule.value, { retainEmptyStrings: true }).slice(0, 2).map((v) => shouldRenderAsNumber(v, parseNumbers) ? parseNumber(v, { parseNumbers }) : v);
2867
+ if (parameterized) {
2868
+ params.push(first, second);
2869
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${numberedParams ? `${paramPrefix}${processedParams.length + 1}` : "?"} and ${numberedParams ? `${paramPrefix}${processedParams.length + 2}` : "?"}`);
2870
+ }
2871
+ const firstParamName = getNextNamedParam(rule.field);
2872
+ const secondParamName = getNextNamedParam(rule.field);
2873
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${firstParamName}`] = first;
2874
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${secondParamName}`] = second;
2875
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${paramPrefix}${firstParamName} and ${paramPrefix}${secondParamName}`);
2876
+ }
2877
+ let paramValue = rule.value;
2878
+ if (typeof rule.value === "string") if (shouldRenderAsNumber(rule.value, parseNumbers)) paramValue = parseNumber(rule.value, { parseNumbers });
2879
+ else paramValue = /^'.*'$/g.test(value) ? value.replaceAll(/(^'|'$)/g, "") : value;
2880
+ let paramName = "";
2881
+ if (parameterized) params.push(paramValue);
2882
+ else {
2883
+ paramName = getNextNamedParam(rule.field);
2884
+ paramsNamed[`${paramsKeepPrefix ? paramPrefix : ""}${paramName}`] = paramValue;
2885
+ }
2886
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${parameterized ? numberedParams ? `${paramPrefix}${processedParams.length + 1}` : "?" : `${paramPrefix}${paramName}`}`.trim());
2887
+ };
2888
+
2889
+ //#endregion
2890
+ //#region src/utils/formatQuery/defaultRuleProcessorPrisma.ts
2891
+ const processNumber = (value, fallback, parseNumbers) => shouldRenderAsNumber(value, !!parseNumbers || typeof value === "bigint") ? Number(parseNumber(value, { parseNumbers: !!parseNumbers })) : fallback;
2892
+ /**
2893
+ * Default rule processor used by {@link formatQuery} for "prisma" format.
2894
+ *
2895
+ * @group Export
2896
+ */
2897
+ const defaultRuleProcessorPrisma = (rule, options = {}) => {
2898
+ const { field, operator, value, valueSource } = rule;
2899
+ // istanbul ignore next
2900
+ const { parseNumbers, preserveValueOrder } = options;
2901
+ if (valueSource === "field" || processMatchMode(rule)) return;
2902
+ const operatorLC = lc(operator);
2903
+ switch (operatorLC) {
2904
+ case "=": return { [field]: processNumber(value, value, parseNumbers) };
2905
+ case "!=":
2906
+ case "<":
2907
+ case "<=":
2908
+ case ">":
2909
+ case ">=": {
2910
+ const prismaOperator = prismaOperators[operatorLC];
2911
+ return { [field]: { [prismaOperator]: processNumber(value, value, parseNumbers) } };
2912
+ }
2913
+ case "contains": return { [field]: { contains: value } };
2914
+ case "beginswith": return { [field]: { startsWith: value } };
2915
+ case "endswith": return { [field]: { endsWith: value } };
2916
+ case "doesnotcontain": return { NOT: { [field]: { contains: value } } };
2917
+ case "doesnotbeginwith": return { NOT: { [field]: { startsWith: value } } };
2918
+ case "doesnotendwith": return { NOT: { [field]: { endsWith: value } } };
2919
+ case "null": return { [field]: null };
2920
+ case "notnull": return { [field]: { not: null } };
2921
+ case "in":
2922
+ case "notin": {
2923
+ const valueAsArray = toArray(value);
2924
+ return { [field]: { [prismaOperators[operatorLC]]: valueAsArray.map((val) => processNumber(val, val, parseNumbers)) } };
2925
+ }
2926
+ case "between":
2927
+ case "notbetween": {
2928
+ const valueAsArray = toArray(value);
2929
+ if (valueAsArray.length >= 2 && isValidValue(valueAsArray[0]) && isValidValue(valueAsArray[1])) {
2930
+ const [first, second] = valueAsArray;
2931
+ const shouldParseNumbers = !(parseNumbers === false);
2932
+ const firstNum = shouldRenderAsNumber(first, shouldParseNumbers) ? parseNumber(first, { parseNumbers }) : NaN;
2933
+ const secondNum = shouldRenderAsNumber(second, shouldParseNumbers) ? parseNumber(second, { parseNumbers }) : NaN;
2934
+ let firstValue = Number.isNaN(firstNum) ? first : firstNum;
2935
+ let secondValue = Number.isNaN(secondNum) ? second : secondNum;
2936
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
2937
+ const tempNum = secondNum;
2938
+ secondValue = firstNum;
2939
+ firstValue = tempNum;
2940
+ }
2941
+ return operatorLC === "between" ? { [field]: {
2942
+ gte: firstValue,
2943
+ lte: secondValue
2944
+ } } : { OR: [{ [field]: { lt: firstValue } }, { [field]: { gt: secondValue } }] };
2945
+ } else return "";
2946
+ }
2947
+ }
2948
+ return "";
2949
+ };
2950
+
2951
+ //#endregion
2952
+ //#region src/utils/formatQuery/defaultRuleProcessorSequelize.ts
2953
+ /**
2954
+ * Default rule processor used by {@link formatQuery} for the "sequelize" format.
2955
+ *
2956
+ * @group Export
2957
+ */
2958
+ const defaultRuleProcessorSequelize = (rule, { parseNumbers, preserveValueOrder, context = {} } = {}) => {
2959
+ const { sequelizeOperators: Op, sequelizeCol: col, sequelizeFn: fn } = context;
2960
+ if (processMatchMode(rule)) return;
2961
+ const { field, operator, value, valueSource } = rule;
2962
+ const valueIsField = valueSource === "field";
2963
+ const operatorLC = lc(operator);
2964
+ if (!Op || valueIsField && (!col || !fn && [
2965
+ "doesnotcontain",
2966
+ "doesnotbeginwith",
2967
+ "doesnotendwith"
2968
+ ].includes(operatorLC))) return;
2969
+ switch (operatorLC) {
2970
+ case "=":
2971
+ case "!=":
2972
+ case "<":
2973
+ case "<=":
2974
+ case ">":
2975
+ case ">=": {
2976
+ const sequelizeOperator = {
2977
+ "=": Op.eq,
2978
+ "!=": Op.ne,
2979
+ "<": Op.lt,
2980
+ "<=": Op.lte,
2981
+ ">": Op.gt,
2982
+ ">=": Op.gte
2983
+ }[operatorLC];
2984
+ return { [field]: valueIsField && operatorLC === "=" ? { [Op.col]: value } : { [sequelizeOperator]: valueIsField ? col(value) : shouldRenderAsNumber(value, parseNumbers) ? parseNumber(value, { parseNumbers: "strict" }) : value } };
2985
+ }
2986
+ case "contains": return { [field]: { [Op.substring]: valueIsField ? col(value) : `${value}` } };
2987
+ case "beginswith": return { [field]: { [Op.startsWith]: valueIsField ? col(value) : `${value}` } };
2988
+ case "endswith": return { [field]: { [Op.endsWith]: valueIsField ? col(value) : `${value}` } };
2989
+ case "doesnotcontain": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value), "%") : `%${value}%` } };
2990
+ case "doesnotbeginwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", col(value), "%") : `${value}%` } };
2991
+ case "doesnotendwith": return { [field]: { [Op.notLike]: valueIsField ? fn("CONCAT", "%", col(value)) : `%${value}` } };
2992
+ case "null": return { [field]: { [Op.is]: null } };
2993
+ case "notnull": return { [field]: { [Op.not]: null } };
2994
+ case "in":
2995
+ case "notin": {
2996
+ const valueAsArray = toArray(value);
2997
+ return { [field]: { [operatorLC === "in" ? Op.in : Op.notIn]: valueAsArray.map((val) => valueIsField ? col(val) : shouldRenderAsNumber(val, parseNumbers) ? parseNumber(val, { parseNumbers: "strict" }) : val) } };
2998
+ }
2999
+ case "between":
3000
+ case "notbetween": {
3001
+ const valueAsArray = toArray(value, { retainEmptyStrings: true });
3002
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return;
3003
+ const [first, second] = valueAsArray;
3004
+ const firstNum = shouldRenderAsNumber(first, parseNumbers) ? parseNumber(first, { parseNumbers: "strict" }) : NaN;
3005
+ const secondNum = shouldRenderAsNumber(second, parseNumbers) ? parseNumber(second, { parseNumbers: "strict" }) : NaN;
3006
+ const firstValue = Number.isNaN(firstNum) ? first : firstNum;
3007
+ const secondValue = Number.isNaN(secondNum) ? second : secondNum;
3008
+ const valsOneAndTwoOnly = [firstValue, secondValue];
3009
+ if (!preserveValueOrder && firstValue === firstNum && secondValue === secondNum && secondNum < firstNum) {
3010
+ valsOneAndTwoOnly[0] = secondNum;
3011
+ valsOneAndTwoOnly[1] = firstNum;
3012
+ }
3013
+ 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 } };
3014
+ }
3015
+ }
3016
+ };
3017
+
3018
+ //#endregion
3019
+ //#region src/utils/formatQuery/formatQuery.ts
3020
+ /**
3021
+ * A collection of option presets for {@link formatQuery}, specifically for SQL-based formats.
3022
+ *
3023
+ * @group Export
3024
+ */
3025
+ const sqlDialectPresets = {
3026
+ ansi: {},
3027
+ sqlite: { paramsKeepPrefix: true },
3028
+ oracle: {},
3029
+ mssql: {
3030
+ concatOperator: "+",
3031
+ quoteFieldNamesWith: ["[", "]"],
3032
+ fieldIdentifierSeparator: ".",
3033
+ paramPrefix: "@"
3034
+ },
3035
+ mysql: { concatOperator: "CONCAT" },
3036
+ postgresql: {
3037
+ quoteFieldNamesWith: "\"",
3038
+ numberedParams: true,
3039
+ paramPrefix: "$"
3040
+ }
3041
+ };
3042
+ /**
3043
+ * A collection of option presets for {@link formatQuery}.
3044
+ *
3045
+ * @group Export
3046
+ */
3047
+ const formatQueryOptionPresets = { ...sqlDialectPresets };
3048
+ const defaultRuleProcessors = {
3049
+ cel: defaultRuleProcessorCEL,
3050
+ drizzle: defaultRuleProcessorDrizzle,
3051
+ elasticsearch: defaultRuleProcessorElasticSearch,
3052
+ json_without_ids: defaultRuleProcessorSQL,
3053
+ json: defaultRuleProcessorSQL,
3054
+ jsonata: defaultRuleProcessorJSONata,
3055
+ jsonlogic: defaultRuleProcessorJsonLogic,
3056
+ ldap: defaultRuleProcessorLDAP,
3057
+ mongodb_query: defaultRuleProcessorMongoDBQuery,
3058
+ mongodb: defaultRuleProcessorMongoDB,
3059
+ natural_language: defaultRuleProcessorNL,
3060
+ parameterized_named: defaultRuleProcessorParameterized,
3061
+ parameterized: defaultRuleProcessorParameterized,
3062
+ prisma: defaultRuleProcessorPrisma,
3063
+ sequelize: defaultRuleProcessorSequelize,
3064
+ spel: defaultRuleProcessorSpEL,
3065
+ sql: defaultRuleProcessorSQL
3066
+ };
3067
+ /* istanbul ignore next */
3068
+ const defaultOperatorProcessor = (r) => r.operator;
3069
+ const defaultOperatorProcessors = {
3070
+ cel: defaultOperatorProcessor,
3071
+ drizzle: defaultOperatorProcessor,
3072
+ elasticsearch: defaultOperatorProcessor,
3073
+ json_without_ids: defaultOperatorProcessor,
3074
+ json: defaultOperatorProcessor,
3075
+ jsonata: defaultOperatorProcessor,
3076
+ jsonlogic: defaultOperatorProcessor,
3077
+ ldap: defaultOperatorProcessor,
3078
+ mongodb_query: defaultOperatorProcessor,
3079
+ mongodb: defaultOperatorProcessor,
3080
+ natural_language: defaultOperatorProcessorNL,
3081
+ parameterized_named: defaultOperatorProcessorSQL,
3082
+ parameterized: defaultOperatorProcessorSQL,
3083
+ prisma: defaultOperatorProcessor,
3084
+ sequelize: defaultOperatorProcessor,
3085
+ spel: defaultOperatorProcessor,
3086
+ sql: defaultOperatorProcessorSQL
3087
+ };
3088
+ const defaultFallbackExpressions = {
3089
+ cel: "1 == 1",
3090
+ ldap: "",
3091
+ mongodb: "\"$and\":[{\"$expr\":true}]",
3092
+ natural_language: "1 is 1",
3093
+ spel: "1 == 1",
3094
+ sql: "(1 = 1)"
3095
+ };
3096
+ const defaultFormatQueryOptions = {
3097
+ format: "json",
3098
+ fields: [],
3099
+ quoteFieldNamesWith: ["", ""],
3100
+ fieldIdentifierSeparator: "",
3101
+ getOperators: () => [],
3102
+ paramPrefix: ":",
3103
+ paramsKeepPrefix: false,
3104
+ numberedParams: false,
3105
+ preserveValueOrder: false,
3106
+ placeholderFieldName: defaultPlaceholderFieldName,
3107
+ placeholderOperatorName: defaultPlaceholderOperatorName,
3108
+ quoteValuesWith: "'",
3109
+ concatOperator: "||",
3110
+ preset: "ansi",
3111
+ wordOrder: "SVO",
3112
+ translations: {},
3113
+ operatorMap: {}
3114
+ };
3115
+ const valueProcessorCanActAsRuleProcessor = new Set([
3116
+ "cel",
3117
+ "drizzle",
3118
+ "elasticsearch",
3119
+ "jsonata",
3120
+ "jsonlogic",
3121
+ "ldap",
3122
+ "mongodb_query",
3123
+ "mongodb",
3124
+ "prisma",
3125
+ "sequelize",
3126
+ "spel"
3127
+ ]);
3128
+ const sqlFormats = new Set([
3129
+ "sql",
3130
+ "parameterized",
3131
+ "parameterized_named",
3132
+ "drizzle",
3133
+ "prisma",
3134
+ "sequelize"
3135
+ ]);
3136
+ function formatQuery(ruleGroup, optionParam = {}) {
3137
+ const options = typeof optionParam === "string" ? { format: lc(optionParam) } : optionParam;
3138
+ const optObj = {
3139
+ ...defaultFormatQueryOptions,
3140
+ ...!options.format || sqlFormats.has(options.format) ? sqlDialectPresets[options.preset ?? "ansi"] ?? null : null,
3141
+ ...options,
3142
+ ...!options.format && (Object.keys(sqlDialectPresets).includes(options.preset ?? "") ? { format: "sql" } : null)
3143
+ };
3144
+ const format = lc(optObj.format);
3145
+ 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;
3146
+ const getParseNumberBoolean = (inputType) => {
3147
+ return typeof getParseNumberMethod({
3148
+ parseNumbers,
3149
+ inputType
3150
+ }) === "string" ? true : typeof parseNumbers === "boolean" ? parseNumbers : void 0;
3151
+ };
3152
+ const operatorProcessor = typeof operatorProcessor_option === "function" ? operatorProcessor_option : defaultOperatorProcessors[format] ?? defaultOperatorProcessor;
3153
+ 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;
3154
+ const ruleProcessor = (typeof ruleProcessor_option === "function" ? ruleProcessor_option : null) ?? (valueProcessorCanActAsRuleProcessor.has(format) && typeof ruleProcessor_option !== "function" && valueProcessor_option ? valueProcessor : null) ?? defaultRuleProcessors[format] ?? defaultRuleProcessorSQL;
3155
+ const quoteFieldNamesWith = getQuoteFieldNamesWithArray(quoteFieldNamesWith_option);
3156
+ const fields = toFullOptionList(optObj.fields);
3157
+ const getOperators = (f, m) => toFullOptionList(getOperators_option(f, m) ?? []);
3158
+ const fallbackExpression = fallbackExpression_option ?? defaultFallbackExpressions[format] ?? defaultFallbackExpressions.sql;
3159
+ let validationMap = {};
3160
+ // istanbul ignore else
3161
+ if (typeof validator === "function") {
3162
+ const validationResult = validator(ruleGroup);
3163
+ if (typeof validationResult === "boolean") {
3164
+ // istanbul ignore else
3165
+ if (!validationResult) return format === "parameterized" ? {
3166
+ sql: fallbackExpression,
3167
+ params: []
3168
+ } : format === "parameterized_named" ? {
3169
+ sql: fallbackExpression,
3170
+ params: {}
3171
+ } : format === "mongodb" ? `{${fallbackExpression}}` : format === "mongodb_query" ? mongoDbFallback : format === "prisma" ? prismaFallback : format === "jsonlogic" ? false : format === "elasticsearch" ? {} : format === "drizzle" || format === "sequelize" ? void 0 : fallbackExpression;
3172
+ } else validationMap = validationResult;
3173
+ }
3174
+ const validatorMap = {};
3175
+ const uniqueFields = toFlatOptionArray(fields);
3176
+ for (const f of uniqueFields)
3177
+ // istanbul ignore else
3178
+ if (typeof f.validator === "function") validatorMap[f.value ?? f.name] = f.validator;
3179
+ const validateRule = (rule) => {
3180
+ let validationResult;
3181
+ let fieldValidator;
3182
+ if (rule.id) validationResult = validationMap[rule.id];
3183
+ if (uniqueFields.length > 0) {
3184
+ const fieldArr = uniqueFields.filter((f) => f.name === rule.field);
3185
+ if (fieldArr.length > 0) {
3186
+ const field = fieldArr[0];
3187
+ // istanbul ignore else
3188
+ if (typeof field.validator === "function") fieldValidator = field.validator;
3189
+ }
3190
+ }
3191
+ return [validationResult, fieldValidator];
3192
+ };
3193
+ const finalOptions = {
3194
+ ...optObj,
3195
+ fallbackExpression,
3196
+ fields,
3197
+ format,
3198
+ getOperators,
3199
+ getParseNumberBoolean,
3200
+ quoteFieldNamesWith,
3201
+ operatorProcessor,
3202
+ ruleProcessor,
3203
+ valueProcessor,
3204
+ validateRule,
3205
+ validationMap,
3206
+ context
3207
+ };
3208
+ if (typeof ruleGroupProcessor_option === "function") return ruleGroupProcessor_option(ruleGroup, finalOptions);
3209
+ switch (format) {
3210
+ case "json":
3211
+ case "json_without_ids": {
3212
+ const rg = parseNumbers ? produce(ruleGroup, (g) => numerifyValues(g, finalOptions)) : ruleGroup;
3213
+ if (format === "json_without_ids") return JSON.stringify(rg, (key, value) => key === "id" || key === "path" ? void 0 : bigIntJsonStringifyReplacer(key, value));
3214
+ return JSON.stringify(rg, bigIntJsonStringifyReplacer, 2);
3215
+ }
3216
+ case "sql": return defaultRuleGroupProcessorSQL(ruleGroup, finalOptions);
3217
+ case "parameterized":
3218
+ case "parameterized_named": return defaultRuleGroupProcessorParameterized(ruleGroup, finalOptions);
3219
+ case "mongodb": return defaultRuleGroupProcessorMongoDB(ruleGroup, finalOptions);
3220
+ case "mongodb_query": return defaultRuleGroupProcessorMongoDBQuery(ruleGroup, finalOptions);
3221
+ case "cel": return defaultRuleGroupProcessorCEL(ruleGroup, finalOptions);
3222
+ case "spel": return defaultRuleGroupProcessorSpEL(ruleGroup, finalOptions);
3223
+ case "jsonata": return defaultRuleGroupProcessorJSONata(ruleGroup, finalOptions);
3224
+ case "jsonlogic": return defaultRuleGroupProcessorJsonLogic(ruleGroup, finalOptions);
3225
+ case "elasticsearch": return defaultRuleGroupProcessorElasticSearch(ruleGroup, finalOptions);
3226
+ case "natural_language": return defaultRuleGroupProcessorNL(ruleGroup, finalOptions);
3227
+ case "ldap": return defaultRuleGroupProcessorLDAP(ruleGroup, finalOptions);
3228
+ case "prisma": return defaultRuleGroupProcessorPrisma(ruleGroup, finalOptions);
3229
+ case "drizzle": return defaultRuleGroupProcessorDrizzle(ruleGroup, finalOptions);
3230
+ case "sequelize": return defaultRuleGroupProcessorSequelize(ruleGroup, finalOptions);
3231
+ default: return "";
3232
+ }
3233
+ }
3234
+
3235
+ //#endregion
3236
+ //#region src/utils/formatQuery/index.ts
3237
+ const generateValueProcessor = (vpbr) => (field, operator, value, valueSource) => vpbr({
3238
+ field,
3239
+ operator,
3240
+ value,
3241
+ valueSource
3242
+ }, { parseNumbers: false });
3243
+ /**
3244
+ * Default value processor used by {@link formatQuery} for "sql" format.
3245
+ *
3246
+ * @group Export
3247
+ */
3248
+ const defaultValueProcessor = generateValueProcessor(defaultValueProcessorByRule);
3249
+ /**
3250
+ * @deprecated Prefer {@link defaultRuleProcessorMongoDB}.
3251
+ *
3252
+ * @group Export
3253
+ */
3254
+ const defaultMongoDBValueProcessor = generateValueProcessor(defaultRuleProcessorMongoDB);
3255
+ /**
3256
+ * @deprecated Prefer {@link defaultRuleProcessorCEL}.
3257
+ *
3258
+ * @group Export
3259
+ */
3260
+ const defaultCELValueProcessor = generateValueProcessor(defaultRuleProcessorCEL);
3261
+ /**
3262
+ * @deprecated Prefer {@link defaultRuleProcessorSpEL}.
3263
+ *
3264
+ * @group Export
3265
+ */
3266
+ const defaultSpELValueProcessor = generateValueProcessor(defaultRuleProcessorSpEL);
3267
+ /**
3268
+ * @deprecated Renamed to {@link defaultRuleProcessorCEL}.
3269
+ *
3270
+ * @group Export
3271
+ */
3272
+ const defaultValueProcessorCELByRule = defaultRuleProcessorCEL;
3273
+ /**
3274
+ * @deprecated Renamed to {@link defaultRuleProcessorMongoDB}.
3275
+ *
3276
+ * @group Export
3277
+ */
3278
+ const defaultValueProcessorMongoDBByRule = defaultRuleProcessorMongoDB;
3279
+ /**
3280
+ * @deprecated Renamed to {@link defaultRuleProcessorSpEL}.
3281
+ *
3282
+ * @group Export
3283
+ */
3284
+ const defaultValueProcessorSpELByRule = defaultRuleProcessorSpEL;
3285
+
3286
+ //#endregion
3287
+ //#region src/utils/pathUtils.ts
3288
+ /**
3289
+ * Returns the {@link RuleType} or {@link RuleGroupType}/{@link RuleGroupTypeIC}
3290
+ * at the given path within a query.
3291
+ */
3292
+ const findPath = (path, query) => {
3293
+ let target = query;
3294
+ let level = 0;
3295
+ while (level < path.length && target && isRuleGroup(target)) {
3296
+ const t = target.rules[path[level]];
3297
+ target = typeof t === "string" ? null : t;
3298
+ level++;
3299
+ }
3300
+ return target;
3301
+ };
3302
+ /**
3303
+ * Returns the {@link RuleType} or {@link RuleGroupType}/{@link RuleGroupTypeIC}
3304
+ * with the given `id` within a query.
3305
+ */
3306
+ const findID = (id, query) => {
3307
+ if (query.id === id) return query;
3308
+ for (const rule of query.rules) {
3309
+ if (typeof rule === "string") continue;
3310
+ if (rule.id === id) return rule;
3311
+ else if (isRuleGroup(rule)) {
3312
+ const subRule = findID(id, rule);
3313
+ if (subRule) return subRule;
3314
+ }
3315
+ }
3316
+ return null;
3317
+ };
3318
+ /**
3319
+ * Returns the {@link Path} of the {@link RuleType} or {@link RuleGroupType}/{@link RuleGroupTypeIC}
3320
+ * with the given `id` within a query.
3321
+ */
3322
+ const getPathOfID = (id, query) => {
3323
+ if (query.id === id) return [];
3324
+ const idx = query.rules.findIndex((r) => !(typeof r === "string") && r.id === id);
3325
+ if (idx >= 0) return [idx];
3326
+ for (const [i, r] of Object.entries(query.rules)) if (isRuleGroup(r)) {
3327
+ const subPath = getPathOfID(id, r);
3328
+ if (Array.isArray(subPath)) return [Number.parseInt(i), ...subPath];
3329
+ }
3330
+ return null;
3331
+ };
3332
+ /**
3333
+ * Truncates the last element of an array and returns the result as a new array.
3334
+ */
3335
+ const getParentPath = (path) => path.slice(0, -1);
3336
+ /**
3337
+ * Determines if two paths (each `Path`) are equivalent.
3338
+ */
3339
+ const pathsAreEqual = (path1, path2) => path1.length === path2.length && path1.every((val, idx) => val === path2[idx]);
3340
+ /**
3341
+ * Determines if the first path is an ancestor of the second path. The first path must
3342
+ * be shorter and exactly match the second path up through the length of the first path.
3343
+ */
3344
+ const isAncestor = (maybeAncestor, path) => maybeAncestor.length < path.length && (/* @__PURE__ */ new RegExp(`^${maybeAncestor.join("-")}`)).test(path.join("-"));
3345
+ /**
3346
+ * Finds the deepest/longest path that two paths have in common.
3347
+ */
3348
+ const getCommonAncestorPath = (path1, path2) => {
3349
+ const commonAncestorPath = [];
3350
+ const parentPath1 = getParentPath(path1);
3351
+ const parentPath2 = getParentPath(path2);
3352
+ let i = 0;
3353
+ while (i < parentPath1.length && i < parentPath2.length && parentPath1[i] === parentPath2[i]) {
3354
+ commonAncestorPath.push(parentPath2[i]);
3355
+ i++;
3356
+ }
3357
+ return commonAncestorPath;
3358
+ };
3359
+ /**
3360
+ * Determines if the rule or group at the specified path is either disabled itself
3361
+ * or disabled by an ancestor group.
3362
+ */
3363
+ const pathIsDisabled = (path, query) => {
3364
+ let disabled = !!query.disabled;
3365
+ let target = query;
3366
+ let level = 0;
3367
+ while (level < path.length && !disabled && isRuleGroup(target)) {
3368
+ const t = target.rules[path[level]];
3369
+ if (isPojo(t) && (isRuleGroup(t) || "field" in t && !!t.field)) {
3370
+ disabled = !!t.disabled;
3371
+ target = t;
3372
+ }
3373
+ level++;
3374
+ }
3375
+ return disabled;
3376
+ };
3377
+
3378
+ //#endregion
3379
+ //#region src/utils/generateAccessibleDescription.ts
3380
+ const generateAccessibleDescription = (params) => pathsAreEqual([], params.path) ? `Query builder` : `Rule group at path ${params.path.join("-")}`;
3381
+
3382
+ //#endregion
3383
+ //#region src/utils/generateID.ts
3384
+ const cryptoModule = globalThis.crypto;
3385
+ /**
3386
+ * Default `id` generator. Generates a valid v4 UUID. Uses `crypto.randomUUID()`
3387
+ * when available, otherwise uses an alternate method based on `getRandomValues`.
3388
+ * The returned string is guaranteed to match this regex:
3389
+ * ```
3390
+ * /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
3391
+ * ```
3392
+ * @returns Valid v4 UUID
3393
+ */
3394
+ // istanbul ignore next
3395
+ let generateID = () => "00-0-4-2-000".replaceAll(/[^-]/g, (s) => ((Math.random() + Math.trunc(s)) * 65536 >> Number.parseInt(s)).toString(16).padStart(4, "0"));
3396
+ // istanbul ignore else
3397
+ if (cryptoModule) {
3398
+ // istanbul ignore else
3399
+ if (typeof cryptoModule.randomUUID === "function") generateID = () => cryptoModule.randomUUID();
3400
+ else if (typeof cryptoModule.getRandomValues === "function") {
3401
+ const position19vals = "89ab";
3402
+ const container = new Uint32Array(32);
3403
+ generateID = () => {
3404
+ cryptoModule.getRandomValues(container);
3405
+ let id = (container[0] % 16).toString(16);
3406
+ for (let i = 1; i < 32; i++) {
3407
+ if (i === 12) id = `${id}4`;
3408
+ else if (i === 16) id = `${id}${position19vals[container[17] % 4]}`;
3409
+ else id = `${id}${(container[i] % 16).toString(16)}`;
3410
+ if (i === 7 || i === 11 || i === 15 || i === 19) id = `${id}-`;
3411
+ }
3412
+ return id;
3413
+ };
3414
+ }
3415
+ }
3416
+
3417
+ //#endregion
3418
+ //#region src/utils/getMatchModesUtil.ts
3419
+ const dummyFD$1 = {
3420
+ name: "name",
3421
+ value: "name",
3422
+ matchModes: null,
3423
+ label: "label"
3424
+ };
3425
+ /**
3426
+ * Utility function to get the match modes array for the given
3427
+ * field. If the field definition does not define a `matchModes`
3428
+ * property, the `getMatchModes` prop is used. Returns
3429
+ * `FullOption<MatchMode>[]` of all match modes by default.
3430
+ */
3431
+ const getMatchModesUtil = (fieldData, getMatchModes) => {
3432
+ const fd = fieldData ? toFullOption(fieldData) : dummyFD$1;
3433
+ let matchModes = fd.matchModes ?? false;
3434
+ if (!matchModes && getMatchModes) matchModes = getMatchModes(fd.value, { fieldData: fd });
3435
+ if (matchModes === true) return defaultMatchModes;
3436
+ else if (matchModes === false) return [];
3437
+ if (isFlexibleOptionArray(matchModes)) return toFullOptionList(matchModes);
3438
+ return matchModes?.map((mm) => defaultMatchModes.find((dmm) => dmm.value === lc(mm)) ?? {
3439
+ name: mm,
3440
+ value: mm,
3441
+ label: mm
3442
+ }) ?? [];
3443
+ };
3444
+
3445
+ //#endregion
3446
+ //#region src/utils/getValidationClassNames.ts
3447
+ /**
3448
+ * Gets the standard classname for valid or invalid components
3449
+ * based on the given validation result.
3450
+ */
3451
+ const getValidationClassNames = (validationResult) => {
3452
+ const valid = typeof validationResult === "boolean" ? validationResult : typeof validationResult === "object" && validationResult !== null ? validationResult.valid : null;
3453
+ return typeof valid === "boolean" ? valid ? standardClassnames.valid : standardClassnames.invalid : "";
3454
+ };
3455
+
3456
+ //#endregion
3457
+ //#region src/utils/getValueSourcesUtil.ts
3458
+ const defaultValueSourcesArray = [{
3459
+ name: "value",
3460
+ value: "value",
3461
+ label: "value"
3462
+ }];
3463
+ const dummyFD = {
3464
+ name: "name",
3465
+ value: "name",
3466
+ valueSources: null,
3467
+ label: "label"
3468
+ };
3469
+ /**
3470
+ * Utility function to get the value sources array for the given
3471
+ * field and operator. If the field definition does not define a
3472
+ * `valueSources` property, the `getValueSources` prop is used.
3473
+ * Returns `[FullOption<"value">]` by default.
3474
+ */
3475
+ const getValueSourcesUtil = (fieldData, operator, getValueSources) => {
3476
+ const fd = fieldData ? toFullOption(fieldData) : dummyFD;
3477
+ let valueSourcesNEW = fd.valueSources ?? false;
3478
+ if (typeof valueSourcesNEW === "function") valueSourcesNEW = valueSourcesNEW(operator);
3479
+ if (!valueSourcesNEW && getValueSources) valueSourcesNEW = getValueSources(fd.value, operator, { fieldData: fd });
3480
+ if (!valueSourcesNEW) return defaultValueSourcesArray;
3481
+ if (isFlexibleOptionArray(valueSourcesNEW)) return toFullOptionList(valueSourcesNEW);
3482
+ return valueSourcesNEW.map((vs) => defaultValueSourcesArray.find((dmm) => dmm.value === lc(vs)) ?? {
3483
+ name: vs,
3484
+ value: vs,
3485
+ label: vs
3486
+ });
3487
+ };
3488
+
3489
+ //#endregion
3490
+ //#region src/utils/mergeClassnames.ts
3491
+ const joinClassnamesByName = (name, args) => clsx(args.map((c) => clsx(c?.[name])));
3492
+ /**
3493
+ * Merges a list of partial {@link Classnames} definitions into a single definition.
3494
+ */
3495
+ const mergeClassnames = (...args) => ({
3496
+ queryBuilder: joinClassnamesByName("queryBuilder", args),
3497
+ ruleGroup: joinClassnamesByName("ruleGroup", args),
3498
+ header: joinClassnamesByName("header", args),
3499
+ body: joinClassnamesByName("body", args),
3500
+ combinators: joinClassnamesByName("combinators", args),
3501
+ addRule: joinClassnamesByName("addRule", args),
3502
+ addGroup: joinClassnamesByName("addGroup", args),
3503
+ cloneRule: joinClassnamesByName("cloneRule", args),
3504
+ cloneGroup: joinClassnamesByName("cloneGroup", args),
3505
+ removeGroup: joinClassnamesByName("removeGroup", args),
3506
+ rule: joinClassnamesByName("rule", args),
3507
+ fields: joinClassnamesByName("fields", args),
3508
+ operators: joinClassnamesByName("operators", args),
3509
+ value: joinClassnamesByName("value", args),
3510
+ removeRule: joinClassnamesByName("removeRule", args),
3511
+ notToggle: joinClassnamesByName("notToggle", args),
3512
+ shiftActions: joinClassnamesByName("shiftActions", args),
3513
+ dragHandle: joinClassnamesByName("dragHandle", args),
3514
+ lockRule: joinClassnamesByName("lockRule", args),
3515
+ lockGroup: joinClassnamesByName("lockGroup", args),
3516
+ valueSource: joinClassnamesByName("valueSource", args),
3517
+ actionElement: joinClassnamesByName("actionElement", args),
3518
+ valueSelector: joinClassnamesByName("valueSelector", args),
3519
+ betweenRules: joinClassnamesByName("betweenRules", args),
3520
+ valid: joinClassnamesByName("valid", args),
3521
+ invalid: joinClassnamesByName("invalid", args),
3522
+ dndDragging: joinClassnamesByName("dndDragging", args),
3523
+ dndOver: joinClassnamesByName("dndOver", args),
3524
+ dndCopy: joinClassnamesByName("dndCopy", args),
3525
+ dndGroup: joinClassnamesByName("dndGroup", args),
3526
+ dndDropNotAllowed: joinClassnamesByName("dndDropNotAllowed", args),
3527
+ disabled: joinClassnamesByName("disabled", args),
3528
+ valueListItem: joinClassnamesByName("valueListItem", args),
3529
+ matchMode: joinClassnamesByName("matchMode", args),
3530
+ matchThreshold: joinClassnamesByName("matchThreshold", args),
3531
+ branches: joinClassnamesByName("branches", args),
3532
+ hasSubQuery: joinClassnamesByName("hasSubQuery", args)
3533
+ });
3534
+
3535
+ //#endregion
3536
+ //#region src/utils/objectUtils.ts
3537
+ /**
3538
+ * A strongly-typed version of `Object.keys()`.
3539
+ *
3540
+ * [Original source](https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-keys.ts)
3541
+ */
3542
+ const objectKeys = Object.keys;
3543
+ /**
3544
+ * A strongly-typed version of `Object.entries()`.
3545
+ *
3546
+ * [Original source](https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-entries.ts)
3547
+ */
3548
+ const objectEntries = Object.entries;
3549
+
3550
+ //#endregion
3551
+ //#region src/utils/prepareQueryObjects.ts
3552
+ /**
3553
+ * Ensures that a rule is valid by adding an `id` property if it does not already exist.
3554
+ */
3555
+ const prepareRule = (rule, { idGenerator = generateID } = {}) => produce(rule, (draft) => {
3556
+ if (!draft.id) draft.id = idGenerator();
3557
+ });
3558
+ /**
3559
+ * Ensures that a rule group is valid by recursively adding an `id` property to the group itself
3560
+ * and all its rules and subgroups where one does not already exist.
3561
+ */
3562
+ const prepareRuleGroup = (queryObject, { idGenerator = generateID } = {}) => produce(queryObject, (draft) => {
3563
+ if (!draft.id) draft.id = idGenerator();
3564
+ draft.rules = draft.rules.map((r) => typeof r === "string" ? r : isRuleGroup(r) ? prepareRuleGroup(r, { idGenerator }) : prepareRule(r, { idGenerator }));
3565
+ });
3566
+ /**
3567
+ * Ensures that a rule or group is valid. See {@link prepareRule} and {@link prepareRuleGroup}.
3568
+ */
3569
+ const prepareRuleOrGroup = (rg, { idGenerator = generateID } = {}) => isRuleGroup(rg) ? prepareRuleGroup(rg, { idGenerator }) : prepareRule(rg, { idGenerator });
3570
+
3571
+ //#endregion
3572
+ //#region src/utils/regenerateIDs.ts
3573
+ /**
3574
+ * Generates a new `id` property for a rule.
3575
+ */
3576
+ const regenerateID = (rule, { idGenerator = generateID } = {}) => structuredClone({
3577
+ ...rule,
3578
+ id: idGenerator()
3579
+ });
3580
+ /**
3581
+ * Recursively generates new `id` properties for a group and all its rules and subgroups.
3582
+ */
3583
+ const regenerateIDs = (ruleOrGroup, { idGenerator = generateID } = {}) => {
3584
+ if (!isPojo(ruleOrGroup)) return ruleOrGroup;
3585
+ if (!isRuleGroup(ruleOrGroup)) return structuredClone({
3586
+ ...ruleOrGroup,
3587
+ id: idGenerator()
3588
+ });
3589
+ if (isRuleGroupType(ruleOrGroup)) {
3590
+ const rules$1 = ruleOrGroup.rules.map((r) => isRuleGroup(r) ? regenerateIDs(r, { idGenerator }) : regenerateID(r, { idGenerator }));
3591
+ return {
3592
+ ...ruleOrGroup,
3593
+ id: idGenerator(),
3594
+ rules: rules$1
3595
+ };
3596
+ }
3597
+ const rules = ruleOrGroup.rules.map((r) => typeof r === "string" ? r : isRuleGroup(r) ? regenerateIDs(r, { idGenerator }) : regenerateID(r, { idGenerator }));
3598
+ return {
3599
+ ...ruleOrGroup,
3600
+ id: idGenerator(),
3601
+ rules
3602
+ };
3603
+ };
3604
+
3605
+ //#endregion
3606
+ //#region src/utils/queryTools.ts
3607
+ /**
3608
+ * Adds a rule or group to a query.
3609
+ * @returns The new query with the rule or group added.
3610
+ *
3611
+ * @group Query Tools
3612
+ */
3613
+ const add = (query, ruleOrGroup, parentPathOrID, { combinators = defaultCombinators, combinatorPreceding, idGenerator = generateID } = {}) => produce(query, (draft) => {
3614
+ const parent = Array.isArray(parentPathOrID) ? findPath(parentPathOrID, draft) : findID(parentPathOrID, draft);
3615
+ if (!parent || !isRuleGroup(parent)) return;
3616
+ if (isRuleGroupTypeIC(parent) && parent.rules.length > 0) {
3617
+ const prevCombinator = parent.rules.at(-2);
3618
+ parent.rules.push(combinatorPreceding ?? (typeof prevCombinator === "string" ? prevCombinator : getFirstOption(combinators)));
3619
+ }
3620
+ parent.rules.push(prepareRuleOrGroup(ruleOrGroup, { idGenerator }));
3621
+ });
3622
+ /**
3623
+ * Updates a property of a rule or group within a query.
3624
+ * @returns The new query with the rule or group property updated.
3625
+ *
3626
+ * @group Query Tools
3627
+ */
3628
+ const update = (query, prop, value, pathOrID, { resetOnFieldChange = true, resetOnOperatorChange = false, getRuleDefaultOperator = () => "=", getValueSources = () => ["value"], getRuleDefaultValue = () => "", getMatchModes = () => [] } = {}) => produce(query, (draft) => {
3629
+ const path = Array.isArray(pathOrID) ? pathOrID : getPathOfID(pathOrID, draft);
3630
+ if (!path) return;
3631
+ if (prop === "combinator" && !isRuleGroupType(draft)) {
3632
+ const parentRules = findPath(getParentPath(path), draft).rules;
3633
+ if (path.at(-1) % 2 === 1) parentRules[path.at(-1)] = value;
3634
+ return;
3635
+ }
3636
+ const ruleOrGroup = findPath(path, draft);
3637
+ if (!ruleOrGroup) return;
3638
+ const isGroup = isRuleGroup(ruleOrGroup);
3639
+ if (ruleOrGroup[prop] === value) return;
3640
+ if (prop !== "valueSource") ruleOrGroup[prop] = value;
3641
+ if (isGroup) return;
3642
+ let resetValueSource = false;
3643
+ let resetValue = false;
3644
+ if (prop === "field") {
3645
+ const fromFieldMatchModes = getMatchModes(ruleOrGroup.field);
3646
+ const toFieldMatchModes = getMatchModes(value);
3647
+ if (toFieldMatchModes.length === 0) delete ruleOrGroup.match;
3648
+ else {
3649
+ const nextMatchMode = ruleOrGroup.match?.mode && getOption(toFieldMatchModes, ruleOrGroup.match.mode) ? null : getFirstOption(toFieldMatchModes);
3650
+ if (nextMatchMode) ruleOrGroup.match = {
3651
+ mode: nextMatchMode,
3652
+ threshold: 1
3653
+ };
3654
+ }
3655
+ if (fromFieldMatchModes.length > 0 || toFieldMatchModes.length > 0) resetOnFieldChange = true;
3656
+ }
3657
+ if (resetOnFieldChange && prop === "field") {
3658
+ ruleOrGroup.operator = getRuleDefaultOperator(value);
3659
+ resetValueSource = true;
3660
+ resetValue = true;
3661
+ }
3662
+ if (resetOnOperatorChange && prop === "operator") {
3663
+ resetValueSource = true;
3664
+ resetValue = true;
3665
+ }
3666
+ const valueSources = getValueSourcesUtil({
3667
+ name: ruleOrGroup.field,
3668
+ value: ruleOrGroup.field,
3669
+ label: ""
3670
+ }, ruleOrGroup.operator, getValueSources);
3671
+ const defaultValueSource = getFirstOption(valueSources);
3672
+ if (resetValueSource && ruleOrGroup.valueSource && defaultValueSource !== ruleOrGroup.valueSource || prop === "valueSource" && value !== ruleOrGroup.valueSource) {
3673
+ resetValue = !!ruleOrGroup.valueSource || !ruleOrGroup.valueSource && value !== defaultValueSource;
3674
+ ruleOrGroup.valueSource = resetValueSource ? defaultValueSource : value;
3675
+ }
3676
+ if (resetValue) ruleOrGroup.value = getRuleDefaultValue(ruleOrGroup);
3677
+ });
3678
+ /**
3679
+ * Removes a rule or group from a query.
3680
+ * @returns The new query with the rule or group removed.
3681
+ *
3682
+ * @group Query Tools
3683
+ */
3684
+ const remove = (query, pathOrID) => {
3685
+ const path = Array.isArray(pathOrID) ? pathOrID : getPathOfID(pathOrID, query);
3686
+ if (!path) return query;
3687
+ if (path.length === 0 || !isRuleGroupType(query) && !findPath(path, query)) return query;
3688
+ return produce(query, (draft) => {
3689
+ const index = path.at(-1);
3690
+ const parent = findPath(getParentPath(path), draft);
3691
+ if (parent && isRuleGroup(parent)) if (!isRuleGroupType(parent) && parent.rules.length > 1) {
3692
+ const idxStartDelete = index === 0 ? 0 : index - 1;
3693
+ parent.rules.splice(idxStartDelete, 2);
3694
+ } else parent.rules.splice(index, 1);
3695
+ });
3696
+ };
3697
+ const getNextPath = (query, currentPath, newPathOrShiftDirection) => {
3698
+ if (Array.isArray(newPathOrShiftDirection)) return newPathOrShiftDirection;
3699
+ const ic = isRuleGroupTypeIC(query);
3700
+ if (newPathOrShiftDirection === "up") if (pathsAreEqual(currentPath, [0])) return currentPath;
3701
+ else if (currentPath.at(-1) === 0) {
3702
+ const parentPath = getParentPath(currentPath);
3703
+ return [...getParentPath(parentPath), Math.max(0, parentPath.at(-1) - (ic ? 1 : 0))];
3704
+ } else {
3705
+ const evaluationPath = [...getParentPath(currentPath), Math.max(0, currentPath.at(-1) - (ic ? 2 : 1))];
3706
+ const entityAtTarget = findPath(evaluationPath, query);
3707
+ if (isRuleGroup(entityAtTarget)) return [...evaluationPath, entityAtTarget.rules.length];
3708
+ else return [...getParentPath(currentPath), Math.max(0, currentPath.at(-1) - (ic ? 3 : 1))];
3709
+ }
3710
+ else if (newPathOrShiftDirection === "down") if (pathsAreEqual([query.rules.length - 1], currentPath)) return currentPath;
3711
+ else if (currentPath.at(-1) === findPath(getParentPath(currentPath), query).rules.length - 1) {
3712
+ const parentPath = getParentPath(currentPath);
3713
+ return [...getParentPath(parentPath), parentPath.at(-1) + 1];
3714
+ } else {
3715
+ const evaluationPath = [...getParentPath(currentPath), currentPath.at(-1) + (ic ? 2 : 1)];
3716
+ const entityToEvaluate = findPath(evaluationPath, query);
3717
+ if (isRuleGroup(entityToEvaluate)) return [...evaluationPath, 0];
3718
+ else return [...getParentPath(currentPath), currentPath.at(-1) + (ic ? 3 : 2)];
3719
+ }
3720
+ return currentPath;
3721
+ };
3722
+ /**
3723
+ * Moves a rule or group from one path to another. In the options parameter, pass
3724
+ * `{ clone: true }` to copy instead of move.
3725
+ * @returns The new query with the rule or group moved or cloned.
3726
+ *
3727
+ * @group Query Tools
3728
+ */
3729
+ const move = (query, oldPathOrID, newPath, { clone = false, combinators = defaultCombinators, idGenerator = generateID } = {}) => {
3730
+ const oldPath = Array.isArray(oldPathOrID) ? oldPathOrID : getPathOfID(oldPathOrID, query);
3731
+ if (!oldPath) return query;
3732
+ const nextPath = getNextPath(query, oldPath, newPath);
3733
+ if (oldPath.length === 0 || pathsAreEqual(oldPath, nextPath) || !findPath(getParentPath(nextPath), query)) return query;
3734
+ const ruleOrGroupOriginal = findPath(oldPath, query);
3735
+ if (!ruleOrGroupOriginal) return query;
3736
+ const ruleOrGroup = clone ? regenerateIDs(ruleOrGroupOriginal, { idGenerator }) : ruleOrGroupOriginal;
3737
+ return produce(query, (draft) => {
3738
+ const independentCombinators = isRuleGroupTypeIC(draft);
3739
+ const parentOfRuleToRemove = findPath(getParentPath(oldPath), draft);
3740
+ const ruleToRemoveIndex = oldPath.at(-1);
3741
+ const oldPrevCombinator = independentCombinators && ruleToRemoveIndex > 0 ? parentOfRuleToRemove.rules[ruleToRemoveIndex - 1] : null;
3742
+ const oldNextCombinator = independentCombinators && ruleToRemoveIndex < parentOfRuleToRemove.rules.length - 1 ? parentOfRuleToRemove.rules[ruleToRemoveIndex + 1] : null;
3743
+ if (!clone) {
3744
+ const idxStartDelete = independentCombinators ? Math.max(0, ruleToRemoveIndex - 1) : ruleToRemoveIndex;
3745
+ const deleteLength = independentCombinators ? 2 : 1;
3746
+ parentOfRuleToRemove.rules.splice(idxStartDelete, deleteLength);
3747
+ }
3748
+ const newNewPath = [...nextPath];
3749
+ const commonAncestorPath = getCommonAncestorPath(oldPath, nextPath);
3750
+ if (!clone && oldPath.length === commonAncestorPath.length + 1 && nextPath[commonAncestorPath.length] > oldPath[commonAncestorPath.length]) newNewPath[commonAncestorPath.length] -= independentCombinators ? 2 : 1;
3751
+ const newNewParentPath = getParentPath(newNewPath);
3752
+ const parentToInsertInto = findPath(newNewParentPath, draft);
3753
+ const newIndex = newNewPath.at(-1);
3754
+ /**
3755
+ * This function 1) glosses over the need for type assertions to splice directly
3756
+ * into `parentToInsertInto.rules`, and 2) shortens the actual insertion code.
3757
+ */
3758
+ const insertRuleOrGroup = (...args) => parentToInsertInto.rules.splice(newIndex, 0, ...args);
3759
+ if (parentToInsertInto.rules.length === 0 || !independentCombinators) insertRuleOrGroup(ruleOrGroup);
3760
+ else if (newIndex === 0) if (ruleToRemoveIndex === 0 && oldNextCombinator) insertRuleOrGroup(ruleOrGroup, oldNextCombinator);
3761
+ else {
3762
+ const newNextCombinator = parentToInsertInto.rules[1] ?? oldPrevCombinator ?? getFirstOption(combinators);
3763
+ insertRuleOrGroup(ruleOrGroup, newNextCombinator);
3764
+ }
3765
+ else if (oldPrevCombinator) insertRuleOrGroup(oldPrevCombinator, ruleOrGroup);
3766
+ else {
3767
+ const newPrevCombinator = parentToInsertInto.rules[newIndex - 2] ?? oldNextCombinator ?? getFirstOption(combinators);
3768
+ insertRuleOrGroup(newPrevCombinator, ruleOrGroup);
3769
+ }
3770
+ });
3771
+ };
3772
+ /**
3773
+ * Inserts a rule or group into a query.
3774
+ * @returns The new query with the rule or group inserted.
3775
+ *
3776
+ * @group Query Tools
3777
+ */
3778
+ const insert = (query, ruleOrGroup, path, { combinators = defaultCombinators, combinatorPreceding, combinatorSucceeding, idGenerator = generateID, replace = false } = {}) => produce(query, (draft) => {
3779
+ const parentToInsertInto = findPath(getParentPath(path), draft);
3780
+ if (!parentToInsertInto || !isRuleGroup(parentToInsertInto)) return;
3781
+ const rorg = regenerateIDs(ruleOrGroup, { idGenerator });
3782
+ const independentCombinators = isRuleGroupTypeIC(draft);
3783
+ const newIndex = path.at(-1);
3784
+ /**
3785
+ * This function 1) glosses over the need for type assertions to splice directly
3786
+ * into `parentToInsertInto.rules`, and 2) shortens the actual insertion code.
3787
+ */
3788
+ const insertRuleOrGroup = (idx, ...args) => parentToInsertInto.rules.splice(idx, replace ? args.length : 0, ...args);
3789
+ if (parentToInsertInto.rules.length === 0 || !independentCombinators) insertRuleOrGroup(newIndex, rorg);
3790
+ else if (replace && independentCombinators) insertRuleOrGroup(newIndex + newIndex % 2, rorg);
3791
+ else if (newIndex === 0) if (rorg.path?.at(-1) === 0 && combinatorSucceeding) insertRuleOrGroup(newIndex, rorg, combinatorSucceeding);
3792
+ else {
3793
+ const newNextCombinator = parentToInsertInto.rules[1] ?? combinatorPreceding ?? getFirstOption(combinators);
3794
+ insertRuleOrGroup(newIndex, rorg, newNextCombinator);
3795
+ }
3796
+ else {
3797
+ const normalizedNewIndex = newIndex % 2 === 0 ? newIndex - 1 : newIndex;
3798
+ if (combinatorPreceding) insertRuleOrGroup(normalizedNewIndex, combinatorPreceding, rorg);
3799
+ else {
3800
+ const newPrevCombinator = parentToInsertInto.rules[normalizedNewIndex - 2] ?? combinatorSucceeding ?? getFirstOption(combinators);
3801
+ insertRuleOrGroup(normalizedNewIndex, newPrevCombinator, rorg);
3802
+ }
3803
+ }
3804
+ });
3805
+ /**
3806
+ * Creates a new group at a target path with its `rules` array containing the current
3807
+ * objects at the target path and the source path. In the options parameter, pass
3808
+ * `{ clone: true }` to copy the source rule/group instead of move.
3809
+ *
3810
+ * @returns The new query with the rules or groups grouped.
3811
+ *
3812
+ * @group Query Tools
3813
+ */
3814
+ const group = (query, sourcePathOrID, targetPathOrID, { clone = false, combinators = defaultCombinators, idGenerator = generateID } = {}) => {
3815
+ const sourcePath = Array.isArray(sourcePathOrID) ? sourcePathOrID : getPathOfID(sourcePathOrID, query);
3816
+ const targetPath = Array.isArray(targetPathOrID) ? targetPathOrID : getPathOfID(targetPathOrID, query);
3817
+ if (!sourcePath || !targetPath) return query;
3818
+ const nextPath = getNextPath(query, sourcePath, targetPath);
3819
+ if (sourcePath.length === 0 || pathsAreEqual(sourcePath, nextPath) || !findPath(getParentPath(nextPath), query)) return query;
3820
+ const sourceRuleOrGroupOriginal = findPath(sourcePath, query);
3821
+ const targetRuleOrGroup = findPath(targetPath, query);
3822
+ if (!sourceRuleOrGroupOriginal || !targetRuleOrGroup) return query;
3823
+ const sourceRuleOrGroup = clone ? regenerateIDs(sourceRuleOrGroupOriginal, { idGenerator }) : sourceRuleOrGroupOriginal;
3824
+ return produce(query, (draft) => {
3825
+ const independentCombinators = isRuleGroupTypeIC(draft);
3826
+ const parentOfRuleToRemove = findPath(getParentPath(sourcePath), draft);
3827
+ const ruleToRemoveIndex = sourcePath.at(-1);
3828
+ if (!clone) {
3829
+ const idxStartDelete = independentCombinators ? Math.max(0, ruleToRemoveIndex - 1) : ruleToRemoveIndex;
3830
+ const deleteLength = independentCombinators ? 2 : 1;
3831
+ parentOfRuleToRemove.rules.splice(idxStartDelete, deleteLength);
3832
+ }
3833
+ const newNewPath = [...nextPath];
3834
+ const commonAncestorPath = getCommonAncestorPath(sourcePath, nextPath);
3835
+ if (!clone && sourcePath.length === commonAncestorPath.length + 1 && nextPath[commonAncestorPath.length] > sourcePath[commonAncestorPath.length]) newNewPath[commonAncestorPath.length] -= independentCombinators ? 2 : 1;
3836
+ const newNewParentPath = getParentPath(newNewPath);
3837
+ const parentOfTargetPath = findPath(newNewParentPath, draft);
3838
+ const targetPathIndex = newNewPath.at(-1);
3839
+ parentOfTargetPath.rules.splice(targetPathIndex, 1, prepareRuleOrGroup(independentCombinators ? { rules: [
3840
+ targetRuleOrGroup,
3841
+ getFirstOption(combinators),
3842
+ sourceRuleOrGroup
3843
+ ] } : {
3844
+ combinator: getFirstOption(combinators),
3845
+ rules: [targetRuleOrGroup, sourceRuleOrGroup]
3846
+ }, { idGenerator }));
3847
+ });
3848
+ };
3849
+
3850
+ //#endregion
3851
+ export { LogType, TestID, add, bigIntJsonParseReviver, bigIntJsonStringifyReplacer, celCombinatorMap, clsx, convertFromIC, convertQuery, convertToIC, defaultCELValueProcessor, defaultCombinatorLabelMap, defaultCombinators, defaultCombinatorsExtended, defaultControlClassnames, defaultExportOperatorMap, defaultJoinChar, defaultMatchModes, defaultMongoDBValueProcessor, defaultNLTranslations, defaultOperatorLabelMap, defaultOperatorNegationMap, defaultOperatorProcessorNL, defaultOperatorProcessorSQL, defaultOperators, defaultPlaceholderFieldGroupLabel, defaultPlaceholderFieldLabel, defaultPlaceholderFieldName, defaultPlaceholderLabel, defaultPlaceholderName, defaultPlaceholderOperatorGroupLabel, defaultPlaceholderOperatorLabel, defaultPlaceholderOperatorName, defaultPlaceholderValueGroupLabel, defaultPlaceholderValueLabel, defaultPlaceholderValueName, 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, defaultValidator, defaultValueProcessor, defaultValueProcessorByRule, defaultValueProcessorCELByRule, defaultValueProcessorMongoDBByRule, defaultValueProcessorNL, defaultValueProcessorSpELByRule, filterFieldsByComparator, findID, findPath, formatQuery, formatQueryOptionPresets, generateAccessibleDescription, generateID, getCommonAncestorPath, getFirstOption, getMatchModesUtil, getNLTranslataion, getOption, getParentPath, getParseNumberMethod, getPathOfID, getQuoteFieldNamesWithArray, getQuotedFieldName, getValidationClassNames, getValueSourcesUtil, group, groupInvalidReasons, insert, isAncestor, isFlexibleOptionArray, isFlexibleOptionGroupArray, isFullOptionArray, isFullOptionGroupArray, isOptionGroupArray, isPojo, isRuleGroup, isRuleGroupType, isRuleGroupTypeIC, isRuleOrGroupValid, isValidValue, isValidationResult, isValueProcessorLegacy, joinWith, jsonLogicAdditionalOperators, lc, mapSQLOperator, mergeClassnames, mongoDbFallback, mongoOperators, move, normalizeConstituentWordOrder, nullFreeArray, nullOrUndefinedOrEmpty, numericRegex, numerifyValues, objectEntries, objectKeys, parseNumber, pathIsDisabled, pathsAreEqual, prepareRule, prepareRuleGroup, prepareRuleOrGroup, prismaFallback, prismaOperators, processMatchMode, regenerateID, regenerateIDs, remove, rootPath, shouldRenderAsNumber, splitBy, sqlDialectPresets, standardClassnames, toArray, toFlatOptionArray, toFullOption, toFullOptionList, toFullOptionMap, transformQuery, trimIfString, uniqByIdentifier, uniqByName, uniqOptGroups, uniqOptList, update };
3852
+ //# sourceMappingURL=react-querybuilder_core.mjs.map