whistle.mockbubu 2.0.0 → 2.1.0
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 +38 -0
- package/index.js +3 -3
- package/lib/config/const.js +138 -0
- package/lib/config/rule-collector.js +81 -0
- package/lib/constants.js +62 -0
- package/lib/core/memory-buffer/index.js +207 -0
- package/lib/core/memory-buffer/shared-instance.js +15 -0
- package/lib/core/plugin-mode-manager.js +74 -0
- package/lib/core/resRulesServer.js +14 -0
- package/lib/core/rulesServer.js +31 -0
- package/lib/core/server-entry/capture-handler.js +191 -0
- package/lib/core/server-entry/request-interceptor.js +82 -0
- package/lib/core/server-entry/response-handler.js +147 -0
- package/lib/core/server-entry/server.js +230 -0
- package/lib/storage/group-manager.js +627 -0
- package/lib/storage/storage-adapter.js +712 -0
- package/lib/storage/storage-v3.js +1418 -0
- package/lib/uiServer/index.js +61 -24
- package/lib/uiServer/router/export/import-export-router.js +459 -0
- package/lib/uiServer/router/files/api-list-router.js +150 -0
- package/lib/uiServer/router/files/batch-operations-router.js +185 -0
- package/lib/uiServer/router/files/file-config-router.js +118 -0
- package/lib/uiServer/router/files/file-crud-router.js +212 -0
- package/lib/uiServer/router/files/file-save-router.js +146 -0
- package/lib/uiServer/router/files/version-router.js +260 -0
- package/lib/uiServer/router/global/plugin-control.js +135 -0
- package/lib/uiServer/router/global/system-info-router.js +386 -0
- package/lib/uiServer/router/{group-router.js → groups/group-router.js} +21 -20
- package/lib/uiServer/router/index.js +38 -1521
- package/lib/uiServer/utils/router-helpers.js +100 -0
- package/lib/uiServer/utils/util.js +172 -0
- package/lib/uiServer/{validator.js → utils/validator.js} +11 -6
- package/lib/utils/archive-utils.js +788 -0
- package/lib/utils/error-handler.js +173 -0
- package/lib/utils/logger.js +79 -0
- package/lib/utils/path-utils.js +147 -0
- package/lib/utils/performance.js +265 -0
- package/lib/utils/utils.js +541 -0
- package/package.json +2 -2
- package/public/js/app.js +3707 -1922
- package/public/js/app.js.map +1 -1
- package/public/js/chunk-vendors.js +5098 -3965
- package/public/js/chunk-vendors.js.map +1 -1
- package/rules.txt +1 -1
- package/CHANGELOG_GROUP_FEATURE.md +0 -468
- package/CHANGELOG_P0_FIXES.md +0 -412
- package/CHANGELOG_P1_OPTIMIZATIONS.md +0 -292
- package/CLAUDE.md +0 -436
- package/GROUP_FEATURE_DESIGN.md +0 -520
- package/lib/const.js +0 -47
- package/lib/group-manager.js +0 -491
- package/lib/resRulesServer.js +0 -9
- package/lib/server.js +0 -249
- package/lib/uiServer/router/version-router.js +0 -205
- package/lib/uiServer/util.js +0 -153
- package/lib/utils.js +0 -409
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文件名: system-info-router.js
|
|
3
|
+
* 功能: 系统信息路由(存储统计、规则信息、内存监控)
|
|
4
|
+
* 依赖: util.js, fs, path, child_process
|
|
5
|
+
*
|
|
6
|
+
* 职责:
|
|
7
|
+
* - 存储统计(文件数量、磁盘占用)
|
|
8
|
+
* - 生效规则列表查询
|
|
9
|
+
* - 内存使用监控(堆内存、GC统计)
|
|
10
|
+
*
|
|
11
|
+
* 路由:
|
|
12
|
+
* - GET /cgi-bin/mockbubu/storage-stats - 存储统计
|
|
13
|
+
* - GET /cgi-bin/mockbubu/active-rules - 生效规则列表
|
|
14
|
+
* - GET /cgi-bin/mockbubu/memory-stats - 内存统计
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
createErrorResponse,
|
|
19
|
+
createSuccessResponse,
|
|
20
|
+
} = require('../../utils/util')
|
|
21
|
+
const fs = require('fs').promises
|
|
22
|
+
const path = require('path')
|
|
23
|
+
const ruleCollector = require('../../../config/rule-collector')
|
|
24
|
+
|
|
25
|
+
module.exports = (router) => {
|
|
26
|
+
/**
|
|
27
|
+
* 存储统计信息
|
|
28
|
+
*
|
|
29
|
+
* 功能:
|
|
30
|
+
* - 统计所有组的文件数量
|
|
31
|
+
* - 统计 mock 状态、锁定状态
|
|
32
|
+
* - 统计版本数量
|
|
33
|
+
* - 计算磁盘占用(groups, backup, recycle_bin, tmp)
|
|
34
|
+
*
|
|
35
|
+
* 响应:
|
|
36
|
+
* ```javascript
|
|
37
|
+
* {
|
|
38
|
+
* code: 0,
|
|
39
|
+
* data: {
|
|
40
|
+
* // 文件统计
|
|
41
|
+
* totalFiles: 100,
|
|
42
|
+
* mockEnabled: 30,
|
|
43
|
+
* mockDisabled: 70,
|
|
44
|
+
* locked: 5,
|
|
45
|
+
* totalVersions: 50,
|
|
46
|
+
*
|
|
47
|
+
* // 磁盘使用(字节)
|
|
48
|
+
* diskUsage: {
|
|
49
|
+
* total: 10485760,
|
|
50
|
+
* groups: 8388608,
|
|
51
|
+
* backup: 1048576,
|
|
52
|
+
* recycleBin: 1048576,
|
|
53
|
+
* tmp: 0
|
|
54
|
+
* },
|
|
55
|
+
*
|
|
56
|
+
* // 组详情
|
|
57
|
+
* groups: [
|
|
58
|
+
* {
|
|
59
|
+
* id: 'default',
|
|
60
|
+
* name: '默认组',
|
|
61
|
+
* mockEnabled: 30,
|
|
62
|
+
* locked: 5
|
|
63
|
+
* }
|
|
64
|
+
* ],
|
|
65
|
+
*
|
|
66
|
+
* // 元信息
|
|
67
|
+
* timestamp: 1762891525570,
|
|
68
|
+
* baseDir: '/path/to/.whistle/...'
|
|
69
|
+
* },
|
|
70
|
+
* msg: 'success'
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
router.get('/cgi-bin/mockbubu/storage-stats', async (ctx) => {
|
|
75
|
+
const timestamp = new Date().toLocaleString('zh-CN', { hour12: false })
|
|
76
|
+
console.log(`[mockbubu ${timestamp}] 开始统计存储信息`)
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const { storageAdapter } = ctx
|
|
80
|
+
const v3Storage = storageAdapter.getV3Storage()
|
|
81
|
+
|
|
82
|
+
// 1. 获取所有组
|
|
83
|
+
const groups = await v3Storage.listGroups()
|
|
84
|
+
console.log(`[mockbubu ${timestamp}] 组数量: ${groups.length}`)
|
|
85
|
+
|
|
86
|
+
// 2. 统计文件数据
|
|
87
|
+
let totalFiles = 0
|
|
88
|
+
let mockEnabled = 0
|
|
89
|
+
let mockDisabled = 0
|
|
90
|
+
let locked = 0
|
|
91
|
+
let totalVersions = 0
|
|
92
|
+
|
|
93
|
+
const groupsData = []
|
|
94
|
+
|
|
95
|
+
for (const group of groups) {
|
|
96
|
+
const fileIndexData = await v3Storage.getIndex(group.id)
|
|
97
|
+
totalFiles += fileIndexData.files.length
|
|
98
|
+
|
|
99
|
+
let groupMockEnabled = 0
|
|
100
|
+
let groupLocked = 0
|
|
101
|
+
|
|
102
|
+
// 统计每个文件的状态和版本数
|
|
103
|
+
for (const fileEntry of fileIndexData.files) {
|
|
104
|
+
// 从索引中读取配置信息(V3 架构已包含)
|
|
105
|
+
if (fileEntry.config) {
|
|
106
|
+
if (fileEntry.config.mock) {
|
|
107
|
+
mockEnabled++
|
|
108
|
+
groupMockEnabled++
|
|
109
|
+
} else {
|
|
110
|
+
mockDisabled++
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (fileEntry.config.locked) {
|
|
114
|
+
locked++
|
|
115
|
+
groupLocked++
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
mockDisabled++
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 统计版本数(从索引中的 versionCount)
|
|
122
|
+
totalVersions += fileEntry.versionCount || 0
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
groupsData.push({
|
|
126
|
+
id: group.id,
|
|
127
|
+
name: group.name,
|
|
128
|
+
description: group.description,
|
|
129
|
+
mockEnabled: groupMockEnabled,
|
|
130
|
+
locked: groupLocked,
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 3. 计算目录大小(包括 groups, .backup, .recycle_bin, .tmp)
|
|
135
|
+
const { exec } = require('child_process')
|
|
136
|
+
const { promisify } = require('util')
|
|
137
|
+
const execAsync = promisify(exec)
|
|
138
|
+
|
|
139
|
+
const getDirectorySize = async (dirPath) => {
|
|
140
|
+
try {
|
|
141
|
+
await fs.access(dirPath)
|
|
142
|
+
const { stdout, stderr } = await execAsync(`du -sk "${dirPath}"`)
|
|
143
|
+
if (stderr) {
|
|
144
|
+
console.error(`[mockbubu ${timestamp}] du stderr: ${stderr}`)
|
|
145
|
+
}
|
|
146
|
+
const sizeKB = parseInt(stdout.trim().split(/\s+/)[0])
|
|
147
|
+
const sizeBytes = sizeKB * 1024
|
|
148
|
+
console.log(`[mockbubu ${timestamp}] 目录大小: ${path.basename(dirPath)} => ${sizeKB} KB (${(sizeBytes / 1024 / 1024).toFixed(2)} MB)`)
|
|
149
|
+
return sizeBytes // 转换为字节
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error(`[mockbubu ${timestamp}] 获取目录大小失败: ${dirPath}`, error.message)
|
|
152
|
+
return 0
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const baseDir = v3Storage.baseDir
|
|
157
|
+
console.log(`[mockbubu ${timestamp}] baseDir: ${baseDir}`)
|
|
158
|
+
|
|
159
|
+
const [groupsSize, backupSize, recycleBinSize, tmpSize] = await Promise.all([
|
|
160
|
+
getDirectorySize(path.join(baseDir, 'groups')),
|
|
161
|
+
getDirectorySize(path.join(baseDir, '.backup')),
|
|
162
|
+
getDirectorySize(path.join(baseDir, '.recycle_bin')),
|
|
163
|
+
getDirectorySize(path.join(baseDir, '.tmp')),
|
|
164
|
+
])
|
|
165
|
+
|
|
166
|
+
const totalDiskUsage = groupsSize + backupSize + recycleBinSize + tmpSize
|
|
167
|
+
|
|
168
|
+
console.log(`[mockbubu ${timestamp}] 统计完成:`, {
|
|
169
|
+
totalFiles,
|
|
170
|
+
mockEnabled,
|
|
171
|
+
locked,
|
|
172
|
+
totalVersions,
|
|
173
|
+
totalDiskUsage: (totalDiskUsage / 1024 / 1024).toFixed(2) + ' MB',
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
// 4. 返回统计数据
|
|
177
|
+
ctx.body = createSuccessResponse({
|
|
178
|
+
// 文件统计
|
|
179
|
+
totalFiles,
|
|
180
|
+
mockEnabled,
|
|
181
|
+
mockDisabled,
|
|
182
|
+
locked,
|
|
183
|
+
totalVersions,
|
|
184
|
+
|
|
185
|
+
// 磁盘使用统计
|
|
186
|
+
diskUsage: {
|
|
187
|
+
total: totalDiskUsage,
|
|
188
|
+
groups: groupsSize,
|
|
189
|
+
backup: backupSize,
|
|
190
|
+
recycleBin: recycleBinSize,
|
|
191
|
+
tmp: tmpSize,
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
// 组详情
|
|
195
|
+
groups: groupsData,
|
|
196
|
+
|
|
197
|
+
// 元信息
|
|
198
|
+
timestamp: Date.now(),
|
|
199
|
+
baseDir,
|
|
200
|
+
})
|
|
201
|
+
} catch (error) {
|
|
202
|
+
const timestampError = new Date().toLocaleString('zh-CN', { hour12: false })
|
|
203
|
+
console.error(`[mockbubu ${timestampError}] 存储统计失败:`, error)
|
|
204
|
+
ctx.body = createErrorResponse(`存储统计失败: ${error.message}`)
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 获取生效的 Whistle 规则列表
|
|
210
|
+
*
|
|
211
|
+
* 功能:
|
|
212
|
+
* - 获取当前会话中生效的 mockbubu 规则
|
|
213
|
+
* - 规则由 server.js 在捕获请求时记录
|
|
214
|
+
* - 用于帮助用户调试 Whistle 规则配置
|
|
215
|
+
*
|
|
216
|
+
* 响应:
|
|
217
|
+
* ```javascript
|
|
218
|
+
* {
|
|
219
|
+
* code: 0,
|
|
220
|
+
* data: {
|
|
221
|
+
* rules: [
|
|
222
|
+
* '*.example.com mockbubu://pathname',
|
|
223
|
+
* 'https://api.test.com mockbubu://href'
|
|
224
|
+
* ],
|
|
225
|
+
* count: 2,
|
|
226
|
+
* message: '检测到 2 条生效的规则'
|
|
227
|
+
* },
|
|
228
|
+
* msg: 'success'
|
|
229
|
+
* }
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* 注意:
|
|
233
|
+
* - 规则列表会在一定时间后自动过期(10秒)
|
|
234
|
+
* - 如果没有规则,提示用户检查 Whistle 配置
|
|
235
|
+
*/
|
|
236
|
+
router.get('/cgi-bin/mockbubu/active-rules', async (ctx) => {
|
|
237
|
+
try {
|
|
238
|
+
const rules = ruleCollector.getRules()
|
|
239
|
+
const count = ruleCollector.getCount()
|
|
240
|
+
|
|
241
|
+
ctx.body = createSuccessResponse({
|
|
242
|
+
rules,
|
|
243
|
+
count,
|
|
244
|
+
message: count > 0
|
|
245
|
+
? `检测到 ${count} 条生效的规则`
|
|
246
|
+
: '尚未检测到生效的规则,请确保 Whistle 规则已配置并有请求触发',
|
|
247
|
+
})
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.error('[mockbubu] 获取规则列表失败:', error)
|
|
250
|
+
ctx.body = createErrorResponse(`获取规则列表失败: ${error.message}`)
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 内存使用统计
|
|
256
|
+
*
|
|
257
|
+
* 功能:
|
|
258
|
+
* - 监控 Node.js 进程内存使用
|
|
259
|
+
* - 统计堆内存(Heap)使用情况
|
|
260
|
+
* - 统计新生代(New Space)和老生代(Old Space)
|
|
261
|
+
* - 提供 GC 相关统计信息
|
|
262
|
+
*
|
|
263
|
+
* 响应:
|
|
264
|
+
* ```javascript
|
|
265
|
+
* {
|
|
266
|
+
* code: 0,
|
|
267
|
+
* data: {
|
|
268
|
+
* // 总体堆内存(单位:MB)
|
|
269
|
+
* heap: {
|
|
270
|
+
* used: '50.00',
|
|
271
|
+
* total: '100.00',
|
|
272
|
+
* limit: '1024.00',
|
|
273
|
+
* usagePercent: '4.88'
|
|
274
|
+
* },
|
|
275
|
+
*
|
|
276
|
+
* // New Space(新生代,存放新对象)
|
|
277
|
+
* newSpace: {
|
|
278
|
+
* size: '10.00',
|
|
279
|
+
* used: '5.00',
|
|
280
|
+
* usagePercent: '50.00',
|
|
281
|
+
* available: '5.00',
|
|
282
|
+
* physical: '10.00'
|
|
283
|
+
* },
|
|
284
|
+
*
|
|
285
|
+
* // Old Space(老生代,存放长期对象)
|
|
286
|
+
* oldSpace: {
|
|
287
|
+
* size: '90.00',
|
|
288
|
+
* used: '45.00',
|
|
289
|
+
* usagePercent: '50.00',
|
|
290
|
+
* available: '45.00',
|
|
291
|
+
* physical: '90.00'
|
|
292
|
+
* },
|
|
293
|
+
*
|
|
294
|
+
* // 进程总内存
|
|
295
|
+
* process: {
|
|
296
|
+
* rss: '120.00', // 常驻内存
|
|
297
|
+
* heapUsed: '50.00', // 已用堆内存
|
|
298
|
+
* heapTotal: '100.00', // 总堆内存
|
|
299
|
+
* external: '2.00', // C++ 对象内存
|
|
300
|
+
* arrayBuffers: '1.00' // ArrayBuffer 内存
|
|
301
|
+
* },
|
|
302
|
+
*
|
|
303
|
+
* // GC 统计
|
|
304
|
+
* gc: {
|
|
305
|
+
* mallocedMemory: '55.00',
|
|
306
|
+
* peakMalloced: '60.00',
|
|
307
|
+
* nativeContexts: 5,
|
|
308
|
+
* detachedContexts: 0
|
|
309
|
+
* },
|
|
310
|
+
*
|
|
311
|
+
* timestamp: '2025-12-02T10:00:00.000Z',
|
|
312
|
+
* pid: 12345
|
|
313
|
+
* },
|
|
314
|
+
* msg: '内存统计数据获取成功'
|
|
315
|
+
* }
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
router.get('/cgi-bin/mockbubu/memory-stats', async (ctx) => {
|
|
319
|
+
try {
|
|
320
|
+
const v8 = require('v8')
|
|
321
|
+
const memoryUsage = process.memoryUsage()
|
|
322
|
+
const heapStats = v8.getHeapStatistics()
|
|
323
|
+
const heapSpaces = v8.getHeapSpaceStatistics()
|
|
324
|
+
|
|
325
|
+
// 格式化字节为 MB
|
|
326
|
+
const formatMB = (bytes) => (bytes / 1024 / 1024).toFixed(2)
|
|
327
|
+
|
|
328
|
+
// New Space 和 Old Space
|
|
329
|
+
const newSpace = heapSpaces.find(space => space.space_name === 'new_space')
|
|
330
|
+
const oldSpace = heapSpaces.find(space => space.space_name === 'old_space')
|
|
331
|
+
|
|
332
|
+
// 计算使用率
|
|
333
|
+
const heapUsagePercent = ((heapStats.used_heap_size / heapStats.heap_size_limit) * 100).toFixed(2)
|
|
334
|
+
|
|
335
|
+
ctx.body = createSuccessResponse({
|
|
336
|
+
// 总体堆内存
|
|
337
|
+
heap: {
|
|
338
|
+
used: formatMB(heapStats.used_heap_size),
|
|
339
|
+
total: formatMB(heapStats.total_heap_size),
|
|
340
|
+
limit: formatMB(heapStats.heap_size_limit),
|
|
341
|
+
usagePercent: heapUsagePercent,
|
|
342
|
+
},
|
|
343
|
+
// New Space (Young Generation)
|
|
344
|
+
newSpace: newSpace
|
|
345
|
+
? {
|
|
346
|
+
size: formatMB(newSpace.space_size),
|
|
347
|
+
used: formatMB(newSpace.space_used_size),
|
|
348
|
+
usagePercent: ((newSpace.space_used_size / newSpace.space_size) * 100).toFixed(2),
|
|
349
|
+
available: formatMB(newSpace.space_available_size),
|
|
350
|
+
physical: formatMB(newSpace.physical_space_size),
|
|
351
|
+
}
|
|
352
|
+
: null,
|
|
353
|
+
// Old Space (Old Generation)
|
|
354
|
+
oldSpace: oldSpace
|
|
355
|
+
? {
|
|
356
|
+
size: formatMB(oldSpace.space_size),
|
|
357
|
+
used: formatMB(oldSpace.space_used_size),
|
|
358
|
+
usagePercent: ((oldSpace.space_used_size / oldSpace.space_size) * 100).toFixed(2),
|
|
359
|
+
available: formatMB(oldSpace.space_available_size),
|
|
360
|
+
physical: formatMB(oldSpace.physical_space_size),
|
|
361
|
+
}
|
|
362
|
+
: null,
|
|
363
|
+
// 进程总内存
|
|
364
|
+
process: {
|
|
365
|
+
rss: formatMB(memoryUsage.rss),
|
|
366
|
+
heapUsed: formatMB(memoryUsage.heapUsed),
|
|
367
|
+
heapTotal: formatMB(memoryUsage.heapTotal),
|
|
368
|
+
external: formatMB(memoryUsage.external),
|
|
369
|
+
arrayBuffers: formatMB(memoryUsage.arrayBuffers),
|
|
370
|
+
},
|
|
371
|
+
// GC 统计
|
|
372
|
+
gc: {
|
|
373
|
+
mallocedMemory: formatMB(heapStats.malloced_memory),
|
|
374
|
+
peakMalloced: formatMB(heapStats.peak_malloced_memory),
|
|
375
|
+
nativeContexts: heapStats.number_of_native_contexts,
|
|
376
|
+
detachedContexts: heapStats.number_of_detached_contexts,
|
|
377
|
+
},
|
|
378
|
+
// 时间戳
|
|
379
|
+
timestamp: new Date().toISOString(),
|
|
380
|
+
pid: process.pid,
|
|
381
|
+
}, '内存统计数据获取成功')
|
|
382
|
+
} catch (error) {
|
|
383
|
+
ctx.body = createErrorResponse(error.message)
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
const {
|
|
2
2
|
createErrorResponse,
|
|
3
3
|
createSuccessResponse,
|
|
4
|
-
} = require('
|
|
4
|
+
} = require('../../utils/util')
|
|
5
5
|
const {
|
|
6
6
|
validate,
|
|
7
|
-
} = require('
|
|
7
|
+
} = require('../../utils/validator')
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* 组管理路由
|
|
11
11
|
*/
|
|
12
12
|
module.exports = (router) => {
|
|
13
13
|
// 获取组列表
|
|
14
|
-
router.post('/cgi-bin/mockbubu/groups/list', (ctx) => {
|
|
14
|
+
router.post('/cgi-bin/mockbubu/groups/list', async (ctx) => {
|
|
15
15
|
try {
|
|
16
16
|
const { groupManager } = ctx
|
|
17
|
-
const groups = groupManager.getGroups()
|
|
18
|
-
const currentGroupId = groupManager.getCurrentGroupId()
|
|
17
|
+
const groups = await groupManager.getGroups()
|
|
18
|
+
const currentGroupId = await groupManager.getCurrentGroupId()
|
|
19
19
|
|
|
20
20
|
ctx.body = createSuccessResponse({
|
|
21
21
|
groups,
|
|
@@ -27,14 +27,14 @@ module.exports = (router) => {
|
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
// 获取当前组
|
|
30
|
-
router.post('/cgi-bin/mockbubu/groups/current', (ctx) => {
|
|
30
|
+
router.post('/cgi-bin/mockbubu/groups/current', async (ctx) => {
|
|
31
31
|
try {
|
|
32
32
|
const { groupManager } = ctx
|
|
33
|
-
const currentGroup = groupManager.getCurrentGroup()
|
|
33
|
+
const currentGroup = await groupManager.getCurrentGroup()
|
|
34
34
|
|
|
35
35
|
ctx.body = createSuccessResponse({
|
|
36
36
|
currentGroup,
|
|
37
|
-
currentGroupId: groupManager.getCurrentGroupId(),
|
|
37
|
+
currentGroupId: await groupManager.getCurrentGroupId(),
|
|
38
38
|
})
|
|
39
39
|
} catch (error) {
|
|
40
40
|
ctx.body = createErrorResponse(error.message)
|
|
@@ -65,12 +65,12 @@ module.exports = (router) => {
|
|
|
65
65
|
}
|
|
66
66
|
return null
|
|
67
67
|
},
|
|
68
|
-
}), (ctx) => {
|
|
68
|
+
}), async (ctx) => {
|
|
69
69
|
try {
|
|
70
70
|
const { groupManager } = ctx
|
|
71
71
|
const { name, description, copyFromGroupId } = ctx.request.body
|
|
72
72
|
|
|
73
|
-
const newGroup = groupManager.createGroup({
|
|
73
|
+
const newGroup = await groupManager.createGroup({
|
|
74
74
|
name: name.trim(),
|
|
75
75
|
description: description ? description.trim() : '',
|
|
76
76
|
copyFromGroupId: copyFromGroupId || null,
|
|
@@ -107,12 +107,12 @@ module.exports = (router) => {
|
|
|
107
107
|
}
|
|
108
108
|
return null
|
|
109
109
|
},
|
|
110
|
-
}), (ctx) => {
|
|
110
|
+
}), async (ctx) => {
|
|
111
111
|
try {
|
|
112
112
|
const { groupManager } = ctx
|
|
113
113
|
const { groupId, name, description } = ctx.request.body
|
|
114
114
|
|
|
115
|
-
const updatedGroup = groupManager.updateGroup(groupId, {
|
|
115
|
+
const updatedGroup = await groupManager.updateGroup(groupId, {
|
|
116
116
|
name: name ? name.trim() : undefined,
|
|
117
117
|
description: description !== undefined ? description.trim() : undefined,
|
|
118
118
|
})
|
|
@@ -131,12 +131,13 @@ module.exports = (router) => {
|
|
|
131
131
|
}
|
|
132
132
|
return null
|
|
133
133
|
},
|
|
134
|
-
}), (ctx) => {
|
|
134
|
+
}), async (ctx) => {
|
|
135
135
|
try {
|
|
136
|
-
const { groupManager } = ctx
|
|
136
|
+
const { groupManager, memoryBuffer } = ctx
|
|
137
137
|
const { groupId } = ctx.request.body
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
// 删除组时清理内存缓冲区
|
|
140
|
+
await groupManager.deleteGroup(groupId, { memoryBuffer })
|
|
140
141
|
|
|
141
142
|
ctx.body = createSuccessResponse(null, '删除成功')
|
|
142
143
|
} catch (error) {
|
|
@@ -152,12 +153,12 @@ module.exports = (router) => {
|
|
|
152
153
|
}
|
|
153
154
|
return null
|
|
154
155
|
},
|
|
155
|
-
}), (ctx) => {
|
|
156
|
+
}), async (ctx) => {
|
|
156
157
|
try {
|
|
157
158
|
const { groupManager } = ctx
|
|
158
159
|
const { groupId } = ctx.request.body
|
|
159
160
|
|
|
160
|
-
const currentGroup = groupManager.setCurrentGroup(groupId)
|
|
161
|
+
const currentGroup = await groupManager.setCurrentGroup(groupId)
|
|
161
162
|
|
|
162
163
|
ctx.body = createSuccessResponse({
|
|
163
164
|
currentGroup,
|
|
@@ -191,20 +192,20 @@ module.exports = (router) => {
|
|
|
191
192
|
}
|
|
192
193
|
return null
|
|
193
194
|
},
|
|
194
|
-
}), (ctx) => {
|
|
195
|
+
}), async (ctx) => {
|
|
195
196
|
try {
|
|
196
197
|
const { groupManager } = ctx
|
|
197
198
|
const { sourceGroupId, name, description } = ctx.request.body
|
|
198
199
|
|
|
199
200
|
// 检查源组是否存在
|
|
200
|
-
const groups = groupManager.getGroups()
|
|
201
|
+
const groups = await groupManager.getGroups()
|
|
201
202
|
const sourceGroup = groups.find(g => g.id === sourceGroupId)
|
|
202
203
|
if (!sourceGroup) {
|
|
203
204
|
throw new Error(`源组不存在: ${sourceGroupId}`)
|
|
204
205
|
}
|
|
205
206
|
|
|
206
207
|
// 创建新组并复制配置
|
|
207
|
-
const newGroup = groupManager.createGroup({
|
|
208
|
+
const newGroup = await groupManager.createGroup({
|
|
208
209
|
name: name.trim(),
|
|
209
210
|
description: description ? description.trim() : '',
|
|
210
211
|
copyFromGroupId: sourceGroupId,
|