@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,235 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (_) try {
29
+ 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;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.QueryParser = void 0;
51
+ var mongoose_1 = require("mongoose");
52
+ var lodash_1 = require("lodash");
53
+ var query_parser_1 = require("./query-parser");
54
+ /**
55
+ * Helper class
56
+ * Implements the `MongooseQueryParser` and exposes a single method to execute queries on models
57
+ */
58
+ var QueryParser = /** @class */ (function () {
59
+ function QueryParser() {
60
+ }
61
+ /**
62
+ * Build a Mongoose query on a given model from the parsed query string
63
+ * @param model a mongoose `Model` object to perform the query on
64
+ * @param query a query string object received by the controller
65
+ * @param count an optional flag that indicates wether a `count` operation should be performed
66
+ * @returns a Mongoose query on the provided model
67
+ */
68
+ QueryParser.parseQuery = function (model, query, count) {
69
+ if (count === void 0) { count = false; }
70
+ var docsQuery;
71
+ var countQueryDocuments;
72
+ docsQuery = model.find({});
73
+ countQueryDocuments = count ? model.countDocuments() : null;
74
+ if (!(0, lodash_1.isEmpty)(query)) {
75
+ var parser = new query_parser_1.MongooseQueryParser();
76
+ var queryParams = parser.parse(query);
77
+ (0, lodash_1.forOwn)(transformFilter(queryParams.filter), function (value, key) {
78
+ docsQuery = docsQuery.where(key, value);
79
+ if (countQueryDocuments)
80
+ countQueryDocuments = countQueryDocuments.where(key, value);
81
+ });
82
+ if (queryParams.populate)
83
+ docsQuery = docsQuery.populate(queryParams.populate);
84
+ if (queryParams.deepPopulate)
85
+ docsQuery = docsQuery.populate(queryParams.deepPopulate);
86
+ if (queryParams.sort)
87
+ docsQuery = docsQuery.sort(queryParams.sort);
88
+ if (queryParams.limit)
89
+ docsQuery = docsQuery.limit(queryParams.limit);
90
+ if (queryParams.select)
91
+ docsQuery = docsQuery.select(queryParams.select);
92
+ if (queryParams.skip)
93
+ docsQuery = docsQuery.skip(queryParams.skip);
94
+ }
95
+ return count && countQueryDocuments ? countQueryDocuments : docsQuery;
96
+ };
97
+ /**
98
+ * Get all documents matching the provided query for a given model
99
+ * @param model a mongoose `Model` object to perform the query on
100
+ * @param query a query string object received by the controller
101
+ * @param count an optional flag that indicates wether a `count` operation should be performed
102
+ * @returns the result of executing the provided query on the provided model
103
+ */
104
+ QueryParser.docByQuery = function (model, query, count) {
105
+ if (count === void 0) { count = false; }
106
+ return __awaiter(this, void 0, void 0, function () {
107
+ var error_1;
108
+ var _a;
109
+ return __generator(this, function (_b) {
110
+ switch (_b.label) {
111
+ case 0:
112
+ _b.trys.push([0, 2, , 3]);
113
+ _a = {};
114
+ return [4 /*yield*/, QueryParser.parseQuery(model, query, count).exec()];
115
+ case 1: return [2 /*return*/, (_a.data = _b.sent(), _a)];
116
+ case 2:
117
+ error_1 = _b.sent();
118
+ throw new Error(error_1);
119
+ case 3: return [2 /*return*/];
120
+ }
121
+ });
122
+ });
123
+ };
124
+ /**
125
+ * Get all documents matching the provided query for a given model to a mongodb cursor resource
126
+ * @param model a mongoose `Model` object to perform the query on
127
+ * @param query a query string object received by the controller
128
+ * @param count an optional flag that indicates wether a `count` operation should be performed
129
+ * @returns the cursor of executing the provided query on the provided model
130
+ */
131
+ QueryParser.docByQueryToCursor = function (model, query) {
132
+ try {
133
+ return {
134
+ data: QueryParser.parseQuery(model, query, false).cursor(),
135
+ };
136
+ }
137
+ catch (error) {
138
+ throw new Error(error);
139
+ }
140
+ };
141
+ /**
142
+ * Build a Mongoose `findOne` query on a given model with additional params
143
+ * @param model a Mongoose `Model` object to perform the query on
144
+ * @param filter a Mongoose filter query on the provided model
145
+ * @param query a query string object received by the controller
146
+ * @returns a Mongoose query on the provided model
147
+ */
148
+ QueryParser.parseFilterQuery = function (model, filter, query) {
149
+ var docQuery;
150
+ docQuery = model.findOne(__assign({}, filter));
151
+ if (!(0, lodash_1.isEmpty)(query)) {
152
+ var parser = new query_parser_1.MongooseQueryParser({
153
+ blacklist: ['filter', 'sort', 'limit', 'skip'],
154
+ });
155
+ var queryParams = parser.parse(query);
156
+ if (queryParams.populate)
157
+ docQuery = docQuery.populate(queryParams.populate);
158
+ if (queryParams.deepPopulate)
159
+ docQuery = docQuery.populate(queryParams.deepPopulate);
160
+ if (queryParams.select)
161
+ docQuery = docQuery.select(queryParams.select);
162
+ }
163
+ return docQuery;
164
+ };
165
+ /**
166
+ * Get a document matching the provided query for a given model
167
+ * @param model a Mongoose `Model` object to perform the query on
168
+ * @param filter a Mongoose filter query on the provided model
169
+ * @param query a query string object received by the controller
170
+ * @returns the result of executing the provided query on the provided model
171
+ */
172
+ QueryParser.docByFilter = function (model, filter, query) {
173
+ return __awaiter(this, void 0, void 0, function () {
174
+ var error_2;
175
+ var _a;
176
+ return __generator(this, function (_b) {
177
+ switch (_b.label) {
178
+ case 0:
179
+ _b.trys.push([0, 2, , 3]);
180
+ _a = {};
181
+ return [4 /*yield*/, QueryParser.parseFilterQuery(model, filter, query).exec()];
182
+ case 1: return [2 /*return*/, (_a.data = _b.sent(),
183
+ _a)];
184
+ case 2:
185
+ error_2 = _b.sent();
186
+ throw new Error(error_2);
187
+ case 3: return [2 /*return*/];
188
+ }
189
+ });
190
+ });
191
+ };
192
+ /**
193
+ * Build a Mongoose `findOneById` query on a given model with additional params
194
+ * @param model a Mongoose `Model` object to perform the query on
195
+ * @param _id the resource id
196
+ * @param query a query string object received by the controller
197
+ * @returns a Mongoose query on the provided model
198
+ */
199
+ QueryParser.parseByIdQuery = function (model, _id, query) {
200
+ return QueryParser.parseFilterQuery(model, { _id: _id }, query);
201
+ };
202
+ /**
203
+ * Get a document matching the provided query for a given model
204
+ * @param model a Mongoose `Model` object to perform the query on
205
+ * @param _id the resource id
206
+ * @param query a query string object received by the controller
207
+ * @returns the result of executing the provided query on the provided model
208
+ */
209
+ QueryParser.docById = function (model, _id, query) {
210
+ return QueryParser.docByFilter(model, { _id: _id }, query);
211
+ };
212
+ return QueryParser;
213
+ }());
214
+ exports.QueryParser = QueryParser;
215
+ /**
216
+ * Transforms the filter param to correctly support `ObjectId`s
217
+ * @param filter the filter param
218
+ * @returns a casted filter
219
+ */
220
+ function transformFilter(filter) {
221
+ var walk = function (obj) {
222
+ for (var key in obj) {
223
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
224
+ var value = obj[key];
225
+ if (typeof value === 'object')
226
+ walk(obj[key]);
227
+ else
228
+ obj[key] = mongoose_1.Types.ObjectId.isValid(value) ? new mongoose_1.Types.ObjectId(value) : value;
229
+ }
230
+ }
231
+ return obj;
232
+ };
233
+ return walk(__assign({}, filter));
234
+ }
235
+ //# sourceMappingURL=query-parser-helper.js.map
@@ -0,0 +1,96 @@
1
+ import { ParserOptions } from './types/parser-options.type';
2
+ import { QueryOptions } from './types/query-options.type';
3
+ export declare class MongooseQueryParser {
4
+ private options;
5
+ private readonly defaultDateFormat;
6
+ private readonly builtInCaster;
7
+ private readonly operators;
8
+ constructor(options?: ParserOptions);
9
+ /**
10
+ * parses query string/object to Mongoose friendly query object/QueryOptions
11
+ * @param {string | Object} query
12
+ * @param {Object} [context]
13
+ * @return {QueryOptions}
14
+ */
15
+ parse(query: string | Object, context?: Object): QueryOptions;
16
+ /**
17
+ * parses string to typed values
18
+ * This methods will apply auto type casting on Number, RegExp, Date, Boolean and null
19
+ * Also, it will apply defined casters in given options of the instance
20
+ * @param {string} value
21
+ * @param {string} key
22
+ * @return {any} typed value
23
+ */
24
+ parseValue(value: string, key?: string): any;
25
+ private castFilter;
26
+ private parseFilter;
27
+ private parseOperator;
28
+ /**
29
+ * cast select query to object like:
30
+ * select=a,b or select=-a,-b
31
+ * =>
32
+ * {select: { a: 1, b: 1 }} or {select: { a: 0, b: 0 }}
33
+ * @param val
34
+ */
35
+ private castSelect;
36
+ /**
37
+ * cast populate query to object like:
38
+ * populate=field1.p1,field1.p2,field2
39
+ * =>
40
+ * [{path: 'field1', select: 'p1 p2'}, {path: 'field2'}]
41
+ * @param val
42
+ */
43
+ private castPopulate;
44
+ /**
45
+ * cast deep populate query to object like:
46
+ * populate={"path":"any", select="deep"}
47
+ * =>
48
+ * {path: 'field1', select: 'deep'}
49
+ * @param deepPopulate
50
+ */
51
+ private castDeepPopulate;
52
+ private parseDeepPopulate;
53
+ /**
54
+ * cast sort query to object like
55
+ * sort=-a,b
56
+ * =>
57
+ * {sort: {a: -1, b: 1}}
58
+ * @param sort
59
+ */
60
+ private castSort;
61
+ /**
62
+ * Map/reduce helper to transform list of unaries
63
+ * like '+a,-b,c' to {a: 1, b: -1, c: 1}
64
+ */
65
+ private parseUnaries;
66
+ /**
67
+ * cast skip query to object like
68
+ * skip=100
69
+ * =>
70
+ * {skip: 100}
71
+ * @param skip
72
+ */
73
+ private castSkip;
74
+ /**
75
+ * cast limit query to object like
76
+ * limit=10
77
+ * =>
78
+ * {limit: 10}
79
+ * @param limit
80
+ */
81
+ private castLimit;
82
+ /**
83
+ * cast lean option like
84
+ * lean=true
85
+ * =>
86
+ * {lean: true}
87
+ * @param lean
88
+ */
89
+ private castLean;
90
+ /**
91
+ * transform predefined query strings defined in query string to the actual query object out of the given context
92
+ * @param query
93
+ * @param context
94
+ */
95
+ private parsePredefinedQuery;
96
+ }