tspace-mysql 1.4.7 → 1.4.9

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.
Files changed (39) hide show
  1. package/README.md +128 -49
  2. package/dist/lib/{tspace/Interface.d.ts → Interface.d.ts} +18 -2
  3. package/dist/lib/connection/index.d.ts +1 -1
  4. package/dist/lib/constants/index.js +3 -3
  5. package/dist/lib/tspace/{Abstract → Abstracts}/AbstractBuilder.d.ts +3 -3
  6. package/dist/lib/tspace/{Abstract → Abstracts}/AbstractBuilder.js +2 -2
  7. package/dist/lib/tspace/{Abstract → Abstracts}/AbstractDB.d.ts +8 -2
  8. package/dist/lib/tspace/{Abstract → Abstracts}/AbstractModel.d.ts +22 -2
  9. package/dist/lib/tspace/Blueprint.d.ts +19 -5
  10. package/dist/lib/tspace/Blueprint.js +41 -19
  11. package/dist/lib/tspace/Builder.d.ts +26 -11
  12. package/dist/lib/tspace/Builder.js +378 -330
  13. package/dist/lib/tspace/DB.d.ts +42 -2
  14. package/dist/lib/tspace/DB.js +61 -5
  15. package/dist/lib/tspace/Decorator.d.ts +20 -0
  16. package/dist/lib/tspace/Decorator.js +166 -0
  17. package/dist/lib/tspace/{ProxyHandler.js → Handlers/Proxy.js} +1 -1
  18. package/dist/lib/tspace/{RelationHandler.d.ts → Handlers/Relation.d.ts} +4 -4
  19. package/dist/lib/tspace/{RelationHandler.js → Handlers/Relation.js} +103 -28
  20. package/dist/lib/tspace/{StateHandler.js → Handlers/State.js} +3 -2
  21. package/dist/lib/tspace/Model.d.ts +275 -11
  22. package/dist/lib/tspace/Model.js +989 -99
  23. package/dist/lib/tspace/Schema.js +5 -8
  24. package/dist/lib/tspace/index.d.ts +4 -0
  25. package/dist/lib/tspace/index.js +20 -2
  26. package/dist/lib/utils/index.d.ts +1 -0
  27. package/dist/lib/utils/index.js +9 -0
  28. package/dist/tests/01-Pool.test.d.ts +1 -0
  29. package/dist/tests/01-Pool.test.js +45 -0
  30. package/dist/tests/02-DB.test.d.ts +1 -0
  31. package/dist/tests/02-DB.test.js +109 -0
  32. package/dist/tests/03-Model.test.d.ts +1 -0
  33. package/dist/tests/03-Model.test.js +73 -0
  34. package/package.json +14 -3
  35. /package/dist/lib/{tspace/Interface.js → Interface.js} +0 -0
  36. /package/dist/lib/tspace/{Abstract → Abstracts}/AbstractDB.js +0 -0
  37. /package/dist/lib/tspace/{Abstract → Abstracts}/AbstractModel.js +0 -0
  38. /package/dist/lib/tspace/{ProxyHandler.d.ts → Handlers/Proxy.d.ts} +0 -0
  39. /package/dist/lib/tspace/{StateHandler.d.ts → Handlers/State.d.ts} +0 -0
@@ -16,10 +16,10 @@ exports.Model = void 0;
16
16
  const pluralize_1 = __importDefault(require("pluralize"));
17
17
  const DB_1 = require("./DB");
18
18
  const Schema_1 = require("./Schema");
19
- const AbstractModel_1 = require("./Abstract/AbstractModel");
20
- const ProxyHandler_1 = require("./ProxyHandler");
21
- const StateHandler_1 = require("./StateHandler");
22
- const RelationHandler_1 = require("./RelationHandler");
19
+ const AbstractModel_1 = require("./Abstracts/AbstractModel");
20
+ const Proxy_1 = require("./Handlers/Proxy");
21
+ const State_1 = require("./Handlers/State");
22
+ const Relation_1 = require("./Handlers/Relation");
23
23
  /**
24
24
  *
25
25
  * 'Model' class is a representation of a database table
@@ -41,7 +41,7 @@ class Model extends AbstractModel_1.AbstractModel {
41
41
  */
42
42
  this.define();
43
43
  this.boot();
44
- return new Proxy(this, ProxyHandler_1.proxyHandler);
44
+ return new Proxy(this, Proxy_1.proxyHandler);
45
45
  }
46
46
  /**
47
47
  * The 'define' method is a special method that you can define within a model.
@@ -145,7 +145,6 @@ class Model extends AbstractModel_1.AbstractModel {
145
145
  * this.useRegistry()
146
146
  * }
147
147
  * }
148
-
149
148
  */
