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.
Files changed (61) hide show
  1. package/App.js +387 -0
  2. package/base/Context.js +78 -0
  3. package/base/Controller.js +137 -0
  4. package/base/Database.js +314 -0
  5. package/base/Service.js +539 -0
  6. package/common/api.js +25 -0
  7. package/common/category.js +22 -0
  8. package/common/code.js +42 -0
  9. package/common/email.js +110 -0
  10. package/common/index.js +7 -0
  11. package/common/pages.js +86 -0
  12. package/common/sms.js +104 -0
  13. package/common/utils.js +73 -0
  14. package/config/code.js +110 -52
  15. package/config/index.js +10 -0
  16. package/config/paths.js +60 -0
  17. package/extend/art-template.js +46 -28
  18. package/extend/index.js +6 -0
  19. package/global/env.js +11 -5
  20. package/global/global.js +63 -39
  21. package/global/import.js +43 -39
  22. package/global/index.js +8 -3
  23. package/helper/cache.js +182 -0
  24. package/helper/data-parse.js +121 -37
  25. package/helper/db.js +71 -83
  26. package/helper/file.js +158 -208
  27. package/helper/filter.js +34 -0
  28. package/helper/html.js +30 -47
  29. package/helper/index.js +29 -5
  30. package/helper/ip.js +48 -31
  31. package/helper/jwt.js +78 -11
  32. package/helper/loader.js +93 -50
  33. package/helper/request.js +41 -144
  34. package/helper/sign.js +96 -33
  35. package/helper/time.js +89 -74
  36. package/helper/tree.js +77 -0
  37. package/index.js +15 -181
  38. package/middleware/cookie.js +20 -4
  39. package/middleware/cors.js +20 -0
  40. package/middleware/favicon.js +21 -5
  41. package/middleware/header.js +26 -9
  42. package/middleware/index.js +14 -23
  43. package/middleware/preventRetry.js +30 -0
  44. package/middleware/setBody.js +24 -10
  45. package/middleware/static.js +31 -10
  46. package/middleware/template.js +34 -14
  47. package/middleware/validator.js +43 -23
  48. package/middleware/waf.js +147 -287
  49. package/package.json +1 -1
  50. package/utils/checker.js +68 -0
  51. package/utils/error-handler.js +115 -0
  52. package/utils/error.js +81 -0
  53. package/utils/index.js +6 -0
  54. package/utils/keywords.js +126 -0
  55. package/utils/rate-limit.js +116 -0
  56. package/utils/response.js +103 -64
  57. package/utils/xss-filter.js +42 -0
  58. package/core/controller.js +0 -33
  59. package/core/index.js +0 -3
  60. package/core/service.js +0 -307
  61. package/middleware/log.js +0 -21
