pdlab-cli 0.2.2 → 0.4.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 (3) hide show
  1. package/README.md +30 -1
  2. package/dist/index.js +325 -21
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -50,8 +50,10 @@ pdlab schema # 一次性 JSON 输出全部命令、参数、权限要
50
50
  | `pdlab project join \| leave <id>` | 报名共建 / 撤回申请或退出共建 |
51
51
  | `pdlab project member review \| set-role \| remove <projectId> <userId>` | 审核报名、设置协作者角色、移除参与者(仅项目发起人本人) |
52
52
  | `pdlab project revenue <id>` | 查看项目的积分分成明细(只读) |
53
- | `pdlab post list \| get \| create \| update \| delete` | 内容的增删改查 |
53
+ | `pdlab post list \| get \| create \| update \| delete` | 内容的增删改查(`--project-id` 选填,不填即独立发布,不挂任何项目) |
54
54
  | `pdlab post review <id> --action approve\|reject` | 审核一条待审内容 |
55
+ | `pdlab taxonomy list \| create \| update \| delete` | 分类标签的增删改查(列表公开只读,写操作需 `taxonomy:manage`) |
56
+ | `pdlab taxonomy dimension list \| create \| update \| delete <key>` | 分类维度的增删改查(内置维度不可删) |
55
57
 
56
58
  任何命令加 `--help` 看具体参数——示例已经直接打在 `--help` 末尾,不用等一次报错才能看到。
57
59
 
@@ -88,6 +90,17 @@ pdlab post list --project-id <项目 id>
88
90
  # 审核待审内容(需要 content:review 权限)
89
91
  pdlab post review post_123 --action approve
90
92
  pdlab post review post_123 --action reject --comment "缺少数据来源,请补充引用"
