chanjs 2.7.4 → 2.7.5
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/USAGE.md +533 -0
- package/config/index.js +37 -6
- package/core/App.js +166 -0
- package/core/Container.js +77 -0
- package/core/Controller.js +29 -0
- package/core/Database.js +93 -0
- package/core/Repository.js +327 -0
- package/core/Service.js +11 -0
- package/core/bootstrap/error-handler.js +104 -0
- package/core/bootstrap/hook-runner.js +64 -0
- package/core/bootstrap/middleware.js +35 -0
- package/core/bootstrap/router-loader.js +53 -0
- package/core/errors.js +224 -0
- package/core/loader.js +89 -0
- package/core/registry.js +17 -0
- package/doc/Cache.md +279 -106
- package/doc/Common.md +590 -134
- package/doc/Controller.md +166 -95
- package/doc/Help.md +299 -698
- package/doc/QuickStart.md +116 -0
- package/doc/Repository.md +560 -0
- package/doc/Service.md +201 -527
- package/index.js +75 -37
- package/middleware/body.js +17 -0
- package/middleware/cookie.js +7 -15
- package/middleware/cors.js +9 -27
- package/middleware/favicon.js +7 -17
- package/middleware/header.js +15 -16
- package/middleware/index.js +11 -11
- package/middleware/log.js +26 -56
- package/middleware/static.js +15 -28
- package/middleware/template.js +75 -115
- package/middleware/validate.js +79 -0
- package/middleware/waf.js +174 -197
- package/package.json +9 -2
- package/response/code.js +73 -0
- package/response/index.js +9 -6
- package/response/response.js +82 -236
- package/security/checker.js +26 -74
- package/security/index.js +4 -9
- package/security/jwt.js +69 -142
- package/security/keywords.js +32 -136
- package/security/rate-limit.js +38 -80
- package/security/sign.js +83 -176
- package/security/xss-filter.js +21 -53
- package/storage/cache.js +57 -196
- package/storage/index.js +3 -6
- package/storage/redis.js +123 -181
- package/storage/store.js +163 -188
- package/utils/data-parse.js +42 -186
- package/utils/file.js +73 -244
- package/utils/filter.js +22 -25
- package/utils/html.js +49 -33
- package/utils/index.js +21 -7
- package/utils/ip.js +31 -71
- package/utils/logger.js +117 -0
- package/utils/pages.js +55 -0
- package/utils/paths.js +18 -0
- package/utils/request.js +94 -136
- package/utils/signal.js +87 -0
- package/utils/time.js +33 -75
- package/utils/tree.js +112 -104
- package/App.js +0 -533
- package/base/Aop.js +0 -195
- package/base/Container.js +0 -161
- package/base/Controller.js +0 -65
- package/base/Database.js +0 -133
- package/base/Event.js +0 -61
- package/base/Repository.js +0 -644
- package/common/api.js +0 -35
- package/common/code.js +0 -52
- package/common/email.js +0 -191
- package/common/index.js +0 -5
- package/common/pages.js +0 -120
- package/common/utils.js +0 -73
- package/config/code.js +0 -166
- package/config/paths.js +0 -60
- package/doc/Aop.md +0 -269
- package/doc/Email.md +0 -114
- package/doc/Event.md +0 -232
- package/global/env.js +0 -11
- package/global/import.js +0 -39
- package/global/index.js +0 -8
- package/helper/index.js +0 -79
- package/loader/index.js +0 -6
- package/loader/loader.js +0 -138
- package/middleware/compress.js +0 -185
- package/middleware/setBody.js +0 -32
- package/realtime/index.js +0 -7
- package/realtime/sse.js +0 -424
- package/realtime/websocket.js +0 -540
- package/schedule/index.js +0 -6
- package/schedule/schedule.js +0 -491
package/doc/Cache.md
CHANGED
|
@@ -1,160 +1,333 @@
|
|
|
1
|
-
# Cache
|
|
1
|
+
# Cache 缓存工具
|
|
2
|
+
|
|
2
3
|
## 概述
|
|
3
|
-
`Cache` 是一个基于内存实现的 LRU(最近最少使用)缓存类,支持 TTL(生存时间)过期策略和自动过期清理机制。该类通过两个 `Map` 分别存储缓存数据和访问顺序,既保证了缓存的快速存取,又能实现 LRU 淘汰策略,适用于需要临时缓存数据且对内存使用有控制需求的场景。
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { Cache } from 'chanjs/helper';
|
|
9
|
-
// 或引入预创建的默认缓存实例
|
|
10
|
-
import { cache } from 'chanjs/helper';
|
|
11
|
-
```
|
|
5
|
+
`Cache` 是基于单 Map 实现的 LRU + 惰性 TTL 过期清理缓存类,对齐 Redis incr 行为,专用于限流场景的内存存储。
|
|
6
|
+
|
|
7
|
+
## 特性
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
- **LRU 淘汰**:访问刷新 LRU 顺序,容量超限时自动淘汰最久未使用的条目
|
|
10
|
+
- **惰性 TTL**:自增不续期,批量惰性清理过期条目
|
|
11
|
+
- **容量淘汰**:达到最大容量时自动 LRU 淘汰
|
|
12
|
+
- **高性能**:10w 容量,定时批量清理避免阻塞事件循环
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|------|------|--------|------|
|
|
19
|
-
| options.maxSize | number | 1000 | 缓存最大条目数,达到该数量时会自动淘汰最久未使用的条目 |
|
|
20
|
-
| options.defaultTTL | number | 300000(5分钟) | 默认过期时间(毫秒),未指定 TTL 时使用该值 |
|
|
14
|
+
## 引入方式
|
|
21
15
|
|
|
22
|
-
**示例**:
|
|
23
16
|
```javascript
|
|
24
|
-
|
|
25
|
-
const customCache = new Cache({
|
|
26
|
-
maxSize: 500, // 最大缓存500条
|
|
27
|
-
defaultTTL: 60000 // 默认1分钟过期
|
|
28
|
-
});
|
|
17
|
+
import { cache } from 'chanjs';
|
|
29
18
|
|
|
30
|
-
//
|
|
31
|
-
|
|
19
|
+
// 或创建自定义实例
|
|
20
|
+
import Cache from 'chanjs/storage/cache.js';
|
|
21
|
+
const customCache = new Cache({ maxSize: 50000, defaultTTL: 60000 });
|
|
32
22
|
```
|
|
33
23
|
|
|
24
|
+
## 构造函数
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
new Cache(opts = {})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**参数**
|
|
31
|
+
|
|
32
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
33
|
+
|------|------|------|--------|------|
|
|
34
|
+
| opts.maxSize | number | 否 | 100000 | 缓存最大条目数 |
|
|
35
|
+
| opts.defaultTTL | number | 否 | 300000 (5分钟) | 默认过期时间(毫秒) |
|
|
36
|
+
|
|
34
37
|
## 核心方法
|
|
35
|
-
### 1. 设置缓存值
|
|
36
|
-
#### `set(key, value, ttl = this.defaultTTL)`
|
|
37
|
-
将键值对存入缓存,若缓存达到最大容量且键不存在,则自动淘汰最久未使用的条目,每次设置会更新访问时间。
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
### 1. set - 写入缓存
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
set(key, value, ttl = this.defaultTTL)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**参数**
|
|
46
|
+
|
|
47
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
48
|
+
|------|------|------|--------|------|
|
|
49
|
+
| key | string | 是 | - | 缓存键 |
|
|
50
|
+
| value | any | 是 | - | 缓存值 |
|
|
51
|
+
| ttl | number | 否 | defaultTTL | 过期时间(毫秒),<=0 视为永久存储 |
|
|
52
|
+
|
|
53
|
+
**示例**
|
|
44
54
|
|
|
45
|
-
**示例**:
|
|
46
55
|
```javascript
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
import { cache } from 'chanjs';
|
|
57
|
+
|
|
58
|
+
// 设置 60 秒过期的缓存
|
|
59
|
+
cache.set('user:1001', { name: '张三' }, 60000);
|
|
49
60
|
|
|
50
|
-
//
|
|
51
|
-
|
|
61
|
+
// 永久存储(ttl <= 0)
|
|
62
|
+
cache.set('config:app', { version: '1.0' }, 0);
|
|
52
63
|
```
|
|
53
64
|
|
|
54
|
-
### 2.
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
### 2. get - 读取缓存
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
get(key)
|
|
69
|
+
```
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
|------|------|------|
|
|
60
|
-
| key | string | 要获取的缓存键 |
|
|
71
|
+
**参数**
|
|
61
72
|
|
|
62
|
-
|
|
|
63
|
-
|
|
64
|
-
|
|
|
73
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
74
|
+
|------|------|------|------|
|
|
75
|
+
| key | string | 是 | 缓存键 |
|
|
76
|
+
|
|
77
|
+
**返回值**
|
|
78
|
+
|
|
79
|
+
- 缓存值:存在且未过期
|
|
80
|
+
- `null`:不存在或已过期
|
|
81
|
+
|
|
82
|
+
**示例**
|
|
65
83
|
|
|
66
|
-
**示例**:
|
|
67
84
|
```javascript
|
|
68
|
-
const user =
|
|
69
|
-
if (user
|
|
70
|
-
console.log('
|
|
85
|
+
const user = cache.get('user:1001');
|
|
86
|
+
if (user) {
|
|
87
|
+
console.log('用户信息:', user);
|
|
71
88
|
} else {
|
|
72
|
-
console.log('
|
|
89
|
+
console.log('缓存不存在或已过期');
|
|
73
90
|
}
|
|
74
91
|
```
|
|
75
92
|
|
|
76
|
-
### 3.
|
|
77
|
-
|
|
78
|
-
|
|
93
|
+
### 3. has - 检查存在
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
has(key)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**参数**
|
|
100
|
+
|
|
101
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
102
|
+
|------|------|------|------|
|
|
103
|
+
| key | string | 是 | 缓存键 |
|
|
104
|
+
|
|
105
|
+
**返回值**
|
|
106
|
+
|
|
107
|
+
- `true`:存在且未过期
|
|
108
|
+
- `false`:不存在或已过期
|
|
109
|
+
|
|
110
|
+
**示例**
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
if (cache.has('user:1001')) {
|
|
114
|
+
console.log('缓存存在');
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 4. del - 删除缓存
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
del(key)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**示例**
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
cache.del('user:1001');
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 5. clear - 清空所有
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
clear()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**示例**
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
cache.clear();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 6. size - 获取数量
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
size()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**返回值**
|
|
149
|
+
|
|
150
|
+
缓存条目总数(近似值,包含未惰性清理的过期项)
|
|
79
151
|
|
|
80
|
-
|
|
81
|
-
|------|------|------|
|
|
82
|
-
| key | string | 要删除的缓存键 |
|
|
152
|
+
**示例**
|
|
83
153
|
|
|
84
|
-
**示例**:
|
|
85
154
|
```javascript
|
|
86
|
-
|
|
155
|
+
const count = cache.size();
|
|
156
|
+
console.log(`缓存条目数:${count}`);
|
|
87
157
|
```
|
|
88
158
|
|
|
89
|
-
###
|
|
90
|
-
#### `clear()`
|
|
91
|
-
删除所有缓存条目和访问记录,清空整个缓存。
|
|
159
|
+
### 7. incr - 自增(限流专用)
|
|
92
160
|
|
|
93
|
-
**示例**:
|
|
94
161
|
```javascript
|
|
95
|
-
|
|
162
|
+
incr(key, ttlMs = 60000)
|
|
96
163
|
```
|
|
97
164
|
|
|
98
|
-
|
|
99
|
-
#### `has(key)`
|
|
100
|
-
检查指定键是否存在且未过期,若已过期则自动删除条目并返回 `false`。
|
|
165
|
+
**参数**
|
|
101
166
|
|
|
102
|
-
| 参数 | 类型 | 说明 |
|
|
103
|
-
|
|
104
|
-
| key | string |
|
|
167
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
168
|
+
|------|------|------|--------|------|
|
|
169
|
+
| key | string | 是 | - | 缓存键 |
|
|
170
|
+
| ttlMs | number | 否 | 60000 | 新建 key 的过期时间(毫秒),存量不续期 |
|
|
105
171
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
172
|
+
**返回值**
|
|
173
|
+
|
|
174
|
+
自增后的值(number)
|
|
175
|
+
|
|
176
|
+
**特性**
|
|
177
|
+
|
|
178
|
+
- 新建 key 使用指定 TTL
|
|
179
|
+
- 存量 key 不续期 TTL
|
|
180
|
+
- 支持容量超限自动 LRU 淘汰
|
|
181
|
+
|
|
182
|
+
**示例**
|
|
109
183
|
|
|
110
|
-
**示例**:
|
|
111
184
|
```javascript
|
|
112
|
-
|
|
113
|
-
|
|
185
|
+
// 限流场景:60 秒内最多 100 次请求
|
|
186
|
+
const count = cache.incr('rate:192.168.1.1', 60000);
|
|
187
|
+
if (count > 100) {
|
|
188
|
+
console.log('请求过于频繁');
|
|
114
189
|
} else {
|
|
115
|
-
console.log(
|
|
190
|
+
console.log(`当前第 ${count} 次请求`);
|
|
116
191
|
}
|
|
117
192
|
```
|
|
118
193
|
|
|
119
|
-
###
|
|
120
|
-
|
|
121
|
-
|
|
194
|
+
### 8. incrAndExpire - 自增并设置过期时间
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
incrAndExpire(key, ttlMs)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**参数**
|
|
201
|
+
|
|
202
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
203
|
+
|------|------|------|------|
|
|
204
|
+
| key | string | 是 | 缓存键 |
|
|
205
|
+
| ttlMs | number | 是 | 新建 key 的过期时间(毫秒) |
|
|
122
206
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
207
|
+
**返回值**
|
|
208
|
+
|
|
209
|
+
自增后的值(number)
|
|
210
|
+
|
|
211
|
+
**示例**
|
|
126
212
|
|
|
127
|
-
**示例**:
|
|
128
213
|
```javascript
|
|
129
|
-
|
|
214
|
+
const count = cache.incrAndExpire('limit:api:1001', 30000);
|
|
130
215
|
```
|
|
131
216
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
217
|
+
### 9. expire - 刷新过期时间
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
expire(key, ttlMs)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**参数**
|
|
224
|
+
|
|
225
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
226
|
+
|------|------|------|------|
|
|
227
|
+
| key | string | 是 | 缓存键 |
|
|
228
|
+
| ttlMs | number | 是 | 新的过期时间(毫秒) |
|
|
229
|
+
|
|
230
|
+
**返回值**
|
|
231
|
+
|
|
232
|
+
- `true`:刷新成功
|
|
233
|
+
- `false`:key 不存在或已过期
|
|
135
234
|
|
|
136
|
-
|
|
137
|
-
清理所有已过期的缓存条目,在调用 `size()` 方法时自动触发。遍历缓存 `Map`,删除所有过期的条目及对应的访问记录。
|
|
235
|
+
**示例**
|
|
138
236
|
|
|
139
|
-
## 预创建实例
|
|
140
|
-
模块导出了一个默认的 `cache` 实例,使用默认配置(`maxSize=1000`,`defaultTTL=5分钟`),可直接使用:
|
|
141
237
|
```javascript
|
|
142
|
-
|
|
238
|
+
// 续期 30 秒
|
|
239
|
+
cache.expire('session:1001', 30000);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## 内部机制
|
|
243
|
+
|
|
244
|
+
### LRU 淘汰
|
|
245
|
+
|
|
246
|
+
- 使用 Map 的插入顺序特性
|
|
247
|
+
- 访问时删除再插入,刷新到最新位置
|
|
248
|
+
- 容量超限时淘汰最久未使用的条目
|
|
249
|
+
|
|
250
|
+
### 惰性清理
|
|
251
|
+
|
|
252
|
+
- 每 10 秒触发一次批量清理
|
|
253
|
+
- 单次最多清理 1000 条,避免阻塞事件循环
|
|
254
|
+
- 读取时检查过期状态,过期则删除
|
|
255
|
+
|
|
256
|
+
### 容量配置
|
|
143
257
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
258
|
+
- 默认最大容量:100,000 条
|
|
259
|
+
- 达到容量上限时自动 LRU 淘汰
|
|
260
|
+
- 可通过构造函数自定义
|
|
261
|
+
|
|
262
|
+
## 使用场景
|
|
263
|
+
|
|
264
|
+
### 1. 接口限流
|
|
265
|
+
|
|
266
|
+
```javascript
|
|
267
|
+
import { cache } from 'chanjs';
|
|
268
|
+
|
|
269
|
+
function rateLimitMiddleware(req, res, next) {
|
|
270
|
+
const ip = req.ip;
|
|
271
|
+
const key = `rate:${ip}`;
|
|
272
|
+
const count = cache.incr(key, 60000); // 60 秒窗口
|
|
273
|
+
|
|
274
|
+
if (count > 100) {
|
|
275
|
+
return res.status(429).json({
|
|
276
|
+
success: false,
|
|
277
|
+
code: 1009,
|
|
278
|
+
msg: '请求过于频繁'
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
next();
|
|
283
|
+
}
|
|
147
284
|
```
|
|
148
285
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
286
|
+
### 2. 会话缓存
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
// 存储用户会话
|
|
290
|
+
cache.set(`session:${userId}`, {
|
|
291
|
+
userId,
|
|
292
|
+
loginTime: Date.now(),
|
|
293
|
+
role: 'admin'
|
|
294
|
+
}, 3600000); // 1 小时
|
|
295
|
+
|
|
296
|
+
// 读取会话
|
|
297
|
+
const session = cache.get(`session:${userId}`);
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 3. 数据缓存
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
// 缓存数据库查询结果
|
|
304
|
+
async function getUserWithCache(userId) {
|
|
305
|
+
const key = `user:${userId}`;
|
|
306
|
+
let user = cache.get(key);
|
|
307
|
+
|
|
308
|
+
if (!user) {
|
|
309
|
+
user = await db('users').where({ id: userId }).first();
|
|
310
|
+
if (user) {
|
|
311
|
+
cache.set(key, user, 300000); // 缓存 5 分钟
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return user;
|
|
316
|
+
}
|
|
317
|
+
```
|
|
155
318
|
|
|
156
319
|
## 注意事项
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
320
|
+
|
|
321
|
+
1. **内存占用**:缓存存储在内存中,应用重启后数据丢失
|
|
322
|
+
2. **容量限制**:默认 10w 条目,超限自动 LRU 淘汰
|
|
323
|
+
3. **过期精度**:惰性清理,过期时间可能有几秒误差
|
|
324
|
+
4. **并发安全**:单线程环境,无需考虑并发问题
|
|
325
|
+
5. **适用场景**:限流计数、临时缓存、会话存储等短 TTL 数据
|
|
326
|
+
6. **不适用**:持久化存储、跨进程共享、大数据量存储
|
|
327
|
+
|
|
328
|
+
## 与 Store 的关系
|
|
329
|
+
|
|
330
|
+
- `Cache` 是底层内存缓存实现
|
|
331
|
+
- `Store` 是统一存储适配层,封装了 `Cache` 和 Redis
|
|
332
|
+
- 业务层推荐使用 `Store`,自动切换内存/Redis
|
|
333
|
+
- 仅在使用纯内存场景时直接使用 `Cache`
|