chanjs 1.0.36 → 1.0.38
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 +46 -46
- package/core/chan.js +16 -35
- package/core/lib/extend/cache.js +134 -0
- package/package.json +1 -1
package/README.md
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
|
2
|
-
#
|
2
|
+
# Chanjs
|
3
3
|
|
4
|
-
|
4
|
+
Chanjs 是一个基于 Express 构建的轻量级 MVC 框架,完全使用 JavaScript 开发。它体现了函数式编程的概念,提供了卓越的性能、清晰的代码和易于遵循的过程,确保了高可维护性。
|
5
5
|
|
6
6
|
## features
|
7
7
|
|
8
|
-
-
|
9
|
-
-
|
10
|
-
-
|
11
|
-
-
|
12
|
-
-
|
13
|
-
-
|
14
|
-
-
|
15
|
-
-
|
16
|
-
-
|
17
|
-
-
|
8
|
+
- 基于 Express 构建
|
9
|
+
- 支持 ES6 语法
|
10
|
+
- 模块化设计
|
11
|
+
- 多模块化路由
|
12
|
+
- 模块化 views
|
13
|
+
- 模块化 controllers
|
14
|
+
- 模块化 services
|
15
|
+
- 插件式架构
|
16
|
+
- 轻量级(核心代码在300行以内)
|
17
|
+
- 缓存支持
|
18
18
|
|
19
|
-
##
|
19
|
+
## 约定优于配置
|
20
20
|
|
21
21
|
```code
|
22
22
|
|- app
|
@@ -49,51 +49,51 @@ Chan.js is a lightweight MVC framework developed in pure JavaScript based on Exp
|
|
49
49
|
|- index.js
|
50
50
|
```
|
51
51
|
|
52
|
-
###
|
52
|
+
### 初始化过程
|
53
53
|
|
54
|
-
-
|
55
|
-
-
|
56
|
-
-
|
57
|
-
-
|
58
|
-
-
|
59
|
-
-
|
60
|
-
-
|
61
|
-
-
|
62
|
-
-
|
63
|
-
-
|
64
|
-
-
|
65
|
-
- beforeStart()
|
66
|
-
- run()
|
54
|
+
- 初始化
|
55
|
+
- 加载配置
|
56
|
+
- 加载模块
|
57
|
+
- 加载服务
|
58
|
+
- 加载控制器
|
59
|
+
- 加载路由
|
60
|
+
- 加载扩展
|
61
|
+
- 加载插件
|
62
|
+
- 加载服务
|
63
|
+
- 加载控制器
|
64
|
+
- 加载路由
|
65
|
+
- `beforeStart()` 钩子用于将数据库中的配置合并到配置中
|
66
|
+
- `run()` 启动服务器
|
67
67
|
|
68
|
-
###
|
68
|
+
### ### 官方网站
|
69
69
|
|
70
|
-
|
71
|
-
|
70
|
+
使用 Chanjs 开发的 CMS 系统
|
71
|
+
网站:[https://www.chancms.top](https://www.chancms.top)
|
72
72
|
|
73
|
-
###
|
73
|
+
### 功能亮点
|
74
74
|
|
75
|
-
-
|
76
|
-
-
|
77
|
-
-
|
78
|
-
- CORS
|
79
|
-
- MySQL
|
80
|
-
-
|
81
|
-
- Art-template
|
82
|
-
-
|
83
|
-
- Cookie
|
84
|
-
-
|
75
|
+
- 配置文件
|
76
|
+
- 多模块 MVC 结构
|
77
|
+
- 插件 MVC 支持
|
78
|
+
- CORS 跨域配置支持
|
79
|
+
- MySQL 数据库支持
|
80
|
+
- 路由控制
|
81
|
+
- Art-template 模板引擎
|
82
|
+
- 静态资源管理
|
83
|
+
- Cookie 处理
|
84
|
+
- 日志功能
|
85
85
|
|
86
|
-
###
|
86
|
+
### 运行
|
87
87
|
|
88
88
|
```javascript
|
89
89
|
const Chanjs = require("chanjs");
|
90
90
|
const chan = new Chanjs();
|
91
|
-
//
|
91
|
+
// 加载中间件
|
92
92
|
chan.beforeStart(fn);
|
93
|
-
//
|
93
|
+
// 扫描模块
|
94
94
|
chan.start();
|
95
|
-
//
|
95
|
+
// 启动服务器
|
96
96
|
chan.run();
|
97
97
|
```
|
98
98
|
|
99
|
-
|
99
|
+
该框架专为寻求简单与功能之间平衡的开发者设计,为构建 Web 应用程序提供了一个强大的基础。
|
package/core/chan.js
CHANGED
@@ -6,6 +6,7 @@ const config = require("./lib/config/config.js");
|
|
6
6
|
const {bindClass,createKnex,loadWebToEnd} = require("./lib/extend/helper.js");
|
7
7
|
const Controller = require("./lib/controller/controller.js");
|
8
8
|
const Service = require("./lib/service/service.js");
|
9
|
+
const cache = require('./lib/extend/cache.js');
|
9
10
|
const core = require("./lib/index.js");
|
10
11
|
/**
|
11
12
|
* @description 基于express封装的mvc框架,遵循约定优于配置原则
|
@@ -15,6 +16,7 @@ class Chan {
|
|
15
16
|
static modules = {};
|
16
17
|
static plugins = {};
|
17
18
|
static config = config;
|
19
|
+
static cache = cache;
|
18
20
|
static Controller = Controller;
|
19
21
|
static Service = Service;
|
20
22
|
constructor() {
|
@@ -130,30 +132,25 @@ class Chan {
|
|
130
132
|
this.loadRoutes(modules, moduleName);
|
131
133
|
}
|
132
134
|
|
135
|
+
loadFiles(modules, moduleName, type) {
|
136
|
+
const dir = path.join(Chan.config.APP_PATH, modules, moduleName, type);
|
137
|
+
if (fs.existsSync(dir)) {
|
138
|
+
const files = fs.readdirSync(dir).filter(file => file.endsWith(".js"));
|
139
|
+
files.forEach(file => {
|
140
|
+
const module = require(path.join(dir, file));
|
141
|
+
const name = file.replace(".js", "");
|
142
|
+
Chan[modules][moduleName][type][name] = { ...bindClass(module) };
|
143
|
+
});
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
133
147
|
/**
|
134
148
|
* @description 扫描模块下所有service
|
135
149
|
* @param {*} moduleDir 模块路径
|
136
150
|
* @param {*} moduleName 模块名称
|
137
151
|
*/
|
138
152
|
loadServices(modules, moduleName) {
|
139
|
-
|
140
|
-
Chan.config.APP_PATH,
|
141
|
-
modules,
|
142
|
-
moduleName,
|
143
|
-
"service"
|
144
|
-
);
|
145
|
-
if (fs.existsSync(servicesDir)) {
|
146
|
-
let services = fs
|
147
|
-
.readdirSync(servicesDir)
|
148
|
-
.filter((file) => file.endsWith(".js"));
|
149
|
-
for (let i = 0, file; i < services.length; i++) {
|
150
|
-
file = services[i];
|
151
|
-
const Service = require(path.join(servicesDir, file));
|
152
|
-
const serviceName = file.replace(".js", "");
|
153
|
-
//模块文件夹-模块文件名-服务-方法
|
154
|
-
Chan[modules][moduleName].service[serviceName] = {...bindClass(Service)};
|
155
|
-
}
|
156
|
-
}
|
153
|
+
this.loadFiles(modules, moduleName, "service");
|
157
154
|
}
|
158
155
|
|
159
156
|
/**
|
@@ -162,23 +159,7 @@ class Chan {
|
|
162
159
|
* @param {*} moduleName 模块名称
|
163
160
|
*/
|
164
161
|
loadControllers(modules, moduleName) {
|
165
|
-
|
166
|
-
Chan.config.APP_PATH,
|
167
|
-
modules,
|
168
|
-
moduleName,
|
169
|
-
"controller"
|
170
|
-
);
|
171
|
-
if (fs.existsSync(controllersDir)) {
|
172
|
-
let controllers = fs
|
173
|
-
.readdirSync(controllersDir)
|
174
|
-
.filter((file) => file.endsWith(".js"));
|
175
|
-
for (let i = 0, file; i < controllers.length; i++) {
|
176
|
-
file = controllers[i];
|
177
|
-
const controller = require(path.join(controllersDir, file));
|
178
|
-
const controllerName = file.replace(".js", "");
|
179
|
-
Chan[modules][moduleName].controller[controllerName] = {...bindClass(controller)};
|
180
|
-
}
|
181
|
-
}
|
162
|
+
this.loadFiles(modules, moduleName, "controller");
|
182
163
|
}
|
183
164
|
|
184
165
|
/**
|
@@ -0,0 +1,134 @@
|
|
1
|
+
class Cache {
|
2
|
+
constructor(maxSize = 1000) {
|
3
|
+
this.cache = new Map(); // 使用 Map 存储缓存数据
|
4
|
+
this.maxSize = maxSize; // 缓存最大容量
|
5
|
+
this.hits = 0; // 缓存命中次数
|
6
|
+
this.misses = 0; // 缓存未命中次数
|
7
|
+
}
|
8
|
+
|
9
|
+
/**
|
10
|
+
* 设置缓存
|
11
|
+
* @param {string} key - 缓存键
|
12
|
+
* @param {any} value - 缓存值
|
13
|
+
* @param {number} ttl - 缓存时间(毫秒),可选
|
14
|
+
*/
|
15
|
+
set(key, value, ttl = null) {
|
16
|
+
// 如果缓存已满,删除最早的一个缓存项
|
17
|
+
if (this.cache.size >= this.maxSize) {
|
18
|
+
const firstKey = this.cache.keys().next().value;
|
19
|
+
this.cache.delete(firstKey);
|
20
|
+
}
|
21
|
+
|
22
|
+
const cacheItem = {
|
23
|
+
value,
|
24
|
+
expires: ttl ? Date.now() + ttl : null, // 设置过期时间
|
25
|
+
updatedAt: Date.now(), // 记录更新时间
|
26
|
+
};
|
27
|
+
this.cache.set(key, cacheItem);
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* 获取缓存
|
32
|
+
* @param {string} key - 缓存键
|
33
|
+
* @returns {any} - 缓存值,如果过期或不存在则返回 null
|
34
|
+
*/
|
35
|
+
get(key) {
|
36
|
+
if (!this.cache.has(key)) {
|
37
|
+
this.misses++; // 未命中
|
38
|
+
return null;
|
39
|
+
}
|
40
|
+
|
41
|
+
const cacheItem = this.cache.get(key);
|
42
|
+
|
43
|
+
// 检查是否过期
|
44
|
+
if (cacheItem.expires && Date.now() > cacheItem.expires) {
|
45
|
+
this.cache.delete(key); // 删除过期缓存
|
46
|
+
this.misses++; // 未命中
|
47
|
+
return null;
|
48
|
+
}
|
49
|
+
|
50
|
+
this.hits++; // 命中
|
51
|
+
return cacheItem.value; // 返回缓存值
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* 清除指定缓存
|
56
|
+
* @param {string} key - 缓存键
|
57
|
+
*/
|
58
|
+
clear(key) {
|
59
|
+
this.cache.delete(key);
|
60
|
+
}
|
61
|
+
|
62
|
+
/**
|
63
|
+
* 清除所有缓存
|
64
|
+
*/
|
65
|
+
clearAll() {
|
66
|
+
this.cache.clear();
|
67
|
+
this.hits = 0;
|
68
|
+
this.misses = 0;
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* 获取缓存命中率
|
73
|
+
* @returns {number} - 命中率(0 到 1 之间)
|
74
|
+
*/
|
75
|
+
getHitRate() {
|
76
|
+
const total = this.hits + this.misses;
|
77
|
+
return total === 0 ? 0 : this.hits / total;
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* 获取缓存大小
|
82
|
+
* @returns {number} - 缓存项数量
|
83
|
+
*/
|
84
|
+
size() {
|
85
|
+
return this.cache.size;
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* 获取所有缓存键
|
90
|
+
* @returns {string[]} - 缓存键列表
|
91
|
+
*/
|
92
|
+
keys() {
|
93
|
+
return Array.from(this.cache.keys());
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* 遍历缓存项
|
98
|
+
* @param {function} callback - 回调函数,接收 key 和 value 作为参数
|
99
|
+
*/
|
100
|
+
forEach(callback) {
|
101
|
+
this.cache.forEach((cacheItem, key) => {
|
102
|
+
callback(key, cacheItem.value);
|
103
|
+
});
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
module.exports = new Cache();
|
108
|
+
|
109
|
+
// // 示例用法
|
110
|
+
// const cache = new SimpleCache(100); // 设置缓存最大容量为 100
|
111
|
+
|
112
|
+
// // 设置缓存,有效期为 5 秒
|
113
|
+
// cache.set('name', 'Alice', 5000);
|
114
|
+
// cache.set('name', 'Alice', 5000);
|
115
|
+
// // 获取缓存
|
116
|
+
// console.log(cache.get('name')); // 输出: Alice
|
117
|
+
|
118
|
+
// // 获取缓存命中率
|
119
|
+
// console.log(cache.getHitRate()); // 输出: 1 (100% 命中率)
|
120
|
+
|
121
|
+
// // 获取缓存大小
|
122
|
+
// console.log(cache.size()); // 输出: 1
|
123
|
+
|
124
|
+
// // 获取所有缓存键
|
125
|
+
// console.log(cache.keys()); // 输出: ['name']
|
126
|
+
|
127
|
+
// // 遍历缓存项
|
128
|
+
// cache.forEach((key, value) => {
|
129
|
+
// console.log(`Key: ${key}, Value: ${value}`);
|
130
|
+
// });
|
131
|
+
|
132
|
+
// // 清除所有缓存
|
133
|
+
// cache.clearAll();
|
134
|
+
// console.log(cache.size()); // 输出: 0
|