@qcplay/cli 1.0.0 → 1.0.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/bin/qcplay.js CHANGED
@@ -8,11 +8,35 @@ import { fileURLToPath } from "url";
8
8
 
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
+ const PACKAGE_JSON = path.resolve(__dirname, "../package.json");
12
+
13
+ function readPackageVersion() {
14
+ try {
15
+ const packageJson = JSON.parse(fs.readFileSync(PACKAGE_JSON, "utf8"));
16
+ return packageJson.version || "0.0.0";
17
+ } catch {
18
+ return "0.0.0";
19
+ }
20
+ }
21
+
22
+ const PACKAGE_VERSION = readPackageVersion();
11
23
 
12
24
  const QCPLAY_DIR = path.join(os.homedir(), ".qcplay");
25
+ const AGENTS_DIR = path.join(os.homedir(), ".agents");
13
26
  const AUTH_FILE = path.join(QCPLAY_DIR, "auth.json");
14
27
  const CONFIG_FILE = path.join(QCPLAY_DIR, "config.json");
15
- const SKILLS_DIR = path.join(QCPLAY_DIR, "skills");
28
+
29
+ function getSkillsDir() {
30
+ const agentsSkillsDir = path.join(AGENTS_DIR, "skills");
31
+
32
+ if (fs.existsSync(agentsSkillsDir) || fs.existsSync(AGENTS_DIR)) {
33
+ return agentsSkillsDir;
34
+ }
35
+
36
+ return path.join(QCPLAY_DIR, "skills");
37
+ }
38
+
39
+ const SKILLS_DIR = getSkillsDir();
16
40
 
17
41
  const colorsEnabled = process.stdout.isTTY && process.env.NO_COLOR !== "1";
18
42
 