93
+
94
+ # 独立发布内容(不挂任何项目),任何已生效账号都能发;非免审角色发出去要等发起人审
95
+ pdlab post create --title "钠电产业观察" --body "……"
96
+
97
+ # 分类维度与标签管理(需要 taxonomy:manage 权限,即「1836发起人」角色)
98
+ pdlab taxonomy dimension list # 公开只读
99
+ pdlab taxonomy dimension create --key region --label "地区" --sort-order 3
100
+ pdlab taxonomy create --dimension domain --label "钠电固态化" --weight 0.2
101
+ pdlab taxonomy update tax_123 --weight 0.3
102
+ pdlab taxonomy delete tax_123
103
+ pdlab taxonomy dimension delete region # 内置维度(domain/attribute/commercial)不可删
91
104
  ```
92
105
 
93
106
  ### 分页
@@ -136,6 +149,22 @@ API 地址的解析顺序:`--api-url` 参数 > `PDLAB_API_URL` 环境变量 >
136
149
  作者也才能 `post get` 到自己那篇还没过审的稿子。没登录则匿名读公开内容,照常可用。
137
150
  在 CI 里可以只给环境变量,不落配置文件。
138
151
 
152
+ ## 版本更新提示
153
+
154
+ `pdlab` 每次运行都会顺手看一眼本地缓存的版本信息,如果有新版本会在命令结束时打印一行提示到
155
+ **stderr**(不影响 stdout 的 JSON 输出,脚本/agent 该怎么解析还怎么解析):
156
+
157
+ ```
158
+ ※ pdlab-cli 有新版本可用:0.3.0 → 0.4.0
159
+ 运行 npm install -g pdlab-cli@latest 升级(可用 PDLAB_NO_UPDATE_CHECK=1 关闭此提示)
160
+ ```
161
+
162
+ 这个检查本身不会拖慢任何命令:真正去问 npm registry 的动作放在一个独立的后台进程里做,
163
+ 每 24 小时最多问一次,前台命令只读本地缓存(一次磁盘读,微秒级)。离线或连不上 registry
164
+ 时静默跳过,不影响命令本身的执行结果。
165
+
166
+ 不想看到这个提示:设置环境变量 `PDLAB_NO_UPDATE_CHECK=1`(CI/自动化脚本建议直接设置)。
167
+
139
168
  ## 凭证与安全
140
169
 
141
170
  - **凭证怎么来的**:走设备码授权——CLI 生成一次性 code,你在浏览器里确认后服务端才签发。
package/dist/index.js CHANGED
@@ -24,8 +24,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_fs2 = require("fs");
28
- var import_path2 = require("path");
27
+ var import_fs3 = require("fs");
28
+ var import_path3 = require("path");
29
29
  var import_commander2 = require("commander");
30
30
 
31
31
  // src/commands/login.ts
@@ -297,27 +297,42 @@ function isSafeHttpUrl(raw) {
297
297
  return ALLOWED_PROTOCOLS.has(url.protocol);
298
298
  }
299
299
  var safeHttpUrl = import_zod.z.string().trim().max(2048, "\u94FE\u63A5\u8FC7\u957F").refine(isSafeHttpUrl, "\u53EA\u652F\u6301 http/https \u5F00\u5934\u7684\u94FE\u63A5");
300
+ var INTERNAL_IMAGE_PATH = /^\/api\/images\/[a-z0-9]{1,64}$/;
301
+ function isInternalImagePath(raw) {
302
+ return INTERNAL_IMAGE_PATH.test(raw.trim());
303
+ }
304
+ function isSafeImageSrc(raw) {
305
+ return isInternalImagePath(raw) || isSafeHttpUrl(raw);
306
+ }
307
+ var safeImageUrl = import_zod.z.string().trim().max(2048, "\u94FE\u63A5\u8FC7\u957F").refine(isSafeImageSrc, "\u53EA\u652F\u6301 http/https \u94FE\u63A5\u6216\u5E73\u53F0\u5185\u4E0A\u4F20\u7684\u56FE\u7247");
300
308
 
301
309
  // ../shared-schemas/src/projects.ts
302
310
  var import_zod2 = require("zod");
311
+ var taxonomySelectionSchema = import_zod2.z.object({
312
+ taxonomyId: import_zod2.z.string().min(1).describe("\u5206\u7C7B\u6807\u7B7E id"),
313
+ weight: import_zod2.z.number().min(0).max(1).describe("\u8BE5\u6807\u7B7E\u5728\u672C\u9879\u76EE\u91CC\u7684\u6743\u91CD 0~1")
314
+ });
303
315
  var PROJECT_STATUS_VALUES = ["planning", "active", "review", "completed"];
304
316
  var projectCreateSchema = import_zod2.z.object({
305
317
  title: import_zod2.z.string().trim().min(1, "\u9879\u76EE\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A").max(200).describe("\u9879\u76EE\u6807\u9898"),
306
318
  description: import_zod2.z.string().max(2e4).optional().describe("\u9879\u76EE\u63CF\u8FF0"),
307
- coverImage: safeHttpUrl.optional().describe("\u5C01\u9762\u56FE http/https \u94FE\u63A5"),
308
- commercialType: import_zod2.z.string().max(100).optional().describe("\u5546\u4E1A\u5C5E\u6027"),
319
+ coverImage: safeImageUrl.optional().describe("\u5C01\u9762\u56FE\u94FE\u63A5\u6216\u4E0A\u4F20\u56FE\u7247\u5730\u5740"),
320
+ commercialType: import_zod2.z.string().max(100).optional().describe("\u5546\u4E1A\u5408\u4F5C\u72B6\u6001\uFF0C\u5982\u300C\u4E0E\u67D0IDC\u5382\u5546\u63A5\u6D3D\u4E2D\u300D"),
309
321
  status: import_zod2.z.enum(PROJECT_STATUS_VALUES).optional().describe("\u9879\u76EE\u72B6\u6001\uFF1Aplanning/active/review/completed"),
310
322
  progress: import_zod2.z.number().int().min(0).max(100).optional().describe("\u9879\u76EE\u8FDB\u5EA6\u767E\u5206\u6BD4 0-100"),
311
- taxonomyIds: import_zod2.z.array(import_zod2.z.string().min(1)).max(50).optional().default([]).describe("\u5206\u7C7B\u6807\u7B7E id \u5217\u8868")
323
+ taxonomies: import_zod2.z.array(taxonomySelectionSchema).max(50).optional().describe("\u5206\u7C7B\u6807\u7B7E\u53CA\u5176\u5728\u672C\u9879\u76EE\u91CC\u7684\u6743\u91CD\uFF0C\u6BCF\u4E2A\u7EF4\u5EA6\u6700\u591A\u4E00\u4E2A\u6807\u7B7E"),
324
+ // 兼容 pdlab CLI 的旧参数:只给 id、不给权重时,服务端按标签的全局建议权重(Taxonomy.weight)填充
325
+ taxonomyIds: import_zod2.z.array(import_zod2.z.string().min(1)).max(50).optional().default([]).describe("\u5206\u7C7B\u6807\u7B7E id \u5217\u8868\uFF08\u65E7\u53C2\u6570\uFF0C\u6743\u91CD\u53D6\u6807\u7B7E\u9ED8\u8BA4\u503C\uFF09")
312
326
  });
313
327
  var projectUpdateSchema = import_zod2.z.object({
314
328
  title: import_zod2.z.string().trim().min(1, "\u9879\u76EE\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A").max(200).optional().describe("\u9879\u76EE\u6807\u9898"),
315
329
  description: import_zod2.z.string().max(2e4).nullable().optional().describe("\u9879\u76EE\u63CF\u8FF0"),
316
- coverImage: safeHttpUrl.nullable().optional().describe("\u5C01\u9762\u56FE http/https \u94FE\u63A5"),
317
- commercialType: import_zod2.z.string().max(100).nullable().optional().describe("\u5546\u4E1A\u5C5E\u6027"),
330
+ coverImage: safeImageUrl.nullable().optional().describe("\u5C01\u9762\u56FE\u94FE\u63A5\u6216\u4E0A\u4F20\u56FE\u7247\u5730\u5740"),
331
+ commercialType: import_zod2.z.string().max(100).nullable().optional().describe("\u5546\u4E1A\u5408\u4F5C\u72B6\u6001"),
318
332
  progress: import_zod2.z.number().int().min(0).max(100).optional().describe("\u9879\u76EE\u8FDB\u5EA6\u767E\u5206\u6BD4 0-100"),
319
333
  status: import_zod2.z.enum(PROJECT_STATUS_VALUES).optional().describe("\u9879\u76EE\u72B6\u6001\uFF1Aplanning/active/review/completed"),
320
- taxonomyIds: import_zod2.z.array(import_zod2.z.string().min(1)).max(50).optional().describe("\u5206\u7C7B\u6807\u7B7E id \u5217\u8868\uFF08\u5168\u91CF\u66FF\u6362\uFF09")
334
+ taxonomies: import_zod2.z.array(taxonomySelectionSchema).max(50).optional().describe("\u5206\u7C7B\u6807\u7B7E\u53CA\u5176\u6743\u91CD\uFF08\u5168\u91CF\u66FF\u6362\uFF09"),
335
+ taxonomyIds: import_zod2.z.array(import_zod2.z.string().min(1)).max(50).optional().describe("\u5206\u7C7B\u6807\u7B7E id \u5217\u8868\uFF08\u65E7\u53C2\u6570\uFF0C\u5168\u91CF\u66FF\u6362\uFF0C\u6743\u91CD\u53D6\u6807\u7B7E\u9ED8\u8BA4\u503C\uFF09")
321
336
  }).refine((v) => Object.keys(v).length > 0, "\u6CA1\u6709\u9700\u8981\u66F4\u65B0\u7684\u5B57\u6BB5");
322
337
 
323
338
  // ../shared-schemas/src/posts.ts
@@ -325,22 +340,52 @@ var import_zod3 = require("zod");
325
340
  var postCreateSchema = import_zod3.z.object({
326
341
  title: import_zod3.z.string().min(1).describe("\u5185\u5BB9\u6807\u9898"),
327
342
  body: import_zod3.z.string().min(1).describe("\u5185\u5BB9\u6B63\u6587"),
328
- projectId: import_zod3.z.string().describe("\u6240\u5C5E\u9879\u76EE id"),
329
- mediaLinks: import_zod3.z.array(safeHttpUrl).max(20, "\u5A92\u4F53\u94FE\u63A5\u6700\u591A 20 \u6761").optional().default([]).describe("\u5A92\u4F53\u94FE\u63A5\u5217\u8868")
343
+ // V3.1:可以不挂项目独立发布。挂项目时仍然要求发布者是该项目的发起人或已通过审核的参与者。
344
+ projectId: import_zod3.z.string().min(1).nullish().describe("\u6240\u5C5E\u9879\u76EE id\uFF0C\u4E0D\u586B\u8868\u793A\u72EC\u7ACB\u53D1\u5E03"),
345
+ mediaLinks: import_zod3.z.array(safeImageUrl).max(20, "\u5A92\u4F53\u4E0E\u56FE\u7247\u6700\u591A 20 \u6761").optional().default([]).describe("\u4E0A\u4F20\u7684\u56FE\u7247\u5730\u5740\u3001\u89C6\u9891\u94FE\u63A5\u4E0E\u5916\u90E8\u94FE\u63A5")
330
346
  });
331
347
  var postUpdateSchema = import_zod3.z.object({
332
348
  title: import_zod3.z.string().trim().min(1, "\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A").max(200).describe("\u5185\u5BB9\u6807\u9898"),
333
349
  body: import_zod3.z.string().trim().min(1, "\u6B63\u6587\u4E0D\u80FD\u4E3A\u7A7A").max(5e4).describe("\u5185\u5BB9\u6B63\u6587"),
334
- mediaLinks: import_zod3.z.array(safeHttpUrl).max(20).optional().default([]).describe("\u5A92\u4F53\u94FE\u63A5\u5217\u8868")
350
+ mediaLinks: import_zod3.z.array(safeImageUrl).max(20).optional().default([]).describe("\u4E0A\u4F20\u7684\u56FE\u7247\u5730\u5740\u3001\u89C6\u9891\u94FE\u63A5\u4E0E\u5916\u90E8\u94FE\u63A5")
335
351
  });
336
352
  var postReviewSchema = import_zod3.z.object({
337
353
  action: import_zod3.z.enum(["approve", "reject"]).describe("\u5BA1\u6838\u7ED3\u679C\uFF1Aapprove/reject"),
338
354
  reviewComment: import_zod3.z.string().trim().max(500, "\u5BA1\u6838\u610F\u89C1\u6700\u591A 500 \u5B57").optional().describe("\u5BA1\u6838\u610F\u89C1\uFF08\u9A73\u56DE\u65F6\u5FC5\u586B\uFF09")
339
355
  });
340
356
 
357
+ // ../shared-schemas/src/taxonomies.ts
358
+ var import_zod4 = require("zod");
359
+ var taxonomyDimensionCreateSchema = import_zod4.z.object({
360
+ // key 会进 URL 查询串和导出文件,限制成 slug 形态
361
+ key: import_zod4.z.string().trim().min(1).max(40).regex(/^[a-z][a-z0-9_]*$/, "\u7EF4\u5EA6\u6807\u8BC6\u53EA\u80FD\u7528\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4EE5\u5B57\u6BCD\u5F00\u5934").describe("\u7EF4\u5EA6\u6807\u8BC6\uFF0C\u5982 domain\uFF08\u521B\u5EFA\u540E\u4E0D\u53EF\u6539\uFF09"),
362
+ label: import_zod4.z.string().trim().min(1, "\u7EF4\u5EA6\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A").max(40).describe("\u7EF4\u5EA6\u4E2D\u6587\u540D\uFF0C\u5982\u300C\u9886\u57DF\u300D"),
363
+ description: import_zod4.z.string().max(500).optional().describe("\u7EF4\u5EA6\u8BF4\u660E"),
364
+ sortOrder: import_zod4.z.number().int().min(0).max(999).optional().default(0).describe("\u5C55\u793A\u6392\u5E8F")
365
+ });
366
+ var taxonomyDimensionUpdateSchema = import_zod4.z.object({
367
+ label: import_zod4.z.string().trim().min(1).max(40).optional().describe("\u7EF4\u5EA6\u4E2D\u6587\u540D"),
368
+ description: import_zod4.z.string().max(500).nullable().optional().describe("\u7EF4\u5EA6\u8BF4\u660E"),
369
+ sortOrder: import_zod4.z.number().int().min(0).max(999).optional().describe("\u5C55\u793A\u6392\u5E8F")
370
+ });
371
+ var taxonomyCreateSchema = import_zod4.z.object({
372
+ dimension: import_zod4.z.string().min(1).describe("\u6240\u5C5E\u7EF4\u5EA6\u7684 key\uFF0C\u5982 domain"),
373
+ label: import_zod4.z.string().trim().min(1, "\u6807\u7B7E\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A").max(100).describe("\u6807\u7B7E\u503C\uFF0C\u5982\u300C\u94A0\u7535\u4E0EAIDC\u5168\u7403\u57FA\u5EFA\u300D"),
374
+ weight: import_zod4.z.number().min(0).max(1).optional().default(0).describe("\u5EFA\u8BAE\u6743\u91CD 0~1\uFF1A\u53D1\u8D77\u9879\u76EE\u65F6\u9884\u586B\u7ED9\u53D1\u8D77\u4EBA\uFF0C\u53EF\u518D\u8C03"),
375
+ sortOrder: import_zod4.z.number().int().min(0).max(999).optional().default(0).describe("\u5C55\u793A\u6392\u5E8F"),
376
+ description: import_zod4.z.string().max(500).optional().describe("\u6807\u7B7E\u8BF4\u660E")
377
+ });
378
+ var taxonomyUpdateSchema = import_zod4.z.object({
379
+ dimension: import_zod4.z.string().min(1).optional().describe("\u6240\u5C5E\u7EF4\u5EA6\u7684 key"),
380
+ label: import_zod4.z.string().min(1).optional().describe("\u6807\u7B7E\u503C"),
381
+ weight: import_zod4.z.number().min(0).max(1).optional().describe("\u5EFA\u8BAE\u6743\u91CD 0~1"),
382
+ sortOrder: import_zod4.z.number().int().optional().describe("\u5C55\u793A\u6392\u5E8F"),
383
+ description: import_zod4.z.string().optional().describe("\u6807\u7B7E\u8BF4\u660E")
384
+ });
385
+
341
386
  // src/errors.ts
342
387
  var import_commander = require("commander");
343
- var import_zod4 = require("zod");
388
+ var import_zod5 = require("zod");
344
389
  var EXIT_CODES = {
345
390
  ok: 0,
346
391
  unhandled: 1,
@@ -373,7 +418,7 @@ function exampleHint(examples) {
373
418
  }
374
419
  function handleCommandError(error, examples = []) {
375
420
  let structured;
376
- if (error instanceof import_zod4.ZodError) {
421
+ if (error instanceof import_zod5.ZodError) {
377
422
  structured = {
378
423
  error: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
379
424
  code: "validation",
@@ -636,9 +681,13 @@ function registerProjectCommand(program2) {
636
681
 
637
682
  // src/commands/post.ts
638
683
  var CREATE_EXAMPLES2 = [
684
+ {
685
+ command: 'pdlab post create --title "\u94A0\u7535\u4EA7\u4E1A\u89C2\u5BDF" --body "..."',
686
+ note: "\u53EA\u6709 title / body \u5FC5\u586B\uFF1A\u4E0D\u5E26 --project-id \u5C31\u662F\u72EC\u7ACB\u53D1\u5E03\uFF0C\u4E0D\u6302\u4EFB\u4F55\u5171\u5EFA\u9879\u76EE"
687
+ },
639
688
  {
640
689
  command: 'pdlab post create --title "\u7B2C\u4E00\u5468\u8FDB\u5C55" --body "..." --project-id proj_123 --media-links https://example.com/a.png',
641
- note: "title / body / project-id \u5FC5\u586B\uFF1B\u9700\u8981\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u62A5\u540D\u5171\u5EFA\u8BE5\u9879\u76EE"
690
+ note: "\u6302\u5230\u9879\u76EE\u4E0B\u65F6\uFF0C\u9700\u8981\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u901A\u8FC7\u5BA1\u6838\u7684\u53C2\u4E0E\u8005"
642
691
  }
643
692
  ];
644
693
  var UPDATE_EXAMPLES2 = [
@@ -646,6 +695,7 @@ var UPDATE_EXAMPLES2 = [
646
695
  ];
647
696
  var LIST_EXAMPLES2 = [
648
697
  { command: "pdlab post list --project-id proj_123", note: "\u53EA\u770B\u67D0\u4E2A\u9879\u76EE\u4E0B\u7684\u5185\u5BB9" },
698
+ { command: "pdlab post list --project-id none", note: "\u53EA\u770B\u72EC\u7ACB\u53D1\u5E03\uFF08\u4E0D\u6302\u4EFB\u4F55\u9879\u76EE\uFF09\u7684\u5185\u5BB9" },
649
699
  { command: "pdlab post list --status pending", note: "\u67E5\u770B\u5F85\u5BA1\u6838\u5185\u5BB9\uFF0C\u9700\u8981 content:review \u6743\u9650\uFF0C\u5426\u5219 403" },
650
700
  { command: "pdlab post list --limit 10 --cursor <\u4E0A\u4E00\u9875\u8FD4\u56DE\u7684 nextCursor>", note: "\u7FFB\u9875\uFF1BnextCursor \u4E3A null \u8868\u793A\u6CA1\u6709\u4E0B\u4E00\u9875\u4E86" }
651
701
  ];
@@ -670,7 +720,7 @@ function toMediaLinks(value) {
670
720
  function registerPostCommand(program2) {
671
721
  const post = program2.command("post").description("\u5185\u5BB9\uFF08\u5E16\u5B50\uFF09\u7684\u589E\u5220\u6539\u67E5\u4E0E\u5BA1\u6838");
672
722
  attachMeta(
673
- withApiUrl(post.command("list").description("\u5217\u51FA\u5185\u5BB9\uFF08approved \u5185\u5BB9\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528\uFF09")).option("--project-id <id>", "\u6309\u9879\u76EE\u7B5B\u9009").option("--status <status>", "pending | approved | rejected\uFF08\u67E5\u770B\u975E approved \u9700\u8981\u5BA1\u6838\u6743\u9650\uFF09").option("--limit <n>", "\u5355\u9875\u6570\u91CF\uFF0C\u9ED8\u8BA4 30\uFF0C\u4E0A\u9650 100").option("--cursor <token>", "\u7FFB\u9875\u6E38\u6807\uFF0C\u53D6\u4E0A\u4E00\u9875\u54CD\u5E94\u91CC\u7684 nextCursor").action(async (opts) => {
723
+ withApiUrl(post.command("list").description("\u5217\u51FA\u5185\u5BB9\uFF08approved \u5185\u5BB9\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528\uFF09")).option("--project-id <id>", "\u6309\u9879\u76EE\u7B5B\u9009\uFF1B\u4F20 none \u53EA\u770B\u72EC\u7ACB\u53D1\u5E03\uFF08\u4E0D\u6302\u9879\u76EE\uFF09\u7684\u5185\u5BB9").option("--status <status>", "pending | approved | rejected\uFF08\u67E5\u770B\u975E approved \u9700\u8981\u5BA1\u6838\u6743\u9650\uFF09").option("--limit <n>", "\u5355\u9875\u6570\u91CF\uFF0C\u9ED8\u8BA4 30\uFF0C\u4E0A\u9650 100").option("--cursor <token>", "\u7FFB\u9875\u6E38\u6807\uFF0C\u53D6\u4E0A\u4E00\u9875\u54CD\u5E94\u91CC\u7684 nextCursor").action(async (opts) => {
674
724
  const data = await apiRequest("/api/posts", {
675
725
  query: { projectId: opts.projectId, status: opts.status, limit: opts.limit, cursor: opts.cursor },
676
726
  token: optionalToken(),
@@ -690,7 +740,7 @@ function registerPostCommand(program2) {
690
740
  { examples: GET_EXAMPLES2 }
691
741
  );
692
742
  attachMeta(
693
- withApiUrl(post.command("create").description("\u53D1\u5E03\u5185\u5BB9")).option("--title <title>", "\u5185\u5BB9\u6807\u9898\uFF08\u5FC5\u586B\uFF09").option("--body <body>", "\u5185\u5BB9\u6B63\u6587\uFF08\u5FC5\u586B\uFF09").option("--project-id <id>", "\u6240\u5C5E\u9879\u76EE id\uFF08\u5FC5\u586B\uFF09").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u5A92\u4F53\u94FE\u63A5\uFF08\u9009\u586B\uFF0C\u6700\u591A 20 \u6761\uFF0Chttp/https\uFF09").action(async (opts) => {
743
+ withApiUrl(post.command("create").description("\u53D1\u5E03\u5185\u5BB9")).option("--title <title>", "\u5185\u5BB9\u6807\u9898\uFF08\u5FC5\u586B\uFF09").option("--body <body>", "\u5185\u5BB9\u6B63\u6587\uFF08\u5FC5\u586B\uFF09").option("--project-id <id>", "\u6240\u5C5E\u9879\u76EE id\uFF08\u9009\u586B\uFF0C\u4E0D\u586B\u5373\u72EC\u7ACB\u53D1\u5E03\uFF09").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u56FE\u7247/\u89C6\u9891/\u5916\u94FE\u5730\u5740\uFF08\u9009\u586B\uFF0C\u6700\u591A 20 \u6761\uFF09").action(async (opts) => {
694
744
  const token = requireToken();
695
745
  try {
696
746
  const body = postCreateSchema.parse({
@@ -705,10 +755,10 @@ function registerPostCommand(program2) {
705
755
  handleCommandError(error, CREATE_EXAMPLES2);
706
756
  }
707
757
  }),
708
- { permission: "content:create\uFF0C\u4E14\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u62A5\u540D\u5171\u5EFA\u8BE5\u9879\u76EE", examples: CREATE_EXAMPLES2 }
758
+ { permission: "content:create\uFF1B\u5E26 --project-id \u65F6\u8FD8\u9700\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u901A\u8FC7\u5BA1\u6838\u7684\u53C2\u4E0E\u8005", examples: CREATE_EXAMPLES2 }
709
759
  );
710
760
  attachMeta(
711
- withApiUrl(post.command("update <id>").description("\u7F16\u8F91\u5185\u5BB9\uFF08\u4F5C\u8005\u672C\u4EBA\uFF0C\u6216\u6709\u7F16\u8F91\u4EFB\u610F\u5185\u5BB9\u7684\u6743\u9650\uFF09")).option("--title <title>", "\u5185\u5BB9\u6807\u9898\uFF08\u5FC5\u586B\uFF09").option("--body <body>", "\u5185\u5BB9\u6B63\u6587\uFF08\u5FC5\u586B\uFF09").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u5A92\u4F53\u94FE\u63A5\uFF08\u9009\u586B\uFF0C\u6700\u591A 20 \u6761\uFF0Chttp/https\uFF09").action(async (id, opts) => {
761
+ withApiUrl(post.command("update <id>").description("\u7F16\u8F91\u5185\u5BB9\uFF08\u4F5C\u8005\u672C\u4EBA\uFF0C\u6216\u6709\u7F16\u8F91\u4EFB\u610F\u5185\u5BB9\u7684\u6743\u9650\uFF09")).option("--title <title>", "\u5185\u5BB9\u6807\u9898\uFF08\u5FC5\u586B\uFF09").option("--body <body>", "\u5185\u5BB9\u6B63\u6587\uFF08\u5FC5\u586B\uFF09").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u56FE\u7247/\u89C6\u9891/\u5916\u94FE\u5730\u5740\uFF08\u9009\u586B\uFF0C\u6700\u591A 20 \u6761\uFF09").action(async (id, opts) => {
712
762
  const token = requireToken();
713
763
  try {
714
764
  const body = postUpdateSchema.parse({
@@ -749,6 +799,163 @@ function registerPostCommand(program2) {
749
799
  );
750
800
  }
751
801
 
802
+ // src/commands/taxonomy.ts
803
+ var PERMISSION = "taxonomy:manage\uFF08\u4EC5\u300C1836\u53D1\u8D77\u4EBA\u300D\u89D2\u8272\uFF09";
804
+ var DIM_LIST_EXAMPLES = [
805
+ { command: "pdlab taxonomy dimension list", note: "\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528" }
806
+ ];
807
+ var DIM_CREATE_EXAMPLES = [
808
+ {
809
+ command: 'pdlab taxonomy dimension create --key region --label "\u5730\u533A" --sort-order 3',
810
+ note: "key \u53EA\u80FD\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF\u4E14\u4EE5\u5B57\u6BCD\u5F00\u5934\uFF0C\u5EFA\u597D\u4E4B\u540E\u4E0D\u80FD\u6539"
811
+ }
812
+ ];
813
+ var DIM_UPDATE_EXAMPLES = [
814
+ { command: 'pdlab taxonomy dimension update domain --label "\u9886\u57DF\uFF08\u66F4\u65B0\uFF09"', note: "key \u4E0D\u53EF\u6539\uFF0C\u53EA\u80FD\u6539\u5C55\u793A\u5C5E\u6027" }
815
+ ];
816
+ var DIM_DELETE_EXAMPLES = [
817
+ {
818
+ command: "pdlab taxonomy dimension delete region",
819
+ note: "\u5185\u7F6E\u7EF4\u5EA6\uFF08domain/attribute/commercial\uFF09\u4E0D\u53EF\u5220\uFF1B\u7EF4\u5EA6\u4E0B\u8FD8\u6709\u6807\u7B7E\u65F6\u4F1A 409"
820
+ }
821
+ ];
822
+ var LIST_EXAMPLES3 = [{ command: "pdlab taxonomy list", note: "\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528" }];
823
+ var CREATE_EXAMPLES3 = [
824
+ {
825
+ command: 'pdlab taxonomy create --dimension domain --label "\u94A0\u7535\u56FA\u6001\u5316" --weight 0.2',
826
+ note: "dimension \u5FC5\u987B\u662F\u5DF2\u5B58\u5728\u7684\u7EF4\u5EA6 key\uFF1Bweight \u662F\u53D1\u8D77\u9879\u76EE\u65F6\u9884\u586B\u7ED9\u53D1\u8D77\u4EBA\u7684\u5EFA\u8BAE\u503C\uFF0C\u4E0D\u662F\u6700\u7EC8\u53C2\u4E0E\u8BA1\u7B97\u7684\u90A3\u4EFD"
827
+ }
828
+ ];
829
+ var UPDATE_EXAMPLES3 = [
830
+ { command: "pdlab taxonomy update tax_123 --weight 0.3", note: "\u53EA\u4F20\u8981\u6539\u7684\u5B57\u6BB5" }
831
+ ];
832
+ var DELETE_EXAMPLES3 = [{ command: "pdlab taxonomy delete tax_123" }];
833
+ function toDimensionBody(opts) {
834
+ const body = {};
835
+ if (opts.key !== void 0) body.key = opts.key;
836
+ if (opts.label !== void 0) body.label = opts.label;
837
+ if (opts.description !== void 0) body.description = opts.description;
838
+ if (opts.sortOrder !== void 0) body.sortOrder = Number(opts.sortOrder);
839
+ return body;
840
+ }
841
+ function toTaxonomyBody(opts) {
842
+ const body = {};
843
+ if (opts.dimension !== void 0) body.dimension = opts.dimension;
844
+ if (opts.label !== void 0) body.label = opts.label;
845
+ if (opts.weight !== void 0) body.weight = Number(opts.weight);
846
+ if (opts.sortOrder !== void 0) body.sortOrder = Number(opts.sortOrder);
847
+ if (opts.description !== void 0) body.description = opts.description;
848
+ return body;
849
+ }
850
+ function registerTaxonomyCommand(program2) {
851
+ const taxonomy = program2.command("taxonomy").description("\u5206\u7C7B\u7EF4\u5EA6\u4E0E\u5206\u7C7B\u6807\u7B7E\u7684\u589E\u5220\u6539\u67E5\uFF08PRD 4.2.4\uFF09");
852
+ const dimension = taxonomy.command("dimension").description("\u5206\u7C7B\u7EF4\u5EA6\uFF08\u9886\u57DF/\u5C5E\u6027/\u5546\u4E1A\u2026\u2026\uFF09\u7684\u589E\u5220\u6539\u67E5");
853
+ attachMeta(
854
+ withApiUrl(dimension.command("list").description("\u5217\u51FA\u5168\u90E8\u5206\u7C7B\u7EF4\u5EA6\uFF08\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528\uFF09")).action(
855
+ async (opts) => {
856
+ const data = await apiRequest("/api/taxonomy-dimensions", { token: optionalToken(), apiUrl: opts.apiUrl });
857
+ console.log(JSON.stringify(data, null, 2));
858
+ }
859
+ ),
860
+ { examples: DIM_LIST_EXAMPLES }
861
+ );
862
+ attachMeta(
863
+ withApiUrl(dimension.command("create").description("\u65B0\u5EFA\u5206\u7C7B\u7EF4\u5EA6")).option("--key <key>", "\u7EF4\u5EA6\u6807\u8BC6\uFF08\u5FC5\u586B\uFF0C\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF\uFF0C\u4EE5\u5B57\u6BCD\u5F00\u5934\uFF0C\u521B\u5EFA\u540E\u4E0D\u53EF\u6539\uFF09").option("--label <label>", "\u7EF4\u5EA6\u4E2D\u6587\u540D\uFF08\u5FC5\u586B\uFF09").option("--description <text>", "\u7EF4\u5EA6\u8BF4\u660E\uFF08\u9009\u586B\uFF09").option("--sort-order <n>", "\u5C55\u793A\u6392\u5E8F\uFF0C\u6574\u6570 0-999\uFF08\u9009\u586B\uFF09").action(async (opts) => {
864
+ const token = requireToken();
865
+ try {
866
+ const body = taxonomyDimensionCreateSchema.parse(toDimensionBody(opts));
867
+ const data = await apiRequest("/api/taxonomy-dimensions", {
868
+ method: "POST",
869
+ body,
870
+ token,
871
+ apiUrl: opts.apiUrl
872
+ });
873
+ console.log(JSON.stringify(data, null, 2));
874
+ } catch (error) {
875
+ handleCommandError(error, DIM_CREATE_EXAMPLES);
876
+ }
877
+ }),
878
+ { permission: PERMISSION, examples: DIM_CREATE_EXAMPLES }
879
+ );
880
+ attachMeta(
881
+ withApiUrl(dimension.command("update <key>").description("\u66F4\u65B0\u5206\u7C7B\u7EF4\u5EA6\u7684\u5C55\u793A\u5C5E\u6027\uFF08key \u672C\u8EAB\u4E0D\u53EF\u6539\uFF09")).option("--label <label>", "\u7EF4\u5EA6\u4E2D\u6587\u540D").option("--description <text>", "\u7EF4\u5EA6\u8BF4\u660E").option("--sort-order <n>", "\u5C55\u793A\u6392\u5E8F\uFF0C\u6574\u6570 0-999").action(async (key, opts) => {
882
+ const token = requireToken();
883
+ try {
884
+ const body = taxonomyDimensionUpdateSchema.parse(toDimensionBody(opts));
885
+ const data = await apiRequest(`/api/taxonomy-dimensions/${key}`, {
886
+ method: "PATCH",
887
+ body,
888
+ token,
889
+ apiUrl: opts.apiUrl
890
+ });
891
+ console.log(JSON.stringify(data, null, 2));
892
+ } catch (error) {
893
+ handleCommandError(error, DIM_UPDATE_EXAMPLES);
894
+ }
895
+ }),
896
+ { permission: PERMISSION, examples: DIM_UPDATE_EXAMPLES }
897
+ );
898
+ attachMeta(
899
+ withApiUrl(
900
+ dimension.command("delete <key>").description("\u5220\u9664\u5206\u7C7B\u7EF4\u5EA6\uFF08\u5185\u7F6E\u7EF4\u5EA6\u4E0D\u53EF\u5220\uFF1B\u7EF4\u5EA6\u4E0B\u8FD8\u6709\u6807\u7B7E\u65F6\u4F1A 409\uFF09")
901
+ ).action(async (key, opts) => {
902
+ const token = requireToken();
903
+ const data = await apiRequest(`/api/taxonomy-dimensions/${key}`, {
904
+ method: "DELETE",
905
+ token,
906
+ apiUrl: opts.apiUrl
907
+ });
908
+ console.log(JSON.stringify(data, null, 2));
909
+ }),
910
+ { permission: PERMISSION, examples: DIM_DELETE_EXAMPLES }
911
+ );
912
+ attachMeta(
913
+ withApiUrl(taxonomy.command("list").description("\u5217\u51FA\u5168\u90E8\u5206\u7C7B\u6807\u7B7E\uFF08\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528\uFF09")).action(
914
+ async (opts) => {
915
+ const data = await apiRequest("/api/taxonomies", { token: optionalToken(), apiUrl: opts.apiUrl });
916
+ console.log(JSON.stringify(data, null, 2));
917
+ }
918
+ ),
919
+ { examples: LIST_EXAMPLES3 }
920
+ );
921
+ attachMeta(
922
+ withApiUrl(taxonomy.command("create").description("\u65B0\u5EFA\u5206\u7C7B\u6807\u7B7E")).option("--dimension <key>", "\u6240\u5C5E\u7EF4\u5EA6\u7684 key\uFF08\u5FC5\u586B\uFF0C\u987B\u662F\u5DF2\u5B58\u5728\u7684\u7EF4\u5EA6\uFF09").option("--label <label>", "\u6807\u7B7E\u503C\uFF08\u5FC5\u586B\uFF09").option("--weight <n>", "\u5EFA\u8BAE\u6743\u91CD 0~1\uFF08\u9009\u586B\uFF0C\u9ED8\u8BA4 0\uFF09").option("--sort-order <n>", "\u5C55\u793A\u6392\u5E8F\uFF0C\u6574\u6570 0-999\uFF08\u9009\u586B\uFF09").option("--description <text>", "\u6807\u7B7E\u8BF4\u660E\uFF08\u9009\u586B\uFF09").action(async (opts) => {
923
+ const token = requireToken();
924
+ try {
925
+ const body = taxonomyCreateSchema.parse(toTaxonomyBody(opts));
926
+ const data = await apiRequest("/api/taxonomies", { method: "POST", body, token, apiUrl: opts.apiUrl });
927
+ console.log(JSON.stringify(data, null, 2));
928
+ } catch (error) {
929
+ handleCommandError(error, CREATE_EXAMPLES3);
930
+ }
931
+ }),
932
+ { permission: PERMISSION, examples: CREATE_EXAMPLES3 }
933
+ );
934
+ attachMeta(
935
+ withApiUrl(taxonomy.command("update <id>").description("\u66F4\u65B0\u5206\u7C7B\u6807\u7B7E")).option("--dimension <key>", "\u6240\u5C5E\u7EF4\u5EA6\u7684 key").option("--label <label>", "\u6807\u7B7E\u503C").option("--weight <n>", "\u5EFA\u8BAE\u6743\u91CD 0~1").option("--sort-order <n>", "\u5C55\u793A\u6392\u5E8F").option("--description <text>", "\u6807\u7B7E\u8BF4\u660E").action(async (id, opts) => {
936
+ const token = requireToken();
937
+ try {
938
+ const body = taxonomyUpdateSchema.parse(toTaxonomyBody(opts));
939
+ const data = await apiRequest(`/api/taxonomies/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
940
+ console.log(JSON.stringify(data, null, 2));
941
+ } catch (error) {
942
+ handleCommandError(error, UPDATE_EXAMPLES3);
943
+ }
944
+ }),
945
+ { permission: PERMISSION, examples: UPDATE_EXAMPLES3 }
946
+ );
947
+ attachMeta(
948
+ withApiUrl(taxonomy.command("delete <id>").description("\u5220\u9664\u5206\u7C7B\u6807\u7B7E")).action(
949
+ async (id, opts) => {
950
+ const token = requireToken();
951
+ const data = await apiRequest(`/api/taxonomies/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
952
+ console.log(JSON.stringify(data, null, 2));
953
+ }
954
+ ),
955
+ { permission: PERMISSION, examples: DELETE_EXAMPLES3 }
956
+ );
957
+ }
958
+
752
959
  // src/commands/schema.ts
753
960
  var CODE_DESCRIPTION = {
754
961
  ok: "\u6210\u529F",
@@ -768,6 +975,9 @@ function exitCodeTable() {
768
975
  }
769
976
  return table;
770
977
  }
978
+ function isInternalCommand(command) {
979
+ return command.name().startsWith("__");
980
+ }
771
981
  function serialize(command) {
772
982
  const meta = getMeta(command);
773
983
  return {
@@ -777,7 +987,7 @@ function serialize(command) {
777
987
  arguments: command.registeredArguments.map((a) => ({ name: a.name(), required: a.required })),
778
988
  options: command.options.map((o) => ({ flags: o.flags, description: o.description, required: o.mandatory })),
779
989
  examples: meta.examples ?? [],
780
- subcommands: command.commands.map(serialize)
990
+ subcommands: command.commands.filter((c) => !isInternalCommand(c)).map(serialize)
781
991
  };
782
992
  }
783
993
  function registerSchemaCommand(program2) {
@@ -786,7 +996,7 @@ function registerSchemaCommand(program2) {
786
996
  JSON.stringify(
787
997
  {
788
998
  exitCodes: exitCodeTable(),
789
- commands: program2.commands.map(serialize)
999
+ commands: program2.commands.filter((c) => !isInternalCommand(c)).map(serialize)
790
1000
  },
791
1001
  null,
792
1002
  2
@@ -795,8 +1005,96 @@ function registerSchemaCommand(program2) {
795
1005
  });
796
1006
  }
797
1007
 
1008
+ // src/update-check.ts
1009
+ var import_fs2 = require("fs");
1010
+ var import_child_process = require("child_process");
1011
+ var import_path2 = require("path");
1012
+ var CACHE_FILE = (0, import_path2.join)(CONFIG_DIR, "update-check.json");
1013
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
1014
+ var FETCH_TIMEOUT_MS = 3e3;
1015
+ function readUpdateCache() {
1016
+ if (!(0, import_fs2.existsSync)(CACHE_FILE)) return { lastCheckedAt: 0 };
1017
+ try {
1018
+ return JSON.parse((0, import_fs2.readFileSync)(CACHE_FILE, "utf8"));
1019
+ } catch {
1020
+ return { lastCheckedAt: 0 };
1021
+ }
1022
+ }
1023
+ function writeUpdateCache(cache) {
1024
+ if (!(0, import_fs2.existsSync)(CONFIG_DIR)) (0, import_fs2.mkdirSync)(CONFIG_DIR, { recursive: true, mode: 448 });
1025
+ (0, import_fs2.writeFileSync)(CACHE_FILE, JSON.stringify(cache, null, 2));
1026
+ }
1027
+ function parseVersion(version) {
1028
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
1029
+ if (!match) return null;
1030
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
1031
+ }
1032
+ function isNewerVersion(candidate, current) {
1033
+ const a = parseVersion(candidate);
1034
+ const b = parseVersion(current);
1035
+ if (!a || !b) return false;
1036
+ for (let i = 0; i < 3; i++) {
1037
+ if (a[i] !== b[i]) return a[i] > b[i];
1038
+ }
1039
+ return false;
1040
+ }
1041
+ async function fetchLatestVersion(packageName) {
1042
+ const controller = new AbortController();
1043
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
1044
+ try {
1045
+ const res = await fetch(`https://registry.npmjs.org/-/package/${packageName}/dist-tags`, {
1046
+ signal: controller.signal
1047
+ });
1048
+ if (!res.ok) return null;
1049
+ const data = await res.json();
1050
+ return data.latest ?? null;
1051
+ } catch {
1052
+ return null;
1053
+ } finally {
1054
+ clearTimeout(timer);
1055
+ }
1056
+ }
1057
+ async function refreshUpdateCache(packageName) {
1058
+ const latestVersion = await fetchLatestVersion(packageName);
1059
+ const previous = readUpdateCache();
1060
+ writeUpdateCache({
1061
+ lastCheckedAt: Date.now(),
1062
+ latestVersion: latestVersion ?? previous.latestVersion
1063
+ });
1064
+ }
1065
+ function spawnBackgroundRefresh(packageName) {
1066
+ try {
1067
+ const entry = process.argv[1];
1068
+ if (!entry) return;
1069
+ const child = (0, import_child_process.spawn)(process.execPath, [entry, "__update-check-worker", packageName], {
1070
+ detached: true,
1071
+ stdio: "ignore"
1072
+ });
1073
+ child.unref();
1074
+ } catch {
1075
+ }
1076
+ }
1077
+ function notifyIfUpdateAvailable(currentVersion, packageName) {
1078
+ if (process.env.PDLAB_NO_UPDATE_CHECK) return;
1079
+ try {
1080
+ const cache = readUpdateCache();
1081
+ if (cache.latestVersion && isNewerVersion(cache.latestVersion, currentVersion)) {
1082
+ console.error(
1083
+ `
1084
+ \u203B ${packageName} \u6709\u65B0\u7248\u672C\u53EF\u7528\uFF1A${currentVersion} \u2192 ${cache.latestVersion}
1085
+ \u8FD0\u884C npm install -g ${packageName}@latest \u5347\u7EA7\uFF08\u53EF\u7528 PDLAB_NO_UPDATE_CHECK=1 \u5173\u95ED\u6B64\u63D0\u793A\uFF09
1086
+ `
1087
+ );
1088
+ }
1089
+ if (Date.now() - cache.lastCheckedAt > CHECK_INTERVAL_MS) {
1090
+ spawnBackgroundRefresh(packageName);
1091
+ }
1092
+ } catch {
1093
+ }
1094
+ }
1095
+
798
1096
  // src/index.ts