package/helper/time.js CHANGED
@@ -1,74 +1,89 @@
1
- import dayjs from "dayjs";
2
- import "dayjs/locale/zh-cn.js";
3
- import relativeTime from "dayjs/plugin/relativeTime.js";
4
-
5
- dayjs.extend(relativeTime);
6
- dayjs.locale("zh-cn");
7
-
8
- /**
9
- * @description 格式化时间
10
- * @param {Array} data 数组
11
- * @param {Boolean} time 是否开启具体时间
12
- * @param {String} format YYYY-MM-DD HH:mm:ss
13
- * @returns 返回处理过的数组
14
- */
15
- export const formatDay = (data, time = true, format = "YYYY-MM-DD") => {
16
- data.forEach((item) => {
17
- if (item.createdAt) {
18
- item.createdAt = time
19
- ? dayjs(item.createdAt).format(format)
20
- : dayjs(item.createdAt).fromNow().replace(" ", "");
21
- }
22
- });
23
- return data;
24
- };
25
-
26
- export const formatTime = (data, format = "YYYY-MM-DD HH:mm:ss") => {
27
- return dayjs(data).format(format);
28
- };
29
-
30
- /**
31
- * 格式化对象或数组中的日期字段
32
- * @param {Object|Array} data - 要格式化的数据
33
- * @param {Object} options - 配置选项
34
- * @param {Array} options.fields - 要格式化的字段名,默认 ['createdAt', 'updatedAt']
35
- * @param {String} options.format - 日期格式,默认 'YYYY-MM-DD HH:mm:ss'
36
- * @returns {Object|Array} - 格式化后的数据
37
- */
38
- export const formatDateFields = (data, options = {}) => {
39
- const {
40
- fields = ['createdAt', 'updatedAt'],
41
- format = 'YYYY-MM-DD HH:mm:ss',
42
- } = options;
43
-
44
- const isPlainObject = (val) =>
45
- Object.prototype.toString.call(val) === '[object Object]';
46
-
47
- if (isPlainObject(data)) {
48
- const result = { ...data };
49
- fields.forEach(field => {
50
- const value = result[field];
51
- if (value != null) {
52
- const type = typeof value;
53
- if (type === 'string' || type === 'number' || value instanceof Date) {
54
- try {
55
- result[field] = formatTime(value, format);
56
- } catch (e) {
57
- console.warn(`格式化字段 ${field} 失败:`, e.message);
58
- }
59
- }
60
- }
61
- });
62
- return result;
63
- }
64
-
65
- if (Array.isArray(data)) {
66
- return data.map(item =>
67
- typeof item === 'object' && item !== null
68
- ? formatDateFields(item, options)
69
- : item
70
- );
71
- }
72
-
73
- return data;
74
- };;
1
+ /**
2
+ * 格式化时间戳为指定格式的字符串
3
+ * @param {number|string|Date} timestamp - 时间戳、日期字符串或 Date 对象
4
+ * @param {string} [format='YYYY-MM-DD HH:mm:ss'] - 输出格式
5
+ * @returns {string} 格式化后的时间字符串
6
+ * @description
7
+ * 支持的格式占位符:
8
+ * - YYYY: 四位年份
9
+ * - MM: 两位月份(01-12)
10
+ * - DD: 两位日期(01-31)
11
+ * - HH: 两位小时(00-23)
12
+ * - mm: 两位分钟(00-59)
13
+ * - ss: 两位秒数(00-59)
14
+ * @example
15
+ * formatTime(1704067200000); // '2024-01-01 00:00:00'
16
+ * formatTime(1704067200000, 'YYYY/MM/DD'); // '2024/01/01'
17
+ * formatTime('2024-01-01', 'YYYY-MM-DD'); // '2024-01-01'
18
+ */
19
+ export function formatTime(timestamp, format = 'YYYY-MM-DD HH:mm:ss') {
20
+ try {
21
+ const date = new Date(timestamp);
22
+ if (isNaN(date.getTime())) {
23
+ return timestamp;
24
+ }
25
+ const year = date.getFullYear();
26
+ const month = String(date.getMonth() + 1).padStart(2, '0');
27
+ const day = String(date.getDate()).padStart(2, '0');
28
+ const hours = String(date.getHours()).padStart(2, '0');
29
+ const minutes = String(date.getMinutes()).padStart(2, '0');
30
+ const seconds = String(date.getSeconds()).padStart(2, '0');
31
+
32
+ return format
33
+ .replace('YYYY', year)
34
+ .replace('MM', month)
35
+ .replace('DD', day)
36
+ .replace('HH', hours)
37
+ .replace('mm', minutes)
38
+ .replace('ss', seconds);
39
+ } catch (error) {
40
+ console.error('[formatTime] 格式化时间失败:', error, 'timestamp:', timestamp);
41
+ return timestamp;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * 格式化对象或数组中的日期字段
47
+ * @param {Object|Array<Object>} data - 要处理的数据对象或数组
48
+ * @param {Array<string>} [fields] - 需要格式化的字段名数组(可选,默认处理常用日期字段)
49
+ * @returns {Object|Array<Object>} 处理后的数据
50
+ * @description
51
+ * 将对象或数组中指定的日期字段格式化为 'YYYY-MM-DD HH:mm:ss' 格式
52
+ * 支持递归处理数组中的每个对象
53
+ * 自动匹配下划线和驼峰格式的字段名(如 createdAt/created_at)
54
+ * @example
55
+ * const data = { id: 1, createdAt: 1704067200000, updatedAt: 1704067200000 };
56
+ * const result = formatDateFields(data);
57
+ * console.log(result);
58
+ * // { id: 1, createdAt: '2024-01-01 00:00:00', updatedAt: '2024-01-01 00:00:00' }
59
+ *
60
+ * const list = [
61
+ * { id: 1, createdAt: 1704067200000 },
62
+ * { id: 2, createdAt: 1704153600000 }
63
+ * ];
64
+ * const formatted = formatDateFields(list);
65
+ * console.log(formatted);
66
+ * // [
67
+ * // { id: 1, createdAt: '2024-01-01 00:00:00' },
68
+ * // { id: 2, createdAt: '2024-01-02 00:00:00' }
69
+ * // ]
70
+ */
71
+ export function formatDateFields(data, fields) {
72
+ if (!data || typeof data !== 'object') return data;
73
+
74
+ if (Array.isArray(data)) {
75
+ return data.map(item => formatDateFields(item, fields));
76
+ }
77
+
78
+ const result = { ...data };
79
+
80
+ const defaultFields = ['createdAt', 'updatedAt', 'created_at', 'updated_at', 'createdAt', 'updatedAt'];
81
+ const targetFields = fields || defaultFields;
82
+
83
+ for (const field of targetFields) {
84
+ if (result[field]) {
85
+ result[field] = formatTime(result[field]);
86
+ }
87
+ }
88
+ return result;
89
+ }
package/helper/tree.js ADDED
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 树形结构工具函数
3
+ * 提供数组转树形结构和路径查找功能
4
+ */
5
+
6
+ /**
7
+ * 将扁平数组转换为树形结构
8
+ * @param {Array<Object>} arr - 扁平化的数据数组
9
+ * @param {number} [pid=0] - 父节点 ID,默认为 0
10
+ * @returns {Array<Object>} 树形结构数组
11
+ * @description
12
+ * 递归构建树形结构,为每个节点添加 level 属性
13
+ * 如果有子节点,则添加 children 属性
14
+ * @example
15
+ * const arr = [
16
+ * { id: 1, pid: 0, name: '根节点' },
17
+ * { id: 2, pid: 1, name: '子节点' },
18
+ * { id: 3, pid: 2, name: '孙节点' }
19
+ * ];
20
+ * const tree = tree(arr);
21
+ * // 返回带有 children 和 level 的树形结构
22
+ */
23
+ export function tree(arr, pid = 0) {
24
+ if(arr.length === 0){
25
+ return []
26
+ }
27
+ let result = [];
28
+ arr.forEach((item) => {
29
+ if (item.pid === pid) {
30
+ let children = tree(arr, item.id);
31
+ if (children.length) {
32
+ item.children = children;
33
+ }
34
+ item.level = 1;
35
+ result.push(item);
36
+ }
37
+ });
38
+ return result;
39
+ }
40
+
41
+ /**
42
+ * 根据 ID 查找节点路径
43
+ * @param {number} id - 要查找的节点 ID
44
+ * @param {Array<Object>} source - 数据源数组
45
+ * @returns {Array<Object>} 从根节点到目标节点的路径数组
46
+ * @description
47
+ * 递归查找指定 ID 的节点及其所有父节点
48
+ * 为每个节点添加 path 属性,包含拼音路径
49
+ * @example
50
+ * const arr = [
51
+ * { id: 1, pid: 0, pinyin: 'root' },
52
+ * { id: 2, pid: 1, pinyin: 'child' }
53
+ * ];
54
+ * const path = treeById(2, arr);
55
+ * // 返回包含 root 和 child 节点的数组
56
+ */
57
+ export function treeById(id, source) {
58
+ const arr = [];
59
+ const findId = (id, source) => {
60
+ for (let i = 0, item; i < source.length; i++) {
61
+ item = source[i];
62
+ if (item.id == id) {
63
+ arr.unshift(item);
64
+ if (item.pid != 0) {
65
+ findId(item.pid, source);
66
+ }
67
+ }
68
+ }
69
+ };
70
+ findId(id, source);
71
+ const _path = [];
72
+ arr.forEach((item) => {
73
+ _path.push("/" + item.pinyin);
74
+ item.path = _path.join("");
75
+ });
76
+ return arr;
77
+ }
package/index.js CHANGED
@@ -1,181 +1,15 @@
1
- import "./global/index.js";
2
- import path from "path";
3
- import fs from "fs";
4
- import express from "express";
5
-
6
- import { Controller, Service } from "./core/index.js";
7
- import {
8
- log,
9
- setCookie,
10
- setFavicon,
11
- setBody,
12
- setStatic,
13
- setHeader,
14
- setTemplate,
15
- Cors,
16
- validator,
17
- waf,
18
- } from "./middleware/index.js";
19
- import { db, loaderSort, loadConfig } from "./helper/index.js";
20
- import { dirname } from "./helper/file.js";
21
-
22
- class Chan {
23
- //版本号
24
- #version = "1.0.0";
25
- static helper = {};
26
- static common = {}; //公共方法
27
- static config = {}; //配置
28
- static Service = Service; //服务
29
- static Controller = Controller; //控制器
30
- static extend = {}; //组件扩展
31
- static middleware = {}; //中间件
32
- static modules = {}; //模块
33
-
34
- constructor() {
35
- this.app = express();
36
- this.router = express.Router();
37
- }
38
-
39
- beforeStart(cb) {
40
- cb && cb();
41
- }
42
-
43
- async init() {
44
- await this.config();
45
- await this.loadExtend(); //utils
46
- this.loadMiddleware();
47
- this.loadDB();
48
- }
49
-
50
- //加载配置文件
51
- async config() {
52
- let config = await loadConfig();
53
- //版本号,先从package.json中获取,如果没有,则使用默认版本号
54
- config.APP_VERSION = APP_VERSION || config.APP_VERSION;
55
- Chan.config = config;
56
- }
57
-
58
- //加载中间件
59
- async loadMiddleware() {
60
- const {
61
- views,
62
- env,
63
- APP_NAME,
64
- APP_VERSION,
65
- cookieKey,
66
- BODY_LIMIT,
67
- statics,
68
- logger,
69
- cors,
70
- PROXY,
71
- } = Chan.config;
72
-
73
- this.app.set("trust proxy", PROXY === "true" ? true : false);
74
- log(this.app, logger);
75
- setFavicon(this.app);
76
- setCookie(this.app, cookieKey);
77
- setBody(this.app, BODY_LIMIT);
78
- waf(this.app);
79
- setTemplate(this.app, { views, env });
80
- setStatic(this.app, statics);
81
- Cors(this.app, cors);
82
- setHeader(this.app, { APP_NAME, APP_VERSION });
83
- }
84
-
85
- //数据库操作
86
- loadDB() {
87
- if (Chan.config?.db?.length > 0) {
88
- Chan.config.db.map((item, index) => {
89
- if (index == 0) {
90
- Chan.knex = db(item);
91
- } else {
92
- Chan[`knex${index}`] = db(item);
93
- }
94
- });
95
- }
96
- }
97
-
98
- async loadRouter() {
99
- const configPath = path.join(APP_PATH, "modules");
100
- if (fs.existsSync(configPath)) {
101
- const dirs = loaderSort(Chan.config.modules);
102
- for (const item of dirs) {
103
- let router = await importFile(`app/modules/${item}/router.js`);
104
- router(this.app, this.router, Chan.config);
105
- }
106
- }
107
- }
108
-
109
- //通用路由,加载错误处理和500路由和爬虫处理
110
- async loadCommonRouter() {
111
- try {
112
- let router = await importFile("app/router.js");
113
- router(this.app, this.router, Chan.config);
114
- } catch (error) {
115
- console.log(error);
116
- }
117
- }
118
-
119
- async loadExtend() {
120
- let arr = [
121
- {
122
- _path: COMMON_PATH,
123
- key: "common",
124
- },
125
- {
126
- _path: HELPER_PATH,
127
- key: "helper",
128
- },
129
- {
130
- _path: path.join(dirname(import.meta.url), "helper"),
131
- key: "helper",
132
- },
133
- ];
134
- for (let item of arr) {
135
- await this.loadFn(item._path, item.key);
136
- }
137
- }
138
-
139
- async loadFn(_path, key) {
140
- if (fs.existsSync(_path)) {
141
- const files = fs
142
- .readdirSync(_path)
143
- .filter((file) => file.endsWith(".js"));
144
- for (const file of files) {
145
- const filePath = path.join(_path, file);
146
- let helperModule = await importFile(filePath);
147
- // Chan.common[file.replace(".js", "")] = helperModule;
148
- // 将模块导出的所有方法/属性,直接混入到 Chan.common 上
149
- Object.assign(Chan[key], helperModule);
150
- }
151
- }
152
- }
153
-
154
- async start(cb) {
155
- await this.init();
156
- await this.loadRouter();
157
- await this.loadCommonRouter();
158
-
159
- cb && cb();
160
- }
161
-
162
- getAllRouter() {
163
- // 获取所有路径
164
- const routes = this.router.stack
165
- .filter((r) => r.route) // 过滤掉中间件
166
- .map((r) => ({
167
- path: r.route.path,
168
- methods: Object.keys(r.route.methods),
169
- }));
170
- }
171
-
172
- run(cb) {
173
- const port = parseInt(Chan.config.PORT) || 3000;
174
- this.app.listen(port, () => {
175
- cb ? cb(port) : console.log(`Server is running on port ${port}`);
176
- });
177
- }
178
- }
179
-
180
- global.Chan = Chan;
181
- export default Chan;
1
+ export { default as Chan } from "./App.js";
2
+ export { default as Controller } from "./base/Controller.js";
3
+ export { default as Service } from "./base/Service.js";
4
+ export { default as AppContext } from "./base/Context.js";
5
+ export { default as DatabaseManager } from "./base/Database.js";
6
+
7
+ export * as helper from "./helper/index.js";
8
+ export * as utils from "./utils/index.js";
9
+ export * as middleware from "./middleware/index.js";
10
+ export * as config from "./config/index.js";
11
+ export * as common from "./common/index.js";
12
+ export * as extend from "./extend/index.js";
13
+
14
+ import Chan from "./App.js";
15
+ export default Chan;
@@ -1,4 +1,20 @@
1
- import cookieParser from "cookie-parser";
2
- export const setCookie = (app, cookieKey) => {
3
- app.use(cookieParser(cookieKey));
4
- };
1
+ import cookieParser from "cookie-parser";
2
+
3
+ /**
4
+ * Cookie 中间件配置
5
+ * 配置 Express 应用的 cookie 解析功能
6
+ */
7
+
8
+ /**
9
+ * 设置 Cookie 解析中间件
10
+ * @param {Object} app - Express 应用实例
11
+ * @param {string} cookieKey - Cookie 签名密钥
12
+ * @description
13
+ * 为 Express 应用配置 cookie-parser 中间件
14
+ * 使用密钥对 cookie 进行签名验证
15
+ * @example
16
+ * setCookie(app, 'my-secret-key');
17
+ */
18
+ export const setCookie = (app, cookieKey) => {
19
+ app.use(cookieParser(cookieKey));
20
+ };
@@ -1,4 +1,24 @@
1
1
  import cors from "cors";
2
+
3
+ /**
4
+ * CORS 中间件配置
5
+ * 配置跨域资源共享
6
+ */
7
+
8
+ /**
9
+ * 设置 CORS 中间件
10
+ * @param {Object} app - Express 应用实例
11
+ * @param {Object} _cors - CORS 配置选项
12
+ * @description
13
+ * 为 Express 应用配置 CORS 中间件
14
+ * 支持自定义 CORS 配置选项
15
+ * @example
16
+ * Cors(app, {
17
+ * origin: '*',
18
+ * methods: ['GET', 'POST'],
19
+ * allowedHeaders: ['Content-Type']
20
+ * });
21
+ */
2
22
  export const Cors = (app, _cors) => {
3
23
  app.use(cors(_cors));
4
24
  };
@@ -1,5 +1,21 @@
1
- import path from "path";
2
- import favicon from "serve-favicon";
3
- export const setFavicon = (app) => {
4
- app.use(favicon(path.join(ROOT_PATH, "public/favicon.ico")));
5
- };
1
+ import path from "path";
2
+ import favicon from "serve-favicon";
3
+ import { Paths } from "../config/paths.js";
4
+
5
+ /**
6
+ * Favicon 中间件配置
7
+ * 配置网站图标
8
+ */
9
+
10
+ /**
11
+ * 设置 Favicon 中间件
12
+ * @param {Object} app - Express 应用实例
13
+ * @description
14
+ * 为 Express 应用配置 favicon 服务
15
+ * 从 public 目录加载 favicon.ico 文件
16
+ * @example
17
+ * setFavicon(app);
18
+ */
19
+ export const setFavicon = (app) => {
20
+ app.use(favicon(path.join(Paths.publicPath, "favicon.ico")));
21
+ };
@@ -1,9 +1,26 @@
1
- export let setHeader = (app, { APP_NAME, APP_VERSION }) => {
2
- app.use((req, res, next) => {
3
- res.setHeader("Create-By", "Chanjs");
4
- res.setHeader("X-Powered-By", "ChanCMS");
5
- res.setHeader("ChanCMS", APP_VERSION);
6
- res.setHeader("Server", APP_NAME);
7
- next();
8
- });
9
- };
1
+ /**
2
+ * 响应头中间件配置
3
+ * 设置应用相关的响应头信息
4
+ */
5
+
6
+ /**
7
+ * 设置响应头中间件
8
+ * @param {Object} app - Express 应用实例
9
+ * @param {Object} options - 配置选项
10
+ * @param {string} options.APP_NAME - 应用名称
11
+ * @param {string} options.APP_VERSION - 应用版本
12
+ * @description
13
+ * 为所有响应添加自定义响应头
14
+ * 包含 Create-By、X-Powered-By、ChanCMS、Server 等头
15
+ * @example
16
+ * setHeader(app, { APP_NAME: 'MyApp', APP_VERSION: '1.0.0' });
17
+ */
18
+ export let setHeader = (app, { APP_NAME, APP_VERSION }) => {
19
+ app.use((req, res, next) => {
20
+ res.setHeader("Create-By", "Chanjs");
21
+ res.setHeader("X-Powered-By", "ChanCMS");
22
+ res.setHeader("ChanCMS", APP_VERSION);
23
+ res.setHeader("Server", APP_NAME);
24
+ next();
25
+ });
26
+ };
@@ -1,23 +1,14 @@
1
- import { log } from "./log.js";
2
- import { setCookie } from "./cookie.js";
3
- import { setFavicon } from "./favicon.js";
4
- import { setBody } from "./setBody.js";
5
- import { setStatic } from "./static.js";
6
- import { setHeader } from "./header.js";
7
- import { setTemplate } from "./template.js";
8
- import { validator } from "./validator.js";
9
- import { Cors } from "./cors.js";
10
- import { waf } from "./waf.js";
11
-
12
- export {
13
- log,
14
- setCookie,
15
- setFavicon,
16
- setBody,
17
- setStatic,
18
- setHeader,
19
- setTemplate,
20
- Cors,
21
- validator,
22
- waf,
23
- };
1
+ /**
2
+ * 中间件模块入口
3
+ * 导出所有中间件配置函数
4
+ */
5
+
6
+ export { setCookie } from "./cookie.js";
7
+ export { setFavicon } from "./favicon.js";
8
+ export { setBody } from "./setBody.js";
9
+ export { setStatic } from "./static.js";
10
+ export { setHeader } from "./header.js";
11
+ export { setTemplate } from "./template.js";
12
+ export { Cors } from "./cors.js";
13
+ export { validator } from "./validator.js";
14
+ export { waf } from "./waf.js";
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 防止快速重复请求中间件
3
+ * 使用 Cache 实现请求频率限制
4
+ */
5
+
6
+ import Cache from "../helper/cache.js";
7
+
8
+ const sendResponse = (res, code, message, data = null) => {
9
+ res.json({ code, msg: message, data });
10
+ };
11
+
12
+ const requestCache = new Cache({ maxSize: 1000, defaultTTL: 500 });
13
+
14
+ export default () => {
15
+ return (req, res, next) => {
16
+ if (req.method !== 'GET') {
17
+ return next();
18
+ }
19
+
20
+ const key = `${req.method}:${req.originalUrl}`;
21
+
22
+ if (requestCache.has(key)) {
23
+ console.log(`[preventRetry] 阻止快速重复请求: ${key}`);
24
+ return sendResponse(res, 429, '请求过于频繁,请稍后再试');
25
+ }
26
+
27
+ requestCache.set(key, Date.now());
28
+ next();
29
+ };
30
+ };
@@ -1,10 +1,24 @@
1
- import express from "express";
2
- let setBody = function (app, JSON_LIMIT) {
3
- // 1. 优先解析 XML 数据(必须在 json/urlencoded 之前)
4
- app.use(express.raw({ type: "application/xml", limit: JSON_LIMIT }));
5
- // 2. 再解析 JSON 和表单数据
6
- app.use(express.json({ limit: JSON_LIMIT }));
7
- app.use(express.urlencoded({ extended: false }));
8
- };
9
-
10
- export { setBody };
1
+ import express from "express";
2
+
3
+ /**
4
+ * 请求体解析中间件配置
5
+ * 配置请求体的解析方式
6
+ */
7
+
8
+ /**
9
+ * 设置请求体解析中间件
10
+ * @param {Object} app - Express 应用实例
11
+ * @param {string} JSON_LIMIT - JSON 请求体大小限制
12
+ * @description
13
+ * 为 Express 应用配置请求体解析中间件
14
+ * 支持 JSON、URL 编码和 XML 格式的请求体
15
+ * @example
16
+ * setBody(app, '10mb');
17
+ */
18
+ let setBody = function (app, JSON_LIMIT) {
19
+ app.use(express.raw({ type: "application/xml", limit: JSON_LIMIT }));
20
+ app.use(express.json({ limit: JSON_LIMIT }));
21
+ app.use(express.urlencoded({ extended: false }));
22
+ };
23
+
24
+ export { setBody };