@e22m4u/js-repository-mongodb-adapter 0.0.21 → 0.0.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-repository-mongodb-adapter",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "MongoDB адаптер для @e22m4u/js-repository",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -373,6 +373,11 @@ export class MongodbAdapter extends Adapter {
373
373
  const query = {};
374
374
  const idPropName = this._getIdPropName(modelName);
375
375
  Object.keys(clause).forEach(key => {
376
+ if (String(key).indexOf('$') !== -1)
377
+ throw new InvalidArgumentError(
378
+ 'The symbol "$" is not supported, but %v given.',
379
+ key,
380
+ );
376
381
  let cond = clause[key];
377
382
  // and/or/nor clause
378
383
  if (key === 'and' || key === 'or' || key === 'nor') {
@@ -382,7 +387,9 @@ export class MongodbAdapter extends Adapter {
382
387
  if (cond.length === 0) return;
383
388
  cond = cond.map(c => this._buildQuery(modelName, c));
384
389
  cond = cond.filter(c => c != null);
385
- query['$' + key] = cond;
390
+ const opKey = '$' + key;
391
+ query[opKey] = query[opKey] ?? [];
392
+ query[opKey] = [...query[opKey], ...cond];
386
393
  return;
387
394
  }
388
395
  // id
@@ -403,29 +410,30 @@ export class MongodbAdapter extends Adapter {
403
410
  }
404
411
  // operator
405
412
  if (cond && cond.constructor && cond.constructor.name === 'Object') {
413
+ const opConds = [];
406
414
  // eq
407
415
  if ('eq' in cond) {
408
- query[key] = this._coerceId(cond.eq);
416
+ opConds.push({$eq: this._coerceId(cond.eq)});
409
417
  }
410
418
  // neq
411
419
  if ('neq' in cond) {
412
- query[key] = {$ne: this._coerceId(cond.neq)};
420
+ opConds.push({$ne: this._coerceId(cond.neq)});
413
421
  }
414
422
  // gt
415
423
  if ('gt' in cond) {
416
- query[key] = {$gt: cond.gt};
424
+ opConds.push({$gt: cond.gt});
417
425
  }
418
426
  // lt
419
427
  if ('lt' in cond) {
420
- query[key] = {$lt: cond.lt};
428
+ opConds.push({$lt: cond.lt});
421
429
  }
422
430
  // gte
423
431
  if ('gte' in cond) {
424
- query[key] = {$gte: cond.gte};
432
+ opConds.push({$gte: cond.gte});
425
433
  }
426
434
  // lte
427
435
  if ('lte' in cond) {
428
- query[key] = {$lte: cond.lte};
436
+ opConds.push({$lte: cond.lte});
429
437
  }
430
438
  // inq
431
439
  if ('inq' in cond) {
@@ -435,7 +443,7 @@ export class MongodbAdapter extends Adapter {
435
443
  'an Array of possible values',
436
444
  cond.inq,
437
445
  );
438
- query[key] = {$in: cond.inq.map(v => this._coerceId(v))};
446
+ opConds.push({$in: cond.inq.map(v => this._coerceId(v))});
439
447
  }
440
448
  // nin
441
449
  if ('nin' in cond) {
@@ -445,7 +453,7 @@ export class MongodbAdapter extends Adapter {
445
453
  'an Array of possible values',
446
454
  cond,
447
455
  );
448
- query[key] = {$nin: cond.nin.map(v => this._coerceId(v))};
456
+ opConds.push({$nin: cond.nin.map(v => this._coerceId(v))});
449
457
  }
450
458
  // between
451
459
  if ('between' in cond) {
@@ -455,7 +463,7 @@ export class MongodbAdapter extends Adapter {
455
463
  'an Array of 2 elements',
456
464
  cond.between,
457
465
  );
458
- query[key] = {$gte: cond.between[0], $lte: cond.between[1]};
466
+ opConds.push({$gte: cond.between[0], $lte: cond.between[1]});
459
467
  }
460
468
  // exists
461
469
  if ('exists' in cond) {
@@ -465,7 +473,7 @@ export class MongodbAdapter extends Adapter {
465
473
  'a Boolean',
466
474
  cond.exists,
467
475
  );
468
- query[key] = {$exists: cond.exists};
476
+ opConds.push({$exists: cond.exists});
469
477
  }
470
478
  // like
471
479
  if ('like' in cond) {
@@ -475,7 +483,7 @@ export class MongodbAdapter extends Adapter {
475
483
  'a String or RegExp',
476
484
  cond.like,
477
485
  );
478
- query[key] = {$regex: stringToRegexp(cond.like)};
486
+ opConds.push({$regex: stringToRegexp(cond.like)});
479
487
  }
480
488
  // nlike
481
489
  if ('nlike' in cond) {
@@ -485,7 +493,7 @@ export class MongodbAdapter extends Adapter {
485
493
  'a String or RegExp',
486
494
  cond.nlike,
487
495
  );
488
- query[key] = {$not: stringToRegexp(cond.nlike)};
496
+ opConds.push({$not: stringToRegexp(cond.nlike)});
489
497
  }
490
498
  // ilike
491
499
  if ('ilike' in cond) {
@@ -495,7 +503,7 @@ export class MongodbAdapter extends Adapter {
495
503
  'a String or RegExp',
496
504
  cond.ilike,
497
505
  );
498
- query[key] = {$regex: stringToRegexp(cond.ilike, 'i')};
506
+ opConds.push({$regex: stringToRegexp(cond.ilike, 'i')});
499
507
  }
500
508
  // nilike
501
509
  if ('nilike' in cond) {
@@ -509,7 +517,7 @@ export class MongodbAdapter extends Adapter {
509
517
  cond.nilike,
510
518
  );
511
519
  }
512
- query[key] = {$not: stringToRegexp(cond.nilike, 'i')};
520
+ opConds.push({$not: stringToRegexp(cond.nilike, 'i')});
513
521
  }
514
522
  // regexp and flags (optional)
515
523
  if ('regexp' in cond) {
@@ -529,7 +537,15 @@ export class MongodbAdapter extends Adapter {
529
537
  'RegExp flags must be a String, but %v given.',
530
538
  cond.flags,
531
539
  );
532
- query[key] = {$regex: stringToRegexp(cond.regexp, flags)};
540
+ opConds.push({$regex: stringToRegexp(cond.regexp, flags)});
541
+ }
542
+ // adds a single operator condition
543
+ if (opConds.length === 1) {
544
+ query[key] = opConds[0];
545
+ // adds multiple operator conditions
546
+ } else if (opConds.length > 1) {
547
+ query['$and'] = query['$and'] ?? [];
548
+ opConds.forEach(c => query['$and'].push({[key]: c}));
533
549
  }
534
550
  return;
535
551
  }
@@ -478,42 +478,89 @@ describe('MongodbAdapter', function () {
478
478
  expect(res).to.be.eql({bar: 'a1', qux: null});
479
479
  });
480
480
 
481
- it('converts strings of the ObjectId to instances', async function () {
481
+ it('throws an error when using "$" character', async function () {
482
482
  const schema = createSchema();
483
483
  schema.defineModel({name: 'model', datasource: 'mongodb'});
484
484
  const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
485
- const oid1 = new ObjectId();
486
- const oid2 = new ObjectId();
487
- const id1 = String(oid1);
488
- const id2 = String(oid2);
489
- const res = A._buildQuery('model', {foo: id1, bar: id2});
490
- expect(res.foo).to.be.instanceof(ObjectId);
491
- expect(res.bar).to.be.instanceof(ObjectId);
492
- expect(res.foo).to.be.eql(oid1);
493
- expect(res.bar).to.be.eql(oid2);
485
+ const throwable = () => A._buildQuery('model', {$and: []});
486
+ expect(throwable).to.throw(
487
+ 'The symbol "$" is not supported, but "$and" given.',
488
+ );
494
489
  });
495
490
 
496
- it('adds "$" prefix to the "and", "or" and "nor" operator keys', async function () {
497
- const input = {
498
- and: [{foo: 'a1'}],
499
- or: [{foo: 'a2'}],
500
- nor: [{foo: 'a3'}],
491
+ it('the "and" operator requires an array of objects', async function () {
492
+ const schema = createSchema();
493
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
494
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
495
+ const throwable = v => () => A._buildQuery('model', {and: v});
496
+ const error = v => {
497
+ v = v.replace(/"/g, '$');
498
+ const e = new InvalidOperatorValueError('and', 'an Array', v);
499
+ return e.message.replace(/"/g, '').replace(/\$/g, '"');
501
500
  };
501
+ expect(throwable('str')).to.throw(error('"str"'));
502
+ expect(throwable('')).to.throw(error('""'));
503
+ expect(throwable(10)).to.throw(error('10'));
504
+ expect(throwable(0)).to.throw(error('0'));
505
+ expect(throwable(true)).to.throw(error('true'));
506
+ expect(throwable(false)).to.throw(error('false'));
507
+ });
508
+
509
+ it('the "or" operator requires an array of objects', async function () {
502
510
  const schema = createSchema();
503
511
  schema.defineModel({name: 'model', datasource: 'mongodb'});
504
512
  const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
505
- const res = A._buildQuery('model', input);
506
- expect(res).to.be.eql({
507
- $and: [{foo: 'a1'}],
508
- $or: [{foo: 'a2'}],
509
- $nor: [{foo: 'a3'}],
510
- });
513
+ const throwable = v => () => A._buildQuery('model', {or: v});
514
+ const error = v => {
515
+ v = v.replace(/"/g, '$');
516
+ const e = new InvalidOperatorValueError('or', 'an Array', v);
517
+ return e.message.replace(/"/g, '').replace(/\$/g, '"');
518
+ };
519
+ expect(throwable('str')).to.throw(error('"str"'));
520
+ expect(throwable('')).to.throw(error('""'));
521
+ expect(throwable(10)).to.throw(error('10'));
522
+ expect(throwable(0)).to.throw(error('0'));
523
+ expect(throwable(true)).to.throw(error('true'));
524
+ expect(throwable(false)).to.throw(error('false'));
525
+ });
526
+
527
+ it('the "nor" operator requires an array of objects', async function () {
528
+ const schema = createSchema();
529
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
530
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
531
+ const throwable = v => () => A._buildQuery('model', {nor: v});
532
+ const error = v => {
533
+ v = v.replace(/"/g, '$');
534
+ const e = new InvalidOperatorValueError('nor', 'an Array', v);
535
+ return e.message.replace(/"/g, '').replace(/\$/g, '"');
536
+ };
537
+ expect(throwable('str')).to.throw(error('"str"'));
538
+ expect(throwable('')).to.throw(error('""'));
539
+ expect(throwable(10)).to.throw(error('10'));
540
+ expect(throwable(0)).to.throw(error('0'));
541
+ expect(throwable(true)).to.throw(error('true'));
542
+ expect(throwable(false)).to.throw(error('false'));
543
+ });
544
+
545
+ it('does not include an empty value of "and" operator', async function () {
546
+ const input1 = {foo: 'a1', and: []};
547
+ const input2 = {foo: 'a2', and: undefined};
548
+ const input3 = {foo: 'a3', and: null};
549
+ const schema = createSchema();
550
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
551
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
552
+ const res1 = A._buildQuery('model', input1);
553
+ const res2 = A._buildQuery('model', input2);
554
+ const res3 = A._buildQuery('model', input3);
555
+ expect(res1).to.be.eql({foo: 'a1'});
556
+ expect(res2).to.be.eql({foo: 'a2'});
557
+ expect(res3).to.be.eql({foo: 'a3'});
511
558
  });
512
559
 
513
- it('does not include an empty array of "and", "or" and "nor" operators', async function () {
514
- const input1 = {foo: 'a1', and: [], or: [], nor: []};
515
- const input2 = {foo: 'a2', and: undefined, or: undefined, nor: undefined};
516
- const input3 = {foo: 'a3', and: null, or: null, nor: null};
560
+ it('does not include an empty value of "or" operator', async function () {
561
+ const input1 = {foo: 'a1', or: []};
562
+ const input2 = {foo: 'a2', or: undefined};
563
+ const input3 = {foo: 'a3', or: null};
517
564
  const schema = createSchema();
518
565
  schema.defineModel({name: 'model', datasource: 'mongodb'});
519
566
  const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
@@ -525,26 +572,341 @@ describe('MongodbAdapter', function () {
525
572
  expect(res3).to.be.eql({foo: 'a3'});
526
573
  });
527
574
 
528
- it('operators "and", "or" and "nor" are require an array of objects', async function () {
575
+ it('does not include an empty value of "nor" operator', async function () {
576
+ const input1 = {foo: 'a1', nor: []};
577
+ const input2 = {foo: 'a2', nor: undefined};
578
+ const input3 = {foo: 'a3', nor: null};
579
+ const schema = createSchema();
580
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
581
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
582
+ const res1 = A._buildQuery('model', input1);
583
+ const res2 = A._buildQuery('model', input2);
584
+ const res3 = A._buildQuery('model', input3);
585
+ expect(res1).to.be.eql({foo: 'a1'});
586
+ expect(res2).to.be.eql({foo: 'a2'});
587
+ expect(res3).to.be.eql({foo: 'a3'});
588
+ });
589
+
590
+ it('converts the "and" operator to "$and"', async function () {
591
+ const input = {and: [{foo: 'bar'}, {baz: 'qux'}]};
592
+ const schema = createSchema();
593
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
594
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
595
+ const res = A._buildQuery('model', input);
596
+ expect(res).to.be.eql({$and: [{foo: 'bar'}, {baz: 'qux'}]});
597
+ });
598
+
599
+ it('converts the "or" operator to "$or"', async function () {
600
+ const input = {or: [{foo: 'bar'}, {baz: 'qux'}]};
601
+ const schema = createSchema();
602
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
603
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
604
+ const res = A._buildQuery('model', input);
605
+ expect(res).to.be.eql({$or: [{foo: 'bar'}, {baz: 'qux'}]});
606
+ });
607
+
608
+ it('converts the "nor" operator to "$nor"', async function () {
609
+ const input = {nor: [{foo: 'bar'}, {baz: 'qux'}]};
610
+ const schema = createSchema();
611
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
612
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
613
+ const res = A._buildQuery('model', input);
614
+ expect(res).to.be.eql({$nor: [{foo: 'bar'}, {baz: 'qux'}]});
615
+ });
616
+
617
+ it('converts the "eq" operator to "$eq"', async function () {
618
+ const input = {foo: {eq: 'bar'}};
619
+ const schema = createSchema();
620
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
621
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
622
+ const res = A._buildQuery('model', input);
623
+ expect(res).to.be.eql({foo: {$eq: 'bar'}});
624
+ });
625
+
626
+ it('converts the "neq" operator to "$ne"', async function () {
627
+ const input = {foo: {neq: 'bar'}};
628
+ const schema = createSchema();
629
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
630
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
631
+ const res = A._buildQuery('model', input);
632
+ expect(res).to.be.eql({foo: {$ne: 'bar'}});
633
+ });
634
+
635
+ it('converts the "gt" operator to "$gt"', async function () {
636
+ const input = {foo: {gt: 5}};
637
+ const schema = createSchema();
638
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
639
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
640
+ const res = A._buildQuery('model', input);
641
+ expect(res).to.be.eql({foo: {$gt: 5}});
642
+ });
643
+
644
+ it('converts the "lt" operator to "$lt"', async function () {
645
+ const input = {foo: {lt: 5}};
646
+ const schema = createSchema();
647
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
648
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
649
+ const res = A._buildQuery('model', input);
650
+ expect(res).to.be.eql({foo: {$lt: 5}});
651
+ });
652
+
653
+ it('converts the "gte" operator to "$gte"', async function () {
654
+ const input = {foo: {gte: 5}};
655
+ const schema = createSchema();
656
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
657
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
658
+ const res = A._buildQuery('model', input);
659
+ expect(res).to.be.eql({foo: {$gte: 5}});
660
+ });
661
+
662
+ it('converts the "lte" operator to "$lte"', async function () {
663
+ const input = {foo: {lte: 5}};
664
+ const schema = createSchema();
665
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
666
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
667
+ const res = A._buildQuery('model', input);
668
+ expect(res).to.be.eql({foo: {$lte: 5}});
669
+ });
670
+
671
+ it('converts the "inq" operator to "$in"', async function () {
672
+ const input = {foo: {inq: [1, 2, 3]}};
673
+ const schema = createSchema();
674
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
675
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
676
+ const res = A._buildQuery('model', input);
677
+ expect(res).to.be.eql({foo: {$in: [1, 2, 3]}});
678
+ });
679
+
680
+ it('converts the "nin" operator to "$nin"', async function () {
681
+ const input = {foo: {nin: ['a', 'b', 'c']}};
682
+ const schema = createSchema();
683
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
684
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
685
+ const res = A._buildQuery('model', input);
686
+ expect(res).to.be.eql({foo: {$nin: ['a', 'b', 'c']}});
687
+ });
688
+
689
+ it('converts the "between" operator to "$gte" and "$lte"', async function () {
690
+ const input = {foo: {between: [1, 10]}};
691
+ const schema = createSchema();
692
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
693
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
694
+ const res = A._buildQuery('model', input);
695
+ const expected = {foo: {$gte: 1, $lte: 10}};
696
+ expect(res).to.be.eql(expected);
697
+ });
698
+
699
+ it('converts the "exists" operator to "$exists"', async function () {
700
+ const input1 = {foo: {exists: true}};
701
+ const input2 = {foo: {exists: false}};
529
702
  const schema = createSchema();
530
703
  schema.defineModel({name: 'model', datasource: 'mongodb'});
531
704
  const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
532
- const throwable = (k, v) => () => A._buildQuery('model', {[k]: v});
533
- const error = (k, v) => {
534
- const e = new InvalidOperatorValueError(k, 'an Array', v);
535
- return e.message;
705
+ const res1 = A._buildQuery('model', input1);
706
+ const res2 = A._buildQuery('model', input2);
707
+ expect(res1).to.be.eql({foo: {$exists: true}});
708
+ expect(res2).to.be.eql({foo: {$exists: false}});
709
+ });
710
+
711
+ it('converts the "like" operator to "$regex"', async function () {
712
+ const input = {foo: {like: 'test'}};
713
+ const schema = createSchema();
714
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
715
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
716
+ const res = A._buildQuery('model', input);
717
+ expect(res).to.be.eql({foo: {$regex: /test/}});
718
+ });
719
+
720
+ it('converts the "nlike" operator to "$not"', async function () {
721
+ const input = {foo: {nlike: 'test'}};
722
+ const schema = createSchema();
723
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
724
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
725
+ const res = A._buildQuery('model', input);
726
+ expect(res).to.be.eql({foo: {$not: /test/}});
727
+ });
728
+
729
+ it('converts the "ilike" operator to "$regex" with "i" flag', async function () {
730
+ const input = {foo: {ilike: 'test'}};
731
+ const schema = createSchema();
732
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
733
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
734
+ const res = A._buildQuery('model', input);
735
+ expect(res).to.be.eql({foo: {$regex: /test/i}});
736
+ });
737
+
738
+ it('converts the "nilike" operator to "$not" with "i" flag', async function () {
739
+ const input = {foo: {nilike: 'test'}};
740
+ const schema = createSchema();
741
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
742
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
743
+ const res = A._buildQuery('model', input);
744
+ expect(res).to.be.eql({foo: {$not: /test/i}});
745
+ });
746
+
747
+ it('converts property value to an instance of ObjectId', async function () {
748
+ const oid = new ObjectId();
749
+ const id = String(oid);
750
+ const input = {foo: id};
751
+ const schema = createSchema();
752
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
753
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
754
+ const res = A._buildQuery('model', input);
755
+ expect(res.foo).to.be.instanceof(ObjectId);
756
+ expect(res.foo).to.be.eql(oid);
757
+ });
758
+
759
+ it('the "eq" operator converts ObjectId string to an instance', async function () {
760
+ const oid = new ObjectId();
761
+ const id = oid.toString();
762
+ const input = {foo: {eq: id}};
763
+ const schema = createSchema();
764
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
765
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
766
+ const {
767
+ foo: {$eq: res},
768
+ } = A._buildQuery('model', input);
769
+ expect(res).to.be.instanceOf(ObjectId);
770
+ expect(res).to.be.eql(oid);
771
+ });
772
+
773
+ it('the "neq" operator converts ObjectId string to an instance', async function () {
774
+ const oid = new ObjectId();
775
+ const id = oid.toString();
776
+ const input = {foo: {neq: id}};
777
+ const schema = createSchema();
778
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
779
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
780
+ const {
781
+ foo: {$ne: res},
782
+ } = A._buildQuery('model', input);
783
+ expect(res).to.be.instanceOf(ObjectId);
784
+ expect(res).to.be.eql(oid);
785
+ });
786
+
787
+ it('the "inq" operator converts ObjectId string to an instance', async function () {
788
+ const oid = new ObjectId();
789
+ const id = oid.toString();
790
+ const input = {foo: {inq: [id]}};
791
+ const schema = createSchema();
792
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
793
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
794
+ const {
795
+ foo: {$in: res},
796
+ } = A._buildQuery('model', input);
797
+ expect(res[0]).to.be.instanceOf(ObjectId);
798
+ expect(res[0]).to.be.eql(oid);
799
+ });
800
+
801
+ it('the "nin" operator converts ObjectId string to an instance', async function () {
802
+ const oid = new ObjectId();
803
+ const id = oid.toString();
804
+ const input = {foo: {nin: [id]}};
805
+ const schema = createSchema();
806
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
807
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
808
+ const {
809
+ foo: {$nin: res},
810
+ } = A._buildQuery('model', input);
811
+ expect(res[0]).to.be.instanceOf(ObjectId);
812
+ expect(res[0]).to.be.eql(oid);
813
+ });
814
+
815
+ it('combines the given operators by the "and" clause', async function () {
816
+ const input = {
817
+ foo: {
818
+ eq: 'bar',
819
+ neq: 'baz',
820
+ gt: 5,
821
+ lt: 10,
822
+ gte: 6,
823
+ lte: 9,
824
+ inq: ['qux'],
825
+ nin: ['qwe'],
826
+ between: [100, 200],
827
+ exists: true,
828
+ like: 'asd',
829
+ nlike: 'zxc',
830
+ ilike: 'rty',
831
+ nilike: 'fgh',
832
+ regexp: 'vbn',
833
+ flags: 'i',
834
+ },
536
835
  };
537
- const testOf = v => {
538
- expect(throwable('and', v)).to.throw(error('and', v));
539
- expect(throwable('or', v)).to.throw(error('or', v));
540
- expect(throwable('nor', v)).to.throw(error('nor', v));
836
+ const expected = {
837
+ $and: [
838
+ {foo: {$eq: 'bar'}},
839
+ {foo: {$ne: 'baz'}},
840
+ {foo: {$gt: 5}},
841
+ {foo: {$lt: 10}},
842
+ {foo: {$gte: 6}},
843
+ {foo: {$lte: 9}},
844
+ {foo: {$in: ['qux']}},
845
+ {foo: {$nin: ['qwe']}},
846
+ {foo: {$gte: 100, $lte: 200}},
847
+ {foo: {$exists: true}},
848
+ {foo: {$regex: /asd/}},
849
+ {foo: {$not: /zxc/}},
850
+ {foo: {$regex: /rty/i}},
851
+ {foo: {$not: /fgh/i}},
852
+ {foo: {$regex: /vbn/i}},
853
+ ],
541
854
  };
542
- testOf('str');
543
- testOf('');
544
- testOf(10);
545
- testOf(0);
546
- testOf(true);
547
- testOf(false);
855
+ const schema = createSchema();
856
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
857
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
858
+ const res = A._buildQuery('model', input);
859
+ expect(res).to.be.eql(expected);
860
+ });
861
+
862
+ it('combines the given operators by the existing "and" clause', async function () {
863
+ const input = {
864
+ and: [{featured: true}, {removed: false}],
865
+ foo: {
866
+ eq: 'bar',
867
+ neq: 'baz',
868
+ gt: 5,
869
+ lt: 10,
870
+ gte: 6,
871
+ lte: 9,
872
+ inq: ['qux'],
873
+ nin: ['qwe'],
874
+ between: [100, 200],
875
+ exists: true,
876
+ like: 'asd',
877
+ nlike: 'zxc',
878
+ ilike: 'rty',
879
+ nilike: 'fgh',
880
+ regexp: 'vbn',
881
+ flags: 'i',
882
+ },
883
+ };
884
+ const expected = {
885
+ $and: [
886
+ {featured: true},
887
+ {removed: false},
888
+ {foo: {$eq: 'bar'}},
889
+ {foo: {$ne: 'baz'}},
890
+ {foo: {$gt: 5}},
891
+ {foo: {$lt: 10}},
892
+ {foo: {$gte: 6}},
893
+ {foo: {$lte: 9}},
894
+ {foo: {$in: ['qux']}},
895
+ {foo: {$nin: ['qwe']}},
896
+ {foo: {$gte: 100, $lte: 200}},
897
+ {foo: {$exists: true}},
898
+ {foo: {$regex: /asd/}},
899
+ {foo: {$not: /zxc/}},
900
+ {foo: {$regex: /rty/i}},
901
+ {foo: {$not: /fgh/i}},
902
+ {foo: {$regex: /vbn/i}},
903
+ ],
904
+ };
905
+ const schema = createSchema();
906
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
907
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
908
+ const res = A._buildQuery('model', input);
909
+ expect(res).to.be.eql(expected);
548
910
  });
549
911
  });
550
912