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