mm_os 4.3.7 → 5.0.1
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 +102 -504
- package/index.js +26 -19
- package/lib/os.js +536 -0
- package/package.json +60 -84
- package/LICENSE +0 -21
- package/README_EN.md +0 -505
- package/adapter/adapter.js +0 -484
- package/adapter/custom_persistence.js +0 -661
- package/adapter/mqtt.js +0 -254
- package/adapter/socket.js +0 -244
- package/adapter/web.js +0 -92
- package/adapter/websocket.js +0 -43
- package/ai.js +0 -130
- package/com/api/README.md +0 -3
- package/com/api/com.json +0 -5
- package/com/api/config.tpl.json +0 -41
- package/com/api/drive.js +0 -732
- package/com/api/index.js +0 -201
- package/com/api/oauth.js +0 -200
- package/com/api/script.tpl.js +0 -32
- package/com/cmd/README.md +0 -11
- package/com/cmd/com.json +0 -5
- package/com/cmd/config.tpl.json +0 -48
- package/com/cmd/drive.js +0 -176
- package/com/cmd/index.js +0 -287
- package/com/cmd/job/config.json +0 -66
- package/com/cmd/job/index.js +0 -241
- package/com/cmd/job/test.js +0 -188
- package/com/cmd/msg.json +0 -48
- package/com/cmd/script.tpl.js +0 -12
- package/com/db/README.md +0 -3
- package/com/db/com.json +0 -5
- package/com/db/drive.js +0 -2206
- package/com/db/index.js +0 -241
- package/com/event/README.md +0 -4
- package/com/event/com.json +0 -5
- package/com/event/config.tpl.json +0 -20
- package/com/event/drive.js +0 -61
- package/com/event/index.js +0 -438
- package/com/event/script.tpl.js +0 -23
- package/com/mqtt/README.md +0 -47
- package/com/mqtt/com.json +0 -5
- package/com/mqtt/config.tpl.json +0 -42
- package/com/mqtt/drive.js +0 -704
- package/com/mqtt/index.js +0 -1052
- package/com/mqtt/index.test.js +0 -503
- package/com/mqtt/script.tpl.js +0 -719
- package/com/nav/README.md +0 -2
- package/com/nav/com.json +0 -5
- package/com/nav/config.tpl.json +0 -84
- package/com/nav/drive.js +0 -702
- package/com/nav/index.js +0 -228
- package/com/nav/tpl/admin_pc/page_channel.vue +0 -305
- package/com/nav/tpl/admin_pc/page_config.vue +0 -280
- package/com/nav/tpl/admin_pc/page_config_form.vue +0 -194
- package/com/nav/tpl/admin_pc/page_default.vue +0 -247
- package/com/nav/tpl/admin_pc/page_form.vue +0 -180
- package/com/nav/tpl/admin_pc/page_lang.vue +0 -264
- package/com/nav/tpl/admin_pc/page_nav.vue +0 -321
- package/com/nav/tpl/admin_pc/page_table.vue +0 -296
- package/com/nav/tpl/admin_pc/page_type.vue +0 -321
- package/com/nav/tpl/admin_pc/page_view.vue +0 -124
- package/com/nav/tpl/dev_pc/page_channel.vue +0 -253
- package/com/nav/tpl/dev_pc/page_config.vue +0 -253
- package/com/nav/tpl/dev_pc/page_default.vue +0 -247
- package/com/nav/tpl/dev_pc/page_form.vue +0 -162
- package/com/nav/tpl/dev_pc/page_nav.vue +0 -253
- package/com/nav/tpl/dev_pc/page_table.vue +0 -247
- package/com/nav/tpl/dev_pc/page_type.vue +0 -313
- package/com/nav/tpl/home_pc/page_channel.vue +0 -234
- package/com/nav/tpl/home_pc/page_default.vue +0 -234
- package/com/nav/tpl/home_pc/page_form.vue +0 -137
- package/com/nav/tpl/home_pc/page_list.vue +0 -234
- package/com/nav/tpl/home_pc/page_nav.vue +0 -221
- package/com/nav/tpl/home_pc/page_type.vue +0 -234
- package/com/nav/tpl/home_pc/page_view.vue +0 -125
- package/com/nav/tpl/home_phone/page_channel.vue +0 -234
- package/com/nav/tpl/home_phone/page_default.vue +0 -234
- package/com/nav/tpl/home_phone/page_form.vue +0 -137
- package/com/nav/tpl/home_phone/page_list.vue +0 -234
- package/com/nav/tpl/home_phone/page_nav.vue +0 -237
- package/com/nav/tpl/home_phone/page_type.vue +0 -234
- package/com/nav/tpl/home_phone/page_view.vue +0 -125
- package/com/nav/viewmodel.js +0 -446
- package/com/param/README.md +0 -2
- package/com/param/com.json +0 -5
- package/com/param/config.tpl.json +0 -136
- package/com/param/drive.js +0 -502
- package/com/param/index.js +0 -158
- package/com/param/script.tpl.js +0 -12
- package/com/pendant/README.md +0 -3
- package/com/pendant/com.json +0 -5
- package/com/pendant/config.tpl.json +0 -32
- package/com/pendant/drive.js +0 -204
- package/com/pendant/index.js +0 -467
- package/com/pendant/pendant.html +0 -16
- package/com/pendant/script.tpl.js +0 -18
- package/com/socket/README.md +0 -47
- package/com/socket/com.json +0 -5
- package/com/socket/config.tpl.json +0 -12
- package/com/socket/drive.js +0 -679
- package/com/socket/index.js +0 -402
- package/com/socket/script.tpl.js +0 -41
- package/com/sql/README.md +0 -3
- package/com/sql/com.json +0 -5
- package/com/sql/config.tpl.json +0 -74
- package/com/sql/drive.js +0 -1328
- package/com/sql/index.js +0 -152
- package/com/sql/script.tpl.js +0 -47
- package/com/static/README.md +0 -2
- package/com/static/com.json +0 -5
- package/com/static/config.tpl.json +0 -24
- package/com/static/drive.js +0 -194
- package/com/static/index.js +0 -237
- package/com/static/script.tpl.js +0 -28
- package/com/task/README.md +0 -3
- package/com/task/com.json +0 -5
- package/com/task/config.tpl.json +0 -24
- package/com/task/drive.js +0 -428
- package/com/task/index.js +0 -159
- package/com/task/script.tpl.js +0 -40
- package/com/template/com.json +0 -5
- package/com/template/config.tpl.json +0 -16
- package/com/template/drive.js +0 -81
- package/com/template/index.js +0 -141
- package/com.js +0 -237
- package/common/README.md +0 -2
- package/common/middleware/web_after/index.js +0 -26
- package/common/middleware/web_after/middleware.json +0 -9
- package/common/middleware/web_base/index.js +0 -113
- package/common/middleware/web_base/middleware.json +0 -19
- package/common/middleware/web_before/index.js +0 -33
- package/common/middleware/web_before/middleware.json +0 -9
- package/common/middleware/web_cors/index.js +0 -87
- package/common/middleware/web_cors/middleware.json +0 -24
- package/common/middleware/web_error/index.js +0 -131
- package/common/middleware/web_error/middleware.json +0 -19
- package/common/middleware/web_ip/index.js +0 -15
- package/common/middleware/web_ip/middleware.json +0 -14
- package/common/middleware/web_logger/index.js +0 -156
- package/common/middleware/web_logger/middleware.json +0 -14
- package/common/middleware/web_main/index.js +0 -26
- package/common/middleware/web_main/middleware.json +0 -9
- package/common/middleware/web_static/index.js +0 -73
- package/common/middleware/web_static/middleware.json +0 -54
- package/common/middleware/web_waf/index.js +0 -395
- package/common/middleware/web_waf/middleware.json +0 -13
- package/core/app/config.tpl.json +0 -67
- package/core/app/index.js +0 -711
- package/core/app/script.tpl.js +0 -52
- package/core/channel/index.js +0 -899
- package/core/channel/matcher.js +0 -585
- package/core/com/config.tpl.json +0 -16
- package/core/com/index.js +0 -77
- package/core/com/script.tpl.js +0 -5
- package/core/component/component.js +0 -42
- package/core/component/config.tpl.json +0 -63
- package/core/component/index.js +0 -273
- package/core/component/script.tpl.js +0 -19
- package/core/controller/config.tpl.json +0 -14
- package/core/controller/index.js +0 -371
- package/core/controller/script.tpl.js +0 -27
- package/core/factory/config.tpl.json +0 -14
- package/core/factory/entity.js +0 -275
- package/core/factory/index.js +0 -241
- package/core/factory/script.tpl.js +0 -16
- package/core/game/bat/index.js +0 -137
- package/core/game/bat/world.js +0 -622
- package/core/game/config.tpl.json +0 -16
- package/core/game/entity_admin.js +0 -230
- package/core/game/index.js +0 -186
- package/core/handler/config.tpl.json +0 -22
- package/core/handler/index.js +0 -181
- package/core/handler/script.tpl.js +0 -23
- package/core/logic/config.tpl.json +0 -14
- package/core/logic/index.js +0 -59
- package/core/logic/script.tpl.js +0 -19
- package/core/middleware/config.tpl.json +0 -16
- package/core/middleware/index.js +0 -117
- package/core/middleware/script.tpl.js +0 -37
- package/core/mod/config.tpl.json +0 -22
- package/core/mod/index.js +0 -136
- package/core/mod/script.tpl.js +0 -34
- package/core/model/config.tpl.json +0 -219
- package/core/model/index.js +0 -272
- package/core/model/model.js +0 -27
- package/core/model/script.tpl.js +0 -20
- package/core/notifier/config.tpl.json +0 -14
- package/core/notifier/index.js +0 -77
- package/core/notifier/script.tpl.js +0 -20
- package/core/plugin/config.tpl.json +0 -36
- package/core/plugin/index.js +0 -267
- package/core/plugin/script.tpl.js +0 -51
- package/core/pusher/config.tpl.json +0 -14
- package/core/pusher/index.js +0 -158
- package/core/pusher/script.tpl.js +0 -20
- package/core/room/bat/index.js +0 -170
- package/core/room/bat/room.js +0 -524
- package/core/room/config.tpl.json +0 -20
- package/core/room/index.js +0 -249
- package/core/room/room.js +0 -61
- package/core/scene/config.tpl.json +0 -14
- package/core/scene/index.js +0 -467
- package/core/scene/loop.js +0 -1306
- package/core/scene/map.js +0 -28
- package/core/scene/script.tpl.js +0 -22
- package/core/sender/config.tpl.json +0 -14
- package/core/sender/index.js +0 -79
- package/core/sender/script.tpl.js +0 -20
- package/core/service/config.tpl.json +0 -14
- package/core/service/index.js +0 -100
- package/core/service/script.tpl.js +0 -25
- package/core/store/config.tpl.json +0 -26
- package/core/store/index.js +0 -1794
- package/core/store/script.tpl.js +0 -22
- package/core/system/config.tpl.json +0 -18
- package/core/system/index.js +0 -312
- package/core/system/script.tpl.js +0 -77
- package/core/view/config.tpl.json +0 -14
- package/core/view/index.js +0 -91
- package/core/view/script.tpl.js +0 -20
- package/core/zone/bat/index.js +0 -744
- package/core/zone/config.tpl.json +0 -54
- package/core/zone/index.js +0 -655
- package/core/zone/script.tpl.js +0 -10
- package/core/zone/zone_bat.js +0 -136
- package/core//345/237/272/347/261/273/346/250/241/345/235/227/346/270/205/345/215/225.md +0 -24
- package/os.js +0 -53
- package/server.js +0 -602
- package/ulits/id_gen.js +0 -134
- package/ulits/word.js +0 -206
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// 导出符合系统期望的函数
|
|
2
|
-
module.exports = {
|
|
3
|
-
/**
|
|
4
|
-
* 初始化
|
|
5
|
-
* @param {object} adapter 适配器对象
|
|
6
|
-
*/
|
|
7
|
-
_init(adapter) {
|
|
8
|
-
// 获取web服务
|
|
9
|
-
// var web = adapter.web;
|
|
10
|
-
|
|
11
|
-
// 获取配置
|
|
12
|
-
this.config = { ...this.config, ...adapter.web.config };
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* CORS跨域中间件
|
|
17
|
-
* 处理跨域资源共享(CORS)配置
|
|
18
|
-
* @param {object} ctx Koa上下文
|
|
19
|
-
* @param {object} config CORS配置
|
|
20
|
-
*/
|
|
21
|
-
_setCorsHeaders(ctx, config) {
|
|
22
|
-
// 设置Access-Control-Allow-Origin
|
|
23
|
-
if (config.origin === '*') {
|
|
24
|
-
ctx.set('Access-Control-Allow-Origin', '*');
|
|
25
|
-
} else if (Array.isArray(config.origin)) {
|
|
26
|
-
let request_origin = ctx.get('Origin');
|
|
27
|
-
if (config.origin.includes(request_origin)) {
|
|
28
|
-
ctx.set('Access-Control-Allow-Origin', request_origin);
|
|
29
|
-
}
|
|
30
|
-
} else {
|
|
31
|
-
ctx.set('Access-Control-Allow-Origin', config.origin);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// 设置Access-Control-Allow-Headers
|
|
35
|
-
if (config.headers === '*') {
|
|
36
|
-
ctx.set('Access-Control-Allow-Headers', '*');
|
|
37
|
-
} else if (Array.isArray(config.headers)) {
|
|
38
|
-
ctx.set('Access-Control-Allow-Headers', config.headers.join(', '));
|
|
39
|
-
} else {
|
|
40
|
-
ctx.set('Access-Control-Allow-Headers', config.headers);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 设置Access-Control-Allow-Methods
|
|
44
|
-
ctx.set('Access-Control-Allow-Methods', config.methods.join(', '));
|
|
45
|
-
|
|
46
|
-
// 设置Access-Control-Allow-Credentials
|
|
47
|
-
if (config.credentials) {
|
|
48
|
-
ctx.set('Access-Control-Allow-Credentials', 'true');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 设置Access-Control-Max-Age
|
|
52
|
-
if (config.max_age > 0) {
|
|
53
|
-
ctx.set('Access-Control-Max-Age', config.max_age.toString());
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 设置Access-Control-Expose-Headers
|
|
57
|
-
if (config.expose_headers.length > 0) {
|
|
58
|
-
ctx.set('Access-Control-Expose-Headers', config.expose_headers.join(', '));
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
async main(ctx, next) {
|
|
63
|
-
let config = this.config;
|
|
64
|
-
|
|
65
|
-
if (!config.enable) {
|
|
66
|
-
return await next();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 检查是否应该忽略该路径
|
|
70
|
-
let path = ctx.path;
|
|
71
|
-
if (config.ignore_paths.some(p => path.startsWith(p))) {
|
|
72
|
-
return await next();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 设置CORS头
|
|
76
|
-
this._setCorsHeaders(ctx, config);
|
|
77
|
-
|
|
78
|
-
// 处理预检请求
|
|
79
|
-
if (ctx.method === 'OPTIONS') {
|
|
80
|
-
ctx.status = 204;
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
await next();
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "web_cors",
|
|
3
|
-
"title": "CORS跨域中间件",
|
|
4
|
-
"description": "处理跨域资源共享(CORS)配置,支持灵活的跨域策略",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "web",
|
|
7
|
-
"state": 1,
|
|
8
|
-
"sort": 30,
|
|
9
|
-
"enable": true,
|
|
10
|
-
"origin": "*",
|
|
11
|
-
"headers": "*",
|
|
12
|
-
"methods": [
|
|
13
|
-
"GET",
|
|
14
|
-
"POST",
|
|
15
|
-
"PUT",
|
|
16
|
-
"DELETE",
|
|
17
|
-
"OPTIONS",
|
|
18
|
-
"HEAD"
|
|
19
|
-
],
|
|
20
|
-
"credentials": false,
|
|
21
|
-
"max_age": 3600,
|
|
22
|
-
"expose_headers": [],
|
|
23
|
-
"ignore_paths": []
|
|
24
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
// 导出错误处理中间件
|
|
2
|
-
module.exports = {
|
|
3
|
-
/**
|
|
4
|
-
* 初始化
|
|
5
|
-
* @param {object} adapter 适配器对象
|
|
6
|
-
*/
|
|
7
|
-
_init(adapter) {
|
|
8
|
-
// 获取配置
|
|
9
|
-
this.config = { ...this.config, ...adapter.web.config };
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* 获取错误消息
|
|
14
|
-
* @private
|
|
15
|
-
* @param {object} config 配置对象
|
|
16
|
-
* @param {number} status 状态码
|
|
17
|
-
* @returns {string} 错误消息
|
|
18
|
-
*/
|
|
19
|
-
_getErrorMessage(config, status) {
|
|
20
|
-
if (config.error_codes && config.error_codes[status]) {
|
|
21
|
-
return config.error_codes[status];
|
|
22
|
-
}
|
|
23
|
-
return config.default_message || "Internal Server Error";
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 格式化错误信息
|
|
28
|
-
* @private
|
|
29
|
-
* @param {object} config 配置对象
|
|
30
|
-
* @param {Error} err 错误对象
|
|
31
|
-
* @returns {object} 格式化后的错误信息
|
|
32
|
-
*/
|
|
33
|
-
_formatError(config, err) {
|
|
34
|
-
let errorInfo = {
|
|
35
|
-
message: err.message,
|
|
36
|
-
status: err.status || err.statusCode || config.default_status,
|
|
37
|
-
stack: err.stack,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
if (err.code) {
|
|
41
|
-
errorInfo.code = err.code;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (err.details) {
|
|
45
|
-
errorInfo.details = err.details;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (err.name) {
|
|
49
|
-
errorInfo.name = err.name;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return errorInfo;
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 处理错误
|
|
57
|
-
* @private
|
|
58
|
-
* @param {object} ctx Koa上下文
|
|
59
|
-
* @param {Error} err 错误对象
|
|
60
|
-
*/
|
|
61
|
-
async _handleError(ctx, err) {
|
|
62
|
-
// 记录错误日志到控制台
|
|
63
|
-
let error_info = this._formatError(this.config, err);
|
|
64
|
-
this.log("error", `Error occurred: ${err.message}`, error_info);
|
|
65
|
-
|
|
66
|
-
// 设置响应状态码
|
|
67
|
-
let status = err.status || err.status_code || this.config.default_status;
|
|
68
|
-
|
|
69
|
-
// 特殊错误处理:文件不存在错误返回404
|
|
70
|
-
if (err.code === "ENOENT") {
|
|
71
|
-
status = 404;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
ctx.status = status;
|
|
75
|
-
|
|
76
|
-
let message = err.message || this._getErrorMessage(this.config, status);
|
|
77
|
-
let error_response = $.ret.error(status, message);
|
|
78
|
-
|
|
79
|
-
// 如果配置允许,暴露堆栈信息(仅在开发环境使用)
|
|
80
|
-
if (this.config.expose_trace && err.stack) {
|
|
81
|
-
error_response.trace = err.stack;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// 添加额外的错误信息
|
|
85
|
-
if (err.code) {
|
|
86
|
-
error_response.error_code = err.code;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (err.details) {
|
|
90
|
-
error_response.details = err.details;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// 设置响应体
|
|
94
|
-
ctx.body = error_response;
|
|
95
|
-
|
|
96
|
-
// 设置响应头
|
|
97
|
-
ctx.set("Content-Type", "application/json");
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* 中间件主方法
|
|
102
|
-
* @param {object} ctx Koa上下文
|
|
103
|
-
* @param {Function} next 下一个中间件
|
|
104
|
-
* @returns {Promise<void>}
|
|
105
|
-
*/
|
|
106
|
-
async main(ctx, next) {
|
|
107
|
-
// 监听响应流错误,避免客户端断开导致 ERR_STREAM_PREMATURE_CLOSE 未捕获
|
|
108
|
-
ctx.res.on("error", (err) => {
|
|
109
|
-
if (
|
|
110
|
-
err.code === "ERR_STREAM_PREMATURE_CLOSE" ||
|
|
111
|
-
err.code === "ECONNRESET"
|
|
112
|
-
) {
|
|
113
|
-
// 客户端断开连接属于正常行为,静默处理
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
this.log("error", "响应流错误: " + err.message);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
await next();
|
|
121
|
-
|
|
122
|
-
// 处理404错误
|
|
123
|
-
if (ctx.status === 404 && !ctx.body) {
|
|
124
|
-
ctx.status = 404;
|
|
125
|
-
ctx.body = $.ret.error(404, "Not Found");
|
|
126
|
-
}
|
|
127
|
-
} catch (error) {
|
|
128
|
-
await this._handleError(ctx, error);
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "web_error",
|
|
3
|
-
"title": "错误处理中间件",
|
|
4
|
-
"description": "统一处理Web请求中的错误",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "web",
|
|
7
|
-
"state": 1,
|
|
8
|
-
"sort": 10,
|
|
9
|
-
"expose_stacktrace": false,
|
|
10
|
-
"default_status": 500,
|
|
11
|
-
"default_message": "Internal Server Error",
|
|
12
|
-
"error_codes": {
|
|
13
|
-
"400": "Bad Request",
|
|
14
|
-
"401": "Unauthorized",
|
|
15
|
-
"403": "Forbidden",
|
|
16
|
-
"404": "Not Found",
|
|
17
|
-
"500": "Internal Server Error"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// 导出中间件主方法
|
|
2
|
-
module.exports = {
|
|
3
|
-
_getClientIp(ctx) {
|
|
4
|
-
return ctx.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
|
|
5
|
-
ctx.headers['x-real-ip'] ||
|
|
6
|
-
ctx.ip ||
|
|
7
|
-
'unknown';
|
|
8
|
-
},
|
|
9
|
-
async main(ctx, next) {
|
|
10
|
-
if (ctx.ip === undefined) {
|
|
11
|
-
ctx.ip = this._getClientIp(ctx);
|
|
12
|
-
}
|
|
13
|
-
await next();
|
|
14
|
-
}
|
|
15
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "web_ip",
|
|
3
|
-
"title": "HTTP请求IP中间件",
|
|
4
|
-
"description": "用于记录HTTP请求IP地址",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "web",
|
|
7
|
-
"state": 1,
|
|
8
|
-
"sort": 11,
|
|
9
|
-
"level": "info",
|
|
10
|
-
"format": "default",
|
|
11
|
-
"request": true,
|
|
12
|
-
"response": true,
|
|
13
|
-
"duration": true
|
|
14
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
// 导出中间件主方法
|
|
2
|
-
module.exports = {
|
|
3
|
-
/**
|
|
4
|
-
* 初始化
|
|
5
|
-
* @param {object} adapter 适配器集合
|
|
6
|
-
*/
|
|
7
|
-
_init(adapter) {
|
|
8
|
-
// 获取web服务
|
|
9
|
-
var web = adapter.web;
|
|
10
|
-
|
|
11
|
-
// 注册中间件
|
|
12
|
-
web.use(async (ctx, next) => {
|
|
13
|
-
if (ctx.path === '/favicon.ico') {
|
|
14
|
-
await next();
|
|
15
|
-
} else {
|
|
16
|
-
ctx.ip = this._getClientIp(ctx);
|
|
17
|
-
ctx.start_time = Date.now();
|
|
18
|
-
let log = {
|
|
19
|
-
method: ctx.method,
|
|
20
|
-
path: ctx.path,
|
|
21
|
-
ip: ctx.ip || this._getClientIp(ctx),
|
|
22
|
-
request: this._format(ctx),
|
|
23
|
-
user_agent: this._getUserAgent(ctx)
|
|
24
|
-
};
|
|
25
|
-
try {
|
|
26
|
-
await next();
|
|
27
|
-
|
|
28
|
-
// 请求后置处理
|
|
29
|
-
log.duration = Date.now() - ctx.start_time;
|
|
30
|
-
log.response = this._sanitizeBody(ctx.body) || {};
|
|
31
|
-
log.status = ctx.status;
|
|
32
|
-
// 请求前置处理
|
|
33
|
-
this._record(log);
|
|
34
|
-
} catch (err) {
|
|
35
|
-
// 记录错误日志
|
|
36
|
-
log.duration = Date.now() - ctx.start_time;
|
|
37
|
-
log.status = 500;
|
|
38
|
-
log.response = {
|
|
39
|
-
error: {
|
|
40
|
-
message: err.message,
|
|
41
|
-
stack: err.stack
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
this._record(log);
|
|
45
|
-
|
|
46
|
-
// 重新抛出错误,由web_error中间件统一处理
|
|
47
|
-
throw err;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
},
|
|
52
|
-
_getClientIp(ctx) {
|
|
53
|
-
return ctx.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
|
|
54
|
-
ctx.headers['x-real-ip'] ||
|
|
55
|
-
'unknown';
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 获取用户代理信息
|
|
60
|
-
* @private
|
|
61
|
-
* @param {object} ctx Koa上下文
|
|
62
|
-
* @returns {string} 用户代理信息
|
|
63
|
-
*/
|
|
64
|
-
_getUserAgent(ctx) {
|
|
65
|
-
let ua = ctx.headers['user-agent'] || '';
|
|
66
|
-
|
|
67
|
-
// 简化的 UA 解析,只提取浏览器和 OS
|
|
68
|
-
if (ua.includes('Chrome')) return 'Chrome';
|
|
69
|
-
if (ua.includes('Firefox')) return 'Firefox';
|
|
70
|
-
if (ua.includes('Safari')) return 'Safari';
|
|
71
|
-
if (ua.includes('Postman')) return 'Postman';
|
|
72
|
-
if (ua.includes('curl')) return 'curl';
|
|
73
|
-
|
|
74
|
-
return ua.length > 20 ? ua.substring(0, 20) + '...' : ua;
|
|
75
|
-
},
|
|
76
|
-
/**
|
|
77
|
-
* 格式化请求信息
|
|
78
|
-
* @private
|
|
79
|
-
* @param {object} ctx Koa上下文
|
|
80
|
-
* @returns {object} 格式化后的请求数据
|
|
81
|
-
*/
|
|
82
|
-
_format(ctx) {
|
|
83
|
-
// const headers = this._sanitizeHeaders(ctx.headers);
|
|
84
|
-
let body = ctx.request.body ? this._sanitizeBody(ctx.request.body) : undefined;
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
query: ctx.query,
|
|
88
|
-
body: body
|
|
89
|
-
};
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* 清理敏感头信息
|
|
94
|
-
* @private
|
|
95
|
-
* @param {object} headers 请求头
|
|
96
|
-
* @returns {object} 清理后的请求头
|
|
97
|
-
*/
|
|
98
|
-
_sanitizeHeaders(headers) {
|
|
99
|
-
const SENS_HEADERS = ['authorization', 'cookie', 'x-api-key'];
|
|
100
|
-
const SAN_VAL = {};
|
|
101
|
-
|
|
102
|
-
for (var k in headers) {
|
|
103
|
-
if (SENS_HEADERS.includes(k.toLowerCase())) {
|
|
104
|
-
SAN_VAL[k] = '[REDACTED]';
|
|
105
|
-
} else {
|
|
106
|
-
SAN_VAL[k] = headers[k];
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return SAN_VAL;
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* 清理敏感请求体信息
|
|
115
|
-
* @private
|
|
116
|
-
* @param {object} body 请求体
|
|
117
|
-
* @returns {object} 清理后的请求体
|
|
118
|
-
*/
|
|
119
|
-
_sanitizeBody(body) {
|
|
120
|
-
const SENS_KEYS = ['password', 'token', 'secret', 'key', 'credit_card'];
|
|
121
|
-
let by = {};
|
|
122
|
-
if (typeof(body) === 'object') {
|
|
123
|
-
for (var k in body) {
|
|
124
|
-
if (SENS_KEYS.some(field => k.toLowerCase().includes(field))) {
|
|
125
|
-
by[k] = '[REDACTED]';
|
|
126
|
-
} else {
|
|
127
|
-
by[k] = body[k];
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return by;
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* 记录请求日志
|
|
136
|
-
* @private
|
|
137
|
-
* @param {object} log 日志对象
|
|
138
|
-
*/
|
|
139
|
-
_record(log) {
|
|
140
|
-
var status = log.status;
|
|
141
|
-
this.log('http', `[${log.ip}] [${log.method}] ${log.path} ${status} ${log.duration}ms`,
|
|
142
|
-
log.request, log.response);
|
|
143
|
-
// 时间 time '2022-11-11 12:00:00'
|
|
144
|
-
// 信息级别 level 'warn'
|
|
145
|
-
// 来源IP ip '127.0.0.1'
|
|
146
|
-
// 浏览器 user_agent 'Chrome' X
|
|
147
|
-
// 查询条件 query '{'id':1}' X
|
|
148
|
-
// 提交内容 body '{'name':'test'}' X
|
|
149
|
-
// 错误信息 error 'Error: test' X
|
|
150
|
-
// 请求方法 method 'GET'
|
|
151
|
-
// 请求路径 path '/test'
|
|
152
|
-
// 响应时长 duration '38ms'
|
|
153
|
-
// 响应状态 status 200
|
|
154
|
-
// 用户ID user_id 1
|
|
155
|
-
}
|
|
156
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "web_logger",
|
|
3
|
-
"title": "HTTP请求日志中间件",
|
|
4
|
-
"description": "用于记录HTTP请求日志,包括请求方法、URL、状态码、响应时间等",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "web",
|
|
7
|
-
"state": 1,
|
|
8
|
-
"sort": 20,
|
|
9
|
-
"level": "info",
|
|
10
|
-
"format": "default",
|
|
11
|
-
"request": true,
|
|
12
|
-
"response": true,
|
|
13
|
-
"duration": true
|
|
14
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 中间件
|
|
3
|
-
*/
|
|
4
|
-
module.exports = {
|
|
5
|
-
/**
|
|
6
|
-
* 主要逻辑
|
|
7
|
-
* @param {object} ctx Koa上下文
|
|
8
|
-
* @param {Function} next 下一个中间件
|
|
9
|
-
*/
|
|
10
|
-
async main(ctx, next) {
|
|
11
|
-
if (ctx.path !== '/favicon.ico') {
|
|
12
|
-
var event = $.admin.event('api');
|
|
13
|
-
var ret = await event.main(ctx.path, ctx, ctx.db);
|
|
14
|
-
if (ret) {
|
|
15
|
-
ctx.body = ret;
|
|
16
|
-
ret = await event.render(ctx.path, ctx, ctx.db);
|
|
17
|
-
if (ret) {
|
|
18
|
-
ctx.body = ret;
|
|
19
|
-
}
|
|
20
|
-
// 已有处理结果,终止中间件链,避免后续中间件覆盖
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
await next();
|
|
25
|
-
}
|
|
26
|
-
};
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 增强的静态资源处理中间件
|
|
3
|
-
* 提供缓存控制、压缩、预加载等性能优化功能
|
|
4
|
-
*/
|
|
5
|
-
const { statics } = require('mm_statics');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 静态资源请求
|
|
9
|
-
* @param {object} server 服务
|
|
10
|
-
* @param {object} config 配置参数
|
|
11
|
-
*/
|
|
12
|
-
module.exports = {
|
|
13
|
-
/**
|
|
14
|
-
* 初始化
|
|
15
|
-
* @param {object} adapter 适配器集合
|
|
16
|
-
* @param {object} eventer 事件管理器
|
|
17
|
-
* @param {object} logger 日志管理器
|
|
18
|
-
*/
|
|
19
|
-
_init(adapter, eventer, logger) {
|
|
20
|
-
// 获取web服务
|
|
21
|
-
var web = adapter.web;
|
|
22
|
-
let config = web.config.static || {};
|
|
23
|
-
let cg = { ...this.config, ...config };
|
|
24
|
-
if (cg) {
|
|
25
|
-
this._setupMainStatic(web, cg);
|
|
26
|
-
this._setupMultiStatic(web, cg);
|
|
27
|
-
this._setupGlobalStatic(web);
|
|
28
|
-
} else {
|
|
29
|
-
console.warn('未找到静态文件配置');
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
/**
|
|
33
|
-
* 设置主静态路径
|
|
34
|
-
* @private
|
|
35
|
-
* @param {object} web web服务
|
|
36
|
-
* @param {object} cg 配置
|
|
37
|
-
*/
|
|
38
|
-
_setupMainStatic(web, cg) {
|
|
39
|
-
web.use(statics(cg));
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 设置多静态路径
|
|
44
|
-
* @private
|
|
45
|
-
* @param {object} web web服务
|
|
46
|
-
* @param {object} cg 配置
|
|
47
|
-
*/
|
|
48
|
-
_setupMultiStatic(web, cg) {
|
|
49
|
-
if (Array.isArray(cg.paths) && cg.paths.length > 0) {
|
|
50
|
-
for (let i = 0; i < cg.paths.length; i++) {
|
|
51
|
-
let path = cg.paths[i];
|
|
52
|
-
let config = { ...cg, root: path.fullname() };
|
|
53
|
-
web.use(statics(config));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 设置全局静态资源
|
|
60
|
-
* @private
|
|
61
|
-
* @param {object} web web服务
|
|
62
|
-
*/
|
|
63
|
-
_setupGlobalStatic(web) {
|
|
64
|
-
if ($.admin.static) {
|
|
65
|
-
$.static = new $.admin.static();
|
|
66
|
-
$.static.call('update', 'app/');
|
|
67
|
-
|
|
68
|
-
web.use(async (ctx, next) => {
|
|
69
|
-
await $.static.run(ctx, next);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "web_static",
|
|
3
|
-
"title": "web静态文件处理",
|
|
4
|
-
"description": "用于处理静态文件",
|
|
5
|
-
"version": "1.0",
|
|
6
|
-
"main": "./index.js",
|
|
7
|
-
"type": "web",
|
|
8
|
-
"state": 1,
|
|
9
|
-
"sort": 90,
|
|
10
|
-
// 是否启用静态文件处理
|
|
11
|
-
"static": true,
|
|
12
|
-
// 默认首页文件
|
|
13
|
-
"index": "index.html",
|
|
14
|
-
// 缓存键前缀
|
|
15
|
-
"key_prefix": "static:",
|
|
16
|
-
// 前端缓存时间,单位秒
|
|
17
|
-
"max_age": 7200,
|
|
18
|
-
// 是否开启缓存
|
|
19
|
-
"cache": true,
|
|
20
|
-
// 后端缓存时间,单位秒
|
|
21
|
-
"cache_age": 31536000,
|
|
22
|
-
// 是否开启immutable缓存
|
|
23
|
-
"immutable": true,
|
|
24
|
-
// 是否开启隐藏文件处理
|
|
25
|
-
"hidden": false,
|
|
26
|
-
// 是否格式化文件
|
|
27
|
-
"format": true,
|
|
28
|
-
// 是否指定文件扩展名
|
|
29
|
-
"extensions": false,
|
|
30
|
-
// 是否开启brotli压缩
|
|
31
|
-
"brotli": false,
|
|
32
|
-
// 是否开启gzip压缩
|
|
33
|
-
"gzip": false,
|
|
34
|
-
// 静态文件根目录
|
|
35
|
-
"root": "./static",
|
|
36
|
-
// 编译vue文件,启动后会将vue转为js,可让前端通过 import xxx from './xxx.vue' 引入
|
|
37
|
-
"compile_vue": true,
|
|
38
|
-
// 编译markdown文件,启动后会将markdown转为html
|
|
39
|
-
"compile_md": true,
|
|
40
|
-
// 是否将files中的文件的js转换为amd格式
|
|
41
|
-
"convert_amd": false,
|
|
42
|
-
// 指定路径文件需要转换
|
|
43
|
-
"src_path": "/src",
|
|
44
|
-
// 监听路由路径
|
|
45
|
-
"path": "/",
|
|
46
|
-
// 需要转换的文件扩展名
|
|
47
|
-
"files": [
|
|
48
|
-
".js",
|
|
49
|
-
".vue",
|
|
50
|
-
".html"
|
|
51
|
-
],
|
|
52
|
-
// 是否启用文件修改监听(实时检测文件修改)
|
|
53
|
-
"watch": true
|
|
54
|
-
}
|