beech-api 3.8.0 → 3.9.0-beta.9-rc
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 +551 -146
- package/package.json +13 -12
- package/packages/cli/bin/beech-app.js +4 -4
- package/packages/cli/bin/beech-service.js +62 -25
- package/packages/cli/core/auth/Credentials.js +115 -88
- package/packages/cli/core/auth/Passport.js +111 -39
- package/packages/cli/core/configure/passport.config.js +1 -1
- package/packages/cli/core/databases/mysql.js +1 -1
- package/packages/cli/core/databases/sequelize.js +15 -6
- package/packages/cli/core/databases/test.js +125 -39
- package/packages/cli/core/generator/_models +3 -26
- package/packages/cli/core/generator/_models_basic +0 -9
- package/packages/cli/core/generator/_package +6 -7
- package/packages/cli/core/generator/_scheduler +16 -6
- package/packages/cli/core/generator/index.js +277 -23
- package/packages/cli/core/helpers/2fa.js +22 -1
- package/packages/cli/core/helpers/math.js +14 -2
- package/packages/cli/core/helpers/poolEntity.js +70 -26
- package/packages/cli/core/index.js +88 -10
- package/packages/cli/core/middleware/express/duplicateRequest.js +10 -6
- package/packages/cli/core/middleware/express/jwtCheckAllow.js +52 -34
- package/packages/cli/core/middleware/express/rateLimit.js +14 -2
- package/packages/cli/core/middleware/origin/guard/advance.js +5 -4
- package/packages/cli/core/services/http.express.js +49 -9
- package/packages/cli/core/test/check-node.js +21 -0
- package/packages/lib/src/endpoint.js +639 -286
- package/packages/lib/src/schema.js +4 -1
|
@@ -27,7 +27,7 @@ connectInProcess = async (database_config, headDbShow, cb) => {
|
|
|
27
27
|
// check hash ?
|
|
28
28
|
if(val.username && val.password) {
|
|
29
29
|
if(val.username.length < 55 || val.password < 55) {
|
|
30
|
-
return cb("Error:
|
|
30
|
+
return cb("Error: Incorrect Hash access for connect to database.\n", null);
|
|
31
31
|
}
|
|
32
32
|
let accessDb = [];
|
|
33
33
|
[val.username, val.password].map((e, k) => {
|
|
@@ -102,7 +102,7 @@ connectInProcess = async (database_config, headDbShow, cb) => {
|
|
|
102
102
|
freezeTableName: ((val.define) ? ((val.define.freezeTableName === false) ? val.define.freezeTableName : true) : true),
|
|
103
103
|
charset: ((val.define) ? ((val.define.charset) ? val.define.charset : "utf8") : "utf8"),
|
|
104
104
|
dialectOptions: {
|
|
105
|
-
collate: ((val.define) ? ((val.define.dialectOptions) ? ((val.define.dialectOptions.
|
|
105
|
+
collate: ((val.define) ? ((val.define.dialectOptions) ? ((val.define.dialectOptions.collate) ? val.define.dialectOptions.collate : "utf8_general_ci") : "utf8_general_ci") : "utf8_general_ci"),
|
|
106
106
|
},
|
|
107
107
|
timestamps: ((val.define) ? ((val.define.timestamps) ? val.define.timestamps : false) : false),
|
|
108
108
|
},
|
|
@@ -125,11 +125,19 @@ connectInProcess = async (database_config, headDbShow, cb) => {
|
|
|
125
125
|
|
|
126
126
|
// JSON response
|
|
127
127
|
query: {
|
|
128
|
-
raw: ((val.query) ? ((val.query.raw) ? val.query.raw :
|
|
128
|
+
raw: ((val.query) ? ((val.query.raw) ? val.query.raw : false) : false),
|
|
129
129
|
nest: ((val.query) ? ((val.query.nest) ? val.query.nest : true) : true),
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
|
-
|
|
132
|
+
|
|
133
|
+
// Hook to set `SET NAMES xxx` (ONLY MySQL)
|
|
134
|
+
await sq.addHook('afterConnect', async (connection) => {
|
|
135
|
+
if(val.dialect == "mysql") {
|
|
136
|
+
let charset = ["SET NAMES", ((val.define) ? ((val.define.charset) ? val.define.charset : "utf8") : "utf8")].join(" ");
|
|
137
|
+
connection.query(charset);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
133
141
|
// show only one text db connnections
|
|
134
142
|
if (headDbShow) {
|
|
135
143
|
console.log('[102m[90m Passed [0m [0mDatabase is connected at:');
|
|
@@ -144,7 +152,7 @@ connectInProcess = async (database_config, headDbShow, cb) => {
|
|
|
144
152
|
// shuout
|
|
145
153
|
console.log('- [91m[' + val.dialect + '] [0m[36m' + val.name + ' [0m->[93m ' + sq.config.database + ':' + sq.config.port + '[0m');
|
|
146
154
|
}
|
|
147
|
-
|
|
155
|
+
|
|
148
156
|
// connection
|
|
149
157
|
await sq.authenticate()
|
|
150
158
|
.then(() => {
|
|
@@ -161,7 +169,8 @@ connectInProcess = async (database_config, headDbShow, cb) => {
|
|
|
161
169
|
}
|
|
162
170
|
})
|
|
163
171
|
.catch(err => {
|
|
164
|
-
console.
|
|
172
|
+
console.log("Unable to connect to the database:", err);
|
|
173
|
+
cb(err, null);
|
|
165
174
|
});
|
|
166
175
|
});
|
|
167
176
|
} else {
|
|
@@ -2,6 +2,7 @@ const logUpdate = require("log-update");
|
|
|
2
2
|
const emoji = require('node-emoji')
|
|
3
3
|
const { DeHashIt, M, X } = require(__dirname + "/../helpers/math");
|
|
4
4
|
const Sequelize = require('sequelize');
|
|
5
|
+
const fs = require("fs");
|
|
5
6
|
let testSql = {};
|
|
6
7
|
|
|
7
8
|
function filterDbIsTrue(dbConfig, cb) {
|
|
@@ -17,7 +18,7 @@ function filterDbIsTrue(dbConfig, cb) {
|
|
|
17
18
|
}
|
|
18
19
|
setTimeout(() => {
|
|
19
20
|
cb(null, dbIsTrue);
|
|
20
|
-
},
|
|
21
|
+
}, 200);
|
|
21
22
|
}
|
|
22
23
|
});
|
|
23
24
|
} catch (error) {
|
|
@@ -25,42 +26,44 @@ function filterDbIsTrue(dbConfig, cb) {
|
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
function testConnectInProcess
|
|
29
|
+
function testConnectInProcess(database_config, dbConnTotal, cb) {
|
|
29
30
|
try {
|
|
31
|
+
// Recursive test connection
|
|
30
32
|
let val = database_config.shift();
|
|
31
33
|
if (val) {
|
|
32
|
-
initSequelize(val, async (err, sq) => {
|
|
34
|
+
initSequelize(val, true, async (err, sq) => {
|
|
33
35
|
if (err) {
|
|
34
|
-
console.
|
|
35
|
-
cb(err, null, null);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
//console.log("[101m Failed [0m Can't connect to connection name:[36m", val.name, "[0m\n", err);
|
|
37
|
+
return cb(err, null, null);
|
|
38
|
+
} else {
|
|
39
|
+
// Test connection
|
|
40
|
+
await sq.authenticate()
|
|
41
|
+
.then(() => {
|
|
42
|
+
// Database some is true perfectly.
|
|
43
|
+
if (database_config.length == 0) {
|
|
44
|
+
if (sq) {
|
|
45
|
+
testSql[ val.name ] = sq;
|
|
46
|
+
//console.log("DB true, Perfectly.", val.name);
|
|
47
|
+
return cb(null, true, testSql);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
43
50
|
testSql[ val.name ] = sq;
|
|
44
|
-
|
|
45
|
-
cb(null, true, testSql);
|
|
51
|
+
testConnectInProcess(database_config, dbConnTotal, cb);
|
|
46
52
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
console.error("[101m Failed [0m Unable to connect to the database:[36m", val.name, "[0m\n", err);
|
|
54
|
-
cb(err, null, null);
|
|
55
|
-
});
|
|
53
|
+
})
|
|
54
|
+
.catch(err => {
|
|
55
|
+
console.log("[101m Failed [0m Unable to connect to the database:[36m", val.name, "[0m\n", err);
|
|
56
|
+
return cb(err, null, null);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
56
59
|
});
|
|
57
60
|
} else if (!dbConnTotal) {
|
|
58
61
|
// All Database is falsly perfectly.
|
|
59
62
|
//console.log("DB all false, Perfectly.");
|
|
60
|
-
cb(null, true, testSql);
|
|
63
|
+
return cb(null, true, testSql);
|
|
61
64
|
}
|
|
62
65
|
} catch (error) {
|
|
63
|
-
cb(error, null, null);
|
|
66
|
+
return cb(error, null, null);
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -88,33 +91,69 @@ function logit(msg, next = false) {
|
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
function initSequelize(val, cb) {
|
|
94
|
+
function initSequelize(val, testConn = true, cb) {
|
|
92
95
|
try {
|
|
93
96
|
const promise = new Promise((resolve) => {
|
|
94
97
|
// check hash ?
|
|
95
98
|
if(val.username && val.password) {
|
|
96
99
|
if(val.username.length < 55 || val.password < 55) {
|
|
97
|
-
return cb("[
|
|
100
|
+
return cb("[91mERR:[0m Incorrect Hash access for connect to database, Please Hashing your access by command `beech hash:<your_access>`\n", null);
|
|
98
101
|
}
|
|
99
102
|
let accessDb = [];
|
|
100
|
-
[val.username, val.password].map((e, k) => {
|
|
101
|
-
DeHashIt(e.toString(), null, (17).toString().slice(0,-1).length, (err, d) => {
|
|
102
|
-
if(
|
|
103
|
-
|
|
103
|
+
[val.username, val.password].map(async (e, k) => {
|
|
104
|
+
await DeHashIt(e.toString(), null, (17).toString().slice(0,-1).length, async (err, d) => {
|
|
105
|
+
if(err) {
|
|
106
|
+
cb("[91mERR:[0m Hash access error,", err);
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
accessDb.push(d.split("sh,")[1].split(M(X).toString().slice(0,2)+M(X).toString())[0].slice(0,-1));
|
|
110
|
+
// Finally username & password
|
|
111
|
+
if(k+1==2) {
|
|
112
|
+
// Last push dialect connection
|
|
113
|
+
accessDb.push(val.dialect);
|
|
114
|
+
// resolve it
|
|
115
|
+
resolve(accessDb);
|
|
104
116
|
}
|
|
105
117
|
});
|
|
106
|
-
if(k+1==2) {
|
|
107
|
-
resolve(accessDb);
|
|
108
|
-
}
|
|
109
118
|
});
|
|
110
119
|
} else {
|
|
111
120
|
resolve([null, null]);
|
|
112
121
|
}
|
|
113
122
|
});
|
|
114
123
|
Promise.all([promise]).then(final => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
/**
|
|
125
|
+
* The final callback variable : [['hashed', 'hashed', 'dialect']]
|
|
126
|
+
*
|
|
127
|
+
* final[0][0] : username hashed
|
|
128
|
+
* final[0][1] : password hashed
|
|
129
|
+
* final[0][2] : dialect
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
// Check test connection for stdout pre-flight
|
|
134
|
+
if(testConn) {
|
|
135
|
+
// stdout pre-flight connection
|
|
136
|
+
logit(`- [91m[${val.dialect}] [0m[36m${val.name}[0m`);
|
|
137
|
+
logit(emoji.get('heavy_multiplication_x') + ` [91m[${val.dialect}] [0m[36m${val.name}[0m`);
|
|
138
|
+
}
|
|
139
|
+
fs.readFile("./global.config.js", 'utf8', (err, data) => {
|
|
140
|
+
if (err) {
|
|
141
|
+
console.log("\n[101m Faltal [0m Can't read `global.config.js` file.\n", err);
|
|
142
|
+
return; // break;
|
|
143
|
+
} else {
|
|
144
|
+
let buffer = Buffer.from(data);
|
|
145
|
+
let buf2str = buffer.toString();
|
|
146
|
+
let buf2json = JSON.parse(JSON.stringify(buf2str));
|
|
147
|
+
let pool_base = /global.pool_base\s+=\s+(?:"|')([^"]+)(?:"|')(?:\r|\n|$|;|\r)/i.exec(buf2json);
|
|
148
|
+
if (pool_base) {
|
|
149
|
+
if(pool_base == "basic") {
|
|
150
|
+
if(final[0][2] != "mysql") {
|
|
151
|
+
return cb(`The Basic pool engine not support with: ${val.dialect}, Please use Sequelize engine.`, null);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
118
157
|
// create connection
|
|
119
158
|
const sq = new Sequelize({
|
|
120
159
|
dialect: val.dialect || "mysql",
|
|
@@ -157,7 +196,10 @@ function initSequelize(val, cb) {
|
|
|
157
196
|
nest: ((val.query) ? ((val.query.nest) ? val.query.nest : true) : true),
|
|
158
197
|
}
|
|
159
198
|
});
|
|
160
|
-
|
|
199
|
+
// Check test connection for stdout pre-flight (mark)
|
|
200
|
+
if(testConn) {
|
|
201
|
+
logit(emoji.get('heavy_check_mark') + ` [91m[${val.dialect}] [0m[36m${val.name}[0m`, true);
|
|
202
|
+
}
|
|
161
203
|
cb(false, sq);
|
|
162
204
|
}).catch(err => {
|
|
163
205
|
console.log(`[103m[90m Warning [0m[0m Connection name \`[93m${val.name}[0m\``, err);
|
|
@@ -167,4 +209,48 @@ function initSequelize(val, cb) {
|
|
|
167
209
|
}
|
|
168
210
|
}
|
|
169
211
|
|
|
170
|
-
|
|
212
|
+
function connectForGenerateModel(dbConnectName, tableName, databaseConfig, cb) {
|
|
213
|
+
/**
|
|
214
|
+
* Callback
|
|
215
|
+
*
|
|
216
|
+
* err String : Error message
|
|
217
|
+
* tableSchema Object : Schema of table
|
|
218
|
+
* tableName String : table name
|
|
219
|
+
*
|
|
220
|
+
*/
|
|
221
|
+
const connectionChoose = databaseConfig.filter((e) => e.name == dbConnectName)[0];
|
|
222
|
+
initSequelize(connectionChoose, false, async (err, sq) => {
|
|
223
|
+
if (err) {
|
|
224
|
+
cb(err, null, null);
|
|
225
|
+
}
|
|
226
|
+
// Connection
|
|
227
|
+
await sq.authenticate()
|
|
228
|
+
.then(() => {
|
|
229
|
+
getTableSchema(sq, tableName, (errSchema, tableSchema) => {
|
|
230
|
+
if(errSchema) {
|
|
231
|
+
cb(errSchema, null, null);
|
|
232
|
+
} else {
|
|
233
|
+
// Closing database
|
|
234
|
+
sq.close();
|
|
235
|
+
// Callback
|
|
236
|
+
cb(null, tableSchema, tableName);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
})
|
|
240
|
+
.catch(err => {
|
|
241
|
+
cb(err, null, null);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function getTableSchema(sq, tableName, cb) {
|
|
247
|
+
try {
|
|
248
|
+
const queryInterface = sq.getQueryInterface();
|
|
249
|
+
const schema = await queryInterface.describeTable(tableName);
|
|
250
|
+
cb(null, schema);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
cb("Fetching table schema " + error, null);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = { filterDbIsTrue, testConnectInProcess, disConnectTestDB, connectForGenerateModel }
|
|
@@ -1,29 +1,6 @@
|
|
|
1
1
|
const { Schema } = require("beech-api");
|
|
2
2
|
// {{modelNameUppercase}} structure
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
field: "id",
|
|
6
|
-
type: DataTypes.INTEGER,
|
|
7
|
-
autoIncrement: true,
|
|
8
|
-
primaryKey: true,
|
|
9
|
-
},
|
|
10
|
-
examField1: DataTypes.STRING,
|
|
11
|
-
examField3: DataTypes.DATE,
|
|
12
|
-
examField4: {
|
|
13
|
-
type: DataTypes.STRING,
|
|
14
|
-
allowNull: false,
|
|
15
|
-
// set(value) {
|
|
16
|
-
// this.setDataValue("examField4", md5(value));
|
|
17
|
-
// },
|
|
18
|
-
},
|
|
19
|
-
createdAt: DataTypes.DATE,
|
|
20
|
-
updatedAt: DataTypes.DATE,
|
|
21
|
-
// Asign more DataTypes, Learn more: https://sequelize.org/docs/v6/core-concepts/model-basics/#data-types
|
|
22
|
-
});
|
|
3
|
+
{{modelStructure}}
|
|
4
|
+
// Asign more DataTypes, Learn more: https://sequelize.org/docs/v6/core-concepts/model-basics/#data-types
|
|
23
5
|
|
|
24
|
-
|
|
25
|
-
function exampleFindOne{{modelNameUppercase}}ById(id) {
|
|
26
|
-
return {{modelNameUppercase}}.findOne({ where: { id: id } });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module.exports = { {{modelNameUppercase}}, exampleFindOne{{modelNameUppercase}}ById };
|
|
6
|
+
module.exports = { {{modelNameUppercase}} };
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
|
|
3
|
-
// Example basic function return exam data
|
|
4
|
-
getData() {
|
|
5
|
-
return [
|
|
6
|
-
{ "id": 1, "name": "Oggy" },
|
|
7
|
-
{ "id": 2, "name": "Jack" },
|
|
8
|
-
{ "id": 3, "name": "The Cockroaches Gang" }
|
|
9
|
-
];
|
|
10
|
-
},
|
|
11
|
-
|
|
12
3
|
// Example basic function get data from table {{modelName}}
|
|
13
4
|
findAll() {
|
|
14
5
|
return new Promise((resolve, reject) => {
|
|
@@ -5,17 +5,16 @@
|
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"start": "beech-service serve",
|
|
8
|
+
"predev": "node ./node_modules/beech-api/packages/cli/core/test/check-node.js",
|
|
9
|
+
"prebuild": "node ./node_modules/beech-api/packages/cli/core/test/check-node.js",
|
|
10
|
+
"build": "set NODE_ENV=production&& beech-service build",
|
|
11
|
+
"dev": "beech-service serve",
|
|
13
12
|
"test": "node ./node_modules/jest/bin/jest __tests__ -o --watch --config"
|
|
14
13
|
},
|
|
15
14
|
"dependencies": {
|
|
16
|
-
"beech-api": "
|
|
15
|
+
"beech-api": "^3.9.0"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
|
-
"jest": "^
|
|
18
|
+
"jest": "^29.7.0"
|
|
20
19
|
}
|
|
21
20
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
const CronJob = require("cron").CronJob;
|
|
1
2
|
//const Users = require("@/models/Users");
|
|
2
|
-
//const CronJob = require("cron").CronJob;
|
|
3
3
|
|
|
4
4
|
exports.init = () => {
|
|
5
5
|
|
|
@@ -8,15 +8,25 @@ exports.init = () => {
|
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
//
|
|
11
|
+
// const getUsers = async () => {
|
|
12
|
+
// try {
|
|
13
|
+
// const users = await Users.findAll();
|
|
14
|
+
// console.log(users);
|
|
15
|
+
// } catch (error) {
|
|
16
|
+
// console.error(error);
|
|
17
|
+
// }
|
|
18
|
+
// };
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
|
-
* Job schedule:
|
|
21
|
+
* Job schedule: seconds minutes hours dayOfMonth month dayOfWeek
|
|
15
22
|
* Learn more: https://github.com/kelektiv/node-cron
|
|
16
23
|
*
|
|
17
24
|
*/
|
|
18
|
-
|
|
19
|
-
//Run job.
|
|
20
|
-
|
|
25
|
+
new CronJob("0 0 0 * * *", () => {
|
|
26
|
+
// Run job.
|
|
27
|
+
|
|
28
|
+
// getUsers();
|
|
29
|
+
|
|
30
|
+
}, null, true, "Asia/Bangkok");
|
|
21
31
|
|
|
22
32
|
};
|