chanjs 2.7.4 → 2.7.5

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.
Files changed (93) hide show
  1. package/USAGE.md +533 -0
  2. package/config/index.js +37 -6
  3. package/core/App.js +166 -0
  4. package/core/Container.js +77 -0
  5. package/core/Controller.js +29 -0
  6. package/core/Database.js +93 -0
  7. package/core/Repository.js +327 -0
  8. package/core/Service.js +11 -0
  9. package/core/bootstrap/error-handler.js +104 -0
  10. package/core/bootstrap/hook-runner.js +64 -0
  11. package/core/bootstrap/middleware.js +35 -0
  12. package/core/bootstrap/router-loader.js +53 -0
  13. package/core/errors.js +224 -0
  14. package/core/loader.js +89 -0
  15. package/core/registry.js +17 -0
  16. package/doc/Cache.md +279 -106
  17. package/doc/Common.md +590 -134
  18. package/doc/Controller.md +166 -95
  19. package/doc/Help.md +299 -698
  20. package/doc/QuickStart.md +116 -0
  21. package/doc/Repository.md +560 -0
  22. package/doc/Service.md +201 -527
  23. package/index.js +75 -37
  24. package/middleware/body.js +17 -0
  25. package/middleware/cookie.js +7 -15
  26. package/middleware/cors.js +9 -27
  27. package/middleware/favicon.js +7 -17
  28. package/middleware/header.js +15 -16
  29. package/middleware/index.js +11 -11
  30. package/middleware/log.js +26 -56
  31. package/middleware/static.js +15 -28
  32. package/middleware/template.js +75 -115
  33. package/middleware/validate.js +79 -0
  34. package/middleware/waf.js +174 -197
  35. package/package.json +9 -2
  36. package/response/code.js +73 -0
  37. package/response/index.js +9 -6
  38. package/response/response.js +82 -236
  39. package/security/checker.js +26 -74
  40. package/security/index.js +4 -9
  41. package/security/jwt.js +69 -142
  42. package/security/keywords.js +32 -136
  43. package/security/rate-limit.js +38 -80
  44. package/security/sign.js +83 -176
  45. package/security/xss-filter.js +21 -53
  46. package/storage/cache.js +57 -196
  47. package/storage/index.js +3 -6
  48. package/storage/redis.js +123 -181
  49. package/storage/store.js +163 -188
  50. package/utils/data-parse.js +42 -186
  51. package/utils/file.js +73 -244
  52. package/utils/filter.js +22 -25
  53. package/utils/html.js +49 -33
  54. package/utils/index.js +21 -7
  55. package/utils/ip.js +31 -71
  56. package/utils/logger.js +117 -0
  57. package/utils/pages.js +55 -0
  58. package/utils/paths.js +18 -0
  59. package/utils/request.js +94 -136
  60. package/utils/signal.js +87 -0
  61. package/utils/time.js +33 -75
  62. package/utils/tree.js +112 -104
  63. package/App.js +0 -533
  64. package/base/Aop.js +0 -195
  65. package/base/Container.js +0 -161
  66. package/base/Controller.js +0 -65
  67. package/base/Database.js +0 -133
  68. package/base/Event.js +0 -61
  69. package/base/Repository.js +0 -644
  70. package/common/api.js +0 -35
  71. package/common/code.js +0 -52
  72. package/common/email.js +0 -191
  73. package/common/index.js +0 -5
  74. package/common/pages.js +0 -120
  75. package/common/utils.js +0 -73
  76. package/config/code.js +0 -166
  77. package/config/paths.js +0 -60
  78. package/doc/Aop.md +0 -269
  79. package/doc/Email.md +0 -114
  80. package/doc/Event.md +0 -232
  81. package/global/env.js +0 -11
  82. package/global/import.js +0 -39
  83. package/global/index.js +0 -8
  84. package/helper/index.js +0 -79
  85. package/loader/index.js +0 -6
  86. package/loader/loader.js +0 -138
  87. package/middleware/compress.js +0 -185
  88. package/middleware/setBody.js +0 -32
  89. package/realtime/index.js +0 -7
  90. package/realtime/sse.js +0 -424
  91. package/realtime/websocket.js +0 -540
  92. package/schedule/index.js +0 -6
  93. package/schedule/schedule.js +0 -491
