@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.
@@ -0,0 +1,420 @@
1
+ 'use strict';
2
+
3
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
4
+
5
+ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
6
+
7
+ var yup = require('yup');
8
+
9
+ var regexBool = /(true|false)/i;
10
+
11
+ function OptionError() {
12
+ var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
13
+
14
+ this.name = 'OptionError';
15
+ this.message = message;
16
+ }
17
+ OptionError.prototype = Error.prototype;
18
+
19
+ var asBool = function asBool(v) {
20
+ var match = void 0;
21
+ if (typeof v === 'string' && (match = v.match(regexBool))) {
22
+ return {
23
+ true: true,
24
+ false: false
25
+ }[match[0].toLowerCase()];
26
+ } else return !!v;
27
+ };
28
+
29
+ function fixFilterAndSearch(schema) {
30
+
31
+ var operators = ['=', '<>', '>', '>=', '<', '<='];
32
+
33
+ function fixValue(type, value) {
34
+ return {
35
+ int: parseInt,
36
+ float: parseFloat,
37
+ datetime: function datetime(v) {
38
+ return new Date(v);
39
+ },
40
+ bool: asBool
41
+ }[type](value);
42
+ }
43
+
44
+ function fixFilter(f) {
45
+ if (!f || !Array.isArray(f)) return f;
46
+ if (f.length === 3 && typeof f[2] === 'string' && schema[f[0]] && operators.includes(f[1])) return [f[0], f[1], fixValue(schema[f[0]], f[2])];else return f.map(function (e) {
47
+ return fixFilter(e);
48
+ });
49
+ }
50
+
51
+ function fixSearch(se, so, sv) {
52
+ if (!se || !so || !sv || typeof sv !== 'string') return sv;
53
+ var fieldName = typeof se === 'string' ? schema[se] : Array.isArray(se) ? se.find(function (e) {
54
+ return schema[e] ? e : null;
55
+ }) : null;
56
+ return fieldName ? fixValue(schema[fieldName], sv) : sv;
57
+ }
58
+
59
+ return function (qry) {
60
+ if (!qry) return qry;
61
+ var fixedFilter = fixFilter(parse(qry.filter));
62
+ var fixedSearchValue = fixSearch(qry.searchExpr, qry.searchOperation, qry.searchValue);
63
+
64
+ return Object.assign({}, qry, fixedFilter ? {
65
+ filter: fixedFilter
66
+ } : {}, fixedSearchValue ? {
67
+ searchValue: fixedSearchValue
68
+ } : {});
69
+ };
70
+ }
71
+
72
+ var wrapYupChecker = function wrapYupChecker(yupChecker) {
73
+ return {
74
+ validate: function validate(o) {
75
+ try {
76
+ yupChecker.validateSync(o, { strict: true });
77
+ return null;
78
+ } catch (e) {
79
+ return e;
80
+ }
81
+ }
82
+ };
83
+ };
84
+
85
+ var sortOptionsCheckerYup = yup.object().shape({
86
+ desc: yup.bool().required(),
87
+ selector: yup.string().required(),
88
+
89
+ isExpanded: yup.mixed()
90
+ }).noUnknown();
91
+
92
+ var sortOptionsChecker = wrapYupChecker(sortOptionsCheckerYup);
93
+
94
+ yup.addMethod(yup.mixed, 'or', function (schemas, msg) {
95
+ return this.test({
96
+ name: 'or',
97
+ message: "Can't find valid schema" || msg,
98
+ test: function test(value) {
99
+ if (!Array.isArray(schemas)) throw new OptionError('"or" requires schema array');
100
+
101
+ var results = schemas.map(function (schema) {
102
+ return schema.isValidSync(value, { strict: true });
103
+ });
104
+ return results.some(function (res) {
105
+ return !!res;
106
+ });
107
+ },
108
+ exclusive: false
109
+ });
110
+ });
111
+
112
+ var groupOptionsCheckerYup = yup.object().shape({
113
+ selector: yup.string().required(),
114
+ desc: yup.bool(),
115
+ isExpanded: yup.bool(),
116
+ groupInterval: yup.mixed().or([yup.number().integer(), yup.mixed().oneOf(['year', 'quarter', 'month', 'day', 'dayOfWeek', 'hour', 'minute', 'second'])])
117
+ }).noUnknown();
118
+
119
+ var groupOptionsChecker = wrapYupChecker(groupOptionsCheckerYup);
120
+
121
+ var summaryOptionsCheckerYup = yup.object().shape({
122
+ summaryType: yup.mixed().oneOf(['sum', 'avg', 'min', 'max', 'count']).required(),
123
+ selector: yup.string()
124
+ }).noUnknown();
125
+
126
+ var summaryOptionsChecker = wrapYupChecker(summaryOptionsCheckerYup);
127
+
128
+ function validateAll(list, checker) {
129
+ var short = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
130
+
131
+ return list.reduce(function (r, v) {
132
+ if (short && !r.valid) return r;
133
+ var newr = checker.validate(v);
134
+ if (newr) {
135
+ r.errors.push(newr);
136
+ r.valid = false;
137
+ }
138
+ return r;
139
+ }, { valid: true, errors: [] });
140
+ }
141
+
142
+ function parse(arg) {
143
+ var canBeString = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
144
+
145
+ var ob = arg;
146
+ if (typeof arg === 'string') {
147
+ try {
148
+ ob = JSON.parse(arg);
149
+ } catch (e) {
150
+ if (!canBeString) throw new OptionError(e.message);
151
+ return arg;
152
+ }
153
+ }
154
+ return ob;
155
+ }
156
+
157
+ function representsTrue(val) {
158
+ return val === true || val === 'true';
159
+ }
160
+
161
+ function wrapLoadOptions(lo) {
162
+ return {
163
+ loadOptions: lo
164
+ };
165
+ }
166
+
167
+ function wrapProcessingOptions(po) {
168
+ return {
169
+ processingOptions: po
170
+ };
171
+ }
172
+
173
+ function check(qry, onames, checker) {
174
+ var converter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function (v) {
175
+ return v;
176
+ };
177
+ var defaultValue = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
178
+ var wrapper = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : wrapLoadOptions;
179
+
180
+ var options = typeof onames === 'string' ? [onames] : onames;
181
+ var allFound = qry && options.reduce(function (r, v) {
182
+ return r && !!qry[v];
183
+ }, true);
184
+
185
+ if (!allFound) return defaultValue;
186
+ try {
187
+ var vals = options.map(function (o) {
188
+ return converter(qry[o], o);
189
+ });
190
+
191
+ var checkResult = checker.apply(undefined, _toConsumableArray(vals));
192
+
193
+ return checkResult ? wrapper(checkResult) : {
194
+ errors: options.map(function (o) {
195
+ return 'Invalid \'' + o + '\': ' + qry[o];
196
+ })
197
+ };
198
+ } catch (err) {
199
+ return {
200
+ errors: [err]
201
+ };
202
+ }
203
+ }
204
+
205
+ function takeOptions(qry) {
206
+ return check(qry, 'take', function (take) {
207
+ return take >= 0 ? {
208
+ take: take
209
+ } : null;
210
+ }, function (take) {
211
+ return parseInt(take);
212
+ });
213
+ }
214
+
215
+ function skipOptions(qry) {
216
+ return check(qry, 'skip', function (skip) {
217
+ return skip >= 0 ? {
218
+ skip: skip
219
+ } : null;
220
+ }, function (skip) {
221
+ return parseInt(skip);
222
+ });
223
+ }
224
+
225
+ function totalCountOptions(qry) {
226
+ return check(qry, 'requireTotalCount', function (requireTotalCount) {
227
+ return {
228
+ requireTotalCount: requireTotalCount
229
+ };
230
+ }, function (requireTotalCount) {
231
+ return representsTrue(requireTotalCount);
232
+ });
233
+ }
234
+
235
+ function sortOptions(qry) {
236
+ return check(qry, 'sort', function (sort) {
237
+ var sortOptions = parse(sort);
238
+ if (Array.isArray(sortOptions) && sortOptions.length > 0) {
239
+ var vr = validateAll(sortOptions, sortOptionsChecker);
240
+ if (vr.valid) return {
241
+ sort: sortOptions
242
+ };else {
243
+ throw new OptionError('Sort parameter validation errors: ' + JSON.stringify(vr.errors));
244
+ }
245
+ } else return null;
246
+ }, function (sort) {
247
+ var sortOptions = parse(sort);
248
+ if (Array.isArray(sortOptions)) {
249
+ return sortOptions.map(function (s) {
250
+ return _extends({}, s, { desc: representsTrue(s.desc) });
251
+ });
252
+ } else return sort;
253
+ });
254
+ }
255
+
256
+ function groupOptions(qry) {
257
+ return check(qry, 'group', function (group) {
258
+ var groupOptions = parse(group);
259
+ if (Array.isArray(groupOptions)) {
260
+ if (groupOptions.length > 0) {
261
+ var vr = validateAll(groupOptions, groupOptionsChecker);
262
+ if (vr.valid) return mergeResults([wrapLoadOptions({
263
+ group: groupOptions
264
+ }), check(qry, 'requireGroupCount', function (requireGroupCount) {
265
+ return {
266
+ requireGroupCount: requireGroupCount
267
+ };
268
+ }, function (requireGroupCount) {
269
+ return representsTrue(requireGroupCount);
270
+ }), check(qry, 'groupSummary', function (groupSummary) {
271
+ var gsOptions = parse(groupSummary);
272
+ if (Array.isArray(gsOptions)) {
273
+ if (gsOptions.length > 0) {
274
+ var _vr = validateAll(gsOptions, summaryOptionsChecker);
275
+ if (_vr.valid) return {
276
+ groupSummary: gsOptions
277
+ };else throw new OptionError('Group summary parameter validation errors: ' + JSON.stringify(_vr.errors));
278
+ } else return {};
279
+ } else return null;
280
+ })]);else throw new OptionError('Group parameter validation errors: ' + JSON.stringify(vr.errors));
281
+ } else return {};
282
+ } else return null;
283
+ }, function (group) {
284
+ var groupOptions = parse(group);
285
+ if (Array.isArray(groupOptions)) {
286
+ return groupOptions.map(function (g) {
287
+ return _extends({}, g, {
288
+ isExpanded: representsTrue(g.isExpanded)
289
+ });
290
+ });
291
+ } else return group;
292
+ }, undefined, function (o) {
293
+ return o;
294
+ });
295
+ }
296
+
297
+ function totalSummaryOptions(qry) {
298
+ return check(qry, 'totalSummary', function (totalSummary) {
299
+ var tsOptions = parse(totalSummary);
300
+ if (Array.isArray(tsOptions)) {
301
+ if (tsOptions.length > 0) {
302
+ var vr = validateAll(tsOptions, summaryOptionsChecker);
303
+ if (vr.valid) return {
304
+ totalSummary: tsOptions
305
+ };else throw new OptionError('Total summary parameter validation errors: ' + JSON.stringify(vr.errors));
306
+ } else return {};
307
+ } else return null;
308
+ });
309
+ }
310
+
311
+ function filterOptions(qry) {
312
+ return check(qry, 'filter', function (filter) {
313
+ var filterOptions = parse(filter, true);
314
+ if (typeof filterOptions === 'string' || Array.isArray(filterOptions)) return {
315
+ filter: filterOptions
316
+ };else return null;
317
+ });
318
+ }
319
+
320
+ function searchOptions(qry) {
321
+ return check(qry, ['searchExpr', 'searchOperation', 'searchValue'], function (se, so, sv) {
322
+ if (typeof se === 'string' || Array.isArray(se)) return {
323
+ searchExpr: se,
324
+ searchOperation: so,
325
+ searchValue: sv
326
+ };else return null;
327
+ });
328
+ }
329
+
330
+ function selectOptions(qry) {
331
+ return check(qry, 'select', function (select) {
332
+ var selectOptions = parse(select, true);
333
+ if (typeof selectOptions === 'string') return {
334
+ select: [selectOptions]
335
+ };else if (Array.isArray(selectOptions)) {
336
+ if (selectOptions.length > 0) {
337
+ if (selectOptions.reduce(function (r, v) {
338
+ return r && typeof v === 'string';
339
+ })) return {
340
+ select: selectOptions
341
+ };else throw new OptionError('Select array parameter has invalid content: ' + JSON.stringify(selectOptions));
342
+ } else return {};
343
+ } else return null;
344
+ });
345
+ }
346
+
347
+ function timezoneOptions(qry) {
348
+ return check(qry, 'tzOffset', function (tzOffset) {
349
+ return {
350
+ timezoneOffset: parseInt(tzOffset) || 0
351
+ };
352
+ }, function (v) {
353
+ return v;
354
+ }, {
355
+ timezoneOffset: 0
356
+ }, wrapProcessingOptions);
357
+ }
358
+
359
+ function caseInsensitiveRegexOptions(qry) {
360
+ return check(qry, 'caseInsensitiveRegex', function (caseInsensitiveRegex) {
361
+ return {
362
+ caseInsensitiveRegex: caseInsensitiveRegex
363
+ };
364
+ }, function (caseInsensitiveRegex) {
365
+ return representsTrue(caseInsensitiveRegex);
366
+ }, { caseInsensitiveRegex: true }, wrapProcessingOptions);
367
+ }
368
+
369
+ function summaryQueryLimitOptions(qry) {
370
+ return check(qry, 'summaryQueryLimit', function (sql) {
371
+ return sql >= 0 ? {
372
+ summaryQueryLimit: sql
373
+ } : {};
374
+ }, function (sql) {
375
+ return parseInt(sql);
376
+ }, {}, wrapProcessingOptions);
377
+ }
378
+
379
+ function mergeResults(results) {
380
+ return results.reduce(function (r, v) {
381
+ return {
382
+ loadOptions: _extends({}, r.loadOptions || {}, v.loadOptions || {}),
383
+ processingOptions: _extends({}, r.processingOptions || {}, v.processingOptions || {}),
384
+ errors: [].concat(_toConsumableArray(r.errors || []), _toConsumableArray(v.errors || []))
385
+ };
386
+ }, {});
387
+ }
388
+
389
+ function getOptions(qry, schema) {
390
+ if (!qry) return undefined;
391
+
392
+ var fixedQry = schema ? fixFilterAndSearch(schema)(qry) : qry;
393
+
394
+ return mergeResults([takeOptions, skipOptions, totalCountOptions, sortOptions, groupOptions, totalSummaryOptions, filterOptions, searchOptions, selectOptions, timezoneOptions, summaryQueryLimitOptions, caseInsensitiveRegexOptions].map(function (f) {
395
+ return f(fixedQry);
396
+ }));
397
+ }
398
+
399
+ module.exports = {
400
+ getOptions: getOptions,
401
+ private: {
402
+ fixFilterAndSearch: fixFilterAndSearch,
403
+ validateAll: validateAll,
404
+ check: check,
405
+ takeOptions: takeOptions,
406
+ skipOptions: skipOptions,
407
+ totalCountOptions: totalCountOptions,
408
+ sortOptions: sortOptions,
409
+ groupOptions: groupOptions,
410
+ totalSummaryOptions: totalSummaryOptions,
411
+ filterOptions: filterOptions,
412
+ searchOptions: searchOptions,
413
+ selectOptions: selectOptions,
414
+ sortOptionsChecker: sortOptionsChecker,
415
+ groupOptionsChecker: groupOptionsChecker,
416
+ summaryOptionsChecker: summaryOptionsChecker,
417
+ asBool: asBool,
418
+ parse: parse
419
+ }
420
+ };