pdlab-cli 0.1.0 → 0.1.2
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 +15 -2
- package/dist/index.js +68 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,13 @@ npm install -g pdlab-cli
|
|
|
17
17
|
## 快速开始
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
|
|
20
|
+
pdlab login
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
默认连官方部署 `https://1836.online`,装完直接就能用。
|
|
24
|
+
自建实例才需要指定地址,指定过一次之后会记在配置文件里:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
21
27
|
pdlab login --api-url https://your-1836-instance.example.com
|
|
22
28
|
```
|
|
23
29
|
|
|
@@ -71,7 +77,14 @@ pdlab post list --project-id <项目 id>
|
|
|
71
77
|
{ "apiUrl": "https://your-1836-instance.example.com", "token": "pdlab_…" }
|
|
72
78
|
```
|
|
73
79
|
|
|
74
|
-
API 地址的解析顺序:`--api-url` 参数 > `PDLAB_API_URL` 环境变量 >
|
|
80
|
+
API 地址的解析顺序:`--api-url` 参数 > `PDLAB_API_URL` 环境变量 > 配置文件 > 默认地址
|
|
81
|
+
(`https://1836.online`)。所有命令都支持 `--api-url`,
|
|
82
|
+
包括 `project` / `post` 这些资源命令。`pdlab config get` 会同时打出配置文件里写了什么、
|
|
83
|
+
以及这次实际会用哪个地址。
|
|
84
|
+
|
|
85
|
+
读命令(`project list` / `get`、`post list` / `get`)会在**已登录时带上凭证**,
|
|
86
|
+
可见范围因此按你的身份走:有审核权限才能 `post list --status pending`,
|
|
87
|
+
作者也才能 `post get` 到自己那篇还没过审的稿子。没登录则匿名读公开内容,照常可用。
|
|
75
88
|
在 CI 里可以只给环境变量,不落配置文件。
|
|
76
89
|
|
|
77
90
|
## 凭证与安全
|
package/dist/index.js
CHANGED
|
@@ -35,8 +35,9 @@ 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
|
-
var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".pdlab");
|
|
38
|
+
var CONFIG_DIR = process.env.PDLAB_CONFIG_DIR ?? (0, import_path.join)((0, import_os.homedir)(), ".pdlab");
|
|
39
39
|
var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
|
|
40
|
+
var DEFAULT_API_URL = "https://1836.online";
|
|
40
41
|
function readConfig() {
|
|
41
42
|
if (!(0, import_fs.existsSync)(CONFIG_FILE)) return {};
|
|
42
43
|
try {
|
|
@@ -55,13 +56,12 @@ function updateConfig(patch) {
|
|
|
55
56
|
return next;
|
|
56
57
|
}
|
|
57
58
|
function resolveApiUrl(flagValue) {
|
|
58
|
-
const apiUrl = flagValue ?? process.env.PDLAB_API_URL ?? readConfig().apiUrl;
|
|
59
|
-
if (!apiUrl) {
|
|
60
|
-
console.error("\u672A\u914D\u7F6E API \u5730\u5740\u3002\u8BF7\u5148\u8FD0\u884C `pdlab login` / `pdlab register`\uFF0C\u6216\u8BBE\u7F6E PDLAB_API_URL \u73AF\u5883\u53D8\u91CF\u3002");
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
59
|
+
const apiUrl = flagValue ?? process.env.PDLAB_API_URL ?? readConfig().apiUrl ?? DEFAULT_API_URL;
|
|
63
60
|
return apiUrl.replace(/\/+$/, "");
|
|
64
61
|
}
|
|
62
|
+
function optionalToken() {
|
|
63
|
+
return readConfig().token;
|
|
64
|
+
}
|
|
65
65
|
function requireToken() {
|
|
66
66
|
const token = readConfig().token;
|
|
67
67
|
if (!token) {
|
|
@@ -139,7 +139,7 @@ async function pollCliAuth(code, apiUrl) {
|
|
|
139
139
|
|
|
140
140
|
// src/commands/login.ts
|
|
141
141
|
function registerLoginCommand(program2) {
|
|
142
|
-
program2.command("login").description("\u5728\u6D4F\u89C8\u5668\u91CC\u5B8C\u6210\u4E00\u6B21\u6027\u6388\u6743\uFF0C\u767B\u5F55 pdlab CLI\uFF08token \u957F\u671F\u6709\u6548\uFF0C\u76F4\u5230\u88AB\u64A4\u9500\uFF09").option("--api-url <url>", "API \u670D\u52A1\u5668\u5730\u5740\uFF0C\
|
|
142
|
+
program2.command("login").description("\u5728\u6D4F\u89C8\u5668\u91CC\u5B8C\u6210\u4E00\u6B21\u6027\u6388\u6743\uFF0C\u767B\u5F55 pdlab CLI\uFF08token \u957F\u671F\u6709\u6548\uFF0C\u76F4\u5230\u88AB\u64A4\u9500\uFF09").option("--api-url <url>", "API \u670D\u52A1\u5668\u5730\u5740\uFF0C\u9ED8\u8BA4\u662F\u5B98\u65B9\u90E8\u7F72\uFF0C\u81EA\u5EFA\u5B9E\u4F8B\u624D\u9700\u8981\u586B").action(async (opts) => {
|
|
143
143
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
144
144
|
const start = await apiRequest("/api/cli/auth/start", {
|
|
145
145
|
method: "POST",
|
|
@@ -171,7 +171,7 @@ function registerLoginCommand(program2) {
|
|
|
171
171
|
// src/commands/register.ts
|
|
172
172
|
var import_open2 = __toESM(require("open"));
|
|
173
173
|
function registerRegisterCommand(program2) {
|
|
174
|
-
program2.command("register").description("\u5728\u6D4F\u89C8\u5668\u91CC\u5B8C\u6210\u6CE8\u518C\u7533\u8BF7\uFF08\u6CE8\u518C\u540E\u9700\u7BA1\u7406\u5458\u5BA1\u6838\uFF0CCLI \u4E0D\u4F1A\u81EA\u52A8\u767B\u5F55\uFF09").option("--api-url <url>", "API \u670D\u52A1\u5668\u5730\u5740\uFF0C\
|
|
174
|
+
program2.command("register").description("\u5728\u6D4F\u89C8\u5668\u91CC\u5B8C\u6210\u6CE8\u518C\u7533\u8BF7\uFF08\u6CE8\u518C\u540E\u9700\u7BA1\u7406\u5458\u5BA1\u6838\uFF0CCLI \u4E0D\u4F1A\u81EA\u52A8\u767B\u5F55\uFF09").option("--api-url <url>", "API \u670D\u52A1\u5668\u5730\u5740\uFF0C\u9ED8\u8BA4\u662F\u5B98\u65B9\u90E8\u7F72\uFF0C\u81EA\u5EFA\u5B9E\u4F8B\u624D\u9700\u8981\u586B").action(async (opts) => {
|
|
175
175
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
176
176
|
const start = await apiRequest("/api/cli/auth/start", {
|
|
177
177
|
method: "POST",
|
|
@@ -224,8 +224,19 @@ function registerWhoamiCommand(program2) {
|
|
|
224
224
|
function registerConfigCommand(program2) {
|
|
225
225
|
const config = program2.command("config").description("\u67E5\u770B/\u4FEE\u6539\u672C\u5730\u914D\u7F6E\uFF08~/.pdlab/config.json\uFF09");
|
|
226
226
|
config.command("get").description("\u6253\u5370\u5F53\u524D\u914D\u7F6E").action(() => {
|
|
227
|
-
const { token,
|
|
228
|
-
console.log(
|
|
227
|
+
const { token, apiUrl } = readConfig();
|
|
228
|
+
console.log(
|
|
229
|
+
JSON.stringify(
|
|
230
|
+
{
|
|
231
|
+
apiUrl,
|
|
232
|
+
token: token ? "***" : void 0,
|
|
233
|
+
effectiveApiUrl: resolveApiUrl(),
|
|
234
|
+
defaultApiUrl: DEFAULT_API_URL
|
|
235
|
+
},
|
|
236
|
+
null,
|
|
237
|
+
2
|
|
238
|
+
)
|
|
239
|
+
);
|
|
229
240
|
});
|
|
230
241
|
config.command("set <key> <value>").description("\u8BBE\u7F6E\u4E00\u9879\u914D\u7F6E\uFF0C\u76EE\u524D\u652F\u6301\uFF1Aapi-url").action((key, value) => {
|
|
231
242
|
if (key !== "api-url") {
|
|
@@ -330,6 +341,11 @@ function handleCommandError(error, examples) {
|
|
|
330
341
|
process.exit(1);
|
|
331
342
|
}
|
|
332
343
|
|
|
344
|
+
// src/commands/options.ts
|
|
345
|
+
function withApiUrl(cmd) {
|
|
346
|
+
return cmd.option("--api-url <url>", "API \u670D\u52A1\u5668\u5730\u5740\uFF0C\u8986\u76D6 PDLAB_API_URL\u3001\u914D\u7F6E\u6587\u4EF6\u4E0E\u9ED8\u8BA4\u5730\u5740");
|
|
347
|
+
}
|
|
348
|
+
|
|
333
349
|
// src/commands/project.ts
|
|
334
350
|
var CREATE_EXAMPLES = [
|
|
335
351
|
{
|
|
@@ -354,24 +370,30 @@ function toBody(opts) {
|
|
|
354
370
|
return body;
|
|
355
371
|
}
|
|
356
372
|
function withProjectFlags(cmd) {
|
|
357
|
-
return 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>", "planning | active | review | completed").option("--progress <percent>", "\u8FDB\u5EA6 0-100").option("--taxonomy-ids <ids>", "\u9017\u53F7\u5206\u9694\u7684\u5206\u7C7B\u6807\u7B7E id \u5217\u8868");
|
|
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>", "planning | active | review | completed").option("--progress <percent>", "\u8FDB\u5EA6 0-100").option("--taxonomy-ids <ids>", "\u9017\u53F7\u5206\u9694\u7684\u5206\u7C7B\u6807\u7B7E id \u5217\u8868");
|
|
358
374
|
}
|
|
359
375
|
function registerProjectCommand(program2) {
|
|
360
376
|
const project = program2.command("project").description("\u9879\u76EE\u7684\u589E\u5220\u6539\u67E5");
|
|
361
|
-
project.command("list").description("\u5217\u51FA\u9879\u76EE").option("--status <status>", "\u6309\u72B6\u6001\u7B5B\u9009\uFF1Aplanning | active | review | completed").action(async (opts) => {
|
|
362
|
-
const data = await apiRequest("/api/projects", {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
377
|
+
withApiUrl(project.command("list").description("\u5217\u51FA\u9879\u76EE")).option("--status <status>", "\u6309\u72B6\u6001\u7B5B\u9009\uFF1Aplanning | active | review | completed").action(async (opts) => {
|
|
378
|
+
const data = await apiRequest("/api/projects", {
|
|
379
|
+
query: { status: opts.status },
|
|
380
|
+
token: optionalToken(),
|
|
381
|
+
apiUrl: opts.apiUrl
|
|
382
|
+
});
|
|
367
383
|
console.log(JSON.stringify(data, null, 2));
|
|
368
384
|
});
|
|
385
|
+
withApiUrl(project.command("get <id>").description("\u67E5\u770B\u9879\u76EE\u8BE6\u60C5")).action(
|
|
386
|
+
async (id, opts) => {
|
|
387
|
+
const data = await apiRequest(`/api/projects/${id}`, { token: optionalToken(), apiUrl: opts.apiUrl });
|
|
388
|
+
console.log(JSON.stringify(data, null, 2));
|
|
389
|
+
}
|
|
390
|
+
);
|
|
369
391
|
withProjectFlags(project.command("create").description("\u521B\u5EFA\u9879\u76EE\uFF08\u9700\u8981\u9879\u76EE\u521B\u5EFA\u6743\u9650\uFF09")).action(
|
|
370
392
|
async (opts) => {
|
|
371
393
|
const token = requireToken();
|
|
372
394
|
try {
|
|
373
395
|
const body = projectCreateSchema.parse(toBody(opts));
|
|
374
|
-
const data = await apiRequest("/api/projects", { method: "POST", body, token });
|
|
396
|
+
const data = await apiRequest("/api/projects", { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
375
397
|
console.log(JSON.stringify(data, null, 2));
|
|
376
398
|
} catch (error) {
|
|
377
399
|
handleCommandError(error, CREATE_EXAMPLES);
|
|
@@ -383,16 +405,18 @@ function registerProjectCommand(program2) {
|
|
|
383
405
|
const token = requireToken();
|
|
384
406
|
try {
|
|
385
407
|
const body = projectUpdateSchema.parse(toBody(opts));
|
|
386
|
-
const data = await apiRequest(`/api/projects/${id}`, { method: "PATCH", body, token });
|
|
408
|
+
const data = await apiRequest(`/api/projects/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
|
|
387
409
|
console.log(JSON.stringify(data, null, 2));
|
|
388
410
|
} catch (error) {
|
|
389
411
|
handleCommandError(error, UPDATE_EXAMPLES);
|
|
390
412
|
}
|
|
391
413
|
}
|
|
392
414
|
);
|
|
393
|
-
|
|
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) => {
|
|
394
418
|
const token = requireToken();
|
|
395
|
-
const data = await apiRequest(`/api/projects/${id}`, { method: "DELETE", token });
|
|
419
|
+
const data = await apiRequest(`/api/projects/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
396
420
|
console.log(JSON.stringify(data, null, 2));
|
|
397
421
|
});
|
|
398
422
|
}
|
|
@@ -411,15 +435,21 @@ function toMediaLinks(value) {
|
|
|
411
435
|
}
|
|
412
436
|
function registerPostCommand(program2) {
|
|
413
437
|
const post = program2.command("post").description("\u5185\u5BB9\uFF08\u5E16\u5B50\uFF09\u7684\u589E\u5220\u6539\u67E5");
|
|
414
|
-
post.command("list").description("\u5217\u51FA\u5185\u5BB9").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").action(async (opts) => {
|
|
415
|
-
const data = await apiRequest("/api/posts", {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
438
|
+
withApiUrl(post.command("list").description("\u5217\u51FA\u5185\u5BB9")).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").action(async (opts) => {
|
|
439
|
+
const data = await apiRequest("/api/posts", {
|
|
440
|
+
query: { projectId: opts.projectId, status: opts.status },
|
|
441
|
+
token: optionalToken(),
|
|
442
|
+
apiUrl: opts.apiUrl
|
|
443
|
+
});
|
|
420
444
|
console.log(JSON.stringify(data, null, 2));
|
|
421
445
|
});
|
|
422
|
-
post.command("
|
|
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) => {
|
|
423
453
|
const token = requireToken();
|
|
424
454
|
try {
|
|
425
455
|
const body = postCreateSchema.parse({
|
|
@@ -428,13 +458,13 @@ function registerPostCommand(program2) {
|
|
|
428
458
|
projectId: opts.projectId,
|
|
429
459
|
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
430
460
|
});
|
|
431
|
-
const data = await apiRequest("/api/posts", { method: "POST", body, token });
|
|
461
|
+
const data = await apiRequest("/api/posts", { method: "POST", body, token, apiUrl: opts.apiUrl });
|
|
432
462
|
console.log(JSON.stringify(data, null, 2));
|
|
433
463
|
} catch (error) {
|
|
434
464
|
handleCommandError(error, CREATE_EXAMPLES2);
|
|
435
465
|
}
|
|
436
466
|
});
|
|
437
|
-
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").option("--body <body>", "\u5185\u5BB9\u6B63\u6587").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u5A92\u4F53\u94FE\u63A5").action(async (id, opts) => {
|
|
467
|
+
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").option("--body <body>", "\u5185\u5BB9\u6B63\u6587").option("--media-links <urls>", "\u9017\u53F7\u5206\u9694\u7684\u5A92\u4F53\u94FE\u63A5").action(async (id, opts) => {
|
|
438
468
|
const token = requireToken();
|
|
439
469
|
try {
|
|
440
470
|
const body = postUpdateSchema.parse({
|
|
@@ -442,17 +472,19 @@ function registerPostCommand(program2) {
|
|
|
442
472
|
body: opts.body,
|
|
443
473
|
mediaLinks: toMediaLinks(opts.mediaLinks)
|
|
444
474
|
});
|
|
445
|
-
const data = await apiRequest(`/api/posts/${id}`, { method: "PATCH", body, token });
|
|
475
|
+
const data = await apiRequest(`/api/posts/${id}`, { method: "PATCH", body, token, apiUrl: opts.apiUrl });
|
|
446
476
|
console.log(JSON.stringify(data, null, 2));
|
|
447
477
|
} catch (error) {
|
|
448
478
|
handleCommandError(error, UPDATE_EXAMPLES2);
|
|
449
479
|
}
|
|
450
480
|
});
|
|
451
|
-
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(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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) => {
|
|
483
|
+
const token = requireToken();
|
|
484
|
+
const data = await apiRequest(`/api/posts/${id}`, { method: "DELETE", token, apiUrl: opts.apiUrl });
|
|
485
|
+
console.log(JSON.stringify(data, null, 2));
|
|
486
|
+
}
|
|
487
|
+
);
|
|
456
488
|
}
|
|
457
489
|
|
|
458
490
|
// src/index.ts
|