@@ -1,258 +1,104 @@
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";
1
+ import { CODE_OK, CODE_BUSINESS_FAIL, CODE_NOT_FOUND, CODE_SYSTEM_ERROR, getCodeMsg } from "./code.js";
2
+ import { isAppError } from "../core/errors.js";
3
+ import { htmlEncode } from "../utils/html.js";
10
4
 
11
5
  /**
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: {} }
6
+ * 统一响应序列化工具(纯函数:无 IO、无日志、无环境判断、无 DB 感知)
7
+ * 仅做数据格式化,可复用于定时任务 / RPC / 接口返回,与全局错误处理器解耦
49
8
  */
9
+ export const success = ({ data = {}, msg = getCodeMsg(CODE_OK) } = {}) => ({
10
+ success: true, code: CODE_OK, msg, data,
11
+ });
50
12
 
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
- }
13
+ export const fail = ({ msg = getCodeMsg(CODE_BUSINESS_FAIL), data = {}, code = CODE_BUSINESS_FAIL } = {}) => ({
14
+ success: false, code, msg, data,
15
+ });
118
16
 
119
- return {
120
- code: errorCode,
121
- msg: ERROR_MESSAGES[errorCode] || error?.message || "服务器内部错误",
122
- statusCode,
123
- };
124
- }
17
+ /** 404 路由不存在专用返回体 */
18
+ export const routeNotFound = req => ({
19
+ success: false,
20
+ code: CODE_NOT_FOUND,
21
+ msg: "请求的资源不存在",
22
+ data: { path: req.originalUrl || req.url, method: req.method },
23
+ });
125
24
 
126
25
  /**
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)附带数据库错误详情
26
+ * 统一错误序列化格式化(纯函数)
27
+ * - 业务错误(AppError 体系):提取 code / msg + 自定义扩展字段
28
+ * - 系统 / 未知错误:生产环境强制脱敏,仅 exposeDetail=true 时附带堆栈
137
29
  */
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
- };
30
+ export function serializeError(err, exposeDetail = false) {
31
+ if (isAppError(err)) {
32
+ const result = { success: false, code: err.code, msg: err.message };
33
+ const extra = {};
34
+ for (const key of Object.getOwnPropertyNames(err)) {
35
+ const val = err[key];
36
+ if (val === undefined || val === null) continue;
37
+ if (typeof val === "function" || typeof val === "symbol") continue;
38
+ try { extra[key] = val && typeof val === "object" && !Array.isArray(val) ? JSON.stringify(val) : val; }
39
+ catch { extra[key] = "[unserializable]"; }
40
+ }
41
+ if (Object.keys(extra).length > 0) result.data = extra;
42
+ return result;
156
43
  }
157
44
 
158
- const msg = getCodeMsg(code, "操作失败");
45
+ // 原生未知系统错误:生产环境强制脱敏,不泄露 SQL / 堆栈
159
46
  return {
160
47
  success: false,
161
- msg,
162
- code,
163
- data,
48
+ code: CODE_SYSTEM_ERROR,
49
+ msg: err?.message || "系统内部错误",
50
+ ...(exposeDetail && err?.stack ? { data: { stack: err.stack } } : {}),
164
51
  };
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
- };
52
+ }
191
53
 
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
- });
54
+ // =================== HTML 错误页(纯函数,无模板引擎依赖) ===================
207
55
 
208
56
  /**
209
- * 生成 404 响应(接口不存在)
210
- * @param {Object} req - Express 请求对象
211
- * @returns {Object} 404 响应对象
212
- * @description
213
- * HTTP Status 404,业务 code 1004
57
+ * 框架内置兜底错误HTML页面
214
58
  */
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
- };
59
+ export function buildErrorHtml(status, errorMsg, code, req) {
60
+ const url = htmlEncode(req.originalUrl || req.url);
61
+ const method = htmlEncode(req.method);
62
+ const msg = htmlEncode(errorMsg || "服务器内部错误");
63
+ const codeText = htmlEncode(code ? String(code) : `HTTP_${status}`);
64
+
65
+ return `<!DOCTYPE html>
66
+ <html lang="zh-CN">
67
+ <head>
68
+ <meta charset="utf-8">
69
+ <meta name="viewport" content="width=device-width,initial-scale=1">
70
+ <title>${status} 服务异常</title>
71
+ <style>
72
+ *{margin:0;padding:0;box-sizing:border-box}
73
+ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background:#f5f7fa;color:#2c3e50;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
74
+ .box{max-width:620px;width:100%;background:#fff;border-radius:12px;box-shadow:0 2px 16px rgba(0,0,0,.06);padding:40px 32px;}
75
+ .code{font-size:64px;font-weight:700;line-height:1;color:#1677ff;margin-bottom:8px;text-align:center}
76
+ .title{font-size:18px;font-weight:600;margin-bottom:12px;color:rgba(0,0,0,0.88);text-align:center}
77
+ .msg{font-size:14px;color:#262626;line-height:1.6;margin-bottom:20px;word-break:break-all;background: #fafafa;padding: 20px;border-radius: 8px;}
78
+ .url{font-size:14px;color:#434343;margin-bottom:24px;word-break:break-all}
79
+ </style>
80
+ </head>
81
+ <body>
82
+ <div class="box">
83
+ <div class="code">${status}</div>
84
+ <div class="title">服务异常</div>
85
+ <div class="msg">${msg}</div>
86
+ <div class="url">请求地址:${method} ${url}</div>
87
+ <div class="url">错误码:${codeText}</div>
88
+ </div>
89
+ </body>
90
+ </html>`;
222
91
  }
