tspace-mysql 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -14
- package/dist/cli/generate/make.js +1 -1
- package/dist/cli/generate/model.d.ts +2 -0
- package/dist/cli/generate/model.js +30 -0
- package/dist/lib/connection/index.js +1 -1
- package/dist/lib/connection/options.js +3 -3
- package/dist/lib/constants/index.js +1 -0
- package/dist/lib/tspace/Database.js +14 -14
- package/dist/lib/tspace/Interface.d.ts +2 -0
- package/dist/lib/tspace/Model.d.ts +15 -5
- package/dist/lib/tspace/Model.js +150 -107
- package/dist/lib/utils/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,12 +45,13 @@ DB_USERNAME = root
|
|
|
45
45
|
DB_PASSWORD = password
|
|
46
46
|
DB_DATABASE = database
|
|
47
47
|
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
/**
|
|
49
|
+
* @default
|
|
50
|
+
* DB_CONNECTION_LIMIT = 10
|
|
51
|
+
* DB_CONNECTION_ERROR = true
|
|
52
|
+
* DB_QUEUE_LIMIT = 0
|
|
53
|
+
* DB_TIMEOUT = 60000
|
|
54
|
+
* DB_DATE_STRINGS = true
|
|
54
55
|
*/
|
|
55
56
|
|
|
56
57
|
```
|
|
@@ -212,7 +213,7 @@ const user = await new DB('users')
|
|
|
212
213
|
Running A Delete Query
|
|
213
214
|
```js
|
|
214
215
|
const deleted = await new DB('users').where('id',1).delete()
|
|
215
|
-
// deleted =>
|
|
216
|
+
// deleted => Boolean
|
|
216
217
|
```
|
|
217
218
|
## Database Transactions
|
|
218
219
|
|
|
@@ -300,7 +301,7 @@ Backup database, you may backup is this:
|
|
|
300
301
|
* @param conection defalut current connection
|
|
301
302
|
*/
|
|
302
303
|
const backup = await new DB().backup({
|
|
303
|
-
database: 'try-to-backup', // clone current database to this
|
|
304
|
+
database: 'try-to-backup', // clone current database to this database
|
|
304
305
|
connection ?: {
|
|
305
306
|
host: 'localhost',
|
|
306
307
|
port : 3306,
|
|
@@ -358,16 +359,31 @@ import { Model } from 'tspace-mysql'
|
|
|
358
359
|
class User extends Model {
|
|
359
360
|
constructor(){
|
|
360
361
|
super()
|
|
361
|
-
this.useTimestamp() /** created_at , updated_at
|
|
362
362
|
/**
|
|
363
363
|
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
364
|
+
* Assign setting global in your model
|
|
365
|
+
* @useMethod
|
|
366
|
+
*
|
|
367
|
+
* this.useDebug()
|
|
368
|
+
* this.usePrimaryKey('id')
|
|
366
369
|
* this.useTimestamp({
|
|
367
370
|
* createdAt : 'created_at',
|
|
368
371
|
* updatedAt : 'updated_at'
|
|
369
|
-
* })
|
|
370
|
-
|
|
372
|
+
* }) // runing a timestamp when insert or update
|
|
373
|
+
* this.useSoftDelete()
|
|
374
|
+
* this.useTable('users')
|
|
375
|
+
* this.useTableSingular() // 'user'
|
|
376
|
+
* this.useTablePlural() // 'users'
|
|
377
|
+
* this.usePattern('snake_case')
|
|
378
|
+
* this.useUUID('uuid') // => runing a uuid (universally unique identifier) when insert new data
|
|
379
|
+
* this.useRegistry()
|
|
380
|
+
* this.useSchema({
|
|
381
|
+
* id : Number,
|
|
382
|
+
* username : String
|
|
383
|
+
* created_at : Date,
|
|
384
|
+
* updated_at : Date,
|
|
385
|
+
* }) // validate type of schema when return result
|
|
386
|
+
*/
|
|
371
387
|
|
|
372
388
|
/*
|
|
373
389
|
* the "snake case", plural name of the class will be used as the table name
|
|
@@ -565,7 +581,7 @@ await new User().relations('posts')
|
|
|
565
581
|
.relationQuery('user', (query : User) => {
|
|
566
582
|
return query.relations('posts').relationQuery('posts',(query : Post)=> {
|
|
567
583
|
return query.relations('comments','user')
|
|
568
|
-
// relation n
|
|
584
|
+
// relation n, n, ...n
|
|
569
585
|
})
|
|
570
586
|
})
|
|
571
587
|
})
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const model_1 = __importDefault(require("
|
|
6
|
+
const model_1 = __importDefault(require("./model"));
|
|
7
7
|
const pluralize_1 = __importDefault(require("pluralize"));
|
|
8
8
|
const lib_1 = require("../../lib");
|
|
9
9
|
exports.default = (cmd) => {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const Model = (model, npm) => {
|
|
4
|
+
return `import { Model } from '${npm}'
|
|
5
|
+
class ${model} extends Model {
|
|
6
|
+
constructor(){
|
|
7
|
+
super()
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* Assign setting global in your model
|
|
11
|
+
* @useMethod
|
|
12
|
+
*
|
|
13
|
+
* this.useDebug() // => runing a uuid (universally unique identifier) when insert new data
|
|
14
|
+
* this.usePrimaryKey('id') // => runing a uuid (universally unique identifier) when insert new data
|
|
15
|
+
* this.useTimestamp({ createdAt : 'created_at' , updatedAt : 'updated_at' }) // runing a timestamp when insert or update
|
|
16
|
+
* this.useSoftDelete()
|
|
17
|
+
* this.useTable('users')
|
|
18
|
+
* this.useTableSingular() // 'user'
|
|
19
|
+
* this.useTablePlural() // 'users'
|
|
20
|
+
* this.usePattern('snake_case')
|
|
21
|
+
* this.useUUID('uuid')
|
|
22
|
+
* this.useRegistry()
|
|
23
|
+
*/
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export { ${model} }
|
|
27
|
+
export default ${model}
|
|
28
|
+
`;
|
|
29
|
+
};
|
|
30
|
+
exports.default = Model;
|
|
@@ -24,9 +24,9 @@ const env = {
|
|
|
24
24
|
USERNAME: process.env.DB_USERNAME || process.env.TSPACE_USERNAME,
|
|
25
25
|
PASSWORD: process.env.DB_PASSWORD || process.env.TSPACE_PASSWORD || '',
|
|
26
26
|
DATABASE: process.env.DB_DATABASE || process.env.TSPACE_DATABASE,
|
|
27
|
-
CONNECTION_LIMIT: process.env.DB_CONNECTION_LIMIT || process.env.TSPACE_CONNECTION_LIMIT ||
|
|
28
|
-
QUEUE_LIMIT: process.env.DB_QUEUE_LIMIT || process.env.TSPACE_QUEUE_LIMIT ||
|
|
29
|
-
TIMEOUT: process.env.DB_TIMEOUT || process.env.TSPACE_TIMEOUT || 1000 *
|
|
27
|
+
CONNECTION_LIMIT: process.env.DB_CONNECTION_LIMIT || process.env.TSPACE_CONNECTION_LIMIT || 10,
|
|
28
|
+
QUEUE_LIMIT: process.env.DB_QUEUE_LIMIT || process.env.TSPACE_QUEUE_LIMIT || 0,
|
|
29
|
+
TIMEOUT: process.env.DB_TIMEOUT || process.env.TSPACE_TIMEOUT || 1000 * 60,
|
|
30
30
|
CHARSET: process.env.DB_CHARSET || process.env.TSPACE_CHARSET || 'utf8mb4',
|
|
31
31
|
CONNECTION_ERROR: process.env.DB_CONNECTION_ERROR || process.env.TSPACE_CONNECTION_ERROR || true,
|
|
32
32
|
WAIT_FOR_CONNECTIONS: process.env.DB_WAIT_FOR_CONNECTIONS || process.env.TSPACE_WAIT_FOR_CONNECTIONS || true,
|
|
@@ -1283,14 +1283,14 @@ class Database extends AbstractDatabase_1.default {
|
|
|
1283
1283
|
throw new Error(`can't find property '${pluck}' of result`);
|
|
1284
1284
|
const r = newData[pluck] || null;
|
|
1285
1285
|
const hook = this.$state.get('HOOK');
|
|
1286
|
-
|
|
1287
|
-
yield hook(r);
|
|
1286
|
+
for (let i in hook)
|
|
1287
|
+
yield hook[i](r);
|
|
1288
1288
|
return r;
|
|
1289
1289
|
}
|
|
1290
1290
|
const r = (result === null || result === void 0 ? void 0 : result.shift()) || null;
|
|
1291
1291
|
const hook = this.$state.get('HOOK');
|
|
1292
|
-
|
|
1293
|
-
yield hook(r);
|
|
1292
|
+
for (let i in hook)
|
|
1293
|
+
yield hook[i](r);
|
|
1294
1294
|
return r;
|
|
1295
1295
|
});
|
|
1296
1296
|
}
|
|
@@ -1336,8 +1336,8 @@ class Database extends AbstractDatabase_1.default {
|
|
|
1336
1336
|
throw Object.assign({ message }, options);
|
|
1337
1337
|
}
|
|
1338
1338
|
const hook = this.$state.get('HOOK');
|
|
1339
|
-
|
|
1340
|
-
yield hook(data);
|
|
1339
|
+
for (let i in hook)
|
|
1340
|
+
yield hook[i](data);
|
|
1341
1341
|
return data;
|
|
1342
1342
|
}
|
|
1343
1343
|
const data = (result === null || result === void 0 ? void 0 : result.shift()) || null;
|
|
@@ -1348,8 +1348,8 @@ class Database extends AbstractDatabase_1.default {
|
|
|
1348
1348
|
throw Object.assign({ message }, options);
|
|
1349
1349
|
}
|
|
1350
1350
|
const hook = this.$state.get('HOOK');
|
|
1351
|
-
|
|
1352
|
-
yield hook(data);
|
|
1351
|
+
for (let i in hook)
|
|
1352
|
+
yield hook[i](data);
|
|
1353
1353
|
return data;
|
|
1354
1354
|
});
|
|
1355
1355
|
}
|
|
@@ -1386,8 +1386,8 @@ class Database extends AbstractDatabase_1.default {
|
|
|
1386
1386
|
return resultArray;
|
|
1387
1387
|
}, []);
|
|
1388
1388
|
const hook = this.$state.get('HOOK');
|
|
1389
|
-
|
|
1390
|
-
yield hook(data || []);
|
|
1389
|
+
for (let i in hook)
|
|
1390
|
+
yield hook[i](data || []);
|
|
1391
1391
|
return data || [];
|
|
1392
1392
|
}
|
|
1393
1393
|
if (this.$state.get('PLUCK')) {
|
|
@@ -1397,13 +1397,13 @@ class Database extends AbstractDatabase_1.default {
|
|
|
1397
1397
|
throw new Error(`can't find property '${pluck}' of result`);
|
|
1398
1398
|
}
|
|
1399
1399
|
const hook = this.$state.get('HOOK');
|
|
1400
|
-
|
|
1401
|
-
yield hook(newData || []);
|
|
1400
|
+
for (let i in hook)
|
|
1401
|
+
yield hook[i](newData || []);
|
|
1402
1402
|
return newData || [];
|
|
1403
1403
|
}
|
|
1404
1404
|
const hook = this.$state.get('HOOK');
|
|
1405
|
-
|
|
1406
|
-
yield hook(result || []);
|
|
1405
|
+
for (let i in hook)
|
|
1406
|
+
yield hook[i](result || []);
|
|
1407
1407
|
return result || [];
|
|
1408
1408
|
});
|
|
1409
1409
|
}
|
|
@@ -5,6 +5,7 @@ export interface Relation {
|
|
|
5
5
|
localKey?: string | undefined;
|
|
6
6
|
foreignKey?: string | undefined;
|
|
7
7
|
freezeTable?: string | undefined;
|
|
8
|
+
pivot?: string | undefined;
|
|
8
9
|
query?: any | undefined;
|
|
9
10
|
relation?: Object | undefined;
|
|
10
11
|
}
|
|
@@ -15,6 +16,7 @@ export interface RelationQuery {
|
|
|
15
16
|
localKey?: string | undefined;
|
|
16
17
|
foreignKey?: string | undefined;
|
|
17
18
|
freezeTable?: string | undefined;
|
|
19
|
+
pivot?: string | undefined;
|
|
18
20
|
query?: any | undefined;
|
|
19
21
|
relation?: Object | undefined;
|
|
20
22
|
}
|
|
@@ -15,10 +15,10 @@ declare class Model extends AbstractModel {
|
|
|
15
15
|
*/
|
|
16
16
|
protected useRegistry(): this;
|
|
17
17
|
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
*
|
|
19
|
+
* Assign primary column in model
|
|
20
|
+
* @return {this} this
|
|
21
|
+
*/
|
|
22
22
|
protected usePrimaryKey(primary: string): this;
|
|
23
23
|
/**
|
|
24
24
|
* Assign generate uuid when creating in model
|
|
@@ -77,6 +77,15 @@ declare class Model extends AbstractModel {
|
|
|
77
77
|
* @return {this} this
|
|
78
78
|
*/
|
|
79
79
|
protected useTablePlural(): this;
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* Assign schema column in model
|
|
83
|
+
* @param {Object<Function>} schema type String Number and Date
|
|
84
|
+
* @return {this} this
|
|
85
|
+
*/
|
|
86
|
+
protected useSchema(schema: {
|
|
87
|
+
[key: string]: Function;
|
|
88
|
+
}): this;
|
|
80
89
|
/**
|
|
81
90
|
* Build method for relation in model
|
|
82
91
|
* @param {string} name name relation registry in your model
|
|
@@ -540,6 +549,7 @@ declare class Model extends AbstractModel {
|
|
|
540
549
|
* @return {this} this this
|
|
541
550
|
*/
|
|
542
551
|
createNotExists(data: object): this;
|
|
552
|
+
getSchema(): Promise<any>;
|
|
543
553
|
/**
|
|
544
554
|
*
|
|
545
555
|
* @override Method
|
|
@@ -566,13 +576,13 @@ declare class Model extends AbstractModel {
|
|
|
566
576
|
private _handleSoftDelete;
|
|
567
577
|
private _buildQueryModel;
|
|
568
578
|
private _showOnly;
|
|
579
|
+
private _validateSchema;
|
|
569
580
|
private _execute;
|
|
570
581
|
private _executeGroup;
|
|
571
582
|
private _relationMapData;
|
|
572
583
|
private _handleRelationsExists;
|
|
573
584
|
private _queryRelationsExists;
|
|
574
585
|
private _relation;
|
|
575
|
-
private _handleBelongsToMany;
|
|
576
586
|
private _belongsToMany;
|
|
577
587
|
private _pagination;
|
|
578
588
|
private _result;
|
package/dist/lib/tspace/Model.js
CHANGED
|
@@ -37,8 +37,7 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
37
37
|
* define for initialize of models
|
|
38
38
|
* @return {void} void
|
|
39
39
|
*/
|
|
40
|
-
define() {
|
|
41
|
-
}
|
|
40
|
+
define() { }
|
|
42
41
|
/**
|
|
43
42
|
*
|
|
44
43
|
* Assign function callback in model
|
|
@@ -49,10 +48,10 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
49
48
|
return this;
|
|
50
49
|
}
|
|
51
50
|
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
*
|
|
52
|
+
* Assign primary column in model
|
|
53
|
+
* @return {this} this
|
|
54
|
+
*/
|
|
56
55
|
usePrimaryKey(primary) {
|
|
57
56
|
this.$state.set('PRIMARY_KEY', primary);
|
|
58
57
|
return this;
|
|
@@ -154,6 +153,16 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
154
153
|
this.$state.set('TABLE_NAME', `\`${pluralize_1.default.plural(table)}\``);
|
|
155
154
|
return this;
|
|
156
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
*
|
|
158
|
+
* Assign schema column in model
|
|
159
|
+
* @param {Object<Function>} schema type String Number and Date
|
|
160
|
+
* @return {this} this
|
|
161
|
+
*/
|
|
162
|
+
useSchema(schema) {
|
|
163
|
+
this.$state.set('SCHEMA', schema);
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
157
166
|
/**
|
|
158
167
|
* Build method for relation in model
|
|
159
168
|
* @param {string} name name relation registry in your model
|
|
@@ -1307,6 +1316,54 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1307
1316
|
this.$state.set('SAVE', 'INSERT_NOT_EXISTS');
|
|
1308
1317
|
return this;
|
|
1309
1318
|
}
|
|
1319
|
+
getSchema() {
|
|
1320
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1321
|
+
const sql = [
|
|
1322
|
+
`${this.$constants('SHOW')}`,
|
|
1323
|
+
`${this.$constants('COLUMNS')}`,
|
|
1324
|
+
`${this.$constants('FROM')}`,
|
|
1325
|
+
`\`${this.$state.get('TABLE_NAME').replace(/\`/g, '')}\``
|
|
1326
|
+
].join(' ');
|
|
1327
|
+
const raw = yield this.queryStatement(sql);
|
|
1328
|
+
const schemas = raw.map((r) => {
|
|
1329
|
+
let schema = { [r.Field]: String };
|
|
1330
|
+
const numberLists = [
|
|
1331
|
+
'tinyint',
|
|
1332
|
+
'smallint',
|
|
1333
|
+
'mediumint',
|
|
1334
|
+
'int',
|
|
1335
|
+
'bigint',
|
|
1336
|
+
'float',
|
|
1337
|
+
'double',
|
|
1338
|
+
'decimal',
|
|
1339
|
+
'real',
|
|
1340
|
+
'bit',
|
|
1341
|
+
'boolean',
|
|
1342
|
+
'serial'
|
|
1343
|
+
];
|
|
1344
|
+
const dateAndTimeLists = [
|
|
1345
|
+
'date',
|
|
1346
|
+
'datetime',
|
|
1347
|
+
'time',
|
|
1348
|
+
'timestamp',
|
|
1349
|
+
'year'
|
|
1350
|
+
];
|
|
1351
|
+
if (numberLists.includes(r.Type)) {
|
|
1352
|
+
schema = {
|
|
1353
|
+
[r.Field]: Number
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
if (dateAndTimeLists.includes(r.Type)) {
|
|
1357
|
+
schema = {
|
|
1358
|
+
[r.Field]: Date
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
return schema;
|
|
1362
|
+
});
|
|
1363
|
+
const result = Object.assign({}, ...schemas);
|
|
1364
|
+
return result;
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1310
1367
|
/**
|
|
1311
1368
|
*
|
|
1312
1369
|
* @override Method
|
|
@@ -1314,6 +1371,7 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1314
1371
|
*/
|
|
1315
1372
|
save() {
|
|
1316
1373
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1374
|
+
this._validateMethod('save');
|
|
1317
1375
|
const attributes = this.$attributes;
|
|
1318
1376
|
if (attributes != null) {
|
|
1319
1377
|
while (true) {
|
|
@@ -1418,12 +1476,13 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1418
1476
|
return (_a = this.$state.get('TABLE_NAME')) === null || _a === void 0 ? void 0 : _a.replace(/`/g, '');
|
|
1419
1477
|
}
|
|
1420
1478
|
_valueInRelation(relationModel) {
|
|
1421
|
-
var _a, _b;
|
|
1479
|
+
var _a, _b, _c, _d;
|
|
1422
1480
|
const relation = relationModel.relation;
|
|
1423
1481
|
const model = (_a = relationModel.model) === null || _a === void 0 ? void 0 : _a.name;
|
|
1424
1482
|
const table = relationModel.freezeTable
|
|
1425
1483
|
? relationModel.freezeTable
|
|
1426
1484
|
: (_b = relationModel.query) === null || _b === void 0 ? void 0 : _b._tableName();
|
|
1485
|
+
let pivot = null;
|
|
1427
1486
|
const name = relationModel.name;
|
|
1428
1487
|
const as = relationModel.as;
|
|
1429
1488
|
this._assertError(!model || model == null, 'not found model');
|
|
@@ -1459,8 +1518,12 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1459
1518
|
`${this.$state.get('PRIMARY_KEY')}`
|
|
1460
1519
|
].join('_'));
|
|
1461
1520
|
foreignKey = 'id';
|
|
1521
|
+
pivot = (_c = relationModel.pivot) !== null && _c !== void 0 ? _c : this._valuePattern([
|
|
1522
|
+
pluralize_1.default.singular(this === null || this === void 0 ? void 0 : this._tableName()),
|
|
1523
|
+
pluralize_1.default.singular((_d = relationModel.query) === null || _d === void 0 ? void 0 : _d._tableName())
|
|
1524
|
+
].sort().join('_'));
|
|
1462
1525
|
}
|
|
1463
|
-
return { name, as, relation, table, localKey, foreignKey, model };
|
|
1526
|
+
return { name, as, relation, table, localKey, foreignKey, model, pivot };
|
|
1464
1527
|
}
|
|
1465
1528
|
_handleSoftDelete() {
|
|
1466
1529
|
if (this.$state.get('SOFT_DELETE')) {
|
|
@@ -1527,9 +1590,36 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1527
1590
|
});
|
|
1528
1591
|
return result;
|
|
1529
1592
|
}
|
|
1593
|
+
_validateSchema(results) {
|
|
1594
|
+
const schema = this.$state.get('SCHEMA');
|
|
1595
|
+
if (schema == null)
|
|
1596
|
+
return;
|
|
1597
|
+
if (!results.length)
|
|
1598
|
+
return;
|
|
1599
|
+
const typeOf = (data) => Object.prototype.toString.apply(data).slice(8, -1).toLocaleLowerCase();
|
|
1600
|
+
for (const result of results) {
|
|
1601
|
+
for (const key in result) {
|
|
1602
|
+
const s = schema[key];
|
|
1603
|
+
if (s == null)
|
|
1604
|
+
this._assertError(`not found this column [${key}] in schema`);
|
|
1605
|
+
const regexDate = /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/;
|
|
1606
|
+
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]/;
|
|
1607
|
+
if (regexDate.test(result[key]) || regexDateTime.test(result[key])) {
|
|
1608
|
+
if (typeOf(new Date(result[key])) === typeOf(new s()))
|
|
1609
|
+
continue;
|
|
1610
|
+
this._assertError(`this column [${key}] is invalid schema field type`);
|
|
1611
|
+
}
|
|
1612
|
+
if (typeOf(result[key]) === typeOf(new s()))
|
|
1613
|
+
continue;
|
|
1614
|
+
this._assertError(`this column [${key}] is invalid schema field type`);
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
return this;
|
|
1618
|
+
}
|
|
1530
1619
|
_execute({ sql, type, message, options }) {
|
|
1531
1620
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1532
1621
|
let result = yield this.queryStatement(sql);
|
|
1622
|
+
this._validateSchema(result);
|
|
1533
1623
|
if (!result.length)
|
|
1534
1624
|
return this._returnEmpty(type, result, message, options);
|
|
1535
1625
|
const relations = this.$state.get('WITH');
|
|
@@ -1629,7 +1719,7 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1629
1719
|
const relation = relations[index];
|
|
1630
1720
|
if (!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length))
|
|
1631
1721
|
continue;
|
|
1632
|
-
const { localKey, foreignKey } = this._valueInRelation(relation);
|
|
1722
|
+
const { localKey, foreignKey, pivot } = this._valueInRelation(relation);
|
|
1633
1723
|
const query = relation.query;
|
|
1634
1724
|
this._assertError(query == null, `unknown callback query in [relation : '${relation.name}']`);
|
|
1635
1725
|
let clone = new Model().clone(query);
|
|
@@ -1641,6 +1731,21 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1641
1731
|
clone.whereExists(sql);
|
|
1642
1732
|
}
|
|
1643
1733
|
}
|
|
1734
|
+
if (relation.relation === this.$constants('RELATIONSHIP').belongsToMany) {
|
|
1735
|
+
const sql = clone
|
|
1736
|
+
.bind(this.$pool.get())
|
|
1737
|
+
.whereReference(`\`${this._tableName()}\`.\`${localKey}\``, `\`${query._tableName()}\`.\`${foreignKey}\``)
|
|
1738
|
+
.toString();
|
|
1739
|
+
this.whereExists(sql);
|
|
1740
|
+
const thisPivot = new Model();
|
|
1741
|
+
thisPivot.$state.set('TABLE_NAME', `\`${pivot}\``);
|
|
1742
|
+
const sqlPivot = thisPivot
|
|
1743
|
+
.bind(this.$pool.get())
|
|
1744
|
+
.whereReference(`\`${this._tableName()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${this._valuePattern([pluralize_1.default.singular(this._tableName()), foreignKey].join("_"))}\``)
|
|
1745
|
+
.toString();
|
|
1746
|
+
this.whereExists(sqlPivot);
|
|
1747
|
+
continue;
|
|
1748
|
+
}
|
|
1644
1749
|
const sql = clone
|
|
1645
1750
|
.bind(this.$pool.get())
|
|
1646
1751
|
.whereReference(`\`${this._tableName()}\`.\`${localKey}\``, `\`${query._tableName()}\`.\`${foreignKey}\``)
|
|
@@ -1676,66 +1781,15 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1676
1781
|
return dataFromRelation;
|
|
1677
1782
|
});
|
|
1678
1783
|
}
|
|
1679
|
-
|
|
1784
|
+
_belongsToMany(dataFromParent, relation) {
|
|
1785
|
+
var _a;
|
|
1680
1786
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
const localKeyId = dataFromParent.map((parent) => {
|
|
1684
|
-
const data = parent[localKey];
|
|
1685
|
-
if (!parent.hasOwnProperty(localKey)) {
|
|
1686
|
-
this._assertError(data == null, "unknown relationship without primary or foreign key");
|
|
1687
|
-
}
|
|
1688
|
-
return data;
|
|
1689
|
-
}).filter((data) => data != null);
|
|
1690
|
-
const dataPerentId = Array.from(new Set(localKeyId)).join(',') || [];
|
|
1691
|
-
if (!dataPerentId.length && this.$state.get('WITH_EXISTS'))
|
|
1692
|
-
return [];
|
|
1693
|
-
const modelOther = new relation.model();
|
|
1694
|
-
const other = this._classToTableName(modelOther.constructor.name, { singular: true });
|
|
1695
|
-
const otherlocalKey = 'id';
|
|
1696
|
-
const otherforeignKey = this._valuePattern(`${other}Id`);
|
|
1697
|
-
const sqldataChilds = [
|
|
1698
|
-
`${this.$constants('SELECT')}`,
|
|
1699
|
-
`*`,
|
|
1700
|
-
`${this.$constants('FROM')}`,
|
|
1701
|
-
`${pivotTable}`,
|
|
1702
|
-
`${this.$constants('WHERE')}`,
|
|
1703
|
-
`${otherforeignKey} ${this.$constants('IN')} (${dataPerentId})`
|
|
1704
|
-
].join(' ');
|
|
1705
|
-
let dataChilds = yield this.queryStatement(sqldataChilds);
|
|
1706
|
-
const otherId = dataChilds.map((sub) => sub[otherforeignKey]).filter((data) => data != null);
|
|
1707
|
-
const otherArrId = Array.from(new Set(otherId)) || [];
|
|
1708
|
-
const otherdataChilds = yield this.queryStatement(modelOther
|
|
1709
|
-
.bind(this.$pool.get())
|
|
1710
|
-
.whereIn(otherlocalKey, otherArrId)
|
|
1711
|
-
.debug(this.$state.get('DEBUG'))
|
|
1712
|
-
.toString());
|
|
1713
|
-
dataChilds.forEach((sub) => {
|
|
1714
|
-
sub[other] = [];
|
|
1715
|
-
otherdataChilds.forEach((otherSub) => {
|
|
1716
|
-
if (otherSub[otherlocalKey] === sub[otherforeignKey]) {
|
|
1717
|
-
sub[other] = otherSub;
|
|
1718
|
-
}
|
|
1719
|
-
});
|
|
1720
|
-
});
|
|
1721
|
-
dataFromParent.forEach((dataPerent) => {
|
|
1722
|
-
if (dataPerent[name] == null)
|
|
1723
|
-
dataPerent[name] = [];
|
|
1724
|
-
dataChilds.forEach((sub) => {
|
|
1725
|
-
if (sub[localKey] === dataPerent[otherforeignKey]) {
|
|
1726
|
-
dataPerent[name].push(sub);
|
|
1727
|
-
}
|
|
1728
|
-
});
|
|
1729
|
-
});
|
|
1730
|
-
if (this.$state.get('HIDDEN').length)
|
|
1731
|
-
this._hiddenColumnModel(dataFromParent);
|
|
1732
|
-
return dataFromParent;
|
|
1733
|
-
}
|
|
1734
|
-
let { name, localKey, foreignKey } = this._valueInRelation(relation);
|
|
1787
|
+
const { name, localKey, foreignKey, pivot } = this._valueInRelation(relation);
|
|
1788
|
+
const pivotTable = String(((_a = relation.pivot) !== null && _a !== void 0 ? _a : pivot));
|
|
1735
1789
|
const localKeyId = dataFromParent.map((parent) => {
|
|
1736
|
-
const data = parent[
|
|
1737
|
-
if (!parent.hasOwnProperty(
|
|
1738
|
-
this._assertError(data == null,
|
|
1790
|
+
const data = parent[foreignKey];
|
|
1791
|
+
if (!parent.hasOwnProperty(foreignKey)) {
|
|
1792
|
+
this._assertError(data == null, `unknown relationship without primary or foreign key in relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
|
|
1739
1793
|
}
|
|
1740
1794
|
return data;
|
|
1741
1795
|
}).filter((data) => data != null);
|
|
@@ -1746,13 +1800,14 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1746
1800
|
const other = this._classToTableName(modelOther.constructor.name, { singular: true });
|
|
1747
1801
|
const otherlocalKey = 'id';
|
|
1748
1802
|
const otherforeignKey = this._valuePattern(`${other}Id`);
|
|
1803
|
+
const localKeyPivotTable = this._valuePattern([pluralize_1.default.singular(this._tableName()), foreignKey].join("_"));
|
|
1749
1804
|
const sqldataChilds = [
|
|
1750
1805
|
`${this.$constants('SELECT')}`,
|
|
1751
1806
|
`*`,
|
|
1752
1807
|
`${this.$constants('FROM')}`,
|
|
1753
1808
|
`${pivotTable}`,
|
|
1754
1809
|
`${this.$constants('WHERE')}`,
|
|
1755
|
-
`${
|
|
1810
|
+
`${localKeyPivotTable} ${this.$constants('IN')} (${dataPerentId})`
|
|
1756
1811
|
].join(' ');
|
|
1757
1812
|
let dataChilds = yield this.queryStatement(sqldataChilds);
|
|
1758
1813
|
const otherId = dataChilds.map((sub) => sub[otherforeignKey]).filter((data) => data != null);
|
|
@@ -1763,7 +1818,6 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1763
1818
|
.debug(this.$state.get('DEBUG'))
|
|
1764
1819
|
.toString());
|
|
1765
1820
|
dataChilds.forEach((sub) => {
|
|
1766
|
-
sub[other] = [];
|
|
1767
1821
|
otherdataChilds.forEach((otherSub) => {
|
|
1768
1822
|
if (otherSub[otherlocalKey] === sub[otherforeignKey]) {
|
|
1769
1823
|
sub[other] = otherSub;
|
|
@@ -1774,7 +1828,7 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1774
1828
|
if (dataPerent[name] == null)
|
|
1775
1829
|
dataPerent[name] = [];
|
|
1776
1830
|
dataChilds.forEach((sub) => {
|
|
1777
|
-
if (sub[
|
|
1831
|
+
if (sub[localKeyPivotTable] === dataPerent[foreignKey]) {
|
|
1778
1832
|
dataPerent[name].push(sub);
|
|
1779
1833
|
}
|
|
1780
1834
|
});
|
|
@@ -1784,27 +1838,6 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1784
1838
|
return dataFromParent;
|
|
1785
1839
|
});
|
|
1786
1840
|
}
|
|
1787
|
-
_belongsToMany(dataFromParent, relation) {
|
|
1788
|
-
var _a, _b;
|
|
1789
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1790
|
-
const local = this._classToTableName(this.constructor.name, { singular: true });
|
|
1791
|
-
const modelOther = new relation.model();
|
|
1792
|
-
const other = this._classToTableName(modelOther.constructor.name, { singular: true });
|
|
1793
|
-
try {
|
|
1794
|
-
const pivotTable = (_a = relation.freezeTable) !== null && _a !== void 0 ? _a : `${local}_${other}`;
|
|
1795
|
-
return yield this._handleBelongsToMany(dataFromParent, relation, pivotTable);
|
|
1796
|
-
}
|
|
1797
|
-
catch (err) {
|
|
1798
|
-
try {
|
|
1799
|
-
const pivotTable = (_b = relation.freezeTable) !== null && _b !== void 0 ? _b : `${other}_${local}`;
|
|
1800
|
-
return yield this._handleBelongsToMany(dataFromParent, relation, pivotTable);
|
|
1801
|
-
}
|
|
1802
|
-
catch (e) {
|
|
1803
|
-
throw new Error(err.message);
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
1841
|
_pagination(data) {
|
|
1809
1842
|
var _a, _b;
|
|
1810
1843
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1896,16 +1929,14 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1896
1929
|
if (this._isPatternSnakeCase()) {
|
|
1897
1930
|
const empty = this.$utils.snakeCase(this._result(emptyData));
|
|
1898
1931
|
const hook = this.$state.get('HOOK');
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
yield hook[i](empty);
|
|
1932
|
+
for (let i in hook)
|
|
1933
|
+
yield hook[i](empty);
|
|
1902
1934
|
return empty;
|
|
1903
1935
|
}
|
|
1904
1936
|
const empty = this._result(emptyData);
|
|
1905
1937
|
const hook = this.$state.get('HOOK');
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
yield hook[i](empty);
|
|
1938
|
+
for (let i in hook)
|
|
1939
|
+
yield hook[i](empty);
|
|
1909
1940
|
return empty;
|
|
1910
1941
|
});
|
|
1911
1942
|
}
|
|
@@ -1980,9 +2011,8 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
1980
2011
|
}
|
|
1981
2012
|
}
|
|
1982
2013
|
const hook = this.$state.get('HOOK');
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
yield hook[i](result);
|
|
2014
|
+
for (let i in hook)
|
|
2015
|
+
yield hook[i](result);
|
|
1986
2016
|
return result;
|
|
1987
2017
|
});
|
|
1988
2018
|
}
|
|
@@ -2222,15 +2252,13 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
2222
2252
|
const result = (data === null || data === void 0 ? void 0 : data.shift()) || null;
|
|
2223
2253
|
this.$state.set('RESULT', result);
|
|
2224
2254
|
const hook = this.$state.get('HOOK');
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
yield hook[i](result);
|
|
2255
|
+
for (let i in hook)
|
|
2256
|
+
yield hook[i](result);
|
|
2228
2257
|
return result;
|
|
2229
2258
|
}
|
|
2230
2259
|
const hook = this.$state.get('HOOK');
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
yield hook[i](result || []);
|
|
2260
|
+
for (let i in hook)
|
|
2261
|
+
yield hook[i](result || []);
|
|
2234
2262
|
return null;
|
|
2235
2263
|
});
|
|
2236
2264
|
}
|
|
@@ -2373,12 +2401,27 @@ class Model extends AbstractModel_1.AbstractModel {
|
|
|
2373
2401
|
'updateOrCreate',
|
|
2374
2402
|
'updateOrInsert',
|
|
2375
2403
|
'insertOrUpdate',
|
|
2376
|
-
'update'
|
|
2404
|
+
'update',
|
|
2405
|
+
'delete'
|
|
2377
2406
|
];
|
|
2378
2407
|
const findMethodNotAllowed = methodCallings.find((methodCalling) => methodsNotAllowed.includes(methodCalling));
|
|
2379
2408
|
this._assertError(methodCallings.some((methodCalling) => methodsNotAllowed.includes(methodCalling)), `this method ${method} can't using method : [ ${findMethodNotAllowed} ]`);
|
|
2380
2409
|
break;
|
|
2381
2410
|
}
|
|
2411
|
+
case 'save': {
|
|
2412
|
+
const methodCallings = this.$logger.get();
|
|
2413
|
+
const methodsSomeAllowed = [
|
|
2414
|
+
'create',
|
|
2415
|
+
'createNotExists',
|
|
2416
|
+
'updateOrCreate',
|
|
2417
|
+
'updateOrInsert',
|
|
2418
|
+
'insertOrUpdate',
|
|
2419
|
+
'update',
|
|
2420
|
+
'delete'
|
|
2421
|
+
];
|
|
2422
|
+
this._assertError(!methodCallings.some((methodCalling) => methodsSomeAllowed.includes(methodCalling)), `this ${method} method need some : [ ${methodsSomeAllowed.join(', ')} ] methods`);
|
|
2423
|
+
break;
|
|
2424
|
+
}
|
|
2382
2425
|
}
|
|
2383
2426
|
}
|
|
2384
2427
|
_initialModel() {
|
package/dist/lib/utils/index.js
CHANGED
|
@@ -123,7 +123,7 @@ const camelCase = (obj) => {
|
|
|
123
123
|
const consoleDebug = (debug) => {
|
|
124
124
|
if (debug == null)
|
|
125
125
|
return;
|
|
126
|
-
console.log(
|
|
126
|
+
console.log(`\n\x1b[33m${debug.replace(/(\r\n|\n|\r|\t)/gm, "").trim()};\x1b[0m`);
|
|
127
127
|
};
|
|
128
128
|
const faker = (value) => {
|
|
129
129
|
if (!value.search('timestamp'))
|