@cnbcool/cnb-api-generate 2.12.2 → 2.12.3

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.
@@ -130,6 +130,15 @@ interface IssueUploadData {
130
130
 
131
131
  /** Pull 上传成功时的 data */
132
132
  interface PullUploadData {
133
+ /**
134
+ * 资源链接,添加到 body 中提交。
135
+ *
136
+ * pull 上传接口(/{repo}/-/upload/{files,imgs})响应模型 dto.UploadAssetsResponse
137
+ * 并没有 asset_link 字段,等价信息由 assets.path 承载,
138
+ * 这里用 assets.path + 文件名拼成与 issue 侧一致的 markdown 形态
139
+ * (图片 `![name](path)`、文件 `[name](path)`)。
140
+ */
141
+ asset_link?: string;
133
142
  name: string;
134
143
  size: number;
135
144
  token?: string;
@@ -209,6 +218,39 @@ async function putFileStream(
209
218
  return undefined;
210
219
  }
211
220
 
221
+ /**
222
+ * 去掉资源路径里的仓库 slug 前缀。
223
+ *
224
+ * pull 上传接口返回的 assets.path 形如 `/{slug}/-/imgs/xxx/xxx.png`,
225
+ * 而 issue 侧 asset_link 是不带 slug 的 `/-/files/issues/xxx/xxx.txt`,
226
+ * 这里统一截断到 `/-/` 开始,保证两条上传路径产出的引用格式一致。
227
+ */
228
+ function stripSlugPrefix(assetPath: string): string {
229
+ const idx = assetPath.indexOf('/-/');
230
+ return idx > 0 ? assetPath.slice(idx) : assetPath;
231
+ }
232
+
233
+ /**
234
+ * 转义 markdown 链接文字。
235
+ *
236
+ * 链接文字取自文件名(本地文件决定,属于不可信输入),
237
+ * 含 `[` `]` `(` `)` `\` 时会破坏链接结构、甚至注入额外 markdown,
238
+ * 换行同样会打断评论结构,这里统一转义 / 折叠为空格。
239
+ */
240
+ function escapeMarkdownLinkText(text: string): string {
241
+ return text.replace(/[[\]()\\]/g, '\\$&').replace(/\r?\n/g, ' ');
242
+ }
243
+
244
+ /**
245
+ * 编码 markdown 链接地址。
246
+ *
247
+ * 先做 URL 编码处理空格等字符,再把圆括号转成百分号形式,
248
+ * 避免路径里的 `(` `)` 提前截断 `[](...)` 结构。
249
+ */
250
+ function encodeMarkdownLinkUrl(url: string): string {
251
+ return encodeURI(url).replace(/\(/g, '%28').replace(/\)/g, '%29');
252
+ }
253
+
212
254
  /** asset-group 接口请求体 */
213
255
  interface PostAssetGroupForm {
214
256
  image_assets?: Array<{ name: string; size: number; content_type: string }>;
@@ -303,6 +345,7 @@ export async function handleIssueCreateUpload(
303
345
  * Pull 路径(保留原有的 upload-files / upload-imgs 一步上传):
304
346
  * 1. POST /{repo}/upload-files(或 imgs) 拿 upload_url
305
347
  * 2. PUT 文件流到 upload_url
348
+ * 3. 该接口不返回 asset_link,用 assets.path + 文件名拼成 markdown 形态的 asset_link 返回给调用方
306
349
  *
307
350
  * @param shortcut 解析后的快捷命令;shortcut.kind 决定 issue 上传走 file 还是 image 通道
308
351
  * @param filePath 本地文件路径
@@ -349,8 +392,21 @@ export async function handleUpload(
349
392
  const data = apiResponse?.data as PullUploadResponseData | undefined;
350
393
  uploadUrl = data?.upload_url;
351
394
  if (!uploadUrl) return apiResponse as unknown as UploadResult;
395
+ // 接口只返回 assets.path,这里按 issue 侧 asset_link 的 markdown 形态拼装:
396
+ // 图片 -> ![name](path),文件 -> [name](path)
397
+ // 链接文字直接复用返回的 name(图片会被服务端改名为 uuid,文件保持原名)
398
+ // 路径去掉 slug 前缀,与 issue 侧 asset_link 保持一致
399
+ const assetPath = data?.assets?.path;
400
+ const assetName = data?.assets?.name || fileName;
401
+ // kind 由 quick-commands.json 配置,是权威来源;
402
+ // realTool 名兜底仅用于兼容老版本产物里没有 kind 的 shortcuts 配置,
403
+ // 一旦 realTool 被重命名该兜底会失效(此时应以配置里的 kind 为准)。
404
+ const isImage = shortcut.kind === 'image' || shortcut.tool === 'upload-imgs';
352
405
  successData = {
353
- name: data?.assets?.name || fileName,
406
+ asset_link: assetPath
407
+ ? `${isImage ? '!' : ''}[${escapeMarkdownLinkText(assetName)}](${encodeMarkdownLinkUrl(stripSlugPrefix(assetPath))})`
408
+ : undefined,
409
+ name: assetName,
354
410
  size: fileSize,
355
411
  token: data?.token,
356
412
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnbcool/cnb-api-generate",
3
- "version": "2.12.2",
3
+ "version": "2.12.3",
4
4
  "main": "./built/index.js",
5
5
  "module": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -27,8 +27,8 @@
27
27
  { "shortName": "check-status", "realTool": "list-pull-commit-statuses", "description": "查看 CI 状态" },
28
28
  { "shortName": "list-reviews", "realTool": "list-pull-reviews", "description": "查看评审列表" },
29
29
  { "shortName": "list-assignees", "realTool": "list-pull-assignees", "description": "查看处理人" },
30
- { "shortName": "upload-file", "realTool": "upload-files", "description": "上传文件", "repoOnly": true, "upload": true, "hideInSkill": true, "dataTip": "--file 文件路径" },
31
- { "shortName": "upload-image", "realTool": "upload-imgs", "description": "上传图片", "repoOnly": true, "upload": true, "hideInSkill": true, "dataTip": "--file 图片路径" },
30
+ { "shortName": "upload-file", "realTool": "upload-files", "description": "上传文件", "repoOnly": true, "upload": true, "kind": "file", "hideInSkill": true, "dataTip": "--file 文件路径" },
31
+ { "shortName": "upload-image", "realTool": "upload-imgs", "description": "上传图片", "repoOnly": true, "upload": true, "kind": "image", "hideInSkill": true, "dataTip": "--file 图片路径" },
32
32
  { "shortName": "get-ci-logs", "realTool": "__get-ci-logs__", "description": "获取 CI 失败日志", "repoOnly": true, "custom": true, "dataTip": "--sn 构建号(可选)" },
33
33
  { "shortName": "get-ci-timing", "realTool": "__get-ci-timing__", "description": "分析 CI 耗时瓶颈", "repoOnly": true, "custom": true, "dataTip": "--sn 构建号(可选)" },
34
34
  { "shortName": "get-imgs", "realTool": "get-pr-imgs", "description": "获取 PR 图片", "repoOnly": true, "dataTip": "--img-path 图片路径" },