@cnbcool/cnb-cli 1.2.0 → 1.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnbcool/cnb-cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "CNB OpenAPI 命令行工具,基于 CNB 平台 Swagger 自动生成,支持 Issues、PR、Git、组织管理等全部 API 操作",
5
5
  "main": "skills/cnb-api/scripts/core/index.js",
6
6
  "bin": {
@@ -33,10 +33,10 @@
33
33
  },
34
34
  "author": "",
35
35
  "license": "MIT",
36
- "dependencies": {
37
- "@cnbcool/cnb-api-generate": "^2.1.0"
38
- },
39
36
  "devDependencies": {
40
37
  "skills": "^1.4.4"
38
+ },
39
+ "dependencies": {
40
+ "@cnbcool/cnb-api-generate": "^2.2.0"
41
41
  }
42
42
  }
@@ -27,10 +27,8 @@ function getToolParamDefs(moduleName, toolName) {
27
27
  * @returns 格式化后的参数对象,包含 module, tool, path, query, data 等
28
28
  */
29
29
  function formatParams(params) {
30
- console.log(JSON.stringify(params));
31
30
  // 先将 CLI 带 '-' 的参数名还原为原始 '_'/'@' 参数名
32
31
  params = (0, _restoreOriginalKeys.restoreOriginalKeys)(params);
33
- console.log(params);
34
32
  const formatted = {
35
33
  module: params.module,
36
34
  tool: params.tool
@@ -106,7 +104,15 @@ function formatParams(params) {
106
104
  } else if (bodyProps[key]) {
107
105
  // body 字段(无冲突,直接用原 key)
108
106
  if (!formatted.data) formatted.data = {};
109
- formatted.data[key] = Array.isArray(value) ? value : (0, _parsers.tryParseJSON)(value);
107
+ if (Array.isArray(value)) {
108
+ formatted.data[key] = value;
109
+ } else if (bodyProps[key].type === 'string') {
110
+ // schema 定义为 string 类型时,保持原始字符串,不做 JSON 解析
111
+ // 避免纯数字字符串(如 "123")被转为 number
112
+ formatted.data[key] = value;
113
+ } else {
114
+ formatted.data[key] = (0, _parsers.tryParseJSON)(value);
115
+ }
110
116
  } else {
111
117
  // 处理 d- 前缀(冲突时 CLI 以 d- 前缀传入)
112
118
  const stripped = key.startsWith('d-') || key.startsWith('d_') ? key.replace(/^d[-_]/, '') : key;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.printJSON = printJSON;
7
+ var _toon = require("@toon-format/toon");
7
8
  /**
8
9
  * 将数据转换为格式化的 JSON 字符串
9
10
  * @param data 要序列化的数据(可以是任意类型)缩进)
@@ -11,5 +12,13 @@ exports.printJSON = printJSON;
11
12
  * @returns 格式化的 JSON 字符串,如果序列化失败则返回错误信息的 JSON
12
13
  */
13
14
  function printJSON(data, verbose = false) {
14
- return verbose ? JSON.stringify(data, null, 2) : JSON.stringify(data);
15
+ if (verbose) {
16
+ return JSON.stringify(data, null, 2);
17
+ } else {
18
+ try {
19
+ return (0, _toon.encode)(data);
20
+ } catch (e) {
21
+ return JSON.stringify(data);
22
+ }
23
+ }
15
24
  }
@@ -14,14 +14,16 @@ var _shortcuts = require("../shortcuts");
14
14
  * 为单个 tool 子命令注册 Commander options
15
15
  * 直接读取预生成的 flat-options.json 中已扁平化的参数定义,无需运行时计算
16
16
  */
17
- function registerToolOptions(toolCmd, moduleName, toolName) {
17
+ function registerToolOptions(toolCmd, moduleName, toolName, skipPathMandatory) {
18
18
  const moduleOptions = _flatOptionsData.flatOptionsData[moduleName];
19
19
  if (!moduleOptions) return;
20
20
  const toolOptions = moduleOptions[toolName];
21
21
  if (!toolOptions) return;
22
22
  for (const [, opt] of Object.entries(toolOptions)) {
23
+ // 快捷命令跳过 path 参数(由环境变量自动注入)
24
+ if (skipPathMandatory && opt.source === 'path') continue;
23
25
  const option = new _commander.Option(`--${opt.optKey} ${opt.valuePlaceholder}`.trim(), opt.description);
24
- if (opt.required && opt.source === 'path') {
26
+ if (opt.required && opt.source === 'path' && !skipPathMandatory) {
25
27
  option.makeOptionMandatory();
26
28
  }
27
29
  if (opt.choices) {
@@ -43,6 +45,15 @@ function registerToolOptions(toolCmd, moduleName, toolName) {
43
45
  }
44
46
  }
45
47
 
48
+ /**
49
+ * 获取指定模块的快捷命令列表
50
+ */
51
+ function getShortcutsForModule(moduleName) {
52
+ if (moduleName === 'issues') return _shortcuts.ISSUE_SHORTCUTS;
53
+ if (moduleName === 'pulls') return _shortcuts.PR_SHORTCUTS;
54
+ return [];
55
+ }
56
+
46
57
  /**
47
58
  * 为每个模块注册子命令,使 cnb <module> -h 显示模块帮助
48
59
  * 每个 tool 的参数通过 Commander 的 option 系统注册,--help 自动展示参数说明
@@ -53,6 +64,9 @@ function registerModuleCommands(program) {
53
64
  const toolEntries = Object.values(tools);
54
65
  const sub = program.command(moduleName).description(`${moduleName} 模块 (${toolEntries.length} tools)`).helpOption('-h, --help', '显示帮助文档');
55
66
 
67
+ // 收集已注册的子命令名,避免快捷命令与真实 tool 名冲突
68
+ const registeredNames = new Set();
69
+
56
70
  // 为每个 tool 注册子命令
57
71
  for (const [toolName, toolInfo] of Object.entries(tools)) {
58
72
  const summary = (0, _trimSummary.trimSummary)(toolInfo.summary || '');
@@ -67,6 +81,23 @@ function registerModuleCommands(program) {
67
81
 
68
82
  // 根据 flat-options.json 注册参数选项
69
83
  registerToolOptions(toolCmd, moduleName, toolName);
84
+ registeredNames.add(toolName);
85
+ }
86
+
87
+ // 为快捷命令注册 Commander 子命令(别名)
88
+ // 复用对应真实 tool 的选项定义,但跳过 path 参数(由环境变量自动注入)
89
+ const shortcuts = getShortcutsForModule(moduleName);
90
+ for (const shortcut of shortcuts) {
91
+ // 如果快捷命令名与真实 tool 名重复,跳过(真实 tool 优先)
92
+ if (registeredNames.has(shortcut.shortName)) continue;
93
+ const shortcutCmd = sub.command(shortcut.shortName).description(`[快捷] ${shortcut.description}`).option('-v, --verbose', '输出完整原始响应').helpOption('-h, --help', '显示帮助文档').showHelpAfterError(true).action(async opts => {
94
+ // 传入快捷命令名,executeAction 内部会通过 resolveShortcut 转换
95
+ await (0, _executeAction.executeAction)(moduleName, shortcut.shortName, opts, sub);
96
+ });
97
+
98
+ // 复用真实 tool 的选项,跳过 path 参数
99
+ registerToolOptions(shortcutCmd, moduleName, shortcut.realTool, true);
100
+ registeredNames.add(shortcut.shortName);
70
101
  }
71
102
 
72
103
  // 允许未匹配到子命令时也能正常执行(不报错)
@@ -74,16 +105,11 @@ function registerModuleCommands(program) {
74
105
  sub.allowExcessArguments();
75
106
 
76
107
  // 模块级 action:处理未匹配到子命令的情况
77
- // 如果输入了快捷命令名(如 cnb issues get),Commander 匹配不到真实 tool 子命令,
78
- // 会走到这里,此时尝试 resolveShortcut 将其转换为真实 tool
79
- sub.argument('[tool]', '工具名称(支持快捷命令)').action(async (toolArg, opts) => {
108
+ sub.argument('[tool]', '工具名称(支持快捷命令)').action(async (toolArg, _opts) => {
80
109
  if (toolArg) {
81
- const shortcut = (0, _shortcuts.resolveShortcut)(moduleName, toolArg);
82
- if (shortcut) {
83
- // 快捷命令匹配成功,走 executeAction 流程
84
- await (0, _executeAction.executeAction)(moduleName, toolArg, opts, sub);
85
- return;
86
- }
110
+ // 此处已不会再命中快捷命令(因为已注册为子命令),仅作兜底
111
+ sub.help();
112
+ return;
87
113
  }
88
114
  sub.help();
89
115
  });
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.PR_SHORTCUTS = exports.ISSUE_SHORTCUTS = void 0;
6
7
  exports.detectEventContext = detectEventContext;
7
8
  exports.resolveShortcut = resolveShortcut;
8
9
  exports.showShort = showShort;
@@ -40,7 +41,7 @@ function getPRNumber() {
40
41
  // 快捷命令定义
41
42
  // ============================================================
42
43
 
43
- const ISSUE_SHORTCUTS = [{
44
+ const ISSUE_SHORTCUTS = exports.ISSUE_SHORTCUTS = [{
44
45
  shortName: 'get',
45
46
  realTool: 'get-issue',
46
47
  description: '获取详情'
@@ -100,7 +101,7 @@ const ISSUE_SHORTCUTS = [{
100
101
  upload: true,
101
102
  dataTip: "--file 图片路径"
102
103
  }];
103
- const PR_SHORTCUTS = [{
104
+ const PR_SHORTCUTS = exports.PR_SHORTCUTS = [{
104
105
  shortName: 'get',
105
106
  realTool: 'get-pull',
106
107
  description: '获取详情'