sequelize-mock-v5 1.2.3 → 1.3.4

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/README.md CHANGED
@@ -6,7 +6,7 @@ A mocking interface designed for testing code that uses [Sequelize](http://seque
6
6
  ## Install
7
7
 
8
8
  ```
9
- npm i sequelize-mock --save-dev
9
+ npm i sequelize-mock-v5 --save-dev
10
10
  ```
11
11
 
12
12
  ## Getting Started
package/package.json CHANGED
@@ -1,54 +1,54 @@
1
1
  {
2
- "name": "sequelize-mock-v5",
3
- "version": "1.2.3",
4
- "description": "A simple mock interface specifically for testing code relying on Sequelize models",
5
- "main": "src/index.js",
6
- "scripts": {
7
- "doc-gen": "node scripts/doc-gen.js",
8
- "test": "nyc --reporter=text --reporter=html mocha",
9
- "test-report": "nyc report --reporter=html",
10
- "coverage": "nyc report --reporter=text-lcov | coveralls",
11
- "preversion": "npm test",
12
- "version": "node scripts/version.js && git add changelog.md"
13
- },
14
- "repository": {
15
- "type": "git",
16
- "url": "git+https://github.com/foyer-inc/sequelize-mock.git"
17
- },
18
- "keywords": [
19
- "sequelize",
20
- "mocking",
21
- "test",
22
- "testing"
2
+ "name": "sequelize-mock-v5",
3
+ "version": "1.3.4",
4
+ "description": "A simple mock interface specifically for testing code relying on Sequelize models",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "doc-gen": "node scripts/doc-gen.js",
8
+ "test": "nyc --reporter=text --reporter=html mocha",
9
+ "test-report": "nyc report --reporter=html",
10
+ "coverage": "nyc report --reporter=text-lcov | coveralls",
11
+ "preversion": "npm test",
12
+ "version": "node scripts/version.js && git add changelog.md"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/KozyOps/sequelize-mock.git"
17
+ },
18
+ "keywords": [
19
+ "sequelize",
20
+ "mocking",
21
+ "test",
22
+ "testing"
23
+ ],
24
+ "author": "Kozy Operations",
25
+ "license": "MIT",
26
+ "bugs": {
27
+ "url": "https://github.com/KozyOps/sequelize-mock/issues"
28
+ },
29
+ "homepage": "https://github.com/KozyOps/sequelize-mock#readme",
30
+ "dependencies": {
31
+ "inflection": "^1.10.0",
32
+ "lodash": "^4.17.20"
33
+ },
34
+ "devDependencies": {
35
+ "coveralls": "^3.1.0",
36
+ "dox": "^0.9.0",
37
+ "glob": "^7.1.1",
38
+ "istanbul": "^0.4.5",
39
+ "mocha": "^8.1.3",
40
+ "moment": "^2.17.1",
41
+ "nyc": "^15.1.0",
42
+ "proxyquire": "^1.7.10",
43
+ "should": "^11.1.1"
44
+ },
45
+ "nyc": {
46
+ "exclude": [
47
+ "src/index.js"
23
48
  ],
24
- "author": "Foyer Inc",
25
- "license": "MIT",
26
- "bugs": {
27
- "url": "https://github.com/foyer-inc/sequelize-mock/issues"
28
- },
29
- "homepage": "https://github.com/foyer-inc/sequelize-mock#readme",
30
- "dependencies": {
31
- "inflection": "^1.10.0",
32
- "lodash": "^4.17.20"
33
- },
34
- "devDependencies": {
35
- "coveralls": "^3.1.0",
36
- "dox": "^0.9.0",
37
- "glob": "^7.1.1",
38
- "istanbul": "^0.4.5",
39
- "mocha": "^8.1.3",
40
- "moment": "^2.17.1",
41
- "nyc": "^15.1.0",
42
- "proxyquire": "^1.7.10",
43
- "should": "^11.1.1"
44
- },
45
- "nyc": {
46
- "exclude": [
47
- "src/index.js"
48
- ],
49
- "include": [
50
- "src/**/*.js"
51
- ],
52
- "all": true
53
- }
49
+ "include": [
50
+ "src/**/*.js"
51
+ ],
52
+ "all": true
53
+ }
54
54
  }
Binary file
package/src/model.js CHANGED
@@ -28,8 +28,8 @@ var _ = require('lodash'),
28
28
  * @param {Object} [opts.instanceMethods] Map of function names and the functions to be run. These functions will be added to any instances of this Model type
29
29
  * @param {Object} [opts.sequelize] Sequelize instance that this is tied to
30
30
  **/
31
- function fakeModel (name, defaults, opts) {
32
- if(typeof name === 'object') {
31
+ function fakeModel(name, defaults, opts) {
32
+ if (typeof name === 'object') {
33
33
  defaults = name;
34
34
  name = '';
35
35
  }
@@ -70,6 +70,13 @@ function fakeModel (name, defaults, opts) {
70
70
  this.name = name;
71
71
  this._defaults = defaults || {};
72
72
 
73
+ /**
74
+ * Model definition containing the attributes/fields defined for this model
75
+ *
76
+ * @member {Object}
77
+ **/
78
+ this.modelDefinition = defaults || {};
79
+
73
80
  this.tableName = this.options.tableName || (this.options.freezeTableName ? name : Utils.pluralize(name));
74
81
 
75
82
  /**
@@ -77,7 +84,7 @@ function fakeModel (name, defaults, opts) {
77
84
  *
78
85
  * @member {Object}
79
86
  **/
80
- this.Instance = function() {
87
+ this.Instance = function () {
81
88
  Instance.apply(this, arguments);
82
89
  };
83
90
 
@@ -88,7 +95,7 @@ function fakeModel (name, defaults, opts) {
88
95
  }
89
96
  });
90
97
 
91
- if(this.options.instanceMethods) {
98
+ if (this.options.instanceMethods) {
92
99
  _.each(this.options.instanceMethods, function (fn, name) {
93
100
  self.Instance.prototype[name] = fn;
94
101
  });
@@ -101,7 +108,7 @@ function fakeModel (name, defaults, opts) {
101
108
  createdDefault: this.options.createdDefault,
102
109
  fallbackFn: !this.options.autoQueryFallback ? this.build.bind(this) : null,
103
110
  };
104
- if(this.options.sequelize) {
111
+ if (this.options.sequelize) {
105
112
  qiOptions.parent = this.options.sequelize.getQueryInterface();
106
113
  }
107
114
  /**
@@ -251,15 +258,15 @@ fakeModel.prototype.getTableName = function () {
251
258
  * @return {Model} Self
252
259
  **/
253
260
  fakeModel.prototype.unscoped =
254
- /**
255
- * No-op that returns the current object
256
- *
257
- * @instance
258
- * @return {Model} Self
259
- **/
260
- fakeModel.prototype.scope = function () {
261
- return this;
262
- };
261
+ /**
262
+ * No-op that returns the current object
263
+ *
264
+ * @instance
265
+ * @return {Model} Self
266
+ **/
267
+ fakeModel.prototype.scope = function () {
268
+ return this;
269
+ };
263
270
 
264
271
  /**
265
272
  * No-op that returns a void.
@@ -267,7 +274,7 @@ fakeModel.prototype.scope = function () {
267
274
  * @instance
268
275
  * @return {undefined}
269
276
  **/
270
- fakeModel.prototype.addScope = function () {};
277
+ fakeModel.prototype.addScope = function () { };
271
278
 
272
279
  /**
273
280
  * Executes a mock query to find all of the instances with any provided options. Without
@@ -295,14 +302,14 @@ fakeModel.prototype.addScope = function () {};
295
302
  * @param {Object} [options.where] Values that any automatically created Instances should have
296
303
  * @return {Promise<Instance[]>} result returned by the mock query
297
304
  **/
298
- fakeModel.prototype.findAll = async function (options) {
305
+ fakeModel.prototype.findAll = async function (options) {
299
306
  var self = this;
300
307
 
301
308
  return await this.$query({
302
309
  query: "findAll",
303
310
  queryOptions: arguments,
304
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
305
- return [ self.build(options ? options.where : {}) ];
311
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
312
+ return [self.build(options ? options.where : {})];
306
313
  },
307
314
  });
308
315
  };
@@ -338,19 +345,57 @@ fakeModel.prototype.findAll = async function (options) {
338
345
  * @return {Promise<Object>} result returned by the mock query
339
346
  **/
340
347
  fakeModel.prototype.findAndCount =
341
- fakeModel.prototype.findAndCountAll = async function (options) {
348
+ fakeModel.prototype.findAndCountAll = async function (options) {
349
+ var self = this;
350
+
351
+ return await this.$query({
352
+ query: "findAndCountAll",
353
+ queryOptions: arguments,
354
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
355
+ let result = [self.build(options ? options.where : {})]
356
+ return {
357
+ count: result.length,
358
+ rows: result
359
+ };
360
+ },
361
+ });
362
+ };
363
+
364
+ /**
365
+ * Executes a mock query to count all of the instances with any provided options. Without any other configuration, the default behavior when no queueud query result
366
+ * is present is to create an array of a single result based on the where query in the options and
367
+ * wraps it in a promise.
368
+ *
369
+ * To turn off this behavior, the `$autoQueryFallback` option on the model should be set
370
+ * to `false`.
371
+ *
372
+ * @example
373
+ * // This is an example of the default behavior with no queued results
374
+ * // If there is a queued result or failure, that will be returned instead
375
+ * User.count({
376
+ * where: {
377
+ * email: 'myEmail@example.com',
378
+ * },
379
+ * }).then(function (count) {
380
+ * // count == 1 true
381
+ * });
382
+ *
383
+ * @instance
384
+ * @method count
385
+ * @param {Object} [options] Options for the count query
386
+ * @param {Object} [options.where] Values that any automatically created Instances should have
387
+ * @return {Promise<Object>} result returned by the mock query
388
+ **/
389
+ fakeModel.prototype.count = async function (options) {
342
390
  var self = this;
343
391
 
344
392
  return await this.$query({
345
- query: "findAndCountAll",
393
+ query: "count",
346
394
  queryOptions: arguments,
347
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
348
- let result = [ self.build(options ? options.where : {}) ]
349
- return {
350
- count: result.length,
351
- rows: result
352
- };
353
- },
395
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
396
+ let result = [self.build(options ? options.where : {})]
397
+ return result.length
398
+ }
354
399
  });
355
400
  };
356
401
 
@@ -367,17 +412,17 @@ fakeModel.prototype.findAndCountAll = async function (options) {
367
412
  * @return {Promise<Instance>} Promise that resolves with an instance with the given ID
368
413
  **/
369
414
  fakeModel.prototype.findById =
370
- fakeModel.prototype.findByPk = async function (id) {
371
- var self = this;
415
+ fakeModel.prototype.findByPk = async function (id) {
416
+ var self = this;
372
417
 
373
- return await this.$query({
374
- query: "findById",
375
- queryOptions: arguments,
376
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
377
- return self.build({ id: id });
378
- },
379
- });
380
- };
418
+ return await this.$query({
419
+ query: "findById",
420
+ queryOptions: arguments,
421
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
422
+ return self.build({ id: id });
423
+ },
424
+ });
425
+ };
381
426
 
382
427
  /**
383
428
  * Executes a mock query to find an instance with the given infomation. Without any other
@@ -404,17 +449,17 @@ fakeModel.prototype.findByPk = async function (id) {
404
449
  * @return {Promise<Instance>} Promise that resolves with an instance with the given properties
405
450
  **/
406
451
  fakeModel.prototype.find =
407
- fakeModel.prototype.findOne = async function (obj) {
408
- var self = this;
452
+ fakeModel.prototype.findOne = async function (obj) {
453
+ var self = this;
409
454
 
410
- return await this.$query({
411
- query: "findOne",
412
- queryOptions: arguments,
413
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
414
- return self.build(obj ? obj.where : {});
415
- },
416
- });
417
- };
455
+ return await this.$query({
456
+ query: "findOne",
457
+ queryOptions: arguments,
458
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
459
+ return self.build(obj ? obj.where : {});
460
+ },
461
+ });
462
+ };
418
463
 
419
464
  /**
420
465
  * Executes a mock query to find the max value of a field. Without any other
@@ -427,38 +472,38 @@ fakeModel.prototype.findOne = async function (obj) {
427
472
  * @return {Any} the default value for the given field
428
473
  **/
429
474
  fakeModel.prototype.max =
430
- /**
431
- * Executes a mock query to find the min value of a field. Without any other
432
- * configuration, the default behavior when no queueud query result is present
433
- * is to return the default value for the given field
434
- *
435
- * @instance
436
- * @method
437
- * @param {String} field Name of the field to return for
438
- * @return {Any} the default value for the given field
439
- **/
440
- fakeModel.prototype.min =
441
- /**
442
- * Executes a mock query to find the sum value of a field. Without any other
443
- * configuration, the default behavior when no queueud query result is present
444
- * is to return the default value for the given field
445
- *
446
- * @instance
447
- * @method
448
- * @param {String} field Name of the field to return for
449
- * @return {Any} the default value for the given field
450
- **/
451
- fakeModel.prototype.sum = async function (field) {
452
- var self = this;
475
+ /**
476
+ * Executes a mock query to find the min value of a field. Without any other
477
+ * configuration, the default behavior when no queueud query result is present
478
+ * is to return the default value for the given field
479
+ *
480
+ * @instance
481
+ * @method
482
+ * @param {String} field Name of the field to return for
483
+ * @return {Any} the default value for the given field
484
+ **/
485
+ fakeModel.prototype.min =
486
+ /**
487
+ * Executes a mock query to find the sum value of a field. Without any other
488
+ * configuration, the default behavior when no queueud query result is present
489
+ * is to return the default value for the given field
490
+ *
491
+ * @instance
492
+ * @method
493
+ * @param {String} field Name of the field to return for
494
+ * @return {Any} the default value for the given field
495
+ **/
496
+ fakeModel.prototype.sum = async function (field) {
497
+ var self = this;
453
498
 
454
- return await this.$query({
455
- query: "sum",
456
- queryOptions: arguments,
457
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
458
- return self._defaults[field];
459
- },
460
- });
461
- };
499
+ return await this.$query({
500
+ query: "sum",
501
+ queryOptions: arguments,
502
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
503
+ return self._defaults[field];
504
+ },
505
+ });
506
+ };
462
507
 
463
508
  /**
464
509
  * Builds a new Instance with the given properties
@@ -479,7 +524,7 @@ fakeModel.prototype.build = function (values, options) {
479
524
  deletedAt: this.options.deletedAt,
480
525
  });
481
526
 
482
- if(typeof options.isNewRecord != 'boolean') {
527
+ if (typeof options.isNewRecord != 'boolean') {
483
528
  options.isNewRecord = true;
484
529
  }
485
530
 
@@ -545,22 +590,22 @@ fakeModel.prototype.findOrCreate = async function (obj) {
545
590
  * @return {Promise<Boolean>} Promise that resolves with a boolean meant to indicate if something was inserted
546
591
  **/
547
592
  fakeModel.prototype.insertOrUpdate =
548
- fakeModel.prototype.upsert = async function (values) {
549
- var self = this;
593
+ fakeModel.prototype.upsert = async function (values) {
594
+ var self = this;
550
595
 
551
- return await this.$query({
552
- query: "upsert",
553
- queryOptions: arguments,
554
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
555
- if (Object.keys().length === 0) {
556
- return self.options.createdDefault;
557
- }
558
- else {
559
- return await self.build(values).save();
560
- }
561
- },
562
- });
563
- }
596
+ return await this.$query({
597
+ query: "upsert",
598
+ queryOptions: arguments,
599
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
600
+ if (Object.keys().length === 0) {
601
+ return self.options.createdDefault;
602
+ }
603
+ else {
604
+ return await self.build(values).save();
605
+ }
606
+ },
607
+ });
608
+ }
564
609
 
