chanjs 2.7.8 → 2.7.11
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 +261 -363
- package/config/index.js +4 -2
- package/core/App.js +35 -0
- package/core/Container.js +56 -29
- package/core/Database.js +58 -8
- package/core/EventBus.js +88 -0
- package/core/Lang.js +56 -0
- package/core/Repository.js +34 -2
- package/core/Task.js +87 -0
- package/core/errors.js +0 -5
- package/doc/00-README.md +208 -0
- package/doc/01-/346/240/270/345/277/203/347/261/273Controller-Service-Repository.md +432 -0
- package/doc/02-/345/223/215/345/272/224/344/270/216/351/224/231/350/257/257.md +255 -0
- package/doc/03-/345/256/211/345/205/250/346/250/241/345/235/227.md +264 -0
- package/doc/04-/345/255/230/345/202/250/344/270/216/347/274/223/345/255/230.md +157 -0
- package/doc/05-/345/267/245/345/205/267/344/270/216/346/240/241/351/252/214.md +309 -0
- package/doc/06-/345/272/224/347/224/250/347/224/237/345/221/275/345/221/250/346/234/237.md +207 -0
- package/doc/07-/344/272/213/344/273/266/347/263/273/347/273/237EventBus.md +324 -0
- package/doc/08-/345/256/232/346/227/266/344/273/273/345/212/241Task.md +262 -0
- package/doc/09-/345/233/275/351/231/205/345/214/226Lang.md +220 -0
- package/index.js +30 -1
- package/middleware/log.js +48 -31
- package/middleware/waf.js +22 -90
- package/package.json +20 -2
- package/response/code.js +0 -12
- package/response/response.js +8 -2
- package/security/checker.js +14 -7
- package/security/keywords.js +2 -3
- package/utils/logger.js +60 -91
- package/utils/pages.js +13 -12
- package/utils/signal.js +21 -2
- package/USAGE.md +0 -533
- package/doc/Cache.md +0 -333
- package/doc/Common.md +0 -638
- package/doc/Controller.md +0 -223
- package/doc/Help.md +0 -390
- package/doc/QuickStart.md +0 -116
- package/doc/Repository.md +0 -560
- package/doc/Service.md +0 -240
- package/publish.bat +0 -4
- package/todo.md +0 -1
package/README.md
CHANGED
|
@@ -1,363 +1,261 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
###
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
-
|
|
244
|
-
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
// 触发事件
|
|
265
|
-
event.emit("user.login", { userId: 1, username: "admin" });
|
|
266
|
-
|
|
267
|
-
// 移除监听器
|
|
268
|
-
event.off("user.login", listener);
|
|
269
|
-
|
|
270
|
-
// 移除所有监听器
|
|
271
|
-
event.removeAllListeners("user.login");
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### 4. 自动加载控制器
|
|
275
|
-
|
|
276
|
-
Chanjs 提供了 `loadController` 辅助函数,可以自动加载指定模块下的所有控制器。
|
|
277
|
-
|
|
278
|
-
#### 使用方式
|
|
279
|
-
|
|
280
|
-
```javascript
|
|
281
|
-
import { helper } from "chanjs";
|
|
282
|
-
|
|
283
|
-
// 加载 member 模块下的所有控制器
|
|
284
|
-
const controller = await helper.loadController("member");
|
|
285
|
-
|
|
286
|
-
// 使用控制器
|
|
287
|
-
controller.Member.getUser();
|
|
288
|
-
controller.Comment.getComments();
|
|
289
|
-
controller.Favorite.getFavorites();
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
#### 目录结构
|
|
293
|
-
|
|
294
|
-
```
|
|
295
|
-
member/
|
|
296
|
-
controller/
|
|
297
|
-
Member.js
|
|
298
|
-
Comment.js
|
|
299
|
-
Favorite.js
|
|
300
|
-
service/
|
|
301
|
-
Member.js
|
|
302
|
-
Comment.js
|
|
303
|
-
Favorite.js
|
|
304
|
-
router.js
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
`loadController("member")` 会自动加载 `member/controller/` 目录下的所有文件,并返回一个对象:
|
|
308
|
-
|
|
309
|
-
```javascript
|
|
310
|
-
{
|
|
311
|
-
Member: MemberController实例,
|
|
312
|
-
Comment: CommentController实例,
|
|
313
|
-
Favorite: FavoriteController实例
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
## 运行
|
|
318
|
-
|
|
319
|
-
```javascript
|
|
320
|
-
import Chanjs from "chanjs";
|
|
321
|
-
const chan = new Chanjs();
|
|
322
|
-
|
|
323
|
-
// 前置钩子
|
|
324
|
-
chan.beforeStart(fn);
|
|
325
|
-
|
|
326
|
-
// 开始加载
|
|
327
|
-
await chan.start();
|
|
328
|
-
|
|
329
|
-
// 启动服务器
|
|
330
|
-
chan.run((port) => {
|
|
331
|
-
console.log(`ChanCMS is running on ${port}`);
|
|
332
|
-
});
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
## 完整示例
|
|
336
|
-
|
|
337
|
-
```javascript
|
|
338
|
-
import Chanjs from "chanjs";
|
|
339
|
-
import { aop, event } from "chanjs";
|
|
340
|
-
|
|
341
|
-
const app = new Chanjs();
|
|
342
|
-
|
|
343
|
-
// 注册切面
|
|
344
|
-
aop.set("logBefore", async ({ ctx, methodName, args }) => {
|
|
345
|
-
console.log(`[Before] ${methodName} 被调用`);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// 监听事件
|
|
349
|
-
event.on("app.start", () => {
|
|
350
|
-
console.log("应用启动");
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
// 启动应用
|
|
354
|
-
await app.start();
|
|
355
|
-
|
|
356
|
-
// 运行
|
|
357
|
-
app.run((port) => {
|
|
358
|
-
event.emit("app.start", { port });
|
|
359
|
-
console.log(`Server running on port ${port}`);
|
|
360
|
-
});
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
该框架专为寻求简单与功能之间平衡的开发者设计,为构建 Web 应用程序提供了一个强大的基础。
|
|
1
|
+
# ChanJS
|
|
2
|
+
|
|
3
|
+
基于 Node.js + Express 5 的标准 HMVC 框架(NHMVC),纯 JavaScript(ESM)开发。模块自治 + 跨模块双通道协作,约定优于配置,开箱即用。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
### 核心架构
|
|
8
|
+
- Express 5+ 原生
|
|
9
|
+
- Node.js 22.18+
|
|
10
|
+
- ES Modules(import / export)
|
|
11
|
+
- 标准 HMVC 架构(模块自治 + 跨模块双通道协作)
|
|
12
|
+
- 约定优于配置
|
|
13
|
+
|
|
14
|
+
### 基础设施
|
|
15
|
+
- **日志**:[pino](https://github.com/pinojs/pino) 高性能结构化日志
|
|
16
|
+
- **请求日志**:pino-http,自动生成 requestId 贯穿全链路
|
|
17
|
+
- **国际化**:[i18next](https://www.i18next.com/) 多语言支持
|
|
18
|
+
- **事件总线**:EventBus,基于 Node 内置 EventEmitter
|
|
19
|
+
- **定时任务**:Task,基于 [node-cron](https://github.com/node-cron/node-cron)
|
|
20
|
+
- **数据库**:[Knex](https://knexjs.org/) 查询构建器,慢查询监控
|
|
21
|
+
- **组件容器**:按需动态加载 controller/service,成功永久缓存、缺失不缓存
|
|
22
|
+
- **优雅停机**:统一信号处理,资源按序释放
|
|
23
|
+
|
|
24
|
+
### 安全能力
|
|
25
|
+
- WAF 防火墙
|
|
26
|
+
- XSS 防护
|
|
27
|
+
- 关键词过滤
|
|
28
|
+
- 请求限流
|
|
29
|
+
- 路由白名单
|
|
30
|
+
- Cookie 安全
|
|
31
|
+
|
|
32
|
+
### 中间件生态
|
|
33
|
+
- CORS
|
|
34
|
+
- 请求解析(body / cookie)
|
|
35
|
+
- 静态资源
|
|
36
|
+
- favicon
|
|
37
|
+
- 请求头注入
|
|
38
|
+
- Art-template 模板引擎
|
|
39
|
+
|
|
40
|
+
### 开发体验
|
|
41
|
+
- 多环境配置(.env.dev / .env.prd)
|
|
42
|
+
- 统一响应(success / fail)
|
|
43
|
+
- Zod 参数校验中间件
|
|
44
|
+
- 全局异常处理
|
|
45
|
+
- 工具函数库
|
|
46
|
+
|
|
47
|
+
## 目录结构
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
|- app/
|
|
51
|
+
| |- common/ # 公共路由
|
|
52
|
+
| |- helper/ # 辅助函数
|
|
53
|
+
| |- middleware/ # 应用中间件
|
|
54
|
+
| |- modules/ # 业务模块
|
|
55
|
+
| | |- <module>/
|
|
56
|
+
| | |- controller/
|
|
57
|
+
| | |- service/
|
|
58
|
+
| | |- middleware/
|
|
59
|
+
| | |- router.js
|
|
60
|
+
| |- router.js
|
|
61
|
+
|- config/ # 框架常量与环境加载
|
|
62
|
+
|- data/ # 运行数据
|
|
63
|
+
|- doc/ # 文档
|
|
64
|
+
|- lang/ # i18n 资源(zh-CN/en-US/...)
|
|
65
|
+
|- public/ # 静态资源
|
|
66
|
+
|- view/ # 模板视图
|
|
67
|
+
|- app.js # 业务入口
|
|
68
|
+
|- .env.dev / .env.prd # 环境变量
|
|
69
|
+
|- pm2.json # 进程管理
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 快速开始
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
import Chan from "chanjs";
|
|
76
|
+
|
|
77
|
+
const chan = new Chan();
|
|
78
|
+
|
|
79
|
+
// 注册启动前置钩子
|
|
80
|
+
chan.beforeStart(() => {
|
|
81
|
+
// 此处可注册事件监听、定时任务等
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await chan.start(); // 加载配置、i18n、数据库、中间件、路由
|
|
85
|
+
chan.run((port) => { // 启动 HTTP 服务
|
|
86
|
+
console.log(`ChanJS running on ${port}`);
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 核心能力
|
|
91
|
+
|
|
92
|
+
### 1. 日志系统(pino)
|
|
93
|
+
|
|
94
|
+
dev 环境彩色输出,prod 环境输出 JSON(pm2 捕获 stdout)。API 完全兼容旧用法。
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
import logger, { createLogger } from "chanjs";
|
|
98
|
+
|
|
99
|
+
// 全局日志
|
|
100
|
+
logger.info("启动完成");
|
|
101
|
+
logger.error("查询失败", err); // 自动分离 Error 对象
|
|
102
|
+
|
|
103
|
+
// 带模块标签的子日志
|
|
104
|
+
const dbLog = createLogger("DB");
|
|
105
|
+
dbLog.warn("慢查询");
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
请求日志由 pino-http 自动处理,每个请求生成唯一 `requestId`,业务中通过 `req.log` 输出带 requestId 的日志:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// 在 Controller 中
|
|
112
|
+
async getUser(req, res) {
|
|
113
|
+
req.log.info("查询用户详情"); // 自动携带 requestId
|
|
114
|
+
// ...
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 2. 事件总线(EventBus)
|
|
119
|
+
|
|
120
|
+
基于 Node 内置 EventEmitter 的轻量封装,全局单例。
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
import { event, EventBus } from "chanjs";
|
|
124
|
+
|
|
125
|
+
// 全局实例
|
|
126
|
+
const off = event.on("user.login", (uid) => {
|
|
127
|
+
logger.info(`用户 ${uid} 登录`);
|
|
128
|
+
});
|
|
129
|
+
event.emit("user.login", 1001);
|
|
130
|
+
off(); // 取消监听
|
|
131
|
+
|
|
132
|
+
// 独立实例(隔离场景)
|
|
133
|
+
const localBus = new EventBus();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
> 详见 [doc/07-事件系统EventBus.md](./doc/07-事件系统EventBus.md)
|
|
137
|
+
|
|
138
|
+
### 3. 定时任务(Task)
|
|
139
|
+
|
|
140
|
+
基于 node-cron 封装,支持 cron 表达式校验、异常自动捕获、优雅停机。
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
import Chan from "chanjs";
|
|
144
|
+
|
|
145
|
+
const chan = new Chan();
|
|
146
|
+
|
|
147
|
+
chan.beforeStart(() => {
|
|
148
|
+
// 注册定时任务(启动时自动开始)
|
|
149
|
+
chan.task.add("clear-log", "0 3 * * *", async () => {
|
|
150
|
+
await chan.db.raw("DELETE FROM logs WHERE created_at < NOW() - INTERVAL 7 DAY");
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await chan.start();
|
|
155
|
+
chan.run();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 4. 国际化(i18next)
|
|
159
|
+
|
|
160
|
+
启动时扫描 `lang/` 目录加载全部语言资源到内存,运行时 O(1) 查找。
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
lang/
|
|
164
|
+
zh-CN/
|
|
165
|
+
common.json # { "user.welcome": "欢迎,{{name}}" }
|
|
166
|
+
en-US/
|
|
167
|
+
common.json # { "user.welcome": "Welcome, {{name}}" }
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
import { initLang } from "chanjs";
|
|
172
|
+
|
|
173
|
+
const i18n = await initLang("zh-CN");
|
|
174
|
+
i18n.t("user.welcome", { name: "张三" }); // → "欢迎,张三"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 5. 数据库(Knex + 慢查询监控)
|
|
178
|
+
|
|
179
|
+
多连接管理,自动慢查询与错误监控。
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
// 框架启动时根据 config.db 自动注册连接
|
|
183
|
+
// 业务中通过 this.db 或 getApp().db 访问默认连接
|
|
184
|
+
|
|
185
|
+
// 运行时调整慢查询阈值
|
|
186
|
+
chan.dbManager.setSlowThreshold(500); // 500ms
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 6. 组件容器(跨模块按需获取)
|
|
190
|
+
|
|
191
|
+
Controller / Service 都继承 `Container`,自带 `this.get()`,按「模块名 + 文件名」动态加载组件。
|
|
192
|
+
成功永久缓存;缺失不缓存(文件新增后立即感知)。
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
// 同模块获取 Service(Service 容器默认 type=service)
|
|
196
|
+
const cat = await this.get("book", "BookCategory");
|
|
197
|
+
|
|
198
|
+
// 跨模块获取其他模块的 Service(Controller 容器默认 type=controller,取 service 需传第三参)
|
|
199
|
+
const book = await this.get("book", "Book", "service");
|
|
200
|
+
const special = await this.get("cms", "Special", "service");
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- 存在返回实例并永久缓存;缺失返回 `null`,下次实时感知。
|
|
204
|
+
- 自带非法名称 / 路径越界安全校验。
|
|
205
|
+
- 异步方法,需 `await`。
|
|
206
|
+
- 跨模块协作优先用 `get`,避免手写 `../../` 相对路径 import。
|
|
207
|
+
|
|
208
|
+
### HMVC 定位(标准实现)
|
|
209
|
+
|
|
210
|
+
教科书把「Controller 嵌套调用 Controller + 运行时子请求」当作 HMVC 的标准,其实是把**实现手段**当成了标准,是片面的。
|
|
211
|
+
HMVC 的本质是**分层 + 模块自治 + 跨模块复用**。Chanjs 抓住本质,支持**双通道跨模块协作**:
|
|
212
|
+
|
|
213
|
+
- `await this.get("模块", "Controller")` —— 获取其他模块的 Controller(默认本容器类型)
|
|
214
|
+
- `await this.get("模块", "Service", "service")` —— 获取其他模块的 Service(推荐路径)
|
|
215
|
+
|
|
216
|
+
因此 Chanjs 是更贴合 HMVC 本质的**标准 HMVC 实现**,教科书把手段当标准才是过时的变体。
|
|
217
|
+
|
|
218
|
+
### 7. 优雅停机
|
|
219
|
+
|
|
220
|
+
统一处理 SIGTERM / SIGINT / SIGQUIT,按序释放资源:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
HTTP 服务 → 定时任务 → 缓存存储 → 数据库连接 → 事件总线
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
单个资源关闭失败不阻断其他资源,超时强制退出。
|
|
227
|
+
|
|
228
|
+
## 环境变量
|
|
229
|
+
|
|
230
|
+
| 变量 | 说明 | 默认 |
|
|
231
|
+
|------|------|------|
|
|
232
|
+
| `NODE_ENV` | 环境(dev/prd) | dev |
|
|
233
|
+
| `PORT` | HTTP 端口 | 3000 |
|
|
234
|
+
| `LOCALE` | 默认语言 | zh-CN |
|
|
235
|
+
| `LOG_LEVEL` | 日志级别 | dev:debug / prd:info |
|
|
236
|
+
| `TRUSTED_PROXIES` | 信任代理 | loopback |
|
|
237
|
+
| `SHUTDOWN_TIMEOUT` | 停机超时(ms) | 5000 |
|
|
238
|
+
| `REDIS_ENABLED` | 启用 Redis | false |
|
|
239
|
+
|
|
240
|
+
## 依赖
|
|
241
|
+
|
|
242
|
+
### 运行时依赖
|
|
243
|
+
- express ^5.2.1
|
|
244
|
+
- knex ^3.2.10
|
|
245
|
+
- pino ^9.5.0
|
|
246
|
+
- pino-http ^10.3.0
|
|
247
|
+
- i18next ^24.2.0
|
|
248
|
+
- node-cron ^3.0.3
|
|
249
|
+
- art-template ^4.13.4
|
|
250
|
+
- mysql2 ^3.22.3
|
|
251
|
+
- ioredis ^5.4.6
|
|
252
|
+
|
|
253
|
+
### 开发依赖
|
|
254
|
+
- pino-pretty ^11.3.0
|
|
255
|
+
|
|
256
|
+
### 可选 Peer 依赖
|
|
257
|
+
- zod ^4.4.3(参数校验)
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
ISC
|
package/config/index.js
CHANGED
|
@@ -7,7 +7,8 @@ import { Paths } from "../utils/paths.js";
|
|
|
7
7
|
* 框架运行默认常量
|
|
8
8
|
* 1. 优雅停机强制退出超时(ms)
|
|
9
9
|
* 2. 请求体最大限制
|
|
10
|
-
* 3. 单条beforeStart启动钩子超时阈值(ms)
|
|
10
|
+
* 3. 单条 beforeStart 启动钩子超时阈值(ms)
|
|
11
|
+
* 4. 数据库慢查询阈值(ms),超过则记 warn 日志
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
export const SHUTDOWN_TIMEOUT = 5000;
|
|
@@ -16,6 +17,7 @@ export const BODY_LIMIT = "10mb";
|
|
|
16
17
|
|
|
17
18
|
export const HOOK_TIMEOUT = 10000;
|
|
18
19
|
|
|
20
|
+
export const SLOW_THRESHOLD = 200;
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* @description {string}
|
|
@@ -38,4 +40,4 @@ export function loadDotEnv() {
|
|
|
38
40
|
if (fs.existsSync(envPath)) {
|
|
39
41
|
dotenv.config({ path: envPath });
|
|
40
42
|
}
|
|
41
|
-
}
|
|
43
|
+
}
|