@cnbcool/cnb-cli 1.1.0 → 1.2.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.
Files changed (25) hide show
  1. package/package.json +4 -2
  2. package/skills/cnb-api/scripts/core/flat-options.json +8909 -0
  3. package/skills/cnb-api/scripts/core/help.json +704 -704
  4. package/skills/cnb-api/scripts/core/index.js +33 -455
  5. package/skills/cnb-api/scripts/core/key-mapping.json +538 -0
  6. package/skills/cnb-api/scripts/core/lib/execute-action.js +97 -0
  7. package/skills/cnb-api/scripts/core/lib/extra-help.js +20 -0
  8. package/skills/cnb-api/scripts/core/lib/flat-options-data.js +16 -0
  9. package/skills/cnb-api/scripts/core/lib/format-output.js +85 -0
  10. package/skills/cnb-api/scripts/core/lib/format-params.js +211 -0
  11. package/skills/cnb-api/scripts/core/lib/help-data.js +15 -0
  12. package/skills/cnb-api/scripts/core/lib/key-mapping-data.js +16 -0
  13. package/skills/cnb-api/scripts/core/lib/parsers.js +126 -0
  14. package/skills/cnb-api/scripts/core/lib/print-json.js +15 -0
  15. package/skills/cnb-api/scripts/core/lib/register-fallback.js +15 -0
  16. package/skills/cnb-api/scripts/core/lib/register-modules.js +91 -0
  17. package/skills/cnb-api/scripts/core/lib/summary-extractors.js +181 -0
  18. package/skills/cnb-api/scripts/core/lib/trim-summary.js +17 -0
  19. package/skills/cnb-api/scripts/core/shortcuts.js +10 -186
  20. package/skills/cnb-api/scripts/core/utils/build-nested-field-map.js +35 -0
  21. package/skills/cnb-api/scripts/core/utils/flat-key-from-segments.js +14 -0
  22. package/skills/cnb-api/scripts/core/utils/match-array-object-field.js +25 -0
  23. package/skills/cnb-api/scripts/core/utils/restore-original-keys.js +24 -0
  24. package/skills/cnb-api/scripts/core/utils/upload.js +107 -15
  25. package/skills/cnb-api/scripts/modules/knowledge-base/search-npc.js +5 -5
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.summarizeResponse = summarizeResponse;
7
+ /**
8
+ * 摘要输出
9
+ * 对返回数据量大的快捷命令,默认只输出核心字段,减少 token 消耗
10
+ */
11
+
12
+ /**
13
+ * 摘要提取器配置
14
+ * key: "module/tool",value: 摘要提取函数
15
+ * - 对象响应:直接对 data 应用提取函数
16
+ * - 数组响应:对 data 中每个元素应用提取函数
17
+ */
18
+ const SUMMARY_EXTRACTORS = {
19
+ // Issue 详情摘要:保留标题、状态、标签和正文
20
+ // 过滤: number, state_reason, assignees, author, created_at, updated_at 等
21
+ 'issues/get-issue': item => ({
22
+ title: item.title,
23
+ state: item.state,
24
+ labels: item.labels?.map?.(l => l.name).filter(Boolean) || [],
25
+ body: item.body
26
+ }),
27
+ // Issue 更新摘要:只保留状态变更结果
28
+ // 过滤: title, body, labels, assignees, author, created_at, updated_at 等
29
+ 'issues/update-issue': item => ({
30
+ number: item.number,
31
+ state: item.state,
32
+ state_reason: item.state_reason
33
+ }),
34
+ // Issue 评论列表摘要:只保留作者用户名、内容和创建时间
35
+ // 过滤: author 完整对象(avatar/email/freeze/is_npc/nickname), reactions, updated_at
36
+ 'issues/list-issue-comments': item => ({
37
+ id: item.id,
38
+ author: item.author?.username,
39
+ body: item.body,
40
+ created_at: item.created_at
41
+ }),
42
+ // Issue 发表评论摘要:只保留评论 ID 和创建时间(body 已在请求中传入,无需重复)
43
+ // 过滤: body(请求已传入), author 完整对象(avatar/email/freeze/is_npc/nickname/username), reactions, updated_at
44
+ 'issues/post-issue-comment': item => ({
45
+ id: item.id,
46
+ created_at: item.created_at
47
+ }),
48
+ // Issue 标签列表摘要:保留名称、颜色和描述
49
+ // 过滤: id
50
+ 'issues/list-issue-labels': item => ({
51
+ name: item.name,
52
+ color: item.color,
53
+ description: item.description
54
+ }),
55
+ // Issue 添加标签摘要:只保留 ID 和颜色(name 已在请求中传入,无需重复)
56
+ // 过滤: name(请求已传入), description
57
+ 'issues/post-issue-labels': item => ({
58
+ id: item.id,
59
+ color: item.color
60
+ }),
61
+ // Issue 处理人列表摘要:保留用户名和昵称
62
+ // 过滤: avatar, email, freeze, is_npc
63
+ 'issues/list-issue-assignees': item => ({
64
+ username: item.username,
65
+ nickname: item.nickname
66
+ }),
67
+ // Issue 添加处理人摘要:保留处理人用户名和昵称列表
68
+ // 过滤: assignees 中每个用户的 avatar/email/freeze/is_npc,以及 issue 其他字段
69
+ 'issues/post-issue-assignees': item => ({
70
+ number: item.number,
71
+ assignees: item.assignees?.map?.(a => ({
72
+ username: a.username,
73
+ nickname: a.nickname
74
+ })).filter(a => a.username) || []
75
+ }),
76
+ // PR 详情摘要:保留标题、状态、标签、正文和分支信息
77
+ // 过滤: number, author, assignees, reviewers, created_at, updated_at, base/head 完整对象等
78
+ 'pulls/get-pull': item => ({
79
+ title: item.title,
80
+ state: item.state,
81
+ labels: item.labels?.map?.(l => l.name).filter(Boolean) || [],
82
+ base: item.base?.ref,
83
+ head: item.head?.ref,
84
+ body: item.body
85
+ }),
86
+ // PR 文件列表摘要:保留文件名、sha、变更状态和增删行数
87
+ // 过滤: patch, blob_url, raw_url, contents_url, previous_filename
88
+ 'pulls/list-pull-files': item => ({
89
+ filename: item.filename,
90
+ sha: item.sha,
91
+ status: item.status,
92
+ additions: item.additions,
93
+ deletions: item.deletions
94
+ }),
95
+ // PR 提交列表摘要:只保留 sha 前 8 位和 commit message
96
+ // 过滤: sha 完整值, commit 完整对象(author/committer/tree/verification), parents, url 等
97
+ 'pulls/list-pull-commits': item => ({
98
+ sha: typeof item.sha === 'string' ? item.sha.substring(0, 8) : item.sha,
99
+ message: item.commit?.message
100
+ }),
101
+ // PR 评论列表摘要:保留作者用户名和昵称、内容和创建时间
102
+ // 过滤: author 完整对象(avatar/email/freeze/is_npc), reactions, updated_at
103
+ 'pulls/list-pull-comments': item => ({
104
+ id: item.id,
105
+ author: item.author?.username,
106
+ nickname: item.author?.nickname,
107
+ body: item.body,
108
+ created_at: item.created_at
109
+ }),
110
+ // PR 发表评论摘要:只保留评论 ID 和创建时间(body 已在请求中传入,无需重复)
111
+ // 过滤: body(请求已传入), author 完整对象(avatar/email/freeze/is_npc/nickname/username), reactions, updated_at
112
+ 'pulls/post-pull-comment': item => ({
113
+ id: item.id,
114
+ created_at: item.created_at
115
+ }),
116
+ // PR 标签列表摘要:保留 ID、名称、颜色和描述
117
+ // 过滤: 无
118
+ 'pulls/list-pull-labels': item => ({
119
+ id: item.id,
120
+ name: item.name,
121
+ color: item.color,
122
+ description: item.description
123
+ }),
124
+ // PR 添加标签摘要:只保留 ID 和颜色(name 已在请求中传入,无需重复)
125
+ // 过滤: name(请求已传入), description
126
+ 'pulls/post-pull-labels': item => ({
127
+ id: item.id,
128
+ color: item.color
129
+ }),
130
+ // PR CI 状态摘要:保留整体状态和各检查项的核心信息(sha 截断为前 8 位)
131
+ // 过滤: sha 完整值, statuses 中每项的 target_url/created_at/updated_at
132
+ 'pulls/list-pull-commit-statuses': item => ({
133
+ sha: typeof item.sha === 'string' ? item.sha.substring(0, 8) : item.sha,
134
+ state: item.state,
135
+ statuses: item.statuses?.map?.(s => ({
136
+ context: s.context,
137
+ state: s.state,
138
+ description: s.description
139
+ })) || []
140
+ }),
141
+ // PR 评审列表摘要:保留作者用户名和昵称、状态和内容
142
+ // 过滤: author 完整对象(avatar/email/freeze/is_npc), created_at, updated_at
143
+ 'pulls/list-pull-reviews': item => ({
144
+ id: item.id,
145
+ author: item.author?.username,
146
+ nickname: item.author?.nickname,
147
+ state: item.state,
148
+ body: item.body
149
+ }),
150
+ // PR 处理人列表摘要:保留用户名和昵称
151
+ // 过滤: avatar, email, freeze, is_npc
152
+ 'pulls/list-pull-assignees': item => ({
153
+ username: item.username,
154
+ nickname: item.nickname
155
+ }),
156
+ // PR 添加处理人摘要:保留处理人用户名和昵称列表
157
+ // 过滤: assignees 中每个用户的 avatar/email/freeze/is_npc,以及 PR 其他字段
158
+ 'pulls/post-pull-assignees': item => ({
159
+ number: item.number,
160
+ assignees: item.assignees?.map?.(a => ({
161
+ username: a.username,
162
+ nickname: a.nickname
163
+ })).filter(a => a.username) || []
164
+ })
165
+ };
166
+
167
+ /**
168
+ * 对响应数据应用摘要提取(如果当前 tool 配置了摘要提取器)
169
+ * @param data 原始 data(对象或数组)
170
+ * @param toolKey 当前 tool 标识,格式为 "module/tool"
171
+ * @returns 摘要后的 data,如果无匹配提取器则返回 null
172
+ */
173
+ function summarizeResponse(data, toolKey) {
174
+ const extractor = SUMMARY_EXTRACTORS[toolKey];
175
+ if (!extractor) return null;
176
+ if (data == null) return data;
177
+ if (Array.isArray(data)) {
178
+ return data.map(extractor);
179
+ }
180
+ return extractor(data);
181
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.trimSummary = trimSummary;
7
+ /**
8
+ * 去除 summary 中的英文部分(保留中文句号前的内容)
9
+ */
10
+ function trimSummary(summary) {
11
+ if (!summary) return '';
12
+ // 匹配中文句号"。"后面跟英文的模式,只保留中文部分
13
+ const match = summary.match(/^(.*?[\u4e00-\u9fff].*?)[。.]\s*[A-Z]/);
14
+ if (match) return match[1];
15
+ // 没有匹配到则返回原文
16
+ return summary;
17
+ }
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.detectEventContext = detectEventContext;
7
7
  exports.resolveShortcut = resolveShortcut;
8
8
  exports.showShort = showShort;
9
- exports.summarizeResponse = summarizeResponse;
10
9
  /**
11
10
  * 快捷命令模块
12
11
  *
@@ -53,7 +52,7 @@ const ISSUE_SHORTCUTS = [{
53
52
  shortName: 'comment',
54
53
  realTool: 'post-issue-comment',
55
54
  description: '评论',
56
- dataTip: "--data '{\"body\":\"内容\"}'"
55
+ dataTip: "--body 内容"
57
56
  }, {
58
57
  shortName: 'close',
59
58
  realTool: 'update-issue',
@@ -78,7 +77,7 @@ const ISSUE_SHORTCUTS = [{
78
77
  shortName: 'add-labels',
79
78
  realTool: 'post-issue-labels',
80
79
  description: '添加标签',
81
- dataTip: "--data '{\"labels\":[\"bug\",\"feature\"]}'"
80
+ dataTip: "--labels bug --labels feature"
82
81
  }, {
83
82
  shortName: 'list-assignees',
84
83
  realTool: 'list-issue-assignees',
@@ -87,19 +86,19 @@ const ISSUE_SHORTCUTS = [{
87
86
  shortName: 'add-assignees',
88
87
  realTool: 'post-issue-assignees',
89
88
  description: '添加处理人',
90
- dataTip: "--data '{\"assignees\":[\"username\"]}'"
89
+ dataTip: "--assignees username"
91
90
  }, {
92
91
  shortName: 'upload-file',
93
92
  realTool: 'post-issue-file-asset-upload-url',
94
93
  description: '上传文件',
95
94
  upload: true,
96
- dataTip: "--data '{\"file\":\"文件路径\"}'"
95
+ dataTip: "--file 文件路径"
97
96
  }, {
98
97
  shortName: 'upload-image',
99
98
  realTool: 'post-issue-image-asset-upload-url',
100
99
  description: '上传图片',
101
100
  upload: true,
102
- dataTip: "--data '{\"file\":\"图片路径\"}'"
101
+ dataTip: "--file 图片路径"
103
102
  }];
104
103
  const PR_SHORTCUTS = [{
105
104
  shortName: 'get',
@@ -121,7 +120,7 @@ const PR_SHORTCUTS = [{
121
120
  shortName: 'comment',
122
121
  realTool: 'post-pull-comment',
123
122
  description: '评论',
124
- dataTip: "--data '{\"body\":\"内容\"}'"
123
+ dataTip: "--body 内容"
125
124
  }, {
126
125
  shortName: 'list-labels',
127
126
  realTool: 'list-pull-labels',
@@ -130,7 +129,7 @@ const PR_SHORTCUTS = [{
130
129
  shortName: 'add-labels',
131
130
  realTool: 'post-pull-labels',
132
131
  description: '添加标签',
133
- dataTip: "--data '{\"labels\":[\"ready\",\"approved\"]}'"
132
+ dataTip: "--labels ready --labels approved"
134
133
  }, {
135
134
  shortName: 'check-status',
136
135
  realTool: 'list-pull-commit-statuses',
@@ -149,14 +148,14 @@ const PR_SHORTCUTS = [{
149
148
  description: '上传文件',
150
149
  repoOnly: true,
151
150
  upload: true,
152
- dataTip: "--data '{\"file\":\"文件路径\"}'"
151
+ dataTip: "--file 文件路径"
153
152
  }, {
154
153
  shortName: 'upload-image',
155
154
  realTool: 'upload-imgs',
156
155
  description: '上传图片',
157
156
  repoOnly: true,
158
157
  upload: true,
159
- dataTip: "--data '{\"file\":\"图片路径\"}'"
158
+ dataTip: "--file 图片路径"
160
159
  }];
161
160
 
162
161
  // ============================================================
@@ -234,7 +233,7 @@ ${prList}
234
233
  CNB_ISSUE_IID - Issue 编号(Issue 相关快捷命令)
235
234
  CNB_PULL_REQUEST_IID - PR 编号(PR 相关快捷命令)
236
235
 
237
- 默认只输出摘要信息,添加 --verbose 可输出全部信息
236
+ 默认只输出摘要信息,添加 --v 可输出全部信息
238
237
  `);
239
238
  }
240
239
  }
@@ -273,179 +272,4 @@ function resolveShortcut(moduleName, toolName) {
273
272
  autoData: matched.autoData || null,
274
273
  upload: !!matched.upload
275
274
  };
276
- }
277
-
278
- // ============================================================
279
- // 摘要输出
280
- // 对返回数据量大的快捷命令,默认只输出核心字段,减少 token 消耗
281
- // ============================================================
282
-
283
- /**
284
- * 摘要提取器配置
285
- * key: "module/tool",value: 摘要提取函数
286
- * - 对象响应:直接对 data 应用提取函数
287
- * - 数组响应:对 data 中每个元素应用提取函数
288
- */
289
- const SUMMARY_EXTRACTORS = {
290
- // Issue 详情摘要:保留标题、状态、标签和正文
291
- // 过滤: number, state_reason, assignees, author, created_at, updated_at 等
292
- 'issues/get-issue': item => ({
293
- title: item.title,
294
- state: item.state,
295
- labels: item.labels?.map?.(l => l.name).filter(Boolean) || [],
296
- body: item.body
297
- }),
298
- // Issue 更新摘要:只保留状态变更结果
299
- // 过滤: title, body, labels, assignees, author, created_at, updated_at 等
300
- 'issues/update-issue': item => ({
301
- number: item.number,
302
- state: item.state,
303
- state_reason: item.state_reason
304
- }),
305
- // Issue 评论列表摘要:只保留作者用户名、内容和创建时间
306
- // 过滤: author 完整对象(avatar/email/freeze/is_npc/nickname), reactions, updated_at
307
- 'issues/list-issue-comments': item => ({
308
- id: item.id,
309
- author: item.author?.username,
310
- body: item.body,
311
- created_at: item.created_at
312
- }),
313
- // Issue 发表评论摘要:只保留评论 ID 和创建时间(body 已在请求中传入,无需重复)
314
- // 过滤: body(请求已传入), author 完整对象(avatar/email/freeze/is_npc/nickname/username), reactions, updated_at
315
- 'issues/post-issue-comment': item => ({
316
- id: item.id,
317
- created_at: item.created_at
318
- }),
319
- // Issue 标签列表摘要:保留名称、颜色和描述
320
- // 过滤: id
321
- 'issues/list-issue-labels': item => ({
322
- name: item.name,
323
- color: item.color,
324
- description: item.description
325
- }),
326
- // Issue 添加标签摘要:只保留 ID 和颜色(name 已在请求中传入,无需重复)
327
- // 过滤: name(请求已传入), description
328
- 'issues/post-issue-labels': item => ({
329
- id: item.id,
330
- color: item.color
331
- }),
332
- // Issue 处理人列表摘要:保留用户名和昵称
333
- // 过滤: avatar, email, freeze, is_npc
334
- 'issues/list-issue-assignees': item => ({
335
- username: item.username,
336
- nickname: item.nickname
337
- }),
338
- // Issue 添加处理人摘要:保留处理人用户名和昵称列表
339
- // 过滤: assignees 中每个用户的 avatar/email/freeze/is_npc,以及 issue 其他字段
340
- 'issues/post-issue-assignees': item => ({
341
- number: item.number,
342
- assignees: item.assignees?.map?.(a => ({
343
- username: a.username,
344
- nickname: a.nickname
345
- })).filter(a => a.username) || []
346
- }),
347
- // PR 详情摘要:保留标题、状态、标签、正文和分支信息
348
- // 过滤: number, author, assignees, reviewers, created_at, updated_at, base/head 完整对象等
349
- 'pulls/get-pull': item => ({
350
- title: item.title,
351
- state: item.state,
352
- labels: item.labels?.map?.(l => l.name).filter(Boolean) || [],
353
- base: item.base?.ref,
354
- head: item.head?.ref,
355
- body: item.body
356
- }),
357
- // PR 文件列表摘要:保留文件名、sha、变更状态和增删行数
358
- // 过滤: patch, blob_url, raw_url, contents_url, previous_filename
359
- 'pulls/list-pull-files': item => ({
360
- filename: item.filename,
361
- sha: item.sha,
362
- status: item.status,
363
- additions: item.additions,
364
- deletions: item.deletions
365
- }),
366
- // PR 提交列表摘要:只保留 sha 前 8 位和 commit message
367
- // 过滤: sha 完整值, commit 完整对象(author/committer/tree/verification), parents, url 等
368
- 'pulls/list-pull-commits': item => ({
369
- sha: typeof item.sha === 'string' ? item.sha.substring(0, 8) : item.sha,
370
- message: item.commit?.message
371
- }),
372
- // PR 评论列表摘要:保留作者用户名和昵称、内容和创建时间
373
- // 过滤: author 完整对象(avatar/email/freeze/is_npc), reactions, updated_at
374
- 'pulls/list-pull-comments': item => ({
375
- id: item.id,
376
- author: item.author?.username,
377
- nickname: item.author?.nickname,
378
- body: item.body,
379
- created_at: item.created_at
380
- }),
381
- // PR 发表评论摘要:只保留评论 ID 和创建时间(body 已在请求中传入,无需重复)
382
- // 过滤: body(请求已传入), author 完整对象(avatar/email/freeze/is_npc/nickname/username), reactions, updated_at
383
- 'pulls/post-pull-comment': item => ({
384
- id: item.id,
385
- created_at: item.created_at
386
- }),
387
- // PR 标签列表摘要:保留 ID、名称、颜色和描述
388
- // 过滤: 无
389
- 'pulls/list-pull-labels': item => ({
390
- id: item.id,
391
- name: item.name,
392
- color: item.color,
393
- description: item.description
394
- }),
395
- // PR 添加标签摘要:只保留 ID 和颜色(name 已在请求中传入,无需重复)
396
- // 过滤: name(请求已传入), description
397
- 'pulls/post-pull-labels': item => ({
398
- id: item.id,
399
- color: item.color
400
- }),
401
- // PR CI 状态摘要:保留整体状态和各检查项的核心信息(sha 截断为前 8 位)
402
- // 过滤: sha 完整值, statuses 中每项的 target_url/created_at/updated_at
403
- 'pulls/list-pull-commit-statuses': item => ({
404
- sha: typeof item.sha === 'string' ? item.sha.substring(0, 8) : item.sha,
405
- state: item.state,
406
- statuses: item.statuses?.map?.(s => ({
407
- context: s.context,
408
- state: s.state,
409
- description: s.description
410
- })) || []
411
- }),
412
- // PR 评审列表摘要:保留作者用户名和昵称、状态和内容
413
- // 过滤: author 完整对象(avatar/email/freeze/is_npc), created_at, updated_at
414
- 'pulls/list-pull-reviews': item => ({
415
- id: item.id,
416
- author: item.author?.username,
417
- nickname: item.author?.nickname,
418
- state: item.state,
419
- body: item.body
420
- }),
421
- // PR 处理人列表摘要:保留用户名和昵称
422
- // 过滤: avatar, email, freeze, is_npc
423
- 'pulls/list-pull-assignees': item => ({
424
- username: item.username,
425
- nickname: item.nickname
426
- }),
427
- // PR 添加处理人摘要:保留处理人用户名和昵称列表
428
- // 过滤: assignees 中每个用户的 avatar/email/freeze/is_npc,以及 PR 其他字段
429
- 'pulls/post-pull-assignees': item => ({
430
- number: item.number,
431
- assignees: item.assignees?.map?.(a => ({
432
- username: a.username,
433
- nickname: a.nickname
434
- })).filter(a => a.username) || []
435
- })
436
- };
437
-
438
- /**
439
- * 对响应数据应用摘要提取(如果当前 tool 配置了摘要提取器)
440
- * @param data 原始 data(对象或数组)
441
- * @param toolKey 当前 tool 标识,格式为 "module/tool"
442
- * @returns 摘要后的 data,如果无匹配提取器则返回 null
443
- */
444
- function summarizeResponse(data, toolKey) {
445
- const extractor = SUMMARY_EXTRACTORS[toolKey];
446
- if (!extractor) return null;
447
- if (Array.isArray(data)) {
448
- return data.map(extractor);
449
- }
450
- return extractor(data);
451
275
  }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.buildNestedFieldMap = buildNestedFieldMap;
7
+ /**
8
+ * 递归遍历嵌套对象的 schema,生成所有叶子节点的 flat key 映射
9
+ * @param props 当前层级的 properties
10
+ * @param prefix 当前层级的 CLI flat key 前缀(用 @ 连接),如 "testBody"
11
+ * @param pathKeys 当前层级的 schema 路径数组,如 ["testBody"]
12
+ * @returns Map<flatKey, NestedFieldMapping>
13
+ */
14
+ function buildNestedFieldMap(props, prefix, pathKeys) {
15
+ const map = new Map();
16
+ for (const [subKey, subProp] of Object.entries(props)) {
17
+ const flatKey = `${prefix}@${subKey}`;
18
+ const currentPath = [...pathKeys, subKey];
19
+ if (subProp.type === 'object' && subProp.properties && Object.keys(subProp.properties).length > 0) {
20
+ // 嵌套对象:继续递归
21
+ const subMap = buildNestedFieldMap(subProp.properties, flatKey, currentPath);
22
+ for (const [k, v] of subMap) {
23
+ map.set(k, v);
24
+ }
25
+ } else {
26
+ // 叶子节点:注册 flat key
27
+ const camelKey = flatKey;
28
+ map.set(camelKey, {
29
+ pathKeys: currentPath,
30
+ leafSchema: subProp
31
+ });
32
+ }
33
+ }
34
+ return map;
35
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.flatKeyFromSegments = flatKeyFromSegments;
7
+ /**
8
+ * 生成 CLI flat key:按 '@' 连接层级
9
+ * 例如 "testBody@critical_count@id"
10
+ * Commander 不会对 '@' 做 camelCase 转换,所以 key 保持原样
11
+ */
12
+ function flatKeyFromSegments(str) {
13
+ return str;
14
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.matchArrayObjectField = matchArrayObjectField;
7
+ /**
8
+ * 检测是否为 array<object> 展开字段(格式:bodyArrayKey@subPropName)
9
+ * Commander 不会对 '@' 做 camelCase,所以直接匹配原始 key
10
+ */
11
+ function matchArrayObjectField(camelKey, bodyProps) {
12
+ for (const [rootKey, rootProp] of Object.entries(bodyProps)) {
13
+ if (rootProp.type !== 'array' || !rootProp.items?.properties) continue;
14
+ for (const subKey of Object.keys(rootProp.items.properties)) {
15
+ const flatKey = `${rootKey}@${subKey}`;
16
+ if (flatKey === camelKey) {
17
+ return {
18
+ arrayKey: rootKey,
19
+ subKey
20
+ };
21
+ }
22
+ }
23
+ }
24
+ return null;
25
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.restoreOriginalKeys = restoreOriginalKeys;
7
+ var _keyMappingData = require("../lib/key-mapping-data");
8
+ /**
9
+ * 将 CLI 传入的带 '-' 的参数名还原为原始的 '_' 或 '@' 参数名
10
+ * 通过 key-mapping.json 中的映射表进行查找还原
11
+ */
12
+ function restoreOriginalKeys(params) {
13
+ const moduleName = params.module;
14
+ const toolName = params.tool;
15
+ if (!moduleName || !toolName) return params;
16
+ const toolMapping = _keyMappingData.keyMappingData[moduleName]?.[toolName];
17
+ if (!toolMapping) return params;
18
+ const restored = {};
19
+ for (const [key, value] of Object.entries(params)) {
20
+ const originalKey = toolMapping[key];
21
+ restored[originalKey || key] = value;
22
+ }
23
+ return restored;
24
+ }