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

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.23",
4
4
  "description": "MongoDB адаптер для @e22m4u/js-repository",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -160,6 +160,20 @@ export class MongodbAdapter extends Adapter {
160
160
  return value;
161
161
  }
162
162
 
163
+ /**
164
+ * Coerce date.
165
+ *
166
+ * @param value
167
+ * @returns {Date|*}
168
+ * @private
169
+ */
170
+ _coerceDate(value) {
171
+ if (value == null) return value;
172
+ if (value instanceof Date) return value;
173
+ if (isIsoDate(value)) return new Date(value);
174
+ return value;
175
+ }
176
+
163
177
  /**
164
178
  * To database.
165
179
  *
@@ -373,6 +387,11 @@ export class MongodbAdapter extends Adapter {
373
387
  const query = {};
374
388
  const idPropName = this._getIdPropName(modelName);
375
389
  Object.keys(clause).forEach(key => {
390
+ if (String(key).indexOf('$') !== -1)
391
+ throw new InvalidArgumentError(
392
+ 'The symbol "$" is not supported, but %v given.',
393
+ key,
394
+ );
376
395
  let cond = clause[key];
377
396
  // and/or/nor clause
378
397
  if (key === 'and' || key === 'or' || key === 'nor') {
@@ -382,7 +401,9 @@ export class MongodbAdapter extends Adapter {
382
401
  if (cond.length === 0) return;
383
402
  cond = cond.map(c => this._buildQuery(modelName, c));
384
403
  cond = cond.filter(c => c != null);
385
- query['$' + key] = cond;
404
+ const opKey = '$' + key;
405
+ query[opKey] = query[opKey] ?? [];
406
+ query[opKey] = [...query[opKey], ...cond];
386
407
  return;
387
408
  }
388
409
  // id
@@ -394,6 +415,7 @@ export class MongodbAdapter extends Adapter {
394
415
  // string
395
416
  if (typeof cond === 'string') {
396
417
  query[key] = this._coerceId(cond);
418
+ query[key] = this._coerceDate(query[key]);
397
419
  return;
398
420
  }
399
421
  // ObjectId
@@ -403,29 +425,38 @@ export class MongodbAdapter extends Adapter {
403
425
  }
404
426
  // operator
405
427
  if (cond && cond.constructor && cond.constructor.name === 'Object') {
428
+ const opConds = [];
406
429
  // eq
407
430
  if ('eq' in cond) {
408
- query[key] = this._coerceId(cond.eq);
431
+ let eq = this._coerceId(cond.eq);
432
+ eq = this._coerceDate(eq);
433
+ opConds.push({$eq: eq});
409
434
  }
410
435
  // neq
411
436
  if ('neq' in cond) {
412
- query[key] = {$ne: this._coerceId(cond.neq)};
437
+ let neq = this._coerceId(cond.neq);
438
+ neq = this._coerceDate(neq);
439
+ opConds.push({$ne: neq});
413
440
  }
414
441
  // gt
415
442
  if ('gt' in cond) {
416
- query[key] = {$gt: cond.gt};
443
+ const gt = this._coerceDate(cond.gt);
444
+ opConds.push({$gt: gt});
417
445
  }
418
446
  // lt
419
447
  if ('lt' in cond) {
420
- query[key] = {$lt: cond.lt};
448
+ const lt = this._coerceDate(cond.lt);
449
+ opConds.push({$lt: lt});
421
450
  }
422
451
  // gte
423
452
  if ('gte' in cond) {
424
- query[key] = {$gte: cond.gte};
453
+ const gte = this._coerceDate(cond.gte);
454
+ opConds.push({$gte: gte});
425
455
  }
426
456
  // lte
427
457
  if ('lte' in cond) {
428
- query[key] = {$lte: cond.lte};
458
+ const lte = this._coerceDate(cond.lte);
459
+ opConds.push({$lte: lte});
429
460
  }
430
461
  // inq
431
462
  if ('inq' in cond) {
@@ -435,7 +466,12 @@ export class MongodbAdapter extends Adapter {
435
466
  'an Array of possible values',
436
467
  cond.inq,
437
468
  );
438
- query[key] = {$in: cond.inq.map(v => this._coerceId(v))};
469
+ const inq = cond.inq.map(v => {
470
+ v = this._coerceId(v);
471
+ v = this._coerceDate(v);
472
+ return v;
473
+ });
474
+ opConds.push({$in: inq});
439
475
  }
440
476
  // nin
441
477
  if ('nin' in cond) {
@@ -445,7 +481,12 @@ export class MongodbAdapter extends Adapter {
445
481
  'an Array of possible values',
446
482
  cond,
447
483
  );
448
- query[key] = {$nin: cond.nin.map(v => this._coerceId(v))};
484
+ const nin = cond.nin.map(v => {
485
+ v = this._coerceId(v);
486
+ v = this._coerceDate(v);
487
+ return v;
488
+ });
489
+ opConds.push({$nin: nin});
449
490
  }
450
491
  // between
451
492
  if ('between' in cond) {
@@ -455,7 +496,9 @@ export class MongodbAdapter extends Adapter {
455
496
  'an Array of 2 elements',
456
497
  cond.between,
457
498
  );
458
- query[key] = {$gte: cond.between[0], $lte: cond.between[1]};
499
+ const gte = this._coerceDate(cond.between[0]);
500
+ const lte = this._coerceDate(cond.between[1]);
501
+ opConds.push({$gte: gte, $lte: lte});
459
502
  }
460
503
  // exists
461
504
  if ('exists' in cond) {
@@ -465,7 +508,7 @@ export class MongodbAdapter extends Adapter {
465
508
  'a Boolean',
466
509
  cond.exists,
467
510
  );
468
- query[key] = {$exists: cond.exists};
511
+ opConds.push({$exists: cond.exists});
469
512
  }
470
513
  // like
471
514
  if ('like' in cond) {
@@ -475,7 +518,7 @@ export class MongodbAdapter extends Adapter {
475
518
  'a String or RegExp',
476
519
  cond.like,
477
520
  );
478
- query[key] = {$regex: stringToRegexp(cond.like)};
521
+ opConds.push({$regex: stringToRegexp(cond.like)});
479
522
  }
480
523
  // nlike
481
524
  if ('nlike' in cond) {
@@ -485,7 +528,7 @@ export class MongodbAdapter extends Adapter {
485
528
  'a String or RegExp',
486
529
  cond.nlike,
487
530
  );
488
- query[key] = {$not: stringToRegexp(cond.nlike)};
531
+ opConds.push({$not: stringToRegexp(cond.nlike)});
489
532
  }
490
533
  // ilike
491
534
  if ('ilike' in cond) {
@@ -495,7 +538,7 @@ export class MongodbAdapter extends Adapter {
495
538
  'a String or RegExp',
496
539
  cond.ilike,
497
540
  );
498
- query[key] = {$regex: stringToRegexp(cond.ilike, 'i')};
541
+ opConds.push({$regex: stringToRegexp(cond.ilike, 'i')});
499
542
  }
500
543
  // nilike
501
544
  if ('nilike' in cond) {
@@ -509,7 +552,7 @@ export class MongodbAdapter extends Adapter {
509
552
  cond.nilike,
510
553
  );
511
554
  }
512
- query[key] = {$not: stringToRegexp(cond.nilike, 'i')};
555
+ opConds.push({$not: stringToRegexp(cond.nilike, 'i')});
513
556
  }
514
557
  // regexp and flags (optional)
515
558
  if ('regexp' in cond) {
@@ -529,7 +572,15 @@ export class MongodbAdapter extends Adapter {
529
572
  'RegExp flags must be a String, but %v given.',
530
573
  cond.flags,
531
574
  );
532
- query[key] = {$regex: stringToRegexp(cond.regexp, flags)};
575
+ opConds.push({$regex: stringToRegexp(cond.regexp, flags)});
576
+ }
577
+ // adds a single operator condition
578
+ if (opConds.length === 1) {
579
+ query[key] = opConds[0];
580
+ // adds multiple operator conditions
581
+ } else if (opConds.length > 1) {
582
+ query['$and'] = query['$and'] ?? [];
583
+ opConds.forEach(c => query['$and'].push({[key]: c}));
533
584
  }
534
585
  return;
535
586
  }
@@ -478,42 +478,74 @@ 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'));
511
525
  });
512
526
 
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};
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};
517
549
  const schema = createSchema();
518
550
  schema.defineModel({name: 'model', datasource: 'mongodb'});
519
551
  const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
@@ -525,26 +557,498 @@ describe('MongodbAdapter', function () {
525
557
  expect(res3).to.be.eql({foo: 'a3'});
526
558
  });
527
559
 
528
- it('operators "and", "or" and "nor" are require an array of objects', async function () {
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};
564
+ const schema = createSchema();
565
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
566
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
567
+ const res1 = A._buildQuery('model', input1);
568
+ const res2 = A._buildQuery('model', input2);
569
+ const res3 = A._buildQuery('model', input3);
570
+ expect(res1).to.be.eql({foo: 'a1'});
571
+ expect(res2).to.be.eql({foo: 'a2'});
572
+ expect(res3).to.be.eql({foo: 'a3'});
573
+ });
574
+
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}};
702
+ const schema = createSchema();
703
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
704
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
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'}};
529
740
  const schema = createSchema();
530
741
  schema.defineModel({name: 'model', datasource: 'mongodb'});
531
742
  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;
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('converts property value to an instance of Date', async function () {
816
+ const date = new Date();
817
+ const isoDate = date.toISOString();
818
+ const input = {foo: isoDate};
819
+ const schema = createSchema();
820
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
821
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
822
+ const res = A._buildQuery('model', input);
823
+ expect(res.foo).to.be.instanceof(Date);
824
+ expect(res.foo).to.be.eql(date);
825
+ });
826
+
827
+ it('the "eq" operator converts Date string to an instance', async function () {
828
+ const date = new Date();
829
+ const isoDate = date.toISOString();
830
+ const input = {foo: {eq: isoDate}};
831
+ const schema = createSchema();
832
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
833
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
834
+ const {
835
+ foo: {$eq: res},
836
+ } = A._buildQuery('model', input);
837
+ expect(res).to.be.instanceOf(Date);
838
+ expect(res).to.be.eql(date);
839
+ });
840
+
841
+ it('the "neq" operator converts Date string to an instance', async function () {
842
+ const date = new Date();
843
+ const isoDate = date.toISOString();
844
+ const input = {foo: {neq: isoDate}};
845
+ const schema = createSchema();
846
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
847
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
848
+ const {
849
+ foo: {$ne: res},
850
+ } = A._buildQuery('model', input);
851
+ expect(res).to.be.instanceOf(Date);
852
+ expect(res).to.be.eql(date);
853
+ });
854
+
855
+ it('the "gt" operator converts Date string to an instance', async function () {
856
+ const date = new Date();
857
+ const isoDate = date.toISOString();
858
+ const input = {foo: {gt: isoDate}};
859
+ const schema = createSchema();
860
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
861
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
862
+ const {
863
+ foo: {$gt: res},
864
+ } = A._buildQuery('model', input);
865
+ expect(res).to.be.instanceOf(Date);
866
+ expect(res).to.be.eql(date);
867
+ });
868
+
869
+ it('the "lt" operator converts Date string to an instance', async function () {
870
+ const date = new Date();
871
+ const isoDate = date.toISOString();
872
+ const input = {foo: {lt: isoDate}};
873
+ const schema = createSchema();
874
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
875
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
876
+ const {
877
+ foo: {$lt: res},
878
+ } = A._buildQuery('model', input);
879
+ expect(res).to.be.instanceOf(Date);
880
+ expect(res).to.be.eql(date);
881
+ });
882
+
883
+ it('the "gte" operator converts Date string to an instance', async function () {
884
+ const date = new Date();
885
+ const isoDate = date.toISOString();
886
+ const input = {foo: {gte: isoDate}};
887
+ const schema = createSchema();
888
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
889
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
890
+ const {
891
+ foo: {$gte: res},
892
+ } = A._buildQuery('model', input);
893
+ expect(res).to.be.instanceOf(Date);
894
+ expect(res).to.be.eql(date);
895
+ });
896
+
897
+ it('the "lte" operator converts Date string to an instance', async function () {
898
+ const date = new Date();
899
+ const isoDate = date.toISOString();
900
+ const input = {foo: {lte: isoDate}};
901
+ const schema = createSchema();
902
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
903
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
904
+ const {
905
+ foo: {$lte: res},
906
+ } = A._buildQuery('model', input);
907
+ expect(res).to.be.instanceOf(Date);
908
+ expect(res).to.be.eql(date);
909
+ });
910
+
911
+ it('the "inq" operator converts Date string to an instance', async function () {
912
+ const date = new Date();
913
+ const isoDate = date.toISOString();
914
+ const input = {foo: {inq: [isoDate]}};
915
+ const schema = createSchema();
916
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
917
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
918
+ const {
919
+ foo: {$in: res},
920
+ } = A._buildQuery('model', input);
921
+ expect(res[0]).to.be.instanceOf(Date);
922
+ expect(res[0]).to.be.eql(date);
923
+ });
924
+
925
+ it('the "nin" operator converts Date string to an instance', async function () {
926
+ const date = new Date();
927
+ const isoDate = date.toISOString();
928
+ const input = {foo: {nin: [isoDate]}};
929
+ const schema = createSchema();
930
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
931
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
932
+ const {
933
+ foo: {$nin: res},
934
+ } = A._buildQuery('model', input);
935
+ expect(res[0]).to.be.instanceOf(Date);
936
+ expect(res[0]).to.be.eql(date);
937
+ });
938
+
939
+ it('the "between" operator converts Date string to an instance', async function () {
940
+ const date1 = new Date();
941
+ const date2 = new Date();
942
+ const isoDate1 = date1.toISOString();
943
+ const isoDate2 = date2.toISOString();
944
+ const input = {foo: {between: [isoDate1, isoDate2]}};
945
+ const schema = createSchema();
946
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
947
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
948
+ const {
949
+ foo: {$gte: res1, $lte: res2},
950
+ } = A._buildQuery('model', input);
951
+ expect(res1).to.be.instanceOf(Date);
952
+ expect(res1).to.be.eql(date1);
953
+ expect(res2).to.be.instanceOf(Date);
954
+ expect(res2).to.be.eql(date2);
955
+ });
956
+
957
+ it('combines the given operators by the "and" clause', async function () {
958
+ const input = {
959
+ foo: {
960
+ eq: 'bar',
961
+ neq: 'baz',
962
+ gt: 5,
963
+ lt: 10,
964
+ gte: 6,
965
+ lte: 9,
966
+ inq: ['qux'],
967
+ nin: ['qwe'],
968
+ between: [100, 200],
969
+ exists: true,
970
+ like: 'asd',
971
+ nlike: 'zxc',
972
+ ilike: 'rty',
973
+ nilike: 'fgh',
974
+ regexp: 'vbn',
975
+ flags: 'i',
976
+ },
977
+ };
978
+ const expected = {
979
+ $and: [
980
+ {foo: {$eq: 'bar'}},
981
+ {foo: {$ne: 'baz'}},
982
+ {foo: {$gt: 5}},
983
+ {foo: {$lt: 10}},
984
+ {foo: {$gte: 6}},
985
+ {foo: {$lte: 9}},
986
+ {foo: {$in: ['qux']}},
987
+ {foo: {$nin: ['qwe']}},
988
+ {foo: {$gte: 100, $lte: 200}},
989
+ {foo: {$exists: true}},
990
+ {foo: {$regex: /asd/}},
991
+ {foo: {$not: /zxc/}},
992
+ {foo: {$regex: /rty/i}},
993
+ {foo: {$not: /fgh/i}},
994
+ {foo: {$regex: /vbn/i}},
995
+ ],
996
+ };
997
+ const schema = createSchema();
998
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
999
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
1000
+ const res = A._buildQuery('model', input);
1001
+ expect(res).to.be.eql(expected);
1002
+ });
1003
+
1004
+ it('combines the given operators by the existing "and" clause', async function () {
1005
+ const input = {
1006
+ and: [{featured: true}, {removed: false}],
1007
+ foo: {
1008
+ eq: 'bar',
1009
+ neq: 'baz',
1010
+ gt: 5,
1011
+ lt: 10,
1012
+ gte: 6,
1013
+ lte: 9,
1014
+ inq: ['qux'],
1015
+ nin: ['qwe'],
1016
+ between: [100, 200],
1017
+ exists: true,
1018
+ like: 'asd',
1019
+ nlike: 'zxc',
1020
+ ilike: 'rty',
1021
+ nilike: 'fgh',
1022
+ regexp: 'vbn',
1023
+ flags: 'i',
1024
+ },
536
1025
  };
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));
1026
+ const expected = {
1027
+ $and: [
1028
+ {featured: true},
1029
+ {removed: false},
1030
+ {foo: {$eq: 'bar'}},
1031
+ {foo: {$ne: 'baz'}},
1032
+ {foo: {$gt: 5}},
1033
+ {foo: {$lt: 10}},
1034
+ {foo: {$gte: 6}},
1035
+ {foo: {$lte: 9}},
1036
+ {foo: {$in: ['qux']}},
1037
+ {foo: {$nin: ['qwe']}},
1038
+ {foo: {$gte: 100, $lte: 200}},
1039
+ {foo: {$exists: true}},
1040
+ {foo: {$regex: /asd/}},
1041
+ {foo: {$not: /zxc/}},
1042
+ {foo: {$regex: /rty/i}},
1043
+ {foo: {$not: /fgh/i}},
1044
+ {foo: {$regex: /vbn/i}},
1045
+ ],
541
1046
  };
542
- testOf('str');
543
- testOf('');
544
- testOf(10);
545
- testOf(0);
546
- testOf(true);
547
- testOf(false);
1047
+ const schema = createSchema();
1048
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
1049
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
1050
+ const res = A._buildQuery('model', input);
1051
+ expect(res).to.be.eql(expected);
548
1052
  });
549
1053
  });
550
1054
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Is iso date string.
2
+ * Is iso date.
3
3
  *
4
4
  * @param value
5
5
  * @return {boolean}