UNPKG

23.1 kBJavaScriptView Raw
1/*! *****************************************************************************
2Copyright (c) Microsoft Corporation.
3
4Permission to use, copy, modify, and/or distribute this software for any
5purpose with or without fee is hereby granted.
6
7THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13PERFORMANCE OF THIS SOFTWARE.
14***************************************************************************** */
15/* global Reflect, Promise */
16
17var extendStatics = function(d, b) {
18 extendStatics = Object.setPrototypeOf ||
19 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
20 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
21 return extendStatics(d, b);
22};
23
24function __extends(d, b) {
25 extendStatics(d, b);
26 function __() { this.constructor = d; }
27 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
28}
29
30var typeChecker = function (type) {
31 var typeString = "[object " + type + "]";
32 return function (value) {
33 return getClassName(value) === typeString;
34 };
35};
36var getClassName = function (value) { return Object.prototype.toString.call(value); };
37var comparable = function (value) {
38 if (value instanceof Date) {
39 return value.getTime();
40 }
41 else if (isArray(value)) {
42 return value.map(comparable);
43 }
44 else if (value && typeof value.toJSON === "function") {
45 return value.toJSON();
46 }
47 return value;
48};
49var isArray = typeChecker("Array");
50var isObject = typeChecker("Object");
51var isFunction = typeChecker("Function");
52var isVanillaObject = function (value) {
53 return (value &&
54 (value.constructor === Object ||
55 value.constructor === Array ||
56 value.constructor.toString() === "function Object() { [native code] }" ||
57 value.constructor.toString() === "function Array() { [native code] }") &&
58 !value.toJSON);
59};
60var equals = function (a, b) {
61 if (a == null && a == b) {
62 return true;
63 }
64 if (a === b) {
65 return true;
66 }
67 if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) {
68 return false;
69 }
70 if (isArray(a)) {
71 if (a.length !== b.length) {
72 return false;
73 }
74 for (var i = 0, length_1 = a.length; i < length_1; i++) {
75 if (!equals(a[i], b[i]))
76 return false;
77 }
78 return true;
79 }
80 else if (isObject(a)) {
81 if (Object.keys(a).length !== Object.keys(b).length) {
82 return false;
83 }
84 for (var key in a) {
85 if (!equals(a[key], b[key]))
86 return false;
87 }
88 return true;
89 }
90 return false;
91};
92
93/**
94 * Walks through each value given the context - used for nested operations. E.g:
95 * { "person.address": { $eq: "blarg" }}
96 */
97var walkKeyPathValues = function (item, keyPath, next, depth, key, owner) {
98 var currentKey = keyPath[depth];
99 // if array, then try matching. Might fall through for cases like:
100 // { $eq: [1, 2, 3] }, [ 1, 2, 3 ].
101 if (isArray(item) && isNaN(Number(currentKey))) {
102 for (var i = 0, length_1 = item.length; i < length_1; i++) {
103 // if FALSE is returned, then terminate walker. For operations, this simply
104 // means that the search critera was met.
105 if (!walkKeyPathValues(item[i], keyPath, next, depth, i, item)) {
106 return false;
107 }
108 }
109 }
110 if (depth === keyPath.length || item == null) {
111 return next(item, key, owner);
112 }
113 return walkKeyPathValues(item[currentKey], keyPath, next, depth + 1, currentKey, item);
114};
115var BaseOperation = /** @class */ (function () {
116 function BaseOperation(params, owneryQuery, options) {
117 this.params = params;
118 this.owneryQuery = owneryQuery;
119 this.options = options;
120 this.init();
121 }
122 BaseOperation.prototype.init = function () { };
123 BaseOperation.prototype.reset = function () {
124 this.done = false;
125 this.success = false;
126 };
127 return BaseOperation;
128}());
129var NamedBaseOperation = /** @class */ (function (_super) {
130 __extends(NamedBaseOperation, _super);
131 function NamedBaseOperation(params, owneryQuery, options, name) {
132 var _this = _super.call(this, params, owneryQuery, options) || this;
133 _this.name = name;
134 return _this;
135 }
136 return NamedBaseOperation;
137}(BaseOperation));
138var GroupOperation = /** @class */ (function (_super) {
139 __extends(GroupOperation, _super);
140 function GroupOperation(params, owneryQuery, options, children) {
141 var _this = _super.call(this, params, owneryQuery, options) || this;
142 _this.children = children;
143 return _this;
144 }
145 /**
146 */
147 GroupOperation.prototype.reset = function () {
148 this.success = false;
149 this.done = false;
150 for (var i = 0, length_2 = this.children.length; i < length_2; i++) {
151 this.children[i].reset();
152 }
153 };
154 /**
155 */
156 GroupOperation.prototype.childrenNext = function (item, key, owner) {
157 var done = true;
158 var success = true;
159 for (var i = 0, length_3 = this.children.length; i < length_3; i++) {
160 var childOperation = this.children[i];
161 childOperation.next(item, key, owner);
162 if (!childOperation.success) {
163 success = false;
164 }
165 if (childOperation.done) {
166 if (!childOperation.success) {
167 break;
168 }
169 }
170 else {
171 done = false;
172 }
173 }
174 // console.log("DONE", this.params, done, success);
175 this.done = done;
176 this.success = success;
177 };
178 return GroupOperation;
179}(BaseOperation));
180var NamedGroupOperation = /** @class */ (function (_super) {
181 __extends(NamedGroupOperation, _super);
182 function NamedGroupOperation(params, owneryQuery, options, children, name) {
183 var _this = _super.call(this, params, owneryQuery, options, children) || this;
184 _this.name = name;
185 return _this;
186 }
187 return NamedGroupOperation;
188}(GroupOperation));
189var QueryOperation = /** @class */ (function (_super) {
190 __extends(QueryOperation, _super);
191 function QueryOperation() {
192 return _super !== null && _super.apply(this, arguments) || this;
193 }
194 /**
195 */
196 QueryOperation.prototype.next = function (item, key, parent) {
197 this.childrenNext(item, key, parent);
198 };
199 return QueryOperation;
200}(GroupOperation));
201var NestedOperation = /** @class */ (function (_super) {
202 __extends(NestedOperation, _super);
203 function NestedOperation(keyPath, params, owneryQuery, options, children) {
204 var _this = _super.call(this, params, owneryQuery, options, children) || this;
205 _this.keyPath = keyPath;
206 /**
207 */
208 _this._nextNestedValue = function (value, key, owner) {
209 _this.childrenNext(value, key, owner);
210 return !_this.done;
211 };
212 return _this;
213 }
214 /**
215 */
216 NestedOperation.prototype.next = function (item, key, parent) {
217 walkKeyPathValues(item, this.keyPath, this._nextNestedValue, 0, key, parent);
218 };
219 return NestedOperation;
220}(GroupOperation));
221var createTester = function (a, compare) {
222 if (a instanceof Function) {
223 return a;
224 }
225 if (a instanceof RegExp) {
226 return function (b) {
227 var result = typeof b === "string" && a.test(b);
228 a.lastIndex = 0;
229 return result;
230 };
231 }
232 var comparableA = comparable(a);
233 return function (b) { return compare(comparableA, comparable(b)); };
234};
235var EqualsOperation = /** @class */ (function (_super) {
236 __extends(EqualsOperation, _super);
237 function EqualsOperation() {
238 return _super !== null && _super.apply(this, arguments) || this;
239 }
240 EqualsOperation.prototype.init = function () {
241 this._test = createTester(this.params, this.options.compare);
242 };
243 EqualsOperation.prototype.next = function (item, key, parent) {
244 if (this._test(item, key, parent) &&
245 (!parent || parent.hasOwnProperty(key))) {
246 this.done = true;
247 this.success = true;
248 }
249 };
250 return EqualsOperation;
251}(BaseOperation));
252var createEqualsOperation = function (params, owneryQuery, options) { return new EqualsOperation(params, owneryQuery, options); };
253var NopeOperation = /** @class */ (function (_super) {
254 __extends(NopeOperation, _super);
255 function NopeOperation() {
256 return _super !== null && _super.apply(this, arguments) || this;
257 }
258 NopeOperation.prototype.next = function () {
259 this.done = true;
260 this.success = false;
261 };
262 return NopeOperation;
263}(BaseOperation));
264var numericalOperationCreator = function (createNumericalOperation) { return function (params, owneryQuery, options, name) {
265 if (params == null) {
266 return new NopeOperation(params, owneryQuery, options);
267 }
268 return createNumericalOperation(params, owneryQuery, options, name);
269}; };
270var numericalOperation = function (createTester) {
271 return numericalOperationCreator(function (params, owneryQuery, options) {
272 var typeofParams = typeof comparable(params);
273 var test = createTester(params);
274 return new EqualsOperation(function (b) {
275 return typeof comparable(b) === typeofParams && test(b);
276 }, owneryQuery, options);
277 });
278};
279var createNamedOperation = function (name, params, parentQuery, options) {
280 var operationCreator = options.operations[name];
281 if (!operationCreator) {
282 throw new Error("Unsupported operation: " + name);
283 }
284 return operationCreator(params, parentQuery, options, name);
285};
286var containsOperation = function (query) {
287 for (var key in query) {
288 if (key.charAt(0) === "$")
289 return true;
290 }
291 return false;
292};
293var createNestedOperation = function (keyPath, nestedQuery, owneryQuery, options) {
294 if (containsOperation(nestedQuery)) {
295 var _a = createQueryOperations(nestedQuery, options), selfOperations = _a[0], nestedOperations = _a[1];
296 if (nestedOperations.length) {
297 throw new Error("Property queries must contain only operations, or exact objects.");
298 }
299 return new NestedOperation(keyPath, nestedQuery, owneryQuery, options, selfOperations);
300 }
301 return new NestedOperation(keyPath, nestedQuery, owneryQuery, options, [
302 new EqualsOperation(nestedQuery, owneryQuery, options)
303 ]);
304};
305var createQueryOperation = function (query, owneryQuery, _a) {
306 if (owneryQuery === void 0) { owneryQuery = null; }
307 var _b = _a === void 0 ? {} : _a, compare = _b.compare, operations = _b.operations;
308 var options = {
309 compare: compare || equals,
310 operations: Object.assign({}, operations || {})
311 };
312 var _c = createQueryOperations(query, options), selfOperations = _c[0], nestedOperations = _c[1];
313 var ops = [];
314 if (selfOperations.length) {
315 ops.push(new NestedOperation([], query, owneryQuery, options, selfOperations));
316 }
317 ops.push.apply(ops, nestedOperations);
318 if (ops.length === 1) {
319 return ops[0];
320 }
321 return new QueryOperation(query, owneryQuery, options, ops);
322};
323var createQueryOperations = function (query, options) {
324 var selfOperations = [];
325 var nestedOperations = [];
326 if (!isVanillaObject(query)) {
327 selfOperations.push(new EqualsOperation(query, query, options));
328 return [selfOperations, nestedOperations];
329 }
330 for (var key in query) {
331 if (key.charAt(0) === "$") {
332 var op = createNamedOperation(key, query[key], query, options);
333 // probably just a flag for another operation (like $options)
334 if (op != null) {
335 selfOperations.push(op);
336 }
337 }
338 else {
339 nestedOperations.push(createNestedOperation(key.split("."), query[key], query, options));
340 }
341 }
342 return [selfOperations, nestedOperations];
343};
344var createOperationTester = function (operation) { return function (item, key, owner) {
345 operation.reset();
346 operation.next(item, key, owner);
347 return operation.success;
348}; };
349var createQueryTester = function (query, options) {
350 if (options === void 0) { options = {}; }
351 return createOperationTester(createQueryOperation(query, null, options));
352};
353
354var $Ne = /** @class */ (function (_super) {
355 __extends($Ne, _super);
356 function $Ne() {
357 return _super !== null && _super.apply(this, arguments) || this;
358 }
359 $Ne.prototype.init = function () {
360 this._test = createTester(this.params, this.options.compare);
361 };
362 $Ne.prototype.reset = function () {
363 _super.prototype.reset.call(this);
364 this.success = true;
365 };
366 $Ne.prototype.next = function (item) {
367 if (this._test(item)) {
368 this.done = true;
369 this.success = false;
370 }
371 };
372 return $Ne;
373}(NamedBaseOperation));
374// https://docs.mongodb.com/manual/reference/operator/query/elemMatch/
375var $ElemMatch = /** @class */ (function (_super) {
376 __extends($ElemMatch, _super);
377 function $ElemMatch() {
378 return _super !== null && _super.apply(this, arguments) || this;
379 }
380 $ElemMatch.prototype.init = function () {
381 this._queryOperation = createQueryOperation(this.params, this.owneryQuery, this.options);
382 };
383 $ElemMatch.prototype.reset = function () {
384 this._queryOperation.reset();
385 };
386 $ElemMatch.prototype.next = function (item, key, owner) {
387 this._queryOperation.reset();
388 if (isArray(owner)) {
389 this._queryOperation.next(item, key, owner);
390 this.done =
391 this.done || this._queryOperation.done || key === owner.length - 1;
392 this.success = this.success || this._queryOperation.success;
393 }
394 else {
395 this.done = true;
396 this.success = false;
397 }
398 };
399 return $ElemMatch;
400}(NamedBaseOperation));
401var $Not = /** @class */ (function (_super) {
402 __extends($Not, _super);
403 function $Not() {
404 return _super !== null && _super.apply(this, arguments) || this;
405 }
406 $Not.prototype.init = function () {
407 this._queryOperation = createQueryOperation(this.params, this.owneryQuery, this.options);
408 };
409 $Not.prototype.reset = function () {
410 this._queryOperation.reset();
411 };
412 $Not.prototype.next = function (item, key, owner) {
413 this._queryOperation.next(item, key, owner);
414 this.done = this._queryOperation.done;
415 this.success = !this._queryOperation.success;
416 };
417 return $Not;
418}(NamedBaseOperation));
419var $Or = /** @class */ (function (_super) {
420 __extends($Or, _super);
421 function $Or() {
422 return _super !== null && _super.apply(this, arguments) || this;
423 }
424 $Or.prototype.init = function () {
425 var _this = this;
426 this._ops = this.params.map(function (op) {
427 return createQueryOperation(op, null, _this.options);
428 });
429 };
430 $Or.prototype.reset = function () {
431 this.done = false;
432 this.success = false;
433 for (var i = 0, length_1 = this._ops.length; i < length_1; i++) {
434 this._ops[i].reset();
435 }
436 };
437 $Or.prototype.next = function (item, key, owner) {
438 var done = false;
439 var success = false;
440 for (var i = 0, length_2 = this._ops.length; i < length_2; i++) {
441 var op = this._ops[i];
442 op.next(item, key, owner);
443 if (op.success) {
444 done = true;
445 success = op.success;
446 break;
447 }
448 }
449 this.success = success;
450 this.done = done;
451 };
452 return $Or;
453}(NamedBaseOperation));
454var $Nor = /** @class */ (function (_super) {
455 __extends($Nor, _super);
456 function $Nor() {
457 return _super !== null && _super.apply(this, arguments) || this;
458 }
459 $Nor.prototype.next = function (item, key, owner) {
460 _super.prototype.next.call(this, item, key, owner);
461 this.success = !this.success;
462 };
463 return $Nor;
464}($Or));
465var $In = /** @class */ (function (_super) {
466 __extends($In, _super);
467 function $In() {
468 return _super !== null && _super.apply(this, arguments) || this;
469 }
470 $In.prototype.init = function () {
471 var _this = this;
472 this._testers = this.params.map(function (value) {
473 if (containsOperation(value)) {
474 throw new Error("cannot nest $ under " + _this.constructor.name.toLowerCase());
475 }
476 return createTester(value, _this.options.compare);
477 });
478 };
479 $In.prototype.next = function (item, key, owner) {
480 var done = false;
481 var success = false;
482 for (var i = 0, length_3 = this._testers.length; i < length_3; i++) {
483 var test = this._testers[i];
484 if (test(item)) {
485 done = true;
486 success = true;
487 break;
488 }
489 }
490 this.success = success;
491 this.done = done;
492 };
493 return $In;
494}(NamedBaseOperation));
495var $Nin = /** @class */ (function (_super) {
496 __extends($Nin, _super);
497 function $Nin() {
498 return _super !== null && _super.apply(this, arguments) || this;
499 }
500 $Nin.prototype.next = function (item, key, owner) {
501 _super.prototype.next.call(this, item, key, owner);
502 this.success = !this.success;
503 };
504 return $Nin;
505}($In));
506var $Exists = /** @class */ (function (_super) {
507 __extends($Exists, _super);
508 function $Exists() {
509 return _super !== null && _super.apply(this, arguments) || this;
510 }
511 $Exists.prototype.next = function (item, key, owner) {
512 if (owner.hasOwnProperty(key) === this.params) {
513 this.done = true;
514 this.success = true;
515 }
516 };
517 return $Exists;
518}(NamedBaseOperation));
519var $And = /** @class */ (function (_super) {
520 __extends($And, _super);
521 function $And(params, owneryQuery, options, name) {
522 return _super.call(this, params, owneryQuery, options, params.map(function (query) { return createQueryOperation(query, owneryQuery, options); }), name) || this;
523 }
524 $And.prototype.next = function (item, key, owner) {
525 this.childrenNext(item, key, owner);
526 };
527 return $And;
528}(NamedGroupOperation));
529var $eq = function (params, owneryQuery, options) {
530 return new EqualsOperation(params, owneryQuery, options);
531};
532var $ne = function (params, owneryQuery, options, name) { return new $Ne(params, owneryQuery, options, name); };
533var $or = function (params, owneryQuery, options, name) { return new $Or(params, owneryQuery, options, name); };
534var $nor = function (params, owneryQuery, options, name) { return new $Nor(params, owneryQuery, options, name); };
535var $elemMatch = function (params, owneryQuery, options, name) { return new $ElemMatch(params, owneryQuery, options, name); };
536var $nin = function (params, owneryQuery, options, name) { return new $Nin(params, owneryQuery, options, name); };
537var $in = function (params, owneryQuery, options, name) { return new $In(params, owneryQuery, options, name); };
538var $lt = numericalOperation(function (params) { return function (b) { return b < params; }; });
539var $lte = numericalOperation(function (params) { return function (b) { return b <= params; }; });
540var $gt = numericalOperation(function (params) { return function (b) { return b > params; }; });
541var $gte = numericalOperation(function (params) { return function (b) { return b >= params; }; });
542var $mod = function (_a, owneryQuery, options) {
543 var mod = _a[0], equalsValue = _a[1];
544 return new EqualsOperation(function (b) { return comparable(b) % mod === equalsValue; }, owneryQuery, options);
545};
546var $exists = function (params, owneryQuery, options, name) { return new $Exists(params, owneryQuery, options, name); };
547var $regex = function (pattern, owneryQuery, options) {
548 return new EqualsOperation(new RegExp(pattern, owneryQuery.$options), owneryQuery, options);
549};
550var $not = function (params, owneryQuery, options, name) { return new $Not(params, owneryQuery, options, name); };
551var $type = function (clazz, owneryQuery, options) {
552 return new EqualsOperation(function (b) { return (b != null ? b instanceof clazz || b.constructor === clazz : false); }, owneryQuery, options);
553};
554var $and = function (params, ownerQuery, options, name) { return new $And(params, ownerQuery, options, name); };
555var $all = $and;
556var $size = function (params, ownerQuery, options) { return new EqualsOperation(function (b) { return b && b.length === params; }, ownerQuery, options); };
557var $options = function () { return null; };
558var $where = function (params, ownerQuery, options) {
559 var test;
560 if (isFunction(params)) {
561 test = params;
562 }
563 else if (!process.env.CSP_ENABLED) {
564 test = new Function("obj", "return " + params);
565 }
566 else {
567 throw new Error("In CSP mode, sift does not support strings in \"$where\" condition");
568 }
569 return new EqualsOperation(function (b) { return test.bind(b)(b); }, ownerQuery, options);
570};
571
572var defaultOperations = /*#__PURE__*/Object.freeze({
573 __proto__: null,
574 $eq: $eq,
575 $ne: $ne,
576 $or: $or,
577 $nor: $nor,
578 $elemMatch: $elemMatch,
579 $nin: $nin,
580 $in: $in,
581 $lt: $lt,
582 $lte: $lte,
583 $gt: $gt,
584 $gte: $gte,
585 $mod: $mod,
586 $exists: $exists,
587 $regex: $regex,
588 $not: $not,
589 $type: $type,
590 $and: $and,
591 $all: $all,
592 $size: $size,
593 $options: $options,
594 $where: $where
595});
596
597var createDefaultQueryOperation = function (query, ownerQuery, _a) {
598 var _b = _a === void 0 ? {} : _a, compare = _b.compare, operations = _b.operations;
599 return createQueryOperation(query, ownerQuery, {
600 compare: compare,
601 operations: Object.assign({}, defaultOperations, operations || {})
602 });
603};
604var createDefaultQueryTester = function (query, options) {
605 if (options === void 0) { options = {}; }
606 var op = createDefaultQueryOperation(query, null, options);
607 return createOperationTester(op);
608};
609
610export default createDefaultQueryTester;
611export { $all, $and, $elemMatch, $eq, $exists, $gt, $gte, $in, $lt, $lte, $mod, $ne, $nin, $nor, $not, $options, $or, $regex, $size, $type, $where, EqualsOperation, createDefaultQueryOperation, createEqualsOperation, createOperationTester, createQueryOperation, createQueryTester };
612//# sourceMappingURL=index.js.map