@e22m4u/js-repository-mongodb-adapter 0.2.0 → 0.2.1

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.
@@ -253,6 +253,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
253
253
  * Get id prop name.
254
254
  *
255
255
  * @param modelName
256
+ * @private
256
257
  */
257
258
  _getIdPropName(modelName) {
258
259
  return this.getService(import_js_repository8.ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
@@ -263,6 +264,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
263
264
  * Get id col name.
264
265
  *
265
266
  * @param modelName
267
+ * @private
266
268
  */
267
269
  _getIdColName(modelName) {
268
270
  return this.getService(import_js_repository8.ModelDefinitionUtils).getPrimaryKeyAsColumnName(
@@ -273,7 +275,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
273
275
  * Coerce id.
274
276
  *
275
277
  * @param value
276
- * @return {ObjectId|*}
278
+ * @returns {ObjectId|*}
277
279
  * @private
278
280
  */
279
281
  _coerceId(value) {
@@ -299,7 +301,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
299
301
  *
300
302
  * @param {string} modelName
301
303
  * @param {object} modelData
302
- * @return {object}
304
+ * @returns {object}
303
305
  * @private
304
306
  */
305
307
  _toDatabase(modelName, modelData) {
@@ -329,7 +331,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
329
331
  *
330
332
  * @param {string} modelName
331
333
  * @param {object} tableData
332
- * @return {object}
334
+ * @returns {object}
333
335
  * @private
334
336
  */
335
337
  _fromDatabase(modelName, tableData) {
@@ -358,7 +360,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
358
360
  * Get collection.
359
361
  *
360
362
  * @param {string} modelName
361
- * @return {*}
363
+ * @returns {*}
362
364
  * @private
363
365
  */
364
366
  _getCollection(modelName) {
@@ -373,7 +375,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
373
375
  * Get id type.
374
376
  *
375
377
  * @param modelName
376
- * @return {string|*}
378
+ * @returns {string|*}
377
379
  * @private
378
380
  */
379
381
  _getIdType(modelName) {
@@ -381,42 +383,18 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
381
383
  const pkPropName = utils.getPrimaryKeyAsPropertyName(modelName);
382
384
  return utils.getDataTypeByPropertyName(modelName, pkPropName);
383
385
  }
384
- /**
385
- * Build projection.
386
- *
387
- * @param {string} modelName
388
- * @param {string|string[]} fields
389
- * @return {Record<string, number>|undefined}
390
- * @private
391
- */
392
- _buildProjection(modelName, fields) {
393
- if (fields == null) return;
394
- if (Array.isArray(fields) === false) fields = [fields];
395
- if (!fields.length) return;
396
- if (fields.indexOf("_id") === -1) fields.push("_id");
397
- return fields.reduce((acc, field) => {
398
- if (!field || typeof field !== "string")
399
- throw new import_js_repository9.InvalidArgumentError(
400
- 'The provided option "fields" should be a non-empty String or an Array of non-empty String, but %v given.',
401
- field
402
- );
403
- let colName = this._getColName(modelName, field);
404
- acc[colName] = 1;
405
- return acc;
406
- }, {});
407
- }
408
386
  /**
409
387
  * Get col name.
410
388
  *
411
389
  * @param {string} modelName
412
390
  * @param {string} propName
413
- * @return {string}
391
+ * @returns {string}
414
392
  * @private
415
393
  */
416
394
  _getColName(modelName, propName) {
417
395
  if (!propName || typeof propName !== "string")
418
396
  throw new import_js_repository9.InvalidArgumentError(
419
- "A property name must be a non-empty String, but %v given.",
397
+ "Property name must be a non-empty String, but %v given.",
420
398
  propName
421
399
  );
422
400
  const utils = this.getService(import_js_repository8.ModelDefinitionUtils);
@@ -430,19 +408,78 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
430
408
  }
431
409
  return colName;
432
410
  }
411
+ /**
412
+ * Convert prop names chain to col names chain.
413
+ *
414
+ * @param {string} modelName
415
+ * @param {string} propsChain
416
+ * @returns {string}
417
+ * @private
418
+ */
419
+ _convertPropNamesChainToColNamesChain(modelName, propsChain) {
420
+ if (!modelName || typeof modelName !== "string")
421
+ throw new import_js_repository9.InvalidArgumentError(
422
+ "Model name must be a non-empty String, but %v given.",
423
+ modelName
424
+ );
425
+ if (!propsChain || typeof propsChain !== "string")
426
+ throw new import_js_repository9.InvalidArgumentError(
427
+ "Properties chain must be a non-empty String, but %v given.",
428
+ propsChain
429
+ );
430
+ propsChain = propsChain.replace(/\.{2,}/g, ".");
431
+ const propNames = propsChain.split(".");
432
+ const utils = this.getService(import_js_repository8.ModelDefinitionUtils);
433
+ let currModelName = modelName;
434
+ return propNames.map((currPropName) => {
435
+ if (!currModelName) return currPropName;
436
+ const colName = this._getColName(currModelName, currPropName);
437
+ currModelName = utils.getModelNameOfPropertyValueIfDefined(
438
+ currModelName,
439
+ currPropName
440
+ );
441
+ return colName;
442
+ }).join(".");
443
+ }
444
+ /**
445
+ * Build projection.
446
+ *
447
+ * @param {string} modelName
448
+ * @param {string|string[]} fields
449
+ * @returns {Record<string, number>|undefined}
450
+ * @private
451
+ */
452
+ _buildProjection(modelName, fields) {
453
+ if (fields == null) return;
454
+ if (Array.isArray(fields) === false) fields = [fields];
455
+ if (!fields.length) return;
456
+ if (fields.indexOf("_id") === -1) fields.push("_id");
457
+ return fields.reduce((acc, field) => {
458
+ if (!field || typeof field !== "string")
459
+ throw new import_js_repository9.InvalidArgumentError(
460
+ 'The provided option "fields" should be a non-empty String or an Array of non-empty String, but %v given.',
461
+ field
462
+ );
463
+ let colName = this._convertPropNamesChainToColNamesChain(
464
+ modelName,
465
+ field
466
+ );
467
+ acc[colName] = 1;
468
+ return acc;
469
+ }, {});
470
+ }
433
471
  /**
434
472
  * Build sort.
435
473
  *
436
474
  * @param {string} modelName
437
475
  * @param {string|string[]} clause
438
- * @return {object|undefined}
476
+ * @returns {object|undefined}
439
477
  * @private
440
478
  */
441
479
  _buildSort(modelName, clause) {
442
480
  if (clause == null) return;
443
481
  if (Array.isArray(clause) === false) clause = [clause];
444
482
  if (!clause.length) return;
445
- const utils = this.getService(import_js_repository8.ModelDefinitionUtils);
446
483
  const idPropName = this._getIdPropName(modelName);
447
484
  return clause.reduce((acc, order) => {
448
485
  if (!order || typeof order !== "string")
@@ -456,7 +493,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
456
493
  field = "_id";
457
494
  } else {
458
495
  try {
459
- field = utils.getColumnNameByPropertyName(modelName, field);
496
+ field = this._convertPropNamesChainToColNamesChain(modelName, field);
460
497
  } catch (error) {
461
498
  if (!(error instanceof import_js_repository9.InvalidArgumentError) || error.message.indexOf("does not have the property") === -1) {
462
499
  throw error;
@@ -472,7 +509,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
472
509
  *
473
510
  * @param {string} modelName
474
511
  * @param {object} clause
475
- * @return {object}
512
+ * @returns {object}
476
513
  * @private
477
514
  */
478
515
  _buildQuery(modelName, clause) {
@@ -507,7 +544,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
507
544
  if (key === idPropName) {
508
545
  key = "_id";
509
546
  } else {
510
- key = this._getColName(modelName, key);
547
+ key = this._convertPropNamesChainToColNamesChain(modelName, key);
511
548
  }
512
549
  if (typeof cond === "string") {
513
550
  query[key] = this._coerceId(cond);
@@ -665,7 +702,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
665
702
  * @param {string} modelName
666
703
  * @param {object} modelData
667
704
  * @param {object|undefined} filter
668
- * @return {Promise<object>}
705
+ * @returns {Promise<object>}
669
706
  */
670
707
  async create(modelName, modelData, filter = void 0) {
671
708
  const idPropName = this._getIdPropName(modelName);
@@ -697,7 +734,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
697
734
  * @param {string|number} id
698
735
  * @param {object} modelData
699
736
  * @param {object|undefined} filter
700
- * @return {Promise<object>}
737
+ * @returns {Promise<object>}
701
738
  */
702
739
  async replaceById(modelName, id, modelData, filter = void 0) {
703
740
  id = this._coerceId(id);
@@ -721,7 +758,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
721
758
  * @param {string} modelName
722
759
  * @param {object} modelData
723
760
  * @param {object|undefined} filter
724
- * @return {Promise<object>}
761
+ * @returns {Promise<object>}
725
762
  */
726
763
  async replaceOrCreate(modelName, modelData, filter = void 0) {
727
764
  const idPropName = this._getIdPropName(modelName);
@@ -762,7 +799,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
762
799
  * @param {string} modelName
763
800
  * @param {object} modelData
764
801
  * @param {object|undefined} where
765
- * @return {Promise<number>}
802
+ * @returns {Promise<number>}
766
803
  */
767
804
  async patch(modelName, modelData, where = void 0) {
768
805
  const idPropName = this._getIdPropName(modelName);
@@ -780,7 +817,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
780
817
  * @param {string|number} id
781
818
  * @param {object} modelData
782
819
  * @param {object|undefined} filter
783
- * @return {Promise<object>}
820
+ * @returns {Promise<object>}
784
821
  */
785
822
  async patchById(modelName, id, modelData, filter = void 0) {
786
823
  id = this._coerceId(id);
@@ -803,7 +840,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
803
840
  *
804
841
  * @param {string} modelName
805
842
  * @param {object|undefined} filter
806
- * @return {Promise<object[]>}
843
+ * @returns {Promise<object[]>}
807
844
  */
808
845
  async find(modelName, filter = void 0) {
809
846
  filter = filter || {};
@@ -823,7 +860,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
823
860
  * @param {string} modelName
824
861
  * @param {string|number} id
825
862
  * @param {object|undefined} filter
826
- * @return {Promise<object>}
863
+ * @returns {Promise<object>}
827
864
  */
828
865
  async findById(modelName, id, filter = void 0) {
829
866
  id = this._coerceId(id);
@@ -842,7 +879,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
842
879
  *
843
880
  * @param {string} modelName
844
881
  * @param {object|undefined} where
845
- * @return {Promise<number>}
882
+ * @returns {Promise<number>}
846
883
  */
847
884
  async delete(modelName, where = void 0) {
848
885
  const table = this._getCollection(modelName);
@@ -855,7 +892,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
855
892
  *
856
893
  * @param {string} modelName
857
894
  * @param {string|number} id
858
- * @return {Promise<boolean>}
895
+ * @returns {Promise<boolean>}
859
896
  */
860
897
  async deleteById(modelName, id) {
861
898
  id = this._coerceId(id);
@@ -868,7 +905,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
868
905
  *
869
906
  * @param {string} modelName
870
907
  * @param {string|number} id
871
- * @return {Promise<boolean>}
908
+ * @returns {Promise<boolean>}
872
909
  */
873
910
  async exists(modelName, id) {
874
911
  id = this._coerceId(id);
@@ -881,7 +918,7 @@ var _MongodbAdapter = class _MongodbAdapter extends import_js_repository3.Adapte
881
918
  *
882
919
  * @param {string} modelName
883
920
  * @param {object|undefined} where
884
- * @return {Promise<number>}
921
+ * @returns {Promise<number>}
885
922
  */
886
923
  async count(modelName, where = void 0) {
887
924
  const query = this._buildQuery(modelName, where);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-repository-mongodb-adapter",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "MongoDB адаптер для @e22m4u/js-repository",
5
5
  "type": "module",
6
6
  "module": "./src/index.js",
@@ -16,8 +16,8 @@
16
16
  "lint": "eslint ./src",
17
17
  "lint:fix": "eslint ./src --fix",
18
18
  "format": "prettier --write \"./src/**/*.js\"",
19
- "test": "npm run lint && c8 --reporter=text-summary mocha",
20
- "test:coverage": "npm run lint && c8 --reporter=text mocha",
19
+ "test": "npm run lint && c8 --reporter=text-summary mocha --bail",
20
+ "test:coverage": "npm run lint && c8 --reporter=text mocha --bail",
21
21
  "build:cjs": "rimraf ./dist/cjs && node --no-warnings=ExperimentalWarning build-cjs.js",
22
22
  "prepare": "husky"
23
23
  },
@@ -42,7 +42,7 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@e22m4u/js-format": "0.1.x",
45
- "@e22m4u/js-repository": "0.2.x",
45
+ "@e22m4u/js-repository": "~0.2.4",
46
46
  "@e22m4u/js-service": "0.2.x"
47
47
  },
48
48
  "devDependencies": {
@@ -129,6 +129,7 @@ export class MongodbAdapter extends Adapter {
129
129
  * Get id prop name.
130
130
  *
131
131
  * @param modelName
132
+ * @private
132
133
  */
133
134
  _getIdPropName(modelName) {
134
135
  return this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
@@ -140,6 +141,7 @@ export class MongodbAdapter extends Adapter {
140
141
  * Get id col name.
141
142
  *
142
143
  * @param modelName
144
+ * @private
143
145
  */
144
146
  _getIdColName(modelName) {
145
147
  return this.getService(ModelDefinitionUtils).getPrimaryKeyAsColumnName(
@@ -151,7 +153,7 @@ export class MongodbAdapter extends Adapter {
151
153
  * Coerce id.
152
154
  *
153
155
  * @param value
154
- * @return {ObjectId|*}
156
+ * @returns {ObjectId|*}
155
157
  * @private
156
158
  */
157
159
  _coerceId(value) {
@@ -179,7 +181,7 @@ export class MongodbAdapter extends Adapter {
179
181
  *
180
182
  * @param {string} modelName
181
183
  * @param {object} modelData
182
- * @return {object}
184
+ * @returns {object}
183
185
  * @private
184
186
  */
185
187
  _toDatabase(modelName, modelData) {
@@ -213,7 +215,7 @@ export class MongodbAdapter extends Adapter {
213
215
  *
214
216
  * @param {string} modelName
215
217
  * @param {object} tableData
216
- * @return {object}
218
+ * @returns {object}
217
219
  * @private
218
220
  */
219
221
  _fromDatabase(modelName, tableData) {
@@ -246,7 +248,7 @@ export class MongodbAdapter extends Adapter {
246
248
  * Get collection.
247
249
  *
248
250
  * @param {string} modelName
249
- * @return {*}
251
+ * @returns {*}
250
252
  * @private
251
253
  */
252
254
  _getCollection(modelName) {
@@ -263,7 +265,7 @@ export class MongodbAdapter extends Adapter {
263
265
  * Get id type.
264
266
  *
265
267
  * @param modelName
266
- * @return {string|*}
268
+ * @returns {string|*}
267
269
  * @private
268
270
  */
269
271
  _getIdType(modelName) {
@@ -272,44 +274,18 @@ export class MongodbAdapter extends Adapter {
272
274
  return utils.getDataTypeByPropertyName(modelName, pkPropName);
273
275
  }
274
276
 
275
- /**
276
- * Build projection.
277
- *
278
- * @param {string} modelName
279
- * @param {string|string[]} fields
280
- * @return {Record<string, number>|undefined}
281
- * @private
282
- */
283
- _buildProjection(modelName, fields) {
284
- if (fields == null) return;
285
- if (Array.isArray(fields) === false) fields = [fields];
286
- if (!fields.length) return;
287
- if (fields.indexOf('_id') === -1) fields.push('_id');
288
- return fields.reduce((acc, field) => {
289
- if (!field || typeof field !== 'string')
290
- throw new InvalidArgumentError(
291
- 'The provided option "fields" should be a non-empty String ' +
292
- 'or an Array of non-empty String, but %v given.',
293
- field,
294
- );
295
- let colName = this._getColName(modelName, field);
296
- acc[colName] = 1;
297
- return acc;
298
- }, {});
299
- }
300
-
301
277
  /**
302
278
  * Get col name.
303
279
  *
304
280
  * @param {string} modelName
305
281
  * @param {string} propName
306
- * @return {string}
282
+ * @returns {string}
307
283
  * @private
308
284
  */
309
285
  _getColName(modelName, propName) {
310
286
  if (!propName || typeof propName !== 'string')
311
287
  throw new InvalidArgumentError(
312
- 'A property name must be a non-empty String, but %v given.',
288
+ 'Property name must be a non-empty String, but %v given.',
313
289
  propName,
314
290
  );
315
291
  const utils = this.getService(ModelDefinitionUtils);
@@ -327,19 +303,88 @@ export class MongodbAdapter extends Adapter {
327
303
  return colName;
328
304
  }
329
305
 
306
+ /**
307
+ * Convert prop names chain to col names chain.
308
+ *
309
+ * @param {string} modelName
310
+ * @param {string} propsChain
311
+ * @returns {string}
312
+ * @private
313
+ */
314
+ _convertPropNamesChainToColNamesChain(modelName, propsChain) {
315
+ if (!modelName || typeof modelName !== 'string')
316
+ throw new InvalidArgumentError(
317
+ 'Model name must be a non-empty String, but %v given.',
318
+ modelName,
319
+ );
320
+ if (!propsChain || typeof propsChain !== 'string')
321
+ throw new InvalidArgumentError(
322
+ 'Properties chain must be a non-empty String, but %v given.',
323
+ propsChain,
324
+ );
325
+ // удаление повторяющихся точек,
326
+ // где строка "foo..bar.baz...qux"
327
+ // будет преобразована к "foo.bar.baz.qux"
328
+ propsChain = propsChain.replace(/\.{2,}/g, '.');
329
+ // разделение цепочки на массив свойств,
330
+ // и формирование цепочки имен колонок
331
+ const propNames = propsChain.split('.');
332
+ const utils = this.getService(ModelDefinitionUtils);
333
+ let currModelName = modelName;
334
+ return propNames
335
+ .map(currPropName => {
336
+ if (!currModelName) return currPropName;
337
+ const colName = this._getColName(currModelName, currPropName);
338
+ currModelName = utils.getModelNameOfPropertyValueIfDefined(
339
+ currModelName,
340
+ currPropName,
341
+ );
342
+ return colName;
343
+ })
344
+ .join('.');
345
+ }
346
+
347
+ /**
348
+ * Build projection.
349
+ *
350
+ * @param {string} modelName
351
+ * @param {string|string[]} fields
352
+ * @returns {Record<string, number>|undefined}
353
+ * @private
354
+ */
355
+ _buildProjection(modelName, fields) {
356
+ if (fields == null) return;
357
+ if (Array.isArray(fields) === false) fields = [fields];
358
+ if (!fields.length) return;
359
+ if (fields.indexOf('_id') === -1) fields.push('_id');
360
+ return fields.reduce((acc, field) => {
361
+ if (!field || typeof field !== 'string')
362
+ throw new InvalidArgumentError(
363
+ 'The provided option "fields" should be a non-empty String ' +
364
+ 'or an Array of non-empty String, but %v given.',
365
+ field,
366
+ );
367
+ let colName = this._convertPropNamesChainToColNamesChain(
368
+ modelName,
369
+ field,
370
+ );
371
+ acc[colName] = 1;
372
+ return acc;
373
+ }, {});
374
+ }
375
+
330
376
  /**
331
377
  * Build sort.
332
378
  *
333
379
  * @param {string} modelName
334
380
  * @param {string|string[]} clause
335
- * @return {object|undefined}
381
+ * @returns {object|undefined}
336
382
  * @private
337
383
  */
338
384
  _buildSort(modelName, clause) {
339
385
  if (clause == null) return;
340
386
  if (Array.isArray(clause) === false) clause = [clause];
341
387
  if (!clause.length) return;
342
- const utils = this.getService(ModelDefinitionUtils);
343
388
  const idPropName = this._getIdPropName(modelName);
344
389
  return clause.reduce((acc, order) => {
345
390
  if (!order || typeof order !== 'string')
@@ -354,7 +399,7 @@ export class MongodbAdapter extends Adapter {
354
399
  field = '_id';
355
400
  } else {
356
401
  try {
357
- field = utils.getColumnNameByPropertyName(modelName, field);
402
+ field = this._convertPropNamesChainToColNamesChain(modelName, field);
358
403
  } catch (error) {
359
404
  if (
360
405
  !(error instanceof InvalidArgumentError) ||
@@ -374,7 +419,7 @@ export class MongodbAdapter extends Adapter {
374
419
  *
375
420
  * @param {string} modelName
376
421
  * @param {object} clause
377
- * @return {object}
422
+ * @returns {object}
378
423
  * @private
379
424
  */
380
425
  _buildQuery(modelName, clause) {
@@ -410,7 +455,7 @@ export class MongodbAdapter extends Adapter {
410
455
  if (key === idPropName) {
411
456
  key = '_id';
412
457
  } else {
413
- key = this._getColName(modelName, key);
458
+ key = this._convertPropNamesChainToColNamesChain(modelName, key);
414
459
  }
415
460
  // string
416
461
  if (typeof cond === 'string') {
@@ -596,7 +641,7 @@ export class MongodbAdapter extends Adapter {
596
641
  * @param {string} modelName
597
642
  * @param {object} modelData
598
643
  * @param {object|undefined} filter
599
- * @return {Promise<object>}
644
+ * @returns {Promise<object>}
600
645
  */
601
646
  async create(modelName, modelData, filter = undefined) {
602
647
  const idPropName = this._getIdPropName(modelName);
@@ -631,7 +676,7 @@ export class MongodbAdapter extends Adapter {
631
676
  * @param {string|number} id
632
677
  * @param {object} modelData
633
678
  * @param {object|undefined} filter
634
- * @return {Promise<object>}
679
+ * @returns {Promise<object>}
635
680
  */
636
681
  async replaceById(modelName, id, modelData, filter = undefined) {
637
682
  id = this._coerceId(id);
@@ -656,7 +701,7 @@ export class MongodbAdapter extends Adapter {
656
701
  * @param {string} modelName
657
702
  * @param {object} modelData
658
703
  * @param {object|undefined} filter
659
- * @return {Promise<object>}
704
+ * @returns {Promise<object>}
660
705
  */
661
706
  async replaceOrCreate(modelName, modelData, filter = undefined) {
662
707
  const idPropName = this._getIdPropName(modelName);
@@ -700,7 +745,7 @@ export class MongodbAdapter extends Adapter {
700
745
  * @param {string} modelName
701
746
  * @param {object} modelData
702
747
  * @param {object|undefined} where
703
- * @return {Promise<number>}
748
+ * @returns {Promise<number>}
704
749
  */
705
750
  async patch(modelName, modelData, where = undefined) {
706
751
  const idPropName = this._getIdPropName(modelName);
@@ -719,7 +764,7 @@ export class MongodbAdapter extends Adapter {
719
764
  * @param {string|number} id
720
765
  * @param {object} modelData
721
766
  * @param {object|undefined} filter
722
- * @return {Promise<object>}
767
+ * @returns {Promise<object>}
723
768
  */
724
769
  async patchById(modelName, id, modelData, filter = undefined) {
725
770
  id = this._coerceId(id);
@@ -743,7 +788,7 @@ export class MongodbAdapter extends Adapter {
743
788
  *
744
789
  * @param {string} modelName
745
790
  * @param {object|undefined} filter
746
- * @return {Promise<object[]>}
791
+ * @returns {Promise<object[]>}
747
792
  */
748
793
  async find(modelName, filter = undefined) {
749
794
  filter = filter || {};
@@ -764,7 +809,7 @@ export class MongodbAdapter extends Adapter {
764
809
  * @param {string} modelName
765
810
  * @param {string|number} id
766
811
  * @param {object|undefined} filter
767
- * @return {Promise<object>}
812
+ * @returns {Promise<object>}
768
813
  */
769
814
  async findById(modelName, id, filter = undefined) {
770
815
  id = this._coerceId(id);
@@ -784,7 +829,7 @@ export class MongodbAdapter extends Adapter {
784
829
  *
785
830
  * @param {string} modelName
786
831
  * @param {object|undefined} where
787
- * @return {Promise<number>}
832
+ * @returns {Promise<number>}
788
833
  */
789
834
  async delete(modelName, where = undefined) {
790
835
  const table = this._getCollection(modelName);
@@ -798,7 +843,7 @@ export class MongodbAdapter extends Adapter {
798
843
  *
799
844
  * @param {string} modelName
800
845
  * @param {string|number} id
801
- * @return {Promise<boolean>}
846
+ * @returns {Promise<boolean>}
802
847
  */
803
848
  async deleteById(modelName, id) {
804
849
  id = this._coerceId(id);
@@ -812,7 +857,7 @@ export class MongodbAdapter extends Adapter {
812
857
  *
813
858
  * @param {string} modelName
814
859
  * @param {string|number} id
815
- * @return {Promise<boolean>}
860
+ * @returns {Promise<boolean>}
816
861
  */
817
862
  async exists(modelName, id) {
818
863
  id = this._coerceId(id);
@@ -826,7 +871,7 @@ export class MongodbAdapter extends Adapter {
826
871
  *
827
872
  * @param {string} modelName
828
873
  * @param {object|undefined} where
829
- * @return {Promise<number>}
874
+ * @returns {Promise<number>}
830
875
  */
831
876
  async count(modelName, where = undefined) {
832
877
  const query = this._buildQuery(modelName, where);
@@ -107,6 +107,44 @@ describe('MongodbAdapter', function () {
107
107
  expect(res).to.be.eql({_id: 1, bar: 1});
108
108
  });
109
109
 
110
+ it('converts property names chain to column names chain', async function () {
111
+ const schema = createSchema();
112
+ schema.defineModel({
113
+ name: 'modelA',
114
+ datasource: 'mongodb',
115
+ properties: {
116
+ foo: {
117
+ type: DataType.OBJECT,
118
+ columnName: 'fooCol',
119
+ model: 'modelB',
120
+ },
121
+ },
122
+ });
123
+ schema.defineModel({
124
+ name: 'modelB',
125
+ properties: {
126
+ bar: {
127
+ type: DataType.OBJECT,
128
+ model: 'modelC',
129
+ },
130
+ },
131
+ });
132
+ schema.defineModel({
133
+ name: 'modelC',
134
+ properties: {
135
+ baz: {
136
+ type: DataType.OBJECT,
137
+ columnName: 'bazCol',
138
+ },
139
+ },
140
+ });
141
+ const A = await schema
142
+ .getService(AdapterRegistry)
143
+ .getAdapter('mongodb');
144
+ const res = A._buildProjection('modelA', 'foo.bar.baz.qux');
145
+ expect(res).to.be.eql({_id: 1, 'fooCol.bar.bazCol.qux': 1});
146
+ });
147
+
110
148
  it('includes "_id" field to the projection', async function () {
111
149
  const schema = createSchema();
112
150
  schema.defineModel({name: 'model', datasource: 'mongodb'});
@@ -197,6 +235,64 @@ describe('MongodbAdapter', function () {
197
235
  expect(res).to.be.eql({_id: 1, bar: 1, qux: 1});
198
236
  });
199
237
 
238
+ it('converts property names chain to column names chain', async function () {
239
+ const schema = createSchema();
240
+ schema.defineModel({
241
+ name: 'modelA',
242
+ datasource: 'mongodb',
243
+ properties: {
244
+ foo1: {
245
+ type: DataType.OBJECT,
246
+ columnName: 'foo1Col',
247
+ model: 'modelB',
248
+ },
249
+ foo2: {
250
+ type: DataType.OBJECT,
251
+ columnName: 'foo2Col',
252
+ model: 'modelB',
253
+ },
254
+ },
255
+ });
256
+ schema.defineModel({
257
+ name: 'modelB',
258
+ properties: {
259
+ bar1: {
260
+ type: DataType.OBJECT,
261
+ model: 'modelC',
262
+ },
263
+ bar2: {
264
+ type: DataType.OBJECT,
265
+ model: 'modelC',
266
+ },
267
+ },
268
+ });
269
+ schema.defineModel({
270
+ name: 'modelC',
271
+ properties: {
272
+ baz1: {
273
+ type: DataType.OBJECT,
274
+ columnName: 'baz1Col',
275
+ },
276
+ baz2: {
277
+ type: DataType.OBJECT,
278
+ columnName: 'baz2Col',
279
+ },
280
+ },
281
+ });
282
+ const A = await schema
283
+ .getService(AdapterRegistry)
284
+ .getAdapter('mongodb');
285
+ const res = A._buildProjection('modelA', [
286
+ 'foo1.bar1.baz1.qux1',
287
+ 'foo2.bar2.baz2.qux2',
288
+ ]);
289
+ expect(res).to.be.eql({
290
+ _id: 1,
291
+ 'foo1Col.bar1.baz1Col.qux1': 1,
292
+ 'foo2Col.bar2.baz2Col.qux2': 1,
293
+ });
294
+ });
295
+
200
296
  it('includes "_id" field to the projection', async function () {
201
297
  const schema = createSchema();
202
298
  schema.defineModel({name: 'model', datasource: 'mongodb'});
@@ -327,6 +423,48 @@ describe('MongodbAdapter', function () {
327
423
  expect(res2).to.be.eql({bar: -1});
328
424
  expect(res3).to.be.eql({bar: 1});
329
425
  });
426
+
427
+ it('converts property names chain to column names chain', async function () {
428
+ const schema = createSchema();
429
+ schema.defineModel({
430
+ name: 'modelA',
431
+ datasource: 'mongodb',
432
+ properties: {
433
+ foo: {
434
+ type: DataType.OBJECT,
435
+ columnName: 'fooCol',
436
+ model: 'modelB',
437
+ },
438
+ },
439
+ });
440
+ schema.defineModel({
441
+ name: 'modelB',
442
+ properties: {
443
+ bar: {
444
+ type: DataType.OBJECT,
445
+ model: 'modelC',
446
+ },
447
+ },
448
+ });
449
+ schema.defineModel({
450
+ name: 'modelC',
451
+ properties: {
452
+ baz: {
453
+ type: DataType.OBJECT,
454
+ columnName: 'bazCol',
455
+ },
456
+ },
457
+ });
458
+ const A = await schema
459
+ .getService(AdapterRegistry)
460
+ .getAdapter('mongodb');
461
+ const res1 = A._buildSort('modelA', 'foo.bar.baz.qux');
462
+ const res2 = A._buildSort('modelA', 'foo.bar.baz.qux DESC');
463
+ const res3 = A._buildSort('modelA', 'foo.bar.baz.qux ASC');
464
+ expect(res1).to.be.eql({'fooCol.bar.bazCol.qux': 1});
465
+ expect(res2).to.be.eql({'fooCol.bar.bazCol.qux': -1});
466
+ expect(res3).to.be.eql({'fooCol.bar.bazCol.qux': 1});
467
+ });
330
468
  });
331
469
 
332
470
  describe('multiple fields', function () {
@@ -431,6 +569,79 @@ describe('MongodbAdapter', function () {
431
569
  expect(res2).to.be.eql({bar: -1, qux: 1});
432
570
  expect(res3).to.be.eql({bar: 1, qux: -1});
433
571
  });
572
+
573
+ it('converts property names chain to column names chain', async function () {
574
+ const schema = createSchema();
575
+ schema.defineModel({
576
+ name: 'modelA',
577
+ datasource: 'mongodb',
578
+ properties: {
579
+ foo1: {
580
+ type: DataType.OBJECT,
581
+ columnName: 'foo1Col',
582
+ model: 'modelB',
583
+ },
584
+ foo2: {
585
+ type: DataType.OBJECT,
586
+ columnName: 'foo2Col',
587
+ model: 'modelB',
588
+ },
589
+ },
590
+ });
591
+ schema.defineModel({
592
+ name: 'modelB',
593
+ properties: {
594
+ bar1: {
595
+ type: DataType.OBJECT,
596
+ model: 'modelC',
597
+ },
598
+ bar2: {
599
+ type: DataType.OBJECT,
600
+ model: 'modelC',
601
+ },
602
+ },
603
+ });
604
+ schema.defineModel({
605
+ name: 'modelC',
606
+ properties: {
607
+ baz1: {
608
+ type: DataType.OBJECT,
609
+ columnName: 'baz1Col',
610
+ },
611
+ baz2: {
612
+ type: DataType.OBJECT,
613
+ columnName: 'baz2Col',
614
+ },
615
+ },
616
+ });
617
+ const A = await schema
618
+ .getService(AdapterRegistry)
619
+ .getAdapter('mongodb');
620
+ const res1 = A._buildSort('modelA', [
621
+ 'foo1.bar1.baz1.qux1',
622
+ 'foo2.bar2.baz2.qux2',
623
+ ]);
624
+ const res2 = A._buildSort('modelA', [
625
+ 'foo1.bar1.baz1.qux1 DESC',
626
+ 'foo2.bar2.baz2.qux2 DESC',
627
+ ]);
628
+ const res3 = A._buildSort('modelA', [
629
+ 'foo1.bar1.baz1.qux1 ASC',
630
+ 'foo2.bar2.baz2.qux2 ASC',
631
+ ]);
632
+ expect(res1).to.be.eql({
633
+ 'foo1Col.bar1.baz1Col.qux1': 1,
634
+ 'foo2Col.bar2.baz2Col.qux2': 1,
635
+ });
636
+ expect(res2).to.be.eql({
637
+ 'foo1Col.bar1.baz1Col.qux1': -1,
638
+ 'foo2Col.bar2.baz2Col.qux2': -1,
639
+ });
640
+ expect(res3).to.be.eql({
641
+ 'foo1Col.bar1.baz1Col.qux1': 1,
642
+ 'foo2Col.bar2.baz2Col.qux2': 1,
643
+ });
644
+ });
434
645
  });
435
646
  });
436
647
 
@@ -478,6 +689,42 @@ describe('MongodbAdapter', function () {
478
689
  expect(res).to.be.eql({bar: 'a1', qux: null});
479
690
  });
480
691
 
692
+ it('converts property names chain to column names chain', async function () {
693
+ const schema = createSchema();
694
+ schema.defineModel({
695
+ name: 'modelA',
696
+ datasource: 'mongodb',
697
+ properties: {
698
+ foo: {
699
+ type: DataType.OBJECT,
700
+ columnName: 'fooCol',
701
+ model: 'modelB',
702
+ },
703
+ },
704
+ });
705
+ schema.defineModel({
706
+ name: 'modelB',
707
+ properties: {
708
+ bar: {
709
+ type: DataType.OBJECT,
710
+ model: 'modelC',
711
+ },
712
+ },
713
+ });
714
+ schema.defineModel({
715
+ name: 'modelC',
716
+ properties: {
717
+ baz: {
718
+ type: DataType.OBJECT,
719
+ columnName: 'bazCol',
720
+ },
721
+ },
722
+ });
723
+ const A = await schema.getService(AdapterRegistry).getAdapter('mongodb');
724
+ const res = A._buildQuery('modelA', {'foo.bar.baz.qux': 10});
725
+ expect(res).to.be.eql({'fooCol.bar.bazCol.qux': 10});
726
+ });
727
+
481
728
  it('throws an error when using "$" character', async function () {
482
729
  const schema = createSchema();
483
730
  schema.defineModel({name: 'model', datasource: 'mongodb'});