150
149
  useRegistry() {
151
150
  this._setState('REGISTRY', Object.assign(Object.assign({}, this._getState('REGISTRY')), { '$attach': this._attach, '$detach': this._detach }));
@@ -247,11 +246,31 @@ class Model extends AbstractModel_1.AbstractModel {
247
246
  this._makeTableName();
248
247
  return this;
249
248
  }
249
+ /**
250
+ * The "useCamelCase" method is used to assign pattern camelCase.
251
+ * @return {this} this
252
+ * @example
253
+ * class User extends Model {
254
+ * constructor() {
255
+ * this.useCamelCase()
256
+ * }
257
+ * }
258
+ */
250
259
  useCamelCase() {
251
260
  this._setState('PATTERN', this.$constants('PATTERN').camelCase);
252
261
  this._makeTableName();
253
262
  return this;
254
263
  }
264
+ /**
265
+ * The "SnakeCase" method is used to assign pattern snake_case.
266
+ * @return {this} this
267
+ * @example
268
+ * class User extends Model {
269
+ * constructor() {
270
+ * this.SnakeCase()
271
+ * }
272
+ * }
273
+ */
255
274
  useSnakeCase() {
256
275
  this._setState('PATTERN', this.$constants('PATTERN').snake_case);
257
276
  this._makeTableName();
@@ -350,7 +369,7 @@ class Model extends AbstractModel_1.AbstractModel {
350
369
  useTablePlural() {
351
370
  var _a;
352
371
  const table = this._classToTableName((_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name);
353
- this._setState('TABLE_NAME', `\`${pluralize_1.default.plural(table)}\``);
372
+ this._setState('TABLE_NAME', `\`${this._valuePattern(table)}\``);
354
373
  return this;
355
374
  }
356
375
  /**
@@ -447,7 +466,7 @@ class Model extends AbstractModel_1.AbstractModel {
447
466
  * @override
448
467
  * @return {promise<string>} string
449
468
  */
450
- _exceptColumns() {
469
+ exceptColumns() {
451
470
  return __awaiter(this, void 0, void 0, function* () {
452
471
  const excepts = this._getState('EXCEPTS');
453
472
  const hasDot = excepts.some((except) => /\./.test(except));
@@ -458,9 +477,14 @@ class Model extends AbstractModel_1.AbstractModel {
458
477
  }).filter((d) => d != null);
459
478
  const tableNames = names.length ? [...new Set(names)] : [this._getState('TABLE_NAME')];
460
479
  const removeExcepts = [];
480
+ const schemaColumns = this.getSchemaModel();
461
481
  for (const tableName of tableNames) {
462
- if (this._getState('SCHEMA_TABLE') && (tableName === this._getState('TABLE_NAME').replace(/`/g, ''))) {
463
- const columns = Object.keys(this._getState('SCHEMA_TABLE'));
482
+ const isHasSchema = [
483
+ schemaColumns != null,
484
+ tableName.replace(/`/g, '') === this._getState('TABLE_NAME').replace(/`/g, '')
485
+ ].every(d => d);
486
+ if (isHasSchema) {
487
+ const columns = Object.keys(schemaColumns);
464
488
  const removeExcept = columns.filter((column) => {
465
489
  return excepts.every((except) => {
466
490
  if (/\./.test(except)) {
@@ -470,7 +494,7 @@ class Model extends AbstractModel_1.AbstractModel {
470
494
  return except !== column;
471
495
  });
472
496
  });
473
- removeExcepts.push(hasDot ? removeExcept.map(r => `\`${tableName}\`.${r}`) : removeExcept);
497
+ removeExcepts.push(hasDot ? removeExcept.map(r => `${tableName}.${r}`) : removeExcept);
474
498
  continue;
475
499
  }
476
500
  const sql = [
@@ -515,6 +539,135 @@ class Model extends AbstractModel_1.AbstractModel {
515
539
  relation.query = callback(new relation.model());
516
540
  return this;
517
541
  }
542
+ /**
543
+ *
544
+ * The 'makeSelectStatement' method is used to make select statement.
545
+ * @return {Promise<string>} string
546
+ */
547
+ makeSelectStatement() {
548
+ return __awaiter(this, void 0, void 0, function* () {
549
+ const schemaModel = this.getSchemaModel();
550
+ const makeStatement = (columns) => {
551
+ return [
552
+ `${this.$constants('SELECT')}`,
553
+ `${columns.join(', ')}`,
554
+ `${this.$constants('FROM')}`,
555
+ `\`${this.getTableName()}\``,
556
+ ].join(' ');
557
+ };
558
+ if (schemaModel == null) {
559
+ const schemaTable = yield this.getSchema();
560
+ const columns = schemaTable.map(column => `\`${this.getTableName()}\`.\`${column.Field}\``);
561
+ return makeStatement(columns);
562
+ }
563
+ const columns = Object.keys(schemaModel).map((column) => `\`${this.getTableName()}\`.\`${column}\``);
564
+ return makeStatement(columns);
565
+ });
566
+ }
567
+ /**
568
+ *
569
+ * The 'makeInsertStatement' method is used to make insert table statement.
570
+ * @return {Promise<string>} string
571
+ */
572
+ makeInsertStatement() {
573
+ return __awaiter(this, void 0, void 0, function* () {
574
+ const schemaModel = this.getSchemaModel();
575
+ const makeStatement = (columns) => {
576
+ return [
577
+ `${this.$constants('INSERT')}`,
578
+ `\`${this.getTableName()}\``,
579
+ `(${columns.join(', ')})`,
580
+ `${this.$constants('VALUES')}`,
581
+ `(${Array(columns.length).fill('?').join(' , ')})`
582
+ ].join(' ');
583
+ };
584
+ if (schemaModel == null) {
585
+ const schemaTable = yield this.getSchema();
586
+ const columns = schemaTable.map(column => `\`${column.Field}\``);
587
+ return makeStatement(columns);
588
+ }
589
+ const columns = Object.keys(schemaModel).map((column) => `\`${column}\``);
590
+ return makeStatement(columns);
591
+ });
592
+ }
593
+ /**
594
+ *
595
+ * The 'makeUpdateStatement' method is used to make update table statement.
596
+ * @return {Promise<string>} string
597
+ */
598
+ makeUpdateStatement() {
599
+ return __awaiter(this, void 0, void 0, function* () {
600
+ const schemaModel = this.getSchemaModel();
601
+ const makeStatement = (columns) => {
602
+ return [
603
+ `${this.$constants('UPDATE')}`,
604
+ `\`${this.getTableName()}\``,
605
+ `${this.$constants('SET')}`,
606
+ `(${columns.join(', ')})`
607
+ ].join(' ');
608
+ };
609
+ if (schemaModel == null) {
610
+ const schemaTable = yield this.getSchema();
611
+ const columns = schemaTable.map(column => `\`${column.Field}\` = ?`);
612
+ return makeStatement(columns);
613
+ }
614
+ const columns = Object.keys(schemaModel).map((column) => `\`${column}\` = ?`);
615
+ return makeStatement(columns);
616
+ });
617
+ }
618
+ /**
619
+ *
620
+ * The 'makeDeleteStatement' method is used to make delete statement.
621
+ * @return {Promise<string>} string
622
+ */
623
+ makeDeleteStatement() {
624
+ return __awaiter(this, void 0, void 0, function* () {
625
+ const makeStatement = () => {
626
+ return [
627
+ `${this.$constants('DELETE')}`,
628
+ `${this.$constants('FROM')}`,
629
+ `\`${this.getTableName()}\``,
630
+ `${this.$constants('WHERE')}`,
631
+ `?where_expression`
632
+ ].join(' ');
633
+ };
634
+ return makeStatement();
635
+ });
636
+ }
637
+ /**
638
+ *
639
+ * The 'makeCreateStatement' method is used to make create table statement.
640
+ * @return {Promise<string>} string
641
+ */
642
+ makeCreateStatement() {
643
+ return __awaiter(this, void 0, void 0, function* () {
644
+ const schemaModel = this.getSchemaModel();
645
+ const makeStatement = (columns) => {
646
+ return [
647
+ `${this.$constants('CREATE_TABLE_NOT_EXISTS')}`,
648
+ `\`${this.getTableName()}\``,
649
+ `(`,
650
+ `\n${columns === null || columns === void 0 ? void 0 : columns.join(',\n')}`,
651
+ `\n)`,
652
+ `${this.$constants('ENGINE')}`
653
+ ].join(' ');
654
+ };
655
+ if (schemaModel == null) {
656
+ const columns = yield this.showSchema();
657
+ return makeStatement(columns);
658
+ }
659
+ let columns = [];
660
+ for (const key in schemaModel) {
661
+ const data = schemaModel[key];
662
+ const { type, attributes } = data;
663
+ columns = [
664
+ ...columns,
665
+ `${key} ${type} ${attributes === null || attributes === void 0 ? void 0 : attributes.join(' ')}`
666
+ ];
667
+ }
668
+ return makeStatement(columns);
669
+ });
670
+ }
518
671
  /**
519
672
  *
520
673
  * Clone instance of model
@@ -547,7 +700,7 @@ class Model extends AbstractModel_1.AbstractModel {
547
700
  if ((options === null || options === void 0 ? void 0 : options.delete) == null)
548
701
  newInstance.$state.set('DELETE', '');
549
702
  if ((options === null || options === void 0 ? void 0 : options.where) == null)
550
- newInstance.$state.set('WHERE', '');
703
+ newInstance.$state.set('WHERE', []);
551
704
  if ((options === null || options === void 0 ? void 0 : options.limit) == null)
552
705
  newInstance.$state.set('LIMIT', '');
553
706
  if ((options === null || options === void 0 ? void 0 : options.offset) == null)
@@ -559,7 +712,7 @@ class Model extends AbstractModel_1.AbstractModel {
559
712
  if ((options === null || options === void 0 ? void 0 : options.select) == null)
560
713
  newInstance.$state.set('SELECT', []);
561
714
  if ((options === null || options === void 0 ? void 0 : options.join) == null)
562
- newInstance.$state.set('JOIN', '');
715
+ newInstance.$state.set('JOIN', []);
563
716
  return newInstance;
564
717
  }
565
718
  /**
@@ -573,11 +726,8 @@ class Model extends AbstractModel_1.AbstractModel {
573
726
  var _a;
574
727
  return __awaiter(this, void 0, void 0, function* () {
575
728
  try {
576
- if (this._getState('DEBUG')) {
729
+ if (this._getState('DEBUG'))
577
730
  this.$utils.consoleDebug(sql);
578
- const result = yield this.$pool.query(sql);
579
- return result;
580
- }
581
731
  return yield this.$pool.query(sql);
582
732
  }
583
733
  catch (error) {
@@ -602,15 +752,8 @@ class Model extends AbstractModel_1.AbstractModel {
602
752
  var _a;
603
753
  return __awaiter(this, void 0, void 0, function* () {
604
754
  try {
605
- if (this._getState('DEBUG')) {
755
+ if (this._getState('DEBUG'))
606
756
  this.$utils.consoleDebug(sql);
607
- if (returnId) {
608
- const result = yield this.$pool.query(sql);
609
- return [result.affectedRows, result.insertId];
610
- }
611
- const { affectedRows: result } = yield this.$pool.query(sql);
612
- return result;
613
- }
614
757
  if (returnId) {
615
758
  const result = yield this.$pool.query(sql);
616
759
  return [result.affectedRows, result.insertId];
@@ -710,6 +853,19 @@ class Model extends AbstractModel_1.AbstractModel {
710
853
  this._setState('RELATIONS', (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.apply(nameRelations, 'all'));
711
854
  return this;
712
855
  }
856
+ /**
857
+ * The 'withAll' method is used to eager load related (relations) data when retrieving records from a database.
858
+ *
859
+ * Eager loading allows you to retrieve a primary model and its related models in a more efficient
860
+ * It's method ignore soft delete
861
+ * @param {...string} nameRelations if data exists return blank
862
+ * @return {this} this
863
+ */
864
+ withCount(...nameRelations) {
865
+ var _a;
866
+ this._setState('RELATIONS', (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.apply(nameRelations, 'count'));
867
+ return this;
868
+ }
713
869
  /**
714
870
  * The 'withTrashed' method is used to eager load related (relations) data when retrieving records from a database.
715
871
  *
@@ -780,7 +936,7 @@ class Model extends AbstractModel_1.AbstractModel {
780
936
  * @return {this} this
781
937
  */
782
938
  has(...nameRelations) {
783
- return this.relationsExists(...nameRelations);
939
+ return this.withExists(...nameRelations);
784
940
  }
785
941
  /**
786
942
  *
@@ -832,6 +988,7 @@ class Model extends AbstractModel_1.AbstractModel {
832
988
  */
833
989
  withQuery(nameRelation, callback) {
834
990
  var _a;
991
+ this.with(nameRelation);
835
992
  (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.callback(nameRelation, callback);
836
993
  return this;
837
994
  }
@@ -860,7 +1017,7 @@ class Model extends AbstractModel_1.AbstractModel {
860
1017
  * @return {this} this
861
1018
  */
862
1019
  relations(...nameRelations) {
863
- return this.relations(...nameRelations);
1020
+ return this.with(...nameRelations);
864
1021
  }
865
1022
  /**
866
1023
  *
@@ -887,7 +1044,7 @@ class Model extends AbstractModel_1.AbstractModel {
887
1044
  * @return {this} this
888
1045
  */
889
1046
  relationsExists(...nameRelations) {
890
- return this.relationsExists(...nameRelations);
1047
+ return this.withExists(...nameRelations);
891
1048
  }
892
1049
  /**
893
1050
  *
@@ -945,7 +1102,7 @@ class Model extends AbstractModel_1.AbstractModel {
945
1102
  * @return {this} this
946
1103
  */
947
1104
  relationsAll(...nameRelations) {
948
- return this.relationsAll(...nameRelations);
1105
+ return this.withAll(...nameRelations);
949
1106
  }
950
1107
  /**
951
1108
  *
@@ -954,7 +1111,7 @@ class Model extends AbstractModel_1.AbstractModel {
954
1111
  * @return {this} this
955
1112
  */
956
1113
  relationsTrashed(...nameRelations) {
957
- return this.relationsTrashed(...nameRelations);
1114
+ return this.withTrashed(...nameRelations);
958
1115
  }
959
1116
  /**
960
1117
  * The 'hasOne' relationship defines a one-to-one relationship between two database tables.
@@ -1222,12 +1379,622 @@ class Model extends AbstractModel_1.AbstractModel {
1222
1379
  return yield this.save();
1223
1380
  });
1224
1381
  }
1382
+ /**
1383
+ *
1384
+ * @return {string} string
1385
+ */
1225
1386
  toTableName() {
1226
1387
  return this.getTableName();
1227
1388
  }
1389
+ /**
1390
+ *
1391
+ * @param {string} column
1392
+ * @return {string} string
1393
+ */
1228
1394
  toTableNameAndColumn(column) {
1229
1395
  return `\`${this.getTableName()}\`.\`${this._valuePattern(column)}\``;
1230
1396
  }
1397
+ _columnPattern(column) {
1398
+ if (column.startsWith(this.$constants('RAW'))) {
1399
+ return column.replace(`${this.$constants('RAW')} `, '').replace(this.$constants('RAW'), '');
1400
+ }
1401
+ return this._valuePattern(column);
1402
+ }
1403
+ /**
1404
+ * @override Method
1405
+ * @param {string} column if arguments is object
1406
+ * @param {string?} operator ['=', '<', '>' ,'!=', '!<', '!>' ,'LIKE']
1407
+ * @param {any?} value
1408
+ * @return {this} this
1409
+ */
1410
+ where(column, operator, value) {
1411
+ if (typeof column === 'object' && column !== null && !Array.isArray(column)) {
1412
+ return this.whereObject(column);
1413
+ }
1414
+ column = this._columnPattern(String(column));
1415
+ [value, operator] = this._valueAndOperator(value, operator, arguments.length === 2);
1416
+ value = this.$utils.escape(value);
1417
+ value = this._valueTrueFalse(value);
1418
+ this._setState('WHERE', [
1419
+ ...this._getState('WHERE'),
1420
+ [
1421
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1422
+ `${this.bindColumn(String(column))}`,
1423
+ `${operator}`,
1424
+ `${this._checkValueHasRaw(value)}`
1425
+ ].join(' ')
1426
+ ]);
1427
+ return this;
1428
+ }
1429
+ /**
1430
+ * @override Method
1431
+ * @param {string} column
1432
+ * @param {string?} operator ['=', '<', '>' ,'!=', '!<', '!>' ,'LIKE']
1433
+ * @param {any?} value
1434
+ * @return {this}
1435
+ */
1436
+ orWhere(column, operator, value) {
1437
+ [value, operator] = this._valueAndOperator(value, operator, arguments.length === 2);
1438
+ column = this._columnPattern(String(column));
1439
+ value = this.$utils.escape(value);
1440
+ value = this._valueTrueFalse(value);
1441
+ this._setState('WHERE', [
1442
+ ...this._getState('WHERE'),
1443
+ [
1444
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1445
+ `${this.bindColumn(String(column))}`,
1446
+ `${operator}`,
1447
+ `${this._checkValueHasRaw(value)}`
1448
+ ].join(' ')
1449
+ ]);
1450
+ return this;
1451
+ }
1452
+ /**
1453
+ * @override Method
1454
+ * @param {Object} columns
1455
+ * @return {this}
1456
+ */
1457
+ whereObject(columns) {
1458
+ for (let column in columns) {
1459
+ column = this._columnPattern(String(column));
1460
+ const operator = '=';
1461
+ const value = this.$utils.escape(columns[column]);
1462
+ this._setState('WHERE', [
1463
+ ...this._getState('WHERE'),
1464
+ [
1465
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1466
+ `${this.bindColumn(String(column))}`,
1467
+ `${operator}`,
1468
+ `${this._checkValueHasRaw(value)}`
1469
+ ].join(' ')
1470
+ ]);
1471
+ }
1472
+ return this;
1473
+ }
1474
+ /**
1475
+ * @override Method
1476
+ * @param {string} column
1477
+ * @param {object} property object { key , value , operator }
1478
+ * @property {string} property.key
1479
+ * @property {string} property.value
1480
+ * @property {string?} property.operator
1481
+ * @return {this}
1482
+ */
1483
+ whereJSON(column, { key, value, operator }) {
1484
+ value = this.$utils.escape(value);
1485
+ value = this._valueTrueFalse(value);
1486
+ column = this._columnPattern(String(column));
1487
+ this._setState('WHERE', [
1488
+ ...this._getState('WHERE'),
1489
+ [
1490
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1491
+ `${this.bindColumn(column)}->>'$.${key}'`,
1492
+ `${operator == null ? "=" : operator.toLocaleUpperCase()}`,
1493
+ `${this._checkValueHasRaw(value)}`
1494
+ ].join(' ')
1495
+ ]);
1496
+ return this;
1497
+ }
1498
+ /**
1499
+ * @override Method
1500
+ * @param {number} userId
1501
+ * @param {string?} column custom it *if column is not user_id
1502
+ * @return {this}
1503
+ */
1504
+ whereUser(userId, column = 'user_id') {
1505
+ column = this._columnPattern(String(column));
1506
+ this._setState('WHERE', [
1507
+ ...this._getState('WHERE'),
1508
+ [
1509
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1510
+ `${this.bindColumn(column)} = ${this.$utils.escape(userId)}`,
1511
+ ].join(' ')
1512
+ ]);
1513
+ return this;
1514
+ }
1515
+ /**
1516
+ * @override Method
1517
+ * @param {string} column
1518
+ * @param {array} array
1519
+ * @return {this}
1520
+ */
1521
+ whereIn(column, array) {
1522
+ if (!Array.isArray(array))
1523
+ throw new Error(`This 'whereIn' method is required array only`);
1524
+ column = this._columnPattern(String(column));
1525
+ const values = array.length
1526
+ ? `${array.map((value) => this._checkValueHasRaw(this.$utils.escape(value))).join(',')}`
1527
+ : this.$constants('NULL');
1528
+ this._setState('WHERE', [
1529
+ ...this._getState('WHERE'),
1530
+ [
1531
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1532
+ `${this.bindColumn(column)}`,
1533
+ `${this.$constants('IN')}`,
1534
+ `(${values})`
1535
+ ].join(' ')
1536
+ ]);
1537
+ return this;
1538
+ }
1539
+ /**
1540
+ * @override Method
1541
+ * @param {string} column
1542
+ * @param {array} array
1543
+ * @return {this}
1544
+ */
1545
+ orWhereIn(column, array) {
1546
+ if (!Array.isArray(array))
1547
+ throw new Error(`This 'whereIn' method is required array only`);
1548
+ column = this._columnPattern(String(column));
1549
+ const values = array.length
1550
+ ? `${array.map((value) => this._checkValueHasRaw(this.$utils.escape(value))).join(',')}`
1551
+ : this.$constants('NULL');
1552
+ this._setState('WHERE', [
1553
+ ...this._getState('WHERE'),
1554
+ [
1555
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1556
+ `${this.bindColumn(column)}`,
1557
+ `${this.$constants('IN')}`,
1558
+ `(${values})`
1559
+ ].join(' ')
1560
+ ]);
1561
+ return this;
1562
+ }
1563
+ /**
1564
+ * @override Method
1565
+ * @param {string} column
1566
+ * @param {array} array
1567
+ * @return {this}
1568
+ */
1569
+ whereNotIn(column, array) {
1570
+ if (!Array.isArray(array))
1571
+ throw new Error(`This 'whereIn' method is required array only`);
1572
+ column = this._columnPattern(String(column));
1573
+ const values = array.length
1574
+ ? `${array.map((value) => this._checkValueHasRaw(this.$utils.escape(value))).join(',')}`
1575
+ : this.$constants('NULL');
1576
+ this._setState('WHERE', [
1577
+ ...this._getState('WHERE'),
1578
+ [
1579
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1580
+ `${this.bindColumn(column)}`,
1581
+ `${this.$constants('NOT_IN')}`,
1582
+ `(${values})`
1583
+ ].join(' ')
1584
+ ]);
1585
+ return this;
1586
+ }
1587
+ /**
1588
+ * @override Method
1589
+ * @param {string} column
1590
+ * @param {array} array
1591
+ * @return {this}
1592
+ */
1593
+ orWhereNotIn(column, array) {
1594
+ if (!Array.isArray(array))
1595
+ throw new Error(`This 'whereIn' method is required array only`);
1596
+ column = this._columnPattern(String(column));
1597
+ const values = array.length
1598
+ ? `${array.map((value) => this._checkValueHasRaw(this.$utils.escape(value))).join(',')}`
1599
+ : this.$constants('NULL');
1600
+ this._setState('WHERE', [
1601
+ ...this._getState('WHERE'),
1602
+ [
1603
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1604
+ `${this.bindColumn(column)}`,
1605
+ `${this.$constants('NOT_IN')}`,
1606
+ `(${values})`
1607
+ ].join(' ')
1608
+ ]);
1609
+ return this;
1610
+ }
1611
+ /**
1612
+ * @override Method
1613
+ * @param {string} column
1614
+ * @param {string} subQuery
1615
+ * @return {this}
1616
+ */
1617
+ whereSubQuery(column, subQuery) {
1618
+ if (!this.$utils.isSubQuery(subQuery))
1619
+ throw new Error(`This "${subQuery}" is invalid. Sub query is should contain 1 column(s)`);
1620
+ column = this._columnPattern(String(column));
1621
+ this._setState('WHERE', [
1622
+ ...this._getState('WHERE'),
1623
+ [
1624
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1625
+ `${this.bindColumn(column)}`,
1626
+ `${this.$constants('IN')}`,
1627
+ `(${subQuery})`
1628
+ ].join(' ')
1629
+ ]);
1630
+ return this;
1631
+ }
1632
+ /**
1633
+ * @override Method
1634
+ * @param {string} column
1635
+ * @param {string} subQuery
1636
+ * @return {this}
1637
+ */
1638
+ whereNotSubQuery(column, subQuery) {
1639
+ if (!this.$utils.isSubQuery(subQuery))
1640
+ throw new Error(`This "${subQuery}" is invalid. Sub query is should contain 1 column(s)`);
1641
+ column = this._columnPattern(String(column));
1642
+ this._setState('WHERE', [
1643
+ ...this._getState('WHERE'),
1644
+ [
1645
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1646
+ `${this.bindColumn(column)}`,
1647
+ `${this.$constants('NOT_IN')}`,
1648
+ `(${subQuery})`
1649
+ ].join(' ')
1650
+ ]);
1651
+ return this;
1652
+ }
1653
+ /**
1654
+ * @override Method
1655
+ * @param {string} column
1656
+ * @param {string} subQuery
1657
+ * @return {this}
1658
+ */
1659
+ orWhereSubQuery(column, subQuery) {
1660
+ if (!this.$utils.isSubQuery(subQuery))
1661
+ throw new Error(`This "${subQuery}" is invalid. Sub query is should contain 1 column(s)`);
1662
+ column = this._columnPattern(String(column));
1663
+ this._setState('WHERE', [
1664
+ ...this._getState('WHERE'),
1665
+ [
1666
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1667
+ `${this.bindColumn(column)}`,
1668
+ `${this.$constants('IN')}`,
1669
+ `(${subQuery})`
1670
+ ].join(' ')
1671
+ ]);
1672
+ return this;
1673
+ }
1674
+ /**
1675
+ * @override Method
1676
+ * @param {string} column
1677
+ * @param {string} subQuery
1678
+ * @return {this}
1679
+ */
1680
+ orWhereNotSubQuery(column, subQuery) {
1681
+ if (!this.$utils.isSubQuery(subQuery))
1682
+ throw new Error(`This "${subQuery}" is invalid sub query (Sub query Operand should contain 1 column(s) not select * )`);
1683
+ column = this._columnPattern(String(column));
1684
+ this._setState('WHERE', [
1685
+ ...this._getState('WHERE'),
1686
+ [
1687
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1688
+ `${this.bindColumn(column)}`,
1689
+ `${this.$constants('NOT_IN')}`,
1690
+ `(${subQuery})`
1691
+ ].join(' ')
1692
+ ]);
1693
+ return this;
1694
+ }
1695
+ /**
1696
+ * @override Method
1697
+ * @param {string} column
1698
+ * @param {array} array
1699
+ * @return {this}
1700
+ */
1701
+ whereBetween(column, array) {
1702
+ if (!Array.isArray(array))
1703
+ throw new Error("Value is't array");
1704
+ column = this._columnPattern(String(column));
1705
+ if (!array.length) {
1706
+ this._setState('WHERE', [
1707
+ ...this._getState('WHERE'),
1708
+ [
1709
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1710
+ `${this.bindColumn(column)}`,
1711
+ `${this.$constants('BETWEEN')}`,
1712
+ `${this.$constants('NULL')}`,
1713
+ `${this.$constants('AND')}`,
1714
+ `${this.$constants('NULL')}`
1715
+ ].join(' ')
1716
+ ]);
1717
+ return this;
1718
+ }
1719
+ const [value1, value2] = array;
1720
+ this._setState('WHERE', [
1721
+ ...this._getState('WHERE'),
1722
+ [
1723
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1724
+ `${this.bindColumn(column)}`,
1725
+ `${this.$constants('BETWEEN')}`,
1726
+ `${this._checkValueHasRaw(this.$utils.escape(value1))}`,
1727
+ `${this.$constants('AND')}`,
1728
+ `${this._checkValueHasRaw(this.$utils.escape(value2))}`
1729
+ ].join(' ')
1730
+ ]);
1731
+ return this;
1732
+ }
1733
+ /**
1734
+ * @override Method
1735
+ * @param {string} column
1736
+ * @param {array} array
1737
+ * @return {this}
1738
+ */
1739
+ orWhereBetween(column, array) {
1740
+ if (!Array.isArray(array))
1741
+ throw new Error("Value is't array");
1742
+ column = this._columnPattern(String(column));
1743
+ if (!array.length) {
1744
+ this._setState('WHERE', [
1745
+ ...this._getState('WHERE'),
1746
+ [
1747
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1748
+ `${this.bindColumn(column)}`,
1749
+ `${this.$constants('BETWEEN')}`,
1750
+ `${this.$constants('NULL')}`,
1751
+ `${this.$constants('AND')}`,
1752
+ `${this.$constants('NULL')}`
1753
+ ].join(' ')
1754
+ ]);
1755
+ return this;
1756
+ }
1757
+ const [value1, value2] = array;
1758
+ this._setState('WHERE', [
1759
+ ...this._getState('WHERE'),
1760
+ [
1761
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1762
+ `${this.bindColumn(column)}`,
1763
+ `${this.$constants('BETWEEN')}`,
1764
+ `${this._checkValueHasRaw(this.$utils.escape(value1))}`,
1765
+ `${this.$constants('AND')}`,
1766
+ `${this._checkValueHasRaw(this.$utils.escape(value2))}`
1767
+ ].join(' ')
1768
+ ]);
1769
+ return this;
1770
+ }
1771
+ /**
1772
+ * @override Method
1773
+ * @param {string} column
1774
+ * @param {array} array
1775
+ * @return {this}
1776
+ */
1777
+ whereNotBetween(column, array) {
1778
+ if (!Array.isArray(array))
1779
+ throw new Error("Value is't array");
1780
+ column = this._columnPattern(String(column));
1781
+ if (!array.length) {
1782
+ this._setState('WHERE', [
1783
+ ...this._getState('WHERE'),
1784
+ [
1785
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1786
+ `${this.bindColumn(column)}`,
1787
+ `${this.$constants('NOT_BETWEEN')}`,
1788
+ `${this.$constants('NULL')}`,
1789
+ `${this.$constants('AND')}`,
1790
+ `${this.$constants('NULL')}`
1791
+ ].join(' ')
1792
+ ]);
1793
+ return this;
1794
+ }
1795
+ const [value1, value2] = array;
1796
+ this._setState('WHERE', [
1797
+ ...this._getState('WHERE'),
1798
+ [
1799
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1800
+ `${this.bindColumn(column)}`,
1801
+ `${this.$constants('NOT_BETWEEN')}`,
1802
+ `${this._checkValueHasRaw(this.$utils.escape(value1))}`,
1803
+ `${this.$constants('AND')}`,
1804
+ `${this._checkValueHasRaw(this.$utils.escape(value2))}`
1805
+ ].join(' ')
1806
+ ]);
1807
+ return this;
1808
+ }
1809
+ /**
1810
+ * @override Method
1811
+ * @param {string} column
1812
+ * @param {array} array
1813
+ * @return {this}
1814
+ */
1815
+ orWhereNotBetween(column, array) {
1816
+ if (!Array.isArray(array))
1817
+ throw new Error("Value is't array");
1818
+ column = this._columnPattern(String(column));
1819
+ if (!array.length) {
1820
+ this._setState('WHERE', [
1821
+ ...this._getState('WHERE'),
1822
+ [
1823
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1824
+ `${this.bindColumn(column)}`,
1825
+ `${this.$constants('NOT_BETWEEN')}`,
1826
+ `${this.$constants('NULL')}`,
1827
+ `${this.$constants('AND')}`,
1828
+ `${this.$constants('NULL')}`
1829
+ ].join(' ')
1830
+ ]);
1831
+ return this;
1832
+ }
1833
+ const [value1, value2] = array;
1834
+ this._setState('WHERE', [
1835
+ ...this._getState('WHERE'),
1836
+ [
1837
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1838
+ `${this.bindColumn(column)}`,
1839
+ `${this.$constants('NOT_BETWEEN')}`,
1840
+ `${this._checkValueHasRaw(this.$utils.escape(value1))}`,
1841
+ `${this.$constants('AND')}`,
1842
+ `${this._checkValueHasRaw(this.$utils.escape(value2))}`
1843
+ ].join(' ')
1844
+ ]);
1845
+ return this;
1846
+ }
1847
+ /**
1848
+ * @override Method
1849
+ * @param {string} column
1850
+ * @return {this}
1851
+ */
1852
+ whereNull(column) {
1853
+ column = this._columnPattern(String(column));
1854
+ this._setState('WHERE', [
1855
+ ...this._getState('WHERE'),
1856
+ [
1857
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1858
+ `${this.bindColumn(column)}`,
1859
+ `${this.$constants('IS_NULL')}`
1860
+ ].join(' ')
1861
+ ]);
1862
+ return this;
1863
+ }
1864
+ /**
1865
+ * @override Method
1866
+ * @param {string} column
1867
+ * @return {this}
1868
+ */
1869
+ orWhereNull(column) {
1870
+ column = this._columnPattern(String(column));
1871
+ this._setState('WHERE', [
1872
+ ...this._getState('WHERE'),
1873
+ [
1874
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1875
+ `${this.bindColumn(column)}`,
1876
+ `${this.$constants('IS_NULL')}`
1877
+ ].join(' ')
1878
+ ]);
1879
+ return this;
1880
+ }
1881
+ /**
1882
+ * @override Method
1883
+ * @param {string} column
1884
+ * @return {this}
1885
+ */
1886
+ whereNotNull(column) {
1887
+ column = this._columnPattern(String(column));
1888
+ this._setState('WHERE', [
1889
+ ...this._getState('WHERE'),
1890
+ [
1891
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1892
+ `${this.bindColumn(column)}`,
1893
+ `${this.$constants('IS_NOT_NULL')}`
1894
+ ].join(' ')
1895
+ ]);
1896
+ return this;
1897
+ }
1898
+ /**
1899
+ * @override Method
1900
+ * @param {string} column
1901
+ * @return {this}
1902
+ */
1903
+ orWhereNotNull(column) {
1904
+ column = this._columnPattern(String(column));
1905
+ this._setState('WHERE', [
1906
+ ...this._getState('WHERE'),
1907
+ [
1908
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1909
+ `${this.bindColumn(column)}`,
1910
+ `${this.$constants('IS_NOT_NULL')}`
1911
+ ].join(' ')
1912
+ ]);
1913
+ return this;
1914
+ }
1915
+ /**
1916
+ * @override Method
1917
+ * @param {string} column
1918
+ * @param {string?} operator = < > != !< !>
1919
+ * @param {any?} value
1920
+ * @return {this}
1921
+ */
1922
+ whereSensitive(column, operator, value) {
1923
+ [value, operator] = this._valueAndOperator(value, operator, arguments.length === 2);
1924
+ column = this._columnPattern(String(column));
1925
+ value = this.$utils.escape(value);
1926
+ value = this._valueTrueFalse(value);
1927
+ this._setState('WHERE', [
1928
+ ...this._getState('WHERE'),
1929
+ [
1930
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1931
+ `${this.$constants('BINARY')}`,
1932
+ `${this.bindColumn(column)}`,
1933
+ `${operator}`,
1934
+ `${this._checkValueHasRaw(this.$utils.escape(value))}`
1935
+ ].join(' ')
1936
+ ]);
1937
+ return this;
1938
+ }
1939
+ /**
1940
+ * @override Method
1941
+ * @param {string} column
1942
+ * @param {string?} operator = < > != !< !>
1943
+ * @param {any?} value
1944
+ * @return {this}
1945
+ */
1946
+ whereStrict(column, operator, value) {
1947
+ return this.whereSensitive(column, operator, value);
1948
+ }
1949
+ /**
1950
+ * @override Method
1951
+ * @param {string} column
1952
+ * @param {string?} operator = < > != !< !>
1953
+ * @param {any?} value
1954
+ * @return {this}
1955
+ */
1956
+ orWhereSensitive(column, operator, value) {
1957
+ [value, operator] = this._valueAndOperator(value, operator, arguments.length === 2);
1958
+ column = this._columnPattern(String(column));
1959
+ value = this.$utils.escape(value);
1960
+ value = this._valueTrueFalse(value);
1961
+ this._setState('WHERE', [
1962
+ ...this._getState('WHERE'),
1963
+ [
1964
+ this._getState('WHERE').length ? `${this.$constants('OR')}` : '',
1965
+ `${this.$constants('BINARY')}`,
1966
+ `${this.bindColumn(column)}`,
1967
+ `${operator}`,
1968
+ `${this._checkValueHasRaw(this.$utils.escape(value))}`
1969
+ ].join(' ')
1970
+ ]);
1971
+ return this;
1972
+ }
1973
+ /**
1974
+ * @override Method
1975
+ * @param {Function} callback callback query
1976
+ * @return {this}
1977
+ */
1978
+ whereQuery(callback) {
1979
+ const db = new Model().copyModel(this);
1980
+ const repository = callback(db);
1981
+ if (repository instanceof Promise)
1982
+ throw new Error('"whereQuery" is not supported a Promise');
1983
+ if (!(repository instanceof Model))
1984
+ throw new Error(`Unknown callback query: '${repository}'`);
1985
+ const where = (repository === null || repository === void 0 ? void 0 : repository._getState('WHERE')) || [];
1986
+ if (!where.length)
1987
+ return this;
1988
+ const query = where.join(' ');
1989
+ this._setState('WHERE', [
1990
+ ...this._getState('WHERE'),
1991
+ [
1992
+ this._getState('WHERE').length ? `${this.$constants('AND')}` : '',
1993
+ `(${query})`
1994
+ ].join(' ')
1995
+ ]);
1996
+ return this;
1997
+ }
1231
1998
  /**
1232
1999
  * @override Method
1233
2000
  * @return {promise<boolean>} promise boolean
@@ -1235,8 +2002,7 @@ class Model extends AbstractModel_1.AbstractModel {
1235
2002
  delete() {
1236
2003
  var _a, _b;
1237
2004
  return __awaiter(this, void 0, void 0, function* () {
1238
- if (!this._getState('WHERE'))
1239
- throw new Error("Can't delete without where condition");
2005
+ this._assertError(!this._getState('where').length, "This method 'delete' is require to use 'where' conditions");
1240
2006
  this.limit(1);
1241
2007
  if (this._getState('SOFT_DELETE')) {
1242
2008
  const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
@@ -1270,14 +2036,13 @@ class Model extends AbstractModel_1.AbstractModel {
1270
2036
  deleteMany() {
1271
2037
  var _a, _b;
1272
2038
  return __awaiter(this, void 0, void 0, function* () {
1273
- if (!this._getState('WHERE'))
1274
- throw new Error("Can't delete without where condition");
2039
+ this._assertError(!this._getState('where').length, "This method 'delete' is require to use 'where' conditions");
1275
2040
  if (this._getState('SOFT_DELETE')) {
1276
2041
  const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
1277
2042
  const sql = new Model()
1278
2043
  .copyModel(this, { where: true, limit: true })
1279
2044
  .bind(this.$pool.get())
1280
- .update({
2045
+ .updateMany({
1281
2046
  [deletedAt]: this.$utils.timestamp()
1282
2047
  })
1283
2048
  .toString();
@@ -1308,7 +2073,7 @@ class Model extends AbstractModel_1.AbstractModel {
1308
2073
  if (this._getState('VOID'))
1309
2074
  return this._resultHandler(undefined);
1310
2075
  if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1311
- this.select(...yield this._exceptColumns());
2076
+ this.select(...yield this.exceptColumns());
1312
2077
  this.limit(1);
1313
2078
  if (this._getState('RELATIONS_EXISTS')) {
1314
2079
  return yield this._execute({
@@ -1340,7 +2105,7 @@ class Model extends AbstractModel_1.AbstractModel {
1340
2105
  return __awaiter(this, void 0, void 0, function* () {
1341
2106
  this._validateMethod('firstOrError');
1342
2107
  if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1343
- this.select(...yield this._exceptColumns());
2108
+ this.select(...yield this.exceptColumns());
1344
2109
  this.limit(1);
1345
2110
  if (this._getState('RELATIONS_EXISTS')) {
1346
2111
  return yield this._execute({
@@ -1378,7 +2143,7 @@ class Model extends AbstractModel_1.AbstractModel {
1378
2143
  if (this._getState('VOID'))
1379
2144
  return [];
1380
2145
  if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1381
- this.select(...yield this._exceptColumns());
2146
+ this.select(...yield this.exceptColumns());
1382
2147
  let sql = this._queryBuilder().select();
1383
2148
  if (this._getState('RELATIONS_EXISTS'))
1384
2149
  sql = String((_b = this.$relation) === null || _b === void 0 ? void 0 : _b.loadExists());
@@ -1416,7 +2181,7 @@ class Model extends AbstractModel_1.AbstractModel {
1416
2181
  page = (paginationOptions === null || paginationOptions === void 0 ? void 0 : paginationOptions.page) || page;
1417
2182
  }
1418
2183
  if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1419
- this.select(...yield this._exceptColumns());
2184
+ this.select(...yield this.exceptColumns());
1420
2185
  const offset = (page - 1) * limit;
1421
2186
  this._setState('PER_PAGE', limit);
1422
2187
  this._setState('PAGE', page);
@@ -1453,7 +2218,7 @@ class Model extends AbstractModel_1.AbstractModel {
1453
2218
  var _a;
1454
2219
  return __awaiter(this, void 0, void 0, function* () {
1455
2220
  if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1456
- this.select(...yield this._exceptColumns());
2221
+ this.select(...yield this.exceptColumns());
1457
2222
  this.selectRaw([
1458
2223
  `\`${column}\`,`,
1459
2224
  `${this.$constants('GROUP_CONCAT')}(id)`,
@@ -1721,24 +2486,23 @@ class Model extends AbstractModel_1.AbstractModel {
1721
2486
  insertNotExists(data) {
1722
2487
  return this.createNotExists(data);
1723
2488
  }
2489
+ getSchemaModel() {
2490
+ if (this.$schema == null)
2491
+ return this._getState('SCHEMA_TABLE');
2492
+ return this.$schema;
2493
+ }
2494
+ validation(schema) {
2495
+ this._setState('VALIDATE_SCHEMA', true);
2496
+ this._setState('VALIDATE_SCHEMA_DEFINED', schema);
2497
+ return this;
2498
+ }
1724
2499
  /**
1725
- *
1726
- * get schema from table
1727
- * @return {this} this this
2500
+ * The 'bindPattern' method is used to covert column relate with pattern
2501
+ * @param {string} column
2502
+ * @return {string} return table.column
1728
2503
  */
1729
- getSchema() {
1730
- return __awaiter(this, void 0, void 0, function* () {
1731
- const sql = [
1732
- `${this.$constants('SHOW')}`,
1733
- `${this.$constants('COLUMNS')}`,
1734
- `${this.$constants('FROM')}`,
1735
- `\`${this._getState('TABLE_NAME').replace(/\`/g, '')}\``
1736
- ].join(' ');
1737
- return yield this._queryStatement(sql);
1738
- });
1739
- }
1740
- getSchemaModel() {
1741
- return this._getState('SCHEMA_TABLE');
2504
+ bindPattern(column) {
2505
+ return this._valuePattern(column);
1742
2506
  }
1743
2507
  /**
1744
2508
  * @override Method
@@ -1746,17 +2510,6 @@ class Model extends AbstractModel_1.AbstractModel {
1746
2510
  */
1747
2511
  save() {
1748
2512
  return __awaiter(this, void 0, void 0, function* () {
1749
- const attributes = this.$attributes;
1750
- if (attributes != null) {
1751
- while (true) {
1752
- if (this._getState('WHERE')) {
1753
- this.update(attributes);
1754
- break;
1755
- }
1756
- this.create(attributes);
1757
- break;
1758
- }
1759
- }
1760
2513
  this._validateMethod('save');
1761
2514
  switch (String(this._getState('SAVE'))) {
1762
2515
  case 'INSERT': return yield this._insertModel();
@@ -1775,36 +2528,129 @@ class Model extends AbstractModel_1.AbstractModel {
1775
2528
  * @param {number} rows number of rows
1776
2529
  * @return {promise<any>}
1777
2530
  */
1778
- faker(rows = 1) {
2531
+ faker(rows, callback) {
1779
2532
  return __awaiter(this, void 0, void 0, function* () {
1780
2533
  let data = [];
1781
- this.void();
1782
2534
  const sql = [
1783
2535
  `${this.$constants('SHOW')}`,
1784
2536
  `${this.$constants('FIELDS')}`,
1785
2537
  `${this.$constants('FROM')}`,
1786
2538
  `${this._getState('TABLE_NAME')}`
1787
2539
  ].join(' ');
1788
- const fields = yield this._queryStatement(sql);
2540
+ const schemaModel = this.getSchemaModel();
2541
+ const fields = schemaModel == null
2542
+ ? yield this._queryStatement(sql)
2543
+ : Object.entries(schemaModel).map(([key, value]) => {
2544
+ return {
2545
+ Field: key,
2546
+ Type: value.type
2547
+ };
2548
+ });
1789
2549
  for (let row = 0; row < rows; row++) {
1790
2550
  this._assertError(this._getState('TABLE_NAME') === '' || this._getState('TABLE_NAME') == null, "Unknow this table");
1791
2551
  let columnAndValue = {};
1792
2552
  for (const { Field: field, Type: type } of fields) {
1793
- const passed = ['id', '_id', 'uuid', 'deleted_at', 'deletedAt'].some(p => field.toLowerCase() === p);
2553
+ const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
2554
+ const passed = ['id', '_id', 'uuid', deletedAt].some(p => field === p);
1794
2555
  if (passed)
1795
2556
  continue;
1796
2557
  columnAndValue = Object.assign(Object.assign({}, columnAndValue), { [field]: this.$utils.faker(type) });
1797
2558
  }
2559
+ if (callback) {
2560
+ data = [...data, callback(columnAndValue, row)];
2561
+ continue;
2562
+ }
1798
2563
  data = [...data, columnAndValue];
1799
2564
  }
1800
- const query = this._queryInsertMultipleModel(data);
1801
- this._setState('INSERT', [
1802
- `${this.$constants('INSERT')}`,
1803
- `${this._getState('TABLE_NAME')}`,
1804
- `${query}`
1805
- ].join(' '));
1806
- this._setState('SAVE', 'INSERT_MULTIPLE');
1807
- return yield this.save();
2565
+ return yield this.createMultiple(data).save();
2566
+ });
2567
+ }
2568
+ /**
2569
+ * The 'Sync' method is used to check for create or update table or columns with your schema in your model.
2570
+ *
2571
+ * @property {boolean} force - forec always check all columns if not exists will be created
2572
+ * @property {boolean} foreign - foreign key for constraint
2573
+ * @return {promise<void>}
2574
+ */
2575
+ sync({ force = false, foreign = false } = {}) {
2576
+ var _a, _b, _c, _d;
2577
+ return __awaiter(this, void 0, void 0, function* () {
2578
+ const checkTables = yield this._queryStatement(`SHOW TABLES LIKE '${this.getTableName()}'`);
2579
+ const existsTables = checkTables.map((c) => Object.values(c)[0]);
2580
+ const schemaModel = this.getSchemaModel();
2581
+ if (schemaModel == null)
2582
+ return this._assertError(schemaModel == null, 'Schema model not found');
2583
+ const checkTableIsExists = existsTables.some((table) => table === this.getTableName());
2584
+ const syncForeignKey = ({ schemaModel, model }) => __awaiter(this, void 0, void 0, function* () {
2585
+ var _e;
2586
+ for (const key in schemaModel) {
2587
+ if (((_e = schemaModel[key]) === null || _e === void 0 ? void 0 : _e.foreignKey) == null)
2588
+ continue;
2589
+ const foreign = schemaModel[key].foreignKey;
2590
+ const table = typeof foreign.on === "string" ? foreign.on : foreign.on.getTableName();
2591
+ const sql = [
2592
+ "ALTER TABLE",
2593
+ `\`${model.getTableName()}\``,
2594
+ "ADD CONSTRAINT",
2595
+ `\`${model.getTableName()}(${key})_${table}(${foreign.references})\``,
2596
+ `FOREIGN KEY(\`${key}\`)`,
2597
+ `REFERENCES \`${table}\`(\`${foreign.references}\`)`,
2598
+ `ON DELETE ${foreign.onDelete} ON UPDATE ${foreign.onUpdate}`
2599
+ ].join(' ');
2600
+ try {
2601
+ yield model._queryStatement(sql);
2602
+ }
2603
+ catch (e) {
2604
+ if (typeof foreign.on === "string")
2605
+ continue;
2606
+ if (String(e.message).includes("Duplicate foreign key constraint"))
2607
+ continue;
2608
+ const schemaModelOn = yield foreign.on.getSchemaModel();
2609
+ if (!schemaModelOn)
2610
+ continue;
2611
+ const tableSql = new Schema_1.Schema().createTable(`\`${table}\``, schemaModelOn);
2612
+ yield model._queryStatement(tableSql).catch(e => console.log(e));
2613
+ yield model._queryStatement(sql).catch(e => console.log(e));
2614
+ continue;
2615
+ }
2616
+ }
2617
+ });
2618
+ if (!checkTableIsExists) {
2619
+ const sql = new Schema_1.Schema().createTable(`\`${this.getTableName()}\``, schemaModel);
2620
+ yield this._queryStatement(sql);
2621
+ yield syncForeignKey({ schemaModel, model: this });
2622
+ }
2623
+ if (foreign) {
2624
+ yield syncForeignKey({ schemaModel, model: this });
2625
+ return;
2626
+ }
2627
+ if (!force)
2628
+ return;
2629
+ const schemaTable = yield this.getSchema();
2630
+ const schemaTableKeys = schemaTable.map((k) => k.Field);
2631
+ const schemaModelKeys = Object.keys(schemaModel);
2632
+ const missingColumns = schemaModelKeys.filter(schemaModelKey => !schemaTableKeys.includes(schemaModelKey));
2633
+ if (!missingColumns.length)
2634
+ return;
2635
+ const entries = Object.entries(schemaModel);
2636
+ for (const column of missingColumns) {
2637
+ const indexWithColumn = entries.findIndex(([key]) => key === column);
2638
+ const findAfterIndex = indexWithColumn ? entries[indexWithColumn - 1][0] : null;
2639
+ const type = (_b = (_a = schemaModel[column]) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : null;
2640
+ const attributes = (_d = (_c = schemaModel[column]) === null || _c === void 0 ? void 0 : _c.attributes) !== null && _d !== void 0 ? _d : null;
2641
+ if (findAfterIndex == null || type == null || attributes == null)
2642
+ continue;
2643
+ const sql = [
2644
+ 'ALTER TABLE',
2645
+ `\`${this.getTableName()}\``,
2646
+ 'ADD',
2647
+ `\`${column}\` ${type} ${attributes.join(' ')}`,
2648
+ 'AFTER',
2649
+ `\`${findAfterIndex}\``
2650
+ ].join(' ');
2651
+ yield this._queryStatement(sql);
2652
+ }
2653
+ return;
1808
2654
  });
1809
2655
  }
1810
2656
  _valuePattern(value) {
@@ -1830,14 +2676,27 @@ class Model extends AbstractModel_1.AbstractModel {
1830
2676
  return pluralize_1.default.plural(this._valuePattern(tb));
1831
2677
  }
1832
2678
  _makeTableName() {
1833
- const tableName = this._classToTableName();
1834
- this._setState('TABLE_NAME', `\`${tableName}\``);
2679
+ if (this.$table == null || this.$table === '') {
2680
+ const tableName = this._classToTableName();
2681
+ this._setState('TABLE_NAME', `\`${this._valuePattern(tableName)}\``);
2682
+ return this;
2683
+ }
2684
+ this._setState('TABLE_NAME', `\`${this._valuePattern(this.$table)}\``);
1835
2685
  return this;
1836
2686
  }
1837
2687
  _handleSoftDelete() {
1838
2688
  if (this._getState('SOFT_DELETE')) {
1839
2689
  const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
1840
- this.whereNull(deletedAt);
2690
+ const wheres = this._getState('WHERE');
2691
+ const softDeleteIsNull = [
2692
+ this.bindColumn(`${this.getTableName()}.${deletedAt}`),
2693
+ this.$constants('IS_NULL')
2694
+ ].join(' ');
2695
+ if (!wheres.some((where) => where.includes(softDeleteIsNull))) {
2696
+ this.whereNull(deletedAt);
2697
+ return this;
2698
+ }
2699
+ return this;
1841
2700
  }
1842
2701
  return this;
1843
2702
  }
@@ -1872,7 +2731,7 @@ class Model extends AbstractModel_1.AbstractModel {
1872
2731
  const validateSchema = this._getState('VALIDATE_SCHEMA');
1873
2732
  if (!validateSchema)
1874
2733
  return;
1875
- const schemaTable = this._getState('SCHEMA_TABLE');
2734
+ const schemaTable = this.getSchemaModel();
1876
2735
  if (schemaTable == null) {
1877
2736
  return this._assertError(schemaTable == null, `This method "validateSchema" isn't validation without schema. Please use the method "useSchema" for define your schema`);
1878
2737
  }
@@ -1885,10 +2744,6 @@ class Model extends AbstractModel_1.AbstractModel {
1885
2744
  return;
1886
2745
  const regexDate = /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/;
1887
2746
  const regexDateTime = /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]/;
1888
- Object.entries(data).some(([column]) => {
1889
- if (schema[column] == null)
1890
- this._assertError(`This column "${column}" is not in schema`);
1891
- });
1892
2747
  for (const column in schema) {
1893
2748
  const s = schema[column];
1894
2749
  const r = data[column];
@@ -2339,12 +3194,12 @@ class Model extends AbstractModel_1.AbstractModel {
2339
3194
  return [
2340
3195
  `(${[...new Set(columns)].join(',')})`,
2341
3196
  `${this.$constants('VALUES')}`,
2342
- `${values.join(',')}`
3197
+ `${values.join(', ')}`
2343
3198
  ].join(' ');
2344
3199
  }
2345
3200
  _insertNotExistsModel() {
2346
3201
  return __awaiter(this, void 0, void 0, function* () {
2347
- this._assertError(!this._getState('WHERE'), "This method 'createNotExists' is require to use 'where'");
3202
+ this._assertError(!this._getState('where').length, "This method 'createNotExists' is require to use 'where' conditions");
2348
3203
  const check = (yield new Model()
2349
3204
  .copyModel(this, { where: true, select: true, limit: true })
2350
3205
  .bind(this.$pool.get())
@@ -2390,8 +3245,9 @@ class Model extends AbstractModel_1.AbstractModel {
2390
3245
  });
2391
3246
  }
2392
3247
  _createMultipleModel() {
3248
+ var _a;
2393
3249
  return __awaiter(this, void 0, void 0, function* () {
2394
- for (const data of this._getState('DATA')) {
3250
+ for (const data of (_a = this._getState('DATA')) !== null && _a !== void 0 ? _a : []) {
2395
3251
  yield this._validateSchema(data, 'insert');
2396
3252
  }
2397
3253
  const [result, id] = yield this._actionStatement({
@@ -2416,7 +3272,7 @@ class Model extends AbstractModel_1.AbstractModel {
2416
3272
  }
2417
3273
  _updateOrInsertModel() {
2418
3274
  return __awaiter(this, void 0, void 0, function* () {
2419
- this._assertError(!this._getState('WHERE'), "This method 'createOrUpdate' is require to use 'where'");
3275
+ this._assertError(!this._getState('where').length, "This method 'createOrUpdate' is require to use 'where' conditions");
2420
3276
  const check = (yield new Model()
2421
3277
  .copyModel(this, { select: true, where: true, limit: true })
2422
3278
  .bind(this.$pool.get())
@@ -2471,7 +3327,7 @@ class Model extends AbstractModel_1.AbstractModel {
2471
3327
  }
2472
3328
  _insertOrSelectModel() {
2473
3329
  return __awaiter(this, void 0, void 0, function* () {
2474
- this._assertError(!this._getState('WHERE'), "This method 'createOrSelect' is require to use 'where'");
3330
+ this._assertError(!this._getState('where').length, "This method 'createOrSelect' is require to use 'where' conditions");
2475
3331
  const check = (yield new Model()
2476
3332
  .copyModel(this, { select: true, where: true, limit: true })
2477
3333
  .bind(this.$pool.get())
@@ -2520,7 +3376,7 @@ class Model extends AbstractModel_1.AbstractModel {
2520
3376
  }
2521
3377
  _updateModel() {
2522
3378
  return __awaiter(this, void 0, void 0, function* () {
2523
- this._assertError(!String(this._getState('WHERE')), "This method 'update' is require to use 'where'");
3379
+ this._assertError(!this._getState('where').length, "This method 'update' is require to use 'where' conditions");
2524
3380
  yield this._validateSchema(this._getState('DATA'), 'update');
2525
3381
  const sql = this._queryBuilder().update();
2526
3382
  const result = yield this._actionStatement({ sql });
@@ -2600,9 +3456,9 @@ class Model extends AbstractModel_1.AbstractModel {
2600
3456
  var _a, _b, _c, _d, _e;
2601
3457
  return __awaiter(this, void 0, void 0, function* () {
2602
3458
  try {
2603
- if (retry > 3 || this._getState('RETRY') > 3)
3459
+ if (retry > 2 || this._getState('RETRY') > 2)
2604
3460
  throw e;
2605
- const schemaTable = this._getState('SCHEMA_TABLE');
3461
+ const schemaTable = this.getSchemaModel();
2606
3462
  if (schemaTable == null)
2607
3463
  return this._stoppedRetry(e);
2608
3464
  if (!(e instanceof Error))
@@ -2643,14 +3499,14 @@ class Model extends AbstractModel_1.AbstractModel {
2643
3499
  yield this._queryStatement(sql);
2644
3500
  }
2645
3501
  catch (e) {
2646
- if (retry > 3)
3502
+ if (retry >= 2)
2647
3503
  throw e;
2648
3504
  yield this._checkSchemaOrNextError(e, retry + 1);
2649
3505
  }
2650
3506
  });
2651
3507
  }
2652
3508
  _stoppedRetry(e) {
2653
- this._setState('RETRY', 3);
3509
+ this._setState('RETRY', 2);
2654
3510
  throw e;
2655
3511
  }
2656
3512
  _observer(result, type) {
@@ -2664,10 +3520,44 @@ class Model extends AbstractModel_1.AbstractModel {
2664
3520
  }
2665
3521
  return;
2666
3522
  }
3523
+ _makeRelations() {
3524
+ if (this.$hasOne != null) {
3525
+ for (const hasOne of this.$hasOne) {
3526
+ this.hasOne(Object.assign(Object.assign({}, hasOne), { name: String(hasOne.name) }));
3527
+ }
3528
+ }
3529
+ if (this.$hasMany != null) {
3530
+ for (const hasMany of this.$hasMany) {
3531
+ this.hasMany(Object.assign(Object.assign({}, hasMany), { name: String(hasMany.name) }));
3532
+ }
3533
+ }
3534
+ if (this.$belongsTo != null) {
3535
+ for (const belongsTo of this.$belongsTo) {
3536
+ this.belongsTo(Object.assign(Object.assign({}, belongsTo), { name: String(belongsTo.name) }));
3537
+ }
3538
+ }
3539
+ if (this.$belongsToMany != null) {
3540
+ for (const belongsToMany of this.$belongsToMany) {
3541
+ this.belongsToMany(Object.assign(Object.assign({}, belongsToMany), { name: String(belongsToMany.name) }));
3542
+ }
3543
+ }
3544
+ return this;
3545
+ }
2667
3546
  _initialModel() {
2668
- this.$state = new StateHandler_1.StateHandler(this.$constants('MODEL'));
3547
+ this.$state = new State_1.StateHandler(this.$constants('MODEL'));
3548
+ if (this.$pattern != null)
3549
+ this.usePattern(this.$pattern);
2669
3550
  this._makeTableName();
2670
- this.$relation = new RelationHandler_1.RelationHandler(this);
3551
+ this.$relation = new Relation_1.RelationHandler(this);
3552
+ this._makeRelations();
3553
+ if (this.$uuid != null)
3554
+ this.useUUID(this.$uuidColumn);
3555
+ if (this.$timestamp != null)
3556
+ this.useTimestamp(this.$timestampColumns);
3557
+ if (this.$softDelete != null)
3558
+ this.useSoftDelete(this.$softDeleteColumn);
3559
+ if (this.$validateSchema != null)
3560
+ this.useValidateSchema(this.$validateSchema);
2671
3561
  return this;
2672
3562
  }
2673
3563
  }