@e22m4u/js-repository-mongodb-adapter 0.0.20 → 0.0.21
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 +2 -2
- package/src/mongodb-adapter.js +13 -4
- package/src/mongodb-adapter.spec.js +171 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e22m4u/js-repository-mongodb-adapter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "MongoDB адаптер для @e22m4u/js-repository",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@e22m4u/js-format": "*",
|
|
40
40
|
"@e22m4u/js-service": "*",
|
|
41
|
-
"@e22m4u/js-repository": "~0.0.
|
|
41
|
+
"@e22m4u/js-repository": "~0.0.36"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@commitlint/cli": "^17.7.1",
|
package/src/mongodb-adapter.js
CHANGED
|
@@ -364,15 +364,24 @@ export class MongodbAdapter extends Adapter {
|
|
|
364
364
|
* @private
|
|
365
365
|
*/
|
|
366
366
|
_buildQuery(modelName, clause) {
|
|
367
|
+
if (clause == null) return;
|
|
368
|
+
if (typeof clause !== 'object' || Array.isArray(clause))
|
|
369
|
+
throw new InvalidArgumentError(
|
|
370
|
+
'The provided option "where" should be an Object, but %v given.',
|
|
371
|
+
clause,
|
|
372
|
+
);
|
|
367
373
|
const query = {};
|
|
368
|
-
if (!clause || typeof clause !== 'object') return query;
|
|
369
374
|
const idPropName = this._getIdPropName(modelName);
|
|
370
375
|
Object.keys(clause).forEach(key => {
|
|
371
376
|
let cond = clause[key];
|
|
372
377
|
// and/or/nor clause
|
|
373
378
|
if (key === 'and' || key === 'or' || key === 'nor') {
|
|
374
|
-
if (
|
|
375
|
-
|
|
379
|
+
if (cond == null) return;
|
|
380
|
+
if (!Array.isArray(cond))
|
|
381
|
+
throw new InvalidOperatorValueError(key, 'an Array', cond);
|
|
382
|
+
if (cond.length === 0) return;
|
|
383
|
+
cond = cond.map(c => this._buildQuery(modelName, c));
|
|
384
|
+
cond = cond.filter(c => c != null);
|
|
376
385
|
query['$' + key] = cond;
|
|
377
386
|
return;
|
|
378
387
|
}
|
|
@@ -527,7 +536,7 @@ export class MongodbAdapter extends Adapter {
|
|
|
527
536
|
// unknown
|
|
528
537
|
query[key] = cond;
|
|
529
538
|
});
|
|
530
|
-
return query;
|
|
539
|
+
return Object.keys(query).length ? query : undefined;
|
|
531
540
|
}
|
|
532
541
|
|
|
533
542
|
/**
|
|
@@ -7,6 +7,7 @@ import {DataType} from '@e22m4u/js-repository';
|
|
|
7
7
|
import {createMongodbUrl} from './utils/index.js';
|
|
8
8
|
import {MongodbAdapter} from './mongodb-adapter.js';
|
|
9
9
|
import {AdapterRegistry} from '@e22m4u/js-repository';
|
|
10
|
+
import {InvalidOperatorValueError} from '@e22m4u/js-repository';
|
|
10
11
|
import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '@e22m4u/js-repository';
|
|
11
12
|
|
|
12
13
|
const CONFIG = {
|
|
@@ -274,18 +275,34 @@ describe('MongodbAdapter', function () {
|
|
|
274
275
|
expect(throwable(null)()).to.be.undefined;
|
|
275
276
|
});
|
|
276
277
|
|
|
277
|
-
it('
|
|
278
|
+
it('uses ascending direction by default', async function () {
|
|
278
279
|
const schema = createSchema();
|
|
279
280
|
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
280
281
|
const A = await schema
|
|
281
282
|
.getService(AdapterRegistry)
|
|
282
283
|
.getAdapter('mongodb');
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
284
|
+
const res = A._buildSort('model', 'foo');
|
|
285
|
+
expect(res).to.be.eql({foo: 1});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('uses descending direction by the "DESC" flag', async function () {
|
|
289
|
+
const schema = createSchema();
|
|
290
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
291
|
+
const A = await schema
|
|
292
|
+
.getService(AdapterRegistry)
|
|
293
|
+
.getAdapter('mongodb');
|
|
294
|
+
const res = A._buildSort('model', 'foo DESC');
|
|
295
|
+
expect(res).to.be.eql({foo: -1});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('uses ascending direction by the "ASC" flag', async function () {
|
|
299
|
+
const schema = createSchema();
|
|
300
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
301
|
+
const A = await schema
|
|
302
|
+
.getService(AdapterRegistry)
|
|
303
|
+
.getAdapter('mongodb');
|
|
304
|
+
const res = A._buildSort('model', 'foo ASC');
|
|
305
|
+
expect(res).to.be.eql({foo: 1});
|
|
289
306
|
});
|
|
290
307
|
|
|
291
308
|
it('converts the given property name to the column name', async function () {
|
|
@@ -348,18 +365,44 @@ describe('MongodbAdapter', function () {
|
|
|
348
365
|
expect(throwable(['bar', 'baz'])()).to.be.eql({bar: 1, baz: 1});
|
|
349
366
|
});
|
|
350
367
|
|
|
351
|
-
it('
|
|
368
|
+
it('uses ascending direction by default', async function () {
|
|
369
|
+
const schema = createSchema();
|
|
370
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
371
|
+
const A = await schema
|
|
372
|
+
.getService(AdapterRegistry)
|
|
373
|
+
.getAdapter('mongodb');
|
|
374
|
+
const res = A._buildSort('model', ['foo', 'bar']);
|
|
375
|
+
expect(res).to.be.eql({foo: 1, bar: 1});
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('uses descending direction by the "DESC" flag', async function () {
|
|
379
|
+
const schema = createSchema();
|
|
380
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
381
|
+
const A = await schema
|
|
382
|
+
.getService(AdapterRegistry)
|
|
383
|
+
.getAdapter('mongodb');
|
|
384
|
+
const res = A._buildSort('model', ['foo DESC', 'bar DESC']);
|
|
385
|
+
expect(res).to.be.eql({foo: -1, bar: -1});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('uses ascending direction by the "ASC" flag', async function () {
|
|
389
|
+
const schema = createSchema();
|
|
390
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
391
|
+
const A = await schema
|
|
392
|
+
.getService(AdapterRegistry)
|
|
393
|
+
.getAdapter('mongodb');
|
|
394
|
+
const res = A._buildSort('model', ['foo ASC', 'bar ASC']);
|
|
395
|
+
expect(res).to.be.eql({foo: 1, bar: 1});
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it('uses multiple directions by the multiple fields', async function () {
|
|
352
399
|
const schema = createSchema();
|
|
353
400
|
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
354
401
|
const A = await schema
|
|
355
402
|
.getService(AdapterRegistry)
|
|
356
403
|
.getAdapter('mongodb');
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
const res3 = A._buildSort('model', ['foo ASC', 'bar DESC']);
|
|
360
|
-
expect(res1).to.be.eql({foo: 1, bar: 1});
|
|
361
|
-
expect(res2).to.be.eql({foo: -1, bar: 1});
|
|
362
|
-
expect(res3).to.be.eql({foo: 1, bar: -1});
|
|
404
|
+
const res = A._buildSort('model', ['foo', 'bar DESC', 'baz ASC']);
|
|
405
|
+
expect(res).to.be.eql({foo: 1, bar: -1, baz: 1});
|
|
363
406
|
});
|
|
364
407
|
|
|
365
408
|
it('converts the given property names to column names', async function () {
|
|
@@ -391,6 +434,120 @@ describe('MongodbAdapter', function () {
|
|
|
391
434
|
});
|
|
392
435
|
});
|
|
393
436
|
|
|
437
|
+
describe('_buildQuery', function () {
|
|
438
|
+
it('requires the second argument to be an object', async function () {
|
|
439
|
+
const schema = createSchema();
|
|
440
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
441
|
+
const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
|
|
442
|
+
const throwable = v => () => A._buildQuery('model', v);
|
|
443
|
+
const error = v =>
|
|
444
|
+
format(
|
|
445
|
+
'The provided option "where" should be an Object, but %s given.',
|
|
446
|
+
v,
|
|
447
|
+
);
|
|
448
|
+
expect(throwable('str')).to.throw(error('"str"'));
|
|
449
|
+
expect(throwable('')).to.throw(error('""'));
|
|
450
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
451
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
452
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
453
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
454
|
+
expect(throwable({foo: 'bar'})()).to.be.eql({foo: 'bar'});
|
|
455
|
+
expect(throwable({})()).to.be.undefined;
|
|
456
|
+
expect(throwable(undefined)()).to.be.undefined;
|
|
457
|
+
expect(throwable(null)()).to.be.undefined;
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('converts the property names to column names', async function () {
|
|
461
|
+
const schema = createSchema();
|
|
462
|
+
schema.defineModel({
|
|
463
|
+
name: 'model',
|
|
464
|
+
datasource: 'mongodb',
|
|
465
|
+
properties: {
|
|
466
|
+
foo: {
|
|
467
|
+
type: DataType.STRING,
|
|
468
|
+
columnName: 'bar',
|
|
469
|
+
},
|
|
470
|
+
baz: {
|
|
471
|
+
type: DataType.STRING,
|
|
472
|
+
columnName: 'qux',
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
|
|
477
|
+
const res = A._buildQuery('model', {foo: 'a1', baz: null});
|
|
478
|
+
expect(res).to.be.eql({bar: 'a1', qux: null});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
it('converts strings of the ObjectId to instances', async function () {
|
|
482
|
+
const schema = createSchema();
|
|
483
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
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);
|
|
494
|
+
});
|
|
495
|
+
|
|
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'}],
|
|
501
|
+
};
|
|
502
|
+
const schema = createSchema();
|
|
503
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
504
|
+
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
|
+
});
|
|
511
|
+
});
|
|
512
|
+
|
|
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};
|
|
517
|
+
const schema = createSchema();
|
|
518
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
519
|
+
const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
|
|
520
|
+
const res1 = A._buildQuery('model', input1);
|
|
521
|
+
const res2 = A._buildQuery('model', input2);
|
|
522
|
+
const res3 = A._buildQuery('model', input3);
|
|
523
|
+
expect(res1).to.be.eql({foo: 'a1'});
|
|
524
|
+
expect(res2).to.be.eql({foo: 'a2'});
|
|
525
|
+
expect(res3).to.be.eql({foo: 'a3'});
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it('operators "and", "or" and "nor" are require an array of objects', async function () {
|
|
529
|
+
const schema = createSchema();
|
|
530
|
+
schema.defineModel({name: 'model', datasource: 'mongodb'});
|
|
531
|
+
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;
|
|
536
|
+
};
|
|
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));
|
|
541
|
+
};
|
|
542
|
+
testOf('str');
|
|
543
|
+
testOf('');
|
|
544
|
+
testOf(10);
|
|
545
|
+
testOf(0);
|
|
546
|
+
testOf(true);
|
|
547
|
+
testOf(false);
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
|
|
394
551
|
describe('create', function () {
|
|
395
552
|
it('generates a new identifier when a value of a primary key is not provided', async function () {
|
|
396
553
|
const schema = createSchema();
|