chanjs 2.1.1 → 2.3.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/App.js +387 -0
- package/base/Context.js +78 -0
- package/base/Controller.js +137 -0
- package/base/Database.js +314 -0
- package/base/Service.js +539 -0
- package/common/api.js +25 -0
- package/common/category.js +22 -0
- package/common/code.js +42 -0
- package/common/email.js +110 -0
- package/common/index.js +7 -0
- package/common/pages.js +86 -0
- package/common/sms.js +104 -0
- package/common/utils.js +73 -0
- package/config/code.js +110 -52
- package/config/index.js +10 -0
- package/config/paths.js +60 -0
- package/extend/art-template.js +46 -28
- package/extend/index.js +6 -0
- package/global/env.js +11 -5
- package/global/global.js +63 -39
- package/global/import.js +43 -39
- package/global/index.js +8 -3
- package/helper/cache.js +182 -0
- package/helper/data-parse.js +121 -37
- package/helper/db.js +71 -83
- package/helper/file.js +158 -208
- package/helper/filter.js +34 -0
- package/helper/html.js +30 -47
- package/helper/index.js +29 -5
- package/helper/ip.js +48 -31
- package/helper/jwt.js +78 -11
- package/helper/loader.js +93 -50
- package/helper/request.js +41 -144
- package/helper/sign.js +96 -33
- package/helper/time.js +89 -74
- package/helper/tree.js +77 -0
- package/index.js +15 -181
- package/middleware/cookie.js +20 -4
- package/middleware/cors.js +20 -0
- package/middleware/favicon.js +21 -5
- package/middleware/header.js +26 -9
- package/middleware/index.js +14 -23
- package/middleware/preventRetry.js +30 -0
- package/middleware/setBody.js +24 -10
- package/middleware/static.js +31 -10
- package/middleware/template.js +34 -14
- package/middleware/validator.js +43 -23
- package/middleware/waf.js +147 -287
- package/package.json +1 -1
- package/utils/checker.js +68 -0
- package/utils/error-handler.js +115 -0
- package/utils/error.js +81 -0
- package/utils/index.js +6 -0
- package/utils/keywords.js +126 -0
- package/utils/rate-limit.js +116 -0
- package/utils/response.js +103 -64
- package/utils/xss-filter.js +42 -0
- package/core/controller.js +0 -33
- package/core/index.js +0 -3
- package/core/service.js +0 -307
- package/middleware/log.js +0 -21
package/base/Database.js
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import knex from "knex";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 数据库管理器类
|
|
5
|
+
* 用于管理多个数据库连接和创建数据模型
|
|
6
|
+
*/
|
|
7
|
+
class DatabaseManager {
|
|
8
|
+
/**
|
|
9
|
+
* 构造函数
|
|
10
|
+
* 初始化数据库连接存储和默认连接名称
|
|
11
|
+
*/
|
|
12
|
+
constructor() {
|
|
13
|
+
this._connections = new Map();
|
|
14
|
+
this._defaultName = "default";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 添加数据库连接
|
|
19
|
+
* @param {string} name - 连接名称
|
|
20
|
+
* @param {Object} config - Knex配置对象
|
|
21
|
+
* @param {Object} options - 选项
|
|
22
|
+
* @param {boolean} options.isDefault - 是否设为默认连接
|
|
23
|
+
* @returns {Object} Knex连接实例
|
|
24
|
+
*/
|
|
25
|
+
add(name, config, options = {}) {
|
|
26
|
+
const { isDefault = false } = options;
|
|
27
|
+
|
|
28
|
+
const connection = knex(config);
|
|
29
|
+
this._connections.set(name, connection);
|
|
30
|
+
|
|
31
|
+
if (isDefault || this._connections.size === 1) {
|
|
32
|
+
this._defaultName = name;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return connection;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 获取数据库连接
|
|
40
|
+
* @param {string} name - 连接名称,默认为默认连接
|
|
41
|
+
* @returns {Object} Knex连接实例
|
|
42
|
+
* @throws {Error} 连接不存在时抛出异常
|
|
43
|
+
*/
|
|
44
|
+
get(name = this._defaultName) {
|
|
45
|
+
const connection = this._connections.get(name);
|
|
46
|
+
if (!connection) {
|
|
47
|
+
throw new Error(`Database connection "${name}" not found`);
|
|
48
|
+
}
|
|
49
|
+
return connection;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 获取默认数据库连接
|
|
54
|
+
* @returns {Object} Knex连接实例
|
|
55
|
+
*/
|
|
56
|
+
getDefault() {
|
|
57
|
+
return this.get(this._defaultName);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 检查连接是否存在
|
|
62
|
+
* @param {string} name - 连接名称
|
|
63
|
+
* @returns {boolean} 是否存在
|
|
64
|
+
*/
|
|
65
|
+
has(name) {
|
|
66
|
+
return this._connections.has(name);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 移除数据库连接
|
|
71
|
+
* @param {string} name - 连接名称
|
|
72
|
+
*/
|
|
73
|
+
remove(name) {
|
|
74
|
+
const connection = this._connections.get(name);
|
|
75
|
+
if (connection) {
|
|
76
|
+
connection.destroy();
|
|
77
|
+
this._connections.delete(name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 关闭所有数据库连接
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
*/
|
|
85
|
+
async closeAll() {
|
|
86
|
+
const closePromises = [];
|
|
87
|
+
for (const [name, connection] of this._connections) {
|
|
88
|
+
closePromises.push(
|
|
89
|
+
connection.destroy().catch((err) => {
|
|
90
|
+
console.error(`Error closing database "${name}":`, err);
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
await Promise.all(closePromises);
|
|
95
|
+
this._connections.clear();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 获取所有连接名称
|
|
100
|
+
* @returns {Array<string>} 连接名称数组
|
|
101
|
+
*/
|
|
102
|
+
getConnections() {
|
|
103
|
+
return Array.from(this._connections.keys());
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 创建数据模型
|
|
108
|
+
* @param {string} name - 模型名称
|
|
109
|
+
* @param {string} tableName - 表名
|
|
110
|
+
* @param {string} connectionName - 连接名称
|
|
111
|
+
* @returns {Object} 模型对象
|
|
112
|
+
*/
|
|
113
|
+
createModel(name, tableName, connectionName) {
|
|
114
|
+
const db = this.get(connectionName);
|
|
115
|
+
return {
|
|
116
|
+
db,
|
|
117
|
+
tableName,
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 查询字段
|
|
121
|
+
* @param {string} fields - 字段列表,默认"*"
|
|
122
|
+
* @returns {Object} Knex查询构建器
|
|
123
|
+
*/
|
|
124
|
+
select(fields = "*") {
|
|
125
|
+
return db(this.tableName).select(fields);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 条件查询
|
|
130
|
+
* @param {Object} conditions - 查询条件
|
|
131
|
+
* @returns {Object} Knex查询构建器
|
|
132
|
+
*/
|
|
133
|
+
where(conditions) {
|
|
134
|
+
return db(this.tableName).where(conditions);
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 查找记录
|
|
139
|
+
* @param {Object} query - 查询参数
|
|
140
|
+
* @param {Object} query.sort - 排序条件
|
|
141
|
+
* @param {Object} query.where - 查询条件
|
|
142
|
+
* @returns {Promise<Array>} 查询结果数组
|
|
143
|
+
*/
|
|
144
|
+
find(query = {}) {
|
|
145
|
+
let q = db(this.tableName);
|
|
146
|
+
const { sort, ...where } = query;
|
|
147
|
+
|
|
148
|
+
if (Object.keys(where).length > 0) {
|
|
149
|
+
q = q.where(where);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (sort && typeof sort === "object") {
|
|
153
|
+
for (const [field, dir] of Object.entries(sort)) {
|
|
154
|
+
q = q.orderBy(field, dir);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return q.select();
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 查找单条记录
|
|
163
|
+
* @param {Object} query - 查询条件
|
|
164
|
+
* @returns {Promise<Object|null>} 查询结果或null
|
|
165
|
+
*/
|
|
166
|
+
findOne(query = {}) {
|
|
167
|
+
let q = db(this.tableName);
|
|
168
|
+
if (Object.keys(query).length > 0) {
|
|
169
|
+
q = q.where(query);
|
|
170
|
+
}
|
|
171
|
+
return q.first();
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 根据ID查找记录
|
|
176
|
+
* @param {number|string} id - 记录ID
|
|
177
|
+
* @returns {Promise<Object|null>} 查询结果或null
|
|
178
|
+
*/
|
|
179
|
+
findById(id) {
|
|
180
|
+
return db(this.tableName).where({ id }).first();
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 创建记录
|
|
185
|
+
* @param {Object} data - 要插入的数据
|
|
186
|
+
* @returns {Promise<Array>} 插入结果
|
|
187
|
+
*/
|
|
188
|
+
create(data) {
|
|
189
|
+
return db(this.tableName).insert(data);
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 批量创建记录
|
|
194
|
+
* @param {Array} records - 要插入的记录数组
|
|
195
|
+
* @returns {Promise<Array>} 插入结果
|
|
196
|
+
*/
|
|
197
|
+
createMany(records) {
|
|
198
|
+
return db(this.tableName).insert(records);
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 更新记录
|
|
203
|
+
* @param {Object} conditions - 更新条件
|
|
204
|
+
* @param {Object} data - 更新数据
|
|
205
|
+
* @returns {Promise<number>} 影响的行数
|
|
206
|
+
*/
|
|
207
|
+
update(conditions, data) {
|
|
208
|
+
return db(this.tableName).where(conditions).update(data);
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 删除记录
|
|
213
|
+
* @param {Object} conditions - 删除条件
|
|
214
|
+
* @returns {Promise<number>} 影响的行数
|
|
215
|
+
*/
|
|
216
|
+
delete(conditions) {
|
|
217
|
+
return db(this.tableName).where(conditions).del();
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* 统计记录数
|
|
222
|
+
* @param {Object} query - 查询条件
|
|
223
|
+
* @returns {Promise<number>} 记录总数
|
|
224
|
+
*/
|
|
225
|
+
count(query = {}) {
|
|
226
|
+
let q = db(this.tableName).count("* as total");
|
|
227
|
+
if (Object.keys(query).length > 0) {
|
|
228
|
+
q = q.where(query);
|
|
229
|
+
}
|
|
230
|
+
return q.first().then((result) => result?.total ?? 0);
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* 分页查询
|
|
235
|
+
* @param {Object} options - 查询选项
|
|
236
|
+
* @param {number} options.current - 当前页码,默认1
|
|
237
|
+
* @param {number} options.pageSize - 每页大小,默认10
|
|
238
|
+
* @param {Object} options.where - 查询条件
|
|
239
|
+
* @param {Array} options.select - 查询字段
|
|
240
|
+
* @returns {Promise<Object>} 分页结果
|
|
241
|
+
*/
|
|
242
|
+
query(options = {}) {
|
|
243
|
+
const { current = 1, pageSize = 10, where = {}, select } = options;
|
|
244
|
+
const offset = (current - 1) * pageSize;
|
|
245
|
+
|
|
246
|
+
const countQuery = db(this.tableName).count("* as total");
|
|
247
|
+
const dataQuery = db(this.tableName);
|
|
248
|
+
|
|
249
|
+
if (Object.keys(where).length > 0) {
|
|
250
|
+
countQuery.where(where);
|
|
251
|
+
dataQuery.where(where);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (select) {
|
|
255
|
+
dataQuery.select(select);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return Promise.all([
|
|
259
|
+
countQuery.first(),
|
|
260
|
+
dataQuery.offset(offset).limit(pageSize),
|
|
261
|
+
]).then(([totalResult, list]) => ({
|
|
262
|
+
list,
|
|
263
|
+
total: totalResult?.total ?? 0,
|
|
264
|
+
current,
|
|
265
|
+
pageSize,
|
|
266
|
+
}));
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* 关联查询
|
|
271
|
+
* @param {Object} options - 查询选项
|
|
272
|
+
* @param {string} options.joinTable - 关联表名
|
|
273
|
+
* @param {string} options.localField - 本地表字段
|
|
274
|
+
* @param {string} options.foreignField - 关联表字段
|
|
275
|
+
* @param {string} options.select - 查询字段,默认"*"
|
|
276
|
+
* @param {Object} options.where - 查询条件
|
|
277
|
+
* @returns {Object} Knex查询构建器
|
|
278
|
+
*/
|
|
279
|
+
join(options) {
|
|
280
|
+
const { joinTable, localField, foreignField, select = "*", where = {} } = options;
|
|
281
|
+
let q = db(this.tableName)
|
|
282
|
+
.join(joinTable, `${this.tableName}.${localField}`, "=", `${joinTable}.${foreignField}`)
|
|
283
|
+
.select(select);
|
|
284
|
+
|
|
285
|
+
if (Object.keys(where).length > 0) {
|
|
286
|
+
q = q.where(where);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return q;
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* 执行事务
|
|
294
|
+
* @param {Function} callback - 事务回调函数
|
|
295
|
+
* @returns {Promise} 事务执行结果
|
|
296
|
+
*/
|
|
297
|
+
transaction(callback) {
|
|
298
|
+
return db.transaction(callback);
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* 执行原生SQL
|
|
303
|
+
* @param {string} sql - SQL语句
|
|
304
|
+
* @param {Array} bindings - 绑定参数
|
|
305
|
+
* @returns {Promise} 查询结果
|
|
306
|
+
*/
|
|
307
|
+
raw(sql, bindings) {
|
|
308
|
+
return db.raw(sql, bindings);
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export default DatabaseManager;
|