pdlab-cli 0.1.2 → 0.2.1
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 +428 -118
- 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
|
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/index.ts
|
|
27
27
|
var import_fs2 = require("fs");
|
|
28
28
|
var import_path2 = require("path");
|
|
29
|
-
var
|
|
29
|
+
var import_commander2 = require("commander");
|
|
30
30
|
|
|
31
31
|
// src/commands/login.ts
|
|
32
32
|
var import_open = __toESM(require("open"));
|
|
@@ -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 = {};
|
|
@@ -303,42 +339,86 @@ var postReviewSchema = import_zod3.z.object({
|
|
|
303
339
|
});
|
|
304
340
|
|
|
305
341
|
// src/errors.ts
|
|
342
|
+
var import_commander = require("commander");
|
|
306
343
|
var import_zod4 = require("zod");
|
|
307
|
-
|
|
308
|
-
|
|
344
|
+
var EXIT_CODES = {
|
|
345
|
+
ok: 0,
|
|
346
|
+
unhandled: 1,
|
|
347
|
+
validation: 2,
|
|
348
|
+
unauthenticated: 3,
|
|
349
|
+
forbidden: 4,
|
|
350
|
+
not_found: 5,
|
|
351
|
+
conflict: 6,
|
|
352
|
+
network: 7,
|
|
353
|
+
unknown: 1
|
|
354
|
+
};
|
|
355
|
+
function fieldsFromZod(error) {
|
|
356
|
+
const fields = {};
|
|
309
357
|
for (const issue of error.issues) {
|
|
310
358
|
const path = issue.path.length > 0 ? issue.path.join(".") : "(\u6839)";
|
|
311
|
-
|
|
359
|
+
(fields[path] ??= []).push(issue.message);
|
|
312
360
|
}
|
|
313
|
-
|
|
361
|
+
return fields;
|
|
314
362
|
}
|
|
315
|
-
function
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
363
|
+
function fieldsFromApiDetails(details) {
|
|
364
|
+
if (!details || typeof details !== "object") return void 0;
|
|
365
|
+
const flat = details;
|
|
366
|
+
const fields = { ...flat.fieldErrors ?? {} };
|
|
367
|
+
if (flat.formErrors && flat.formErrors.length > 0) fields["(\u6839)"] = flat.formErrors;
|
|
368
|
+
return Object.keys(fields).length > 0 ? fields : void 0;
|
|
322
369
|
}
|
|
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
|
-
}
|
|
370
|
+
function exampleHint(examples) {
|
|
371
|
+
if (examples.length === 0) return void 0;
|
|
372
|
+
return examples.map((e) => e.command).join(" | ");
|
|
332
373
|
}
|
|
333
|
-
function handleCommandError(error, examples) {
|
|
374
|
+
function handleCommandError(error, examples = []) {
|
|
375
|
+
let structured;
|
|
334
376
|
if (error instanceof import_zod4.ZodError) {
|
|
335
|
-
|
|
377
|
+
structured = {
|
|
378
|
+
error: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
|
|
379
|
+
code: "validation",
|
|
380
|
+
status: null,
|
|
381
|
+
fields: fieldsFromZod(error),
|
|
382
|
+
hint: exampleHint(examples)
|
|
383
|
+
};
|
|
336
384
|
} else if (error instanceof ApiRequestError) {
|
|
337
|
-
|
|
385
|
+
structured = {
|
|
386
|
+
error: error.message,
|
|
387
|
+
code: error.code,
|
|
388
|
+
status: error.status || null,
|
|
389
|
+
fields: fieldsFromApiDetails(error.details),
|
|
390
|
+
hint: exampleHint(examples)
|
|
391
|
+
};
|
|
392
|
+
} else if (error instanceof CliError) {
|
|
393
|
+
structured = { error: error.message, code: error.code, status: null, hint: "pdlab login" };
|
|
394
|
+
} else if (error instanceof import_commander.CommanderError) {
|
|
395
|
+
structured = { error: error.message.replace(/^error:\s*/, ""), code: "validation", status: null, hint: exampleHint(examples) };
|
|
338
396
|
} else {
|
|
339
|
-
|
|
397
|
+
structured = {
|
|
398
|
+
error: error instanceof Error ? error.message : String(error),
|
|
399
|
+
code: "unhandled",
|
|
400
|
+
status: null
|
|
401
|
+
};
|
|
340
402
|
}
|
|
341
|
-
|
|
403
|
+
console.error(JSON.stringify(structured, null, 2));
|
|
404
|
+
process.exit(EXIT_CODES[structured.code] ?? 1);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// src/help-meta.ts
|
|
408
|
+
var META = /* @__PURE__ */ new WeakMap();
|
|
409
|
+
function attachMeta(command, meta) {
|
|
410
|
+
META.set(command, meta);
|
|
411
|
+
if (meta.examples && meta.examples.length > 0) {
|
|
412
|
+
command.addHelpText(
|
|
413
|
+
"after",
|
|
414
|
+
"\n\u793A\u4F8B\uFF1A\n" + meta.examples.map((e) => ` $ ${e.command}${e.note ? `
|
|
415
|
+
${e.note}` : ""}`).join("\n")
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
return command;
|
|
419
|
+
}
|
|
420
|
+
function getMeta(command) {
|
|
421
|
+
return META.get(command) ?? {};
|
|
342
422
|
}
|
|
343
423
|
|
|
344
424
|
// src/commands/options.ts
|
|
@@ -347,15 +427,50 @@ function withApiUrl(cmd) {
|
|
|
347
427
|
}
|
|
348
428
|
|
|
349
429
|
// src/commands/project.ts
|
|
430
|
+
var STATUS_LIST = PROJECT_STATUS_VALUES.join(" | ");
|
|
350
431
|
var CREATE_EXAMPLES = [
|
|
351
432
|
{
|
|
352
433
|
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"
|
|
434
|
+
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
435
|
}
|
|
355
436
|
];
|
|
356
437
|
var UPDATE_EXAMPLES = [
|
|
357
438
|
{ command: "pdlab project update proj_123 --progress 60 --status active", note: "\u53EA\u4F20\u8981\u6539\u7684\u5B57\u6BB5" }
|
|
358
439
|
];
|
|
440
|
+
var LIST_EXAMPLES = [
|
|
441
|
+
{ command: "pdlab project list --status active", note: "\u6309\u72B6\u6001\u7B5B\u9009" },
|
|
442
|
+
{ command: 'pdlab project list --q "\u94A0\u7535"', note: "\u6309\u6807\u9898\u5173\u952E\u8BCD\u641C\u7D22" },
|
|
443
|
+
{ command: "pdlab project list --taxonomy tax_1 --taxonomy tax_2", note: "\u53EF\u91CD\u590D\u4F20\uFF0C\u591A\u4E2A\u6807\u7B7E\u53D6\u4EA4\u96C6" },
|
|
444
|
+
{ 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" }
|
|
445
|
+
];
|
|
446
|
+
var GET_EXAMPLES = [{ command: "pdlab project get proj_123" }];
|
|
447
|
+
var DELETE_EXAMPLES = [
|
|
448
|
+
{ 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" }
|
|
449
|
+
];
|
|
450
|
+
var JOIN_EXAMPLES = [
|
|
451
|
+
{ 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" }
|
|
452
|
+
];
|
|
453
|
+
var LEAVE_EXAMPLES = [
|
|
454
|
+
{ 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" }
|
|
455
|
+
];
|
|
456
|
+
var MEMBER_REVIEW_EXAMPLES = [
|
|
457
|
+
{
|
|
458
|
+
command: "pdlab project member review proj_123 user_456 --status approved",
|
|
459
|
+
note: "\u5BA1\u6838\u4E00\u6761 pending \u7684\u62A5\u540D\u7533\u8BF7\uFF1B\u53EA\u6709\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA\u80FD\u8C03\u7528"
|
|
460
|
+
}
|
|
461
|
+
];
|
|
462
|
+
var MEMBER_SET_ROLE_EXAMPLES = [
|
|
463
|
+
{
|
|
464
|
+
command: "pdlab project member set-role proj_123 user_456 --role maintainer",
|
|
465
|
+
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"
|
|
466
|
+
}
|
|
467
|
+
];
|
|
468
|
+
var MEMBER_REMOVE_EXAMPLES = [
|
|
469
|
+
{ command: "pdlab project member remove proj_123 user_456", note: "\u53EA\u6709\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA\u80FD\u8C03\u7528" }
|
|
470
|
+
];
|
|
471
|
+
var REVENUE_EXAMPLES = [
|
|
472
|
+
{ command: "pdlab project revenue proj_123", note: "\u53EA\u8BFB\uFF0C\u9700\u8981 data:view_stats \u6743\u9650" }
|
|
473
|
+
];
|
|
359
474
|
function toBody(opts) {
|
|
360
475
|
const body = {};
|
|
361
476
|
if (opts.title !== void 0) body.title = opts.title;
|
|
@@ -370,26 +485,43 @@ function toBody(opts) {
|
|
|
370
485
|
return body;
|
|
371
486
|
}
|
|
372
487
|
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>",
|
|
488
|
+
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");
|
|
489
|
+
}
|
|
490
|
+
function collect(value, previous) {
|
|
491
|
+
return previous.concat([value]);
|
|
374
492
|
}
|
|
375
493
|
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
|
-
|
|
494
|
+
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");
|
|
495
|
+
attachMeta(
|
|
496
|
+
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(
|
|
497
|
+
async (opts) => {
|
|
498
|
+
const data = await apiRequest("/api/projects", {
|
|
499
|
+
query: {
|
|
500
|
+
status: opts.status,
|
|
501
|
+
q: opts.q,
|
|
502
|
+
taxonomy: opts.taxonomy.length > 0 ? opts.taxonomy : void 0,
|
|
503
|
+
limit: opts.limit,
|
|
504
|
+
cursor: opts.cursor
|
|
505
|
+
},
|
|
506
|
+
token: optionalToken(),
|
|
507
|
+
apiUrl: opts.apiUrl
|
|
508
|
+
});
|
|
509
|
+
console.log(JSON.stringify(data, null, 2));
|
|
510
|
+
}
|
|
511
|
+
),
|
|
512
|
+
{ examples: LIST_EXAMPLES }
|
|
390
513
|
);
|
|
391
|
-
|
|
392
|
-
|
|
514
|
+
attachMeta(
|
|
515
|
+
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(
|
|
516
|
+
async (id, opts) => {
|
|
517
|
+
const data = await apiRequest(`/api/projects/${id}`, { token: optionalToken(), apiUrl: opts.apiUrl });
|
|
518
|
+
console.log(JSON.stringify(data, null, 2));
|
|
519
|
+
}
|
|
520
|
+
),
|
|
521
|
+
{ examples: GET_EXAMPLES }
|
|
522
|
+
);
|
|
523
|
+
attachMeta(
|
|
524
|
+
withProjectFlags(project.command("create").description("\u521B\u5EFA\u9879\u76EE")).action(async (opts) => {
|
|
393
525
|
const token = requireToken();
|
|
394
526
|
try {
|
|
395
527
|
const body = projectCreateSchema.parse(toBody(opts));
|
|
@@ -398,99 +530,278 @@ function registerProjectCommand(program2) {
|
|
|
398
530
|
} catch (error) {
|
|
399
531
|
handleCommandError(error, CREATE_EXAMPLES);
|
|
400
532
|
}
|
|
533
|
+
}),
|
|
534
|
+
{ permission: "project:create\uFF081836\u53D1\u8D77\u4EBA\u89D2\u8272\uFF09", examples: CREATE_EXAMPLES }
|
|
535
|
+
);
|
|
536
|
+
attachMeta(
|
|
537
|
+
withProjectFlags(project.command("update <id>").description("\u66F4\u65B0\u9879\u76EE")).action(
|
|
538
|
+
async (id, opts) => {
|
|
539
|
+
const token = requireToken();
|
|
540
|
+
try {
|
|
541
|
+
const body = projectUpdateSchema.parse(toBody(opts));
|
|
542
|
+
const data = await apiRequest(`/api/projects/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
|
|
543
|
+
console.log(JSON.stringify(data, null, 2));
|
|
544
|
+
} catch (error) {
|
|
545
|
+
handleCommandError(error, UPDATE_EXAMPLES);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
),
|
|
549
|
+
{
|
|
550
|
+
permission: "project:update_progress\uFF08\u53D1\u8D77\u4EBA\uFF09\u6216 project:join\uFF08\u534F\u4F5C\u8005\uFF0C\u4EC5\u80FD\u6539 progress/status/description\uFF09",
|
|
551
|
+
examples: UPDATE_EXAMPLES
|
|
401
552
|
}
|
|
402
553
|
);
|
|
403
|
-
|
|
404
|
-
|
|
554
|
+
attachMeta(
|
|
555
|
+
withApiUrl(
|
|
556
|
+
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")
|
|
557
|
+
).action(async (id, opts) => {
|
|
405
558
|
const token = requireToken();
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
559
|
+
const data = await apiRequest(`/api/projects/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
560
|
+
console.log(JSON.stringify(data, null, 2));
|
|
561
|
+
}),
|
|
562
|
+
{ 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 }
|
|
563
|
+
);
|
|
564
|
+
attachMeta(
|
|
565
|
+
withApiUrl(project.command("join <id>").description("\u62A5\u540D\u5171\u5EFA\u8BE5\u9879\u76EE\uFF0C\u8FDB\u5165\u5F85\u5BA1\u6838")).action(
|
|
566
|
+
async (id, opts) => {
|
|
567
|
+
const token = requireToken();
|
|
568
|
+
const data = await apiRequest(`/api/projects/${id}/join`, { method: "POST", token, apiUrl: opts.apiUrl });
|
|
409
569
|
console.log(JSON.stringify(data, null, 2));
|
|
410
|
-
} catch (error) {
|
|
411
|
-
handleCommandError(error, UPDATE_EXAMPLES);
|
|
412
570
|
}
|
|
413
|
-
|
|
571
|
+
),
|
|
572
|
+
{ permission: "project:join\uFF081836\u5171\u5EFA\u8005\u7B49\u89D2\u8272\uFF09", examples: JOIN_EXAMPLES }
|
|
573
|
+
);
|
|
574
|
+
attachMeta(
|
|
575
|
+
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(
|
|
576
|
+
async (id, opts) => {
|
|
577
|
+
const token = requireToken();
|
|
578
|
+
const data = await apiRequest(`/api/projects/${id}/join`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
579
|
+
console.log(JSON.stringify(data, null, 2));
|
|
580
|
+
}
|
|
581
|
+
),
|
|
582
|
+
{ permission: "project:join\uFF081836\u5171\u5EFA\u8005\u7B49\u89D2\u8272\uFF09", examples: LEAVE_EXAMPLES }
|
|
583
|
+
);
|
|
584
|
+
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");
|
|
585
|
+
attachMeta(
|
|
586
|
+
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) => {
|
|
587
|
+
const token = requireToken();
|
|
588
|
+
const data = await apiRequest(`/api/projects/${projectId}/members/${userId}`, {
|
|
589
|
+
method: "PATCH",
|
|
590
|
+
body: { status: opts.status },
|
|
591
|
+
token,
|
|
592
|
+
apiUrl: opts.apiUrl
|
|
593
|
+
});
|
|
594
|
+
console.log(JSON.stringify(data, null, 2));
|
|
595
|
+
}),
|
|
596
|
+
{ permission: "project:update_progress\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: MEMBER_REVIEW_EXAMPLES }
|
|
597
|
+
);
|
|
598
|
+
attachMeta(
|
|
599
|
+
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) => {
|
|
600
|
+
const token = requireToken();
|
|
601
|
+
const data = await apiRequest(`/api/projects/${projectId}/members/${userId}`, {
|
|
602
|
+
method: "PATCH",
|
|
603
|
+
body: { role: opts.role },
|
|
604
|
+
token,
|
|
605
|
+
apiUrl: opts.apiUrl
|
|
606
|
+
});
|
|
607
|
+
console.log(JSON.stringify(data, null, 2));
|
|
608
|
+
}),
|
|
609
|
+
{ permission: "project:update_progress\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: MEMBER_SET_ROLE_EXAMPLES }
|
|
610
|
+
);
|
|
611
|
+
attachMeta(
|
|
612
|
+
withApiUrl(member.command("remove <projectId> <userId>").description("\u79FB\u9664\u4E00\u4E2A\u53C2\u4E0E\u8005")).action(
|
|
613
|
+
async (projectId, userId, opts) => {
|
|
614
|
+
const token = requireToken();
|
|
615
|
+
const data = await apiRequest(`/api/projects/${projectId}/members/${userId}`, {
|
|
616
|
+
method: "DELETE",
|
|
617
|
+
token,
|
|
618
|
+
apiUrl: opts.apiUrl
|
|
619
|
+
});
|
|
620
|
+
console.log(JSON.stringify(data, null, 2));
|
|
621
|
+
}
|
|
622
|
+
),
|
|
623
|
+
{ permission: "project:update_progress\uFF0C\u4E14\u5FC5\u987B\u662F\u8BE5\u9879\u76EE\u53D1\u8D77\u4EBA\u672C\u4EBA", examples: MEMBER_REMOVE_EXAMPLES }
|
|
624
|
+
);
|
|
625
|
+
attachMeta(
|
|
626
|
+
withApiUrl(project.command("revenue <id>").description("\u67E5\u770B\u9879\u76EE\u7684\u79EF\u5206\u5206\u6210\u660E\u7EC6\uFF08\u53EA\u8BFB\uFF09")).action(
|
|
627
|
+
async (id, opts) => {
|
|
628
|
+
const token = requireToken();
|
|
629
|
+
const data = await apiRequest(`/api/projects/${id}/revenue-breakdown`, { token, apiUrl: opts.apiUrl });
|
|
630
|
+
console.log(JSON.stringify(data, null, 2));
|
|
631
|
+
}
|
|
632
|
+
),
|
|
633
|
+
{ permission: "data:view_stats", examples: REVENUE_EXAMPLES }
|
|
414
634
|
);
|
|
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
635
|
}
|
|
423
636
|
|
|
424
637
|
// src/commands/post.ts
|
|
425
638
|
var CREATE_EXAMPLES2 = [
|
|
426
639
|
{
|
|
427
640
|
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"
|
|
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"
|
|
642
|
+
}
|
|
643
|
+
];
|
|
644
|
+
var UPDATE_EXAMPLES2 = [
|
|
645
|
+
{ command: 'pdlab post update post_123 --title "..." --body "..."', note: "title \u548C body \u90FD\u5FC5\u987B\u4F20" }
|
|
646
|
+
];
|
|
647
|
+
var LIST_EXAMPLES2 = [
|
|
648
|
+
{ command: "pdlab post list --project-id proj_123", note: "\u53EA\u770B\u67D0\u4E2A\u9879\u76EE\u4E0B\u7684\u5185\u5BB9" },
|
|
649
|
+
{ 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
|
+
{ 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
|
+
];
|
|
652
|
+
var GET_EXAMPLES2 = [{ command: "pdlab post get post_123" }];
|
|
653
|
+
var DELETE_EXAMPLES2 = [
|
|
654
|
+
{ command: "pdlab post delete post_123", note: "\u4F5C\u8005\u672C\u4EBA\uFF0C\u6216\u6709\u5220\u9664\u4EFB\u610F\u5185\u5BB9\u7684\u6743\u9650" }
|
|
655
|
+
];
|
|
656
|
+
var REVIEW_EXAMPLES = [
|
|
657
|
+
{
|
|
658
|
+
command: "pdlab post review post_123 --action approve",
|
|
659
|
+
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"
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
command: 'pdlab post review post_123 --action reject --comment "\u7F3A\u5C11\u6570\u636E\u6765\u6E90\uFF0C\u8BF7\u8865\u5145\u5F15\u7528"',
|
|
663
|
+
note: "\u9A73\u56DE\u65F6\u5FC5\u987B\u586B\u5199 --comment\uFF0C\u5426\u5219 400"
|
|
429
664
|
}
|
|
430
665
|
];
|
|
431
|
-
var UPDATE_EXAMPLES2 = [{ command: 'pdlab post update post_123 --title "..." --body "..."', note: "title \u548C body \u90FD\u5FC5\u987B\u4F20" }];
|
|
432
666
|
function toMediaLinks(value) {
|
|
433
667
|
if (value === void 0) return void 0;
|
|
434
668
|
return value.split(",").map((url) => url.trim()).filter(Boolean);
|
|
435
669
|
}
|
|
436
670
|
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)
|
|
671
|
+
const post = program2.command("post").description("\u5185\u5BB9\uFF08\u5E16\u5B50\uFF09\u7684\u589E\u5220\u6539\u67E5\u4E0E\u5BA1\u6838");
|
|
672
|
+
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) => {
|
|
674
|
+
const data = await apiRequest("/api/posts", {
|
|
675
|
+
query: { projectId: opts.projectId, status: opts.status, limit: opts.limit, cursor: opts.cursor },
|
|
676
|
+
token: optionalToken(),
|
|
677
|
+
apiUrl: opts.apiUrl
|
|
460
678
|
});
|
|
461
|
-
const data = await apiRequest("/api/posts", { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
462
679
|
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) => {
|
|
680
|
+
}),
|
|
681
|
+
{ examples: LIST_EXAMPLES2 }
|
|
682
|
+
);
|
|
683
|
+
attachMeta(
|
|
684
|
+
withApiUrl(post.command("get <id>").description("\u67E5\u770B\u5185\u5BB9\u8BE6\u60C5")).action(
|
|
685
|
+
async (id, opts) => {
|
|
686
|
+
const data = await apiRequest(`/api/posts/${id}`, { token: optionalToken(), apiUrl: opts.apiUrl });
|
|
687
|
+
console.log(JSON.stringify(data, null, 2));
|
|
688
|
+
}
|
|
689
|
+
),
|
|
690
|
+
{ examples: GET_EXAMPLES2 }
|
|
691
|
+
);
|
|
692
|
+
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) => {
|
|
483
694
|
const token = requireToken();
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
695
|
+
try {
|
|
696
|
+
const body = postCreateSchema.parse({
|
|
697
|
+
title: opts.title,
|
|
698
|
+
body: opts.body,
|
|
699
|
+
projectId: opts.projectId,
|
|
700
|
+
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
701
|
+
});
|
|
702
|
+
const data = await apiRequest("/api/posts", { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
703
|
+
console.log(JSON.stringify(data, null, 2));
|
|
704
|
+
} catch (error) {
|
|
705
|
+
handleCommandError(error, CREATE_EXAMPLES2);
|
|
706
|
+
}
|
|
707
|
+
}),
|
|
708
|
+
{ permission: "content:create\uFF0C\u4E14\u662F\u9879\u76EE\u53D1\u8D77\u4EBA\u6216\u5DF2\u62A5\u540D\u5171\u5EFA\u8BE5\u9879\u76EE", examples: CREATE_EXAMPLES2 }
|
|
709
|
+
);
|
|
710
|
+
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) => {
|
|
712
|
+
const token = requireToken();
|
|
713
|
+
try {
|
|
714
|
+
const body = postUpdateSchema.parse({
|
|
715
|
+
title: opts.title,
|
|
716
|
+
body: opts.body,
|
|
717
|
+
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
718
|
+
});
|
|
719
|
+
const data = await apiRequest(`/api/posts/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
|
|
720
|
+
console.log(JSON.stringify(data, null, 2));
|
|
721
|
+
} catch (error) {
|
|
722
|
+
handleCommandError(error, UPDATE_EXAMPLES2);
|
|
723
|
+
}
|
|
724
|
+
}),
|
|
725
|
+
{ examples: UPDATE_EXAMPLES2 }
|
|
726
|
+
);
|
|
727
|
+
attachMeta(
|
|
728
|
+
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(
|
|
729
|
+
async (id, opts) => {
|
|
730
|
+
const token = requireToken();
|
|
731
|
+
const data = await apiRequest(`/api/posts/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
732
|
+
console.log(JSON.stringify(data, null, 2));
|
|
733
|
+
}
|
|
734
|
+
),
|
|
735
|
+
{ examples: DELETE_EXAMPLES2 }
|
|
736
|
+
);
|
|
737
|
+
attachMeta(
|
|
738
|
+
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) => {
|
|
739
|
+
const token = requireToken();
|
|
740
|
+
try {
|
|
741
|
+
const body = postReviewSchema.parse({ action: opts.action, reviewComment: opts.comment });
|
|
742
|
+
const data = await apiRequest(`/api/posts/${id}/review`, { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
743
|
+
console.log(JSON.stringify(data, null, 2));
|
|
744
|
+
} catch (error) {
|
|
745
|
+
handleCommandError(error, REVIEW_EXAMPLES);
|
|
746
|
+
}
|
|
747
|
+
}),
|
|
748
|
+
{ permission: "content:review\uFF0C\u4E14\u4E0D\u80FD\u5BA1\u6838\u81EA\u5DF1\u53D1\u5E03\u7684\u5185\u5BB9", examples: REVIEW_EXAMPLES }
|
|
487
749
|
);
|
|
488
750
|
}
|
|
489
751
|
|
|
752
|
+
// src/commands/schema.ts
|
|
753
|
+
var CODE_DESCRIPTION = {
|
|
754
|
+
ok: "\u6210\u529F",
|
|
755
|
+
unhandled: "\u672A\u5206\u7C7B\u9519\u8BEF",
|
|
756
|
+
validation: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF08\u672C\u5730\u6216\u670D\u52A1\u7AEF\uFF09",
|
|
757
|
+
unauthenticated: "\u672A\u767B\u5F55\u6216 token \u5DF2\u5931\u6548\uFF0C\u9700\u8981 pdlab login",
|
|
758
|
+
forbidden: "\u65E0\u6743\u9650\uFF08\u670D\u52A1\u7AEF 403\uFF09",
|
|
759
|
+
not_found: "\u8D44\u6E90\u4E0D\u5B58\u5728\uFF08\u670D\u52A1\u7AEF 404\uFF09",
|
|
760
|
+
conflict: "\u72B6\u6001\u51B2\u7A81\uFF0C\u4F8B\u5982\u91CD\u590D\u5BA1\u6838\uFF08\u670D\u52A1\u7AEF 409\uFF09",
|
|
761
|
+
network: "\u8FDE\u4E0D\u4E0A API \u670D\u52A1\u5668",
|
|
762
|
+
unknown: "\u672A\u5206\u7C7B\u7684\u670D\u52A1\u7AEF\u9519\u8BEF"
|
|
763
|
+
};
|
|
764
|
+
function exitCodeTable() {
|
|
765
|
+
const table = {};
|
|
766
|
+
for (const [code, exitStatus] of Object.entries(EXIT_CODES)) {
|
|
767
|
+
if (table[exitStatus] === void 0) table[exitStatus] = CODE_DESCRIPTION[code];
|
|
768
|
+
}
|
|
769
|
+
return table;
|
|
770
|
+
}
|
|
771
|
+
function serialize(command) {
|
|
772
|
+
const meta = getMeta(command);
|
|
773
|
+
return {
|
|
774
|
+
name: command.name(),
|
|
775
|
+
description: command.description(),
|
|
776
|
+
permission: meta.permission,
|
|
777
|
+
arguments: command.registeredArguments.map((a) => ({ name: a.name(), required: a.required })),
|
|
778
|
+
options: command.options.map((o) => ({ flags: o.flags, description: o.description, required: o.mandatory })),
|
|
779
|
+
examples: meta.examples ?? [],
|
|
780
|
+
subcommands: command.commands.map(serialize)
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
function registerSchemaCommand(program2) {
|
|
784
|
+
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(() => {
|
|
785
|
+
console.log(
|
|
786
|
+
JSON.stringify(
|
|
787
|
+
{
|
|
788
|
+
exitCodes: exitCodeTable(),
|
|
789
|
+
commands: program2.commands.map(serialize)
|
|
790
|
+
},
|
|
791
|
+
null,
|
|
792
|
+
2
|
|
793
|
+
)
|
|
794
|
+
);
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
|
|
490
798
|
// src/index.ts
|
|
491
799
|
var pkg = JSON.parse((0, import_fs2.readFileSync)((0, import_path2.join)(__dirname, "../package.json"), "utf8"));
|
|
492
|
-
var program = new
|
|
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);
|
|
800
|
+
var program = new import_commander2.Command();
|
|
801
|
+
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
|
+
program.exitOverride();
|
|
803
|
+
program.configureOutput({ writeErr: () => {
|
|
804
|
+
} });
|
|
494
805
|
registerLoginCommand(program);
|
|
495
806
|
registerRegisterCommand(program);
|
|
496
807
|
registerLogoutCommand(program);
|
|
@@ -498,11 +809,10 @@ registerWhoamiCommand(program);
|
|
|
498
809
|
registerConfigCommand(program);
|
|
499
810
|
registerProjectCommand(program);
|
|
500
811
|
registerPostCommand(program);
|
|
812
|
+
registerSchemaCommand(program);
|
|
501
813
|
program.parseAsync(process.argv).catch((error) => {
|
|
502
|
-
if (error instanceof
|
|
503
|
-
|
|
504
|
-
} else {
|
|
505
|
-
console.error(error);
|
|
814
|
+
if (error instanceof import_commander2.CommanderError && error.exitCode === 0) {
|
|
815
|
+
process.exit(0);
|
|
506
816
|
}
|
|
507
|
-
|
|
817
|
+
handleCommandError(error);
|
|
508
818
|
});
|