@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 +1 -1
- package/src/mongodb-adapter.js +67 -16
- package/src/mongodb-adapter.spec.js +544 -40
- package/src/utils/is-iso-date.js +1 -1
package/package.json
CHANGED
package/src/mongodb-adapter.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
443
|
+
const gt = this._coerceDate(cond.gt);
|
|
444
|
+
opConds.push({$gt: gt});
|
|
417
445
|
}
|
|
418
446
|
// lt
|
|
419
447
|
if ('lt' in cond) {
|
|
420
|
-
|
|
448
|
+
const lt = this._coerceDate(cond.lt);
|
|
449
|
+
opConds.push({$lt: lt});
|
|
421
450
|
}
|
|
422
451
|
// gte
|
|
423
452
|
if ('gte' in cond) {
|
|
424
|
-
|
|
453
|
+
const gte = this._coerceDate(cond.gte);
|
|
454
|
+
opConds.push({$gte: gte});
|
|
425
455
|
}
|
|
426
456
|
// lte
|
|
427
457
|
if ('lte' in cond) {
|
|
428
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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('
|
|
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
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
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('
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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('
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
const
|
|
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('
|
|
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
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
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
|
|
package/src/utils/is-iso-date.js
CHANGED