chanjs 2.7.2 → 2.7.4
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 +232 -16
- package/base/Aop.js +20 -3
- package/base/Container.js +80 -3
- package/base/Controller.js +38 -9
- package/base/Database.js +50 -0
- package/base/Event.js +12 -0
- package/base/{Service.js → Repository.js} +644 -539
- package/common/api.js +18 -8
- package/common/code.js +25 -15
- package/common/email.js +98 -17
- package/common/index.js +1 -1
- package/config/code.js +138 -82
- package/global/index.js +1 -1
- package/helper/index.js +43 -41
- package/index.js +19 -6
- package/loader/index.js +6 -0
- package/{helper → loader}/loader.js +41 -27
- package/middleware/compress.js +185 -0
- package/middleware/cors.js +36 -24
- package/middleware/header.js +5 -10
- package/middleware/index.js +1 -0
- package/middleware/log.js +27 -3
- package/middleware/setBody.js +9 -1
- package/middleware/static.js +2 -1
- package/middleware/template.js +139 -4
- package/middleware/waf.js +136 -76
- package/package.json +4 -4
- package/realtime/index.js +7 -0
- package/realtime/sse.js +424 -0
- package/realtime/websocket.js +540 -0
- package/response/index.js +12 -0
- package/response/response.js +258 -0
- package/schedule/index.js +6 -0
- package/schedule/schedule.js +491 -0
- package/{helper → security}/checker.js +23 -8
- package/security/index.js +14 -0
- package/{helper → security}/jwt.js +175 -107
- package/security/keywords.js +179 -0
- package/security/rate-limit.js +105 -0
- package/security/sign.js +210 -0
- package/security/xss-filter.js +63 -0
- package/storage/cache.js +258 -0
- package/storage/index.js +9 -0
- package/storage/redis.js +258 -0
- package/storage/store.js +266 -0
- package/{helper → utils}/file.js +106 -15
- package/{helper → utils}/filter.js +2 -1
- package/{helper → utils}/html.js +19 -1
- package/utils/index.js +34 -0
- package/{helper → utils}/ip.js +25 -16
- package/utils/request.js +172 -0
- package/{helper → utils}/time.js +1 -1
- package/utils/tree.js +121 -0
- package/common/category.js +0 -22
- package/common/sms.js +0 -104
- package/extend/art-template.js +0 -129
- package/extend/index.js +0 -6
- package/global/global.js +0 -63
- package/helper/cache.js +0 -187
- package/helper/keywords.js +0 -132
- package/helper/rate-limit.js +0 -116
- package/helper/request.js +0 -47
- package/helper/response.js +0 -180
- package/helper/sign.js +0 -96
- package/helper/tree.js +0 -77
- package/helper/xss-filter.js +0 -42
- /package/{helper → utils}/data-parse.js +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CODE,
|
|
3
|
+
DB_ERROR,
|
|
4
|
+
CODE_OK,
|
|
5
|
+
CODE_BUSINESS_FAIL,
|
|
6
|
+
CODE_SYSTEM_ERROR,
|
|
7
|
+
CODE_NOT_FOUND,
|
|
8
|
+
getCodeMsg,
|
|
9
|
+
} from "../config/code.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 响应工具函数
|
|
13
|
+
* 提供统一的响应格式和错误处理
|
|
14
|
+
*
|
|
15
|
+
* ============================================================
|
|
16
|
+
* 统一响应格式(三层 code 体系)
|
|
17
|
+
* ============================================================
|
|
18
|
+
* 所有响应都遵循以下结构:
|
|
19
|
+
* {
|
|
20
|
+
* success: boolean, // 业务是否成功(true/false)
|
|
21
|
+
* code: number, // 业务 code(0 成功 / 1xxx 业务 / 5xxx 系统 / 6xxx 数据库)
|
|
22
|
+
* msg: string, // 用户可见消息
|
|
23
|
+
* data: any // 业务数据
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* HTTP Status 与业务 code 解耦:
|
|
27
|
+
* - HTTP Status 由网关/Express 控制(200/400/401/403/404/500)
|
|
28
|
+
* - 业务 code 由业务层控制(0 / 1xxx / 5xxx / 6xxx)
|
|
29
|
+
* - 前端先看 HTTP Status,再看业务 code
|
|
30
|
+
*
|
|
31
|
+
* ============================================================
|
|
32
|
+
* 使用示例
|
|
33
|
+
* ============================================================
|
|
34
|
+
* // 成功
|
|
35
|
+
* success({ data: { list: [] } })
|
|
36
|
+
* // → { success: true, code: 0, msg: '操作成功', data: { list: [] } }
|
|
37
|
+
*
|
|
38
|
+
* // 业务失败(通用)
|
|
39
|
+
* fail({ msg: '栏目下存在文章' })
|
|
40
|
+
* // → { success: false, code: 1008, msg: '栏目下存在文章', data: {} }
|
|
41
|
+
*
|
|
42
|
+
* // 业务失败(指定 code)
|
|
43
|
+
* fail({ msg: '参数缺失', code: 1007 })
|
|
44
|
+
* // → { success: false, code: 1007, msg: '参数缺失', data: {} }
|
|
45
|
+
*
|
|
46
|
+
* // 错误(系统/数据库异常,err 必传)
|
|
47
|
+
* error({ err: dbError })
|
|
48
|
+
* // → { success: false, code: 6005, msg: '数据重复', data: {} }
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 错误消息映射(数据库错误码专用)
|
|
53
|
+
* 与 CODE 字典保持一致,独立出来便于按 code 取消息
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
const ERROR_MESSAGES = CODE;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 是否暴露错误详情(sql/stack)
|
|
60
|
+
* 显式环境变量控制,避免 development 模式自动暴露敏感信息
|
|
61
|
+
* - 默认 false:生产/开发都不暴露
|
|
62
|
+
* - 设 EXPOSE_ERR_DETAIL=true 后才返回 sql/stack/message 等详细信息
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
const EXPOSE_ERR_DETAIL = process.env.EXPOSE_ERR_DETAIL === 'true';
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 根据错误对象推断业务 code
|
|
69
|
+
* @private
|
|
70
|
+
* @param {Error} error - 错误对象
|
|
71
|
+
* @returns {number} 业务 code
|
|
72
|
+
*/
|
|
73
|
+
const inferErrorCode = (error) => {
|
|
74
|
+
if (!error?.message) return CODE_SYSTEM_ERROR;
|
|
75
|
+
|
|
76
|
+
const msg = error.message.toLowerCase();
|
|
77
|
+
if (msg.includes("syntax") || msg.includes("sql")) {
|
|
78
|
+
return 6008; // 数据库语法错误
|
|
79
|
+
}
|
|
80
|
+
if (msg.includes("connection closed") || msg.includes("connection lost")) {
|
|
81
|
+
return 6009; // 数据库连接关闭
|
|
82
|
+
}
|
|
83
|
+
if (msg.includes("permission") || msg.includes("access denied")) {
|
|
84
|
+
return 1003; // 权限不足
|
|
85
|
+
}
|
|
86
|
+
return CODE_SYSTEM_ERROR;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 解析数据库错误
|
|
91
|
+
* @param {Error} error - 数据库错误对象
|
|
92
|
+
* @returns {{code: number, msg: string, statusCode: number}} 包含 code、msg 和 HTTP statusCode
|
|
93
|
+
* @description
|
|
94
|
+
* 将数据库原生错误码映射为业务 code,并给出对应的 HTTP statusCode
|
|
95
|
+
* - 6xxx 数据库错误 → HTTP 500
|
|
96
|
+
* - 1xxx 业务错误 → HTTP 400
|
|
97
|
+
* - 其他 → HTTP 500
|
|
98
|
+
*/
|
|
99
|
+
export function parseDatabaseError(error) {
|
|
100
|
+
let errorCode;
|
|
101
|
+
if (error?.code && DB_ERROR[error.code]) {
|
|
102
|
+
errorCode = DB_ERROR[error.code];
|
|
103
|
+
} else {
|
|
104
|
+
errorCode = inferErrorCode(error);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 根据 code 段位决定 HTTP statusCode
|
|
108
|
+
let statusCode;
|
|
109
|
+
if (errorCode >= 6000) {
|
|
110
|
+
statusCode = 500; // 数据库错误 → 500
|
|
111
|
+
} else if (errorCode >= 5000) {
|
|
112
|
+
statusCode = 500; // 系统错误 → 500
|
|
113
|
+
} else if (errorCode >= 1000) {
|
|
114
|
+
statusCode = 400; // 业务错误 → 400
|
|
115
|
+
} else {
|
|
116
|
+
statusCode = 500; // 兜底
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
code: errorCode,
|
|
121
|
+
msg: ERROR_MESSAGES[errorCode] || error?.message || "服务器内部错误",
|
|
122
|
+
statusCode,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 生成错误响应(系统/数据库异常用)
|
|
128
|
+
* @param {Object} options - 响应选项
|
|
129
|
+
* @param {Error} [options.err] - 错误对象(必传,用于解析 code)
|
|
130
|
+
* @param {Object} [options.data={}] - 响应数据
|
|
131
|
+
* @param {number} [options.code=5001] - 错误 code(err 为空时使用)
|
|
132
|
+
* @returns {Object} 错误响应对象
|
|
133
|
+
* @description
|
|
134
|
+
* - 传 err:自动解析数据库错误码并映射为业务 code
|
|
135
|
+
* - 不传 err:使用传入的 code 或默认 5001
|
|
136
|
+
* 开发环境下(NODE_ENV=development)附带数据库错误详情
|
|
137
|
+
*/
|
|
138
|
+
export const error = ({ err, data = {}, code = CODE_SYSTEM_ERROR } = {}) => {
|
|
139
|
+
if (err) {
|
|
140
|
+
console.error("[DB Error]", err?.message || err);
|
|
141
|
+
const errorCode = err?.code && DB_ERROR[err.code]
|
|
142
|
+
? DB_ERROR[err.code]
|
|
143
|
+
: inferErrorCode(err);
|
|
144
|
+
const msg = ERROR_MESSAGES[errorCode] || "操作失败";
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
success: false,
|
|
148
|
+
msg,
|
|
149
|
+
code: errorCode,
|
|
150
|
+
data: EXPOSE_ERR_DETAIL ? {
|
|
151
|
+
sql: err?.sql,
|
|
152
|
+
sqlMessage: err?.sqlMessage,
|
|
153
|
+
message: err?.message,
|
|
154
|
+
} : {},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const msg = getCodeMsg(code, "操作失败");
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
msg,
|
|
162
|
+
code,
|
|
163
|
+
data,
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 生成失败响应(业务失败用)
|
|
169
|
+
* @param {Object} options - 响应选项
|
|
170
|
+
* @param {string} [options.msg="操作失败"] - 错误消息
|
|
171
|
+
* @param {Object} [options.data={}] - 响应数据
|
|
172
|
+
* @param {number} [options.code=1008] - 业务 code(默认 1008 业务处理失败)
|
|
173
|
+
* @returns {Object} 失败响应对象
|
|
174
|
+
* @description
|
|
175
|
+
* 用于业务逻辑失败(如:栏目下存在文章、参数缺失等)
|
|
176
|
+
* 与 error() 区别:fail 用于业务可恢复错误,error 用于系统/数据库异常
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* fail({ msg: '栏目下存在文章' }) // → code: 1008
|
|
180
|
+
* fail({ msg: '参数缺失', code: 1007 }) // → code: 1007
|
|
181
|
+
* fail({ msg: '权限不足', code: 1003 }) // → code: 1003
|
|
182
|
+
*/
|
|
183
|
+
export const fail = ({ msg = "操作失败", data = {}, code = CODE_BUSINESS_FAIL } = {}) => {
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
msg,
|
|
187
|
+
code,
|
|
188
|
+
data,
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 生成成功响应
|
|
194
|
+
* @param {Object} options - 响应选项
|
|
195
|
+
* @param {Object} [options.data={}] - 响应数据
|
|
196
|
+
* @param {string} [options.msg="操作成功"] - 成功消息
|
|
197
|
+
* @returns {Object} 成功响应对象
|
|
198
|
+
* @description
|
|
199
|
+
* code 固定为 0(不再用 200,避免与 HTTP 200 混淆)
|
|
200
|
+
*/
|
|
201
|
+
export const success = ({ data = {}, msg = "操作成功" } = {}) => ({
|
|
202
|
+
success: true,
|
|
203
|
+
msg,
|
|
204
|
+
code: CODE_OK,
|
|
205
|
+
data,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 生成 404 响应(接口不存在)
|
|
210
|
+
* @param {Object} req - Express 请求对象
|
|
211
|
+
* @returns {Object} 404 响应对象
|
|
212
|
+
* @description
|
|
213
|
+
* HTTP Status 404,业务 code 1004
|
|
214
|
+
*/
|
|
215
|
+
export function notFoundResponse(req) {
|
|
216
|
+
return {
|
|
217
|
+
success: false,
|
|
218
|
+
msg: "接口不存在",
|
|
219
|
+
code: CODE_NOT_FOUND,
|
|
220
|
+
data: { path: req.path, method: req.method },
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* 生成错误响应(Express 错误处理中间件用)
|
|
226
|
+
* @param {Error} err - 错误对象
|
|
227
|
+
* @param {Object} req - Express 请求对象
|
|
228
|
+
* @returns {Object} 错误响应对象
|
|
229
|
+
* @description
|
|
230
|
+
* 用于 Express 全局错误处理中间件
|
|
231
|
+
* 自动解析数据库错误并映射为业务 code
|
|
232
|
+
*/
|
|
233
|
+
export function errorResponse(err, req) {
|
|
234
|
+
const errorInfo = parseDatabaseError(err);
|
|
235
|
+
|
|
236
|
+
console.error(`[Error Handler] ${errorInfo.msg} - ${err?.message}`, {
|
|
237
|
+
code: errorInfo.code,
|
|
238
|
+
path: req?.path,
|
|
239
|
+
method: req?.method,
|
|
240
|
+
sql: err?.sql,
|
|
241
|
+
sqlMessage: err?.sqlMessage,
|
|
242
|
+
stack: err?.stack,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
success: false,
|
|
247
|
+
msg: errorInfo.msg,
|
|
248
|
+
code: errorInfo.code,
|
|
249
|
+
data: EXPOSE_ERR_DETAIL
|
|
250
|
+
? {
|
|
251
|
+
message: err?.message,
|
|
252
|
+
sql: err?.sql,
|
|
253
|
+
sqlMessage: err?.sqlMessage,
|
|
254
|
+
stack: err?.stack,
|
|
255
|
+
}
|
|
256
|
+
: {},
|
|
257
|
+
};
|
|
258
|
+
}
|