whistle.mockbubu 1.0.0-dev.4 → 2.0.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/lib/utils.js CHANGED
@@ -28,7 +28,7 @@ const removePropertyAttr = (storage, property, attrName) => {
28
28
  const getPropertyAttr = (storage, property, attrName) => {
29
29
  const props = storage.getProperty(property)
30
30
 
31
- return props[attrName]
31
+ return props ? props[attrName] : undefined
32
32
  }
33
33
  const getProperty = (storage, property) => {
34
34
  return storage.getProperty(property)
@@ -37,7 +37,7 @@ const removeProperty = (storage, property) => {
37
37
  return storage.removeProperty(property)
38
38
  }
39
39
 
40
- const writeFile = ({ storage, filename, body, properties, encoding }) => {
40
+ const writeFile = ({ storage, filename, body, properties, encoding, groupId }) => {
41
41
  switch (encoding) {
42
42
  case 'gzip':
43
43
  body = zlib.gunzipSync(body)
@@ -68,9 +68,11 @@ const writeFile = ({ storage, filename, body, properties, encoding }) => {
68
68
  default:
69
69
  content = body
70
70
  }
71
- storage.writeFile(filename, content)
71
+
72
+ // 使用组目录结构: groupId/filename
73
+ const filePath = groupId ? `${groupId}/${filename}` : filename
74
+ storage.writeFile(filePath, content)
72
75
  setApiListUpdated(storage, true)
73
- console.log('%c [ content ]-58', 'font-size:13px; background:pink; color:#bf2c9f;', content)
74
76
  // switch (type) {
75
77
  // case '[object String]':
76
78
  // storage.writeFile(filename, body)
@@ -86,38 +88,61 @@ const writeFile = ({ storage, filename, body, properties, encoding }) => {
86
88
  // }
87
89
  }
88
90
 
91
+ // ⚠️ 临时保留:为向后兼容暂时保留(将在 Phase 2 完成后移除)
89
92
  const getApiList = (storage) => {
90
93
  return storage.getFileList()
91
94
  }
92
95
 
93
- const updateFile = (storage, filename, body) => {
96
+ // 新增:按组获取文件列表
97
+ const getGroupFileList = (storage, groupId) => {
98
+ const allFiles = storage.getFileList()
99
+ const prefix = `${groupId}/`
100
+ return allFiles
101
+ .filter(item => item.name.startsWith(prefix))
102
+ .map(item => ({
103
+ ...item,
104
+ name: item.name.replace(prefix, ''), // 移除前缀,返回原始文件名
105
+ }))
106
+ }
107
+
108
+ const updateFile = (storage, filename, body, groupId) => {
94
109
  if (!filename) {
95
110
  throw new Error('文件名不能为空')
96
111
  }
97
- // storage.writeFile(filename, JSON.stringify(body))
98
112
 
99
- const sessionCache = storage.readFile(filename)
113
+ const filePath = groupId ? `${groupId}/${filename}` : filename
114
+ const sessionCache = storage.readFile(filePath)
100
115
  if (sessionCache) {
101
116
  const session = JSON.parse(sessionCache)
102
117
  session.res.body = JSON.stringify(body)
103
- storage.writeFile(filename, JSON.stringify(session))
118
+ storage.writeFile(filePath, JSON.stringify(session))
104
119
  }
105
120
  }
106
121
 
107
- const readFile = (storage, filename) => {
108
- // return storage.readFile(filename)
109
-
110
- const sessionCache = storage.readFile(filename)
122
+ const readFile = (storage, filename, groupId) => {
123
+ const filePath = groupId ? `${groupId}/${filename}` : filename
124
+ const sessionCache = storage.readFile(filePath)
111
125
  if (sessionCache) {
112
126
  const resCache = JSON.parse(sessionCache)?.res
113
- console.log(resCache)
114
127
  return resCache.body
115
128
  }
116
129
  }
117
130
 
118
- const removeFile = (storage, name) => {
119
- storage.removeFile(name)
120
- removeProperty(storage, name)
131
+ // 读取完整的 session 数据(包含 req res)
132
+ const readSession = (storage, filename, groupId) => {
133
+ const filePath = groupId ? `${groupId}/${filename}` : filename
134
+ const sessionCache = storage.readFile(filePath)
135
+ if (sessionCache) {
136
+ return JSON.parse(sessionCache)
137
+ }
138
+ return null
139
+ }
140
+
141
+ const removeFile = (storage, name, groupId) => {
142
+ const filePath = groupId ? `${groupId}/${name}` : name
143
+ console.log(`[mockbubu] ❌ removeFile 被调用,彻底删除文件: ${filePath}`)
144
+ storage.removeFile(filePath)
145
+ // 注意:不再删除 properties,因为元数据现在由 groupManager 管理
121
146
  }
122
147
  // 获取mock文件名
123
148
  const getFilename = (originalReq) => {
@@ -166,21 +191,52 @@ function getVersionName(name) {
166
191
  return 'version.' + name
167
192
  }
168
193
 
194
+ function getVersionMetaName(name) {
195
+ return 'versionMeta.' + name
196
+ }
197
+
198
+ const MAX_VERSION_COUNT = 10 // 最多保留10个版本
199
+
169
200
  /**
170
201
  * mock版本管理
171
202
  */
172
203
 
173
204
  // 新增版本
174
- const addNewVersion = ({ storage, filename, versionName, content }) => {
205
+ const addNewVersion = ({ storage, filename, versionName, content, description = '' }) => {
175
206
  const name = getVersionName(versionName)
207
+ const metaName = getVersionMetaName(versionName)
208
+
209
+ // 检查版本数量限制
210
+ const versions = getVersions({ storage, filename })
211
+ if (versions.length >= MAX_VERSION_COUNT) {
212
+ throw new Error(`版本数量已达上限(${MAX_VERSION_COUNT}个),请删除旧版本后再创建`)
213
+ }
176
214
 
177
- setProperty(storage, filename, { [name]: content })
215
+ // 保存版本内容和元数据
216
+ const now = Date.now()
217
+ setProperty(storage, filename, {
218
+ [name]: content,
219
+ [metaName]: {
220
+ description,
221
+ createTime: now,
222
+ updateTime: now,
223
+ },
224
+ })
178
225
  }
179
226
  // 更新版本文件内容
180
227
  const updateVersionContent = ({ storage, filename, versionName, content }) => {
181
228
  const name = getVersionName(versionName)
182
-
183
- setProperty(storage, filename, { [name]: content })
229
+ const metaName = getVersionMetaName(versionName)
230
+
231
+ // 更新内容和修改时间
232
+ const meta = getPropertyAttr(storage, filename, metaName) || {}
233
+ setProperty(storage, filename, {
234
+ [name]: content,
235
+ [metaName]: {
236
+ ...meta,
237
+ updateTime: Date.now(),
238
+ },
239
+ })
184
240
  }
185
241
  // 获取版本文件内容
186
242
  const getVersionContent = ({ storage, filename, versionName }) => {
@@ -191,32 +247,91 @@ const getVersionContent = ({ storage, filename, versionName }) => {
191
247
  // 删除版本
192
248
  const deleteVersion = ({ storage, filename, versionName }) => {
193
249
  const name = getVersionName(versionName)
250
+ const metaName = getVersionMetaName(versionName)
194
251
 
195
252
  removePropertyAttr(storage, filename, name)
253
+ removePropertyAttr(storage, filename, metaName)
196
254
  }
197
255
  // 更新版本名称
198
256
  const updateVersionName = ({ storage, filename, versionName, newVersion }) => {
199
- const file = getVersionContent(versionName)
257
+ const content = getVersionContent({ storage, filename, versionName })
258
+ const oldMetaName = getVersionMetaName(versionName)
259
+ const meta = getPropertyAttr(storage, filename, oldMetaName) || {}
200
260
 
201
- addNewVersion(storage, filename, { versionName: newVersion, file })
261
+ // 删除旧版本
202
262
  deleteVersion({ storage, filename, versionName })
263
+
264
+ // 创建新版本(保留元数据,但不增加版本数量限制检查)
265
+ const name = getVersionName(newVersion)
266
+ const metaName = getVersionMetaName(newVersion)
267
+ setProperty(storage, filename, {
268
+ [name]: content,
269
+ [metaName]: {
270
+ ...meta,
271
+ updateTime: Date.now(),
272
+ },
273
+ })
203
274
  }
275
+
276
+ // 更新版本元信息(名称和描述)
277
+ const updateVersionMeta = ({ storage, filename, versionName, newVersionName, description }) => {
278
+ const content = getVersionContent({ storage, filename, versionName })
279
+ if (!content) {
280
+ throw new Error('版本不存在')
281
+ }
282
+
283
+ const oldMetaName = getVersionMetaName(versionName)
284
+ const meta = getPropertyAttr(storage, filename, oldMetaName) || {}
285
+
286
+ // 如果版本名变了,删除旧版本
287
+ if (versionName !== newVersionName) {
288
+ deleteVersion({ storage, filename, versionName })
289
+ } else {
290
+ // 只删除旧的元数据
291
+ removePropertyAttr(storage, filename, oldMetaName)
292
+ }
293
+
294
+ // 保存新的版本和元数据
295
+ const newName = getVersionName(newVersionName)
296
+ const newMetaName = getVersionMetaName(newVersionName)
297
+ setProperty(storage, filename, {
298
+ [newName]: content,
299
+ [newMetaName]: {
300
+ ...meta,
301
+ description,
302
+ updateTime: Date.now(),
303
+ },
304
+ })
305
+ }
306
+
204
307
  const getVersions = ({ storage, filename }) => {
205
308
  const props = getProperty(storage, filename)
309
+ if (!props) {
310
+ return []
311
+ }
312
+
206
313
  const list = []
207
314
 
208
315
  Object.keys(props).forEach((key) => {
209
- const matchs = key.match(/^version\.{1}(.+)/)
316
+ const matchs = key.match(/^version\.(.+)/)
210
317
 
211
318
  if (matchs && matchs[1]) {
319
+ const versionName = matchs[1]
320
+ const metaName = getVersionMetaName(versionName)
321
+ const meta = props[metaName] || {}
322
+
212
323
  list.push({
213
- filename: matchs[1],
324
+ filename: versionName,
214
325
  content: props[key],
326
+ description: meta.description || '',
327
+ createTime: meta.createTime || 0,
328
+ updateTime: meta.updateTime || 0,
215
329
  })
216
330
  }
217
331
  })
218
332
 
219
- return list
333
+ // 按修改时间倒序排列(最新修改的在前)
334
+ return list.sort((a, b) => b.updateTime - a.updateTime)
220
335
  }
221
336
 
222
337
  const withTryCatch = (fn) => {
@@ -224,7 +339,11 @@ const withTryCatch = (fn) => {
224
339
  try {
225
340
  return await fn(...args)
226
341
  } catch (e) {
227
- console.error('全局捕获异常:', e)
342
+ // 仅在开发环境输出错误日志
343
+ if (process.env.NODE_ENV === 'development') {
344
+ console.error('[mockbubu] 全局捕获异常:', e)
345
+ }
346
+ throw e
228
347
  }
229
348
  }
230
349
  }
@@ -233,6 +352,7 @@ exports.addNewVersion = addNewVersion
233
352
  exports.updateVersionContent = updateVersionContent
234
353
  exports.deleteVersion = deleteVersion
235
354
  exports.updateVersionName = updateVersionName
355
+ exports.updateVersionMeta = updateVersionMeta
236
356
  exports.getVersions = getVersions
237
357
  exports.setProperty = setProperty
238
358
  exports.getProperty = getProperty
@@ -241,9 +361,11 @@ exports.getVersionContent = getVersionContent
241
361
  exports.removeProperty = removeProperty
242
362
  exports.removePropertyAttr = removePropertyAttr
243
363
  exports.writeFile = writeFile
244
- exports.getApiList = getApiList
364
+ exports.getApiList = getApiList // ⚠️ 临时保留用于向后兼容
365
+ exports.getGroupFileList = getGroupFileList // ✅ 新增:按组获取文件列表
245
366
  exports.updateFile = updateFile
246
367
  exports.readFile = readFile
368
+ exports.readSession = readSession
247
369
  exports.removeFile = removeFile
248
370
  exports.getFilename = getFilename
249
371
  exports.getApiListUpdated = getApiListUpdated
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whistle.mockbubu",
3
- "version": "1.0.0-dev.4",
3
+ "version": "2.0.0",
4
4
  "description": "mock response data",
5
5
  "scripts": {
6
6
  "lint": "eslint . --ext .js",