pdlab-cli 0.1.2 → 0.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.
- package/README.md +51 -2
- package/dist/index.js +418 -117
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ pdlab login --api-url https://your-1836-instance.example.com
|
|
|
33
33
|
```bash
|
|
34
34
|
pdlab whoami # 看看当前是谁
|
|
35
35
|
pdlab project list # 列出项目
|
|
36
|
+
pdlab schema # 一次性 JSON 输出全部命令、参数、权限要求、示例和退出码含义——给 agent/脚本用
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
## 命令
|
|
@@ -44,20 +45,36 @@ pdlab project list # 列出项目
|
|
|
44
45
|
| `pdlab logout` | 清除本地凭证(不撤销服务端的,见下方「撤销凭证」) |
|
|
45
46
|
| `pdlab whoami` | 查看当前登录账号 |
|
|
46
47
|
| `pdlab config get` / `set api-url <url>` | 查看/修改本地配置 |
|
|
48
|
+
| `pdlab schema` | JSON 输出完整命令树 + 权限要求 + 示例 + 退出码含义 |
|
|
47
49
|
| `pdlab project list \| get \| create \| update \| delete` | 项目的增删改查 |
|
|
50
|
+
| `pdlab project join \| leave <id>` | 报名共建 / 撤回申请或退出共建 |
|
|
51
|
+
| `pdlab project member review \| set-role \| remove <projectId> <userId>` | 审核报名、设置协作者角色、移除参与者(仅项目发起人本人) |
|
|
52
|
+
| `pdlab project revenue <id>` | 查看项目的积分分成明细(只读) |
|
|
48
53
|
| `pdlab post list \| get \| create \| update \| delete` | 内容的增删改查 |
|
|
54
|
+
| `pdlab post review <id> --action approve\|reject` | 审核一条待审内容 |
|
|
49
55
|
|
|
50
|
-
任何命令加 `--help`
|
|
56
|
+
任何命令加 `--help` 看具体参数——示例已经直接打在 `--help` 末尾,不用等一次报错才能看到。
|
|
51
57
|
|
|
52
58
|
### 例子
|
|
53
59
|
|
|
54
60
|
```bash
|
|
55
|
-
#
|
|
61
|
+
# 按状态 / 关键词 / 分类标签筛选项目,翻页
|
|
56
62
|
pdlab project list --status active
|
|
63
|
+
pdlab project list --q "钠电"
|
|
64
|
+
pdlab project list --taxonomy tax_1 --taxonomy tax_2 # 可重复传,多个取交集
|
|
65
|
+
pdlab project list --limit 10 --cursor <上一页返回的 nextCursor>
|
|
57
66
|
|
|
58
67
|
# 创建项目(需要项目创建权限,即「1836发起人」角色)
|
|
59
68
|
pdlab project create --title "钠电储能原型" --description "第一阶段验证"
|
|
60
69
|
|
|
70
|
+
# 报名共建 / 退出
|
|
71
|
+
pdlab project join proj_123
|
|
72
|
+
pdlab project leave proj_123
|
|
73
|
+
|
|
74
|
+
# 项目发起人审核报名、提拔协作者
|
|
75
|
+
pdlab project member review proj_123 user_456 --status approved
|
|
76
|
+
pdlab project member set-role proj_123 user_456 --role maintainer
|
|
77
|
+
|
|
61
78
|
# 往自己参与的项目发布内容(共建者发布后进待审队列)
|
|
62
79
|
pdlab post create \
|
|
63
80
|
--project-id <项目 id> \
|
|
@@ -67,8 +84,40 @@ pdlab post create \
|
|
|
67
84
|
|
|
68
85
|
# 只看某个项目下的内容
|
|
69
86
|
pdlab post list --project-id <项目 id>
|
|
87
|
+
|
|
88
|
+
# 审核待审内容(需要 content:review 权限)
|
|
89
|
+
pdlab post review post_123 --action approve
|
|
90
|
+
pdlab post review post_123 --action reject --comment "缺少数据来源,请补充引用"
|
|
70
91
|
```
|
|
71
92
|
|
|
93
|
+
### 分页
|
|
94
|
+
|
|
95
|
+
`project list` / `post list` 默认单页 30 条(上限 100),响应里的 `nextCursor` 非 `null`
|
|
96
|
+
就表示还有下一页,把它传给下一次调用的 `--cursor` 继续翻页;`nextCursor` 为 `null`
|
|
97
|
+
表示已经是最后一页。CLI 不会替你自动拉全量——那样一次调用可能悄悄发出几十次请求。
|
|
98
|
+
|
|
99
|
+
### 报错与退出码
|
|
100
|
+
|
|
101
|
+
失败时,一个 JSON 对象会打到 stderr(不是人类可读的长句),方便脚本/agent 解析:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{ "error": "无权限执行此操作", "code": "forbidden", "status": 403 }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
校验类错误还会带上 `fields`(哪个字段、什么问题)和 `hint`(对应命令的示例)。
|
|
108
|
+
退出码和 `code` 一一对应,`pdlab schema` 的 `exitCodes` 字段里也有同一份:
|
|
109
|
+
|
|
110
|
+
| 退出码 | `code` | 含义 | 建议的处理 |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| 0 | — | 成功 | — |
|
|
113
|
+
| 2 | `validation` | 参数校验失败(本地或服务端) | 按 `fields`/`hint` 改参数重试 |
|
|
114
|
+
| 3 | `unauthenticated` | 未登录或 token 已失效 | 跑 `pdlab login` |
|
|
115
|
+
| 4 | `forbidden` | 无权限 | 不要重试,告知用户 |
|
|
116
|
+
| 5 | `not_found` | 资源不存在 | 检查 id 是否正确 |
|
|
117
|
+
| 6 | `conflict` | 状态冲突(如重复审核) | 不要重试,状态已经变了 |
|
|
118
|
+
| 7 | `network` | 连不上 API 服务器 | 检查 `--api-url`/网络后重试 |
|
|
119
|
+
| 1 | `unknown` / 未分类 | 其他 | 按错误信息人工排查 |
|
|
120
|
+
|
|
72
121
|
## 配置
|
|
73
122
|
|
|
74
123
|
配置存在 `~/.pdlab/config.json`(目录 `0700`、文件 `0600`):
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,17 @@ var import_open = __toESM(require("open"));
|
|
|
35
35
|
var import_fs = require("fs");
|
|
36
36
|
var import_os = require("os");
|
|
37
37
|
var import_path = require("path");
|
|
38
|
+
|
|
39
|
+
// src/cli-error.ts
|
|
40
|
+
var CliError = class extends Error {
|
|
41
|
+
constructor(message, code = "unauthenticated") {
|
|
42
|
+
super(message);
|
|
43
|
+
this.code = code;
|
|
44
|
+
}
|
|
45
|
+
code;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/config.ts
|
|
38
49
|
var CONFIG_DIR = process.env.PDLAB_CONFIG_DIR ?? (0, import_path.join)((0, import_os.homedir)(), ".pdlab");
|
|
39
50
|
var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
|
|
40
51
|
var DEFAULT_API_URL = "https://1836.online";
|
|
@@ -65,28 +76,53 @@ function optionalToken() {
|
|
|
65
76
|
function requireToken() {
|
|
66
77
|
const token = readConfig().token;
|
|
67
78
|
if (!token) {
|
|
68
|
-
|
|
69
|
-
process.exit(1);
|
|
79
|
+
throw new CliError("\u5C1A\u672A\u767B\u5F55\u3002\u8BF7\u5148\u8FD0\u884C `pdlab login`\u3002");
|
|
70
80
|
}
|
|
71
81
|
return token;
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
// src/api-client.ts
|
|
85
|
+
function classifyStatus(status) {
|
|
86
|
+
switch (status) {
|
|
87
|
+
case 400:
|
|
88
|
+
case 422:
|
|
89
|
+
return "validation";
|
|
90
|
+
case 401:
|
|
91
|
+
return "unauthenticated";
|
|
92
|
+
case 403:
|
|
93
|
+
return "forbidden";
|
|
94
|
+
case 404:
|
|
95
|
+
return "not_found";
|
|
96
|
+
case 409:
|
|
97
|
+
return "conflict";
|
|
98
|
+
case 0:
|
|
99
|
+
return "network";
|
|
100
|
+
default:
|
|
101
|
+
return "unknown";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
75
104
|
var ApiRequestError = class extends Error {
|
|
76
105
|
constructor(message, status, details) {
|
|
77
106
|
super(message);
|
|
78
107
|
this.status = status;
|
|
79
108
|
this.details = details;
|
|
109
|
+
this.code = classifyStatus(status);
|
|
80
110
|
}
|
|
81
111
|
status;
|
|
82
112
|
details;
|
|
113
|
+
code;
|
|
83
114
|
};
|
|
84
115
|
async function apiRequest(path, options = {}) {
|
|
85
116
|
const apiUrl = resolveApiUrl(options.apiUrl);
|
|
86
117
|
const url = new URL(path.replace(/^\/+/, ""), apiUrl + "/");
|
|
87
118
|
if (options.query) {
|
|
88
119
|
for (const [key, value] of Object.entries(options.query)) {
|
|
89
|
-
if (value
|
|
120
|
+
if (value === void 0) continue;
|
|
121
|
+
if (Array.isArray(value)) {
|
|
122
|
+
for (const v of value) url.searchParams.append(key, v);
|
|
123
|
+
} else {
|
|
124
|
+
url.searchParams.set(key, value);
|
|
125
|
+
}
|
|
90
126
|
}
|
|
91
127
|
}
|
|
92
128
|
const headers = {};
|
|
@@ -304,41 +340,82 @@ var postReviewSchema = import_zod3.z.object({
|
|
|
304
340
|
|
|
305
341
|
// src/errors.ts
|
|
306
342
|
var import_zod4 = require("zod");
|
|
307
|
-
|
|
308
|
-
|
|
343
|
+
var EXIT_CODES = {
|
|
344
|
+
ok: 0,
|
|
345
|
+
unhandled: 1,
|
|
346
|
+
validation: 2,
|
|
347
|
+
unauthenticated: 3,
|
|
348
|
+
forbidden: 4,
|
|
349
|
+
not_found: 5,
|
|
350
|
+
conflict: 6,
|
|
351
|
+
network: 7,
|
|
352
|
+
unknown: 1
|
|
353
|
+
};
|
|
354
|
+
function fieldsFromZod(error) {
|
|
355
|
+
const fields = {};
|
|
309
356
|
for (const issue of error.issues) {
|
|
310
357
|
const path = issue.path.length > 0 ? issue.path.join(".") : "(\u6839)";
|
|
311
|
-
|
|
358
|
+
(fields[path] ??= []).push(issue.message);
|
|
312
359
|
}
|
|
313
|
-
|
|
360
|
+
return fields;
|
|
314
361
|
}
|
|
315
|
-
function
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
362
|
+
function fieldsFromApiDetails(details) {
|
|
363
|
+
if (!details || typeof details !== "object") return void 0;
|
|
364
|
+
const flat = details;
|
|
365
|
+
const fields = { ...flat.fieldErrors ?? {} };
|
|
366
|
+
if (flat.formErrors && flat.formErrors.length > 0) fields["(\u6839)"] = flat.formErrors;
|
|
367
|
+
return Object.keys(fields).length > 0 ? fields : void 0;
|
|
322
368
|
}
|
|
323
|
-
function
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const flat = error.details;
|
|
327
|
-
for (const [field, messages] of Object.entries(flat.fieldErrors ?? {})) {
|
|
328
|
-
for (const message of messages) console.error(` - ${field}: ${message}`);
|
|
329
|
-
}
|
|
330
|
-
for (const message of flat.formErrors ?? []) console.error(` - ${message}`);
|
|
331
|
-
}
|
|
369
|
+
function exampleHint(examples) {
|
|
370
|
+
if (examples.length === 0) return void 0;
|
|
371
|
+
return examples.map((e) => e.command).join(" | ");
|
|
332
372
|
}
|
|
333
|
-
function handleCommandError(error, examples) {
|
|
373
|
+
function handleCommandError(error, examples = []) {
|
|
374
|
+
let structured;
|
|
334
375
|
if (error instanceof import_zod4.ZodError) {
|
|
335
|
-
|
|
376
|
+
structured = {
|
|
377
|
+
error: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
|
|
378
|
+
code: "validation",
|
|
379
|
+
status: null,
|
|
380
|
+
fields: fieldsFromZod(error),
|
|
381
|
+
hint: exampleHint(examples)
|
|
382
|
+
};
|
|
336
383
|
} else if (error instanceof ApiRequestError) {
|
|
337
|
-
|
|
384
|
+
structured = {
|
|
385
|
+
error: error.message,
|
|
386
|
+
code: error.code,
|
|
387
|
+
status: error.status || null,
|
|
388
|
+
fields: fieldsFromApiDetails(error.details),
|
|
389
|
+
hint: exampleHint(examples)
|
|
390
|
+
};
|
|
391
|
+
} else if (error instanceof CliError) {
|
|
392
|
+
structured = { error: error.message, code: error.code, status: null, hint: "pdlab login" };
|
|
338
393
|
} else {
|
|
339
|
-
|
|
394
|
+
structured = {
|
|
395
|
+
error: error instanceof Error ? error.message : String(error),
|
|
396
|
+
code: "unhandled",
|
|
397
|
+
status: null
|
|
398
|
+
};
|
|
340
399
|
}
|
|
341
|
-
|
|
400
|
+
console.error(JSON.stringify(structured, null, 2));
|
|
401
|
+
process.exit(EXIT_CODES[structured.code] ?? 1);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/help-meta.ts
|
|
405
|
+
var META = /* @__PURE__ */ new WeakMap();
|
|
406
|
+
function attachMeta(command, meta) {
|
|
407
|
+
META.set(command, meta);
|
|
408
|
+
if (meta.examples && meta.examples.length > 0) {
|
|
409
|
+
command.addHelpText(
|
|
410
|
+
"after",
|
|
411
|
+
"\n\u793A\u4F8B\uFF1A\n" + meta.examples.map((e) => ` $ ${e.command}${e.note ? `
|
|
412
|
+
${e.note}` : ""}`).join("\n")
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
return command;
|
|
416
|
+
}
|
|
417
|
+
function getMeta(command) {
|
|
418
|
+
return META.get(command) ?? {};
|
|
342
419
|
}
|
|
343
420
|
|
|
344
421
|
// src/commands/options.ts
|
|
@@ -347,15 +424,50 @@ function withApiUrl(cmd) {
|
|
|
347
424
|
}
|
|
348
425
|
|
|
349
426
|
// src/commands/project.ts
|
|
427
|
+
var STATUS_LIST = PROJECT_STATUS_VALUES.join(" | ");
|
|
350
428
|
var CREATE_EXAMPLES = [
|
|
351
429
|
{
|
|
352
430
|
command: 'pdlab project create --title "\u94A0\u7535\u56DE\u6536\u5DE5\u827A\u4F18\u5316" --description "..." --status planning --taxonomy-ids tax_1,tax_2',
|
|
353
|
-
note: "title \u5FC5\u586B\uFF0C\u5176\u4F59\u5B57\u6BB5\u53EF\u7701\u7565"
|
|
431
|
+
note: "title \u5FC5\u586B\uFF0C\u5176\u4F59\u5B57\u6BB5\u53EF\u7701\u7565\uFF1B\u9700\u8981\u300C1836\u53D1\u8D77\u4EBA\u300D\u89D2\u8272\uFF08project:create \u6743\u9650\uFF09"
|
|
354
432
|
}
|
|
355
433
|
];
|
|
356
434
|
var UPDATE_EXAMPLES = [
|
|
357
435
|
{ command: "pdlab project update proj_123 --progress 60 --status active", note: "\u53EA\u4F20\u8981\u6539\u7684\u5B57\u6BB5" }
|
|
358
436
|
];
|
|
437
|
+
var LIST_EXAMPLES = [
|
|
438
|
+
{ command: "pdlab project list --status active", note: "\u6309\u72B6\u6001\u7B5B\u9009" },
|
|
439
|
+
{ command: 'pdlab project list --q "\u94A0\u7535"', note: "\u6309\u6807\u9898\u5173\u952E\u8BCD\u641C\u7D22" },
|
|
440
|
+
{ command: "pdlab project list --taxonomy tax_1 --taxonomy tax_2", note: "\u53EF\u91CD\u590D\u4F20\uFF0C\u591A\u4E2A\u6807\u7B7E\u53D6\u4EA4\u96C6" },
|
|
441
|
+
{ command: "pdlab project 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" }
|
|
442
|
+
];
|
|
443
|
+
var GET_EXAMPLES = [{ command: "pdlab project get proj_123" }];
|
|
444
|
+
var DELETE_EXAMPLES = [
|
|
445
|
+
{ command: "pdlab project delete proj_123", note: "\u9700\u8981\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\uFF0C\u4E14\u9879\u76EE\u4E0B\u6CA1\u6709\u5185\u5BB9/\u79EF\u5206\u8BB0\u5F55" }
|
|
446
|
+
];
|
|
447
|
+
var JOIN_EXAMPLES = [
|
|
448
|
+
{ command: "pdlab project join proj_123", note: "\u62A5\u540D\u5171\u5EFA\uFF0C\u8FDB\u5165\u5F85\u5BA1\u6838\uFF1B\u91CD\u590D\u8C03\u7528\u662F\u5E42\u7B49\u7684" }
|
|
449
|
+
];
|
|
450
|
+
var LEAVE_EXAMPLES = [
|
|
451
|
+
{ command: "pdlab project leave proj_123", note: "\u64A4\u56DE\u62A5\u540D\u7533\u8BF7\uFF0C\u6216\u9000\u51FA\u5DF2\u901A\u8FC7\u5BA1\u6838\u7684\u5171\u5EFA" }
|
|
452
|
+
];
|
|
453
|
+
var MEMBER_REVIEW_EXAMPLES = [
|
|
454
|
+
{
|
|
455
|
+
command: "pdlab project member review proj_123 user_456 --status approved",
|
|
456
|
+
note: "\u5BA1\u6838\u4E00\u6761 pending \u7684\u62A5\u540D\u7533\u8BF7\uFF1B\u53EA\u6709\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA\u80FD\u8C03\u7528"
|
|
457
|
+
}
|
|
458
|
+
];
|
|
459
|
+
var MEMBER_SET_ROLE_EXAMPLES = [
|
|
460
|
+
{
|
|
461
|
+
command: "pdlab project member set-role proj_123 user_456 --role maintainer",
|
|
462
|
+
note: "\u4EC5\u5BF9\u5DF2\u901A\u8FC7\u5BA1\u6838\uFF08approved\uFF09\u7684\u53C2\u4E0E\u8005\u751F\u6548\uFF1B\u53EA\u6709\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA\u80FD\u8C03\u7528"
|
|
463
|
+
}
|
|
464
|
+
];
|
|
465
|
+
var MEMBER_REMOVE_EXAMPLES = [
|
|
466
|
+
{ command: "pdlab project member remove proj_123 user_456", note: "\u53EA\u6709\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA\u80FD\u8C03\u7528" }
|
|
467
|
+
];
|
|
468
|
+
var REVENUE_EXAMPLES = [
|
|
469
|
+
{ command: "pdlab project revenue proj_123", note: "\u53EA\u8BFB\uFF0C\u9700\u8981 data:view_stats \u6743\u9650" }
|
|
470
|
+
];
|
|
359
471
|
function toBody(opts) {
|
|
360
472
|
const body = {};
|
|
361
473
|
if (opts.title !== void 0) body.title = opts.title;
|
|
@@ -370,26 +482,43 @@ function toBody(opts) {
|
|
|
370
482
|
return body;
|
|
371
483
|
}
|
|
372
484
|
function withProjectFlags(cmd) {
|
|
373
|
-
return withApiUrl(cmd).option("--title <title>", "\u9879\u76EE\u6807\u9898").option("--description <description>", "\u9879\u76EE\u63CF\u8FF0").option("--cover-image <url>", "\u5C01\u9762\u56FE http/https \u94FE\u63A5").option("--commercial-type <type>", "\u5546\u4E1A\u5C5E\u6027").option("--status <status>",
|
|
485
|
+
return withApiUrl(cmd).option("--title <title>", "\u9879\u76EE\u6807\u9898\uFF08\u5FC5\u586B\uFF0C1-200 \u5B57\uFF09").option("--description <description>", "\u9879\u76EE\u63CF\u8FF0\uFF08\u9009\u586B\uFF0C\u6700\u591A 20000 \u5B57\uFF09").option("--cover-image <url>", "\u5C01\u9762\u56FE http/https \u94FE\u63A5\uFF08\u9009\u586B\uFF09").option("--commercial-type <type>", "\u5546\u4E1A\u5C5E\u6027\uFF08\u9009\u586B\uFF09").option("--status <status>", `\u9879\u76EE\u72B6\u6001\uFF1A${STATUS_LIST}\uFF08\u9009\u586B\uFF09`).option("--progress <percent>", "\u8FDB\u5EA6\uFF0C\u6574\u6570 0-100\uFF08\u9009\u586B\uFF09").option("--taxonomy-ids <ids>", "\u9017\u53F7\u5206\u9694\u7684\u5206\u7C7B\u6807\u7B7E id \u5217\u8868\uFF0C\u5168\u91CF\u66FF\u6362\uFF08\u9009\u586B\uFF09");
|
|
486
|
+
}
|
|
487
|
+
function collect(value, previous) {
|
|
488
|
+
return previous.concat([value]);
|
|
374
489
|
}
|
|
375
490
|
function registerProjectCommand(program2) {
|
|
376
|
-
const project = program2.command("project").description("\u9879\u76EE\u7684\u589E\u5220\u6539\u67E5");
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
491
|
+
const project = program2.command("project").description("\u9879\u76EE\u7684\u589E\u5220\u6539\u67E5\u3001\u62A5\u540D\u5171\u5EFA\u3001\u6210\u5458\u7BA1\u7406\u3001\u6536\u76CA\u67E5\u8BE2");
|
|
492
|
+
attachMeta(
|
|
493
|
+
withApiUrl(project.command("list").description("\u5217\u51FA\u9879\u76EE\uFF08\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528\uFF09")).option("--status <status>", `\u6309\u72B6\u6001\u7B5B\u9009\uFF1A${STATUS_LIST}`).option("--q <keyword>", "\u6309\u6807\u9898\u5173\u952E\u8BCD\u641C\u7D22").option("--taxonomy <id>", "\u6309\u5206\u7C7B\u6807\u7B7E id \u7B5B\u9009\uFF0C\u53EF\u91CD\u590D\u4F20\uFF0C\u591A\u4E2A\u53D6\u4EA4\u96C6", collect, []).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(
|
|
494
|
+
async (opts) => {
|
|
495
|
+
const data = await apiRequest("/api/projects", {
|
|
496
|
+
query: {
|
|
497
|
+
status: opts.status,
|
|
498
|
+
q: opts.q,
|
|
499
|
+
taxonomy: opts.taxonomy.length > 0 ? opts.taxonomy : void 0,
|
|
500
|
+
limit: opts.limit,
|
|
501
|
+
cursor: opts.cursor
|
|
502
|
+
},
|
|
503
|
+
token: optionalToken(),
|
|
504
|
+
apiUrl: opts.apiUrl
|
|
505
|
+
});
|
|
506
|
+
console.log(JSON.stringify(data, null, 2));
|
|
507
|
+
}
|
|
508
|
+
),
|
|
509
|
+
{ examples: LIST_EXAMPLES }
|
|
390
510
|
);
|
|
391
|
-
|
|
392
|
-
|
|
511
|
+
attachMeta(
|
|
512
|
+
withApiUrl(project.command("get <id>").description("\u67E5\u770B\u9879\u76EE\u8BE6\u60C5\uFF08\u516C\u5F00\u53EA\u8BFB\uFF0C\u4E0D\u767B\u5F55\u4E5F\u80FD\u7528\uFF09")).action(
|
|
513
|
+
async (id, opts) => {
|
|
514
|
+
const data = await apiRequest(`/api/projects/${id}`, { token: optionalToken(), apiUrl: opts.apiUrl });
|
|
515
|
+
console.log(JSON.stringify(data, null, 2));
|
|
516
|
+
}
|
|
517
|
+
),
|
|
518
|
+
{ examples: GET_EXAMPLES }
|
|
519
|
+
);
|
|
520
|
+
attachMeta(
|
|
521
|
+
withProjectFlags(project.command("create").description("\u521B\u5EFA\u9879\u76EE")).action(async (opts) => {
|
|
393
522
|
const token = requireToken();
|
|
394
523
|
try {
|
|
395
524
|
const body = projectCreateSchema.parse(toBody(opts));
|
|
@@ -398,99 +527,275 @@ function registerProjectCommand(program2) {
|
|
|
398
527
|
} catch (error) {
|
|
399
528
|
handleCommandError(error, CREATE_EXAMPLES);
|
|
400
529
|
}
|
|
530
|
+
}),
|
|
531
|
+
{ permission: "project:create\uFF081836\u53D1\u8D77\u4EBA\u89D2\u8272\uFF09", examples: CREATE_EXAMPLES }
|
|
532
|
+
);
|
|
533
|
+
attachMeta(
|
|
534
|
+
withProjectFlags(project.command("update <id>").description("\u66F4\u65B0\u9879\u76EE")).action(
|
|
535
|
+
async (id, opts) => {
|
|
536
|
+
const token = requireToken();
|
|
537
|
+
try {
|
|
538
|
+
const body = projectUpdateSchema.parse(toBody(opts));
|
|
539
|
+
const data = await apiRequest(`/api/projects/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
|
|
540
|
+
console.log(JSON.stringify(data, null, 2));
|
|
541
|
+
} catch (error) {
|
|
542
|
+
handleCommandError(error, UPDATE_EXAMPLES);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
),
|
|
546
|
+
{
|
|
547
|
+
permission: "project:update_progress\uFF08\u53D1\u8D77\u4EBA\uFF09\u6216 project:join\uFF08\u534F\u4F5C\u8005\uFF0C\u4EC5\u80FD\u6539 progress/status/description\uFF09",
|
|
548
|
+
examples: UPDATE_EXAMPLES
|
|
401
549
|
}
|
|
402
550
|
);
|
|
403
|
-
|
|
404
|
-
|
|
551
|
+
attachMeta(
|
|
552
|
+
withApiUrl(
|
|
553
|
+
project.command("delete <id>").description("\u5220\u9664\u9879\u76EE\uFF08\u9700\u8981\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\uFF0C\u4E14\u9879\u76EE\u4E0B\u6CA1\u6709\u5185\u5BB9/\u79EF\u5206\u8BB0\u5F55\uFF09")
|
|
554
|
+
).action(async (id, opts) => {
|
|
405
555
|
const token = requireToken();
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
556
|
+
const data = await apiRequest(`/api/projects/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
557
|
+
console.log(JSON.stringify(data, null, 2));
|
|
558
|
+
}),
|
|
559
|
+
{ permission: "project:create\uFF081836\u53D1\u8D77\u4EBA\u89D2\u8272\uFF09\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: DELETE_EXAMPLES }
|
|
560
|
+
);
|
|
561
|
+
attachMeta(
|
|
562
|
+
withApiUrl(project.command("join <id>").description("\u62A5\u540D\u5171\u5EFA\u8BE5\u9879\u76EE\uFF0C\u8FDB\u5165\u5F85\u5BA1\u6838")).action(
|
|
563
|
+
async (id, opts) => {
|
|
564
|
+
const token = requireToken();
|
|
565
|
+
const data = await apiRequest(`/api/projects/${id}/join`, { method: "POST", token, apiUrl: opts.apiUrl });
|
|
409
566
|
console.log(JSON.stringify(data, null, 2));
|
|
410
|
-
} catch (error) {
|
|
411
|
-
handleCommandError(error, UPDATE_EXAMPLES);
|
|
412
567
|
}
|
|
413
|
-
|
|
568
|
+
),
|
|
569
|
+
{ permission: "project:join\uFF081836\u5171\u5EFA\u8005\u7B49\u89D2\u8272\uFF09", examples: JOIN_EXAMPLES }
|
|
570
|
+
);
|
|
571
|
+
attachMeta(
|
|
572
|
+
withApiUrl(project.command("leave <id>").description("\u64A4\u56DE\u62A5\u540D\u7533\u8BF7\uFF0C\u6216\u9000\u51FA\u5DF2\u901A\u8FC7\u5BA1\u6838\u7684\u5171\u5EFA")).action(
|
|
573
|
+
async (id, opts) => {
|
|
574
|
+
const token = requireToken();
|
|
575
|
+
const data = await apiRequest(`/api/projects/${id}/join`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
576
|
+
console.log(JSON.stringify(data, null, 2));
|
|
577
|
+
}
|
|
578
|
+
),
|
|
579
|
+
{ permission: "project:join\uFF081836\u5171\u5EFA\u8005\u7B49\u89D2\u8272\uFF09", examples: LEAVE_EXAMPLES }
|
|
580
|
+
);
|
|
581
|
+
const member = project.command("member").description("\u9879\u76EE\u53C2\u4E0E\u8005\u7684\u5BA1\u6838 / \u89D2\u8272 / \u79FB\u9664\uFF08\u4EC5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA\u53EF\u7528\uFF09");
|
|
582
|
+
attachMeta(
|
|
583
|
+
withApiUrl(member.command("review <projectId> <userId>").description("\u5BA1\u6838\u4E00\u6761 pending \u7684\u62A5\u540D\u7533\u8BF7")).requiredOption("--status <status>", "approved | rejected").action(async (projectId, userId, opts) => {
|
|
584
|
+
const token = requireToken();
|
|
585
|
+
const data = await apiRequest(`/api/projects/${projectId}/members/${userId}`, {
|
|
586
|
+
method: "PATCH",
|
|
587
|
+
body: { status: opts.status },
|
|
588
|
+
token,
|
|
589
|
+
apiUrl: opts.apiUrl
|
|
590
|
+
});
|
|
591
|
+
console.log(JSON.stringify(data, null, 2));
|
|
592
|
+
}),
|
|
593
|
+
{ permission: "project:update_progress\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: MEMBER_REVIEW_EXAMPLES }
|
|
594
|
+
);
|
|
595
|
+
attachMeta(
|
|
596
|
+
withApiUrl(member.command("set-role <projectId> <userId>").description("\u8BBE\u7F6E\u5DF2\u901A\u8FC7\u5BA1\u6838\u7684\u53C2\u4E0E\u8005\u7684\u9879\u76EE\u5185\u89D2\u8272")).requiredOption("--role <role>", "member | maintainer").action(async (projectId, userId, opts) => {
|
|
597
|
+
const token = requireToken();
|
|
598
|
+
const data = await apiRequest(`/api/projects/${projectId}/members/${userId}`, {
|
|
599
|
+
method: "PATCH",
|
|
600
|
+
body: { role: opts.role },
|
|
601
|
+
token,
|
|
602
|
+
apiUrl: opts.apiUrl
|
|
603
|
+
});
|
|
604
|
+
console.log(JSON.stringify(data, null, 2));
|
|
605
|
+
}),
|
|
606
|
+
{ permission: "project:update_progress\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: MEMBER_SET_ROLE_EXAMPLES }
|
|
607
|
+
);
|
|
608
|
+
attachMeta(
|
|
609
|
+
withApiUrl(member.command("remove <projectId> <userId>").description("\u79FB\u9664\u4E00\u4E2A\u53C2\u4E0E\u8005")).action(
|
|
610
|
+
async (projectId, userId, opts) => {
|
|
611
|
+
const token = requireToken();
|
|
612
|
+
const data = await apiRequest(`/api/projects/${projectId}/members/${userId}`, {
|
|
613
|
+
method: "DELETE",
|
|
614
|
+
token,
|
|
615
|
+
apiUrl: opts.apiUrl
|
|
616
|
+
});
|
|
617
|
+
console.log(JSON.stringify(data, null, 2));
|
|
618
|
+
}
|
|
619
|
+
),
|
|
620
|
+
{ permission: "project:update_progress\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: MEMBER_REMOVE_EXAMPLES }
|
|
621
|
+
);
|
|
622
|
+
attachMeta(
|
|
623
|
+
withApiUrl(project.command("revenue <id>").description("\u67E5\u770B\u9879\u76EE\u7684\u79EF\u5206\u5206\u6210\u660E\u7EC6\uFF08\u53EA\u8BFB\uFF09")).action(
|
|
624
|
+
async (id, opts) => {
|
|
625
|
+
const token = requireToken();
|
|
626
|
+
const data = await apiRequest(`/api/projects/${id}/revenue-breakdown`, { token, apiUrl: opts.apiUrl });
|
|
627
|
+
console.log(JSON.stringify(data, null, 2));
|
|
628
|
+
}
|
|
629
|
+
),
|
|
630
|
+
{ permission: "data:view_stats", examples: REVENUE_EXAMPLES }
|
|
414
631
|
);
|
|
415
|
-
withApiUrl(
|
|
416
|
-
project.command("delete <id>").description("\u5220\u9664\u9879\u76EE\uFF08\u9700\u8981\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\uFF0C\u4E14\u9879\u76EE\u4E0B\u6CA1\u6709\u5185\u5BB9/\u79EF\u5206\u8BB0\u5F55\uFF09")
|
|
417
|
-
).action(async (id, opts) => {
|
|
418
|
-
const token = requireToken();
|
|
419
|
-
const data = await apiRequest(`/api/projects/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
420
|
-
console.log(JSON.stringify(data, null, 2));
|
|
421
|
-
});
|
|
422
632
|
}
|
|
423
633
|
|
|
424
634
|
// src/commands/post.ts
|
|
425
635
|
var CREATE_EXAMPLES2 = [
|
|
426
636
|
{
|
|
427
637
|
command: 'pdlab post create --title "\u7B2C\u4E00\u5468\u8FDB\u5C55" --body "..." --project-id proj_123 --media-links https://example.com/a.png',
|
|
428
|
-
note: "title / body / project-id \u5FC5\u586B"
|
|
638
|
+
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"
|
|
639
|
+
}
|
|
640
|
+
];
|
|
641
|
+
var UPDATE_EXAMPLES2 = [
|
|
642
|
+
{ command: 'pdlab post update post_123 --title "..." --body "..."', note: "title \u548C body \u90FD\u5FC5\u987B\u4F20" }
|
|
643
|
+
];
|
|
644
|
+
var LIST_EXAMPLES2 = [
|
|
645
|
+
{ command: "pdlab post list --project-id proj_123", note: "\u53EA\u770B\u67D0\u4E2A\u9879\u76EE\u4E0B\u7684\u5185\u5BB9" },
|
|
646
|
+
{ 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" },
|
|
647
|
+
{ 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" }
|
|
648
|
+
];
|
|
649
|
+
var GET_EXAMPLES2 = [{ command: "pdlab post get post_123" }];
|
|
650
|
+
var DELETE_EXAMPLES2 = [
|
|
651
|
+
{ command: "pdlab post delete post_123", note: "\u4F5C\u8005\u672C\u4EBA\uFF0C\u6216\u6709\u5220\u9664\u4EFB\u610F\u5185\u5BB9\u7684\u6743\u9650" }
|
|
652
|
+
];
|
|
653
|
+
var REVIEW_EXAMPLES = [
|
|
654
|
+
{
|
|
655
|
+
command: "pdlab post review post_123 --action approve",
|
|
656
|
+
note: "\u901A\u8FC7\u5BA1\u6838\uFF1B\u4F5C\u8005\u4E0D\u80FD\u5BA1\u81EA\u5DF1\u53D1\u5E03\u7684\u5185\u5BB9\uFF08403\uFF09\uFF0C\u53EA\u80FD\u5BA1 pending \u72B6\u6001\u7684\u5185\u5BB9\uFF08\u975E pending \u4F1A 409\uFF09"
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
command: 'pdlab post review post_123 --action reject --comment "\u7F3A\u5C11\u6570\u636E\u6765\u6E90\uFF0C\u8BF7\u8865\u5145\u5F15\u7528"',
|
|
660
|
+
note: "\u9A73\u56DE\u65F6\u5FC5\u987B\u586B\u5199 --comment\uFF0C\u5426\u5219 400"
|
|
429
661
|
}
|
|
430
662
|
];
|
|
431
|
-
var UPDATE_EXAMPLES2 = [{ command: 'pdlab post update post_123 --title "..." --body "..."', note: "title \u548C body \u90FD\u5FC5\u987B\u4F20" }];
|
|
432
663
|
function toMediaLinks(value) {
|
|
433
664
|
if (value === void 0) return void 0;
|
|
434
665
|
return value.split(",").map((url) => url.trim()).filter(Boolean);
|
|
435
666
|
}
|
|
436
667
|
function registerPostCommand(program2) {
|
|
437
|
-
const post = program2.command("post").description("\u5185\u5BB9\uFF08\u5E16\u5B50\uFF09\u7684\u589E\u5220\u6539\u67E5");
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
console.log(JSON.stringify(data, null, 2));
|
|
445
|
-
});
|
|
446
|
-
withApiUrl(post.command("get <id>").description("\u67E5\u770B\u5185\u5BB9\u8BE6\u60C5")).action(
|
|
447
|
-
async (id, opts) => {
|
|
448
|
-
const data = await apiRequest(`/api/posts/${id}`, { token: optionalToken(), apiUrl: opts.apiUrl });
|
|
449
|
-
console.log(JSON.stringify(data, null, 2));
|
|
450
|
-
}
|
|
451
|
-
);
|
|
452
|
-
withApiUrl(post.command("create").description("\u53D1\u5E03\u5185\u5BB9\uFF08\u9700\u8981\u5185\u5BB9\u521B\u5EFA\u6743\u9650\uFF0C\u4E14\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u62A5\u540D\u5171\u5EFA\uFF09")).option("--title <title>", "\u5185\u5BB9\u6807\u9898").option("--body <body>", "\u5185\u5BB9\u6B63\u6587").option("--project-id <id>", "\u6240\u5C5E\u9879\u76EE id").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u5A92\u4F53\u94FE\u63A5").action(async (opts) => {
|
|
453
|
-
const token = requireToken();
|
|
454
|
-
try {
|
|
455
|
-
const body = postCreateSchema.parse({
|
|
456
|
-
title: opts.title,
|
|
457
|
-
body: opts.body,
|
|
458
|
-
projectId: opts.projectId,
|
|
459
|
-
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
668
|
+
const post = program2.command("post").description("\u5185\u5BB9\uFF08\u5E16\u5B50\uFF09\u7684\u589E\u5220\u6539\u67E5\u4E0E\u5BA1\u6838");
|
|
669
|
+
attachMeta(
|
|
670
|
+
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) => {
|
|
671
|
+
const data = await apiRequest("/api/posts", {
|
|
672
|
+
query: { projectId: opts.projectId, status: opts.status, limit: opts.limit, cursor: opts.cursor },
|
|
673
|
+
token: optionalToken(),
|
|
674
|
+
apiUrl: opts.apiUrl
|
|
460
675
|
});
|
|
461
|
-
const data = await apiRequest("/api/posts", { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
462
676
|
console.log(JSON.stringify(data, null, 2));
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
} catch (error) {
|
|
478
|
-
handleCommandError(error, UPDATE_EXAMPLES2);
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
withApiUrl(post.command("delete <id>").description("\u5220\u9664\u5185\u5BB9\uFF08\u4F5C\u8005\u672C\u4EBA\uFF0C\u6216\u6709\u5220\u9664\u4EFB\u610F\u5185\u5BB9\u7684\u6743\u9650\uFF09")).action(
|
|
482
|
-
async (id, opts) => {
|
|
677
|
+
}),
|
|
678
|
+
{ examples: LIST_EXAMPLES2 }
|
|
679
|
+
);
|
|
680
|
+
attachMeta(
|
|
681
|
+
withApiUrl(post.command("get <id>").description("\u67E5\u770B\u5185\u5BB9\u8BE6\u60C5")).action(
|
|
682
|
+
async (id, opts) => {
|
|
683
|
+
const data = await apiRequest(`/api/posts/${id}`, { token: optionalToken(), apiUrl: opts.apiUrl });
|
|
684
|
+
console.log(JSON.stringify(data, null, 2));
|
|
685
|
+
}
|
|
686
|
+
),
|
|
687
|
+
{ examples: GET_EXAMPLES2 }
|
|
688
|
+
);
|
|
689
|
+
attachMeta(
|
|
690
|
+
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) => {
|
|
483
691
|
const token = requireToken();
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
692
|
+
try {
|
|
693
|
+
const body = postCreateSchema.parse({
|
|
694
|
+
title: opts.title,
|
|
695
|
+
body: opts.body,
|
|
696
|
+
projectId: opts.projectId,
|
|
697
|
+
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
698
|
+
});
|
|
699
|
+
const data = await apiRequest("/api/posts", { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
700
|
+
console.log(JSON.stringify(data, null, 2));
|
|
701
|
+
} catch (error) {
|
|
702
|
+
handleCommandError(error, CREATE_EXAMPLES2);
|
|
703
|
+
}
|
|
704
|
+
}),
|
|
705
|
+
{ permission: "content:create\uFF0C\u4E14\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u62A5\u540D\u5171\u5EFA\u8BE5\u9879\u76EE", examples: CREATE_EXAMPLES2 }
|
|
487
706
|
);
|
|
707
|
+
attachMeta(
|
|
708
|
+
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) => {
|
|
709
|
+
const token = requireToken();
|
|
710
|
+
try {
|
|
711
|
+
const body = postUpdateSchema.parse({
|
|
712
|
+
title: opts.title,
|
|
713
|
+
body: opts.body,
|
|
714
|
+
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
715
|
+
});
|
|
716
|
+
const data = await apiRequest(`/api/posts/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
|
|
717
|
+
console.log(JSON.stringify(data, null, 2));
|
|
718
|
+
} catch (error) {
|
|
719
|
+
handleCommandError(error, UPDATE_EXAMPLES2);
|
|
720
|
+
}
|
|
721
|
+
}),
|
|
722
|
+
{ examples: UPDATE_EXAMPLES2 }
|
|
723
|
+
);
|
|
724
|
+
attachMeta(
|
|
725
|
+
withApiUrl(post.command("delete <id>").description("\u5220\u9664\u5185\u5BB9\uFF08\u4F5C\u8005\u672C\u4EBA\uFF0C\u6216\u6709\u5220\u9664\u4EFB\u610F\u5185\u5BB9\u7684\u6743\u9650\uFF09")).action(
|
|
726
|
+
async (id, opts) => {
|
|
727
|
+
const token = requireToken();
|
|
728
|
+
const data = await apiRequest(`/api/posts/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
729
|
+
console.log(JSON.stringify(data, null, 2));
|
|
730
|
+
}
|
|
731
|
+
),
|
|
732
|
+
{ examples: DELETE_EXAMPLES2 }
|
|
733
|
+
);
|
|
734
|
+
attachMeta(
|
|
735
|
+
withApiUrl(post.command("review <id>").description("\u5BA1\u6838\u4E00\u6761\u5F85\u5BA1\u5185\u5BB9\uFF08approve / reject\uFF09")).requiredOption("--action <action>", "approve | reject").option("--comment <text>", "\u5BA1\u6838\u610F\u89C1\uFF0C\u6700\u591A 500 \u5B57\uFF08reject \u65F6\u5FC5\u586B\uFF09").action(async (id, opts) => {
|
|
736
|
+
const token = requireToken();
|
|
737
|
+
try {
|
|
738
|
+
const body = postReviewSchema.parse({ action: opts.action, reviewComment: opts.comment });
|
|
739
|
+
const data = await apiRequest(`/api/posts/${id}/review`, { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
740
|
+
console.log(JSON.stringify(data, null, 2));
|
|
741
|
+
} catch (error) {
|
|
742
|
+
handleCommandError(error, REVIEW_EXAMPLES);
|
|
743
|
+
}
|
|
744
|
+
}),
|
|
745
|
+
{ permission: "content:review\uFF0C\u4E14\u4E0D\u80FD\u5BA1\u6838\u81EA\u5DF1\u53D1\u5E03\u7684\u5185\u5BB9", examples: REVIEW_EXAMPLES }
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// src/commands/schema.ts
|
|
750
|
+
var CODE_DESCRIPTION = {
|
|
751
|
+
ok: "\u6210\u529F",
|
|
752
|
+
unhandled: "\u672A\u5206\u7C7B\u9519\u8BEF",
|
|
753
|
+
validation: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF08\u672C\u5730\u6216\u670D\u52A1\u7AEF\uFF09",
|
|
754
|
+
unauthenticated: "\u672A\u767B\u5F55\u6216 token \u5DF2\u5931\u6548\uFF0C\u9700\u8981 pdlab login",
|
|
755
|
+
forbidden: "\u65E0\u6743\u9650\uFF08\u670D\u52A1\u7AEF 403\uFF09",
|
|
756
|
+
not_found: "\u8D44\u6E90\u4E0D\u5B58\u5728\uFF08\u670D\u52A1\u7AEF 404\uFF09",
|
|
757
|
+
conflict: "\u72B6\u6001\u51B2\u7A81\uFF0C\u4F8B\u5982\u91CD\u590D\u5BA1\u6838\uFF08\u670D\u52A1\u7AEF 409\uFF09",
|
|
758
|
+
network: "\u8FDE\u4E0D\u4E0A API \u670D\u52A1\u5668",
|
|
759
|
+
unknown: "\u672A\u5206\u7C7B\u7684\u670D\u52A1\u7AEF\u9519\u8BEF"
|
|
760
|
+
};
|
|
761
|
+
function exitCodeTable() {
|
|
762
|
+
const table = {};
|
|
763
|
+
for (const [code, exitStatus] of Object.entries(EXIT_CODES)) {
|
|
764
|
+
if (table[exitStatus] === void 0) table[exitStatus] = CODE_DESCRIPTION[code];
|
|
765
|
+
}
|
|
766
|
+
return table;
|
|
767
|
+
}
|
|
768
|
+
function serialize(command) {
|
|
769
|
+
const meta = getMeta(command);
|
|
770
|
+
return {
|
|
771
|
+
name: command.name(),
|
|
772
|
+
description: command.description(),
|
|
773
|
+
permission: meta.permission,
|
|
774
|
+
arguments: command.registeredArguments.map((a) => ({ name: a.name(), required: a.required })),
|
|
775
|
+
options: command.options.map((o) => ({ flags: o.flags, description: o.description, required: o.mandatory })),
|
|
776
|
+
examples: meta.examples ?? [],
|
|
777
|
+
subcommands: command.commands.map(serialize)
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function registerSchemaCommand(program2) {
|
|
781
|
+
program2.command("schema").description("\u4EE5 JSON \u8F93\u51FA\u5B8C\u6574\u547D\u4EE4\u6811\uFF08\u542B\u53C2\u6570\u3001\u6743\u9650\u8981\u6C42\u3001\u793A\u4F8B\uFF09\u548C\u9000\u51FA\u7801\u542B\u4E49\uFF0C\u4F9B agent/\u811A\u672C\u4E00\u6B21\u6027\u8BFB\u53D6").action(() => {
|
|
782
|
+
console.log(
|
|
783
|
+
JSON.stringify(
|
|
784
|
+
{
|
|
785
|
+
exitCodes: exitCodeTable(),
|
|
786
|
+
commands: program2.commands.map(serialize)
|
|
787
|
+
},
|
|
788
|
+
null,
|
|
789
|
+
2
|
|
790
|
+
)
|
|
791
|
+
);
|
|
792
|
+
});
|
|
488
793
|
}
|
|
489
794
|
|
|
490
795
|
// src/index.ts
|
|
491
796
|
var pkg = JSON.parse((0, import_fs2.readFileSync)((0, import_path2.join)(__dirname, "../package.json"), "utf8"));
|
|
492
797
|
var program = new import_commander.Command();
|
|
493
|
-
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").version(pkg.version);
|
|
798
|
+
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);
|
|
494
799
|
registerLoginCommand(program);
|
|
495
800
|
registerRegisterCommand(program);
|
|
496
801
|
registerLogoutCommand(program);
|
|
@@ -498,11 +803,7 @@ registerWhoamiCommand(program);
|
|
|
498
803
|
registerConfigCommand(program);
|
|
499
804
|
registerProjectCommand(program);
|
|
500
805
|
registerPostCommand(program);
|
|
806
|
+
registerSchemaCommand(program);
|
|
501
807
|
program.parseAsync(process.argv).catch((error) => {
|
|
502
|
-
|
|
503
|
-
console.error(`\u9519\u8BEF\uFF1A${error.message}`);
|
|
504
|
-
} else {
|
|
505
|
-
console.error(error);
|
|
506
|
-
}
|
|
507
|
-
process.exit(1);
|
|
808
|
+
handleCommandError(error);
|
|
508
809
|
});
|