@geekbears/gb-mongoose-query-parser 1.2.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,397 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongooseQueryParser = void 0;
4
+ var Moment = require("moment");
5
+ var qs = require("querystring");
6
+ var _ = require("lodash");
7
+ var MongooseQueryParser = /** @class */ (function () {
8
+ function MongooseQueryParser(options) {
9
+ var _this = this;
10
+ if (options === void 0) { options = {}; }
11
+ this.options = options;
12
+ this.defaultDateFormat = [Moment.ISO_8601];
13
+ this.builtInCaster = {
14
+ string: function (val) { return String(val); },
15
+ date: function (val) {
16
+ var m = Moment(val, _this.options.dateFormat);
17
+ if (m.isValid()) {
18
+ return m.toDate();
19
+ }
20
+ else {
21
+ throw new Error("Invalid date string: [" + val + "]");
22
+ }
23
+ },
24
+ };
25
+ this.operators = [
26
+ { operator: 'select', method: this.castSelect, defaultKey: 'select' },
27
+ { operator: 'populate', method: this.castPopulate, defaultKey: 'populate' },
28
+ { operator: 'sort', method: this.castSort, defaultKey: 'sort' },
29
+ { operator: 'skip', method: this.castSkip, defaultKey: 'skip' },
30
+ { operator: 'limit', method: this.castLimit, defaultKey: 'limit' },
31
+ { operator: 'filter', method: this.castFilter, defaultKey: 'filter' },
32
+ { operator: 'deepPopulate', method: this.castDeepPopulate, defaultKey: 'deepPopulate' },
33
+ { operator: 'lean', method: this.castLean, defaultKey: 'lean' },
34
+ ];
35
+ // add default date format as ISO_8601
36
+ this.options.dateFormat = options.dateFormat || this.defaultDateFormat;
37
+ // add builtInCaster
38
+ this.options.casters = Object.assign(this.builtInCaster, options.casters);
39
+ // build blacklist
40
+ this.options.blacklist = options.blacklist || [];
41
+ this.operators.forEach(function (_a) {
42
+ var operator = _a.operator, method = _a.method, defaultKey = _a.defaultKey;
43
+ _this.options.blacklist.push(_this.options[operator + "Key"] || defaultKey);
44
+ });
45
+ }
46
+ /**
47
+ * parses query string/object to Mongoose friendly query object/QueryOptions
48
+ * @param {string | Object} query
49
+ * @param {Object} [context]
50
+ * @return {QueryOptions}
51
+ */
52
+ MongooseQueryParser.prototype.parse = function (query, context) {
53
+ var _this = this;
54
+ var params = _.isString(query) ? qs.parse(query) : query;
55
+ var options = this.options;
56
+ var result = {};
57
+ this.operators.forEach(function (_a) {
58
+ var operator = _a.operator, method = _a.method, defaultKey = _a.defaultKey;
59
+ var key = options[operator + "Key"] || defaultKey;
60
+ var value = params[key];
61
+ if (value || operator === 'filter') {
62
+ result[operator] = method.call(_this, value, params);
63
+ }
64
+ }, this);
65
+ result = this.parsePredefinedQuery(result, context);
66
+ return result;
67
+ };
68
+ /**
69
+ * parses string to typed values
70
+ * This methods will apply auto type casting on Number, RegExp, Date, Boolean and null
71
+ * Also, it will apply defined casters in given options of the instance
72
+ * @param {string} value
73
+ * @param {string} key
74
+ * @return {any} typed value
75
+ */
76
+ MongooseQueryParser.prototype.parseValue = function (value, key) {
77
+ var me = this;
78
+ var options = this.options;
79
+ // Apply casters
80
+ // Match type casting operators like: string(true), _caster(123), $('test')
81
+ var casters = options.casters;
82
+ var casting = value.match(/^([a-zA-Z_$][0-9a-zA-Z_$]*)\((.*)\)$/);
83
+ if (casting && casters[casting[1]]) {
84
+ return casters[casting[1]](casting[2]);
85
+ }
86
+ // Apply casters per params
87
+ if (key && options.castParams && options.castParams[key] && casters[options.castParams[key]]) {
88
+ return casters[options.castParams[key]](value);
89
+ }
90
+ // cast array
91
+ if (value.includes(',')) {
92
+ return value.split(',').map(function (val) { return me.parseValue(val, key); });
93
+ }
94
+ // Apply type casting for Number, RegExp, Date, Boolean and null
95
+ // Match regex operators like /foo_\d+/i
96
+ var regex = value.match(/^\/(.*)\/(i?)$/);
97
+ if (regex) {
98
+ return new RegExp(regex[1], regex[2]);
99
+ }
100
+ // Match boolean values
101
+ if (value === 'true') {
102
+ return true;
103
+ }
104
+ if (value === 'false') {
105
+ return false;
106
+ }
107
+ // Match null
108
+ if (value === 'null') {
109
+ return null;
110
+ }
111
+ // Match numbers (string padded with zeros are not numbers)
112
+ if (value !== '' && !isNaN(Number(value)) && !/^0[0-9]+/.test(value)) {
113
+ return Number(value);
114
+ }
115
+ // Match dates
116
+ var m = Moment(value, options.dateFormat);
117
+ if (m.isValid()) {
118
+ return m.toDate();
119
+ }
120
+ return value;
121
+ };
122
+ MongooseQueryParser.prototype.castFilter = function (filter, params) {
123
+ var _this = this;
124
+ var options = this.options;
125
+ var parsedFilter = filter ? this.parseFilter(filter) : {};
126
+ return Object.keys(params)
127
+ .map(function (val) {
128
+ var join = params[val] ? val + "=" + params[val] : val;
129
+ // Separate key, operators and value
130
+ var _a = join.match(/(!?)([^><!=]+)([><]=?|!?=|)(.*)/), prefix = _a[1], key = _a[2], op = _a[3], value = _a[4];
131
+ return { prefix: prefix, key: key, op: _this.parseOperator(op), value: _this.parseValue(value, key) };
132
+ })
133
+ .filter(function (_a) {
134
+ var key = _a.key;
135
+ return options.blacklist.indexOf(key) === -1;
136
+ })
137
+ .reduce(function (result, _a) {
138
+ var prefix = _a.prefix, key = _a.key, op = _a.op, value = _a.value;
139
+ if (!result[key]) {
140
+ result[key] = {};
141
+ }
142
+ if (Array.isArray(value)) {
143
+ result[key][op === '$ne' ? '$nin' : '$in'] = value;
144
+ }
145
+ else if (op === '$exists') {
146
+ result[key][op] = prefix !== '!';
147
+ }
148
+ else if (op === '$eq') {
149
+ result[key] = value;
150
+ }
151
+ else if (op === '$ne' && typeof value === 'object') {
152
+ result[key].$not = value;
153
+ }
154
+ else {
155
+ result[key][op] = value;
156
+ }
157
+ return result;
158
+ }, parsedFilter);
159
+ };
160
+ MongooseQueryParser.prototype.parseFilter = function (filter) {
161
+ try {
162
+ if (typeof filter === 'object') {
163
+ return filter;
164
+ }
165
+ return JSON.parse(filter);
166
+ }
167
+ catch (err) {
168
+ throw new Error("Invalid JSON string: " + filter);
169
+ }
170
+ };
171
+ MongooseQueryParser.prototype.parseOperator = function (operator) {
172
+ if (operator === '=') {
173
+ return '$eq';
174
+ }
175
+ else if (operator === '!=') {
176
+ return '$ne';
177
+ }
178
+ else if (operator === '>') {
179
+ return '$gt';
180
+ }
181
+ else if (operator === '>=') {
182
+ return '$gte';
183
+ }
184
+ else if (operator === '<') {
185
+ return '$lt';
186
+ }
187
+ else if (operator === '<=') {
188
+ return '$lte';
189
+ }
190
+ else if (!operator) {
191
+ return '$exists';
192
+ }
193
+ };
194
+ /**
195
+ * cast select query to object like:
196
+ * select=a,b or select=-a,-b
197
+ * =>
198
+ * {select: { a: 1, b: 1 }} or {select: { a: 0, b: 0 }}
199
+ * @param val
200
+ */
201
+ MongooseQueryParser.prototype.castSelect = function (val) {
202
+ var fields = this.parseUnaries(val, { plus: 1, minus: 0 });
203
+ /*
204
+ From the MongoDB documentation:
205
+ "A projection cannot contain both include and exclude specifications, except for the exclusion of the _id field."
206
+ */
207
+ var hasMixedValues = Object.keys(fields).reduce(function (set, key) {
208
+ if (key !== '_id') {
209
+ set.add(fields[key]);
210
+ }
211
+ return set;
212
+ }, new Set()).size > 1;
213
+ if (hasMixedValues) {
214
+ Object.keys(fields).forEach(function (key) {
215
+ if (fields[key] === 1) {
216
+ delete fields[key];
217
+ }
218
+ });
219
+ }
220
+ return fields;
221
+ };
222
+ /**
223
+ * cast populate query to object like:
224
+ * populate=field1.p1,field1.p2,field2
225
+ * =>
226
+ * [{path: 'field1', select: 'p1 p2'}, {path: 'field2'}]
227
+ * @param val
228
+ */
229
+ MongooseQueryParser.prototype.castPopulate = function (val) {
230
+ return val
231
+ .split(',')
232
+ .map(function (qry) {
233
+ var _a = qry.split('.', 2), p = _a[0], s = _a[1];
234
+ return s ? { path: p, select: s } : { path: p };
235
+ })
236
+ .reduce(function (prev, curr, key) {
237
+ // consolidate population array
238
+ var path = curr.path;
239
+ var select = curr.select;
240
+ var found = false;
241
+ prev.forEach(function (e) {
242
+ if (e.path === path) {
243
+ found = true;
244
+ if (select) {
245
+ e.select = e.select ? e.select + ' ' + select : select;
246
+ }
247
+ }
248
+ });
249
+ if (!found) {
250
+ prev.push(curr);
251
+ }
252
+ return prev;
253
+ }, []);
254
+ };
255
+ /**
256
+ * cast deep populate query to object like:
257
+ * populate={"path":"any", select="deep"}
258
+ * =>
259
+ * {path: 'field1', select: 'deep'}
260
+ * @param deepPopulate
261
+ */
262
+ MongooseQueryParser.prototype.castDeepPopulate = function (deepPopulate) {
263
+ return this.parseDeepPopulate(deepPopulate);
264
+ };
265
+ MongooseQueryParser.prototype.parseDeepPopulate = function (deepPopulate) {
266
+ try {
267
+ if (typeof deepPopulate === 'object') {
268
+ return deepPopulate;
269
+ }
270
+ return JSON.parse(deepPopulate);
271
+ }
272
+ catch (err) {
273
+ throw new Error("Invalid JSON string: " + deepPopulate);
274
+ }
275
+ };
276
+ /**
277
+ * cast sort query to object like
278
+ * sort=-a,b
279
+ * =>
280
+ * {sort: {a: -1, b: 1}}
281
+ * @param sort
282
+ */
283
+ MongooseQueryParser.prototype.castSort = function (sort) {
284
+ return this.parseUnaries(sort);
285
+ };
286
+ /**
287
+ * Map/reduce helper to transform list of unaries
288
+ * like '+a,-b,c' to {a: 1, b: -1, c: 1}
289
+ */
290
+ MongooseQueryParser.prototype.parseUnaries = function (unaries, values) {
291
+ if (values === void 0) { values = { plus: 1, minus: -1 }; }
292
+ var unariesAsArray = _.isString(unaries) ? unaries.split(',') : unaries;
293
+ return unariesAsArray
294
+ .map(function (x) { return x.match(/^(\+|-)?(.*)/); })
295
+ .reduce(function (result, _a) {
296
+ var val = _a[1], key = _a[2];
297
+ result[key.trim()] = val === '-' ? values.minus : values.plus;
298
+ return result;
299
+ }, {});
300
+ };
301
+ /**
302
+ * cast skip query to object like
303
+ * skip=100
304
+ * =>
305
+ * {skip: 100}
306
+ * @param skip
307
+ */
308
+ MongooseQueryParser.prototype.castSkip = function (skip) {
309
+ return Number(skip);
310
+ };
311
+ /**
312
+ * cast limit query to object like
313
+ * limit=10
314
+ * =>
315
+ * {limit: 10}
316
+ * @param limit
317
+ */
318
+ MongooseQueryParser.prototype.castLimit = function (limit) {
319
+ return Number(limit);
320
+ };
321
+ /**
322
+ * cast lean option like
323
+ * lean=true
324
+ * =>
325
+ * {lean: true}
326
+ * @param lean
327
+ */
328
+ MongooseQueryParser.prototype.castLean = function (lean) {
329
+ return lean === 'true' ? true : false;
330
+ };
331
+ /**
332
+ * transform predefined query strings defined in query string to the actual query object out of the given context
333
+ * @param query
334
+ * @param context
335
+ */
336
+ MongooseQueryParser.prototype.parsePredefinedQuery = function (query, context) {
337
+ if (context) {
338
+ // check if given string is the format as predefined query i.e. ${query}
339
+ var _match_1 = function (str) {
340
+ var reg = /^\$\{([a-zA-Z_$][0-9a-zA-Z_$]*)\}$/;
341
+ var match = str.match(reg);
342
+ var val = undefined;
343
+ if (match) {
344
+ val = _.property(match[1])(context);
345
+ if (val === undefined) {
346
+ throw new Error("No predefined query found for the provided reference [" + match[1] + "]");
347
+ }
348
+ }
349
+ return { match: !!match, val: val };
350
+ };
351
+ var _transform_1 = function (obj) {
352
+ return _.reduce(obj, function (prev, curr, key) {
353
+ var _a, _b;
354
+ var val = undefined, match = undefined;
355
+ if (_.isString(key)) {
356
+ (_a = _match_1(key), match = _a.match, val = _a.val);
357
+ if (match) {
358
+ if (_.has(curr, '$exists')) {
359
+ // 1). as a key: {'${qry}': {$exits: true}} => {${qry object}}
360
+ return _.merge(prev, val);
361
+ }
362
+ else if (_.isString(val)) {
363
+ // 1). as a key: {'${qry}': 'something'} => {'${qry object}': 'something'}
364
+ key = val;
365
+ }
366
+ else {
367
+ throw new Error("Invalid query string at " + key);
368
+ }
369
+ }
370
+ }
371
+ if (_.isString(curr)) {
372
+ (_b = _match_1(curr), match = _b.match, val = _b.val);
373
+ if (match) {
374
+ _.isNumber(key)
375
+ ? prev.push(val) // 3). as an item of array: ['${qry}', ...] => [${qry object}, ...]
376
+ : (prev[key] = val); // 2). as a value: {prop: '${qry}'} => {prop: ${qry object}}
377
+ return prev;
378
+ }
379
+ }
380
+ if (_.isObject(curr) && !_.isRegExp(curr) && !_.isDate(curr)) {
381
+ // iterate all props & keys recursively
382
+ _.isNumber(key) ? prev.push(_transform_1(curr)) : (prev[key] = _transform_1(curr));
383
+ }
384
+ else {
385
+ _.isNumber(key) ? prev.push(curr) : (prev[key] = curr);
386
+ }
387
+ return prev;
388
+ }, _.isArray(obj) ? [] : {});
389
+ };
390
+ return _transform_1(query);
391
+ }
392
+ return query;
393
+ };
394
+ return MongooseQueryParser;
395
+ }());
396
+ exports.MongooseQueryParser = MongooseQueryParser;
397
+ //# sourceMappingURL=query-parser.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var __generator = (this && this.__generator) || function (thisArg, body) {
21
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
22
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
23
+ function verb(n) { return function (v) { return step([n, v]); }; }
24
+ function step(op) {
25
+ if (f) throw new TypeError("Generator is already executing.");
26
+ while (_) try {
27
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
28
+ if (y = 0, t) op = [op[0] & 2, t.value];
29
+ switch (op[0]) {
30
+ case 0: case 1: t = op; break;
31
+ case 4: _.label++; return { value: op[1], done: false };
32
+ case 5: _.label++; y = op[1]; op = [0]; continue;
33
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
34
+ default:
35
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
36
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
37
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
38
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
39
+ if (t[2]) _.ops.pop();
40
+ _.trys.pop(); continue;
41
+ }
42
+ op = body.call(thisArg, _);
43
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
44
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
45
+ }
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ var mocha_1 = require("@testdeck/mocha");
49
+ var chai_1 = require("chai");
50
+ var _1 = require("./");
51
+ var Tester = /** @class */ (function () {
52
+ function Tester() {
53
+ }
54
+ Tester.prototype.generalParse = function () {
55
+ var parser = new _1.MongooseQueryParser();
56
+ var qry = 'date=2016-01-01&boolean=true&integer=10&regexp=/foobar/i&null=null';
57
+ var parsed = parser.parse(qry);
58
+ chai_1.assert.isNotNull(parsed.filter);
59
+ chai_1.assert.isOk(parsed.filter['date'] instanceof Date);
60
+ chai_1.assert.isOk(parsed.filter['boolean'] === true);
61
+ chai_1.assert.isOk(parsed.filter['integer'] === 10);
62
+ chai_1.assert.isOk(parsed.filter['regexp'] instanceof RegExp);
63
+ chai_1.assert.isOk(parsed.filter['null'] === null);
64
+ };
65
+ Tester.prototype.generalParse2 = function () {
66
+ var parser = new _1.MongooseQueryParser();
67
+ var predefined = {
68
+ vip: { name: { $in: ['Google', 'Microsoft', 'NodeJs'] } },
69
+ sentStatus: 'sent',
70
+ };
71
+ var parsed = parser.parse('${vip}&status=${sentStatus}&timestamp>2017-10-01&author.firstName=/john/i&limit=100&skip=50&sort=-timestamp&select=name&populate=children', predefined);
72
+ chai_1.assert.isOk(parsed.filter['status'] === predefined.sentStatus);
73
+ chai_1.assert.isOk(parsed.filter['name'].$in.length === 3); // checking parsing of ${vip}
74
+ chai_1.assert.isOk(parsed.filter['timestamp']['$gt'] instanceof Date);
75
+ chai_1.assert.isOk(parsed.filter['author.firstName'] instanceof RegExp);
76
+ chai_1.assert.isOk(parsed.limit === 100);
77
+ chai_1.assert.isOk(parsed.skip === 50);
78
+ chai_1.assert.isNotNull(parsed.sort);
79
+ chai_1.assert.isNotNull(parsed.select);
80
+ chai_1.assert.isNotNull(parsed.populate);
81
+ };
82
+ Tester.prototype.populateParse = function () {
83
+ return __awaiter(this, void 0, void 0, function () {
84
+ var parser, qry, parsed;
85
+ return __generator(this, function (_a) {
86
+ parser = new _1.MongooseQueryParser();
87
+ qry = '_id=1&populate=serviceSalesOrders,customer.category,customer.name';
88
+ parsed = parser.parse(qry);
89
+ chai_1.assert.isOk(parsed.populate.length === 2);
90
+ return [2 /*return*/];
91
+ });
92
+ });
93
+ };
94
+ Tester.prototype.builtInCastersTest = function () {
95
+ var parser = new _1.MongooseQueryParser();
96
+ var qry = 'key1=string(10)&key2=date(2017-10-01)&key3=string(null)';
97
+ var parsed = parser.parse(qry);
98
+ chai_1.assert.isOk(typeof parsed.filter['key1'] === 'string');
99
+ chai_1.assert.isOk(parsed.filter['key2'] instanceof Date);
100
+ chai_1.assert.isOk(typeof parsed.filter['key3'] === 'string');
101
+ };
102
+ Tester.prototype.parseCaster = function () {
103
+ var parser = new _1.MongooseQueryParser({
104
+ casters: { $: function (val) { return '$' + val; } },
105
+ });
106
+ var qry = '_id=$(1)';
107
+ var parsed = parser.parse(qry);
108
+ chai_1.assert.equal('$1', parsed.filter['_id']);
109
+ };
110
+ Tester.prototype.parseJsonFilter = function () {
111
+ var parser = new _1.MongooseQueryParser();
112
+ var obj = {
113
+ $or: [{ key1: 'value1' }, { key2: 'value2' }],
114
+ };
115
+ var qry = "filter=" + JSON.stringify(obj) + "&name=Google";
116
+ var parsed = parser.parse(qry);
117
+ chai_1.assert.isArray(parsed.filter['$or']);
118
+ chai_1.assert.isOk(parsed.filter['name'] === 'Google');
119
+ };
120
+ Tester.prototype.parsePredefined = function () {
121
+ var parser = new _1.MongooseQueryParser();
122
+ var preDefined = {
123
+ isActive: { status: { $in: ['In Progress', 'Pending'] } },
124
+ vip: ['KFC', 'Google', 'MS'],
125
+ secret: 'my_secret',
126
+ mykey: 'realkey',
127
+ };
128
+ // test predefined query as key
129
+ var qry = '${isActive}&name&${mykey}=1';
130
+ var parsed = parser.parse(qry, preDefined);
131
+ chai_1.assert.isNotNull(parsed.filter['status']);
132
+ chai_1.assert.isOk(!parsed.filter['${isActive}']);
133
+ chai_1.assert.isOk(parsed.filter['realkey'] === 1);
134
+ // test predefined query as value
135
+ qry = 'secret=${secret}';
136
+ parsed = parser.parse(qry, preDefined);
137
+ chai_1.assert.isOk(parsed.filter['secret'] === preDefined.secret);
138
+ // test predefined query in json
139
+ qry = 'filter={"$and": ["${isActive}", {"customer": "VDF"}]}';
140
+ parsed = parser.parse(qry, preDefined);
141
+ chai_1.assert.isNotNull(parsed.filter['$and'][0].status);
142
+ };
143
+ Tester.prototype.parseLean = function () {
144
+ var parser = new _1.MongooseQueryParser();
145
+ var qryTrue = 'lean=true';
146
+ var qryFalse = 'lean=false';
147
+ var qryUndefined = 'lean=';
148
+ var qryNotBoolean = 'lean=any';
149
+ var parsedTrue = parser.parse(qryTrue);
150
+ var parsedFalse = parser.parse(qryFalse);
151
+ var parsedUndefined = parser.parse(qryUndefined);
152
+ var parsedNotBoolean = parser.parse(qryNotBoolean);
153
+ chai_1.assert.isTrue(parsedTrue.lean);
154
+ chai_1.assert.isFalse(parsedFalse.lean);
155
+ chai_1.assert.notNestedProperty(parsedUndefined, 'lean');
156
+ chai_1.assert.isFalse(parsedNotBoolean.lean);
157
+ };
158
+ __decorate([
159
+ (0, mocha_1.test)('should parse general query'),
160
+ __metadata("design:type", Function),
161
+ __metadata("design:paramtypes", []),
162
+ __metadata("design:returntype", void 0)
163
+ ], Tester.prototype, "generalParse", null);
164
+ __decorate([
165
+ (0, mocha_1.test)('should parse query with string templates'),
166
+ __metadata("design:type", Function),
167
+ __metadata("design:paramtypes", []),
168
+ __metadata("design:returntype", void 0)
169
+ ], Tester.prototype, "generalParse2", null);
170
+ __decorate([
171
+ (0, mocha_1.test)('should parse populate query'),
172
+ __metadata("design:type", Function),
173
+ __metadata("design:paramtypes", []),
174
+ __metadata("design:returntype", Promise)
175
+ ], Tester.prototype, "populateParse", null);
176
+ __decorate([
177
+ (0, mocha_1.test)('should parse built in casters'),
178
+ __metadata("design:type", Function),
179
+ __metadata("design:paramtypes", []),
180
+ __metadata("design:returntype", void 0)
181
+ ], Tester.prototype, "builtInCastersTest", null);
182
+ __decorate([
183
+ (0, mocha_1.test)('should parse custom caster'),
184
+ __metadata("design:type", Function),
185
+ __metadata("design:paramtypes", []),
186
+ __metadata("design:returntype", void 0)
187
+ ], Tester.prototype, "parseCaster", null);
188
+ __decorate([
189
+ (0, mocha_1.test)('should parse json filter'),
190
+ __metadata("design:type", Function),
191
+ __metadata("design:paramtypes", []),
192
+ __metadata("design:returntype", void 0)
193
+ ], Tester.prototype, "parseJsonFilter", null);
194
+ __decorate([
195
+ (0, mocha_1.test)('should parse predefined query objects'),
196
+ __metadata("design:type", Function),
197
+ __metadata("design:paramtypes", []),
198
+ __metadata("design:returntype", void 0)
199
+ ], Tester.prototype, "parsePredefined", null);
200
+ __decorate([
201
+ (0, mocha_1.test)('should parse lean'),
202
+ __metadata("design:type", Function),
203
+ __metadata("design:paramtypes", []),
204
+ __metadata("design:returntype", void 0)
205
+ ], Tester.prototype, "parseLean", null);
206
+ Tester = __decorate([
207
+ (0, mocha_1.suite)('Tester')
208
+ ], Tester);
209
+ return Tester;
210
+ }());
211
+ //# sourceMappingURL=test.spec.js.map
@@ -0,0 +1,2 @@
1
+ export * from './parser-options.type';
2
+ export * from './query-options.type';
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./parser-options.type"), exports);
14
+ __exportStar(require("./query-options.type"), exports);
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,18 @@
1
+ export interface ParserOptions {
2
+ dateFormat?: any;
3
+ blacklist?: string[];
4
+ casters?: {
5
+ [key: string]: (val: string) => any;
6
+ };
7
+ castParams?: {
8
+ [key: string]: string;
9
+ };
10
+ selectKey?: string;
11
+ populateKey?: string;
12
+ deepPopulateKey?: string;
13
+ sortKey?: string;
14
+ skipKey?: string;
15
+ limitKey?: string;
16
+ filterKey?: string;
17
+ leanKey?: string;
18
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=parser-options.type.js.map
@@ -0,0 +1,15 @@
1
+ import { SortOrder } from 'mongoose';
2
+ export interface QueryOptions {
3
+ filter: Object;
4
+ sort?: string | {
5
+ [key: string]: SortOrder | {
6
+ $meta: 'textScore';
7
+ };
8
+ } | [string, SortOrder][] | undefined | null;
9
+ limit?: number;
10
+ skip?: number;
11
+ select?: string | Object;
12
+ populate?: string | Object;
13
+ deepPopulate?: string | Object;
14
+ lean?: boolean;
15
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=query-options.type.js.map