jj.js 0.19.0 → 0.20.0
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 +243 -173
- package/jj.js +14 -14
- package/lib/app.js +52 -17
- package/lib/cache.js +96 -30
- package/lib/config.js +14 -4
- package/lib/context.js +18 -22
- package/lib/controller.js +36 -5
- package/lib/cookie.js +11 -15
- package/lib/ctx.js +28 -28
- package/lib/db/mongodb.js +564 -0
- package/lib/db/mysql.js +32 -28
- package/lib/db/sql.js +13 -3
- package/lib/db/sqlite.js +32 -24
- package/lib/db.js +230 -112
- package/lib/loader.js +79 -44
- package/lib/logger.js +124 -126
- package/lib/middleware.js +39 -6
- package/lib/model.js +23 -9
- package/lib/{run.js → mvc.js} +29 -22
- package/lib/pagination.js +68 -14
- package/lib/request.js +4 -4
- package/lib/response.js +70 -6
- package/lib/router.js +4 -3
- package/lib/types.js +363 -196
- package/lib/upload.js +15 -15
- package/lib/url.js +10 -2
- package/lib/utils/error.js +9 -5
- package/lib/utils/utils.js +2 -0
- package/lib/utils/validate.js +13 -0
- package/lib/view.js +54 -8
- package/logo.png +0 -0
- package/package.json +8 -4
- package/types.js +177 -83
- package/CHANGELOG.md +0 -58
- package/jsdoc.conf.js +0 -17
package/lib/db/mysql.js
CHANGED
|
@@ -36,7 +36,7 @@ class Mysql extends Sql
|
|
|
36
36
|
if(!pool.has(this._config)) {
|
|
37
37
|
const cur_pool = require('mysql').createPool(this._config);
|
|
38
38
|
pool.set(this._config, cur_pool);
|
|
39
|
-
this
|
|
39
|
+
this.logger.sql(`MYSQL连接池创建成功:{all: ${pool.size}}`);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
return this;
|
|
@@ -45,25 +45,27 @@ class Mysql extends Sql
|
|
|
45
45
|
/**
|
|
46
46
|
* 关闭数据库连接池
|
|
47
47
|
* @public
|
|
48
|
-
* @returns {Promise}
|
|
48
|
+
* @returns {Promise<this>}
|
|
49
49
|
*/
|
|
50
50
|
async close() {
|
|
51
|
+
const that = this;
|
|
51
52
|
return new Promise((resolve, reject) => {
|
|
52
53
|
if(pool.has(this._config)) {
|
|
54
|
+
// @ts-ignore
|
|
53
55
|
pool.get(this._config).end(err => {
|
|
54
56
|
if(err) {
|
|
55
57
|
const message = 'MYSQL连接池销毁失败:' + err.message;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
that.logger.sql(message);
|
|
59
|
+
that.logger.error(message);
|
|
58
60
|
reject(new Error('DbError: ' + message));
|
|
59
61
|
} else {
|
|
60
62
|
pool.delete(this._config);
|
|
61
|
-
|
|
62
|
-
resolve(
|
|
63
|
+
that.logger.sql(`MYSQL连接池销毁成功:{poolTotal: ${pool.size}}`);
|
|
64
|
+
resolve(that);
|
|
63
65
|
}
|
|
64
66
|
});
|
|
65
67
|
} else {
|
|
66
|
-
resolve(
|
|
68
|
+
resolve(that);
|
|
67
69
|
}
|
|
68
70
|
});
|
|
69
71
|
}
|
|
@@ -76,11 +78,11 @@ class Mysql extends Sql
|
|
|
76
78
|
release(conn) {
|
|
77
79
|
try {
|
|
78
80
|
conn.release();
|
|
79
|
-
this
|
|
81
|
+
this.logger.sql('释放数据库连接!');
|
|
80
82
|
} catch(e) {
|
|
81
|
-
const message = '释放数据库出错:' + e.message;
|
|
82
|
-
this
|
|
83
|
-
this
|
|
83
|
+
const message = '释放数据库出错:' + (e instanceof Error && e.message || String(e));
|
|
84
|
+
this.logger.sql(message);
|
|
85
|
+
this.logger.error(message);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
|
|
@@ -95,11 +97,12 @@ class Mysql extends Sql
|
|
|
95
97
|
p.getConnection((err, connection) => {
|
|
96
98
|
if(err) {
|
|
97
99
|
const message = '获取数据库连接失败:' + err.message;
|
|
98
|
-
this
|
|
99
|
-
this
|
|
100
|
+
this.logger.sql(message);
|
|
101
|
+
this.logger.error(message);
|
|
100
102
|
reject(new Error('DbError: ' + message));
|
|
101
103
|
} else {
|
|
102
|
-
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
this.logger.sql(`获取数据库连接:{limit: ${p.config.connectionLimit}, all: ${p._allConnections.length}, acquiring: ${p._acquiringConnections.length}, free: ${p._freeConnections.length}, queue: ${p._connectionQueue.length}}`);
|
|
103
106
|
resolve(connection);
|
|
104
107
|
}
|
|
105
108
|
});
|
|
@@ -112,6 +115,7 @@ class Mysql extends Sql
|
|
|
112
115
|
* @returns {Promise<PoolConnection>}
|
|
113
116
|
*/
|
|
114
117
|
async _getConnect() {
|
|
118
|
+
// @ts-ignore
|
|
115
119
|
return trans.get(this.ctx) || await this._creatConnect(pool.get(this._config));
|
|
116
120
|
}
|
|
117
121
|
|
|
@@ -128,7 +132,7 @@ class Mysql extends Sql
|
|
|
128
132
|
nest.set(conn, ++trans_nest);
|
|
129
133
|
if(trans_nest > 1) {
|
|
130
134
|
const message = `开启事务成功:{nest:${trans_nest}}`;
|
|
131
|
-
this
|
|
135
|
+
this.logger.sql(message);
|
|
132
136
|
if(typeof fun === 'function') {
|
|
133
137
|
try {
|
|
134
138
|
await fun();
|
|
@@ -145,12 +149,12 @@ class Mysql extends Sql
|
|
|
145
149
|
conn.beginTransaction(async err => {
|
|
146
150
|
if(err) {
|
|
147
151
|
const message = '开启事务失败:' + err.message;
|
|
148
|
-
this
|
|
149
|
-
this
|
|
152
|
+
this.logger.sql(message);
|
|
153
|
+
this.logger.error(message);
|
|
150
154
|
reject(new Error('DbError: ' + message));
|
|
151
155
|
} else {
|
|
152
156
|
const message = '开启事务成功!';
|
|
153
|
-
this
|
|
157
|
+
this.logger.sql(message);
|
|
154
158
|
if(typeof fun === 'function') {
|
|
155
159
|
try {
|
|
156
160
|
await fun();
|
|
@@ -178,7 +182,7 @@ class Mysql extends Sql
|
|
|
178
182
|
if(trans_nest > 1) {
|
|
179
183
|
nest.set(conn, trans_nest - 1);
|
|
180
184
|
const message = `事务回滚成功:{nest:${trans_nest}}`;
|
|
181
|
-
this
|
|
185
|
+
this.logger.sql(message);
|
|
182
186
|
return message;
|
|
183
187
|
} else {
|
|
184
188
|
nest.delete(conn);
|
|
@@ -191,7 +195,7 @@ class Mysql extends Sql
|
|
|
191
195
|
} else {
|
|
192
196
|
trans.delete(this.ctx);
|
|
193
197
|
const message = '事务回滚成功!';
|
|
194
|
-
this
|
|
198
|
+
this.logger.sql(message);
|
|
195
199
|
this.release(conn);
|
|
196
200
|
resolve(message);
|
|
197
201
|
}
|
|
@@ -210,7 +214,7 @@ class Mysql extends Sql
|
|
|
210
214
|
if(trans_nest > 1) {
|
|
211
215
|
nest.set(conn, trans_nest - 1);
|
|
212
216
|
const message = `事务提交成功:{nest:${trans_nest}}`;
|
|
213
|
-
this
|
|
217
|
+
this.logger.sql(message);
|
|
214
218
|
return message;
|
|
215
219
|
} else {
|
|
216
220
|
nest.delete(conn);
|
|
@@ -220,14 +224,14 @@ class Mysql extends Sql
|
|
|
220
224
|
conn.commit(err => {
|
|
221
225
|
if(err) {
|
|
222
226
|
const message = '事务提交失败:' + err.message;
|
|
223
|
-
this
|
|
224
|
-
this
|
|
227
|
+
this.logger.sql(message);
|
|
228
|
+
this.logger.error(message);
|
|
225
229
|
this.rollback();
|
|
226
230
|
reject(new Error('DbError: ' + message));
|
|
227
231
|
} else {
|
|
228
232
|
trans.delete(this.ctx);
|
|
229
233
|
const message = '事务提交成功!';
|
|
230
|
-
this
|
|
234
|
+
this.logger.sql(message);
|
|
231
235
|
this.release(conn);
|
|
232
236
|
resolve(message);
|
|
233
237
|
}
|
|
@@ -240,7 +244,7 @@ class Mysql extends Sql
|
|
|
240
244
|
* @public
|
|
241
245
|
* @param {string} sql - sql语句或参数
|
|
242
246
|
* @param {*} params - sql参数
|
|
243
|
-
* @returns {Promise}
|
|
247
|
+
* @returns {Promise<*>}
|
|
244
248
|
*/
|
|
245
249
|
async query(sql, params) {
|
|
246
250
|
params || (params = []);
|
|
@@ -250,11 +254,11 @@ class Mysql extends Sql
|
|
|
250
254
|
conn.query(sql, params, (err, data) => {
|
|
251
255
|
if(err) {
|
|
252
256
|
const message = '数据操作失败,' + err.message + "\nSQL:" + this.format(sql, params);
|
|
253
|
-
this
|
|
254
|
-
this
|
|
257
|
+
this.logger.sql(message);
|
|
258
|
+
this.logger.error(message);
|
|
255
259
|
reject(new Error('DbError: ' + message));
|
|
256
260
|
} else {
|
|
257
|
-
this
|
|
261
|
+
this.logger.sql('数据操作成功,SQL:' + this.format(sql, params));
|
|
258
262
|
resolve(data);
|
|
259
263
|
}
|
|
260
264
|
if(!trans.has(this.ctx)) {
|
package/lib/db/sql.js
CHANGED
|
@@ -12,7 +12,7 @@ class Sql
|
|
|
12
12
|
*/
|
|
13
13
|
constructor(ctx, logger) {
|
|
14
14
|
this.ctx = ctx;
|
|
15
|
-
this
|
|
15
|
+
this.logger = logger;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -75,7 +75,7 @@ class Sql
|
|
|
75
75
|
* @public
|
|
76
76
|
* @param {string} sql - sql语句或参数
|
|
77
77
|
* @param {*} params - sql参数
|
|
78
|
-
* @returns {Promise}
|
|
78
|
+
* @returns {Promise<*>}
|
|
79
79
|
*/
|
|
80
80
|
async query(sql, params) {
|
|
81
81
|
}
|
|
@@ -89,7 +89,7 @@ class Sql
|
|
|
89
89
|
*/
|
|
90
90
|
format(sql, params) {
|
|
91
91
|
params || (params = []);
|
|
92
|
-
return `${sql} ${params.map(item => item.join('=')).join(', ')}`;
|
|
92
|
+
return `${sql} ${params.map((/** @type {any[]} */ item) => item.join('=')).join(', ')}`;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/**
|
|
@@ -101,6 +101,16 @@ class Sql
|
|
|
101
101
|
async tableInfo(tableName) {
|
|
102
102
|
return await this.query(`show columns from ?`, [tableName]);
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 设置日志器
|
|
107
|
+
* @param {Logger} logger
|
|
108
|
+
* @returns {this}
|
|
109
|
+
*/
|
|
110
|
+
setLogger(logger) {
|
|
111
|
+
this.logger = logger;
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
104
114
|
}
|
|
105
115
|
|
|
106
116
|
module.exports = Sql;
|
package/lib/db/sqlite.js
CHANGED
|
@@ -2,6 +2,7 @@ const {app: cfg_app} = require('../config');
|
|
|
2
2
|
const Sql = require('./sql');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
+
* @typedef {import('../../types').DbConfigItem} DbConfigItem
|
|
5
6
|
* @typedef {import('sqlite3').Database} Database
|
|
6
7
|
* @typedef {import('../../types').FieldInfo} FieldInfo
|
|
7
8
|
* @typedef {Map<any, Database>} ConnectionMap
|
|
@@ -25,10 +26,10 @@ class Sqlite extends Sql
|
|
|
25
26
|
/**
|
|
26
27
|
* 连接数据库
|
|
27
28
|
* @public
|
|
28
|
-
* @param {
|
|
29
|
+
* @param {DbConfigItem} config - 数据库配置标识或连接参数
|
|
29
30
|
* @returns {Promise<this>}
|
|
30
31
|
*/
|
|
31
|
-
async connect(config
|
|
32
|
+
async connect(config) {
|
|
32
33
|
this._config = config;
|
|
33
34
|
|
|
34
35
|
let connection = connections.get(this._config);
|
|
@@ -36,7 +37,7 @@ class Sqlite extends Sql
|
|
|
36
37
|
const sqlite3 = cfg_app.app_debug ? require('sqlite3').verbose() : require('sqlite3');
|
|
37
38
|
connection = new sqlite3.Database(this._config.database);
|
|
38
39
|
connections.set(this._config, connection);
|
|
39
|
-
this
|
|
40
|
+
this.logger.sql(`SQLITE数据库连接创建成功:{all: ${connections.size}}`);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
return this;
|
|
@@ -45,26 +46,29 @@ class Sqlite extends Sql
|
|
|
45
46
|
/**
|
|
46
47
|
* 关闭数据库连接
|
|
47
48
|
* @public
|
|
48
|
-
* @returns {Promise}
|
|
49
|
+
* @returns {Promise<this>}
|
|
49
50
|
*/
|
|
50
51
|
async close() {
|
|
52
|
+
const that = this;
|
|
51
53
|
return new Promise((resolve, reject) => {
|
|
52
54
|
if(connections.has(this._config)) {
|
|
53
55
|
const connection = connections.get(this._config);
|
|
56
|
+
// @ts-ignore
|
|
54
57
|
connection.close(err => {
|
|
55
58
|
if(err) {
|
|
56
59
|
const message = 'SQLITE数据库连接关闭失败:' + err.message;
|
|
57
|
-
this
|
|
58
|
-
this
|
|
60
|
+
this.logger.sql(message);
|
|
61
|
+
this.logger.error(message);
|
|
59
62
|
reject(new Error('DbError: ' + message));
|
|
60
63
|
} else {
|
|
61
64
|
connections.delete(this._config);
|
|
62
|
-
this
|
|
63
|
-
resolve(
|
|
65
|
+
this.logger.sql(`SQLITE数据库连接关闭成功:{connectionTotal: ${connections.size}}`);
|
|
66
|
+
resolve(that);
|
|
67
|
+
|
|
64
68
|
}
|
|
65
69
|
});
|
|
66
70
|
} else {
|
|
67
|
-
resolve(
|
|
71
|
+
resolve(that);
|
|
68
72
|
}
|
|
69
73
|
});
|
|
70
74
|
}
|
|
@@ -91,7 +95,7 @@ class Sqlite extends Sql
|
|
|
91
95
|
nest.set(conn, ++trans_nest);
|
|
92
96
|
if(trans_nest > 1) {
|
|
93
97
|
const message = `开启事务成功:{nest:${trans_nest}}`;
|
|
94
|
-
this
|
|
98
|
+
this.logger.sql(message);
|
|
95
99
|
if(typeof fun === 'function') {
|
|
96
100
|
try {
|
|
97
101
|
await fun();
|
|
@@ -108,12 +112,12 @@ class Sqlite extends Sql
|
|
|
108
112
|
conn.run('BEGIN TRANSACTION;', async err => {
|
|
109
113
|
if(err) {
|
|
110
114
|
const message = '开启事务失败:' + err.message;
|
|
111
|
-
this
|
|
112
|
-
this
|
|
115
|
+
this.logger.sql(message);
|
|
116
|
+
this.logger.error(message);
|
|
113
117
|
reject(new Error('DbError: ' + message));
|
|
114
118
|
} else {
|
|
115
119
|
const message = '开启事务成功!';
|
|
116
|
-
this
|
|
120
|
+
this.logger.sql(message);
|
|
117
121
|
if(typeof fun === 'function') {
|
|
118
122
|
try {
|
|
119
123
|
await fun();
|
|
@@ -141,7 +145,7 @@ class Sqlite extends Sql
|
|
|
141
145
|
if(trans_nest > 1) {
|
|
142
146
|
nest.set(conn, trans_nest - 1);
|
|
143
147
|
const message = `事务回滚成功:{nest:${trans_nest}}`;
|
|
144
|
-
this
|
|
148
|
+
this.logger.sql(message);
|
|
145
149
|
return message;
|
|
146
150
|
} else {
|
|
147
151
|
nest.delete(conn);
|
|
@@ -154,7 +158,7 @@ class Sqlite extends Sql
|
|
|
154
158
|
} else {
|
|
155
159
|
trans.delete(this.ctx);
|
|
156
160
|
const message = '事务回滚成功!';
|
|
157
|
-
this
|
|
161
|
+
this.logger.sql(message);
|
|
158
162
|
resolve(message);
|
|
159
163
|
}
|
|
160
164
|
});
|
|
@@ -172,7 +176,7 @@ class Sqlite extends Sql
|
|
|
172
176
|
if(trans_nest > 1) {
|
|
173
177
|
nest.set(conn, trans_nest - 1);
|
|
174
178
|
const message = `事务提交成功:{nest:${trans_nest}}`;
|
|
175
|
-
this
|
|
179
|
+
this.logger.sql(message);
|
|
176
180
|
return message;
|
|
177
181
|
} else {
|
|
178
182
|
nest.delete(conn);
|
|
@@ -182,14 +186,14 @@ class Sqlite extends Sql
|
|
|
182
186
|
conn.run('COMMIT;', err => {
|
|
183
187
|
if(err) {
|
|
184
188
|
const message = '事务提交失败:' + err.message;
|
|
185
|
-
this
|
|
186
|
-
this
|
|
189
|
+
this.logger.sql(message);
|
|
190
|
+
this.logger.error(message);
|
|
187
191
|
this.rollback();
|
|
188
192
|
reject(new Error('DbError: ' + message));
|
|
189
193
|
} else {
|
|
190
194
|
trans.delete(this.ctx);
|
|
191
195
|
const message = '事务提交成功!';
|
|
192
|
-
this
|
|
196
|
+
this.logger.sql(message);
|
|
193
197
|
resolve(message);
|
|
194
198
|
}
|
|
195
199
|
});
|
|
@@ -200,8 +204,8 @@ class Sqlite extends Sql
|
|
|
200
204
|
* 执行sql查询
|
|
201
205
|
* @public
|
|
202
206
|
* @param {string} sql - sql语句或参数
|
|
203
|
-
* @param {*} params - sql参数
|
|
204
|
-
* @returns {Promise}
|
|
207
|
+
* @param {*} [params] - sql参数
|
|
208
|
+
* @returns {Promise<*>}
|
|
205
209
|
*/
|
|
206
210
|
async query(sql, params) {
|
|
207
211
|
params || (params = []);
|
|
@@ -213,19 +217,22 @@ class Sqlite extends Sql
|
|
|
213
217
|
const isTableInfo = /^\s*PRAGMA table_info/i.test(sql);
|
|
214
218
|
|
|
215
219
|
const that = this;
|
|
220
|
+
// @ts-ignore
|
|
216
221
|
conn[isSelect || isTableInfo ? 'all' : 'run'](sql, params, function(err, rows) {
|
|
217
222
|
if(err) {
|
|
218
223
|
const message = '数据操作失败,' + err.message + "\nSQL:" + that.format(sql, params);
|
|
219
|
-
that
|
|
220
|
-
that
|
|
224
|
+
that.logger.sql(message);
|
|
225
|
+
that.logger.error(message);
|
|
221
226
|
reject(new Error('DbError: ' + message));
|
|
222
227
|
} else {
|
|
223
|
-
that
|
|
228
|
+
that.logger.sql('数据操作成功,SQL:' + that.format(sql, params));
|
|
224
229
|
if(isSelect || isTableInfo) {
|
|
225
230
|
resolve(rows);
|
|
226
231
|
} else {
|
|
227
232
|
resolve({
|
|
233
|
+
// @ts-ignore - sqlite3 run 回调中的 this 包含 changes 和 lastID
|
|
228
234
|
affectedRows: this.changes,
|
|
235
|
+
// @ts-ignore - sqlite3 run 回调中的 this 包含 changes 和 lastID
|
|
229
236
|
insertId: this.lastID
|
|
230
237
|
});
|
|
231
238
|
}
|
|
@@ -268,6 +275,7 @@ class Sqlite extends Sql
|
|
|
268
275
|
*/
|
|
269
276
|
async tableInfo(tableName) {
|
|
270
277
|
const columns = await this.query(`PRAGMA table_info(${tableName})`);
|
|
278
|
+
// @ts-ignore
|
|
271
279
|
return columns.map(col => {
|
|
272
280
|
return {
|
|
273
281
|
Field: col.name,
|