@builder6/query-mongodb 0.6.1
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/LICENSE +201 -0
- package/README.md +37 -0
- package/dist/index.js +272 -0
- package/dist/index.test.js +1941 -0
- package/dist/options.js +420 -0
- package/dist/options.test.js +960 -0
- package/dist/pipelines.js +751 -0
- package/dist/pipelines.test.js +782 -0
- package/dist/utils.js +45 -0
- package/dist/utils.test.js +36 -0
- package/index.js +1 -0
- package/options.js +1 -0
- package/package.json +60 -0
- package/src/index.js +497 -0
- package/src/index.test.js +2333 -0
- package/src/options.js +573 -0
- package/src/options.test.js +1112 -0
- package/src/pipelines.js +760 -0
- package/src/pipelines.test.js +1300 -0
- package/src/utils.js +33 -0
- package/src/utils.test.js +40 -0
package/src/options.js
ADDED
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
//const valueFixers = require('value-fixers');
|
|
2
|
+
const yup = require('yup');
|
|
3
|
+
|
|
4
|
+
var regexBool = /(true|false)/i;
|
|
5
|
+
|
|
6
|
+
function OptionError(message = '') {
|
|
7
|
+
this.name = 'OptionError';
|
|
8
|
+
this.message = message;
|
|
9
|
+
}
|
|
10
|
+
OptionError.prototype = Error.prototype;
|
|
11
|
+
|
|
12
|
+
const asBool = (v) => {
|
|
13
|
+
let match;
|
|
14
|
+
if (typeof v === 'string' && (match = v.match(regexBool))) {
|
|
15
|
+
return {
|
|
16
|
+
true: true,
|
|
17
|
+
false: false,
|
|
18
|
+
}[match[0].toLowerCase()];
|
|
19
|
+
} else return !!v;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function fixFilterAndSearch(schema) {
|
|
23
|
+
// schema can be
|
|
24
|
+
// {
|
|
25
|
+
// fieldName1: 'int',
|
|
26
|
+
// fieldName2: 'float',
|
|
27
|
+
// fieldName3: 'datetime'
|
|
28
|
+
// }
|
|
29
|
+
|
|
30
|
+
const operators = ['=', '<>', '>', '>=', '<', '<='];
|
|
31
|
+
|
|
32
|
+
function fixValue(type, value) {
|
|
33
|
+
return {
|
|
34
|
+
int: parseInt,
|
|
35
|
+
float: parseFloat,
|
|
36
|
+
datetime: (v) => new Date(v),
|
|
37
|
+
bool: asBool,
|
|
38
|
+
}[type](value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function fixFilter(f) {
|
|
42
|
+
if (!f || !Array.isArray(f)) return f;
|
|
43
|
+
if (
|
|
44
|
+
f.length === 3 &&
|
|
45
|
+
typeof f[2] === 'string' &&
|
|
46
|
+
schema[f[0]] &&
|
|
47
|
+
operators.includes(f[1])
|
|
48
|
+
)
|
|
49
|
+
return [f[0], f[1], fixValue(schema[f[0]], f[2])];
|
|
50
|
+
else return f.map((e) => fixFilter(e));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// According to https://js.devexpress.com/Documentation/ApiReference/Data_Layer/DataSource/Configuration/#searchExpr
|
|
54
|
+
// it is possible to pass an array of field values for searchExpr: ["firstName", "lastName"]
|
|
55
|
+
// For "fixing" purposes, we need to assume that all such fields have the same
|
|
56
|
+
// type. So if an array is passed for searchExpr (se), we simply look for the
|
|
57
|
+
// first item in that array with a corresponding schema entry and use this
|
|
58
|
+
// going forward. If you have fields in this array which are defined in the
|
|
59
|
+
// schema to have different types, then that's your mistake.
|
|
60
|
+
|
|
61
|
+
function fixSearch(se, so, sv) {
|
|
62
|
+
if (!se || !so || !sv || typeof sv !== 'string') return sv;
|
|
63
|
+
const fieldName =
|
|
64
|
+
typeof se === 'string'
|
|
65
|
+
? schema[se]
|
|
66
|
+
: Array.isArray(se)
|
|
67
|
+
? se.find((e) => (schema[e] ? e : null))
|
|
68
|
+
: null;
|
|
69
|
+
return fieldName ? fixValue(schema[fieldName], sv) : sv;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return (qry) => {
|
|
73
|
+
if (!qry) return qry;
|
|
74
|
+
const fixedFilter = fixFilter(parse(qry.filter));
|
|
75
|
+
const fixedSearchValue = fixSearch(
|
|
76
|
+
qry.searchExpr,
|
|
77
|
+
qry.searchOperation,
|
|
78
|
+
qry.searchValue
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return Object.assign(
|
|
82
|
+
{},
|
|
83
|
+
qry,
|
|
84
|
+
fixedFilter
|
|
85
|
+
? {
|
|
86
|
+
filter: fixedFilter,
|
|
87
|
+
}
|
|
88
|
+
: {},
|
|
89
|
+
fixedSearchValue
|
|
90
|
+
? {
|
|
91
|
+
searchValue: fixedSearchValue,
|
|
92
|
+
}
|
|
93
|
+
: {}
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const wrapYupChecker = (yupChecker) => ({
|
|
99
|
+
validate: (o) => {
|
|
100
|
+
try {
|
|
101
|
+
yupChecker.validateSync(o, { strict: true });
|
|
102
|
+
return null;
|
|
103
|
+
} catch (e) {
|
|
104
|
+
return e;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const sortOptionsCheckerYup = yup
|
|
110
|
+
.object()
|
|
111
|
+
.shape({
|
|
112
|
+
desc: yup.bool().required(),
|
|
113
|
+
selector: yup.string().required(),
|
|
114
|
+
// Old note - needs rechecking.
|
|
115
|
+
// isExpanded doesn't make any sense with sort, but the grid seems
|
|
116
|
+
// to include it occasionally - probably a bug
|
|
117
|
+
// Btw, this has always been without type restriction - could probably
|
|
118
|
+
// be bool.
|
|
119
|
+
isExpanded: yup.mixed(),
|
|
120
|
+
})
|
|
121
|
+
.noUnknown();
|
|
122
|
+
|
|
123
|
+
const sortOptionsChecker = wrapYupChecker(sortOptionsCheckerYup);
|
|
124
|
+
|
|
125
|
+
// Based on sample code
|
|
126
|
+
// from https://codesandbox.io/s/example-with-or-validate-for-yup-nodelete-dgm4l?file=/src/index.js:29-497
|
|
127
|
+
// from https://github.com/jquense/yup/issues/743
|
|
128
|
+
yup.addMethod(yup.mixed, 'or', function (schemas, msg) {
|
|
129
|
+
return this.test({
|
|
130
|
+
name: 'or',
|
|
131
|
+
message: "Can't find valid schema" || msg,
|
|
132
|
+
test: (value) => {
|
|
133
|
+
if (!Array.isArray(schemas))
|
|
134
|
+
throw new OptionError('"or" requires schema array');
|
|
135
|
+
|
|
136
|
+
const results = schemas.map((schema) =>
|
|
137
|
+
schema.isValidSync(value, { strict: true })
|
|
138
|
+
);
|
|
139
|
+
return results.some((res) => !!res);
|
|
140
|
+
},
|
|
141
|
+
exclusive: false,
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const groupOptionsCheckerYup = yup
|
|
146
|
+
.object()
|
|
147
|
+
.shape({
|
|
148
|
+
selector: yup.string().required(),
|
|
149
|
+
desc: yup.bool(),
|
|
150
|
+
isExpanded: yup.bool(),
|
|
151
|
+
groupInterval: yup
|
|
152
|
+
.mixed()
|
|
153
|
+
.or([
|
|
154
|
+
yup.number().integer(),
|
|
155
|
+
yup
|
|
156
|
+
.mixed()
|
|
157
|
+
.oneOf([
|
|
158
|
+
'year',
|
|
159
|
+
'quarter',
|
|
160
|
+
'month',
|
|
161
|
+
'day',
|
|
162
|
+
'dayOfWeek',
|
|
163
|
+
'hour',
|
|
164
|
+
'minute',
|
|
165
|
+
'second',
|
|
166
|
+
]),
|
|
167
|
+
]),
|
|
168
|
+
})
|
|
169
|
+
.noUnknown();
|
|
170
|
+
|
|
171
|
+
const groupOptionsChecker = wrapYupChecker(groupOptionsCheckerYup);
|
|
172
|
+
|
|
173
|
+
const summaryOptionsCheckerYup = yup
|
|
174
|
+
.object()
|
|
175
|
+
.shape({
|
|
176
|
+
summaryType: yup
|
|
177
|
+
.mixed()
|
|
178
|
+
.oneOf(['sum', 'avg', 'min', 'max', 'count'])
|
|
179
|
+
.required(),
|
|
180
|
+
selector: yup.string(),
|
|
181
|
+
})
|
|
182
|
+
.noUnknown();
|
|
183
|
+
|
|
184
|
+
const summaryOptionsChecker = wrapYupChecker(summaryOptionsCheckerYup);
|
|
185
|
+
|
|
186
|
+
function validateAll(list, checker, short = true) {
|
|
187
|
+
return list.reduce(
|
|
188
|
+
(r, v) => {
|
|
189
|
+
if (short && !r.valid) return r; // short circuiting
|
|
190
|
+
const newr = checker.validate(v);
|
|
191
|
+
if (newr) {
|
|
192
|
+
r.errors.push(newr);
|
|
193
|
+
r.valid = false;
|
|
194
|
+
}
|
|
195
|
+
return r;
|
|
196
|
+
},
|
|
197
|
+
{ valid: true, errors: [] }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function parse(arg, canBeString = false) {
|
|
202
|
+
let ob = arg;
|
|
203
|
+
if (typeof arg === 'string') {
|
|
204
|
+
try {
|
|
205
|
+
ob = JSON.parse(arg);
|
|
206
|
+
} catch (e) {
|
|
207
|
+
if (!canBeString) throw new OptionError(e.message);
|
|
208
|
+
return arg;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return ob;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function representsTrue(val) {
|
|
215
|
+
return val === true || val === 'true';
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function wrapLoadOptions(lo) {
|
|
219
|
+
return {
|
|
220
|
+
loadOptions: lo,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function wrapProcessingOptions(po) {
|
|
225
|
+
return {
|
|
226
|
+
processingOptions: po,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function check(
|
|
231
|
+
qry,
|
|
232
|
+
onames,
|
|
233
|
+
checker,
|
|
234
|
+
converter = (v /*, vname*/) => v,
|
|
235
|
+
defaultValue = {},
|
|
236
|
+
wrapper = wrapLoadOptions
|
|
237
|
+
) {
|
|
238
|
+
const options = typeof onames === 'string' ? [onames] : onames;
|
|
239
|
+
const allFound = qry && options.reduce((r, v) => r && !!qry[v], true);
|
|
240
|
+
|
|
241
|
+
if (!allFound) return defaultValue;
|
|
242
|
+
try {
|
|
243
|
+
const vals = options.map((o) => converter(qry[o], o));
|
|
244
|
+
|
|
245
|
+
const checkResult = checker(...vals);
|
|
246
|
+
|
|
247
|
+
// It's currently not possible to return per-value errors
|
|
248
|
+
// If something goes wrong, all tested options will be highlighted
|
|
249
|
+
// as errors at the same time.
|
|
250
|
+
return checkResult
|
|
251
|
+
? wrapper(checkResult)
|
|
252
|
+
: {
|
|
253
|
+
errors: options.map((o) => `Invalid '${o}': ${qry[o]}`),
|
|
254
|
+
};
|
|
255
|
+
} catch (err) {
|
|
256
|
+
//console.log('Error caught in check: ' + JSON.stringify(err));
|
|
257
|
+
//console.log('Error message in check: ' + err.message);
|
|
258
|
+
return {
|
|
259
|
+
errors: [err],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function takeOptions(qry) {
|
|
265
|
+
return check(
|
|
266
|
+
qry,
|
|
267
|
+
'take',
|
|
268
|
+
(take) =>
|
|
269
|
+
take >= 0
|
|
270
|
+
? {
|
|
271
|
+
take,
|
|
272
|
+
}
|
|
273
|
+
: null,
|
|
274
|
+
(take) => parseInt(take)
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function skipOptions(qry) {
|
|
279
|
+
return check(
|
|
280
|
+
qry,
|
|
281
|
+
'skip',
|
|
282
|
+
(skip) =>
|
|
283
|
+
skip >= 0
|
|
284
|
+
? {
|
|
285
|
+
skip,
|
|
286
|
+
}
|
|
287
|
+
: null,
|
|
288
|
+
(skip) => parseInt(skip)
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function totalCountOptions(qry) {
|
|
293
|
+
return check(
|
|
294
|
+
qry,
|
|
295
|
+
'requireTotalCount',
|
|
296
|
+
(requireTotalCount) => ({
|
|
297
|
+
requireTotalCount,
|
|
298
|
+
}),
|
|
299
|
+
(requireTotalCount) => representsTrue(requireTotalCount)
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function sortOptions(qry) {
|
|
304
|
+
return check(
|
|
305
|
+
qry,
|
|
306
|
+
'sort',
|
|
307
|
+
(sort) => {
|
|
308
|
+
const sortOptions = parse(sort);
|
|
309
|
+
if (Array.isArray(sortOptions) && sortOptions.length > 0) {
|
|
310
|
+
const vr = validateAll(sortOptions, sortOptionsChecker);
|
|
311
|
+
if (vr.valid)
|
|
312
|
+
return {
|
|
313
|
+
sort: sortOptions,
|
|
314
|
+
};
|
|
315
|
+
else {
|
|
316
|
+
//console.log('Error string generated in sortOptions: ' + JSON.stringify(vr.errors));
|
|
317
|
+
throw new OptionError(
|
|
318
|
+
`Sort parameter validation errors: ${JSON.stringify(vr.errors)}`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
} else return null;
|
|
322
|
+
},
|
|
323
|
+
(sort) => {
|
|
324
|
+
const sortOptions = parse(sort);
|
|
325
|
+
if (Array.isArray(sortOptions)) {
|
|
326
|
+
return sortOptions.map((s) => ({ ...s, desc: representsTrue(s.desc) }));
|
|
327
|
+
} else return sort;
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function groupOptions(qry) {
|
|
333
|
+
return check(
|
|
334
|
+
qry,
|
|
335
|
+
'group',
|
|
336
|
+
(group) => {
|
|
337
|
+
const groupOptions = parse(group);
|
|
338
|
+
if (Array.isArray(groupOptions)) {
|
|
339
|
+
if (groupOptions.length > 0) {
|
|
340
|
+
const vr = validateAll(groupOptions, groupOptionsChecker);
|
|
341
|
+
if (vr.valid)
|
|
342
|
+
return mergeResults([
|
|
343
|
+
wrapLoadOptions({
|
|
344
|
+
group: groupOptions,
|
|
345
|
+
}),
|
|
346
|
+
check(
|
|
347
|
+
qry,
|
|
348
|
+
'requireGroupCount',
|
|
349
|
+
(requireGroupCount) => ({
|
|
350
|
+
requireGroupCount,
|
|
351
|
+
}),
|
|
352
|
+
(requireGroupCount) => representsTrue(requireGroupCount)
|
|
353
|
+
),
|
|
354
|
+
check(qry, 'groupSummary', (groupSummary) => {
|
|
355
|
+
const gsOptions = parse(groupSummary);
|
|
356
|
+
if (Array.isArray(gsOptions)) {
|
|
357
|
+
if (gsOptions.length > 0) {
|
|
358
|
+
const vr = validateAll(gsOptions, summaryOptionsChecker);
|
|
359
|
+
if (vr.valid)
|
|
360
|
+
return {
|
|
361
|
+
groupSummary: gsOptions,
|
|
362
|
+
};
|
|
363
|
+
else
|
|
364
|
+
throw new OptionError(
|
|
365
|
+
`Group summary parameter validation errors: ${JSON.stringify(
|
|
366
|
+
vr.errors
|
|
367
|
+
)}`
|
|
368
|
+
);
|
|
369
|
+
} else return {}; // ignore empty array
|
|
370
|
+
} else return null;
|
|
371
|
+
}),
|
|
372
|
+
]);
|
|
373
|
+
else
|
|
374
|
+
throw new OptionError(
|
|
375
|
+
`Group parameter validation errors: ${JSON.stringify(vr.errors)}`
|
|
376
|
+
);
|
|
377
|
+
} else return {}; // ignore empty array
|
|
378
|
+
} else return null;
|
|
379
|
+
},
|
|
380
|
+
(group) => {
|
|
381
|
+
const groupOptions = parse(group);
|
|
382
|
+
if (Array.isArray(groupOptions)) {
|
|
383
|
+
return groupOptions.map((g) => ({
|
|
384
|
+
...g,
|
|
385
|
+
isExpanded: representsTrue(g.isExpanded),
|
|
386
|
+
}));
|
|
387
|
+
} else return group;
|
|
388
|
+
},
|
|
389
|
+
undefined,
|
|
390
|
+
(o) => o /* deactivate wrapper for the result */
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function totalSummaryOptions(qry) {
|
|
395
|
+
return check(qry, 'totalSummary', (totalSummary) => {
|
|
396
|
+
const tsOptions = parse(totalSummary);
|
|
397
|
+
if (Array.isArray(tsOptions)) {
|
|
398
|
+
if (tsOptions.length > 0) {
|
|
399
|
+
const vr = validateAll(tsOptions, summaryOptionsChecker);
|
|
400
|
+
if (vr.valid)
|
|
401
|
+
return {
|
|
402
|
+
totalSummary: tsOptions,
|
|
403
|
+
};
|
|
404
|
+
else
|
|
405
|
+
throw new OptionError(
|
|
406
|
+
`Total summary parameter validation errors: ${JSON.stringify(
|
|
407
|
+
vr.errors
|
|
408
|
+
)}`
|
|
409
|
+
);
|
|
410
|
+
} else return {}; // ignore empty array
|
|
411
|
+
} else return null;
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function filterOptions(qry) {
|
|
416
|
+
return check(qry, 'filter', (filter) => {
|
|
417
|
+
const filterOptions = parse(filter, true);
|
|
418
|
+
if (typeof filterOptions === 'string' || Array.isArray(filterOptions))
|
|
419
|
+
return {
|
|
420
|
+
filter: filterOptions,
|
|
421
|
+
};
|
|
422
|
+
else return null;
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function searchOptions(qry) {
|
|
427
|
+
return check(
|
|
428
|
+
qry,
|
|
429
|
+
['searchExpr', 'searchOperation', 'searchValue'],
|
|
430
|
+
(se, so, sv) => {
|
|
431
|
+
if (typeof se === 'string' || Array.isArray(se))
|
|
432
|
+
return {
|
|
433
|
+
searchExpr: se,
|
|
434
|
+
searchOperation: so,
|
|
435
|
+
searchValue: sv,
|
|
436
|
+
};
|
|
437
|
+
else return null;
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function selectOptions(qry) {
|
|
443
|
+
return check(qry, 'select', (select) => {
|
|
444
|
+
const selectOptions = parse(select, true);
|
|
445
|
+
if (typeof selectOptions === 'string')
|
|
446
|
+
return {
|
|
447
|
+
select: [selectOptions],
|
|
448
|
+
};
|
|
449
|
+
else if (Array.isArray(selectOptions)) {
|
|
450
|
+
if (selectOptions.length > 0) {
|
|
451
|
+
if (selectOptions.reduce((r, v) => r && typeof v === 'string'))
|
|
452
|
+
return {
|
|
453
|
+
select: selectOptions,
|
|
454
|
+
};
|
|
455
|
+
else
|
|
456
|
+
throw new OptionError(
|
|
457
|
+
`Select array parameter has invalid content: ${JSON.stringify(
|
|
458
|
+
selectOptions
|
|
459
|
+
)}`
|
|
460
|
+
);
|
|
461
|
+
} else return {}; // ignore empty array
|
|
462
|
+
} else return null;
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function timezoneOptions(qry) {
|
|
467
|
+
return check(
|
|
468
|
+
qry,
|
|
469
|
+
'tzOffset',
|
|
470
|
+
(tzOffset) => ({
|
|
471
|
+
timezoneOffset: parseInt(tzOffset) || 0,
|
|
472
|
+
}),
|
|
473
|
+
(v) => v,
|
|
474
|
+
{
|
|
475
|
+
timezoneOffset: 0,
|
|
476
|
+
},
|
|
477
|
+
wrapProcessingOptions
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function caseInsensitiveRegexOptions(qry) {
|
|
482
|
+
return check(
|
|
483
|
+
qry,
|
|
484
|
+
'caseInsensitiveRegex',
|
|
485
|
+
(caseInsensitiveRegex) => ({
|
|
486
|
+
caseInsensitiveRegex,
|
|
487
|
+
}),
|
|
488
|
+
(caseInsensitiveRegex) => representsTrue(caseInsensitiveRegex),
|
|
489
|
+
{ caseInsensitiveRegex: true },
|
|
490
|
+
wrapProcessingOptions
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function summaryQueryLimitOptions(qry) {
|
|
495
|
+
return check(
|
|
496
|
+
qry,
|
|
497
|
+
'summaryQueryLimit',
|
|
498
|
+
(sql) =>
|
|
499
|
+
sql >= 0
|
|
500
|
+
? {
|
|
501
|
+
summaryQueryLimit: sql,
|
|
502
|
+
}
|
|
503
|
+
: {},
|
|
504
|
+
(sql) => parseInt(sql),
|
|
505
|
+
{},
|
|
506
|
+
wrapProcessingOptions
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function mergeResults(results) {
|
|
511
|
+
return results.reduce(
|
|
512
|
+
(r, v) => ({
|
|
513
|
+
loadOptions: {
|
|
514
|
+
...(r.loadOptions || {}),
|
|
515
|
+
...(v.loadOptions || {}),
|
|
516
|
+
},
|
|
517
|
+
processingOptions: {
|
|
518
|
+
...(r.processingOptions || {}),
|
|
519
|
+
...(v.processingOptions || {}),
|
|
520
|
+
},
|
|
521
|
+
errors: [...(r.errors || []), ...(v.errors || [])],
|
|
522
|
+
}),
|
|
523
|
+
{}
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function getOptions(qry, schema) {
|
|
528
|
+
if (!qry) return undefined;
|
|
529
|
+
|
|
530
|
+
const fixedQry = schema ? fixFilterAndSearch(schema)(qry) : qry;
|
|
531
|
+
|
|
532
|
+
// console.log('Fixed query: ', JSON.stringify(fixedQry, null, 2));
|
|
533
|
+
|
|
534
|
+
return mergeResults(
|
|
535
|
+
[
|
|
536
|
+
takeOptions,
|
|
537
|
+
skipOptions,
|
|
538
|
+
totalCountOptions,
|
|
539
|
+
sortOptions,
|
|
540
|
+
groupOptions,
|
|
541
|
+
totalSummaryOptions,
|
|
542
|
+
filterOptions,
|
|
543
|
+
searchOptions,
|
|
544
|
+
selectOptions,
|
|
545
|
+
timezoneOptions,
|
|
546
|
+
summaryQueryLimitOptions,
|
|
547
|
+
caseInsensitiveRegexOptions,
|
|
548
|
+
].map((f) => f(fixedQry))
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
module.exports = {
|
|
553
|
+
getOptions,
|
|
554
|
+
private: {
|
|
555
|
+
fixFilterAndSearch,
|
|
556
|
+
validateAll,
|
|
557
|
+
check,
|
|
558
|
+
takeOptions,
|
|
559
|
+
skipOptions,
|
|
560
|
+
totalCountOptions,
|
|
561
|
+
sortOptions,
|
|
562
|
+
groupOptions,
|
|
563
|
+
totalSummaryOptions,
|
|
564
|
+
filterOptions,
|
|
565
|
+
searchOptions,
|
|
566
|
+
selectOptions,
|
|
567
|
+
sortOptionsChecker,
|
|
568
|
+
groupOptionsChecker,
|
|
569
|
+
summaryOptionsChecker,
|
|
570
|
+
asBool,
|
|
571
|
+
parse
|
|
572
|
+
},
|
|
573
|
+
};
|