tspace-mysql 1.4.6 → 1.4.7

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.
@@ -19,6 +19,14 @@ const Schema_1 = require("./Schema");
19
19
  const AbstractModel_1 = require("./Abstract/AbstractModel");
20
20
  const ProxyHandler_1 = require("./ProxyHandler");
21
21
  const StateHandler_1 = require("./StateHandler");
22
+ const RelationHandler_1 = require("./RelationHandler");
23
+ /**
24
+ *
25
+ * 'Model' class is a representation of a database table
26
+ * @example
27
+ * class User extends Model {}
28
+ * new User().findMany().then(users => console.log(users))
29
+ */
22
30
  class Model extends AbstractModel_1.AbstractModel {
23
31
  constructor() {
24
32
  super();
@@ -36,8 +44,7 @@ class Model extends AbstractModel_1.AbstractModel {
36
44
  return new Proxy(this, ProxyHandler_1.proxyHandler);
37
45
  }
38
46
  /**
39
- *
40
- * define for initialize of models
47
+ * The 'define' method is a special method that you can define within a model.
41
48
  * @example
42
49
  * class User extends Model {
43
50
  * define() {
@@ -51,8 +58,7 @@ class Model extends AbstractModel_1.AbstractModel {
51
58
  */
52
59
  define() { }
53
60
  /**
54
- *
55
- * boot for initialize of models like constructor()
61
+ * The 'boot' method is a special method that you can define within a model.
56
62
  * @example
57
63
  * class User extends Model {
58
64
  * boot() {
@@ -66,8 +72,46 @@ class Model extends AbstractModel_1.AbstractModel {
66
72
  */
67
73
  boot() { }
68
74
  /**
75
+ * The "useObserve" pattern refers to a way of handling model events using observer classes.
76
+ * Model events are triggered when certain actions occur on models,
77
+ * such as creating, updating, deleting, or saving a record.
78
+ *
79
+ * Observers are used to encapsulate the event-handling logic for these events,
80
+ * keeping the logic separate from the model itself and promoting cleaner, more maintainable code.
81
+ * @param {Function} observer
82
+ * @return this
83
+ * @example
69
84
  *
70
- * Assign auto create table when not exists table
85
+ * class UserObserve {
86
+ *
87
+ * public created(results : unknown) {
88
+ * console.log({ results , created : true })
89
+ * }
90
+ *
91
+ * public updated(results : unknown) {
92
+ * console.log({ results ,updated : true })
93
+ * }
94
+ *
95
+ * public deleted(results : unknown) {
96
+ * console.log({ results ,deleted : true })
97
+ * }
98
+ * }
99
+ *
100
+ * class User extends Model {
101
+ * constructor() {
102
+ * super()
103
+ * this.useObserver(UserObserve)
104
+ * }
105
+ * }
106
+ */
107
+ useObserver(observer) {
108
+ this._setState('OBSERVER', observer);
109
+ return this;
110
+ }
111
+ /**
112
+ * The "useSchema" method is used to define the schema.
113
+ *
114
+ * It's automatically create, called when not exists table or columns.
71
115
  * @param {object} schema using Blueprint for schema
72
116
  * @example
73
117
  * import { Blueprint } from 'tspace-mysql'
@@ -86,108 +130,112 @@ class Model extends AbstractModel_1.AbstractModel {
86
130
  * @return {this} this
87
131
  */
88
132
  useSchema(schema) {
89
- this.$state.set('SCHEMA_TABLE', schema);
133
+ this._setState('SCHEMA_TABLE', schema);
90
134
  return this;
91
135
  }
92
136
  /**
93
137
  *
94
- * Assign function callback in model like constructor()
138
+ * The "useRegistry" method is used to define Function to results.
139
+ *
140
+ * It's automatically given Function to results.
141
+ * @return {this} this
95
142
  * @example
96
143
  * class User extends Model {
97
144
  * constructor() {
98
145
  * this.useRegistry()
99
146
  * }
100
147
  * }
101
- * @return {this} this
148
+
102
149
  */
103
150
  useRegistry() {
104
- this.$state.set('REGISTRY', Object.assign(Object.assign({}, this.$state.get('REGISTRY')), { '$attach': this._attach, '$detach': this._detach }));
151
+ this._setState('REGISTRY', Object.assign(Object.assign({}, this._getState('REGISTRY')), { '$attach': this._attach, '$detach': this._detach }));
105
152
  return this;
106
153
  }
107
154
  /**
108
- *
109
- * Assign model calling all relationships in model
155
+ * The "useLoadRelationsInRegistry" method is used automatically called relations in your registry Model.
156
+ * @return {this} this
110
157
  * @example
111
158
  * class User extends Model {
112
159
  * constructor() {
113
160
  * this.useLoadRelationInRegistry()
114
161
  * }
115
162
  * }
116
- * @return {this} this
117
163
  */
118
164
  useLoadRelationsInRegistry() {
119
- const relations = this.$state.get('RELATION').map((r) => String(r.name));
165
+ const relations = this._getState('RELATION').map((r) => String(r.name));
120
166
  if (relations.length)
121
- this.with(...Array.from(new Set(relations)));
167
+ this.relations(...Array.from(new Set(relations)));
122
168
  return this;
123
169
  }
124
170
  /**
171
+ * The "useBuiltInRelationFunctions" method is used to define the function.
125
172
  *
126
- * Assign model built-in relation functions to a results
173
+ * It's automatically given built-in relation functions to a results.
174
+ * @return {this} this
127
175
  * @example
128
176
  * class User extends Model {
129
177
  * constructor() {
130
178
  * this.useBuiltInRelationsFunction()
131
179
  * }
132
180
  * }
133
- * @return {this} this
134
181
  */
135
182
  useBuiltInRelationFunctions() {
136
- this.$state.set('FUNCTION_RELATION', true);
183
+ this._setState('FUNCTION_RELATION', true);
137
184
  return this;
138
185
  }
139
186
  /**
187
+ * The "usePrimaryKey" method is add primary keys for database tables.
140
188
  *
141
- * Assign primary column in model
142
189
  * @param {string} primary
190
+ * @return {this} this
143
191
  * @example
144
192
  * class User extends Model {
145
193
  * constructor() {
146
194
  * this.usePrimaryKey()
147
195
  * }
148
196
  * }
149
- * @return {this} this
150
197
  */
151
198
  usePrimaryKey(primary) {
152
- this.$state.set('PRIMARY_KEY', primary);
199
+ this._setState('PRIMARY_KEY', primary);
153
200
  return this;
154
201
  }
155
202
  /**
156
- * Assign generate uuid when creating in model
203
+ * The "useUUID" method is a concept of using UUIDs (Universally Unique Identifiers) as column 'uuid' in table.
204
+ *
205
+ * It's automatically genarate when created a result.
157
206
  * @param {string?} column [column=uuid] make new name column for custom column replace uuid with this
207
+ * @return {this} this
158
208
  * @example
159
209
  * class User extends Model {
160
210
  * constructor() {
161
211
  * this.useUUID()
162
212
  * }
163
213
  * }
164
- * @return {this} this
165
214
  */
166
215
  useUUID(column) {
167
- this.$state.set('UUID', true);
216
+ this._setState('UUID', true);
168
217
  if (column)
169
- this.$state.set('UUID_FORMAT', column);
218
+ this._setState('UUID_FORMAT', column);
170
219
  return this;
171
220
  }
172
221
  /**
173
- * Assign in model console.log raw sql when fetching query statement
222
+ * The "useDebug" method is viewer raw-sql logs when excute the results.
174
223
  * @return {this} this
175
224
  */
176
225
  useDebug() {
177
- this.$state.set('DEBUG', true);
226
+ this._setState('DEBUG', true);
178
227
  return this;
179
228
  }
180
229
  /**
181
- *
182
- * Assign in model use pattern [snake_case , camelCase]
230
+ * The "usePattern" method is used to assign pattern [snake_case , camelCase].
183
231
  * @param {string} pattern
232
+ * @return {this} this
184
233
  * @example
185
234
  * class User extends Model {
186
235
  * constructor() {
187
236
  * this.usePattern('camelCase')
188
237
  * }
189
238
  * }
190
- * @return {this} this
191
239
  */
192
240
  usePattern(pattern) {
193
241
  const allowPattern = [
@@ -195,34 +243,49 @@ class Model extends AbstractModel_1.AbstractModel {
195
243
  this.$constants('PATTERN').camelCase
196
244
  ];
197
245
  this._assertError(!allowPattern.includes(pattern), `tspace-mysql support only pattern ["${this.$constants('PATTERN').snake_case}","${this.$constants('PATTERN').camelCase}"]`);
198
- this.$state.set('PATTERN', pattern);
246
+ this._setState('PATTERN', pattern);
247
+ this._makeTableName();
248
+ return this;
249
+ }
250
+ useCamelCase() {
251
+ this._setState('PATTERN', this.$constants('PATTERN').camelCase);
252
+ this._makeTableName();
253
+ return this;
254
+ }
255
+ useSnakeCase() {
256
+ this._setState('PATTERN', this.$constants('PATTERN').snake_case);
257
+ this._makeTableName();
199
258
  return this;
200
259
  }
201
260
  /**
261
+ * The "useSoftDelete" refer to a feature that allows you to "soft delete" records from a database table instead of permanently deleting them.
202
262
  *
203
- * Assign in model show data not be deleted
204
- * Relations has reference this method
263
+ * Soft deleting means that the records are not physically removed from the database but are instead marked as deleted by setting a timestamp in a dedicated column.
264
+ *
265
+ * This feature is particularly useful when you want to retain a record of deleted data and potentially recover it later,
266
+ * or when you want to maintain referential integrity in your database
205
267
  * @param {string?} column default deleted_at
268
+ * @return {this} this
206
269
  * @example
207
270
  * class User extends Model {
208
271
  * constructor() {
209
272
  * this.useSoftDelete('deletedAt')
210
273
  * }
211
274
  * }
212
- * @return {this} this
213
275
  */
214
276
  useSoftDelete(column) {
215
- this.$state.set('SOFT_DELETE', true);
277
+ this._setState('SOFT_DELETE', true);
216
278
  if (column)
217
- this.$state.set('SOFT_DELETE_FORMAT', column);
279
+ this._setState('SOFT_DELETE_FORMAT', column);
218
280
  return this;
219
281
  }
220
282
  /**
221
- *
222
- * Assign timestamp when insert || updated created_at and update_at in table
283
+ * The "useTimestamp" method is used to assign a timestamp when creating a new record,
284
+ * or updating a record.
223
285
  * @param {object} timestampFormat
224
286
  * @property {string} timestampFormat.createdAt - change new name column replace by default [created at]
225
287
  * @property {string} timestampFormat.updatedAt - change new name column replace by default updated at
288
+ * @return {this} this
226
289
  * @example
227
290
  * class User extends Model {
228
291
  * constructor() {
@@ -232,12 +295,11 @@ class Model extends AbstractModel_1.AbstractModel {
232
295
  * })
233
296
  * }
234
297
  * }
235
- * @return {this} this
236
298
  */
237
299
  useTimestamp(timestampFormat) {
238
- this.$state.set('TIMESTAMP', true);
300
+ this._setState('TIMESTAMP', true);
239
301
  if (timestampFormat) {
240
- this.$state.set('TIMESTAMP_FORMAT', {
302
+ this._setState('TIMESTAMP_FORMAT', {
241
303
  CREATED_AT: timestampFormat.createdAt,
242
304
  UPDATED_AT: timestampFormat.updatedAt
243
305
  });
@@ -245,126 +307,160 @@ class Model extends AbstractModel_1.AbstractModel {
245
307
  return this;
246
308
  }
247
309
  /**
248
- *
249
- * Assign table name in model
310
+ * This "useTable" method is used to assign the name of the table.
250
311
  * @param {string} table table name in database
312
+ * @return {this} this
251
313
  * @example
252
314
  * class User extends Model {
253
315
  * constructor() {
254
316
  * this.useTable('setTableNameIsUser') // => 'setTableNameIsUser'
255
317
  * }
256
318
  * }
257
- * @return {this} this
258
319
  */
259
320
  useTable(table) {
260
- this.$state.set('TABLE_NAME', `\`${table}\``);
321
+ this._setState('TABLE_NAME', `\`${table}\``);
261
322
  return this;
262
323
  }
263
324
  /**
264
- *
265
- * Assign table name in model with signgular pattern
325
+ * This "useTableSingular" method is used to assign the name of the table with signgular pattern.
326
+ * @return {this} this
266
327
  * @example
267
328
  * class User extends Model {
268
329
  * constructor() {
269
330
  * this.useTableSingular() // => 'user'
270
331
  * }
271
332
  * }
272
- * @return {this} this
273
333
  */
274
334
  useTableSingular() {
275
335
  var _a;
276
336
  const table = this._classToTableName((_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name, { singular: true });
277
- this.$state.set('TABLE_NAME', `\`${pluralize_1.default.singular(table)}\``);
337
+ this._setState('TABLE_NAME', `\`${this._valuePattern(table)}\``);
278
338
  return this;
279
339
  }
280
340
  /**
281
- *
282
- * Assign table name in model with pluarl pattern
341
+ * This "useTablePlural " method is used to assign the name of the table with pluarl pattern
342
+ * @return {this} this
283
343
  * @example
284
344
  * class User extends Model {
285
345
  * constructor() {
286
346
  * this.useTablePlural() // => 'users'
287
347
  * }
288
348
  * }
289
- * @return {this} this
290
349
  */
291
350
  useTablePlural() {
292
351
  var _a;
293
352
  const table = this._classToTableName((_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name);
294
- this.$state.set('TABLE_NAME', `\`${pluralize_1.default.plural(table)}\``);
353
+ this._setState('TABLE_NAME', `\`${pluralize_1.default.plural(table)}\``);
295
354
  return this;
296
355
  }
297
356
  /**
298
- *
299
- * Assign schema column in model for validation data types
300
- * @param {Object<NumberConstructor | StringConstructor | DateConstructor>} schema types (String Number and Date)
357
+ * This 'useValidationSchema' method is used to validate the schema when have some action create or update.
358
+ * @param {Object<ValidateSchema>} schema types (String Number and Date)
359
+ * @return {this} this
301
360
  * @example
302
361
  * class User extends Model {
303
362
  * constructor() {
304
- * this.useValidationSchema()
305
- * }
363
+ * this.useValidationSchema({
364
+ * id : Number,
365
+ * uuid : Number,
366
+ * name : {
367
+ * type : String,
368
+ * require : true
369
+ * // json : true,
370
+ * // enum : ["1","2","3"]
371
+ * },
372
+ * email : {
373
+ * type : String,
374
+ * require : true,
375
+ * length : 199,
376
+ * match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
377
+ * unique : true,
378
+ * fn : async (email : string) => /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
379
+ * },
380
+ * createdAt : Date,
381
+ * updatedAt : Date,
382
+ * deletedAt : Date
383
+ * })
384
+ * }
306
385
  * }
307
- * @return {this} this
308
386
  */
309
387
  useValidationSchema(schema) {
310
- this.$state.set('VALIDATE_SCHEMA', true);
311
- this.$state.set('VALIDATE_SCHEMA_DEFINED', schema);
388
+ this._setState('VALIDATE_SCHEMA', true);
389
+ this._setState('VALIDATE_SCHEMA_DEFINED', schema);
312
390
  return this;
313
391
  }
314
392
  /**
315
- *
316
- * Assign schema column in model for validation data types
317
- * @param {Object<NumberConstructor | StringConstructor | DateConstructor>} schema types (String Number and Date)
318
- * @example
319
- * class User extends Model {
320
- * constructor() {
321
- * this.useValidationSchema()
322
- * }
323
- * }
324
- * @return {this} this
325
- */
393
+ * This 'useValidateSchema' method is used to validate the schema when have some action create or update.
394
+ * @param {Object<ValidateSchema>} schema types (String Number and Date)
395
+ * @return {this} this
396
+ * @example
397
+ * class User extends Model {
398
+ * constructor() {
399
+ * this.useValidationSchema({
400
+ * id : Number,
401
+ * uuid : string,
402
+ * name : {
403
+ * type : String,
404
+ * require : true
405
+ * },
406
+ * email : {
407
+ * type : String,
408
+ * require : true,
409
+ * length : 199,
410
+ * // json : true,
411
+ * // enum : ["1","2","3"]
412
+ * match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
413
+ * unique : true,
414
+ * fn : async (email : string) => /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
415
+ * },
416
+ * createdAt : Date,
417
+ * updatedAt : Date,
418
+ * deletedAt : Date
419
+ * })
420
+ * }
421
+ * }
422
+ */
326
423
  useValidateSchema(schema) {
327
- this.$state.set('VALIDATE_SCHEMA', true);
328
- this.$state.set('VALIDATE_SCHEMA_DEFINED', schema);
329
- return this;
424
+ return this.useValidationSchema(schema);
330
425
  }
331
426
  /**
332
- * Assign hook function when execute returned results to callback function
333
- * @param {Array<Function>} arrayFunctions functions for callback result
427
+ * The "useHooks" method is used to assign hook function when execute returned results to callback function.
428
+ * @param {Function[]} arrayFunctions functions for callback result
429
+ * @return {this} this
334
430
  * @example
335
431
  * class User extends Model {
336
432
  * constructor() {
337
433
  * this.useHook([(results) => console.log(results)])
338
434
  * }
339
435
  * }
340
- * @return {this}
341
436
  */
342
437
  useHooks(arrayFunctions) {
343
438
  for (const func of arrayFunctions) {
344
439
  if (typeof func !== "function")
345
440
  throw new Error(`this '${func}' is not a function`);
346
- this.$state.set('HOOKS', [...this.$state.get('HOOKS'), func]);
441
+ this._setState('HOOKS', [...this._getState('HOOKS'), func]);
347
442
  }
348
443
  return this;
349
444
  }
350
445
  /**
351
446
  * exceptColumns for method except
447
+ * @override
352
448
  * @return {promise<string>} string
353
449
  */
354
- exceptColumns() {
450
+ _exceptColumns() {
355
451
  return __awaiter(this, void 0, void 0, function* () {
356
- const excepts = this.$state.get('EXCEPTS');
452
+ const excepts = this._getState('EXCEPTS');
357
453
  const hasDot = excepts.some((except) => /\./.test(except));
358
454
  const names = excepts.map((except) => {
359
455
  if (/\./.test(except))
360
456
  return except.split('.')[0];
361
457
  return null;
362
458
  }).filter((d) => d != null);
363
- const tableNames = names.length ? [...new Set(names)] : [this.$state.get('TABLE_NAME')];
459
+ const tableNames = names.length ? [...new Set(names)] : [this._getState('TABLE_NAME')];
364
460
  const removeExcepts = [];
365
461
  for (const tableName of tableNames) {
366
- if (this.$state.get('SCHEMA_TABLE') && (tableName === this.$state.get('TABLE_NAME').replace(/`/g, ''))) {
367
- const columns = Object.keys(this.$state.get('SCHEMA_TABLE'));
462
+ if (this._getState('SCHEMA_TABLE') && (tableName === this._getState('TABLE_NAME').replace(/`/g, ''))) {
463
+ const columns = Object.keys(this._getState('SCHEMA_TABLE'));
368
464
  const removeExcept = columns.filter((column) => {
369
465
  return excepts.every((except) => {
370
466
  if (/\./.test(except)) {
@@ -383,7 +479,7 @@ class Model extends AbstractModel_1.AbstractModel {
383
479
  `${this.$constants('FROM')}`,
384
480
  `${tableName}`
385
481
  ].join(' ');
386
- const rawColumns = yield this.queryStatement(sql);
482
+ const rawColumns = yield this._queryStatement(sql);
387
483
  const columns = rawColumns.map((column) => column.Field);
388
484
  const removeExcept = columns.filter((column) => {
389
485
  return excepts.every((except) => {
@@ -407,8 +503,8 @@ class Model extends AbstractModel_1.AbstractModel {
407
503
  */
408
504
  buildMethodRelation(name, callback) {
409
505
  var _a, _b;
410
- this.with(name);
411
- const relation = this.$state.get('RELATIONS').find((data) => data.name === name);
506
+ this.relations(name);
507
+ const relation = this._getState('RELATIONS').find((data) => data.name === name);
412
508
  this._assertError(relation == null, `This Relation "${name}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
413
509
  const relationHasExists = (_b = Object.values(this.$constants('RELATIONSHIP'))) === null || _b === void 0 ? void 0 : _b.includes(relation.relation);
414
510
  this._assertError(!relationHasExists, `Unknown Relationship in [${this.$constants('RELATIONSHIP')}] !`);
@@ -456,6 +552,14 @@ class Model extends AbstractModel_1.AbstractModel {
456
552
  newInstance.$state.set('LIMIT', '');
457
553
  if ((options === null || options === void 0 ? void 0 : options.offset) == null)
458
554
  newInstance.$state.set('OFFSET', '');
555
+ if ((options === null || options === void 0 ? void 0 : options.groupBy) == null)
556
+ newInstance.$state.set('GROUP_BY', '');
557
+ if ((options === null || options === void 0 ? void 0 : options.orderBy) == null)
558
+ newInstance.$state.set('ORDER_BY', '');
559
+ if ((options === null || options === void 0 ? void 0 : options.select) == null)
560
+ newInstance.$state.set('SELECT', []);
561
+ if ((options === null || options === void 0 ? void 0 : options.join) == null)
562
+ newInstance.$state.set('JOIN', '');
459
563
  return newInstance;
460
564
  }
461
565
  /**
@@ -465,18 +569,23 @@ class Model extends AbstractModel_1.AbstractModel {
465
569
  * @param {string} sql
466
570
  * @return {this} this
467
571
  */
468
- queryStatement(sql) {
572
+ _queryStatement(sql) {
573
+ var _a;
469
574
  return __awaiter(this, void 0, void 0, function* () {
470
575
  try {
471
- if (this.$state.get('DEBUG'))
576
+ if (this._getState('DEBUG')) {
472
577
  this.$utils.consoleDebug(sql);
473
- this.$state.set('RETRY_QUERIES', Number(this.$state.get('RETRY_QUERIES')) + 1);
474
- const result = yield this.$pool.query(sql);
475
- return result;
578
+ const result = yield this.$pool.query(sql);
579
+ return result;
580
+ }
581
+ return yield this.$pool.query(sql);
476
582
  }
477
583
  catch (error) {
478
- yield this._checkSchemaOrNextError(error);
479
- return yield this.queryStatement(sql);
584
+ if ((_a = this._getState('JOIN')) === null || _a === void 0 ? void 0 : _a.length)
585
+ throw error;
586
+ yield this._checkSchemaOrNextError(error, Number(this._getState('RETRY')));
587
+ this._setState('RETRY', Number(this._getState('RETRY')) + 1);
588
+ return yield this._queryStatement(sql);
480
589
  }
481
590
  });
482
591
  }
@@ -485,16 +594,23 @@ class Model extends AbstractModel_1.AbstractModel {
485
594
  * execute the query using raw sql syntax actions for insert update and delete
486
595
  * @override method
487
596
  * @param {Object} actions
488
- * @property {Function} actions.sql
597
+ * @property {Function} actions.sqlresult
489
598
  * @property {Function} actions.returnId
490
599
  * @return {this} this
491
600
  */
492
- actionStatement({ sql, returnId = false }) {
601
+ _actionStatement({ sql, returnId = false }) {
602
+ var _a;
493
603
  return __awaiter(this, void 0, void 0, function* () {
494
604
  try {
495
- if (this.$state.get('DEBUG'))
605
+ if (this._getState('DEBUG')) {
496
606
  this.$utils.consoleDebug(sql);
497
- this.$state.set('RETRY_QUERIES', Number(this.$state.get('RETRY_QUERIES')) + 1);
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
+ }
498
614
  if (returnId) {
499
615
  const result = yield this.$pool.query(sql);
500
616
  return [result.affectedRows, result.insertId];
@@ -502,9 +618,12 @@ class Model extends AbstractModel_1.AbstractModel {
502
618
  const { affectedRows: result } = yield this.$pool.query(sql);
503
619
  return result;
504
620
  }
505
- catch (e) {
506
- yield this._checkSchemaOrNextError(e);
507
- return yield this.actionStatement({
621
+ catch (error) {
622
+ if ((_a = this._getState('JOIN')) === null || _a === void 0 ? void 0 : _a.length)
623
+ throw error;
624
+ yield this._checkSchemaOrNextError(error, Number(this._getState('RETRY')));
625
+ this._setState('RETRY', Number(this._getState('RETRY')) + 1);
626
+ return yield this._actionStatement({
508
627
  sql,
509
628
  returnId
510
629
  });
@@ -516,8 +635,8 @@ class Model extends AbstractModel_1.AbstractModel {
516
635
  * @param {string} table table name
517
636
  * @return {this} this
518
637
  */
519
- tableName(table) {
520
- this.$state.set('TABLE_NAME', `\`${table}\``);
638
+ table(table) {
639
+ this._setState('TABLE_NAME', `\`${table}\``);
521
640
  return this;
522
641
  }
523
642
  /**
@@ -526,7 +645,7 @@ class Model extends AbstractModel_1.AbstractModel {
526
645
  * @return {this} this
527
646
  */
528
647
  disableSoftDelete(condition = false) {
529
- this.$state.set('SOFT_DELETE', condition);
648
+ this._setState('SOFT_DELETE', condition);
530
649
  return this;
531
650
  }
532
651
  /**
@@ -535,7 +654,7 @@ class Model extends AbstractModel_1.AbstractModel {
535
654
  * @return {this} this
536
655
  */
537
656
  ignoreSoftDelete(condition = false) {
538
- this.$state.set('SOFT_DELETE', condition);
657
+ this._setState('SOFT_DELETE', condition);
539
658
  return this;
540
659
  }
541
660
  /**
@@ -544,13 +663,15 @@ class Model extends AbstractModel_1.AbstractModel {
544
663
  * @return {this} this
545
664
  */
546
665
  registry(func) {
547
- this.$state.set('REGISTRY', Object.assign(Object.assign({}, func), { attach: this._attach, detach: this._detach }));
666
+ this._setState('REGISTRY', Object.assign(Object.assign({}, func), { attach: this._attach, detach: this._detach }));
548
667
  return this;
549
668
  }
550
669
  /**
670
+ * The 'with' method is used to eager load related (relations) data when retrieving records from a database.
551
671
  *
552
- * Use relations in registry of model return result of relation query
672
+ * Eager loading allows you to retrieve a primary model and its related models in a more efficient
553
673
  * @param {...string} nameRelations ...name registry in models using (hasOne , hasMany , belongsTo , belongsToMany)
674
+ * @return {this} this
554
675
  * @example
555
676
  * import { Model } from 'tspace-mysql'
556
677
  * class User extends Model {
@@ -567,70 +688,48 @@ class Model extends AbstractModel_1.AbstractModel {
567
688
  * this.belongsTo({ name : 'user' , model : User })
568
689
  * }
569
690
  * }
570
- * // use with for results of relationship
571
- * await new User().with('posts').findMany()
572
- * @return {this} this
691
+ * // use 'with' for results of relationship
692
+ * await new User().relations('posts').findMany()
693
+ *
573
694
  */
574
695
  with(...nameRelations) {
575
- const relations = this._handleRelations(nameRelations);
576
- const setRelations = this.$state.get('RELATIONS').length
577
- ? [...relations.map((w) => {
578
- const exists = this.$state.get('RELATIONS').find((r) => r.name === w.name);
579
- if (exists)
580
- return null;
581
- return w;
582
- }).filter((d) => d != null),
583
- ...this.$state.get('RELATIONS')]
584
- : relations;
585
- this.$state.set('RELATIONS', setRelations);
696
+ var _a;
697
+ this._setState('RELATIONS', (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.apply(nameRelations, 'default'));
586
698
  return this;
587
699
  }
588
700
  /**
701
+ * The 'withAll' method is used to eager load related (relations) data when retrieving records from a database.
589
702
  *
590
- * Use relations in registry of model return ignore soft delete
703
+ * Eager loading allows you to retrieve a primary model and its related models in a more efficient
704
+ * It's method ignore soft delete
591
705
  * @param {...string} nameRelations if data exists return blank
592
706
  * @return {this} this
593
707
  */
594
708
  withAll(...nameRelations) {
595
- const relations = this._handleRelations(nameRelations);
596
- relations.forEach(relation => relation.all = true);
597
- const setRelations = this.$state.get('RELATIONS').length
598
- ? [...relations.map((w) => {
599
- const exists = this.$state.get('RELATIONS').find((r) => r.name === w.name);
600
- if (exists)
601
- return null;
602
- return w;
603
- }).filter((d) => d != null),
604
- ...this.$state.get('RELATIONS')]
605
- : relations;
606
- this.$state.set('RELATIONS', setRelations);
709
+ var _a;
710
+ this._setState('RELATIONS', (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.apply(nameRelations, 'all'));
607
711
  return this;
608
712
  }
609
713
  /**
714
+ * The 'withTrashed' method is used to eager load related (relations) data when retrieving records from a database.
610
715
  *
611
- * Use relations in registry of model return only in trash (soft delete)
716
+ * Eager loading allows you to retrieve a primary model and its related models in a more efficient
717
+ * It's method return results only in trash (soft deleted)
612
718
  * @param {...string} nameRelations if data exists return blank
613
719
  * @return {this} this
614
720
  */
615
721
  withTrashed(...nameRelations) {
616
- const relations = this._handleRelations(nameRelations);
617
- relations.forEach(relation => relation.trashed = true);
618
- const setRelations = this.$state.get('RELATIONS').length
619
- ? [...relations.map((w) => {
620
- const exists = this.$state.get('RELATIONS').find((r) => r.name === w.name);
621
- if (exists)
622
- return null;
623
- return w;
624
- }).filter((d) => d != null),
625
- ...this.$state.get('RELATIONS')]
626
- : relations;
627
- this.$state.set('RELATIONS', setRelations);
722
+ var _a;
723
+ this._setState('RELATIONS', (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.apply(nameRelations, 'trashed'));
628
724
  return this;
629
725
  }
630
726
  /**
727
+ * The 'withExists' method is used to eager load related (relations) data when retrieving records from a database.
631
728
  *
632
- * Use relations in registry of model return only exists result of relation query
633
- * @param {...string} nameRelations if data exists return blank
729
+ * Eager loading allows you to retrieve a primary model and its related models in a more efficient
730
+ * It's method return only exists result of relation query
731
+ * @param {...string} nameRelations
732
+ * @return {this} this
634
733
  * @example
635
734
  * import { Model } from 'tspace-mysql'
636
735
  * class User extends Model {
@@ -648,23 +747,12 @@ class Model extends AbstractModel_1.AbstractModel {
648
747
  * }
649
748
  * }
650
749
  * // use with for results of relationship if relations is exists
651
- * await new User().withExists('posts').findMany()
652
- * @return {this} this
750
+ * await new User().relationsExists('posts').findMany()
653
751
  */
654
752
  withExists(...nameRelations) {
655
- this.$state.set('RELATIONS_EXISTS', true);
656
- const relations = (this._handleRelations(nameRelations));
657
- relations.forEach(relation => relation.exists = true);
658
- const setRelations = this.$state.get('RELATIONS').length
659
- ? [...relations.map((w) => {
660
- const exists = this.$state.get('RELATIONS').find((r) => r.name === w.name);
661
- if (exists)
662
- return null;
663
- return w;
664
- }).filter((d) => d != null),
665
- ...this.$state.get('RELATIONS')]
666
- : relations;
667
- this.$state.set('RELATIONS', setRelations);
753
+ var _a;
754
+ this._setState('RELATIONS_EXISTS', true);
755
+ this._setState('RELATIONS', (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.apply(nameRelations, 'exists'));
668
756
  return this;
669
757
  }
670
758
  /**
@@ -692,11 +780,13 @@ class Model extends AbstractModel_1.AbstractModel {
692
780
  * @return {this} this
693
781
  */
694
782
  has(...nameRelations) {
695
- return this.withExists(...nameRelations);
783
+ return this.relationsExists(...nameRelations);
696
784
  }
697
785
  /**
698
786
  *
699
- * Use relation '${name}' registry of model return callback this query model
787
+ * The 'withQuery' method is particularly useful when you want to filter or add conditions records based on related data.
788
+ *
789
+ * Use relation '${name}' registry models then return callback queries
700
790
  * @param {string} nameRelation name relation in registry in your model
701
791
  * @param {function} callback query callback
702
792
  * @example
@@ -724,15 +814,15 @@ class Model extends AbstractModel_1.AbstractModel {
724
814
  * }
725
815
  * }
726
816
  *
727
- * await new User().with('posts')
728
- * .withQuery('posts', (query : Post) => {
729
- * return query.with('comments','user')
730
- * .withQuery('comments', (query : Comment) => {
731
- * return query.with('user','post')
817
+ * await new User().relations('posts')
818
+ * .relationsQuery('posts', (query : Post) => {
819
+ * return query.relations('comments','user')
820
+ * .relationsQuery('comments', (query : Comment) => {
821
+ * return query.relations('user','post')
732
822
  * })
733
- * .withQuery('user', (query : User) => {
734
- * return query.with('posts').withQuery('posts',(query : Post)=> {
735
- * return query.with('comments','user')
823
+ * .relationsQuery('user', (query : User) => {
824
+ * return query.relations('posts').relationsQuery('posts',(query : Post)=> {
825
+ * return query.relations('comments','user')
736
826
  * // relation n, n, ...n
737
827
  * })
738
828
  * })
@@ -741,12 +831,8 @@ class Model extends AbstractModel_1.AbstractModel {
741
831
  * @return {this} this
742
832
  */
743
833
  withQuery(nameRelation, callback) {
744
- var _a, _b;
745
- const relation = this.$state.get('RELATIONS').find((data) => data.name === nameRelation);
746
- this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
747
- const relationHasExists = (_b = Object.values(this.$constants('RELATIONSHIP'))) === null || _b === void 0 ? void 0 : _b.includes(relation.relation);
748
- this._assertError(!relationHasExists, `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
749
- relation.query = callback(new relation.model());
834
+ var _a;
835
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.callback(nameRelation, callback);
750
836
  return this;
751
837
  }
752
838
  /**
@@ -774,7 +860,7 @@ class Model extends AbstractModel_1.AbstractModel {
774
860
  * @return {this} this
775
861
  */
776
862
  relations(...nameRelations) {
777
- return this.with(...nameRelations);
863
+ return this.relations(...nameRelations);
778
864
  }
779
865
  /**
780
866
  *
@@ -801,7 +887,7 @@ class Model extends AbstractModel_1.AbstractModel {
801
887
  * @return {this} this
802
888
  */
803
889
  relationsExists(...nameRelations) {
804
- return this.withExists(...nameRelations);
890
+ return this.relationsExists(...nameRelations);
805
891
  }
806
892
  /**
807
893
  *
@@ -833,15 +919,15 @@ class Model extends AbstractModel_1.AbstractModel {
833
919
  * }
834
920
  * }
835
921
  *
836
- * await new User().with('posts')
922
+ * await new User().relations('posts')
837
923
  * .relationQuery('posts', (query : Post) => {
838
- * return query.with('comments','user')
924
+ * return query.relations('comments','user')
839
925
  * .relationQuery('comments', (query : Comment) => {
840
- * return query.with('user','post')
926
+ * return query.relations('user','post')
841
927
  * })
842
928
  * .relationQuery('user', (query : User) => {
843
- * return query.with('posts').relationQuery('posts',(query : Post)=> {
844
- * return query.with('comments','user')
929
+ * return query.relations('posts').relationQuery('posts',(query : Post)=> {
930
+ * return query.relations('comments','user')
845
931
  * // relation n, n, ...n
846
932
  * })
847
933
  * })
@@ -859,7 +945,7 @@ class Model extends AbstractModel_1.AbstractModel {
859
945
  * @return {this} this
860
946
  */
861
947
  relationsAll(...nameRelations) {
862
- return this.withAll(...nameRelations);
948
+ return this.relationsAll(...nameRelations);
863
949
  }
864
950
  /**
865
951
  *
@@ -868,10 +954,15 @@ class Model extends AbstractModel_1.AbstractModel {
868
954
  * @return {this} this
869
955
  */
870
956
  relationsTrashed(...nameRelations) {
871
- return this.withTrashed(...nameRelations);
957
+ return this.relationsTrashed(...nameRelations);
872
958
  }
873
959
  /**
874
- * Assign the relation in model Objects
960
+ * The 'hasOne' relationship defines a one-to-one relationship between two database tables.
961
+ *
962
+ * It indicates that a particular record in the primary table is associated with one and only one record in the related table.
963
+ *
964
+ * This is typically used when you have a foreign key in the related table that references the primary table.
965
+ *
875
966
  * @param {object} relations registry relation in your model
876
967
  * @property {string} relation.name
877
968
  * @property {string} relation.as
@@ -882,21 +973,24 @@ class Model extends AbstractModel_1.AbstractModel {
882
973
  * @return {this} this
883
974
  */
884
975
  hasOne({ name, as, model, localKey, foreignKey, freezeTable }) {
885
- const relation = {
976
+ var _a;
977
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.hasOne({
886
978
  name,
887
- model,
888
979
  as,
889
- relation: this.$constants('RELATIONSHIP').hasOne,
980
+ model,
890
981
  localKey,
891
982
  foreignKey,
892
- freezeTable,
893
- query: null
894
- };
895
- this.$state.set('RELATION', [...this.$state.get('RELATION'), relation]);
983
+ freezeTable
984
+ });
896
985
  return this;
897
986
  }
898
987
  /**
899
- * Assign the relation in model Objects
988
+ * The 'hasMany' relationship defines a one-to-many relationship between two database tables.
989
+ *
990
+ * It indicates that a record in the primary table can be associated with multiple records in the related table.
991
+ *
992
+ * This is typically used when you have a foreign key in the related table that references the primary table.
993
+ *
900
994
  * @param {object} relations registry relation in your model
901
995
  * @property {string} relation.name
902
996
  * @property {string} relation.as
@@ -907,21 +1001,24 @@ class Model extends AbstractModel_1.AbstractModel {
907
1001
  * @return {this} this
908
1002
  */
909
1003
  hasMany({ name, as, model, localKey, foreignKey, freezeTable }) {
910
- const relation = {
1004
+ var _a;
1005
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.hasMany({
911
1006
  name,
912
- model,
913
1007
  as,
914
- relation: this.$constants('RELATIONSHIP').hasMany,
1008
+ model,
915
1009
  localKey,
916
1010
  foreignKey,
917
- freezeTable,
918
- query: null
919
- };
920
- this.$state.set('RELATION', [...this.$state.get('RELATION'), relation]);
1011
+ freezeTable
1012
+ });
921
1013
  return this;
922
1014
  }
923
1015
  /**
924
- * Assign the relation in model Objects
1016
+ * The 'belongsTo' relationship defines a one-to-one or many-to-one relationship between two database tables.
1017
+ *
1018
+ * It indicates that a record in the related table belongs to a single record in the primary table.
1019
+ *
1020
+ * This is typically used when you have a foreign key in the primary table that references the related table.
1021
+ *
925
1022
  * @param {object} relations registry relation in your model
926
1023
  * @property {string} relation.name
927
1024
  * @property {string} relation.as
@@ -932,21 +1029,24 @@ class Model extends AbstractModel_1.AbstractModel {
932
1029
  * @return {this} this
933
1030
  */
934
1031
  belongsTo({ name, as, model, localKey, foreignKey, freezeTable }) {
935
- const relation = {
1032
+ var _a;
1033
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.belongsTo({
936
1034
  name,
937
1035
  as,
938
1036
  model,
939
- relation: this.$constants('RELATIONSHIP').belongsTo,
940
1037
  localKey,
941
1038
  foreignKey,
942
- freezeTable,
943
- query: null
944
- };
945
- this.$state.set('RELATION', [...this.$state.get('RELATION'), relation]);
1039
+ freezeTable
1040
+ });
946
1041
  return this;
947
1042
  }
948
1043
  /**
949
- * Assign the relation in model Objects
1044
+ * The 'belongsToMany' relationship defines a many-to-many relationship between two database tables.
1045
+ *
1046
+ * It indicates that records in both the primary table and the related table can be associated
1047
+ * with multiple records in each other's table through an intermediate table.
1048
+ *
1049
+ * This is commonly used when you have a many-to-many relationship between entities, such as users and roles or products and categories.
950
1050
  * @param {object} relations registry relation in your model
951
1051
  * @property {string} relation.name
952
1052
  * @property {string} relation.as
@@ -956,61 +1056,53 @@ class Model extends AbstractModel_1.AbstractModel {
956
1056
  * @property {string} relation.freezeTable freeae table name
957
1057
  * @property {string} relation.pivot table name of pivot
958
1058
  * @property {string} relation.oldVersion return value of old version
1059
+ * @property {class?} relation.modelPivot model for pivot
959
1060
  * @return {this} this
960
1061
  */
961
- belongsToMany({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion }) {
962
- const relation = {
1062
+ belongsToMany({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }) {
1063
+ var _a;
1064
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.belongsToMany({
963
1065
  name,
964
- model,
965
1066
  as,
966
- relation: this.$constants('RELATIONSHIP').belongsToMany,
1067
+ model,
967
1068
  localKey,
968
1069
  foreignKey,
969
1070
  freezeTable,
970
1071
  pivot,
971
1072
  oldVersion,
972
- query: null
973
- };
974
- this.$state.set('RELATION', [...this.$state.get('RELATION'), relation]);
1073
+ modelPivot
1074
+ });
975
1075
  return this;
976
1076
  }
977
1077
  /**
978
- * Assign the relation in model Objects
1078
+ * The 'hasOneBuilder' method is useful for creating 'hasOne' relationship to function
1079
+ *
979
1080
  * @param {object} relation registry relation in your model
980
1081
  * @type {object} relation
981
- * @property {class} model
1082
+ * @property {class} model
982
1083
  * @property {string?} name
983
- * @property {string?} as
1084
+ * @property {string?} as
984
1085
  * @property {string?} localKey
985
1086
  * @property {string?} foreignKey
986
1087
  * @property {string?} freezeTable
987
- * @param {function?} callback callback of query
1088
+ * @param {Function?} callback callback of query
988
1089
  * @return {this} this
989
1090
  */
990
1091
  hasOneBuilder({ name, as, model, localKey, foreignKey, freezeTable }, callback) {
991
- const nameRelation = name == null
992
- ? this._functionRelationName()
993
- : String(name);
994
- const relation = {
995
- name: nameRelation,
996
- model,
1092
+ var _a;
1093
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.hasOneBuilder({
1094
+ name,
997
1095
  as,
998
- relation: this.$constants('RELATIONSHIP').hasOne,
1096
+ model,
999
1097
  localKey,
1000
1098
  foreignKey,
1001
- freezeTable,
1002
- query: null
1003
- };
1004
- const r = this._handleRelationsQuery(nameRelation, relation);
1005
- if (callback == null) {
1006
- r.query = new r.model();
1007
- return this;
1008
- }
1009
- r.query = callback(new r.model());
1099
+ freezeTable
1100
+ }, callback);
1010
1101
  return this;
1011
1102
  }
1012
1103
  /**
1013
- * Assign the relation in model Objects
1104
+ * The 'hasManyBuilder' method is useful for creating 'hasMany' relationship to function
1105
+ *
1014
1106
  * @param {object} relation registry relation in your model
1015
1107
  * @type {object} relation
1016
1108
  * @property {class} model
@@ -1023,29 +1115,19 @@ class Model extends AbstractModel_1.AbstractModel {
1023
1115
  * @return {this} this
1024
1116
  */
1025
1117
  hasManyBuilder({ name, as, model, localKey, foreignKey, freezeTable }, callback) {
1026
- const nameRelation = name == null
1027
- ? this._functionRelationName()
1028
- : String(name);
1029
- const relation = {
1030
- name: nameRelation,
1031
- model,
1118
+ var _a;
1119
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.hasManyBuilder({
1120
+ name,
1032
1121
  as,
1033
- relation: this.$constants('RELATIONSHIP').hasMany,
1122
+ model,
1034
1123
  localKey,
1035
1124
  foreignKey,
1036
- freezeTable,
1037
- query: null
1038
- };
1039
- const r = this._handleRelationsQuery(nameRelation, relation);
1040
- if (callback == null) {
1041
- r.query = new r.model();
1042
- return this;
1043
- }
1044
- r.query = callback(new r.model());
1125
+ freezeTable
1126
+ }, callback);
1045
1127
  return this;
1046
1128
  }
1047
1129
  /**
1048
- * Assign the relation in model Objects
1130
+ * The 'belongsToBuilder' method is useful for creating 'belongsTo' relationship to function
1049
1131
  * @param {object} relation registry relation in your model
1050
1132
  * @type {object} relation
1051
1133
  * @property {class} model
@@ -1058,29 +1140,19 @@ class Model extends AbstractModel_1.AbstractModel {
1058
1140
  * @return {this} this
1059
1141
  */
1060
1142
  belongsToBuilder({ name, as, model, localKey, foreignKey, freezeTable }, callback) {
1061
- const nameRelation = name == null
1062
- ? this._functionRelationName()
1063
- : String(name);
1064
- const relation = {
1065
- name: nameRelation,
1066
- model,
1143
+ var _a;
1144
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.belongsToBuilder({
1145
+ name,
1067
1146
  as,
1068
- relation: this.$constants('RELATIONSHIP').belongsTo,
1147
+ model,
1069
1148
  localKey,
1070
1149
  foreignKey,
1071
- freezeTable,
1072
- query: null
1073
- };
1074
- const r = this._handleRelationsQuery(nameRelation, relation);
1075
- if (callback == null) {
1076
- r.query = new r.model();
1077
- return this;
1078
- }
1079
- r.query = callback(new r.model());
1150
+ freezeTable
1151
+ }, callback);
1080
1152
  return this;
1081
1153
  }
1082
1154
  /**
1083
- * Assign the relation in model Objects
1155
+ * The 'belongsToManyBuilder' method is useful for creating 'belongsToMany' relationship to function
1084
1156
  * @param {object} relation registry relation in your model
1085
1157
  * @type {object} relation
1086
1158
  * @property {class} model
@@ -1092,62 +1164,42 @@ class Model extends AbstractModel_1.AbstractModel {
1092
1164
  * @param {function?} callback callback of query
1093
1165
  * @return {this} this
1094
1166
  */
1095
- belongsToManyBuilder({ name, as, model, localKey, foreignKey, freezeTable, pivot }, callback) {
1096
- const nameRelation = name == null
1097
- ? this._functionRelationName()
1098
- : String(name);
1099
- const relation = {
1100
- name: nameRelation,
1101
- model,
1167
+ belongsToManyBuilder({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }, callback) {
1168
+ var _a;
1169
+ (_a = this.$relation) === null || _a === void 0 ? void 0 : _a.belongsToManyBuilder({
1170
+ name,
1102
1171
  as,
1103
- relation: this.$constants('RELATIONSHIP').belongsToMany,
1172
+ model,
1104
1173
  localKey,
1105
1174
  foreignKey,
1106
1175
  freezeTable,
1107
1176
  pivot,
1108
- query: null
1109
- };
1110
- const r = this._handleRelationsQuery(nameRelation, relation);
1111
- if (callback == null) {
1112
- r.query = new r.model();
1113
- return this;
1114
- }
1115
- r.query = callback(new r.model());
1177
+ oldVersion,
1178
+ modelPivot
1179
+ }, callback);
1116
1180
  return this;
1117
1181
  }
1118
1182
  /**
1119
- * where not null using NULL
1120
- * @override
1121
- * @return {this}
1183
+ * The 'trashed' method is used to specify that you want to retrieve only the soft-deleted records from a database table.
1184
+ *
1185
+ * Soft deleting is a feature that allows you to mark records as deleted without physically removing them from the database. Instead,
1186
+ * a special "deleted_at" timestamp column is set to a non-null value to indicate that the record has been deleted.
1187
+ * @return {this} this
1122
1188
  */
1123
- whereTrashed() {
1189
+ onlyTrashed() {
1124
1190
  this.disableSoftDelete();
1125
- this.whereNotNull(this._valuePattern(this.$state.get('SOFT_DELETE_FORMAT')));
1191
+ this.whereNotNull(this._valuePattern(this._getState('SOFT_DELETE_FORMAT')));
1126
1192
  return this;
1127
1193
  }
1128
1194
  /**
1129
- * return only in trashed (data has been remove)
1130
- * @return {promise}
1195
+ * The 'trashed' method is used to specify that you want to retrieve only the soft-deleted records from a database table.
1196
+ *
1197
+ * Soft deleting is a feature that allows you to mark records as deleted without physically removing them from the database. Instead,
1198
+ * a special "deleted_at" timestamp column is set to a non-null value to indicate that the record has been deleted.
1199
+ * @return {this} this
1131
1200
  */
1132
1201
  trashed() {
1133
- return __awaiter(this, void 0, void 0, function* () {
1134
- this.disableSoftDelete();
1135
- this.whereNotNull(this._valuePattern(this.$state.get('SOFT_DELETE_FORMAT')));
1136
- const sql = this._buildQueryStatement();
1137
- return yield this._execute({ sql, type: 'GET' });
1138
- });
1139
- }
1140
- /**
1141
- * return all only in trashed (data has been remove)
1142
- * @return {promise}
1143
- */
1144
- onlyTrashed() {
1145
- return __awaiter(this, void 0, void 0, function* () {
1146
- this.disableSoftDelete();
1147
- this.whereNotNull(this._valuePattern(this.$state.get('SOFT_DELETE_FORMAT')));
1148
- const sql = this._buildQueryStatement();
1149
- return yield this._execute({ sql, type: 'GET' });
1150
- });
1202
+ return this.onlyTrashed();
1151
1203
  }
1152
1204
  /**
1153
1205
  * restore data in trashed
@@ -1156,93 +1208,123 @@ class Model extends AbstractModel_1.AbstractModel {
1156
1208
  restore() {
1157
1209
  return __awaiter(this, void 0, void 0, function* () {
1158
1210
  this.disableSoftDelete();
1159
- const updatedAt = this._valuePattern(this.$state.get('TIMESTAMP_FORMAT').UPDATED_AT);
1160
- const deletedAt = this._valuePattern(this.$state.get('SOFT_DELETE_FORMAT'));
1161
- const query = this.$state.get('TIMESTAMP')
1211
+ const updatedAt = this._valuePattern(this._getState('TIMESTAMP_FORMAT').UPDATED_AT);
1212
+ const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
1213
+ const query = this._getState('TIMESTAMP')
1162
1214
  ? `${deletedAt} = NULL , ${updatedAt} = '${this.$utils.timestamp()}'`
1163
1215
  : `${deletedAt} = NULL`;
1164
- this.$state.set('UPDATE', [
1216
+ this._setState('UPDATE', [
1165
1217
  `${this.$constants('UPDATE')}`,
1166
- `${this.$state.get('TABLE_NAME')}`,
1218
+ `${this._getState('TABLE_NAME')}`,
1167
1219
  `SET ${query}`
1168
1220
  ].join(' '));
1169
- this.$state.set('SAVE', 'UPDATE');
1221
+ this._setState('SAVE', 'UPDATE');
1170
1222
  return yield this.save();
1171
1223
  });
1172
1224
  }
1173
1225
  toTableName() {
1174
- return this._tableName();
1226
+ return this.getTableName();
1175
1227
  }
1176
1228
  toTableNameAndColumn(column) {
1177
- return `\`${this._tableName()}\`.\`${this._valuePattern(column)}\``;
1229
+ return `\`${this.getTableName()}\`.\`${this._valuePattern(column)}\``;
1178
1230
  }
1179
1231
  /**
1180
- * delete data from the database
1181
1232
  * @override Method
1182
- * @return {promise<boolean>}
1233
+ * @return {promise<boolean>} promise boolean
1183
1234
  */
1184
1235
  delete() {
1185
1236
  var _a, _b;
1186
1237
  return __awaiter(this, void 0, void 0, function* () {
1187
- if (!this.$state.get('WHERE'))
1238
+ if (!this._getState('WHERE'))
1188
1239
  throw new Error("Can't delete without where condition");
1189
- if (this.$state.get('SOFT_DELETE')) {
1190
- const deletedAt = this._valuePattern(this.$state.get('SOFT_DELETE_FORMAT'));
1191
- const query = `${deletedAt} = '${this.$utils.timestamp()}'`;
1192
- let sql = [
1193
- `${this.$constants('UPDATE')}`,
1194
- `${this.$state.get('TABLE_NAME')}`,
1195
- `${this.$constants('SET')}`,
1196
- `${query}`
1197
- ].join(' ');
1198
- if (this.$state.get('TIMESTAMP')) {
1199
- const updatedAt = this._valuePattern(this.$state.get('TIMESTAMP_FORMAT').UPDATED_AT);
1200
- sql = `${sql} , ${updatedAt} = '${this.$utils.timestamp()}'`;
1201
- }
1202
- this.$state.set('UPDATE', `${sql} ${this.$state.get('WHERE')}`);
1203
- const result = yield this.actionStatement({ sql: this.$state.get('UPDATE') });
1204
- return Boolean(this.resultHandler((_a = !!result) !== null && _a !== void 0 ? _a : false));
1240
+ this.limit(1);
1241
+ if (this._getState('SOFT_DELETE')) {
1242
+ const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
1243
+ const sql = new Model()
1244
+ .copyModel(this, { where: true, limit: true })
1245
+ .bind(this.$pool.get())
1246
+ .update({
1247
+ [deletedAt]: this.$utils.timestamp()
1248
+ })
1249
+ .toString();
1250
+ const result = yield this._actionStatement({ sql });
1251
+ const r = Boolean(this._resultHandler((_a = !!result) !== null && _a !== void 0 ? _a : false));
1252
+ this._observer(r, 'updated');
1253
+ return r;
1205
1254
  }
1206
- this.$state.set('DELETE', [
1255
+ this._setState('DELETE', [
1207
1256
  `${this.$constants('DELETE')}`,
1208
- `${this.$state.get('FROM')}`,
1209
- `${this.$state.get('TABLE_NAME')}`,
1210
- `${this.$state.get('WHERE')}`
1257
+ `${this._getState('FROM')}`,
1258
+ `${this._getState('TABLE_NAME')}`,
1211
1259
  ].join(' '));
1212
- const result = yield this.actionStatement({ sql: this.$state.get('DELETE') });
1213
- return Boolean(this.resultHandler((_b = !!result) !== null && _b !== void 0 ? _b : false));
1260
+ const result = yield this._actionStatement({ sql: this._queryBuilder().delete() });
1261
+ const r = Boolean(this._resultHandler((_b = !!result) !== null && _b !== void 0 ? _b : false));
1262
+ this._observer(r, 'deleted');
1263
+ return r;
1214
1264
  });
1215
1265
  }
1216
1266
  /**
1217
- *
1218
1267
  * @override Method
1219
- * @return {promise<Record<string,any> | null>}
1268
+ * @return {promise<boolean>} promise boolean
1269
+ */
1270
+ deleteMany() {
1271
+ var _a, _b;
1272
+ return __awaiter(this, void 0, void 0, function* () {
1273
+ if (!this._getState('WHERE'))
1274
+ throw new Error("Can't delete without where condition");
1275
+ if (this._getState('SOFT_DELETE')) {
1276
+ const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
1277
+ const sql = new Model()
1278
+ .copyModel(this, { where: true, limit: true })
1279
+ .bind(this.$pool.get())
1280
+ .update({
1281
+ [deletedAt]: this.$utils.timestamp()
1282
+ })
1283
+ .toString();
1284
+ const result = yield this._actionStatement({ sql });
1285
+ const r = Boolean(this._resultHandler((_a = !!result) !== null && _a !== void 0 ? _a : false));
1286
+ this._observer(r, 'updated');
1287
+ return r;
1288
+ }
1289
+ this._setState('DELETE', [
1290
+ `${this.$constants('DELETE')}`,
1291
+ `${this._getState('FROM')}`,
1292
+ `${this._getState('TABLE_NAME')}`,
1293
+ ].join(' '));
1294
+ const result = yield this._actionStatement({ sql: this._queryBuilder().delete() });
1295
+ const r = Boolean(this._resultHandler((_b = !!result) !== null && _b !== void 0 ? _b : false));
1296
+ this._observer(r, 'deleted');
1297
+ return r;
1298
+ });
1299
+ }
1300
+ /**
1301
+ * @override Method
1302
+ * @return {promise<Record<string,any> | null>} Record | null
1220
1303
  */
1221
1304
  first() {
1222
- var _a;
1305
+ var _a, _b;
1223
1306
  return __awaiter(this, void 0, void 0, function* () {
1224
1307
  this._validateMethod('first');
1225
- if (this.$state.get('VOID'))
1226
- return this.resultHandler(undefined);
1227
- if ((_a = this.$state.get('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1228
- this.select(...yield this.exceptColumns());
1308
+ if (this._getState('VOID'))
1309
+ return this._resultHandler(undefined);
1310
+ if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1311
+ this.select(...yield this._exceptColumns());
1229
1312
  this.limit(1);
1230
- if (this.$state.get('RELATIONS_EXISTS')) {
1313
+ if (this._getState('RELATIONS_EXISTS')) {
1231
1314
  return yield this._execute({
1232
- sql: this._queryRelationsExists(),
1315
+ sql: String((_b = this.$relation) === null || _b === void 0 ? void 0 : _b.loadExists()),
1233
1316
  type: 'FIRST'
1234
1317
  });
1235
1318
  }
1236
1319
  return yield this._execute({
1237
- sql: this._buildQueryStatement(),
1320
+ sql: this._queryBuilder().select(),
1238
1321
  type: 'FIRST'
1239
1322
  });
1240
1323
  });
1241
1324
  }
1242
1325
  /**
1243
- *
1244
1326
  * @override Method
1245
- * @return {promise<Record<string,any> | null>}
1327
+ * @return {promise<Record<string,any> | null>} Record | null
1246
1328
  */
1247
1329
  findOne() {
1248
1330
  return __awaiter(this, void 0, void 0, function* () {
@@ -1250,25 +1332,24 @@ class Model extends AbstractModel_1.AbstractModel {
1250
1332
  });
1251
1333
  }
1252
1334
  /**
1253
- *
1254
1335
  * @override Method
1255
- * @return {promise<object | Error>}
1336
+ * @return {promise<object | Error>} Record | throw error
1256
1337
  */
1257
1338
  firstOrError(message, options) {
1258
- var _a;
1339
+ var _a, _b;
1259
1340
  return __awaiter(this, void 0, void 0, function* () {
1260
1341
  this._validateMethod('firstOrError');
1261
- if ((_a = this.$state.get('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1262
- this.select(...yield this.exceptColumns());
1342
+ if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1343
+ this.select(...yield this._exceptColumns());
1263
1344
  this.limit(1);
1264
- if (this.$state.get('RELATIONS_EXISTS')) {
1345
+ if (this._getState('RELATIONS_EXISTS')) {
1265
1346
  return yield this._execute({
1266
- sql: this._queryRelationsExists(),
1347
+ sql: String((_b = this.$relation) === null || _b === void 0 ? void 0 : _b.loadExists()),
1267
1348
  type: 'FIRST_OR_ERROR', message, options
1268
1349
  });
1269
1350
  }
1270
1351
  return yield this._execute({
1271
- sql: this._buildQueryStatement(),
1352
+ sql: this._queryBuilder().select(),
1272
1353
  type: 'FIRST_OR_ERROR',
1273
1354
  message,
1274
1355
  options
@@ -1278,7 +1359,7 @@ class Model extends AbstractModel_1.AbstractModel {
1278
1359
  /**
1279
1360
  *
1280
1361
  * @override Method
1281
- * @return {promise<any>}
1362
+ * @return {promise<any>} Record | throw error
1282
1363
  */
1283
1364
  findOneOrError(message, options) {
1284
1365
  return __awaiter(this, void 0, void 0, function* () {
@@ -1288,19 +1369,19 @@ class Model extends AbstractModel_1.AbstractModel {
1288
1369
  /**
1289
1370
  *
1290
1371
  * @override Method
1291
- * @return {promise<array>}
1372
+ * @return {promise<array>} Array
1292
1373
  */
1293
1374
  get() {
1294
- var _a;
1375
+ var _a, _b;
1295
1376
  return __awaiter(this, void 0, void 0, function* () {
1296
1377
  this._validateMethod('get');
1297
- if (this.$state.get('VOID'))
1378
+ if (this._getState('VOID'))
1298
1379
  return [];
1299
- if ((_a = this.$state.get('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1300
- this.select(...yield this.exceptColumns());
1301
- let sql = this._buildQueryStatement();
1302
- if (this.$state.get('RELATIONS_EXISTS'))
1303
- sql = this._queryRelationsExists();
1380
+ if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1381
+ this.select(...yield this._exceptColumns());
1382
+ let sql = this._queryBuilder().select();
1383
+ if (this._getState('RELATIONS_EXISTS'))
1384
+ sql = String((_b = this.$relation) === null || _b === void 0 ? void 0 : _b.loadExists());
1304
1385
  return yield this._execute({
1305
1386
  sql,
1306
1387
  type: 'GET'
@@ -1310,7 +1391,7 @@ class Model extends AbstractModel_1.AbstractModel {
1310
1391
  /**
1311
1392
  *
1312
1393
  * @override Method
1313
- * @return {promise<array>}
1394
+ * @return {promise<array>} Array
1314
1395
  */
1315
1396
  findMany() {
1316
1397
  return __awaiter(this, void 0, void 0, function* () {
@@ -1318,15 +1399,14 @@ class Model extends AbstractModel_1.AbstractModel {
1318
1399
  });
1319
1400
  }
1320
1401
  /**
1321
- *
1322
1402
  * @override Method
1323
1403
  * @param {object?} paginationOptions by default page = 1 , limit = 15
1324
1404
  * @property {number} paginationOptions.limit
1325
1405
  * @property {number} paginationOptions.page
1326
- * @return {promise<Pagination>}
1406
+ * @return {promise<Pagination>} Pagination
1327
1407
  */
1328
1408
  pagination(paginationOptions) {
1329
- var _a;
1409
+ var _a, _b;
1330
1410
  return __awaiter(this, void 0, void 0, function* () {
1331
1411
  this._validateMethod('pagination');
1332
1412
  let limit = 15;
@@ -1335,16 +1415,16 @@ class Model extends AbstractModel_1.AbstractModel {
1335
1415
  limit = (paginationOptions === null || paginationOptions === void 0 ? void 0 : paginationOptions.limit) || limit;
1336
1416
  page = (paginationOptions === null || paginationOptions === void 0 ? void 0 : paginationOptions.page) || page;
1337
1417
  }
1338
- if ((_a = this.$state.get('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1339
- this.select(...yield this.exceptColumns());
1418
+ if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1419
+ this.select(...yield this._exceptColumns());
1340
1420
  const offset = (page - 1) * limit;
1341
- this.$state.set('PER_PAGE', limit);
1342
- this.$state.set('PAGE', page);
1421
+ this._setState('PER_PAGE', limit);
1422
+ this._setState('PAGE', page);
1343
1423
  this.limit(limit);
1344
1424
  this.offset(offset);
1345
- let sql = this._buildQueryStatement();
1346
- if (this.$state.get('RELATIONS_EXISTS'))
1347
- sql = this._queryRelationsExists();
1425
+ let sql = this._queryBuilder().select();
1426
+ if (this._getState('RELATIONS_EXISTS'))
1427
+ sql = String((_b = this.$relation) === null || _b === void 0 ? void 0 : _b.loadExists());
1348
1428
  return yield this._execute({
1349
1429
  sql,
1350
1430
  type: 'PAGINATION'
@@ -1357,7 +1437,7 @@ class Model extends AbstractModel_1.AbstractModel {
1357
1437
  * @param {?object} paginationOptions by default page = 1 , limit = 15
1358
1438
  * @property {number} paginationOptions.limit
1359
1439
  * @property {number} paginationOptions.page
1360
- * @return {promise<Pagination>}
1440
+ * @return {promise<Pagination>} Pagination
1361
1441
  */
1362
1442
  paginate(paginationOptions) {
1363
1443
  return __awaiter(this, void 0, void 0, function* () {
@@ -1365,40 +1445,35 @@ class Model extends AbstractModel_1.AbstractModel {
1365
1445
  });
1366
1446
  }
1367
1447
  /**
1368
- *
1369
1448
  * @override Method
1370
1449
  * @param {string} column
1371
- * @return {Promise<array>}
1450
+ * @return {Promise<array>} Array
1372
1451
  */
1373
1452
  getGroupBy(column) {
1374
1453
  var _a;
1375
1454
  return __awaiter(this, void 0, void 0, function* () {
1376
- if ((_a = this.$state.get('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1377
- this.select(...yield this.exceptColumns());
1378
- this.$state.set('GROUP_BY', `${this.$constants('GROUP_BY')} ${column}`);
1379
- this.$state.set('SELECT', [
1380
- `${this.$state.get('SELECT')},`,
1455
+ if ((_a = this._getState('EXCEPTS')) === null || _a === void 0 ? void 0 : _a.length)
1456
+ this.select(...yield this._exceptColumns());
1457
+ this.selectRaw([
1458
+ `\`${column}\`,`,
1381
1459
  `${this.$constants('GROUP_CONCAT')}(id)`,
1382
- `${this.$constants('AS')} data`
1460
+ `${this.$constants('AS')} \`data\``
1383
1461
  ].join(' '));
1384
- const sql = this._buildQueryStatement();
1385
- const results = yield this.queryStatement(sql);
1462
+ this.groupBy(column);
1463
+ const sql = this._queryBuilder().select();
1464
+ const results = yield this._queryStatement(sql);
1386
1465
  let data = [];
1387
1466
  results.forEach((result) => {
1388
1467
  var _a, _b;
1389
1468
  const splits = (_b = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : '0';
1390
1469
  splits.forEach((split) => data = [...data, split]);
1391
1470
  });
1392
- const sqlChild = [
1393
- `${this.$constants('SELECT')}`,
1394
- `*`,
1395
- `${this.$constants('FROM')}`,
1396
- `${this.$state.get('TABLE_NAME')}`,
1397
- `${this.$constants('WHERE')} id`,
1398
- `${this.$constants('IN')}`,
1399
- `(${data.map((a) => `\'${a}\'`).join(',') || ['0']})`
1400
- ].join(' ');
1401
- const childData = yield this.queryStatement(sqlChild);
1471
+ const sqlChild = new Model()
1472
+ .copyModel(this)
1473
+ .select('*')
1474
+ .whereIn('id', data.map((a) => `\'${a}\'`))
1475
+ .toString();
1476
+ const childData = yield this._queryStatement(sqlChild);
1402
1477
  const child = yield this._executeGroup(childData);
1403
1478
  const resultData = results.map((result) => {
1404
1479
  const id = result[column];
@@ -1408,12 +1483,37 @@ class Model extends AbstractModel_1.AbstractModel {
1408
1483
  data: newData
1409
1484
  });
1410
1485
  });
1411
- return this.resultHandler(resultData);
1486
+ return this._resultHandler(resultData);
1412
1487
  });
1413
1488
  }
1414
1489
  /**
1415
- *
1416
- * update data in the database
1490
+ * @override Method
1491
+ * @param {object} data for insert
1492
+ * @return {this} this
1493
+ */
1494
+ insert(data) {
1495
+ if (!Object.keys(data).length)
1496
+ throw new Error('This method must be required');
1497
+ this._setState('DATA', data);
1498
+ const query = this._queryInsertModel(data);
1499
+ this._setState('INSERT', [
1500
+ `${this.$constants('INSERT')}`,
1501
+ `${this._getState('TABLE_NAME')}`,
1502
+ `${query}`
1503
+ ].join(' '));
1504
+ this._setState('SAVE', 'INSERT');
1505
+ return this;
1506
+ }
1507
+ /**
1508
+ * @override Method
1509
+ * @param {object} data for insert
1510
+ * @return {this} this
1511
+ */
1512
+ create(data) {
1513
+ return this.insert(data);
1514
+ }
1515
+ /**
1516
+ * @override Method
1417
1517
  * @param {object} data
1418
1518
  * @param {array?} updateNotExists options for except update some records in your ${data}
1419
1519
  * @return {this} this
@@ -1432,99 +1532,96 @@ class Model extends AbstractModel_1.AbstractModel {
1432
1532
  }
1433
1533
  }
1434
1534
  }
1535
+ this._setState('DATA', data);
1536
+ this.limit(1);
1435
1537
  const query = this._queryUpdateModel(data);
1436
- this.$state.set('UPDATE', [
1538
+ this._setState('UPDATE', [
1437
1539
  `${this.$constants('UPDATE')}`,
1438
- `${this.$state.get('TABLE_NAME')}`,
1540
+ `${this._getState('TABLE_NAME')}`,
1439
1541
  `${query}`
1440
1542
  ].join(' '));
1441
- this.$state.set('SAVE', 'UPDATE');
1543
+ this._setState('SAVE', 'UPDATE');
1442
1544
  return this;
1443
1545
  }
1444
1546
  /**
1445
- *
1446
1547
  * @override Method
1447
1548
  * @param {object} data
1549
+ * @param {array?} updateNotExists options for except update some records in your ${data}
1448
1550
  * @return {this} this
1449
1551
  */
1450
- updateNotExists(data) {
1552
+ updateMany(data, updateNotExists = []) {
1451
1553
  if (!Object.keys(data).length)
1452
1554
  throw new Error('This method must be required');
1453
- for (const column in data) {
1454
- const value = data[column];
1455
- data[column] = this._updateHandler(column, value);
1555
+ if (updateNotExists.length) {
1556
+ for (const c of updateNotExists) {
1557
+ for (const column in data) {
1558
+ if (c !== column)
1559
+ continue;
1560
+ const value = data[column];
1561
+ data[column] = this._updateHandler(column, value);
1562
+ break;
1563
+ }
1564
+ }
1456
1565
  }
1566
+ this._setState('DATA', data);
1457
1567
  const query = this._queryUpdateModel(data);
1458
- this.$state.set('UPDATE', [
1568
+ this._setState('UPDATE', [
1459
1569
  `${this.$constants('UPDATE')}`,
1460
- `${this.$state.get('TABLE_NAME')}`,
1461
- `${query}`
1462
- ].join(' '));
1463
- this.$state.set('SAVE', 'UPDATE');
1464
- return this;
1465
- }
1466
- /**
1467
- *
1468
- * @override Method
1469
- * @param {object} data for insert
1470
- * @return {this} this
1471
- */
1472
- insert(data) {
1473
- if (!Object.keys(data).length)
1474
- throw new Error('This method must be required');
1475
- const query = this._queryInsertModel(data);
1476
- this.$state.set('INSERT', [
1477
- `${this.$constants('INSERT')}`,
1478
- `${this.$state.get('TABLE_NAME')}`,
1570
+ `${this._getState('TABLE_NAME')}`,
1479
1571
  `${query}`
1480
1572
  ].join(' '));
1481
- this.$state.set('SAVE', 'INSERT');
1573
+ this._setState('SAVE', 'UPDATE');
1482
1574
  return this;
1483
1575
  }
1484
1576
  /**
1485
- *
1486
1577
  * @override Method
1487
- * @param {object} data for insert
1578
+ * @param {object} data
1488
1579
  * @return {this} this
1489
1580
  */
1490
- create(data) {
1581
+ updateNotExists(data) {
1582
+ this.limit(1);
1491
1583
  if (!Object.keys(data).length)
1492
1584
  throw new Error('This method must be required');
1493
- const query = this._queryInsertModel(data);
1494
- this.$state.set('INSERT', [
1495
- `${this.$constants('INSERT')}`,
1496
- `${this.$state.get('TABLE_NAME')}`,
1585
+ for (const column in data) {
1586
+ const value = data[column];
1587
+ data[column] = this._updateHandler(column, value);
1588
+ }
1589
+ this._setState('DATA', data);
1590
+ const query = this._queryUpdateModel(data);
1591
+ this._setState('UPDATE', [
1592
+ `${this.$constants('UPDATE')}`,
1593
+ `${this._getState('TABLE_NAME')}`,
1497
1594
  `${query}`
1498
1595
  ].join(' '));
1499
- this.$state.set('SAVE', 'INSERT');
1596
+ this._setState('SAVE', 'UPDATE');
1500
1597
  return this;
1501
1598
  }
1502
1599
  /**
1503
- *
1504
1600
  * @override Method
1505
1601
  * @param {object} data for update or create
1506
1602
  * @return {this} this
1507
1603
  */
1508
1604
  updateOrCreate(data) {
1605
+ this.limit(1);
1509
1606
  if (!Object.keys(data).length)
1510
1607
  throw new Error('This method must be required');
1511
1608
  const queryUpdate = this._queryUpdateModel(data);
1512
1609
  const queryInsert = this._queryInsertModel(data);
1513
- this.$state.set('INSERT', [
1610
+ this._setState('DATA', data);
1611
+ this._setState('INSERT', [
1514
1612
  `${this.$constants('INSERT')}`,
1515
- `${this.$state.get('TABLE_NAME')}`,
1613
+ `${this._getState('TABLE_NAME')}`,
1516
1614
  `${queryInsert}`
1517
1615
  ].join(' '));
1518
- this.$state.set('UPDATE', [
1616
+ this._setState('UPDATE', [
1519
1617
  `${this.$constants('UPDATE')}`,
1520
- `${this.$state.get('TABLE_NAME')}`,
1618
+ `${this._getState('TABLE_NAME')}`,
1521
1619
  `${queryUpdate}`
1522
1620
  ].join(' '));
1523
- this.$state.set('SAVE', 'UPDATE_OR_INSERT');
1621
+ this._setState('SAVE', 'UPDATE_OR_INSERT');
1524
1622
  return this;
1525
1623
  }
1526
1624
  /**
1527
- *
1528
1625
  * @override Method
1529
1626
  * @param {object} data for update or create
1530
1627
  * @return {this} this
@@ -1533,16 +1630,14 @@ class Model extends AbstractModel_1.AbstractModel {
1533
1630
  return this.updateOrCreate(data);
1534
1631
  }
1535
1632
  /**
1536
- *
1537
- * @override Method
1538
- * @param {object} data for update or create
1539
- * @return {this} this
1540
- */
1633
+ * @override Method
1634
+ * @param {object} data for update or create
1635
+ * @return {this} this
1636
+ */
1541
1637
  insertOrUpdate(data) {
1542
1638
  return this.updateOrCreate(data);
1543
1639
  }
1544
1640
  /**
1545
- *
1546
1641
  * @override Method
1547
1642
  * @param {object} data for update or create
1548
1643
  * @return {this} this
@@ -1551,7 +1646,6 @@ class Model extends AbstractModel_1.AbstractModel {
1551
1646
  return this.updateOrCreate(data);
1552
1647
  }
1553
1648
  /**
1554
- *
1555
1649
  * @override Method
1556
1650
  * @param {object} data for create
1557
1651
  * @return {this} this
@@ -1559,72 +1653,69 @@ class Model extends AbstractModel_1.AbstractModel {
1559
1653
  createOrSelect(data) {
1560
1654
  if (!Object.keys(data).length)
1561
1655
  throw new Error('This method must be required');
1656
+ this._setState('DATA', data);
1562
1657
  const queryInsert = this._queryInsertModel(data);
1563
- this.$state.set('INSERT', [
1658
+ this._setState('INSERT', [
1564
1659
  `${this.$constants('INSERT')}`,
1565
- `${this.$state.get('TABLE_NAME')}`,
1660
+ `${this._getState('TABLE_NAME')}`,
1566
1661
  `${queryInsert}`
1567
1662
  ].join(' '));
1568
- this.$state.set('SAVE', 'INSERT_OR_SELECT');
1663
+ this._setState('SAVE', 'INSERT_OR_SELECT');
1569
1664
  return this;
1570
1665
  }
1571
1666
  /**
1572
- *
1573
- * @override Method
1574
- * @param {object} data for update or create
1575
- * @return {this} this
1576
- */
1667
+ * @override Method
1668
+ * @param {object} data for update or create
1669
+ * @return {this} this
1670
+ */
1577
1671
  insertOrSelect(data) {
1578
1672
  return this.createOrSelect(data);
1579
1673
  }
1580
1674
  /**
1581
- *
1582
- * insert multiple data into the database
1583
1675
  * @override Method
1584
- * @param {array<object>} data create multiple data
1676
+ * @param {Record<string,any>[]} data create multiple data
1585
1677
  * @return {this} this this
1586
1678
  */
1587
1679
  createMultiple(data) {
1680
+ this._setState('DATA', data);
1588
1681
  const query = this._queryInsertMultipleModel(data);
1589
- this.$state.set('INSERT', [
1682
+ this._setState('INSERT', [
1590
1683
  `${this.$constants('INSERT')}`,
1591
- `${this.$state.get('TABLE_NAME')}`,
1684
+ `${this._getState('TABLE_NAME')}`,
1592
1685
  `${query}`
1593
1686
  ].join(' '));
1594
- this.$state.set('SAVE', 'INSERT_MULTIPLE');
1687
+ this._setState('SAVE', 'INSERT_MULTIPLE');
1595
1688
  return this;
1596
1689
  }
1597
1690
  /**
1598
1691
  *
1599
- * insert muliple data into the database
1600
1692
  * @override Method
1601
- * @param {array<object>} data create multiple data
1602
- * @return {this} this this
1693
+ * @param {Record<string,any>[]} data create multiple data
1694
+ * @return {this} this
1603
1695
  */
1604
1696
  insertMultiple(data) {
1605
1697
  return this.createMultiple(data);
1606
1698
  }
1607
1699
  /**
1608
- *
1609
- * @param {object} data create not exists data
1610
1700
  * @override Method
1611
- * @return {this} this this
1701
+ * @param {object} data create not exists data
1702
+ * @return {this} this
1612
1703
  */
1613
1704
  createNotExists(data) {
1614
1705
  this._assertError(Array.isArray(data), 'Data must be an array. Only object are supported');
1706
+ this._setState('DATA', data);
1615
1707
  const query = this._queryInsertModel(data);
1616
- this.$state.set('INSERT', [
1708
+ this._setState('INSERT', [
1617
1709
  `${this.$constants('INSERT')}`,
1618
- `${this.$state.get('TABLE_NAME')}`,
1710
+ `${this._getState('TABLE_NAME')}`,
1619
1711
  `${query}`
1620
1712
  ].join(' '));
1621
- this.$state.set('SAVE', 'INSERT_NOT_EXISTS');
1713
+ this._setState('SAVE', 'INSERT_NOT_EXISTS');
1622
1714
  return this;
1623
1715
  }
1624
1716
  /**
1625
- *
1626
- * @param {object} data create not exists data
1627
1717
  * @override Method
1718
+ * @param {object} data create not exists data
1628
1719
  * @return {this} this this
1629
1720
  */
1630
1721
  insertNotExists(data) {
@@ -1641,65 +1732,45 @@ class Model extends AbstractModel_1.AbstractModel {
1641
1732
  `${this.$constants('SHOW')}`,
1642
1733
  `${this.$constants('COLUMNS')}`,
1643
1734
  `${this.$constants('FROM')}`,
1644
- `\`${this.$state.get('TABLE_NAME').replace(/\`/g, '')}\``
1735
+ `\`${this._getState('TABLE_NAME').replace(/\`/g, '')}\``
1645
1736
  ].join(' ');
1646
- return yield this.queryStatement(sql);
1737
+ return yield this._queryStatement(sql);
1647
1738
  });
1648
1739
  }
1649
1740
  getSchemaModel() {
1650
- return __awaiter(this, void 0, void 0, function* () {
1651
- return this.$state.get('SCHEMA_TABLE');
1652
- });
1653
- }
1654
- getTableName() {
1655
- var _a;
1656
- return (_a = this.$state.get('TABLE_NAME')) === null || _a === void 0 ? void 0 : _a.replace(/`/g, '');
1741
+ return this._getState('SCHEMA_TABLE');
1657
1742
  }
1658
1743
  /**
1659
- *
1660
1744
  * @override Method
1661
1745
  * @return {Promise<Record<string,any> | any[] | null | undefined>}
1662
1746
  */
1663
1747
  save() {
1664
1748
  return __awaiter(this, void 0, void 0, function* () {
1665
- this._validateMethod('save');
1666
1749
  const attributes = this.$attributes;
1667
1750
  if (attributes != null) {
1668
1751
  while (true) {
1669
- if (this.$state.get('WHERE')) {
1670
- const query = this._queryUpdateModel(attributes);
1671
- this.$state.set('UPDATE', [
1672
- `${this.$constants('UPDATE')}`,
1673
- `${this.$state.get('TABLE_NAME')}`,
1674
- `${query}`
1675
- ].join(' '));
1676
- this.$state.set('SAVE', 'UPDATE');
1752
+ if (this._getState('WHERE')) {
1753
+ this.update(attributes);
1677
1754
  break;
1678
1755
  }
1679
- const query = this._queryInsertModel(attributes);
1680
- this.$state.set('INSERT', [
1681
- `${this.$constants('INSERT')}`,
1682
- `${this.$state.get('TABLE_NAME')}`,
1683
- `${query}`
1684
- ].join(' '));
1685
- this.$state.set('SAVE', 'INSERT');
1756
+ this.create(attributes);
1686
1757
  break;
1687
1758
  }
1688
1759
  }
1689
- switch (String(this.$state.get('SAVE'))) {
1760
+ this._validateMethod('save');
1761
+ switch (String(this._getState('SAVE'))) {
1690
1762
  case 'INSERT': return yield this._insertModel();
1691
1763
  case 'UPDATE': return yield this._updateModel();
1692
1764
  case 'INSERT_MULTIPLE': return yield this._createMultipleModel();
1693
1765
  case 'INSERT_NOT_EXISTS': return yield this._insertNotExistsModel();
1694
1766
  case 'UPDATE_OR_INSERT': return yield this._updateOrInsertModel();
1695
1767
  case 'INSERT_OR_SELECT': return yield this._insertOrSelectModel();
1696
- default: throw new Error(`Unknown this [${this.$state.get('SAVE')}]`);
1768
+ default: throw new Error(`Unknown this [${this._getState('SAVE')}]`);
1697
1769
  }
1698
1770
  });
1699
1771
  }
1700
1772
  /**
1701
1773
  *
1702
- * fake data into to this table
1703
1774
  * @override Method
1704
1775
  * @param {number} rows number of rows
1705
1776
  * @return {promise<any>}
@@ -1712,11 +1783,11 @@ class Model extends AbstractModel_1.AbstractModel {
1712
1783
  `${this.$constants('SHOW')}`,
1713
1784
  `${this.$constants('FIELDS')}`,
1714
1785
  `${this.$constants('FROM')}`,
1715
- `${this.$state.get('TABLE_NAME')}`
1786
+ `${this._getState('TABLE_NAME')}`
1716
1787
  ].join(' ');
1717
- const fields = yield this.queryStatement(sql);
1788
+ const fields = yield this._queryStatement(sql);
1718
1789
  for (let row = 0; row < rows; row++) {
1719
- this._assertError(this.$state.get('TABLE_NAME') === '' || this.$state.get('TABLE_NAME') == null, "Unknow this table");
1790
+ this._assertError(this._getState('TABLE_NAME') === '' || this._getState('TABLE_NAME') == null, "Unknow this table");
1720
1791
  let columnAndValue = {};
1721
1792
  for (const { Field: field, Type: type } of fields) {
1722
1793
  const passed = ['id', '_id', 'uuid', 'deleted_at', 'deletedAt'].some(p => field.toLowerCase() === p);
@@ -1727,17 +1798,17 @@ class Model extends AbstractModel_1.AbstractModel {
1727
1798
  data = [...data, columnAndValue];
1728
1799
  }
1729
1800
  const query = this._queryInsertMultipleModel(data);
1730
- this.$state.set('INSERT', [
1801
+ this._setState('INSERT', [
1731
1802
  `${this.$constants('INSERT')}`,
1732
- `${this.$state.get('TABLE_NAME')}`,
1803
+ `${this._getState('TABLE_NAME')}`,
1733
1804
  `${query}`
1734
1805
  ].join(' '));
1735
- this.$state.set('SAVE', 'INSERT_MULTIPLE');
1806
+ this._setState('SAVE', 'INSERT_MULTIPLE');
1736
1807
  return yield this.save();
1737
1808
  });
1738
1809
  }
1739
1810
  _valuePattern(value) {
1740
- switch (this.$state.get('PATTERN')) {
1811
+ switch (this._getState('PATTERN')) {
1741
1812
  case this.$constants('PATTERN').snake_case: {
1742
1813
  return value.replace(/([A-Z])/g, (str) => `_${str.toLowerCase()}`);
1743
1814
  }
@@ -1748,93 +1819,24 @@ class Model extends AbstractModel_1.AbstractModel {
1748
1819
  }
1749
1820
  }
1750
1821
  _isPatternSnakeCase() {
1751
- return this.$state.get('PATTERN') === this.$constants('PATTERN').snake_case;
1822
+ return this._getState('PATTERN') === this.$constants('PATTERN').snake_case;
1752
1823
  }
1753
1824
  _classToTableName(className, { singular = false } = {}) {
1754
1825
  if (className == null)
1755
1826
  className = this.constructor.name;
1756
1827
  const tb = className.replace(/([A-Z])/g, (str) => '_' + str.toLowerCase()).slice(1);
1757
1828
  if (singular)
1758
- return this._valuePattern(tb);
1829
+ return pluralize_1.default.singular(this._valuePattern(tb));
1759
1830
  return pluralize_1.default.plural(this._valuePattern(tb));
1760
1831
  }
1761
1832
  _makeTableName() {
1762
- const tb = this._classToTableName();
1763
- this.$state.set('SELECT', `${this.$constants('SELECT')} *`);
1764
- this.$state.set('FROM', `${this.$constants('FROM')}`);
1765
- this.$state.set('TABLE_NAME', `\`${tb}\``);
1833
+ const tableName = this._classToTableName();
1834
+ this._setState('TABLE_NAME', `\`${tableName}\``);
1766
1835
  return this;
1767
1836
  }
1768
- _tableName() {
1769
- var _a;
1770
- return (_a = this.$state.get('TABLE_NAME')) === null || _a === void 0 ? void 0 : _a.replace(/`/g, '');
1771
- }
1772
- _valueInRelation(relationModel) {
1773
- var _a, _b, _c, _d;
1774
- this._assertError((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Promise, 'Nested Relation isn\'t supported Promise method');
1775
- this._assertError(!((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Model), 'Callback function supported instance of Model only');
1776
- const relation = relationModel.relation;
1777
- const model = (_a = relationModel.model) === null || _a === void 0 ? void 0 : _a.name;
1778
- const oldVersion = relationModel.oldVersion;
1779
- const table = relationModel.freezeTable
1780
- ? relationModel.freezeTable
1781
- : (_b = relationModel.query) === null || _b === void 0 ? void 0 : _b._tableName();
1782
- let pivot = null;
1783
- const name = relationModel.name;
1784
- const as = relationModel.as;
1785
- this._assertError(!model || model == null, 'Not found model');
1786
- let localKey = relationModel.localKey
1787
- ? relationModel.localKey
1788
- : this.$state.get('PRIMARY_KEY');
1789
- let foreignKey = relationModel.foreignKey
1790
- ? relationModel.foreignKey
1791
- : this._valuePattern([
1792
- `${pluralize_1.default.singular(this.$state.get('TABLE_NAME').replace(/\`/g, ''))}`,
1793
- `${this.$state.get('PRIMARY_KEY')}`
1794
- ].join('_'));
1795
- const checkRelationIsBelongsTo = [
1796
- relationModel.localKey == null,
1797
- relationModel.foreignKey == null,
1798
- relation === this.$constants('RELATIONSHIP').belongsTo
1799
- ].every(r => r);
1800
- if (checkRelationIsBelongsTo) {
1801
- foreignKey = localKey;
1802
- localKey = this._valuePattern([
1803
- `${pluralize_1.default.singular(table !== null && table !== void 0 ? table : '')}`,
1804
- `${this.$state.get('PRIMARY_KEY')}`
1805
- ].join('_'));
1806
- }
1807
- const checkRelationIsBelongsToMany = [
1808
- relationModel.localKey == null,
1809
- relationModel.foreignKey == null,
1810
- relation === this.$constants('RELATIONSHIP').belongsToMany
1811
- ].every(r => r);
1812
- if (checkRelationIsBelongsToMany) {
1813
- localKey = this._valuePattern([
1814
- `${pluralize_1.default.singular(table !== null && table !== void 0 ? table : '')}`,
1815
- `${this.$state.get('PRIMARY_KEY')}`
1816
- ].join('_'));
1817
- foreignKey = 'id';
1818
- pivot = (_c = relationModel.pivot) !== null && _c !== void 0 ? _c : this._valuePattern([
1819
- pluralize_1.default.singular(this === null || this === void 0 ? void 0 : this._tableName()),
1820
- pluralize_1.default.singular((_d = relationModel.query) === null || _d === void 0 ? void 0 : _d._tableName())
1821
- ].sort().join('_'));
1822
- }
1823
- return {
1824
- name,
1825
- as,
1826
- relation,
1827
- table,
1828
- localKey,
1829
- foreignKey,
1830
- model,
1831
- pivot,
1832
- oldVersion
1833
- };
1834
- }
1835
1837
  _handleSoftDelete() {
1836
- if (this.$state.get('SOFT_DELETE')) {
1837
- const deletedAt = this._valuePattern(this.$state.get('SOFT_DELETE_FORMAT'));
1838
+ if (this._getState('SOFT_DELETE')) {
1839
+ const deletedAt = this._valuePattern(this._getState('SOFT_DELETE_FORMAT'));
1838
1840
  this.whereNull(deletedAt);
1839
1841
  }
1840
1842
  return this;
@@ -1843,56 +1845,17 @@ class Model extends AbstractModel_1.AbstractModel {
1843
1845
  *
1844
1846
  * generate sql statements
1845
1847
  * @override
1846
- * @return {string} string generated query string
1847
- */
1848
- _buildQueryStatement() {
1849
- let sql = [];
1850
- while (true) {
1851
- this._handleSoftDelete();
1852
- if (this.$state.get('INSERT')) {
1853
- sql = [
1854
- this.$state.get('INSERT')
1855
- ];
1856
- break;
1857
- }
1858
- if (this.$state.get('UPDATE')) {
1859
- sql = [
1860
- this.$state.get('UPDATE'),
1861
- this.$state.get('WHERE'),
1862
- this.$state.get('LIMIT'),
1863
- ];
1864
- break;
1865
- }
1866
- if (this.$state.get('DELETE')) {
1867
- sql = [
1868
- this.$state.get('DELETE')
1869
- ];
1870
- break;
1871
- }
1872
- sql = [
1873
- this.$state.get('SELECT'),
1874
- this.$state.get('FROM'),
1875
- this.$state.get('TABLE_NAME'),
1876
- this.$state.get('JOIN'),
1877
- this.$state.get('WHERE'),
1878
- this.$state.get('GROUP_BY'),
1879
- this.$state.get('HAVING'),
1880
- this.$state.get('ORDER_BY'),
1881
- this.$state.get('LIMIT'),
1882
- this.$state.get('OFFSET')
1883
- ];
1884
- break;
1885
- }
1886
- const filterSql = sql.filter(data => data !== '' || data == null);
1887
- const query = filterSql.join(' ');
1888
- return query;
1848
+ */
1849
+ _queryBuilder() {
1850
+ this._handleSoftDelete();
1851
+ return this._buildQueryStatement();
1889
1852
  }
1890
1853
  _showOnly(data) {
1891
1854
  let result = [];
1892
- const hasNameRelation = this.$state.get('RELATIONS').map((w) => { var _a; return (_a = w.as) !== null && _a !== void 0 ? _a : w.name; });
1855
+ const hasNameRelation = this._getState('RELATIONS').map((w) => { var _a; return (_a = w.as) !== null && _a !== void 0 ? _a : w.name; });
1893
1856
  data.forEach((d) => {
1894
1857
  let newData = {};
1895
- this.$state.get('ONLY').forEach((only) => {
1858
+ this._getState('ONLY').forEach((only) => {
1896
1859
  if (d.hasOwnProperty(only))
1897
1860
  newData = Object.assign(Object.assign({}, newData), { [only]: d[only] });
1898
1861
  });
@@ -1904,313 +1867,133 @@ class Model extends AbstractModel_1.AbstractModel {
1904
1867
  });
1905
1868
  return result;
1906
1869
  }
1907
- _validateSchema(results) {
1908
- if (!results.length)
1909
- return;
1910
- const validateSchema = Boolean(this.$state.get('VALIDATE_SCHEMA'));
1911
- if (!validateSchema)
1912
- return;
1913
- const schemaTable = this.$state.get('SCHEMA_TABLE');
1914
- const schemaTableDefined = this.$state.get('VALIDATE_SCHEMA_DEFINED');
1915
- this._assertError(schemaTableDefined == null && schemaTable == null, "Can't validate schema withouted schema");
1916
- const schema = schemaTableDefined !== null && schemaTableDefined !== void 0 ? schemaTableDefined : Object.keys(schemaTable).reduce((acc, key) => {
1917
- acc[key] = schemaTable[key].valueType;
1918
- return acc;
1919
- }, {});
1920
- if (schema == null)
1921
- return;
1922
- const typeOf = (data) => Object.prototype.toString.apply(data).slice(8, -1).toLocaleLowerCase();
1923
- const regexDate = /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/;
1924
- 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]/;
1925
- const select = this.$state.get('SELECT');
1926
- const selectedAll = select.replace('SELECT', '').trim() === '*';
1927
- for (const result of results) {
1928
- const schemaKeys = Object.keys(schema);
1929
- const resultKeys = Object.keys(result);
1930
- if (schemaKeys.some(s => !resultKeys.includes(s)) && selectedAll) {
1931
- const columns = schemaKeys.filter(x => !resultKeys.includes(x));
1932
- this._assertError(`Not found this column "${columns.join(', ')}" in result`);
1870
+ _validateSchema(data, action) {
1871
+ return __awaiter(this, void 0, void 0, function* () {
1872
+ const validateSchema = this._getState('VALIDATE_SCHEMA');
1873
+ if (!validateSchema)
1874
+ return;
1875
+ const schemaTable = this._getState('SCHEMA_TABLE');
1876
+ if (schemaTable == null) {
1877
+ return this._assertError(schemaTable == null, `This method "validateSchema" isn't validation without schema. Please use the method "useSchema" for define your schema`);
1933
1878
  }
1934
- for (const column in result) {
1879
+ const schemaTableDefined = this._getState('VALIDATE_SCHEMA_DEFINED');
1880
+ const schema = schemaTableDefined !== null && schemaTableDefined !== void 0 ? schemaTableDefined : Object.keys(schemaTable).reduce((acc, key) => {
1881
+ acc[key] = schemaTable[key].valueType;
1882
+ return acc;
1883
+ }, {});
1884
+ if (schema == null)
1885
+ return;
1886
+ const regexDate = /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/;
1887
+ 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
+ for (const column in schema) {
1935
1893
  const s = schema[column];
1936
- if (s == null && selectedAll) {
1937
- if (!schemaKeys.every(s => resultKeys.includes(s))) {
1938
- this._assertError(`Not found this column "${column}" in result`);
1894
+ const r = data[column];
1895
+ const typeOf = (r) => this.$utils.typeOf(r);
1896
+ if (typeOf(s) !== 'object') {
1897
+ if (r == null)
1898
+ continue;
1899
+ if (regexDate.test(r) || regexDateTime.test(r)) {
1900
+ if (typeOf(new Date(r)) === typeOf(new s()))
1901
+ continue;
1902
+ this._assertError(`This column "${column}" is must be type "${typeOf(new s())}"`);
1939
1903
  }
1904
+ if (typeOf(r) === typeOf(new s()))
1905
+ continue;
1906
+ this._assertError(`This column "${column}" is must be type "${typeOf(new s())}"`);
1940
1907
  continue;
1941
1908
  }
1942
- if (s == null)
1909
+ if (s.require && action === 'insert')
1910
+ this._assertError(r === '' || r == null, `This column "${column}" is required`);
1911
+ if (r == null)
1943
1912
  continue;
1944
- if (regexDate.test(result[column]) || regexDateTime.test(result[column])) {
1945
- if (typeOf(new Date(result[column])) === typeOf(new s()))
1946
- continue;
1947
- this._assertError(`This column "${column}" is invalid schema field type`);
1913
+ this._assertError((regexDate.test(r) || regexDateTime.test(r)) && typeOf(new Date(r)) !== typeOf(new s.type()) `This column "${column}" is must be type "${typeOf(new s.type())}"`);
1914
+ this._assertError(typeOf(r) !== typeOf(new s.type()), `This column "${column}" is must be type "${typeOf(new s.type())}"`);
1915
+ if (s.json) {
1916
+ try {
1917
+ JSON.parse(r);
1918
+ }
1919
+ catch (_) {
1920
+ this._assertError(`This column "${column}" is must be JSON`);
1921
+ }
1922
+ }
1923
+ if (s.length)
1924
+ this._assertError((`${r}`.length > s.length), `This column "${column}" is more than "${s.length}" length of characters`);
1925
+ if (s.maxLength)
1926
+ this._assertError((`${r}`.length > s.maxLength), `This column "${column}" is more than "${s.maxLength}" length of characters`);
1927
+ if (s.minLength)
1928
+ this._assertError((`${r}`.length < s.minLength), `This column "${column}" is less than "${s.minLength}" length of characters`);
1929
+ if (s.max)
1930
+ this._assertError(r > s.max, `This column "${column}" is more than "${s.max}"`);
1931
+ if (s.min)
1932
+ this._assertError(r < s.min, `This column "${column}" is less than "${s.min}"`);
1933
+ if (s.enum && s.enum.length) {
1934
+ this._assertError(!s.enum.some((e) => e === r), `This column "${column}" is must be in ${s.enum.map((e) => `"${e}"`)}`);
1935
+ }
1936
+ if (s.match)
1937
+ this._assertError(!s.match.test(r), `This column "${column}" is not match a regular expression`);
1938
+ if (s.fn)
1939
+ this._assertError(!(yield s.fn(r)), `This column "${column}" is not valid with function`);
1940
+ if (s.unique && action === 'insert') {
1941
+ const exist = yield new Model()
1942
+ .copyModel(this, { select: true, where: true, limit: true })
1943
+ .where([column], r)
1944
+ .debug(this._getState('DEBUG'))
1945
+ .exists();
1946
+ this._assertError(exist, `This column "${column}" is duplicated`);
1948
1947
  }
1949
- if (result[column] == null)
1950
- continue;
1951
- if (typeOf(result[column]) === typeOf(new s()))
1952
- continue;
1953
- this._assertError(`This column "${column}" is invalid schema field type`);
1954
1948
  }
1955
- }
1956
- return;
1949
+ return;
1950
+ });
1957
1951
  }
1958
1952
  _execute({ sql, type, message, options }) {
1953
+ var _a, _b;
1959
1954
  return __awaiter(this, void 0, void 0, function* () {
1960
- let result = yield this.queryStatement(sql);
1961
- this._validateSchema(result);
1955
+ let result = yield this._queryStatement(sql);
1962
1956
  if (!result.length)
1963
1957
  return this._returnEmpty(type, result, message, options);
1964
- const relations = this.$state.get('RELATIONS');
1958
+ const relations = this._getState('RELATIONS');
1965
1959
  if (!relations.length)
1966
1960
  return (yield this._returnResult(type, result)) || this._returnEmpty(type, result, message, options);
1967
1961
  for (const relation of relations) {
1968
- const relationIsBelongsToMany = relation.relation === this.$constants('RELATIONSHIP').belongsToMany;
1969
- if (relationIsBelongsToMany) {
1970
- result = yield this._belongsToMany(result, relation);
1971
- continue;
1972
- }
1973
- const dataFromRelation = yield this._relation(result, relation);
1974
- result = this._relationMapData(result, dataFromRelation, relation);
1962
+ result = (_b = yield ((_a = this.$relation) === null || _a === void 0 ? void 0 : _a.load(result, relation))) !== null && _b !== void 0 ? _b : [];
1975
1963
  }
1976
- if (this.$state.get('HIDDEN').length)
1964
+ if (this._getState('HIDDEN').length)
1977
1965
  this._hiddenColumnModel(result);
1978
1966
  return (yield this._returnResult(type, result)) || this._returnEmpty(type, result, message, options);
1979
1967
  });
1980
1968
  }
1981
1969
  _executeGroup(dataParents, type = 'GET') {
1982
- var _a;
1970
+ var _a, _b, _c;
1983
1971
  return __awaiter(this, void 0, void 0, function* () {
1984
1972
  if (!dataParents.length)
1985
1973
  return this._returnEmpty(type, dataParents);
1986
- const relations = this.$state.get('RELATIONS');
1974
+ const relations = this._getState('RELATIONS');
1987
1975
  if (relations.length) {
1988
1976
  for (const relation of relations) {
1989
- if (relation.relation === this.$constants('RELATIONSHIP').belongsToMany) {
1990
- return this._belongsToMany(dataParents, relation);
1991
- }
1992
- let dataChilds = yield this._relation(dataParents, relation);
1993
- dataParents = this._relationMapData(dataParents, dataChilds, relation);
1977
+ dataParents = (_b = yield ((_a = this.$relation) === null || _a === void 0 ? void 0 : _a.load(dataParents, relation))) !== null && _b !== void 0 ? _b : [];
1994
1978
  }
1995
1979
  }
1996
- if ((_a = this.$state.get('HIDDEN')) === null || _a === void 0 ? void 0 : _a.length)
1980
+ if ((_c = this._getState('HIDDEN')) === null || _c === void 0 ? void 0 : _c.length)
1997
1981
  this._hiddenColumnModel(dataParents);
1998
1982
  const resultData = yield this._returnResult(type, dataParents);
1999
1983
  return resultData || this._returnEmpty(type, dataParents);
2000
1984
  });
2001
1985
  }
2002
- _relationMapData(dataParents, dataChilds, relations) {
2003
- const { name, as, relation, localKey, foreignKey } = this._valueInRelation(relations);
2004
- const keyRelation = as !== null && as !== void 0 ? as : name;
2005
- for (const dataParent of dataParents) {
2006
- const relationIsHasOneOrBelongsTo = [
2007
- this.$constants('RELATIONSHIP').hasOne,
2008
- this.$constants('RELATIONSHIP').belongsTo
2009
- ].some(r => r === relation);
2010
- dataParent[keyRelation] = [];
2011
- if (relationIsHasOneOrBelongsTo)
2012
- dataParent[keyRelation] = null;
2013
- if (!dataChilds.length)
2014
- continue;
2015
- for (const dataChild of dataChilds) {
2016
- if (dataChild[foreignKey] === dataParent[localKey]) {
2017
- const relationIsHasOneOrBelongsTo = [
2018
- this.$constants('RELATIONSHIP').hasOne,
2019
- this.$constants('RELATIONSHIP').belongsTo
2020
- ].some(r => r === relation);
2021
- if (relationIsHasOneOrBelongsTo) {
2022
- dataParent[keyRelation] = dataParent[keyRelation] || dataChild;
2023
- continue;
2024
- }
2025
- if (dataParent[keyRelation] == null)
2026
- dataParent[keyRelation] = [];
2027
- dataParent[keyRelation].push(dataChild);
2028
- }
2029
- }
2030
- }
2031
- return dataParents;
2032
- }
2033
- _handleRelationsExists(relation) {
2034
- var _a;
2035
- this._assertError(!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length), `unknown [relation]`);
2036
- const { localKey, foreignKey } = this._valueInRelation(relation);
2037
- const query = relation.query;
2038
- this._assertError(query == null, `Unknown callback query in [Relation : '${relation.name}']`);
2039
- const clone = new Model().clone(query);
2040
- if (clone.$state.get('RELATIONS').length) {
2041
- for (const r of clone.$state.get('RELATIONS')) {
2042
- if (r.query == null)
2043
- continue;
2044
- const sql = clone._handleRelationsExists(r);
2045
- clone.whereExists(sql);
2046
- }
2047
- }
2048
- const sql = clone
2049
- .bind(this.$pool.get())
2050
- .select(this.$state.get('PRIMARY_KEY'))
2051
- .whereReference(`\`${this._tableName()}\`.\`${localKey}\``, `\`${query._tableName()}\`.\`${foreignKey}\``)
2052
- .toString();
2053
- return sql;
2054
- }
2055
- _queryRelationsExists() {
2056
- var _a;
2057
- const relations = this.$state.get('RELATIONS');
2058
- for (const index in relations) {
2059
- const relation = relations[index];
2060
- if (!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length))
2061
- continue;
2062
- if (relation.exists == null)
2063
- continue;
2064
- const { localKey, foreignKey, pivot } = this._valueInRelation(relation);
2065
- const query = relation.query;
2066
- this._assertError(query == null, `Unknown callback query in [Relation : '${relation.name}']`);
2067
- let clone = new Model().clone(query);
2068
- if (clone.$state.get('RELATIONS').length) {
2069
- for (const r of clone.$state.get('RELATIONS')) {
2070
- if (r.query == null)
2071
- continue;
2072
- const sql = clone._handleRelationsExists(r);
2073
- clone.whereExists(sql);
2074
- }
2075
- }
2076
- if (relation.relation === this.$constants('RELATIONSHIP').belongsToMany) {
2077
- const thisPivot = new Model();
2078
- thisPivot.$state.set('TABLE_NAME', `\`${pivot}\``);
2079
- const sql = clone
2080
- .bind(this.$pool.get())
2081
- .whereReference(`\`${query._tableName()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${localKey}\``)
2082
- .toString();
2083
- thisPivot.whereExists(sql);
2084
- const sqlPivot = thisPivot
2085
- .bind(this.$pool.get())
2086
- .whereReference(`\`${this._tableName()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${this._valuePattern([pluralize_1.default.singular(this._tableName()), foreignKey].join("_"))}\``)
2087
- .toString();
2088
- this.whereExists(sqlPivot);
2089
- continue;
2090
- }
2091
- const sql = clone
2092
- .bind(this.$pool.get())
2093
- .select(this.$state.get('PRIMARY_KEY'))
2094
- .whereReference(`\`${this._tableName()}\`.\`${localKey}\``, `\`${query._tableName()}\`.\`${foreignKey}\``)
2095
- .toString();
2096
- this.whereExists(sql);
2097
- }
2098
- const sql = this._buildQueryStatement();
2099
- return sql;
2100
- }
2101
- _relation(parents, relation) {
2102
- var _a;
2103
- return __awaiter(this, void 0, void 0, function* () {
2104
- if (!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length))
2105
- return [];
2106
- const { localKey, foreignKey } = this._valueInRelation(relation);
2107
- const localKeyId = parents.map((parent) => {
2108
- const data = parent[localKey];
2109
- if (!parent.hasOwnProperty(localKey)) {
2110
- this._assertError(data == null, `Unknown relationship without primary or foreign key in Relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
2111
- }
2112
- return data;
2113
- }).filter((data) => data != null);
2114
- const dataPerentId = Array.from(new Set(localKeyId)) || [];
2115
- if (!dataPerentId.length && this.$state.get('RELATIONS_EXISTS'))
2116
- return [];
2117
- const query = yield relation.query;
2118
- this._assertError(query == null, `Unknown callback query in [Relation : ${relation.name}]`);
2119
- const dataFromRelation = yield query
2120
- .bind(this.$pool.get())
2121
- .whereIn(foreignKey, dataPerentId)
2122
- .debug(this.$state.get('DEBUG'))
2123
- .when(relation.trashed, (query) => query.whereTrashed())
2124
- .when(relation.all, (query) => query.disableSoftDelete())
2125
- .get();
2126
- return dataFromRelation;
2127
- });
2128
- }
2129
- _belongsToMany(dataFromParent, relation) {
2130
- var _a;
2131
- return __awaiter(this, void 0, void 0, function* () {
2132
- const { name, foreignKey, localKey, pivot, oldVersion } = this._valueInRelation(relation);
2133
- const pivotTable = String(((_a = relation.pivot) !== null && _a !== void 0 ? _a : pivot));
2134
- const localKeyId = dataFromParent.map((parent) => {
2135
- const data = parent[foreignKey];
2136
- if (!parent.hasOwnProperty(foreignKey)) {
2137
- this._assertError(data == null, `Unknown relationship without primary or foreign key in Relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
2138
- }
2139
- return data;
2140
- }).filter((data) => data != null);
2141
- const dataPerentId = Array.from(new Set(localKeyId));
2142
- if (!dataPerentId.length && this.$state.get('RELATIONS_EXISTS'))
2143
- return [];
2144
- const modelOther = new relation.model();
2145
- const other = this._classToTableName(modelOther.constructor.name, { singular: true });
2146
- const otherlocalKey = 'id';
2147
- const otherforeignKey = this._valuePattern(`${other}Id`);
2148
- const localKeyPivotTable = this._valuePattern([pluralize_1.default.singular(this._tableName()), foreignKey].join("_"));
2149
- const sql = new Model().copyModel(modelOther)
2150
- .whereReference(`\`${modelOther._tableName()}\`.\`${foreignKey}\``, `\`${pivotTable}\`.\`${localKey}\``)
2151
- .toString();
2152
- const queryChildModel = new Model();
2153
- queryChildModel.$state.set('TABLE_NAME', `\`${pivotTable}\``);
2154
- const sqldataChilds = queryChildModel
2155
- .whereIn(localKeyPivotTable, dataPerentId)
2156
- .when(relation.exists, (query) => query.whereExists(sql))
2157
- .when(relation.trashed, (query) => query.whereTrashed())
2158
- .when(relation.all, (query) => query.disableSoftDelete())
2159
- .toString();
2160
- const dataChilds = yield this.queryStatement(sqldataChilds);
2161
- const otherId = dataChilds.map((sub) => sub[otherforeignKey]).filter((data) => data != null);
2162
- const otherArrId = Array.from(new Set(otherId)) || [];
2163
- const otherdataChilds = yield this.queryStatement(modelOther
2164
- .whereIn(otherlocalKey, otherArrId)
2165
- .debug(this.$state.get('DEBUG'))
2166
- .when(relation.trashed, (query) => query.disableSoftDelete())
2167
- .toString());
2168
- if (oldVersion) {
2169
- dataChilds.forEach((sub) => {
2170
- otherdataChilds.forEach((otherSub) => {
2171
- if (otherSub[otherlocalKey] === sub[otherforeignKey]) {
2172
- sub[other] = otherSub;
2173
- }
2174
- });
2175
- });
2176
- dataFromParent.forEach((dataPerent) => {
2177
- if (dataPerent[name] == null)
2178
- dataPerent[name] = [];
2179
- dataChilds.forEach((sub) => {
2180
- if (sub[localKeyPivotTable] === dataPerent[foreignKey]) {
2181
- dataPerent[name].push(sub);
2182
- }
2183
- });
2184
- });
2185
- if (this.$state.get('HIDDEN').length)
2186
- this._hiddenColumnModel(dataFromParent);
2187
- return dataFromParent;
2188
- }
2189
- dataFromParent.forEach((dataPerent) => {
2190
- if (dataPerent[name] == null)
2191
- dataPerent[name] = [];
2192
- dataChilds.forEach((sub) => {
2193
- if (sub[localKeyPivotTable] === dataPerent[foreignKey]) {
2194
- const data = otherdataChilds.find(u => u[foreignKey] === sub[localKey]);
2195
- if (data != null) {
2196
- data.pivot = Object.assign({}, sub);
2197
- dataPerent[name].push(data);
2198
- }
2199
- }
2200
- });
2201
- });
2202
- if (this.$state.get('HIDDEN').length)
2203
- this._hiddenColumnModel(dataFromParent);
2204
- return dataFromParent;
2205
- });
2206
- }
2207
1986
  _pagination(data) {
2208
1987
  var _a;
2209
1988
  return __awaiter(this, void 0, void 0, function* () {
2210
- const currentPage = +(this.$state.get('PAGE'));
2211
- const limit = Number(this.$state.get('PER_PAGE'));
2212
- this._assertError(limit < 1, "minimun less 1 of limit");
2213
- const total = yield new Model().copyModel(this, { where: true }).count('*');
1989
+ const currentPage = +(this._getState('PAGE'));
1990
+ const limit = Number(this._getState('PER_PAGE'));
1991
+ this._assertError(limit < 1, "This pagination needed limit minimun less 1 for limit");
1992
+ const total = yield new Model()
1993
+ .copyModel(this, { where: true, select: true })
1994
+ .bind(this.$pool.get())
1995
+ .debug(this._getState('DEBUG'))
1996
+ .count();
2214
1997
  let lastPage = Math.ceil(total / limit) || 0;
2215
1998
  lastPage = lastPage > 1 ? lastPage : 1;
2216
1999
  const nextPage = currentPage + 1;
@@ -2226,12 +2009,12 @@ class Model extends AbstractModel_1.AbstractModel {
2226
2009
  prevPage,
2227
2010
  };
2228
2011
  if (this._isPatternSnakeCase()) {
2229
- return this.$utils.snakeCase(this.resultHandler({
2012
+ return this.$utils.snakeCase(this._resultHandler({
2230
2013
  meta,
2231
2014
  data
2232
2015
  }));
2233
2016
  }
2234
- return this.resultHandler({
2017
+ return this._resultHandler({
2235
2018
  meta,
2236
2019
  data
2237
2020
  });
@@ -2266,9 +2049,9 @@ class Model extends AbstractModel_1.AbstractModel {
2266
2049
  emptyData = {
2267
2050
  meta: {
2268
2051
  total: 0,
2269
- limit: Number(this.$state.get('PER_PAGE')),
2052
+ limit: Number(this._getState('PER_PAGE')),
2270
2053
  totalPage: 0,
2271
- currentPage: Number(this.$state.get('PAGE')),
2054
+ currentPage: Number(this._getState('PAGE')),
2272
2055
  lastPage: 0,
2273
2056
  nextPage: 0,
2274
2057
  prevPage: 0
@@ -2277,24 +2060,22 @@ class Model extends AbstractModel_1.AbstractModel {
2277
2060
  };
2278
2061
  break;
2279
2062
  }
2280
- default: {
2281
- throw new Error('Missing method first get or pagination');
2282
- }
2063
+ default: this._assertError('Missing method first get or pagination');
2283
2064
  }
2284
2065
  if (this._isPatternSnakeCase()) {
2285
- const empty = this.$utils.snakeCase(this.resultHandler(emptyData));
2286
- yield this.$utils.hookHandle(this.$state.get('HOOKS'), empty);
2066
+ const empty = this.$utils.snakeCase(this._resultHandler(emptyData));
2067
+ yield this.$utils.hookHandle(this._getState('HOOKS'), empty);
2287
2068
  return empty;
2288
2069
  }
2289
- const empty = this.resultHandler(emptyData);
2290
- yield this.$utils.hookHandle(this.$state.get('HOOKS'), empty);
2070
+ const empty = this._resultHandler(emptyData);
2071
+ yield this.$utils.hookHandle(this._getState('HOOKS'), empty);
2291
2072
  return empty;
2292
2073
  });
2293
2074
  }
2294
2075
  _returnResult(type, data) {
2295
2076
  var _a, _b, _c, _d, _e;
2296
2077
  return __awaiter(this, void 0, void 0, function* () {
2297
- const registry = this.$state.get('REGISTRY');
2078
+ const registry = this._getState('REGISTRY');
2298
2079
  if (((_a = Object.keys(registry)) === null || _a === void 0 ? void 0 : _a.length) && registry != null) {
2299
2080
  for (const d of data) {
2300
2081
  for (const name in registry) {
@@ -2302,14 +2083,15 @@ class Model extends AbstractModel_1.AbstractModel {
2302
2083
  }
2303
2084
  }
2304
2085
  }
2305
- const functionRelation = this.$state.get('FUNCTION_RELATION');
2086
+ const functionRelation = this._getState('FUNCTION_RELATION');
2306
2087
  if (functionRelation) {
2307
2088
  for (const d of data) {
2308
- for (const r of this.$state.get('RELATION')) {
2089
+ for (const r of this._getState('RELATION')) {
2309
2090
  d[`$${r.name}`] = (cb) => __awaiter(this, void 0, void 0, function* () {
2091
+ var _f, _g;
2310
2092
  const query = cb ? cb(new r.model()) : new r.model();
2311
2093
  r.query = query;
2312
- const dataFromRelation = yield this._relation([d], r);
2094
+ const dataFromRelation = (_g = yield ((_f = this.$relation) === null || _f === void 0 ? void 0 : _f.load([d], r))) !== null && _g !== void 0 ? _g : [];
2313
2095
  const relationIsHasOneOrBelongsTo = [
2314
2096
  this.$constants('RELATIONSHIP').hasOne,
2315
2097
  this.$constants('RELATIONSHIP').belongsTo
@@ -2321,54 +2103,54 @@ class Model extends AbstractModel_1.AbstractModel {
2321
2103
  }
2322
2104
  }
2323
2105
  }
2324
- if ((_b = this.$state.get('ONLY')) === null || _b === void 0 ? void 0 : _b.length)
2106
+ if ((_b = this._getState('ONLY')) === null || _b === void 0 ? void 0 : _b.length)
2325
2107
  data = this._showOnly(data);
2326
2108
  let result = null;
2327
2109
  switch (type) {
2328
2110
  case 'FIRST': {
2329
- if (this.$state.get('PLUCK')) {
2330
- const pluck = this.$state.get('PLUCK');
2111
+ if (this._getState('PLUCK')) {
2112
+ const pluck = this._getState('PLUCK');
2331
2113
  const newData = data.shift();
2332
2114
  const checkProperty = newData.hasOwnProperty(pluck);
2333
2115
  this._assertError(!checkProperty, `Can't find property '${pluck}' of result`);
2334
- result = this.resultHandler(newData[pluck]);
2116
+ result = this._resultHandler(newData[pluck]);
2335
2117
  break;
2336
2118
  }
2337
- result = this.resultHandler((_c = data.shift()) !== null && _c !== void 0 ? _c : null);
2119
+ result = this._resultHandler((_c = data.shift()) !== null && _c !== void 0 ? _c : null);
2338
2120
  break;
2339
2121
  }
2340
2122
  case 'FIRST_OR_ERROR': {
2341
- if (this.$state.get('PLUCK')) {
2342
- const pluck = this.$state.get('PLUCK');
2123
+ if (this._getState('PLUCK')) {
2124
+ const pluck = this._getState('PLUCK');
2343
2125
  const newData = data.shift();
2344
2126
  const checkProperty = newData.hasOwnProperty(pluck);
2345
2127
  this._assertError(!checkProperty, `Can't find property '${pluck}' of result`);
2346
- result = (_d = this.resultHandler(newData[pluck])) !== null && _d !== void 0 ? _d : null;
2128
+ result = (_d = this._resultHandler(newData[pluck])) !== null && _d !== void 0 ? _d : null;
2347
2129
  break;
2348
2130
  }
2349
- result = this.resultHandler((_e = data.shift()) !== null && _e !== void 0 ? _e : null);
2131
+ result = this._resultHandler((_e = data.shift()) !== null && _e !== void 0 ? _e : null);
2350
2132
  break;
2351
2133
  }
2352
2134
  case 'GET': {
2353
- if (this.$state.get('CHUNK')) {
2135
+ if (this._getState('CHUNK')) {
2354
2136
  const r = data.reduce((resultArray, item, index) => {
2355
- const chunkIndex = Math.floor(index / this.$state.get('CHUNK'));
2137
+ const chunkIndex = Math.floor(index / this._getState('CHUNK'));
2356
2138
  if (!resultArray[chunkIndex])
2357
2139
  resultArray[chunkIndex] = [];
2358
2140
  resultArray[chunkIndex].push(item);
2359
2141
  return resultArray;
2360
2142
  }, []);
2361
- result = this.resultHandler(r);
2143
+ result = this._resultHandler(r);
2362
2144
  break;
2363
2145
  }
2364
- if (this.$state.get('PLUCK')) {
2365
- const pluck = this.$state.get('PLUCK');
2146
+ if (this._getState('PLUCK')) {
2147
+ const pluck = this._getState('PLUCK');
2366
2148
  const newData = data.map((d) => d[pluck]);
2367
2149
  this._assertError(newData.every((d) => d == null), `Can't find property '${pluck}' of result`);
2368
- result = this.resultHandler(newData);
2150
+ result = this._resultHandler(newData);
2369
2151
  break;
2370
2152
  }
2371
- result = this.resultHandler(data);
2153
+ result = this._resultHandler(data);
2372
2154
  break;
2373
2155
  }
2374
2156
  case 'PAGINATION': {
@@ -2379,12 +2161,12 @@ class Model extends AbstractModel_1.AbstractModel {
2379
2161
  throw new Error('Missing method first get or pagination');
2380
2162
  }
2381
2163
  }
2382
- yield this.$utils.hookHandle(this.$state.get('HOOKS'), result);
2164
+ yield this.$utils.hookHandle(this._getState('HOOKS'), result);
2383
2165
  return result;
2384
2166
  });
2385
2167
  }
2386
2168
  _hiddenColumnModel(data) {
2387
- const hiddens = this.$state.get('HIDDEN');
2169
+ const hiddens = this._getState('HIDDEN');
2388
2170
  for (const hidden of hiddens) {
2389
2171
  for (const objColumn of data) {
2390
2172
  delete objColumn[hidden];
@@ -2396,11 +2178,11 @@ class Model extends AbstractModel_1.AbstractModel {
2396
2178
  var _a;
2397
2179
  return __awaiter(this, void 0, void 0, function* () {
2398
2180
  this._assertError(!Array.isArray(dataId), `this ${dataId} is not an array`);
2399
- const relation = (_a = this.$state.get('RELATION')) === null || _a === void 0 ? void 0 : _a.find((data) => data.name === name);
2181
+ const relation = (_a = this._getState('RELATION')) === null || _a === void 0 ? void 0 : _a.find((data) => data.name === name);
2400
2182
  this._assertError(!relation, `unknown name relation ['${name}'] in model`);
2401
2183
  const thisTable = this.$utils.columnRelation(this.constructor.name);
2402
2184
  const relationTable = this._classToTableName(relation.model.name, { singular: true });
2403
- const result = this.$state.get('RESULT');
2185
+ const result = this._getState('RESULT');
2404
2186
  try {
2405
2187
  const pivotTable = `${thisTable}_${relationTable}`;
2406
2188
  const success = yield new DB_1.DB().table(pivotTable).createMultiple(dataId.map((id) => {
@@ -2429,11 +2211,11 @@ class Model extends AbstractModel_1.AbstractModel {
2429
2211
  _detach(name, dataId) {
2430
2212
  return __awaiter(this, void 0, void 0, function* () {
2431
2213
  this._assertError(!Array.isArray(dataId), `this ${dataId} is not an array`);
2432
- const relation = this.$state.get('RELATION').find((data) => data.name === name);
2214
+ const relation = this._getState('RELATION').find((data) => data.name === name);
2433
2215
  this._assertError(!relation, `unknown name relation [${name}] in model`);
2434
2216
  const thisTable = this.$utils.columnRelation(this.constructor.name);
2435
2217
  const relationTable = this._classToTableName(relation.model.name, { singular: true });
2436
- const result = this.$state.get('RESULT');
2218
+ const result = this._getState('RESULT');
2437
2219
  try {
2438
2220
  const pivotTable = `${thisTable}_${relationTable}`;
2439
2221
  for (const id of dataId) {
@@ -2466,8 +2248,9 @@ class Model extends AbstractModel_1.AbstractModel {
2466
2248
  });
2467
2249
  }
2468
2250
  _queryUpdateModel(objects) {
2469
- if (this.$state.get('TIMESTAMP')) {
2470
- const updatedAt = this._valuePattern(this.$state.get('TIMESTAMP_FORMAT').UPDATED_AT);
2251
+ this.$utils.covertDataToDateIfDate(objects);
2252
+ if (this._getState('TIMESTAMP')) {
2253
+ const updatedAt = this._valuePattern(this._getState('TIMESTAMP_FORMAT').UPDATED_AT);
2471
2254
  objects = Object.assign(Object.assign({}, objects), { [updatedAt]: this.$utils.timestamp() });
2472
2255
  }
2473
2256
  const keyValue = Object.entries(objects).map(([column, value]) => {
@@ -2481,21 +2264,22 @@ class Model extends AbstractModel_1.AbstractModel {
2481
2264
  });
2482
2265
  return `${this.$constants('SET')} ${keyValue.join(', ')}`;
2483
2266
  }
2484
- _queryInsertModel(objects) {
2485
- const hasTimestamp = Boolean(this.$state.get('TIMESTAMP'));
2267
+ _queryInsertModel(data) {
2268
+ this.$utils.covertDataToDateIfDate(data);
2269
+ const hasTimestamp = Boolean(this._getState('TIMESTAMP'));
2486
2270
  if (hasTimestamp) {
2487
- const format = this.$state.get('TIMESTAMP_FORMAT');
2271
+ const format = this._getState('TIMESTAMP_FORMAT');
2488
2272
  const createdAt = this._valuePattern(String(format === null || format === void 0 ? void 0 : format.CREATED_AT));
2489
2273
  const updatedAt = this._valuePattern(String(format === null || format === void 0 ? void 0 : format.UPDATED_AT));
2490
- objects = Object.assign(Object.assign({}, objects), { [createdAt]: this.$utils.timestamp(), [updatedAt]: this.$utils.timestamp() });
2274
+ data = Object.assign({ [createdAt]: this.$utils.timestamp(), [updatedAt]: this.$utils.timestamp() }, data);
2491
2275
  }
2492
- const hasUUID = objects.hasOwnProperty(this.$state.get('UUID_FORMAT'));
2493
- if (this.$state.get('UUID') && !hasUUID) {
2494
- const uuidFormat = this.$state.get('UUID_FORMAT');
2495
- objects = Object.assign(Object.assign({}, objects), { [uuidFormat]: this.$utils.generateUUID() });
2276
+ const hasUUID = data.hasOwnProperty(this._getState('UUID_FORMAT'));
2277
+ if (this._getState('UUID') && !hasUUID) {
2278
+ const uuidFormat = this._getState('UUID_FORMAT');
2279
+ data = Object.assign({ [uuidFormat]: this.$utils.generateUUID() }, data);
2496
2280
  }
2497
- const columns = Object.keys(objects).map((column) => `\`${column}\``);
2498
- const values = Object.values(objects).map((value) => {
2281
+ const columns = Object.keys(data).map((column) => `\`${column}\``);
2282
+ const values = Object.values(data).map((value) => {
2499
2283
  if (typeof value === 'string' && !(value.includes(this.$constants('RAW'))))
2500
2284
  value = value === null || value === void 0 ? void 0 : value.replace(/'/g, '');
2501
2285
  return `${value == null || value === 'NULL'
@@ -2504,20 +2288,22 @@ class Model extends AbstractModel_1.AbstractModel {
2504
2288
  ? `${this.$utils.covertBooleanToNumber(value)}`.replace(this.$constants('RAW'), '')
2505
2289
  : `'${this.$utils.covertBooleanToNumber(value)}'`}`;
2506
2290
  });
2507
- return [
2291
+ const sql = [
2508
2292
  `(${columns.join(', ')})`,
2509
2293
  `${this.$constants('VALUES')}`,
2510
2294
  `(${values.join(', ')})`,
2511
2295
  ].join(' ');
2296
+ return sql;
2512
2297
  }
2513
2298
  _queryInsertMultipleModel(data) {
2514
2299
  var _a;
2515
2300
  let values = [];
2516
2301
  let columns = Object.keys((_a = [...data]) === null || _a === void 0 ? void 0 : _a.shift()).map((column) => `\`${column}\``);
2517
2302
  for (let objects of data) {
2518
- const hasTimestamp = this.$state.get('TIMESTAMP');
2303
+ this.$utils.covertDataToDateIfDate(data);
2304
+ const hasTimestamp = this._getState('TIMESTAMP');
2519
2305
  if (hasTimestamp) {
2520
- const format = this.$state.get('TIMESTAMP_FORMAT');
2306
+ const format = this._getState('TIMESTAMP_FORMAT');
2521
2307
  const createdAt = this._valuePattern(format.CREATED_AT);
2522
2308
  const updatedAt = this._valuePattern(format.UPDATED_AT);
2523
2309
  objects = Object.assign(Object.assign({}, objects), { [createdAt]: this.$utils.timestamp(), [updatedAt]: this.$utils.timestamp() });
@@ -2527,9 +2313,9 @@ class Model extends AbstractModel_1.AbstractModel {
2527
2313
  `\`${updatedAt}\``
2528
2314
  ];
2529
2315
  }
2530
- const hasUUID = objects.hasOwnProperty(this.$state.get('UUID_FORMAT'));
2531
- if (this.$state.get('UUID') && !hasUUID) {
2532
- const uuidFormat = this.$state.get('UUID_FORMAT');
2316
+ const hasUUID = objects.hasOwnProperty(this._getState('UUID_FORMAT'));
2317
+ if (this._getState('UUID') && !hasUUID) {
2318
+ const uuidFormat = this._getState('UUID_FORMAT');
2533
2319
  objects = Object.assign(Object.assign({}, objects), { [uuidFormat]: this.$utils.generateUUID() });
2534
2320
  columns = [
2535
2321
  ...columns,
@@ -2558,137 +2344,202 @@ class Model extends AbstractModel_1.AbstractModel {
2558
2344
  }
2559
2345
  _insertNotExistsModel() {
2560
2346
  return __awaiter(this, void 0, void 0, function* () {
2561
- this._assertError(!this.$state.get('WHERE'), "Can't insert [insertNotExists] without where condition");
2562
- const clone = new Model().copyModel(this, { where: true }).bind(this.$pool.get());
2563
- const check = (yield clone.exists()) || false;
2347
+ this._assertError(!this._getState('WHERE'), "This method 'createNotExists' is require to use 'where'");
2348
+ const check = (yield new Model()
2349
+ .copyModel(this, { where: true, select: true, limit: true })
2350
+ .bind(this.$pool.get())
2351
+ .debug(this._getState('DEBUG'))
2352
+ .exists()) || false;
2564
2353
  if (check)
2565
- return this.resultHandler(null);
2566
- const [result, id] = yield this.actionStatement({
2567
- sql: this.$state.get('INSERT'),
2354
+ return this._resultHandler(null);
2355
+ yield this._validateSchema(this._getState('DATA'), 'insert');
2356
+ const [result, id] = yield this._actionStatement({
2357
+ sql: this._queryBuilder().insert(),
2568
2358
  returnId: true
2569
2359
  });
2570
2360
  if (!result)
2571
- return this.resultHandler(null);
2572
- return yield new Model().copyModel(this).bind(this.$pool.get()).where('id', id).first();
2361
+ return this._resultHandler(null);
2362
+ const resultData = yield new Model()
2363
+ .copyModel(this, { select: true })
2364
+ .bind(this.$pool.get())
2365
+ .debug(this._getState('DEBUG'))
2366
+ .where('id', id)
2367
+ .first();
2368
+ return this._resultHandler(resultData);
2573
2369
  });
2574
2370
  }
2575
2371
  _insertModel() {
2576
2372
  return __awaiter(this, void 0, void 0, function* () {
2577
- const [result, id] = yield this.actionStatement({
2578
- sql: this.$state.get('INSERT'),
2373
+ yield this._validateSchema(this._getState('DATA'), 'insert');
2374
+ const [result, id] = yield this._actionStatement({
2375
+ sql: this._queryBuilder().insert(),
2579
2376
  returnId: true
2580
2377
  });
2581
- if (this.$state.get('VOID'))
2582
- return this.resultHandler(undefined);
2378
+ if (this._getState('VOID'))
2379
+ return this._resultHandler(undefined);
2583
2380
  if (!result)
2584
- return this.resultHandler(null);
2585
- const resultData = yield new Model().copyModel(this)
2381
+ return this._resultHandler(null);
2382
+ const resultData = yield new Model()
2383
+ .copyModel(this, { select: true })
2586
2384
  .where('id', id)
2587
2385
  .bind(this.$pool.get())
2386
+ .debug(this._getState('DEBUG'))
2588
2387
  .first();
2589
- return this.resultHandler(resultData);
2388
+ this._observer(resultData, 'created');
2389
+ return this._resultHandler(resultData);
2590
2390
  });
2591
2391
  }
2592
2392
  _createMultipleModel() {
2593
2393
  return __awaiter(this, void 0, void 0, function* () {
2594
- const [result, id] = yield this.actionStatement({
2595
- sql: this.$state.get('INSERT'),
2394
+ for (const data of this._getState('DATA')) {
2395
+ yield this._validateSchema(data, 'insert');
2396
+ }
2397
+ const [result, id] = yield this._actionStatement({
2398
+ sql: this._queryBuilder().insert(),
2596
2399
  returnId: true
2597
2400
  });
2598
- if (this.$state.get('VOID'))
2599
- return this.resultHandler(undefined);
2401
+ if (this._getState('VOID'))
2402
+ return this._resultHandler(undefined);
2600
2403
  if (!result)
2601
- return this.resultHandler(null);
2404
+ return this._resultHandler(null);
2602
2405
  const arrayId = [...Array(result)].map((_, i) => i + id);
2603
- const data = new Model().copyModel(this).bind(this.$pool.get()).whereIn('id', arrayId).get();
2406
+ const data = yield new Model()
2407
+ .copyModel(this, { select: true, limit: true })
2408
+ .bind(this.$pool.get())
2409
+ .whereIn('id', arrayId)
2410
+ .debug(this._getState('DEBUG'))
2411
+ .get();
2604
2412
  const resultData = data || [];
2605
- return this.resultHandler(resultData);
2413
+ this._observer(resultData, 'created');
2414
+ return this._resultHandler(resultData);
2606
2415
  });
2607
2416
  }
2608
2417
  _updateOrInsertModel() {
2609
2418
  return __awaiter(this, void 0, void 0, function* () {
2610
- this._assertError(!this.$state.get('WHERE'), "Can not update or insert [updateOrInsert] without where condition");
2611
- const clone = new Model().copyModel(this, { where: true }).bind(this.$pool.get());
2612
- const check = (yield clone.exists()) || false;
2419
+ this._assertError(!this._getState('WHERE'), "This method 'createOrUpdate' is require to use 'where'");
2420
+ const check = (yield new Model()
2421
+ .copyModel(this, { select: true, where: true, limit: true })
2422
+ .bind(this.$pool.get())
2423
+ .debug(this._getState('DEBUG'))
2424
+ .exists()) || false;
2613
2425
  switch (check) {
2614
2426
  case false: {
2615
- const [result, id] = yield this.actionStatement({
2616
- sql: this.$state.get('INSERT'),
2427
+ yield this._validateSchema(this._getState('DATA'), 'insert');
2428
+ const [result, id] = yield this._actionStatement({
2429
+ sql: this._queryBuilder().insert(),
2617
2430
  returnId: true
2618
2431
  });
2619
- if (this.$state.get('VOID') || !result)
2620
- return this.resultHandler(undefined);
2621
- const data = yield new Model().copyModel(this).bind(this.$pool.get()).where('id', id).first();
2622
- const resultData = data == null
2623
- ? null
2624
- : Object.assign(Object.assign({}, data), { $action: 'insert' });
2625
- return this.resultHandler(resultData);
2432
+ if (this._getState('VOID') || !result)
2433
+ return this._resultHandler(undefined);
2434
+ const data = yield new Model()
2435
+ .copyModel(this, { select: true })
2436
+ .bind(this.$pool.get())
2437
+ .where('id', id)
2438
+ .debug(this._getState('DEBUG'))
2439
+ .first();
2440
+ const resultData = data == null ? null : Object.assign(Object.assign({}, data), { $action: 'insert' });
2441
+ const r = this._resultHandler(resultData);
2442
+ this._observer(r, 'created');
2443
+ return r;
2626
2444
  }
2627
2445
  case true: {
2628
- const result = yield this.actionStatement({
2629
- sql: new Model().copyModel(this, { update: true, where: true }).toString()
2446
+ yield this._validateSchema(this._getState('DATA'), 'update');
2447
+ const result = yield this._actionStatement({
2448
+ sql: this._queryBuilder().update()
2630
2449
  });
2631
- if (this.$state.get('VOID') || !result)
2632
- return this.resultHandler(undefined);
2633
- const data = yield new Model().copyModel(this, { where: true }).bind(this.$pool.get()).get();
2450
+ if (this._getState('VOID') || !result)
2451
+ return this._resultHandler(undefined);
2452
+ const data = yield new Model()
2453
+ .copyModel(this, { where: true, select: true, limit: true })
2454
+ .bind(this.$pool.get())
2455
+ .debug(this._getState('DEBUG'))
2456
+ .get();
2634
2457
  if ((data === null || data === void 0 ? void 0 : data.length) > 1) {
2635
2458
  for (const v of data)
2636
2459
  v.$action = 'update';
2637
- return this.resultHandler(data || []);
2460
+ const r = this._resultHandler(data);
2461
+ this._observer(r, 'updated');
2462
+ return r;
2638
2463
  }
2639
2464
  const resultData = Object.assign(Object.assign({}, data === null || data === void 0 ? void 0 : data.shift()), { $action: 'update' }) || null;
2640
- return this.resultHandler(resultData);
2465
+ const r = this._resultHandler(resultData);
2466
+ this._observer(r, 'updated');
2467
+ return r;
2641
2468
  }
2642
2469
  }
2643
2470
  });
2644
2471
  }
2645
2472
  _insertOrSelectModel() {
2646
2473
  return __awaiter(this, void 0, void 0, function* () {
2647
- this._assertError(!this.$state.get('WHERE'), "Can not create or select [createOrSelect] without where condition");
2648
- const clone = new Model().copyModel(this, { where: true }).bind(this.$pool.get());
2649
- const check = (yield clone.exists()) || false;
2474
+ this._assertError(!this._getState('WHERE'), "This method 'createOrSelect' is require to use 'where'");
2475
+ const check = (yield new Model()
2476
+ .copyModel(this, { select: true, where: true, limit: true })
2477
+ .bind(this.$pool.get())
2478
+ .debug(this._getState('DEBUG'))
2479
+ .exists()) || false;
2650
2480
  switch (check) {
2651
2481
  case false: {
2652
- const [result, id] = yield this.actionStatement({
2653
- sql: String(this.$state.get('INSERT')),
2482
+ yield this._validateSchema(this._getState('DATA'), 'insert');
2483
+ const [result, id] = yield this._actionStatement({
2484
+ sql: this._queryBuilder().insert(),
2654
2485
  returnId: true
2655
2486
  });
2656
- if (this.$state.get('VOID') || !result)
2657
- return this.resultHandler(undefined);
2658
- const data = yield new Model().copyModel(this).bind(this.$pool.get()).where('id', id).first();
2487
+ if (this._getState('VOID') || !result)
2488
+ return this._resultHandler(undefined);
2489
+ const data = yield new Model()
2490
+ .copyModel(this, { select: true })
2491
+ .bind(this.$pool.get())
2492
+ .where('id', id)
2493
+ .debug(this._getState('DEBUG'))
2494
+ .first();
2659
2495
  const resultData = data == null
2660
2496
  ? null
2661
2497
  : Object.assign(Object.assign({}, data), { $action: 'insert' });
2662
- return this.resultHandler(resultData);
2498
+ const r = this._resultHandler(resultData);
2499
+ this._observer(r, 'created');
2500
+ return r;
2663
2501
  }
2664
2502
  case true: {
2665
- if (this.$state.get('VOID'))
2666
- return this.resultHandler(undefined);
2667
- const data = yield new Model().copyModel(this, { where: true }).bind(this.$pool.get()).get();
2503
+ if (this._getState('VOID'))
2504
+ return this._resultHandler(undefined);
2505
+ const data = yield new Model()
2506
+ .copyModel(this, { select: true, where: true, limit: true })
2507
+ .bind(this.$pool.get())
2508
+ .debug(this._getState('DEBUG'))
2509
+ .get();
2668
2510
  if ((data === null || data === void 0 ? void 0 : data.length) > 1) {
2669
2511
  for (const v of data)
2670
2512
  v.$action = 'select';
2671
- return this.resultHandler(data || []);
2513
+ return data;
2672
2514
  }
2673
2515
  const resultData = Object.assign(Object.assign({}, data === null || data === void 0 ? void 0 : data.shift()), { $action: 'select' }) || null;
2674
- return this.resultHandler(resultData);
2516
+ return this._resultHandler(resultData);
2675
2517
  }
2676
2518
  }
2677
2519
  });
2678
2520
  }
2679
2521
  _updateModel() {
2680
2522
  return __awaiter(this, void 0, void 0, function* () {
2681
- this._assertError(!String(this.$state.get('WHERE')), "can not update [ update ] without where condition");
2682
- const sql = this._buildQueryStatement();
2683
- const result = yield this.actionStatement({ sql });
2684
- if (this.$state.get('VOID') || !result || result == null)
2685
- return this.resultHandler(undefined);
2686
- const data = yield new Model().copyModel(this, { where: true }).bind(this.$pool.get()).get();
2523
+ this._assertError(!String(this._getState('WHERE')), "This method 'update' is require to use 'where'");
2524
+ yield this._validateSchema(this._getState('DATA'), 'update');
2525
+ const sql = this._queryBuilder().update();
2526
+ const result = yield this._actionStatement({ sql });
2527
+ if (this._getState('VOID') || !result || result == null)
2528
+ return this._resultHandler(undefined);
2529
+ const data = yield new Model()
2530
+ .copyModel(this, { where: true, select: true, limit: true, orderBy: true })
2531
+ .bind(this.$pool.get())
2532
+ .debug(this._getState('DEBUG'))
2533
+ .get();
2687
2534
  if ((data === null || data === void 0 ? void 0 : data.length) > 1) {
2688
- return this.resultHandler(data || []);
2535
+ const r = this._resultHandler(data);
2536
+ this._observer(r, 'updated');
2537
+ return r;
2689
2538
  }
2690
2539
  const resultData = (data === null || data === void 0 ? void 0 : data.shift()) || null;
2691
- return this.resultHandler(resultData);
2540
+ const r = this._resultHandler(resultData);
2541
+ this._observer(r, 'updated');
2542
+ return r;
2692
2543
  });
2693
2544
  }
2694
2545
  _assertError(condition = true, message = 'error') {
@@ -2699,38 +2550,15 @@ class Model extends AbstractModel_1.AbstractModel {
2699
2550
  throw new Error(message);
2700
2551
  return;
2701
2552
  }
2702
- _functionRelationName() {
2703
- const functionName = [...this.$logger.get()][this.$logger.get().length - 2];
2704
- return functionName.replace(/([A-Z])/g, (str) => `_${str.toLowerCase()}`);
2705
- }
2706
- _handleRelations(nameRelations) {
2707
- return nameRelations.map((name) => {
2708
- var _a, _b, _c;
2709
- const relation = (_a = this.$state.get('RELATION')) === null || _a === void 0 ? void 0 : _a.find((data) => data.name === name);
2710
- this._assertError(relation == null, `This Relation "${name}" not be register in Model "${(_b = this.constructor) === null || _b === void 0 ? void 0 : _b.name}"`);
2711
- const relationHasExists = (_c = Object.values(this.$constants('RELATIONSHIP'))) === null || _c === void 0 ? void 0 : _c.includes(relation.relation);
2712
- this._assertError(!relationHasExists, `Unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
2713
- if (relation.query == null)
2714
- relation.query = new relation.model();
2715
- return relation;
2716
- });
2717
- }
2718
- _handleRelationsQuery(nameRelation, relation) {
2719
- var _a;
2720
- this.$state.set('RELATION', [...this.$state.get('RELATION'), relation]);
2721
- this.with(nameRelation);
2722
- const r = this.$state.get('RELATIONS').find((data) => data.name === nameRelation);
2723
- this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
2724
- this._assertError(!Object.values(this.$constants('RELATIONSHIP')).includes(r.relation), `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
2725
- return r;
2726
- }
2727
2553
  _validateMethod(method) {
2728
2554
  const methodChangeStatements = [
2729
2555
  'insert',
2730
2556
  'create',
2731
2557
  'update',
2558
+ 'updateMany',
2732
2559
  'updateNotExists',
2733
2560
  'delete',
2561
+ 'deleteMany',
2734
2562
  'forceDelete',
2735
2563
  'restore',
2736
2564
  'faker',
@@ -2768,58 +2596,78 @@ class Model extends AbstractModel_1.AbstractModel {
2768
2596
  }
2769
2597
  }
2770
2598
  }
2771
- _checkSchemaOrNextError(e) {
2599
+ _checkSchemaOrNextError(e, retry = 1) {
2772
2600
  var _a, _b, _c, _d, _e;
2773
2601
  return __awaiter(this, void 0, void 0, function* () {
2774
2602
  try {
2775
- if (this.$state.get('RETRY_QUERIES') > 3)
2603
+ if (retry > 3 || this._getState('RETRY') > 3)
2776
2604
  throw e;
2777
- const schemaTable = this.$state.get('SCHEMA_TABLE');
2605
+ const schemaTable = this._getState('SCHEMA_TABLE');
2778
2606
  if (schemaTable == null)
2779
- throw e;
2607
+ return this._stoppedRetry(e);
2608
+ if (!(e instanceof Error))
2609
+ return this._stoppedRetry(e);
2780
2610
  const errorMessage = (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : '';
2781
2611
  if (errorMessage.toLocaleLowerCase().includes('unknown column')) {
2782
2612
  const pattern = /'([^']+)'/;
2783
- const column = errorMessage.match(pattern)
2784
- ? String(errorMessage.match(pattern)[0]).replace(/'/g, '').split('.').pop()
2613
+ const isPattern = errorMessage.match(pattern);
2614
+ const column = isPattern
2615
+ ? String(Array.isArray(isPattern) ? isPattern[0] : '').replace(/'/g, '').split('.').pop()
2785
2616
  : null;
2786
2617
  if (column == null)
2787
- throw e;
2618
+ return this._stoppedRetry(e);
2788
2619
  const type = (_c = (_b = schemaTable[column]) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : null;
2789
2620
  const attributes = (_e = (_d = schemaTable[column]) === null || _d === void 0 ? void 0 : _d.attributes) !== null && _e !== void 0 ? _e : null;
2790
2621
  if (type == null || attributes == null)
2791
- throw e;
2622
+ return this._stoppedRetry(e);
2792
2623
  const entries = Object.entries(schemaTable);
2793
2624
  const indexWithColumn = entries.findIndex(([key]) => key === column);
2794
2625
  const findAfterIndex = indexWithColumn ? entries[indexWithColumn - 1][0] : null;
2795
2626
  if (findAfterIndex == null)
2796
- throw e;
2627
+ return this._stoppedRetry(e);
2797
2628
  const sql = [
2798
2629
  `${this.$constants('ALTER_TABLE')}`,
2799
- `${this.$state.get('TABLE_NAME')}`,
2630
+ `${this._getState('TABLE_NAME')}`,
2800
2631
  `${this.$constants('ADD')}`,
2801
2632
  `\`${column}\` ${type} ${attributes.join(' ')}`,
2802
2633
  `${this.$constants('AFTER')}`,
2803
2634
  `\`${findAfterIndex !== null && findAfterIndex !== void 0 ? findAfterIndex : ''}\``
2804
2635
  ].join(' ');
2805
- yield this.queryStatement(sql);
2636
+ yield this._queryStatement(sql);
2806
2637
  return;
2807
2638
  }
2808
2639
  if (!errorMessage.toLocaleLowerCase().includes("doesn't exist"))
2809
- throw e;
2810
- const tableName = this.$state.get('TABLE_NAME');
2640
+ return this._stoppedRetry(e);
2641
+ const tableName = this._getState('TABLE_NAME');
2811
2642
  const sql = new Schema_1.Schema().createTable(tableName, schemaTable);
2812
- yield this.queryStatement(sql);
2813
- return;
2643
+ yield this._queryStatement(sql);
2814
2644
  }
2815
2645
  catch (e) {
2816
- throw e;
2646
+ if (retry > 3)
2647
+ throw e;
2648
+ yield this._checkSchemaOrNextError(e, retry + 1);
2817
2649
  }
2818
2650
  });
2819
2651
  }
2652
+ _stoppedRetry(e) {
2653
+ this._setState('RETRY', 3);
2654
+ throw e;
2655
+ }
2656
+ _observer(result, type) {
2657
+ if (this._getState('OBSERVER') == null)
2658
+ return;
2659
+ const observer = this._getState('OBSERVER');
2660
+ switch (type.toLocaleLowerCase()) {
2661
+ case 'created': return new observer().created(result);
2662
+ case 'updated': return new observer().updated(result);
2663
+ case 'deleted': return new observer().deleted(result);
2664
+ }
2665
+ return;
2666
+ }
2820
2667
  _initialModel() {
2821
2668
  this.$state = new StateHandler_1.StateHandler(this.$constants('MODEL'));
2822
2669
  this._makeTableName();
2670
+ this.$relation = new RelationHandler_1.RelationHandler(this);
2823
2671
  return this;
2824
2672
  }
2825
2673
  }