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