# Chanjs

Chanjs 是一个基于 Express 5+ 构建的轻量级 MVC 框架，完全使用 JavaScript 开发。它体现了函数式编程的概念，提供了卓越的性能、清晰的代码和易于遵循的过程，确保了高可维护性。

‌ChanJS‌ 是一个基于 ‌Express 5+‌ 构建的轻量级 ‌MVC 框架‌，完全使用纯 JavaScript 开发，强调函数式编程理念，具有高性能、代码清晰、易维护等特点。

## 特点

### 核心架构
- ✅ Express 5+ 原生
- ✅ Node.js 24+
- ✅ ES Modules (import / export)
- ✅ 多模块 MVC 架构
- ✅ 轻量级内核
- ✅ 约定优于配置

### 模块化
- ✅ 多模块路由
- ✅ 模块化 views
- ✅ 模块化 controllers
- ✅ 模块化 services
- ✅ 模块化 middleware

### 数据库
- ✅ Knex.js 查询构建器
- ✅ SQLite / MySQL / PostgreSQL
- ✅ 连接池
- ✅ 事务
- ✅ 自动时间格式化

### 安全能力
- ✅ WAF 防火墙
- ✅ XSS 防护
- ✅ 关键词过滤
- ✅ 请求限流
- ✅ 路由白名单
- ✅ Cookie 安全

### 中间件生态
- ✅ CORS
- ✅ 请求解析
- ✅ Cookie
- ✅ 静态资源
- ✅ 日志
- ✅ Art-template 模板引擎

### 高级特性
- ✅ DI 依赖注入（Map 实现）
- ✅ AOP 切面（before/after/error）
- ✅ 事件系统
- ✅ 自动加载控制器
- ✅ 定时任务
- ✅ WebSocket
- ✅ 缓存系统（Redis 和 内存缓存 map 实现）
- ✅ 分页器
- ✅ 国际化 i18n
- ✅ 请求验证器
- ✅ 全局异常处理
- ✅ 接口文档自动生成
- ✅ 文件上传 / OSS 扩展口

### 开发体验
- ✅ 多环境配置
- ✅ 统一响应
- ✅ 工具函数

## 约定优于配置

```code
|- app
    |- common
    |- helper
    |- middleware
    |- modules 
        |- module1 
            |- controller 
            |- service 
            |- middleware
            |- router.js 
        |- module2 
            |- controller 
            |- service 
            |- router.js
    |- plugins
        |- plugin1
            |- controller
            |- router.js
    |- router.js
|- config 
|- data
|- doc
|- public
|- view
|- app.js
|-.env.dev
|-.env.prd
|- pm2.json
|- package.json
```


## npm 包参考

```json
{
  "art-template": "^4.13.4",
  "body-parser": "^2.2.0",
  "cookie-parser": "^1.4.7",
  "cors": "^2.8.5",
  "dotenv": "^17.2.1",
  "dayjs": "^1.11.13",
  "express": "^5.1.0",
  "express-art-template": "^1.0.1",
  "knex": "^3.1.0",
  "morgan": "^1.10.0",
  "mysql2": "^3.14.1",
  "marked": "^17.0.3",
  "adm-zip": "^0.5.16",
  "bcryptjs": "^3.0.2",
  "better-sqlite3": "^12.8.0",
  "chanjs": "^2.6.10",
  "cheerio": "^1.1.2",
  "crypto-js": "^4.2.0",
  "iconv-lite": "^0.6.3",
  "jsonwebtoken": "^9.0.2",
  "multer": "^2.0.2",
  "nodemailer": "^7.0.6",
  "qiniu": "^7.14.0",
  "serve-favicon": "^2.5.1",
  "xml2js": "^0.6.2",
  "xss": "^1.0.15",
  "zod": "^4.1.11"
}
```

## 初始化过程

```
初始化流程：

┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│  初始化  │───▶│ 加载配置 │───▶│ 加载数据库│───▶│ 加载扩展 │
└─────────┘    └─────────┘    └─────────┘    └─────────┘
                                                  │
                    ┌─────────┐    ┌─────────┐   │
                    │ 加载服务 │    │ 加载控制器│   │
                    └────▲────┘    └────▲────┘   │
                         │              │        │
┌─────────┐    ┌─────────┐    ┌─────────┐    ┌──┴──────┐
│ 应用路由 │◀───│加载公共路由│◀───│加载模块路由│◀───│加载中间件│
└────┬────┘    └─────────┘    └────┬────┘    └─────────┘
     │                             │
     │    ┌─────────┐    ┌─────────┐    ┌─────────┐
     └───▶│设置错误处理│───▶│beforeStart│───▶│ run启动  │
          └─────────┘    └─────────┘    └─────────┘
```

