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
@@ -1,5 +1,5 @@
1
- import { AbstractDB } from './Abstract/AbstractDB';
2
- import { Connection, ConnectionOptions, ConnectionTransaction } from './Interface';
1
+ import { AbstractDB } from './Abstracts/AbstractDB';
2
+ import { Connection, ConnectionOptions, ConnectionTransaction } from '../Interface';
3
3
  /**
4
4
  * 'DB' class is a component of the database system
5
5
  * @param {string?} table table name
@@ -95,6 +95,46 @@ declare class DB extends AbstractDB {
95
95
  * @return {string} string
96
96
  */
97
97
  static generateUUID(): string;
98
+ /**
99
+ * The 'snakeCase' methid is used to covert value to snakeCase pattern.
100
+ * @return {string} string
101
+ */
102
+ snakeCase(value: string): string;
103
+ /**
104
+ * The 'snakeCase' methid is used to covert value to snake_case pattern.
105
+ * @return {string} string
106
+ */
107
+ static snakeCase(value: string): string;
108
+ /**
109
+ * The 'camelCase' methid is used to covert value to camelCase pattern.
110
+ * @return {string} string
111
+ */
112
+ camelCase(value: string): string;
113
+ /**
114
+ * The 'camelCase' methid is used to covert value to camelCase pattern.
115
+ * @return {string} string
116
+ */
117
+ static camelCase(value: string): string;
118
+ /**
119
+ * The 'escape' methid is used to escaping SQL injections.
120
+ * @return {string} string
121
+ */
122
+ escape(value: string): string;
123
+ /**
124
+ * The 'escape' methid is used to escaping SQL injections.
125
+ * @return {string} string
126
+ */
127
+ static escape(value: string): string;
128
+ /**
129
+ * The 'escapeXSS' methid is used to escaping XSS characters.
130
+ * @return {string} string
131
+ */
132
+ escapeXSS(value: string): string;
133
+ /**
134
+ * The 'escapeXSS' methid is used to escaping XSS characters.
135
+ * @return {string} string
136
+ */
137
+ static escapeXSS(value: string): string;
98
138
  /**
99
139
  * The 'raw' methid is used to allow for raw sql queries to some method in 'DB' or 'Model'.
100
140
  * @param {string} sql
@@ -24,10 +24,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.DB = void 0;
27
- const AbstractDB_1 = require("./Abstract/AbstractDB");
28
- const ProxyHandler_1 = require("./ProxyHandler");
27
+ const AbstractDB_1 = require("./Abstracts/AbstractDB");
28
+ const Proxy_1 = require("./Handlers/Proxy");
29
29
  const connection_1 = require("../connection");
30
- const StateHandler_1 = __importDefault(require("./StateHandler"));
30
+ const State_1 = __importDefault(require("./Handlers/State"));
31
31
  /**
32
32
  * 'DB' class is a component of the database system
33
33
  * @param {string?} table table name
@@ -40,7 +40,7 @@ class DB extends AbstractDB_1.AbstractDB {
40
40
  this._initialDB();
41
41
  if (table)
42
42
  this.table(table);
43
- return new Proxy(this, ProxyHandler_1.proxyHandler);
43
+ return new Proxy(this, Proxy_1.proxyHandler);
44
44
  }
45
45
  /**
46
46
  * The 'table' method is used to define the table name.
@@ -178,6 +178,62 @@ class DB extends AbstractDB_1.AbstractDB {
178
178
  static generateUUID() {
179
179
  return new this().generateUUID();
180
180
  }
181
+ /**
182
+ * The 'snakeCase' methid is used to covert value to snakeCase pattern.
183
+ * @return {string} string
184
+ */
185
+ snakeCase(value) {
186
+ return this.$utils.snakeCase(value);
187
+ }
188
+ /**
189
+ * The 'snakeCase' methid is used to covert value to snake_case pattern.
190
+ * @return {string} string
191
+ */
192
+ static snakeCase(value) {
193
+ return new this().$utils.snakeCase(value);
194
+ }
195
+ /**
196
+ * The 'camelCase' methid is used to covert value to camelCase pattern.
197
+ * @return {string} string
198
+ */
199
+ camelCase(value) {
200
+ return this.$utils.camelCase(value);
201
+ }
202
+ /**
203
+ * The 'camelCase' methid is used to covert value to camelCase pattern.
204
+ * @return {string} string
205
+ */
206
+ static camelCase(value) {
207
+ return new this().$utils.camelCase(value);
208
+ }
209
+ /**
210
+ * The 'escape' methid is used to escaping SQL injections.
211
+ * @return {string} string
212
+ */
213
+ escape(value) {
214
+ return this.$utils.escape(value);
215
+ }
216
+ /**
217
+ * The 'escape' methid is used to escaping SQL injections.
218
+ * @return {string} string
219
+ */
220
+ static escape(value) {
221
+ return new this().$utils.escape(value);
222
+ }
223
+ /**
224
+ * The 'escapeXSS' methid is used to escaping XSS characters.
225
+ * @return {string} string
226
+ */
227
+ escapeXSS(value) {
228
+ return this.$utils.escapeXSS(value);
229
+ }
230
+ /**
231
+ * The 'escapeXSS' methid is used to escaping XSS characters.
232
+ * @return {string} string
233
+ */
234
+ static escapeXSS(value) {
235
+ return new this().$utils.escapeXSS(value);
236
+ }
181
237
  /**
182
238
  * The 'raw' methid is used to allow for raw sql queries to some method in 'DB' or 'Model'.
183
239
  * @param {string} sql
@@ -276,7 +332,7 @@ class DB extends AbstractDB_1.AbstractDB {
276
332
  });
277
333
  }
278
334
  _initialDB() {
279
- this.$state = new StateHandler_1.default(this.$constants('DB'));
335
+ this.$state = new State_1.default(this.$constants('DB'));
280
336
  return this;
281
337
  }
282
338
  }
@@ -0,0 +1,20 @@
1
+ import { RelationQuery, ValidateSchemaDecorator } from "../Interface";
2
+ import { Blueprint } from "./Blueprint";
3
+ export declare const Table: (name: string) => (constructor: Function) => void;
4
+ export declare const TableSingular: () => (constructor: Function) => void;
5
+ export declare const TablePlural: () => (constructor: Function) => void;
6
+ export declare const Column: (blueprint: () => Blueprint) => (target: any, key: string) => void;
7
+ export declare const Validate: (validate: ValidateSchemaDecorator) => (target: any, key: string) => void;
8
+ export declare const UUID: (column?: string) => (constructor: Function) => void;
9
+ export declare const Timestamp: (timestampColumns?: {
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ }) => (constructor: Function) => void;
13
+ export declare const SoftDelete: (column?: string) => (constructor: Function) => void;
14
+ export declare const Pattern: (pattern: 'camelCase' | 'snake_case') => (constructor: Function) => void;
15
+ export declare const CamelCase: () => (constructor: Function) => void;
16
+ export declare const SnakeCase: () => (constructor: Function) => void;
17
+ export declare const HasOne: ({ name, as, model, localKey, foreignKey, freezeTable }: RelationQuery) => (target: any, key: string) => void;
18
+ export declare const HasMany: ({ name, as, model, localKey, foreignKey, freezeTable }: RelationQuery) => (target: any, key: string) => void;
19
+ export declare const BelongsTo: ({ name, as, model, localKey, foreignKey, freezeTable }: RelationQuery) => (target: any, key: string) => void;
20
+ export declare const BelongsToMany: ({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }: RelationQuery) => (target: any, key: string) => void;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BelongsToMany = exports.BelongsTo = exports.HasMany = exports.HasOne = exports.SnakeCase = exports.CamelCase = exports.Pattern = exports.SoftDelete = exports.Timestamp = exports.UUID = exports.Validate = exports.Column = exports.TablePlural = exports.TableSingular = exports.Table = void 0;
7
+ const pluralize_1 = __importDefault(require("pluralize"));
8
+ const Blueprint_1 = require("./Blueprint");
9
+ const Table = (name) => {
10
+ return (constructor) => {
11
+ if (constructor.prototype == null)
12
+ return;
13
+ constructor.prototype.$table = name;
14
+ };
15
+ };
16
+ exports.Table = Table;
17
+ const TableSingular = () => {
18
+ return (constructor) => {
19
+ if (constructor.prototype == null)
20
+ return;
21
+ const name = constructor.name.replace(/([A-Z])/g, (str) => '_' + str.toLowerCase()).slice(1);
22
+ constructor.prototype.$table = pluralize_1.default.singular(name);
23
+ };
24
+ };
25
+ exports.TableSingular = TableSingular;
26
+ const TablePlural = () => {
27
+ return (constructor) => {
28
+ if (constructor.prototype == null)
29
+ return;
30
+ const name = constructor.name.replace(/([A-Z])/g, (str) => '_' + str.toLowerCase()).slice(1);
31
+ constructor.prototype.$table = pluralize_1.default.plural(name);
32
+ };
33
+ };
34
+ exports.TablePlural = TablePlural;
35
+ const Column = (blueprint) => {
36
+ return (target, key) => {
37
+ if (!(blueprint() instanceof Blueprint_1.Blueprint))
38
+ return;
39
+ if (target.$schema == null)
40
+ target.$schema = {};
41
+ target.$schema = Object.assign(Object.assign({}, target.$schema), { [key]: blueprint() });
42
+ };
43
+ };
44
+ exports.Column = Column;
45
+ const Validate = (validate) => {
46
+ return (target, key) => {
47
+ if (target.$validateSchema == null)
48
+ target.$validateSchema = {};
49
+ target.$validateSchema = Object.assign(Object.assign({}, target.$validateSchema), { [key]: validate });
50
+ };
51
+ };
52
+ exports.Validate = Validate;
53
+ const UUID = (column) => {
54
+ return (constructor) => {
55
+ if (constructor.prototype == null)
56
+ return;
57
+ constructor.prototype.$uuid = true;
58
+ constructor.prototype.$uuidColumn = column;
59
+ };
60
+ };
61
+ exports.UUID = UUID;
62
+ const Timestamp = (timestampColumns) => {
63
+ return (constructor) => {
64
+ if (constructor.prototype == null)
65
+ return;
66
+ constructor.prototype.$timestamp = true;
67
+ constructor.prototype.$timestampColumns = timestampColumns;
68
+ };
69
+ };
70
+ exports.Timestamp = Timestamp;
71
+ const SoftDelete = (column) => {
72
+ return (constructor) => {
73
+ if (constructor.prototype == null)
74
+ return;
75
+ constructor.prototype.$softDelete = true;
76
+ constructor.prototype.$softDeleteColumn = column;
77
+ };
78
+ };
79
+ exports.SoftDelete = SoftDelete;
80
+ const Pattern = (pattern) => {
81
+ return (constructor) => {
82
+ if (constructor.prototype == null)
83
+ return;
84
+ constructor.prototype.$pattern = pattern;
85
+ };
86
+ };
87
+ exports.Pattern = Pattern;
88
+ const CamelCase = () => {
89
+ return (constructor) => {
90
+ if (constructor.prototype == null)
91
+ return;
92
+ constructor.prototype.$pattern = 'camelCase';
93
+ };
94
+ };
95
+ exports.CamelCase = CamelCase;
96
+ const SnakeCase = () => {
97
+ return (constructor) => {
98
+ if (constructor.prototype == null)
99
+ return;
100
+ constructor.prototype.$pattern = 'snake_case';
101
+ };
102
+ };
103
+ exports.SnakeCase = SnakeCase;
104
+ const HasOne = ({ name, as, model, localKey, foreignKey, freezeTable }) => {
105
+ return (target, key) => {
106
+ if (target.$hasOne == null)
107
+ target.$hasOne = [];
108
+ target.$hasOne.push({
109
+ name: name == null ? key : name,
110
+ as,
111
+ model,
112
+ localKey,
113
+ foreignKey,
114
+ freezeTable
115
+ });
116
+ };
117
+ };
118
+ exports.HasOne = HasOne;
119
+ const HasMany = ({ name, as, model, localKey, foreignKey, freezeTable }) => {
120
+ return (target, key) => {
121
+ if (target.$hasMany == null)
122
+ target.$hasMany = [];
123
+ target.$hasMany.push({
124
+ name: name == null ? key : name,
125
+ as,
126
+ model,
127
+ localKey,
128
+ foreignKey,
129
+ freezeTable
130
+ });
131
+ };
132
+ };
133
+ exports.HasMany = HasMany;
134
+ const BelongsTo = ({ name, as, model, localKey, foreignKey, freezeTable }) => {
135
+ return (target, key) => {
136
+ if (target.$belongsTo == null)
137
+ target.$belongsTo = [];
138
+ target.$belongsTo.push({
139
+ name: name == null ? key : name,
140
+ as,
141
+ model,
142
+ localKey,
143
+ foreignKey,
144
+ freezeTable
145
+ });
146
+ };
147
+ };
148
+ exports.BelongsTo = BelongsTo;
149
+ const BelongsToMany = ({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }) => {
150
+ return (target, key) => {
151
+ if (target.$belongsToMany == null)
152
+ target.$belongsToMany = [];
153
+ target.$belongsToMany.push({
154
+ name: name == null ? key : name,
155
+ as,
156
+ model,
157
+ localKey,
158
+ foreignKey,
159
+ freezeTable,
160
+ pivot,
161
+ oldVersion,
162
+ modelPivot
163
+ });
164
+ };
165
+ };
166
+ exports.BelongsToMany = BelongsToMany;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.proxyHandler = void 0;
4
- const Logger_1 = require("./Logger");
4
+ const Logger_1 = require("../Logger");
5
5
  const proxyHandler = {
6
6
  set: (self, name, value) => {
7
7
  var _a;
@@ -1,5 +1,5 @@
1
- import { Relation, RelationQuery } from "./Interface";
2
- import { Model } from "./Model";
1
+ import { Relation, RelationQuery } from "../../Interface";
2
+ import { Model } from "../Model";
3
3
  declare class RelationHandler {
4
4
  private MODEL;
5
5
  private $constants;
@@ -7,7 +7,7 @@ declare class RelationHandler {
7
7
  constructor(model: Model);
8
8
  load(parents: Record<string, any>[], relation: Relation): Promise<any[]>;
9
9
  loadExists(): string;
10
- apply(nameRelations: string[], type: 'all' | 'exists' | 'trashed' | 'default'): Relation[];
10
+ apply(nameRelations: string[], type: 'all' | 'exists' | 'trashed' | 'count' | 'default'): Relation[];
11
11
  callback(nameRelation: string, cb: Function): void;
12
12
  hasOne({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
13
13
  hasMany({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
@@ -23,7 +23,7 @@ declare class RelationHandler {
23
23
  private _relationMapData;
24
24
  private _belongsToMany;
25
25
  private _valueInRelation;
26
- private _valuePattern;
26
+ protected _valuePattern(value: string): string;
27
27
  private _assertError;
28
28
  protected _getState(key: string): any;
29
29
  protected _setState(key: string, value: any): void;
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.RelationHandler = void 0;
16
16
  const pluralize_1 = __importDefault(require("pluralize"));
17
- const Model_1 = require("./Model");
17
+ const Model_1 = require("../Model");
18
18
  class RelationHandler {
19
19
  constructor(model) {
20
20
  this.MODEL = model;
@@ -36,7 +36,7 @@ class RelationHandler {
36
36
  const data = parent[localKey];
37
37
  if (parent.hasOwnProperty(localKey))
38
38
  return data;
39
- this.MODEL['_assertError'](data == null, `Unknown relationship without primary or foreign key in Relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
39
+ this.MODEL['_assertError'](data == null, `This relationship lacks a primary or foreign key in the '${relation === null || relation === void 0 ? void 0 : relation.name}' relation. Please review the query to identify whether the key '${localKey}' or '${foreignKey}' is missing.`);
40
40
  })
41
41
  .filter(d => d != null);
42
42
  const parentIds = Array.from(new Set(localKeyId)) || [];
@@ -44,6 +44,19 @@ class RelationHandler {
44
44
  return [];
45
45
  const query = relation.query;
46
46
  this._assertError(query == null, `Unknown callback query in [Relation : ${relation.name}]`);
47
+ if (relation.count) {
48
+ const results = yield query
49
+ .whereIn(foreignKey, parentIds)
50
+ .select(foreignKey)
51
+ .selectRaw(`${this.$constants('COUNT')}(${foreignKey}) ${this.$constants('AS')} \`aggregate\``)
52
+ .debug(this._getState('DEBUG'))
53
+ .when(relation.trashed, (query) => query.onlyTrashed())
54
+ .when(relation.all, (query) => query.disableSoftDelete())
55
+ .bind(this.MODEL['$pool'].get())
56
+ .groupBy(foreignKey)
57
+ .get();
58
+ return this._relationMapData(parents, results, relation);
59
+ }
47
60
  const results = yield query
48
61
  .whereIn(foreignKey, parentIds)
49
62
  .debug(this._getState('DEBUG'))
@@ -70,6 +83,8 @@ class RelationHandler {
70
83
  const cloneRelations = clone['_getState']('RELATIONS');
71
84
  if (cloneRelations.length) {
72
85
  for (const r of cloneRelations) {
86
+ if (!r.exists)
87
+ continue;
73
88
  if (r.query == null)
74
89
  continue;
75
90
  const sql = (_c = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._handleRelationsExists(r)) !== null && _c !== void 0 ? _c : '';
@@ -82,21 +97,21 @@ class RelationHandler {
82
97
  : new Model_1.Model().table(String(pivot));
83
98
  const sql = clone
84
99
  .bind(this.MODEL['$pool'].get())
85
- .select(this._getState('PRIMARY_KEY'))
86
- .whereReference(`\`${query.getTableName()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${localKey}\``)
100
+ .selectRaw("1")
101
+ .whereReference(`\`${query.getTableName()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${localKey}\``)
87
102
  .toString();
88
103
  thisPivot.whereExists(sql);
89
104
  const sqlPivot = thisPivot
90
105
  .bind(this.MODEL['$pool'].get())
91
- .select(thisPivot['$state'].get('PRIMARY_KEY'))
92
- .whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"))}\``)
106
+ .selectRaw("1")
107
+ .whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"))}\``)
93
108
  .toString();
94
109
  this.MODEL['whereExists'](sqlPivot);
95
110
  continue;
96
111
  }
97
112
  const sql = clone
98
113
  .bind(this.MODEL['$pool'].get())
99
- .select(this._getState('PRIMARY_KEY'))
114
+ .selectRaw("1")
100
115
  .whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${query.getTableName()}\`.\`${foreignKey}\``)
101
116
  .toString();
102
117
  this.MODEL['whereExists'](sql);
@@ -108,7 +123,7 @@ class RelationHandler {
108
123
  const relations = nameRelations.map((name) => {
109
124
  var _a, _b, _c;
110
125
  const relation = (_a = this._getState('RELATION')) === null || _a === void 0 ? void 0 : _a.find((data) => data.name === name);
111
- this._assertError(relation == null, `This Relation "${name}" not be register in Model "${(_b = this.constructor) === null || _b === void 0 ? void 0 : _b.name}"`);
126
+ this._assertError(relation == null, `The relation '${name}' is not registered in the model '${(_b = this.MODEL.constructor) === null || _b === void 0 ? void 0 : _b.name}'.`);
112
127
  const relationHasExists = (_c = Object.values(this.$constants('RELATIONSHIP'))) === null || _c === void 0 ? void 0 : _c.includes(relation.relation);
113
128
  this._assertError(!relationHasExists, `Unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
114
129
  if (relation.query == null)
@@ -133,7 +148,7 @@ class RelationHandler {
133
148
  callback(nameRelation, cb) {
134
149
  var _a, _b;
135
150
  const relation = this._getState('RELATIONS').find((data) => data.name === nameRelation);
136
- this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
151
+ this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.MODEL.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
137
152
  const relationHasExists = (_b = Object.values(this.$constants('RELATIONSHIP'))) === null || _b === void 0 ? void 0 : _b.includes(relation.relation);
138
153
  this._assertError(!relationHasExists, `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
139
154
  relation.query = cb(new relation.model());
@@ -284,7 +299,7 @@ class RelationHandler {
284
299
  return;
285
300
  }
286
301
  _handleRelationsExists(relation) {
287
- var _a, _b, _c;
302
+ var _a, _b, _c, _d;
288
303
  this._assertError(!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length), `unknown [relation]`);
289
304
  const { localKey, foreignKey } = this._valueInRelation(relation);
290
305
  const query = relation.query;
@@ -293,16 +308,46 @@ class RelationHandler {
293
308
  const cloneRelations = clone['_getState']('RELATIONS');
294
309
  if (cloneRelations.length) {
295
310
  for (const r of cloneRelations) {
311
+ if (!r.exists)
312
+ continue;
296
313
  if (r.query == null)
297
314
  continue;
298
- const sql = (_c = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._handleRelationsExists(r)) !== null && _c !== void 0 ? _c : '';
315
+ if (r.relation === this.$constants('RELATIONSHIP').belongsToMany) {
316
+ const data = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._valueInRelation(r);
317
+ if (data == null)
318
+ continue;
319
+ const { modelPivot, pivot, foreignKey } = data;
320
+ const thisPivot = modelPivot == null && pivot == null
321
+ ? new Model_1.Model().table(`${this._valuePattern([
322
+ pluralize_1.default.singular(clone.getTableName()),
323
+ pluralize_1.default.singular(this.MODEL['getTableName']())
324
+ ].join("_"))}`)
325
+ : modelPivot ? new modelPivot : new Model_1.Model().table(`${pivot}`);
326
+ const sql = clone
327
+ .bind(this.MODEL['$pool'].get())
328
+ .selectRaw("1")
329
+ .whereReference(`\`${clone.getTableName()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${this._valuePattern([
330
+ pluralize_1.default.singular(clone.getTableName()),
331
+ localKey
332
+ ].join('_'))}\``)
333
+ .toString();
334
+ thisPivot.whereExists(sql);
335
+ const sqlPivot = thisPivot
336
+ .bind(this.MODEL['$pool'].get())
337
+ .selectRaw("1")
338
+ .whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"))}\``)
339
+ .toString();
340
+ clone.whereExists(sqlPivot);
341
+ continue;
342
+ }
343
+ const sql = (_d = (_c = clone['$relation']) === null || _c === void 0 ? void 0 : _c._handleRelationsExists(r)) !== null && _d !== void 0 ? _d : '';
299
344
  clone.whereExists(sql);
300
345
  }
301
346
  }
302
347
  const sql = clone
303
348
  .bind(this.MODEL['$pool'].get())
304
- .select(this._getState('PRIMARY_KEY'))
305
- .whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${query.getTableName()}\`.\`${foreignKey}\``)
349
+ .selectRaw("1")
350
+ .whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${clone.getTableName()}\`.\`${foreignKey}\``)
306
351
  .toString();
307
352
  return sql;
308
353
  }
@@ -311,16 +356,16 @@ class RelationHandler {
311
356
  this._setState('RELATION', [...this._getState('RELATION'), relation]);
312
357
  this.MODEL['with'](nameRelation);
313
358
  const r = this._getState('RELATIONS').find((data) => data.name === nameRelation);
314
- this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
315
- this._assertError(!Object.values(this.$constants('RELATIONSHIP')).includes(r.relation), `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
359
+ this._assertError(relation == null, `The relation '${nameRelation}' is not registered in the model '${(_a = this.MODEL.constructor) === null || _a === void 0 ? void 0 : _a.name}'.`);
316
360
  return r;
317
361
  }
318
362
  _functionRelationName() {
319
363
  const functionName = [...this.$logger.get()][this.$logger.get().length - 2];
320
364
  return functionName.replace(/([A-Z])/g, (str) => `_${str.toLowerCase()}`);
321
365
  }
322
- _relationMapData(dataParents, dataChilds, relations) {
323
- const { name, as, relation, localKey, foreignKey } = this._valueInRelation(relations);
366
+ _relationMapData(dataParents, dataChilds, r) {
367
+ var _a;
368
+ const { name, as, relation, localKey, foreignKey } = this._valueInRelation(r);
324
369
  const keyRelation = as !== null && as !== void 0 ? as : name;
325
370
  for (const dataParent of dataParents) {
326
371
  const relationIsHasOneOrBelongsTo = [
@@ -329,11 +374,15 @@ class RelationHandler {
329
374
  ].some(r => r === relation);
330
375
  dataParent[keyRelation] = [];
331
376
  if (relationIsHasOneOrBelongsTo)
332
- dataParent[keyRelation] = null;
377
+ dataParent[keyRelation] = r.count ? 0 : null;
333
378
  if (!dataChilds.length)
334
379
  continue;
335
380
  for (const dataChild of dataChilds) {
336
381
  if (dataChild[foreignKey] === dataParent[localKey]) {
382
+ if (r.count) {
383
+ dataParent[keyRelation] = (_a = dataChild === null || dataChild === void 0 ? void 0 : dataChild.aggregate) !== null && _a !== void 0 ? _a : 0;
384
+ continue;
385
+ }
337
386
  const relationIsHasOneOrBelongsTo = [
338
387
  this.$constants('RELATIONSHIP').hasOne,
339
388
  this.$constants('RELATIONSHIP').belongsTo
@@ -351,14 +400,14 @@ class RelationHandler {
351
400
  return dataParents;
352
401
  }
353
402
  _belongsToMany(parents, relation) {
354
- var _a;
403
+ var _a, _b;
355
404
  return __awaiter(this, void 0, void 0, function* () {
356
405
  const { name, foreignKey, localKey, pivot, oldVersion, modelPivot } = this._valueInRelation(relation);
357
406
  const localKeyId = parents.map((parent) => {
358
407
  const data = parent[foreignKey];
359
408
  if (parent.hasOwnProperty(foreignKey))
360
409
  return data;
361
- this._assertError(data == null, `Unknown relationship without primary or foreign key in Relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
410
+ this._assertError(data == null, `This relationship lacks a primary or foreign key in the '${relation === null || relation === void 0 ? void 0 : relation.name}' relation. Please review the query to identify whether the key '${localKey}' or '${foreignKey}' is missing.`);
362
411
  }).filter((d) => d != null);
363
412
  const mainResultIds = Array.from(new Set(localKeyId));
364
413
  if (!mainResultIds.length && this._getState('RELATIONS_EXISTS'))
@@ -371,23 +420,49 @@ class RelationHandler {
371
420
  const pivotTable = String(((_a = relation.pivot) !== null && _a !== void 0 ? _a : pivot));
372
421
  const sqlPivotExists = new Model_1.Model()
373
422
  .copyModel(modelRelation)
374
- .select(this._getState('PRIMARY_KEY'))
423
+ .selectRaw("1")
375
424
  .whereReference(`\`${modelRelation.getTableName()}\`.\`${foreignKey}\``, `\`${pivotTable}\`.\`${localKey}\``)
376
425
  .toString();
377
426
  const queryPivot = modelPivot
378
427
  ? new modelPivot()
379
428
  : new Model_1.Model().table(pivotTable);
380
- const sqlPivot = queryPivot
429
+ if (relation.count) {
430
+ const pivotResults = yield queryPivot
431
+ .whereIn(localKeyPivotTable, mainResultIds)
432
+ .select(localKeyPivotTable)
433
+ .selectRaw(`${this.$constants('COUNT')}(${localKeyPivotTable}) ${this.$constants('AS')} \`aggregate\``)
434
+ .when(relation.exists, (query) => query.whereExists(sqlPivotExists))
435
+ .when(relation.trashed, (query) => query.onlyTrashed())
436
+ .when(relation.all, (query) => query.disableSoftDelete())
437
+ .groupBy(localKeyPivotTable)
438
+ .bind(this.MODEL['$pool'].get())
439
+ .debug(this._getState('DEBUG'))
440
+ .get();
441
+ for (const parent of parents) {
442
+ if (parent[name] == null)
443
+ parent[name] = 0;
444
+ for (const pivotResult of pivotResults) {
445
+ if (pivotResult[localKeyPivotTable] !== parent[foreignKey])
446
+ continue;
447
+ parent[name] = (_b = pivotResult.aggregate) !== null && _b !== void 0 ? _b : 0;
448
+ }
449
+ }
450
+ if (this._getState('HIDDEN').length)
451
+ this.MODEL['_hiddenColumnModel'](parents);
452
+ return parents;
453
+ }
454
+ const pivotResults = yield queryPivot
381
455
  .whereIn(localKeyPivotTable, mainResultIds)
382
456
  .when(relation.exists, (query) => query.whereExists(sqlPivotExists))
383
457
  .when(relation.trashed, (query) => query.onlyTrashed())
384
458
  .when(relation.all, (query) => query.disableSoftDelete())
385
- .toString();
386
- const pivotResults = yield this.MODEL['_queryStatement'](sqlPivot);
459
+ .bind(this.MODEL['$pool'].get())
460
+ .debug(this._getState('DEBUG'))
461
+ .get();
387
462
  const relationIds = Array.from(new Set(pivotResults
388
463
  .map((pivotResult) => pivotResult[relationForeignKey])
389
464
  .filter((d) => d != null)));
390
- const relationResults = yield this.MODEL['_queryStatement'](modelRelation
465
+ const relationResults = yield this.MODEL.rawQuery(modelRelation
391
466
  .whereIn(mainlocalKey, relationIds)
392
467
  .when(relation.trashed, (query) => query.disableSoftDelete())
393
468
  .toString());
@@ -435,8 +510,8 @@ class RelationHandler {
435
510
  }
436
511
  _valueInRelation(relationModel) {
437
512
  var _a, _b, _c;
438
- this._assertError((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Promise, 'Nested Relation isn\'t supported Promise method');
439
- this._assertError(!((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Model_1.Model), 'Callback function supported instance of Model only');
513
+ this._assertError((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Promise, 'The Promise method does not support nested relations.');
514
+ this._assertError(!((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Model_1.Model), 'The callback function only supports instances of the Model class.');
440
515
  const relation = relationModel.relation;
441
516
  const model = (_a = relationModel.model) === null || _a === void 0 ? void 0 : _a.name;
442
517
  const modelPivot = relationModel.modelPivot;
@@ -447,7 +522,7 @@ class RelationHandler {
447
522
  let pivot = null;
448
523
  const name = relationModel.name;
449
524
  const as = relationModel.as;
450
- this._assertError(!model || model == null, 'Not found model');
525
+ this._assertError(!model || model == null, 'Model not found.');
451
526
  let localKey = this._valuePattern(relationModel.localKey
452
527
  ? relationModel.localKey
453
528
  : this._getState('PRIMARY_KEY'));