799
- var pkg = JSON.parse((0, import_fs2.readFileSync)((0, import_path2.join)(__dirname, "../package.json"), "utf8"));
1097
+ var pkg = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)(__dirname, "../package.json"), "utf8"));
800
1098
  var program = new import_commander2.Command();
801
1099
  program.name("pdlab").description("1836 \u5F00\u6E90\u5171\u5EFA\u5E73\u53F0\u547D\u4EE4\u884C\u5DE5\u5177\u2014\u2014\u662F\u73B0\u6709 REST API \u7684\u8584\u5C01\u88C5\u3002\u7ED9 agent/\u811A\u672C\u7528\uFF1Apdlab schema \u4E00\u6B21\u6027\u5217\u51FA\u5168\u90E8\u547D\u4EE4\u3001\u53C2\u6570\u4E0E\u9000\u51FA\u7801\u542B\u4E49\u3002").version(pkg.version);
802
1100
  program.exitOverride();
@@ -809,7 +1107,13 @@ registerWhoamiCommand(program);
809
1107
  registerConfigCommand(program);
810
1108
  registerProjectCommand(program);
811
1109
  registerPostCommand(program);
1110
+ registerTaxonomyCommand(program);
812
1111
  registerSchemaCommand(program);
1112
+ program.command("__update-check-worker <packageName>", { hidden: true }).action(async (packageName) => {
1113
+ await refreshUpdateCache(packageName);
1114
+ process.exit(0);
1115
+ });
1116
+ notifyIfUpdateAvailable(pkg.version, "pdlab-cli");
813
1117
  program.parseAsync(process.argv).catch((error) => {
814
1118
  if (error instanceof import_commander2.CommanderError && error.exitCode === 0) {
815
1119
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdlab-cli",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "1836 开源共建平台(problem-driven-lab)的命令行工具:项目、内容的增删改查,浏览器授权登录",
6
6
  "keywords": [