223
92
 
224
93
  /**
225
- * 生成错误响应(Express 错误处理中间件用)
226
- * @param {Error} err - 错误对象
227
- * @param {Object} req - Express 请求对象
228
- * @returns {Object} 错误响应对象
229
- * @description
230
- * 用于 Express 全局错误处理中间件
231
- * 自动解析数据库错误并映射为业务 code
94
+ * 统一错误响应出口(HTML / JSON 自动分流)
95
+ * - API 请求(XHR、Accept 优先 json)→ 一律返回 JSON
96
+ * - 浏览器页面请求(Accept 优先 html)→ 渲染内置 HTML 错误页
232
97
  */
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
- };
98
+ export function respondError(res, req, { httpStatus = 500, code = 500, msg = "服务器内部错误", data = null } = {}) {
99
+ const wantsJson = req && (req.xhr || req.accepts?.(["json", "html"]) === "json");
100
+ if (!wantsJson && req?.accepts?.("html")) {
101
+ return res.status(httpStatus).type("html").send(buildErrorHtml(httpStatus, msg, code, req));
102
+ }
103
+ return res.status(httpStatus).json({ success: false, code, msg, data });
258
104
  }
@@ -1,83 +1,35 @@
1
- import { keywordRegexCache } from "./keywords.js";
1
+ import { KEYWORD_RULES, keywordRegexCache, SORTED_CATEGORIES } from "./keywords.js";
2
2
 
3
3
  /**
4
- * 安全检查工具
5
- * 提供关键词检测和路径忽略检查功能
4
+ * 恶意关键词检测:单次遍历预排序的分类列表,利用捕获组直接定位命中关键词
5
+ * @param {string} fullText 待检测文本
6
+ * @returns {{category: string; keyword: string}|null}
6
7
  */