@@ -38,6 +62,7 @@ function printRootHelp() {
38
62
  Usage:
39
63
  qcplay-cli install
40
64
  qcplay-cli auth [login|status|logout]
65
+ qcplay-cli auth permissions [--key <key>] [--json]
41
66
  qcplay-cli article
42
67
  qcplay-cli article init [file]
43
68
  qcplay-cli article publish <file> [--env <env>] [--url <url>] [--dry-run]
@@ -56,6 +81,7 @@ function printAuthHelp() {
56
81
  console.log(" qcplay-cli auth");
57
82
  console.log(" qcplay-cli auth status");
58
83
  console.log(" qcplay-cli auth logout");
84
+ console.log(" qcplay-cli auth permissions [--key <key>] [--json]");
59
85
  }
60
86
 
61
87
  function printArticleHelp() {
@@ -81,9 +107,34 @@ function getVendorDir() {
81
107
  throw new Error(`Unsupported platform: ${process.platform}`);
82
108
  }
83
109
 
110
+ function getExeCandidates(name) {
111
+ if (process.platform === "win32") {
112
+ return [`${name}.exe`, name];
113
+ }
114
+
115
+ if (process.platform === "darwin") {
116
+ return [`${name}-darwin-${process.arch}`, name];
117
+ }
118
+
119
+ if (process.platform === "linux") {
120
+ return [`${name}-linux-${process.arch}`, name];
121
+ }
122
+
123
+ return [name];
124
+ }
125
+
84
126
  function getExePath(name) {
85
127
  const vendorDir = getVendorDir();
86
- return process.platform === "win32" ? path.join(vendorDir, `${name}.exe`) : path.join(vendorDir, name);
128
+ const candidates = getExeCandidates(name);
129
+
130
+ for (const candidate of candidates) {
131
+ const exePath = path.join(vendorDir, candidate);
132
+ if (fs.existsSync(exePath)) {
133
+ return exePath;
134
+ }
135
+ }
136
+
137
+ return path.join(vendorDir, candidates[0]);
87
138
  }
88
139
 
89
140
  function runNative(name, args = []) {
@@ -114,6 +165,20 @@ function runNative(name, args = []) {
114
165
  });
115
166
  }
116
167
 
168
+ async function runAuthLogin() {
169
+ try {
170
+ await runNative("qcplay-auth", []);
171
+ } catch (err) {
172
+ const message = String(err?.message || err);
173
+
174
+ if (!message.includes("退出码")) {
175
+ throw err;
176
+ }
177
+
178
+ await runNative("qcplay-auth", ["login"]);
179
+ }
180
+ }
181
+
117
182
  async function pathExists(targetPath) {
118
183
  try {
119
184
  await fs.promises.access(targetPath);
@@ -176,7 +241,7 @@ async function installSkills() {
176
241
  async function saveConfig() {
177
242
  await writeJson(CONFIG_FILE, {
178
243
  cli: "qcplay-cli",
179
- version: "1.0.0",
244
+ version: PACKAGE_VERSION,
180
245
  auth_file: AUTH_FILE,
181
246
  skills_dir: SKILLS_DIR,
182
247
  configured_at: Date.now()
@@ -252,6 +317,11 @@ function printFeatures() {
252
317
  console.log(" qcplay-cli auth");
253
318
  console.log("");
254
319
 
320
+ console.log(chalk.cyan("2. 查看权限"));
321
+ console.log(" qcplay-cli auth permissions");
322
+ console.log(" qcplay-cli auth permissions --key www-article-list.store");
323
+ console.log("");
324
+
255
325
  console.log(chalk.cyan("4. 发布官网文章"));
256
326
  console.log(" qcplay-cli www-article-list.store article.md");
257
327
  console.log(chalk.gray(" 文章标题、分类、缩略图、标签等信息写在 article.md 顶部 Front Matter 中。"));
@@ -266,6 +336,37 @@ function printWhere() {
266
336
  console.log(QCPLAY_DIR);
267
337
  }
268
338
 
339
+ function parsePermissionsOptions(args) {
340
+ const options = {
341
+ key: undefined,
342
+ json: false
343
+ };
344
+
345
+ for (let index = 0; index < args.length; index += 1) {
346
+ const current = args[index];
347
+
348
+ if (current === "--json") {
349
+ options.json = true;
350
+ continue;
351
+ }
352
+
353
+ if (current === "--key") {
354
+ const next = args[index + 1];
355
+ if (!next || next.startsWith("--")) {
356
+ throw new Error("--key 缺少参数值");
357
+ }
358
+
359
+ options.key = next;
360
+ index += 1;
361
+ continue;
362
+ }
363
+
364
+ throw new Error(`未知参数: ${current}`);
365
+ }
366
+
367
+ return options;
368
+ }
369
+
269
370
  async function installCommand() {
270
371
  console.log("");
271
372
  console.log(chalk.cyan("正在安装 QCPlay CLI..."));
@@ -277,6 +378,7 @@ async function installCommand() {
277
378
  const skillsInstalled = await installSkills();
278
379
  if (skillsInstalled) {
279
380
  console.log(chalk.green("✔ Skills 已安装"));
381
+ console.log(`Skills 目录: ${chalk.gray(SKILLS_DIR)}`);
280
382
  } else {
281
383
  console.log(chalk.yellow("! 未找到 Skills 模板,已跳过"));
282
384
  }
@@ -289,39 +391,32 @@ async function installCommand() {
289
391
  console.log(chalk.gray("请在浏览器中完成账号密码登录。"));
290
392
  console.log("");
291
393
 
292
- await runNative("qcplay-auth", ["login"]);
394
+ await runAuthLogin();
293
395
 
294
396
  const loginStatus = await getLoginStatus();
295
397
  if (!loginStatus.ok) {
296
398
  throw new Error(`登录流程结束,但未检测到有效认证文件。\n原因: ${loginStatus.reason}`);
297
399
  }
298
400
 
299
- console.log("");
300
- console.log(chalk.green("✔ 登录成功"));
301
- console.log(`认证文件: ${chalk.gray(AUTH_FILE)}`);
302
-
303
401
  console.log("");
304
402
  console.log(chalk.green("✔ QCPlay CLI 安装完成"));
305
403
 
306
404
  printFeatures();
307
405
  }
308
406
 
309
- async function authCommand(action) {
407
+ async function authCommand(action, args = []) {
310
408
  if (!action || action === "login") {
311
409
  console.log("");
312
410
  console.log(chalk.cyan("正在打开 QCPlay 登录窗口..."));
313
411
  console.log("");
314
412
 
315
- await runNative("qcplay-auth", ["login"]);
413
+ await runAuthLogin();
316
414
 
317
415
  const loginStatus = await getLoginStatus();
318
416
  if (!loginStatus.ok) {
319
417
  throw new Error(`登录失败。\n原因: ${loginStatus.reason}`);
320
418
  }
321
419
 
322
- console.log("");
323
- console.log(chalk.green("✔ 登录成功"));
324
- console.log(`认证文件: ${chalk.gray(AUTH_FILE)}`);
325
420
  return;
326
421
  }
327
422
 
@@ -338,7 +433,6 @@ async function authCommand(action) {
338
433
  }
339
434
 
340
435
  console.log(chalk.green("已登录"));
341
- console.log(`认证文件: ${AUTH_FILE}`);
342
436
  return;
343
437
  }
344
438
 
@@ -348,6 +442,28 @@ async function authCommand(action) {
348
442
  return;
349
443
  }
350
444
 
445
+ if (action === "permissions") {
446
+ const loginStatus = await getLoginStatus();
447
+
448
+ if (!loginStatus.ok) {
449
+ throw new Error(`未检测到有效登录状态。\n原因: ${loginStatus.reason}\n请先执行:qcplay-cli auth`);
450
+ }
451
+
452
+ const options = parsePermissionsOptions(args);
453
+ const nativeArgs = ["permissions"];
454
+
455
+ if (options.key) {
456
+ nativeArgs.push("--key", options.key);
457
+ }
458
+
459
+ if (options.json) {
460
+ nativeArgs.push("--json");
461
+ }
462
+
463
+ await runNative("qcplay-auth", nativeArgs);
464
+ return;
465
+ }
466
+
351
467
  printAuthHelp();
352
468
  }
353
469
 
@@ -584,7 +700,7 @@ async function main() {
584
700
  }
585
701
 
586
702
  if (command === "-V" || command === "--version") {
587
- console.log("1.0.0");
703
+ console.log(PACKAGE_VERSION);
588
704
  return;
589
705
  }
590
706
 
@@ -599,7 +715,7 @@ async function main() {
599
715
  return;
600
716
  }
601
717
 
602
- await runWithErrorBanner("认证失败", () => authCommand(subcommand));
718
+ await runWithErrorBanner("认证失败", () => authCommand(subcommand, rest));
603
719
  return;
604
720
  }
605
721
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qcplay/cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "QCPlay CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,7 +18,7 @@
18
18
  "registry": "https://registry.npmjs.org/"
19
19
  },
20
20
  "engines": {
21
- "node": ">=16 <17",
21
+ "node": ">=16",
22
22
  "npm": ">=8"
23
23
  },
24
24
  "scripts": {
@@ -204,6 +204,12 @@ Windows 示例:
204
204
  C:\Users\Administrator\.qcplay\auth.json
205
205
  ```
206
206
 
207
+ macOS 示例:
208
+
209
+ ```bash
210
+ /Users/<your-name>/.qcplay/auth.json
211
+ ```
212
+
207
213
  认证文件格式:
208
214
 
209
215
  ```json
@@ -1158,4 +1164,4 @@ Node 只做路由。
1158
1164
  Go 负责发布。
1159
1165
  默认参数程序内部补齐。
1160
1166
  发布失败不得伪造成成功。
1161
- ```
1167
+ ```
Binary file