chanjs 2.6.0 → 2.6.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/App.js CHANGED
@@ -72,9 +72,7 @@ class Chan {
72
72
  */
73
73
  async config() {
74
74
  let config = await loadConfig();
75
- console.log('[App.config] 开始加载配置,config keys:', Object.keys(config));
76
75
  Chan.config = config;
77
- console.log('[App.config] 配置加载完成,Chan.config.modules:', Chan.config.modules);
78
76
  }
79
77
 
80
78
  /**
@@ -85,15 +83,15 @@ class Chan {
85
83
  */
86
84
  async loadDB() {
87
85
  const dbList = Chan.config?.db || [];
88
-
89
86
  for (const [index, item] of dbList.entries()) {
90
87
  const key = item.key || String(index);
91
88
  try {
92
89
  const dbConfig = item;
93
- if (!dbConfig) throw new Error("未找到配置");
94
-
90
+ if (!dbConfig) {
91
+ console.error(`[DB] 数据库 ${key} 未找到数据库配置`);
92
+ return;
93
+ };
95
94
  const connection = this.dbManager.add(key, dbConfig, { isDefault: index === 0 });
96
-
97
95
  if (index === 0) {
98
96
  Chan.db = this.dbManager.get();
99
97
  }
@@ -102,9 +100,7 @@ class Chan {
102
100
  }
103
101
  }
104
102
 
105
- console.log(
106
- `[DB] 初始化完成,已加载 ${dbList.length} 个数据库`,
107
- );
103
+ console.log(`[DB] 初始化完成,已加载 ${dbList.length} 个数据库`);
108
104
  }
109
105
 
110
106
  /**
@@ -299,13 +295,8 @@ class Chan {
299
295
  const configPath = path.join(Paths.appPath, "modules");
300
296
  if (fs.existsSync(configPath)) {
301
297
  const dirs = loaderSort(Chan.config.modules);
302
- console.log('路由加载顺序:', dirs);
303
- console.log('Chan.helper keys:', Object.keys(Chan.helper));
304
- console.log('Chan.helper.loadController type:', typeof Chan.helper.loadController);
305
298
  for (const item of dirs) {
306
299
  let routerFn = await importFile(path.join(Paths.modulesPath, item, "router.js"));
307
- console.log('路由函数:', routerFn);
308
-
309
300
  // 为每个模块创建子路由并添加前缀
310
301
  const subRouter = express.Router();
311
302
  routerFn(this.app, subRouter, Chan.config);
package/README.md CHANGED
@@ -1,93 +1,348 @@
1
-
2
1
  # Chanjs
3
2
 
4
- Chanjs 是一个基于 Express5+ 构建的轻量级 MVC 框架,完全使用 JavaScript 开发。它体现了函数式编程的概念,提供了卓越的性能、清晰的代码和易于遵循的过程,确保了高可维护性。
3
+ Chanjs 是一个基于 Express 5+ 构建的轻量级 MVC 框架,完全使用 JavaScript 开发。它体现了函数式编程的概念,提供了卓越的性能、清晰的代码和易于遵循的过程,确保了高可维护性。
5
4
 
6
5
  ## 特点
7
6
 
8
- - 基于 Express 构建
9
- - 支持 ES6 语法
10
- - 模块化设计
11
- - 多模块化路由
12
- - 模块化 views
13
- - 模块化 controllers
14
- - 模块化 services
15
- - 插件式架构
16
- - 轻量级(核心代码在300行以内)
17
- - 缓存支持
7
+ - **核心架构**
8
+ - 基于 Express 5+ 构建
9
+ - 支持 ES6+ 语法
10
+ - 轻量级设计(核心代码精简高效)
11
+
12
+ - **模块化设计**
13
+ - 多模块化路由(支持模块独立路由)
14
+ - 模块化 views(模板文件模块化)
15
+ - 模块化 controllers(控制器模块化)
16
+ - 模块化 services(服务层模块化)
17
+ - 模块化 middleware(模块级中间件)
18
+
19
+ - **插件式架构**
20
+ - 支持插件扩展
21
+ - 插件独立 MVC 结构
22
+ - 热插拔式插件管理
23
+
24
+ - **数据库支持**
25
+ - 多数据库支持(PostgreSQL、MySQL/MariaDB、SQLite3、Oracle、MSSQL)
26
+ - 数据库连接池管理
27
+ - Knex 查询构建器
28
+ - 事务支持
29
+ - 日期字段自动格式化
30
+
31
+ - **安全防护**
32
+ - WAF(Web应用防火墙)
33
+ - XSS 防护
34
+ - 关键词过滤
35
+ - 访问限流(Rate Limiting)
36
+ - 路径白名单
37
+ - Cookie 安全处理
38
+
39
+ - **中间件生态**
40
+ - CORS 跨域配置
41
+ - 请求体解析
42
+ - Cookie 处理
43
+ - 静态资源管理
44
+ - 日志记录
45
+ - 模板引擎(Art-template)
46
+
47
+ - **高级特性**
48
+ - 依赖注入(DI,基于 Map 实现)
49
+ - 面向切面编程(AOP,支持 before/after/error 切面)
50
+ - 事件系统(基于 EventEmitter)
51
+ - 自动控制器加载(loadController)
52
+
53
+ - **开发体验**
54
+ - 缓存支持(内存缓存)
55
+ - 统一响应格式
56
+ - 全局错误处理(404/500)
57
+ - 分页查询封装
58
+ - 配置文件管理
59
+ - 环境变量支持(.env.dev/.env.prd)
60
+
61
+ - **工具函数**
62
+ - 时间格式化
63
+ - 文件操作
64
+ - 路径处理
65
+ - 树形结构转换
66
+ - 代码生成
67
+ - 过滤器
18
68
 
19
69
  ## 约定优于配置
20
70
 
21
71
  ```code
22
72
  |- app
73
+ |- common
74
+ |- helper
75
+ |- middleware
23
76
  |- modules
24
77
  |- module1
25
78
  |- controller
26
79
  |- service
80
+ |- middleware
27
81
  |- router.js
28
82
  |- module2
29
83
  |- controller
30
84
  |- service
31
85
  |- router.js
32
- |- extend
33
- |- middleware
34
- |- plugin
35
- |-views
86
+ |- plugins
87
+ |- plugin1
88
+ |- controller
89
+ |- router.js
90
+ |- router.js
36
91
  |- config
92
+ |- data
93
+ |- doc
37
94
  |- public
38
- |- index.js
95
+ |- view
96
+ |- app.js
39
97
  |-.env.dev
40
98
  |-.env.prd
99
+ |- pm2.json
100
+ |- package.json
101
+ ```
41
102
 
103
+ ## 初始化过程
104
+
105
+ ```mermaid
106
+ graph TD
107
+ A[初始化] --> B[加载配置]
108
+ B --> C[加载数据库]
109
+ C --> D[加载扩展]
110
+ D --> E[加载中间件]
111
+ E --> F[设置应用配置]
112
+ F --> G[加载模块路由]
113
+ G --> H[加载公共路由]
114
+ H --> I[应用路由]
115
+ I --> J[设置错误处理]
116
+ J --> K[beforeStart钩子]
117
+ K --> L[run启动服务器]
118
+
119
+ G --> G1[加载服务]
120
+ G --> G2[加载控制器]
121
+ G --> G3[加载路由]
122
+
123
+ D --> D1[加载common]
124
+ D --> D2[加载helper]
125
+ D --> D3[加载extend]
42
126
  ```
43
127
 
44
- ### 初始化过程
45
-
46
- - 初始化
47
- - 加载配置
48
- - 加载模块
49
- - 加载服务
50
- - 加载控制器
51
- - 加载路由
52
- - 加载扩展
53
- - 加载插件
54
- - 加载服务
55
- - 加载控制器
56
- - 加载路由
57
- - `beforeStart()` 钩子用于将数据库中的配置合并到配置中
58
- - `run()` 启动服务器
59
-
60
- ### 官方网站
61
-
62
- 使用 Chanjs 开发的 CMS 系统
63
- 网站:[https://www.chancms.top](https://www.chancms.top)
128
+ ## 核心功能
129
+
130
+ ### 1. 依赖注入(DI)
131
+
132
+ Chanjs 提供了轻量级的依赖注入容器,支持 Service 和 Controller 的自动加载。
133
+
134
+ #### 使用方式
135
+
136
+ ```javascript
137
+ import { Service, Controller } from "chanjs";
138
+
139
+ class UserService extends Service {
140
+ constructor() {
141
+ super("user");
142
+ }
143
+
144
+ async getUserWithArticles(userId) {
145
+ const user = await this.findById(userId);
146
+ // 从依赖注入容器中获取 ArticleService 实例
147
+ const articleService = await this.get("article", "Article");
148
+ const articles = await articleService.findByUserId(userId);
149
+
150
+ return { user, articles };
151
+ }
152
+ }
153
+
154
+ class UserController extends Controller {
155
+ constructor() {
156
+ super();
157
+ }
64
158
 
65
- ### 功能亮点
159
+ async getUser(req, res, next) {
160
+ try {
161
+ const { id } = req.params;
162
+ // 从依赖注入容器中获取 UserService 实例
163
+ const userService = await this.get("user", "User");
164
+ const result = await userService.findById(id);
165
+ res.json(this.success({ data: result.data }));
166
+ } catch (err) {
167
+ next(err);
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### 2. 面向切面编程(AOP)
66
174
 
67
- - 配置文件
68
- - 多模块 MVC 结构
69
- - 插件 MVC 支持
70
- - CORS 跨域配置支持
71
- - 多数据库支持 (PostgreSQL、MySQL / MariaDB、SQLite3、Oracle Database、MSSQL)
72
- - 路由控制
73
- - Art-template 模板引擎
74
- - 静态资源管理
75
- - Cookie 处理
76
- - 日志功能
175
+ Chanjs 提供了 AOP(面向切面编程)支持,可以在方法执行前后添加切面逻辑。
77
176
 
78
- ### 运行
177
+ #### 支持的切面类型
178
+
179
+ - `before` - 方法执行前
180
+ - `after` - 方法执行后
181
+ - `error` - 方法执行异常时
182
+
183
+ #### 使用方式
184
+
185
+ ```javascript
186
+ import { aop } from "chanjs";
187
+
188
+ // 注册切面函数
189
+ aop.set("logBefore", async ({ ctx, methodName, args }) => {
190
+ console.log(`[Before] ${methodName} 被调用,参数:`, args);
191
+ });
192
+
193
+ aop.set("logAfter", async ({ ctx, methodName, result }) => {
194
+ console.log(`[After] ${methodName} 执行完成,结果:`, result);
195
+ });
196
+
197
+ aop.set("logError", async ({ ctx, methodName, error }) => {
198
+ console.error(`[Error] ${methodName} 执行失败:`, error);
199
+ });
200
+
201
+ // 绑定切面到实例方法
202
+ const controller = new UserController();
203
+ aop.wrap(controller, {
204
+ getUser: [
205
+ { type: "before", logBefore: true },
206
+ { type: "after", logAfter: true },
207
+ { type: "error", logError: true }
208
+ ]
209
+ });
210
+
211
+ // 调用方法时会自动执行切面
212
+ await controller.getUser(1);
213
+ ```
214
+
215
+ #### 切面配置选项
216
+
217
+ ```javascript
218
+ aop.wrap(instance, {
219
+ methodName: [
220
+ { type: "before", enabled: true, customParam: "value" },
221
+ { type: "after", enabled: true },
222
+ { type: "error", enabled: false }
223
+ ]
224
+ });
225
+ ```
226
+
227
+ - `type` - 切面类型(before/after/error)
228
+ - `enabled` - 是否启用该切面(默认 true)
229
+ - 其他自定义参数会传递给切面函数
230
+
231
+ ### 3. 事件系统
232
+
233
+ Chanjs 提供了基于 Node.js EventEmitter 的事件系统,支持应用内的事件发布订阅。
234
+
235
+ #### 使用方式
236
+
237
+ ```javascript
238
+ import { event } from "chanjs";
239
+
240
+ // 监听事件
241
+ event.on("user.login", (data) => {
242
+ console.log("用户登录:", data);
243
+ });
244
+
245
+ event.on("user.logout", (data) => {
246
+ console.log("用户退出:", data);
247
+ });
248
+
249
+ // 触发事件
250
+ event.emit("user.login", { userId: 1, username: "admin" });
251
+
252
+ // 移除监听器
253
+ event.off("user.login", listener);
254
+
255
+ // 移除所有监听器
256
+ event.removeAllListeners("user.login");
257
+ ```
258
+
259
+ ### 4. 自动加载控制器
260
+
261
+ Chanjs 提供了 `loadController` 辅助函数,可以自动加载指定模块下的所有控制器。
262
+
263
+ #### 使用方式
264
+
265
+ ```javascript
266
+ import { helper } from "chanjs";
267
+
268
+ // 加载 member 模块下的所有控制器
269
+ const controller = await helper.loadController("member");
270
+
271
+ // 使用控制器
272
+ controller.Member.getUser();
273
+ controller.Comment.getComments();
274
+ controller.Favorite.getFavorites();
275
+ ```
276
+
277
+ #### 目录结构
278
+
279
+ ```
280
+ member/
281
+ controller/
282
+ Member.js
283
+ Comment.js
284
+ Favorite.js
285
+ service/
286
+ Member.js
287
+ Comment.js
288
+ Favorite.js
289
+ router.js
290
+ ```
291
+
292
+ `loadController("member")` 会自动加载 `member/controller/` 目录下的所有文件,并返回一个对象:
293
+
294
+ ```javascript
295
+ {
296
+ Member: MemberController实例,
297
+ Comment: CommentController实例,
298
+ Favorite: FavoriteController实例
299
+ }
300
+ ```
301
+
302
+ ## 运行
79
303
 
80
304
  ```javascript
81
305
  import Chanjs from "chanjs";
82
306
  const chan = new Chanjs();
307
+
83
308
  // 前置钩子
84
309
  chan.beforeStart(fn);
310
+
85
311
  // 开始加载
86
312
  await chan.start();
313
+
314
+ // 启动服务器
87
315
  chan.run((port) => {
88
316
  console.log(`ChanCMS is running on ${port}`);
89
317
  });
318
+ ```
319
+
320
+ ## 完整示例
90
321
 
322
+ ```javascript
323
+ import Chanjs from "chanjs";
324
+ import { aop, event } from "chanjs";
325
+
326
+ const app = new Chanjs();
327
+
328
+ // 注册切面
329
+ aop.set("logBefore", async ({ ctx, methodName, args }) => {
330
+ console.log(`[Before] ${methodName} 被调用`);
331
+ });
332
+
333
+ // 监听事件
334
+ event.on("app.start", () => {
335
+ console.log("应用启动");
336
+ });
337
+
338
+ // 启动应用
339
+ await app.start();
340
+
341
+ // 运行
342
+ app.run((port) => {
343
+ event.emit("app.start", { port });
344
+ console.log(`Server running on port ${port}`);
345
+ });
91
346
  ```
92
347
 
93
348
  该框架专为寻求简单与功能之间平衡的开发者设计,为构建 Web 应用程序提供了一个强大的基础。
package/helper/loader.js CHANGED
@@ -29,9 +29,6 @@ export function loaderSort(modules = []) {
29
29
  * @description
30
30
  * 从 config/index.js 加载配置,支持缓存机制
31
31
  * 如果存在缓存且未过期,则直接返回缓存值
32
- * @example
33
- * const config = await loadConfig();
34
- * console.log(config.APP_NAME);
35
32
  */
36
33
  export async function loadConfig() {
37
34
  const cacheKey = 'chanjs:config';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "chanjs",
4
- "version": "2.6.0",
4
+ "version": "2.6.1",
5
5
  "description": "chanjs基于express5 纯js研发的轻量级mvc框架。",
6
6
  "main": "index.js",
7
7
  "module": "index.js",