7
-
8
- /**
9
- * 检查文本中是否包含恶意关键词
10
- * @param {string} fullText - 要检查的完整文本
11
- * @returns {Object|null} 检测结果,包含 category 和 keyword,未检测到返回 null
12
- * @description
13
- * 性能优化(P2 #19):
14
- * 1. 先用每类合并的大正则做预检(单次 test 判断该类是否命中)
15
- * 2. 预检命中后再遍历该类的具体关键词定位命中项
16
- * 3. 正常请求:8 次大正则 test,比原版 80+ 次小正则 test 快 10 倍
17
- * 4. 恶意请求:大正则预检 + 该类关键词遍历,开销略增但可接受
18
- *
19
- * 按优先级检查:sqlInjection / xss / commandInjection 优先
20
- * @example
21
- * const result = checkKeywords('SELECT * FROM users WHERE 1=1');
22
- * console.log(result); // { category: 'sqlInjection', keyword: 'union select' }
23
- */
24
- export function checkKeywords(fullText) {
25
- if (!fullText?.trim()) return null;
26
-
27
- const priorityCategories = ['sqlInjection', 'xss', 'commandInjection'];
28
- const otherCategories = Object.keys(keywordRegexCache).filter(c => !priorityCategories.includes(c));
29
-
30
- // 优先类别
31
- for (const category of priorityCategories) {
32
- const cache = keywordRegexCache[category];
33
- if (!cache?.mergedRegex) continue;
34
-
35
- // 预检:大正则一次 test
36
- if (!cache.mergedRegex.test(fullText)) continue;
37
-
38
- // 命中:遍历定位具体关键词
39
- for (const { keyword, regex } of cache.patterns) {
40
- if (regex.test(fullText)) {
41
- return { category, keyword };
42
- }
43
- }
8
+ export const checkKeywords = fullText => {
9
+ const text = fullText?.trim();
10
+ if (!text) return null;
11
+
12
+ for (const cat of SORTED_CATEGORIES) {
13
+ const match = keywordRegexCache[cat].merged.exec(text);
14
+ if (!match) continue;
15
+ // capture[0]是整体匹配,capture[1..]是每个关键词的捕获组
16
+ const idx = match.findIndex((g, i) => i > 0 && g);
17
+ return { category: cat, keyword: KEYWORD_RULES[cat][idx - 1] };
44
18
  }
45
-
46
- // 其他类别
47
- for (const category of otherCategories) {
48
- const cache = keywordRegexCache[category];
49
- if (!cache?.mergedRegex) continue;
50
-
51
- if (!cache.mergedRegex.test(fullText)) continue;
52
-
53
- for (const { keyword, regex } of cache.patterns) {
54
- if (regex.test(fullText)) {
55
- return { category, keyword };
56
- }
57
- }
58
- }
59
-
60
19
  return null;
61
- }
20
+ };
62
21
 
63
22
  /**
64
- * 检查路径是否在忽略列表中
65
- * @param {string} path - 要检查的路径
66
- * @param {Array<string>} ignorePaths - 忽略路径数组
67
- * @returns {boolean} 是否应该忽略该路径
68
- * @description
69
- * 检查给定路径是否匹配忽略列表中的任意路径
70
- * 支持精确匹配和前缀匹配
71
- * @example
72
- * isIgnored('/api/health', ['/api/health', '/metrics']); // true
73
- * isIgnored('/api/users', ['/api/health']); // false
23
+ * 路径忽略校验:大小写不敏感、自动去除末尾斜杠,支持精确/前缀匹配
24
+ * @param {string} path 当前请求路径
25
+ * @param {string[]} ignorePaths 忽略路径列表
26
+ * @returns {boolean}
74
27
  */
75
- export function isIgnored(path, ignorePaths) {
76
- if (!path || !ignorePaths?.length) return false;
77
-
78
- const normalizedPath = path.trim().toLowerCase().replace(/\/$/, '');
79
- return ignorePaths.some(p => {
80
- const normalizedP = p.trim().toLowerCase().replace(/\/$/, '');
81
- return normalizedPath === normalizedP || normalizedPath.startsWith(`${normalizedP}/`);
28
+ export const isIgnored = (path, ignorePaths) => {
29
+ if (!path || !Array.isArray(ignorePaths) || !ignorePaths.length) return false;
30
+ const target = path.trim().toLowerCase().replace(/\/$/, "");
31
+ return ignorePaths.some(raw => {
32
+ const rule = raw.trim().toLowerCase().replace(/\/$/, "");
33
+ return target === rule || target.startsWith(`${rule}/`);
82
34
  });
83
- }
35
+ };
package/security/index.js CHANGED
@@ -1,14 +1,9 @@
1
1
  /**
2
- * 安全模块 - 关键词检查/XSS过滤/签名加密/JWT/限流
3
- * - checker + keywords: 敏感词检测(大正则预检优化)
4
- * - xss-filter: XSS 过滤(WeakSet 防循环引用)
5
- * - sign: AES-256-GCM 签名加密(timingSafeEqual 防时序攻击)
6
- * - jwt: JWT 令牌生成/验证
7
- * - rate-limit: IP 维度限流(服务端存储)
2
+ * security 模块聚合导出
8
3
  */
9
4
  export { checkKeywords, isIgnored } from "./checker.js";
10
- export { keywordRegexCache, KEYWORD_RULES } from "./keywords.js";
5
+ export { keywordRegexCache } from "./keywords.js";
11
6
  export { filterXSS } from "./xss-filter.js";
12
- export { signData, verifySign, aesEncrypt, aesDecrypt } from "./sign.js";
13
- export { verifyToken, generateToken, setToken, getToken, revokeToken, isTokenRevoked } from "./jwt.js";
7
+ export { setToken, getToken } from "./jwt.js";
8
+ export { aesEncrypt, aesDecrypt } from "./sign.js";
14
9
  export { createRateLimitMiddleware } from "./rate-limit.js";