565
610
  /**
566
611
  * @instance
@@ -577,7 +622,7 @@ fakeModel.prototype.upsert = async function (values, returning) {
577
622
  query: "upsert",
578
623
  queryOptions: arguments,
579
624
  //if there is nothing queued, return the input object with a created value equal to the createdDefault
580
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function (values) {
625
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function (values) {
581
626
  if (typeof values === 'undefined') {
582
627
  return self.options.createdDefault;
583
628
  }
@@ -604,9 +649,10 @@ fakeModel.prototype.bulkCreate = async function (set, options) {
604
649
  return await this.$query({
605
650
  query: "bulkCreate",
606
651
  queryOptions: arguments,
607
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
608
- return await Promise.all(set.map(async function(val) {
609
- return await self.build(val).save();
652
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
653
+ return await Promise.all(set.map(async function (val) {
654
+ let res = await self.create(val);
655
+ return await res.fallbackFn();
610
656
  }));
611
657
  },
612
658
  });
@@ -628,14 +674,19 @@ fakeModel.prototype.destroy = async function (options) {
628
674
  return await this.$query({
629
675
  query: "destroy",
630
676
  queryOptions: arguments,
631
- fallbackFn: !this.options.autoQueryFallback ? async function() { return } : async function () {
677
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
632
678
  return Promise.resolve(options && typeof options.limit == 'number' ? options.limit : 1);
633
679
  },
634
680
  });
635
681
  }
636
682
  else {
637
- const instanceLevelDestroy = this.__proto__.__proto__.destroy.bind(this);
638
- return await instanceLevelDestroy()
683
+ return await this.__proto__.Model.$query({
684
+ query: "destroy",
685
+ queryOptions: arguments,
686
+ fallbackFn: !this.options.autoQueryFallback ? async function () { return } : async function () {
687
+ return Promise.resolve(options && typeof options.limit == 'number' ? options.limit : 1);
688
+ },
689
+ });
639
690
  }
640
691
 
641
692
  };
@@ -656,41 +707,36 @@ fakeModel.prototype.destroy = async function (options) {
656
707
  fakeModel.prototype.update = async function (values, options) {
657
708
  var self = this;
658
709
  options = options || {};
659
- if (this.$query) {
660
- return await this.$query({
661
- query: "update",
662
- queryOptions: arguments,
663
- options: options,
664
- //if options.returning are empty or false, we are doing the default (returning both)
665
- includeAffectedRows: !!!options.returning,
666
- fallbackFn: !this.options.autoQueryFallback ? null : async function() {
667
- if(!options.returning) {
668
- return [1];
669
- }
670
- return [ 1, [self.build(values)] ];
671
- }
672
- });
673
- }
674
- else {
675
- const instanceLevelUpdate = this.__proto__.__proto__.update.bind(this, values);
676
- return await instanceLevelUpdate()
677
- }
678
710
 
711
+
712
+ return await this.$query({
713
+ query: "update",
714
+ queryOptions: arguments,
715
+ options: options,
716
+ //if options.returning are empty or false, we are doing the default (returning both)
717
+ includeAffectedRows: !!!options.returning,
718
+ fallbackFn: !this.options.autoQueryFallback ? null : async function () {
719
+ if (!options.returning) {
720
+ return [1];
721
+ }
722
+ return [1, [self.build(values)]];
723
+ }
724
+ });
679
725
  };
680
726
 
681
727
  // Noops
682
728
  fakeModel.prototype.addHook =
683
- fakeModel.prototype.removeHook = function () {};
729
+ fakeModel.prototype.removeHook = function () { };
684
730
 
685
731
  // Associations
686
732
  fakeModel.prototype.belongsTo = fakeModel.prototype.hasOne = function (item, options) {
687
- if(!(item instanceof fakeModel)) {
733
+ if (!(item instanceof fakeModel)) {
688
734
  return;
689
735
  }
690
736
 
691
737
  var isString = typeof item === 'string',
692
738
  name;
693
- if(options && options.as) {
739
+ if (options && options.as) {
694
740
  name = options.as;
695
741
  } else if (isString) {
696
742
  name = item;
@@ -698,12 +744,12 @@ fakeModel.prototype.belongsTo = fakeModel.prototype.hasOne = function (item, opt
698
744
  name = item.getTableName();
699
745
  }
700
746
 
701
- var singular = Utils.uppercaseFirst( Utils.singularize(name) ),
702
- plural = Utils.uppercaseFirst( Utils.pluralize(name) ),
747
+ var singular = Utils.uppercaseFirst(Utils.singularize(name)),
748
+ plural = Utils.uppercaseFirst(Utils.pluralize(name)),
703
749
  self = this,
704
750
  noop = function () { return Promise.resolve(self); };
705
751
 
706
- if(isString) {
752
+ if (isString) {
707
753
  this.Instance.prototype['get' + singular] = function (opts) { return Promise.resolve(new self.Instance(opts && opts.where ? opts.where : opts)); };
708
754
  } else {
709
755
  this.Instance.prototype['get' + singular] = item.findOne.bind(item);
@@ -713,7 +759,7 @@ fakeModel.prototype.belongsTo = fakeModel.prototype.hasOne = function (item, opt
713
759
  };
714
760
 
715
761
  fakeModel.prototype.belongsToMany = fakeModel.prototype.hasMany = function (item, options) {
716
- if(!(item instanceof fakeModel)) {
762
+ if (!(item instanceof fakeModel)) {
717
763
  return {
718
764
  through: {
719
765
  model: new fakeModel(this.getTableName() + (item && item.name ? item.name : 'Association'), {}, { hasPrimaryKeys: false })
@@ -723,10 +769,10 @@ fakeModel.prototype.belongsToMany = fakeModel.prototype.hasMany = function (item
723
769
 
724
770
  var isString = typeof item === 'string',
725
771
  name, singular, plural;
726
- if(options && options.as) {
772
+ if (options && options.as) {
727
773
  name = options.as;
728
- singular = Utils.uppercaseFirst( Utils.singularize(name) );
729
- plural = Utils.uppercaseFirst( name );
774
+ singular = Utils.uppercaseFirst(Utils.singularize(name));
775
+ plural = Utils.uppercaseFirst(name);
730
776
 
731
777
  } else {
732
778
  if (isString) {
@@ -734,14 +780,14 @@ fakeModel.prototype.belongsToMany = fakeModel.prototype.hasMany = function (item
734
780
  } else {
735
781
  name = item.getTableName();
736
782
  }
737
- singular = Utils.uppercaseFirst( Utils.singularize(name) );
738
- plural = Utils.uppercaseFirst( Utils.pluralize(name) );
783
+ singular = Utils.uppercaseFirst(Utils.singularize(name));
784
+ plural = Utils.uppercaseFirst(Utils.pluralize(name));
739
785
  }
740
786
 
741
787
  var self = this,
742
788
  noop = function () { return Promise.resolve(self); };
743
789
 
744
- if(isString) {
790
+ if (isString) {
745
791
  this.Instance.prototype['get' + plural] = function (opts) { return Promise.resolve([new self.Instance(opts && opts.where ? opts.where : opts)]); };
746
792
  } else {
747
793
  this.Instance.prototype['get' + plural] = item.findAll.bind(item);
@@ -758,7 +804,7 @@ fakeModel.prototype.belongsToMany = fakeModel.prototype.hasMany = function (item
758
804
 
759
805
  return {
760
806
  through: {
761
- model: new fakeModel( this.getTableName() + plural, {}, { hasPrimaryKeys: false } )
807
+ model: new fakeModel(this.getTableName() + plural, {}, { hasPrimaryKeys: false })
762
808
  }
763
809
  };
764
810
  };