@hangox/pm-cli 0.2.3 → 0.2.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/dist/index.js +221 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1148,10 +1148,183 @@ function parsePmLink(url) {
|
|
|
1148
1148
|
return null;
|
|
1149
1149
|
}
|
|
1150
1150
|
|
|
1151
|
+
// src/utils/issue-exporter.ts
|
|
1152
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, statSync } from "fs";
|
|
1153
|
+
import { join as join2 } from "path";
|
|
1154
|
+
|
|
1155
|
+
// src/utils/preset-extractor.ts
|
|
1156
|
+
var SUMMARY_CUSTOM_FIELD_IDS = [84];
|
|
1157
|
+
var STANDARD_CUSTOM_FIELD_IDS = [
|
|
1158
|
+
84,
|
|
1159
|
+
// 预计提测时间
|
|
1160
|
+
286,
|
|
1161
|
+
// 需求大类
|
|
1162
|
+
186,
|
|
1163
|
+
// 业务目标
|
|
1164
|
+
77,
|
|
1165
|
+
// 需求来源
|
|
1166
|
+
274,
|
|
1167
|
+
// 开发结束时间
|
|
1168
|
+
19,
|
|
1169
|
+
// 跟进QA
|
|
1170
|
+
86,
|
|
1171
|
+
// 需求延误
|
|
1172
|
+
87
|
|
1173
|
+
// 需求变更
|
|
1174
|
+
];
|
|
1175
|
+
function extractSummaryFields(issue) {
|
|
1176
|
+
const rawIssue = issue;
|
|
1177
|
+
const rawStatus = rawIssue.status;
|
|
1178
|
+
const status = rawStatus ? { id: rawStatus.id ?? 0, name: rawStatus.name ?? "" } : { id: 0, name: "" };
|
|
1179
|
+
const rawAssignedTo = rawIssue.assigned_to;
|
|
1180
|
+
const assigned_to = rawAssignedTo ? { id: rawAssignedTo.id ?? 0, name: rawAssignedTo.name ?? "" } : void 0;
|
|
1181
|
+
const rawCustomFields = rawIssue.custom_fields;
|
|
1182
|
+
const custom_fields = (rawCustomFields || []).filter((cf) => SUMMARY_CUSTOM_FIELD_IDS.includes(cf.id)).map((cf) => ({ id: cf.id, name: cf.name, value: cf.value }));
|
|
1183
|
+
return {
|
|
1184
|
+
id: issue.id,
|
|
1185
|
+
subject: issue.subject,
|
|
1186
|
+
status,
|
|
1187
|
+
assigned_to,
|
|
1188
|
+
estimated_hours: issue.estimated_hours,
|
|
1189
|
+
spent_hours: issue.spent_hours,
|
|
1190
|
+
done_ratio: issue.done_ratio,
|
|
1191
|
+
custom_fields
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
function extractStandardFields(issue) {
|
|
1195
|
+
const rawIssue = issue;
|
|
1196
|
+
const rawStatus = rawIssue.status;
|
|
1197
|
+
const status = rawStatus ? { id: rawStatus.id ?? 0, name: rawStatus.name ?? "", is_closed: rawStatus.is_closed } : { id: 0, name: "" };
|
|
1198
|
+
const rawAssignedTo = rawIssue.assigned_to;
|
|
1199
|
+
const assigned_to = rawAssignedTo ? { id: rawAssignedTo.id ?? 0, name: rawAssignedTo.name ?? "", mail: rawAssignedTo.mail } : void 0;
|
|
1200
|
+
const rawPriority = rawIssue.priority;
|
|
1201
|
+
const priority = rawPriority ? { id: rawPriority.id ?? 0, name: rawPriority.name ?? "" } : void 0;
|
|
1202
|
+
const rawTracker = rawIssue.tracker;
|
|
1203
|
+
const tracker = rawTracker ? { id: rawTracker.id ?? 0, name: rawTracker.name ?? "" } : void 0;
|
|
1204
|
+
const rawProject = rawIssue.project;
|
|
1205
|
+
const project = rawProject ? { id: rawProject.id ?? 0, name: rawProject.name ?? "" } : void 0;
|
|
1206
|
+
const rawCustomFields = rawIssue.custom_fields;
|
|
1207
|
+
const custom_fields = (rawCustomFields || []).filter((cf) => STANDARD_CUSTOM_FIELD_IDS.includes(cf.id)).map((cf) => ({ id: cf.id, name: cf.name, value: cf.value }));
|
|
1208
|
+
return {
|
|
1209
|
+
id: issue.id,
|
|
1210
|
+
subject: issue.subject,
|
|
1211
|
+
status,
|
|
1212
|
+
assigned_to,
|
|
1213
|
+
estimated_hours: issue.estimated_hours,
|
|
1214
|
+
spent_hours: issue.spent_hours,
|
|
1215
|
+
done_ratio: issue.done_ratio,
|
|
1216
|
+
priority,
|
|
1217
|
+
tracker,
|
|
1218
|
+
project,
|
|
1219
|
+
created_on: issue.created_on,
|
|
1220
|
+
updated_on: issue.updated_on,
|
|
1221
|
+
custom_fields
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
function extractCompleteFields(issue) {
|
|
1225
|
+
const rawIssue = issue;
|
|
1226
|
+
const result = {};
|
|
1227
|
+
for (const key of Object.keys(rawIssue)) {
|
|
1228
|
+
if (key !== "children") {
|
|
1229
|
+
result[key] = rawIssue[key];
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return result;
|
|
1233
|
+
}
|
|
1234
|
+
function generateSummaryTree(issue, currentDepth = 0, maxDepth = -1) {
|
|
1235
|
+
const node = extractSummaryFields(issue);
|
|
1236
|
+
if (maxDepth !== -1 && currentDepth >= maxDepth) {
|
|
1237
|
+
node.children = [];
|
|
1238
|
+
return node;
|
|
1239
|
+
}
|
|
1240
|
+
if (issue.children && issue.children.length > 0) {
|
|
1241
|
+
node.children = issue.children.map(
|
|
1242
|
+
(child) => generateSummaryTree(child, currentDepth + 1, maxDepth)
|
|
1243
|
+
);
|
|
1244
|
+
} else {
|
|
1245
|
+
node.children = [];
|
|
1246
|
+
}
|
|
1247
|
+
return node;
|
|
1248
|
+
}
|
|
1249
|
+
function flattenIssues(issue, result = []) {
|
|
1250
|
+
result.push(issue);
|
|
1251
|
+
if (issue.children) {
|
|
1252
|
+
for (const child of issue.children) {
|
|
1253
|
+
flattenIssues(child, result);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
return result;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// src/utils/issue-exporter.ts
|
|
1260
|
+
function generateExportDir(command, identifier) {
|
|
1261
|
+
const now = /* @__PURE__ */ new Date();
|
|
1262
|
+
const timestamp = now.getFullYear().toString() + (now.getMonth() + 1).toString().padStart(2, "0") + now.getDate().toString().padStart(2, "0") + now.getHours().toString().padStart(2, "0") + now.getMinutes().toString().padStart(2, "0") + now.getSeconds().toString().padStart(2, "0");
|
|
1263
|
+
return `/tmp/pm-cli_${command}_${identifier}_${timestamp}`;
|
|
1264
|
+
}
|
|
1265
|
+
async function exportIssuePresets(issue, exportDir, options = {}) {
|
|
1266
|
+
const { depth = -1, pretty = false } = options;
|
|
1267
|
+
const indent = pretty ? 2 : 0;
|
|
1268
|
+
mkdirSync2(exportDir, { recursive: true });
|
|
1269
|
+
mkdirSync2(join2(exportDir, "standard"), { recursive: true });
|
|
1270
|
+
mkdirSync2(join2(exportDir, "complete"), { recursive: true });
|
|
1271
|
+
const resultFiles = [];
|
|
1272
|
+
const summaryTree = generateSummaryTree(issue, 0, depth);
|
|
1273
|
+
const summaryPath = join2(exportDir, "tree.summary.json");
|
|
1274
|
+
writeFileSync3(summaryPath, JSON.stringify(summaryTree, null, indent), "utf-8");
|
|
1275
|
+
const summarySize = statSync(summaryPath).size;
|
|
1276
|
+
resultFiles.push({ path: "tree.summary.json", size: summarySize, type: "tree" });
|
|
1277
|
+
const allIssues = flattenIssues(issue);
|
|
1278
|
+
for (const iss of allIssues) {
|
|
1279
|
+
const standardData = extractStandardFields(iss);
|
|
1280
|
+
const standardPath = join2(exportDir, "standard", `${iss.id}.json`);
|
|
1281
|
+
writeFileSync3(standardPath, JSON.stringify(standardData, null, indent), "utf-8");
|
|
1282
|
+
const standardSize = statSync(standardPath).size;
|
|
1283
|
+
resultFiles.push({ path: `standard/${iss.id}.json`, size: standardSize, type: "standard" });
|
|
1284
|
+
}
|
|
1285
|
+
for (const iss of allIssues) {
|
|
1286
|
+
const completeData = extractCompleteFields(iss);
|
|
1287
|
+
const completePath = join2(exportDir, "complete", `${iss.id}.json`);
|
|
1288
|
+
writeFileSync3(completePath, JSON.stringify(completeData, null, indent), "utf-8");
|
|
1289
|
+
const completeSize = statSync(completePath).size;
|
|
1290
|
+
resultFiles.push({ path: `complete/${iss.id}.json`, size: completeSize, type: "complete" });
|
|
1291
|
+
}
|
|
1292
|
+
const totalSize = resultFiles.reduce((sum, f) => sum + f.size, 0);
|
|
1293
|
+
return {
|
|
1294
|
+
success: true,
|
|
1295
|
+
exportDir,
|
|
1296
|
+
fileCount: resultFiles.length,
|
|
1297
|
+
totalSize,
|
|
1298
|
+
files: resultFiles
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
function generateAIGuideOutput(exportDir, fileCount, totalSize) {
|
|
1302
|
+
const sizeKB = (totalSize / 1024).toFixed(2);
|
|
1303
|
+
return `
|
|
1304
|
+
\u2705 \u5BFC\u51FA\u5B8C\u6210\uFF01
|
|
1305
|
+
\u{1F4C2} ${exportDir}/
|
|
1306
|
+
\u{1F4CA} ${fileCount} \u4E2A\u6587\u4EF6, ${sizeKB} KB
|
|
1307
|
+
|
|
1308
|
+
\u{1F916} AI \u8BFB\u53D6\u6307\u5357:
|
|
1309
|
+
1\uFE0F\u20E3 \u5148\u8BFB tree.summary.json \u2192 \u83B7\u53D6\u4EFB\u52A1\u6811 + \u7236\u5B50\u5173\u7CFB + \u57FA\u672C\u4FE1\u606F
|
|
1310
|
+
2\uFE0F\u20E3 \u9700\u8981\u8BE6\u60C5\u65F6 \u2192 \u8BFB standard/{id}.json \u6216 complete/{id}.json
|
|
1311
|
+
|
|
1312
|
+
\u{1F4D6} \u5B57\u6BB5\u7EA7\u522B:
|
|
1313
|
+
\u2022 summary = id, subject, status, assigned_to, \u5DE5\u65F6, \u9884\u8BA1\u63D0\u6D4B\u65F6\u95F4
|
|
1314
|
+
\u2022 standard = summary + priority, tracker, project, \u65F6\u95F4\u6233, 8\u4E2A\u81EA\u5B9A\u4E49\u5B57\u6BB5
|
|
1315
|
+
\u2022 complete = \u5168\u90E8\u5B57\u6BB5\uFF08\u542B description, author, journals \u7B49\uFF09
|
|
1316
|
+
|
|
1317
|
+
\u{1F4A1} Token \u4F18\u5316:
|
|
1318
|
+
\u2022 \u53EA\u770B\u4EFB\u52A1\u5217\u8868/\u8FDB\u5EA6 \u2192 tree.summary.json (~5k tokens)
|
|
1319
|
+
\u2022 \u5355\u4EFB\u52A1\u4F18\u5148\u7EA7/\u6765\u6E90 \u2192 standard/{id}.json (~3k tokens)
|
|
1320
|
+
\u2022 \u4EFB\u52A1\u8BE6\u7EC6\u63CF\u8FF0/\u5386\u53F2 \u2192 complete/{id}.json (~11k tokens)
|
|
1321
|
+
`.trim();
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1151
1324
|
// src/commands/issue/index.ts
|
|
1152
1325
|
function createIssueCommand() {
|
|
1153
1326
|
const issueCmd = new Command3("issue").description("\u95EE\u9898\u7BA1\u7406");
|
|
1154
|
-
issueCmd.command("get [id]").description("\u83B7\u53D6\u95EE\u9898\u8BE6\u60C5\uFF08\u9ED8\u8BA4\
|
|
1327
|
+
issueCmd.command("get [id]").description("\u83B7\u53D6\u95EE\u9898\u8BE6\u60C5\uFF08\u9ED8\u8BA4\u5206\u7EA7\u5BFC\u51FA\uFF0C--raw \u8F93\u51FA\u5B8C\u6574 JSON\uFF09").option("--url <url>", "PM \u94FE\u63A5").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--depth <depth>", "\u9012\u5F52\u83B7\u53D6\u5B50\u5355\u7684\u6DF1\u5EA6\uFF080 \u8868\u793A\u4E0D\u83B7\u53D6\u5B50\u5355\uFF09", "10").option("-o, --output <path>", "\u8F93\u51FA\u76EE\u5F55\u6216\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4 /tmp\uFF09").option("--stdout", "\u5F3A\u5236\u8F93\u51FA\u5230\u63A7\u5236\u53F0\u800C\u975E\u6587\u4EF6").option("--raw", "\u8F93\u51FA\u5B8C\u6574 JSON \u6587\u4EF6\uFF08\u4E0D\u5206\u7EA7\uFF0C\u539F\u884C\u4E3A\uFF09").option("--include-relations", "\u5305\u542B\u5173\u8054\u95EE\u9898").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (id, options) => {
|
|
1155
1328
|
let issueId;
|
|
1156
1329
|
let host;
|
|
1157
1330
|
if (options.url) {
|
|
@@ -1192,13 +1365,31 @@ function createIssueCommand() {
|
|
|
1192
1365
|
depth
|
|
1193
1366
|
);
|
|
1194
1367
|
if (result.success && result.data) {
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1368
|
+
if (options.raw || options.stdout) {
|
|
1369
|
+
smartOutput(result.data, {
|
|
1370
|
+
stdout: options.stdout,
|
|
1371
|
+
output: options.output,
|
|
1372
|
+
command: "issue-get",
|
|
1373
|
+
identifier: issueId.toString(),
|
|
1374
|
+
pretty: options.pretty
|
|
1375
|
+
});
|
|
1376
|
+
} else {
|
|
1377
|
+
const exportDir = options.output || generateExportDir("issue-get", issueId.toString());
|
|
1378
|
+
const exportResult = await exportIssuePresets(result.data, exportDir, {
|
|
1379
|
+
depth,
|
|
1380
|
+
pretty: options.pretty
|
|
1381
|
+
});
|
|
1382
|
+
if (exportResult.success) {
|
|
1383
|
+
console.log(generateAIGuideOutput(
|
|
1384
|
+
exportResult.exportDir,
|
|
1385
|
+
exportResult.fileCount,
|
|
1386
|
+
exportResult.totalSize
|
|
1387
|
+
));
|
|
1388
|
+
} else {
|
|
1389
|
+
outputError("\u5BFC\u51FA\u5931\u8D25", options.pretty);
|
|
1390
|
+
process.exit(1);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1202
1393
|
} else {
|
|
1203
1394
|
outputError(result.message || result.msg || result.api_error_msg || "\u83B7\u53D6\u95EE\u9898\u5931\u8D25", options.pretty);
|
|
1204
1395
|
process.exit(1);
|
|
@@ -1847,7 +2038,7 @@ function getWeekDateRange(week) {
|
|
|
1847
2038
|
}
|
|
1848
2039
|
function createTimeCommand() {
|
|
1849
2040
|
const timeCmd = new Command4("time").description("\u5DE5\u65F6\u7BA1\u7406");
|
|
1850
|
-
timeCmd.command("list").description("\u67E5\u8BE2\u5DE5\u65F6\u6761\u76EE").option("--from <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)").option("--to <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)").option("--user-id <id>", "\u7528\u6237 ID").option("--activity-id <id>", "\u6D3B\u52A8\u7C7B\u578B ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--all-projects", "\u67E5\u8BE2\u6240\u6709\u9879\u76EE\u7684\u5DE5\u65F6").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
|
|
2041
|
+
timeCmd.command("list").description("\u67E5\u8BE2\u5DE5\u65F6\u6761\u76EE").option("--from <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)").option("--to <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)").option("--user-id <id>", "\u7528\u6237 ID").option("--activity-id <id>", "\u6D3B\u52A8\u7C7B\u578B ID").option("--limit <limit>", "\u8FD4\u56DE\u6570\u91CF\u9650\u5236").option("--offset <offset>", "\u504F\u79FB\u91CF").option("--all-projects", "\u67E5\u8BE2\u6240\u6709\u9879\u76EE\u7684\u5DE5\u65F6").option("--all-user", "\u67E5\u8BE2\u6240\u6709\u7528\u6237\u7684\u5DE5\u65F6\uFF08\u4E0D\u7B5B\u9009\uFF0C\u9ED8\u8BA4\u53EA\u67E5\u8BE2\u5F53\u524D\u7528\u6237\uFF09").option("--token <token>", "API Token").option("--host <host>", "PM \u4E3B\u673A\u5730\u5740").option("--project <project>", "\u9879\u76EE\u540D\u79F0").option("--profile <name>", "\u4F7F\u7528\u914D\u7F6E profile").option("--config <path>", "\u81EA\u5B9A\u4E49\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09").action(async (options) => {
|
|
1851
2042
|
const creds = resolveCredentials(options);
|
|
1852
2043
|
const requiredFields = options.allProjects ? ["token", "host"] : ["token", "host", "project"];
|
|
1853
2044
|
const validation = validateCredentials(creds, requiredFields);
|
|
@@ -1865,6 +2056,24 @@ function createTimeCommand() {
|
|
|
1865
2056
|
const projects = projectsResult.data;
|
|
1866
2057
|
const projectNames = Object.values(projects).map((p) => p.name);
|
|
1867
2058
|
logger_default.info(`\u627E\u5230 ${projectNames.length} \u4E2A\u9879\u76EE`);
|
|
2059
|
+
let userId;
|
|
2060
|
+
if (!options.allUser) {
|
|
2061
|
+
if (options.userId) {
|
|
2062
|
+
userId = parseInt(options.userId, 10);
|
|
2063
|
+
} else {
|
|
2064
|
+
const configUserId = getConfigValue("userId", options.config);
|
|
2065
|
+
if (configUserId) {
|
|
2066
|
+
userId = parseInt(configUserId, 10);
|
|
2067
|
+
logger_default.info(`\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684\u7528\u6237 ID: ${userId}`);
|
|
2068
|
+
} else {
|
|
2069
|
+
outputError("\u672A\u914D\u7F6E\u7528\u6237 ID\uFF0C\u8BF7\u5148\u8BBE\u7F6E: pm-cli config set user-id <\u60A8\u7684\u7528\u6237ID>\uFF0C\u6216\u4F7F\u7528 --all-user \u67E5\u8BE2\u6240\u6709\u7528\u6237", options.pretty);
|
|
2070
|
+
process.exit(1);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
} else if (options.userId) {
|
|
2074
|
+
userId = parseInt(options.userId, 10);
|
|
2075
|
+
logger_default.info(`\u4F7F\u7528\u6307\u5B9A\u7684\u7528\u6237 ID: ${userId}`);
|
|
2076
|
+
}
|
|
1868
2077
|
const allTimeEntries = [];
|
|
1869
2078
|
let totalCount = 0;
|
|
1870
2079
|
const projectSummary = [];
|
|
@@ -1875,7 +2084,7 @@ function createTimeCommand() {
|
|
|
1875
2084
|
project: projectName,
|
|
1876
2085
|
from_date: options.from,
|
|
1877
2086
|
to_date: options.to,
|
|
1878
|
-
user_id:
|
|
2087
|
+
user_id: userId,
|
|
1879
2088
|
activity_id: options.activityId ? parseInt(options.activityId, 10) : void 0,
|
|
1880
2089
|
limit: options.limit ? parseInt(options.limit, 10) : 100,
|
|
1881
2090
|
offset: options.offset ? parseInt(options.offset, 10) : void 0
|
|
@@ -2233,11 +2442,11 @@ function createProjectCommand() {
|
|
|
2233
2442
|
|
|
2234
2443
|
// src/index.ts
|
|
2235
2444
|
import { readFileSync as readFileSync2 } from "fs";
|
|
2236
|
-
import { dirname as dirname2, join as
|
|
2445
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
2237
2446
|
import { fileURLToPath } from "url";
|
|
2238
2447
|
var __filename = fileURLToPath(import.meta.url);
|
|
2239
2448
|
var __dirname = dirname2(__filename);
|
|
2240
|
-
var packageJson = JSON.parse(readFileSync2(
|
|
2449
|
+
var packageJson = JSON.parse(readFileSync2(join3(__dirname, "../package.json"), "utf-8"));
|
|
2241
2450
|
var version = packageJson.version;
|
|
2242
2451
|
var program = new Command6();
|
|
2243
2452
|
program.name("pm-cli").description("\u7F51\u6613\u6613\u534F\u4F5C (PM NetEase) \u547D\u4EE4\u884C\u5DE5\u5177").version(version).option("--verbose", "\u8BE6\u7EC6\u8F93\u51FA").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F").option("--no-mapping", "\u4E0D\u8F93\u51FA key \u6620\u5C04\u8868\uFF08\u9ED8\u8BA4\u8F93\u51FA\uFF09").hook("preAction", (thisCommand) => {
|