## 核心功能

### 1. 依赖注入（DI）

Chanjs 提供了轻量级的依赖注入容器，支持 Service 和 Controller 的自动加载。

#### 使用方式

```javascript
import { Service, Controller } from "chanjs";

class UserService extends Service {
  constructor() {
    super("user");
  }
  
 
}

class UserController extends Controller {
  constructor() {
    super();
  }
  
  async getUser(req, res, next) {
    
  }
}
```

### 2. 面向切面编程（AOP）

Chanjs 提供了 AOP（面向切面编程）支持，可以在方法执行前后添加切面逻辑。

#### 支持的切面类型

- `before` - 方法执行前
- `after` - 方法执行后
- `error` - 方法执行异常时

#### 使用方式

```javascript
import { aop } from "chanjs";

// 注册切面函数
aop.set("logBefore", async ({ ctx, methodName, args }) => {
  console.log(`[Before] ${methodName} 被调用，参数:`, args);
});

aop.set("logAfter", async ({ ctx, methodName, result }) => {
  console.log(`[After] ${methodName} 执行完成，结果:`, result);
});

aop.set("logError", async ({ ctx, methodName, error }) => {
  console.error(`[Error] ${methodName} 执行失败:`, error);
});

// 绑定切面到实例方法
const controller = new UserController();
aop.wrap(controller, {
  getUser: [
    { type: "before", logBefore: true },
    { type: "after", logAfter: true },
    { type: "error", logError: true }
  ]
});

// 调用方法时会自动执行切面
await controller.getUser(1);
```

#### 切面配置选项

```javascript
aop.wrap(instance, {
  methodName: [
    { type: "before", enabled: true, customParam: "value" },
    { type: "after", enabled: true },
    { type: "error", enabled: false }
  ]
});
```

- `type` - 切面类型（before/after/error）
- `enabled` - 是否启用该切面（默认 true）
- 其他自定义参数会传递给切面函数

### 3. 事件系统

Chanjs 提供了基于 Node.js EventEmitter 的事件系统，支持应用内的事件发布订阅。

#### 使用方式

```javascript
import { event } from "chanjs";

// 监听事件
event.on("user.login", (data) => {
  console.log("用户登录:", data);
});

event.on("user.logout", (data) => {
  console.log("用户退出:", data);
});

// 触发事件
event.emit("user.login", { userId: 1, username: "admin" });

// 移除监听器
event.off("user.login", listener);

// 移除所有监听器
event.removeAllListeners("user.login");
```

### 4. 自动加载控制器

Chanjs 提供了 `loadController` 辅助函数，可以自动加载指定模块下的所有控制器。

#### 使用方式

```javascript
import { helper } from "chanjs";

// 加载 member 模块下的所有控制器
const controller = await helper.loadController("member");

// 使用控制器
controller.Member.getUser();
controller.Comment.getComments();
controller.Favorite.getFavorites();
```

#### 目录结构

```
member/
  controller/
    Member.js
    Comment.js
    Favorite.js
  service/
    Member.js
    Comment.js
    Favorite.js
  router.js
```

`loadController("member")` 会自动加载 `member/controller/` 目录下的所有文件，并返回一个对象：

```javascript
{
  Member: MemberController实例,
  Comment: CommentController实例,
  Favorite: FavoriteController实例
}
```

## 运行

```javascript
import Chanjs from "chanjs";
const chan = new Chanjs();

// 前置钩子
chan.beforeStart(fn);

// 开始加载
await chan.start();

// 启动服务器
chan.run((port) => {
  console.log(`ChanCMS is running on ${port}`);
});
```

## 完整示例

```javascript
import Chanjs from "chanjs";
import { aop, event } from "chanjs";

const app = new Chanjs();

// 注册切面
aop.set("logBefore", async ({ ctx, methodName, args }) => {
  console.log(`[Before] ${methodName} 被调用`);
});

// 监听事件
event.on("app.start", () => {
  console.log("应用启动");
});

// 启动应用
await app.start();

// 运行
app.run((port) => {
  event.emit("app.start", { port });
  console.log(`Server running on port ${port}`);
});
```

该框架专为寻求简单与功能之间平衡的开发者设计，为构建 Web 应用程序提供了一个强大的基础。