@yizhuan-cli/cli 0.1.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 +37 -0
- package/package.json +31 -0
- package/src/index.js +166 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @yizhuan-cli/cli
|
|
2
|
+
|
|
3
|
+
易撰命令行工具,用于通过 API Key 查询易撰真实数据。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @yizhuan-cli/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
如果发布在私有 npm registry,请加上对应 registry:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @yizhuan-cli/cli --registry=https://your-private-registry.example
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 配置
|
|
18
|
+
|
|
19
|
+
创建 `~/.config/yizhuan/config.json`:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"apiBaseUrl": "https://api.yizhuan5.com",
|
|
24
|
+
"apiKey": "yz_cli_xxx"
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 使用
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
yizhuan --help
|
|
32
|
+
yizhuan --version
|
|
33
|
+
yizhuan config path
|
|
34
|
+
yizhuan config show
|
|
35
|
+
yizhuan execute --ability membership_info
|
|
36
|
+
yizhuan execute --ability content_search --query "百家号昨天新增了哪些作品"
|
|
37
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yizhuan-cli/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "易撰命令行工具,用于通过 API Key 查询易撰真实数据。",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"yizhuan": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"start": "node src/index.js",
|
|
16
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
17
|
+
"smoke": "node src/index.js --help && node src/index.js --version"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=22"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"yizhuan",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"author": "zoy",
|
|
27
|
+
"license": "UNLICENSED",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "restricted"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import os from 'node:os'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const CLI_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
8
|
+
const PACKAGE_PATH = path.join(CLI_DIR, 'package.json')
|
|
9
|
+
const CONFIG_PATH = path.join(os.homedir(), '.config', 'yizhuan', 'config.json')
|
|
10
|
+
const ABILITIES = new Set([
|
|
11
|
+
'author_query',
|
|
12
|
+
'statistics',
|
|
13
|
+
'content_search',
|
|
14
|
+
'hot_topic_analysis',
|
|
15
|
+
'work_query',
|
|
16
|
+
'membership_info',
|
|
17
|
+
'favorites_query'
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
function printHelp() {
|
|
21
|
+
console.log(`易撰 CLI
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
yizhuan --help
|
|
25
|
+
yizhuan --version
|
|
26
|
+
yizhuan execute --ability <ability> [--query <text>] [--params <json>]
|
|
27
|
+
yizhuan config path
|
|
28
|
+
yizhuan config show
|
|
29
|
+
|
|
30
|
+
Abilities:
|
|
31
|
+
author_query 作者查询
|
|
32
|
+
statistics 数据统计
|
|
33
|
+
content_search 内容检索
|
|
34
|
+
hot_topic_analysis 热点分析
|
|
35
|
+
work_query 作品查询
|
|
36
|
+
membership_info 会员信息
|
|
37
|
+
favorites_query 收藏
|
|
38
|
+
|
|
39
|
+
Config:
|
|
40
|
+
${CONFIG_PATH}
|
|
41
|
+
`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function readPackageVersion() {
|
|
45
|
+
try {
|
|
46
|
+
const packageJson = JSON.parse(fs.readFileSync(PACKAGE_PATH, 'utf8'))
|
|
47
|
+
return packageJson.version || '0.0.0'
|
|
48
|
+
} catch {
|
|
49
|
+
return '0.0.0'
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function parseArgs(argv) {
|
|
54
|
+
const args = { _: [] }
|
|
55
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
56
|
+
const value = argv[index]
|
|
57
|
+
if (value.startsWith('--')) {
|
|
58
|
+
const key = value.slice(2)
|
|
59
|
+
const next = argv[index + 1]
|
|
60
|
+
if (!next || next.startsWith('--')) {
|
|
61
|
+
args[key] = true
|
|
62
|
+
} else {
|
|
63
|
+
args[key] = next
|
|
64
|
+
index += 1
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
args._.push(value)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return args
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function readConfig() {
|
|
74
|
+
if (!fs.existsSync(CONFIG_PATH)) {
|
|
75
|
+
throw new Error(`未找到配置文件:${CONFIG_PATH}`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'))
|
|
79
|
+
if (!config.apiBaseUrl || !config.apiKey) {
|
|
80
|
+
throw new Error('配置文件必须包含 apiBaseUrl 和 apiKey')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
apiBaseUrl: String(config.apiBaseUrl).replace(/\/+$/, ''),
|
|
85
|
+
apiKey: String(config.apiKey)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function parseParams(value) {
|
|
90
|
+
if (!value) return undefined
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(value)
|
|
93
|
+
} catch {
|
|
94
|
+
throw new Error('--params 必须是 JSON,例如:--params "{\\"page\\":1}"')
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function execute(args) {
|
|
99
|
+
const ability = args.ability
|
|
100
|
+
if (!ABILITIES.has(ability)) {
|
|
101
|
+
throw new Error(`未知 ability:${ability || ''},请执行 yizhuan --help 查看可用能力`)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const config = readConfig()
|
|
105
|
+
const response = await fetch(`${config.apiBaseUrl}/api/cli.execute`, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
headers: {
|
|
108
|
+
authorization: config.apiKey,
|
|
109
|
+
'content-type': 'application/json',
|
|
110
|
+
'x-device-type': 'pc'
|
|
111
|
+
},
|
|
112
|
+
body: JSON.stringify({
|
|
113
|
+
json: {
|
|
114
|
+
ability,
|
|
115
|
+
query: args.query,
|
|
116
|
+
params: parseParams(args.params)
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
const text = await response.text()
|
|
121
|
+
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`请求失败 HTTP ${response.status}:${text}`)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const payload = JSON.parse(text)
|
|
127
|
+
console.log(JSON.stringify(payload.result?.data?.json ?? payload, null, 2))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function main() {
|
|
131
|
+
const args = parseArgs(process.argv.slice(2))
|
|
132
|
+
const command = args._[0]
|
|
133
|
+
|
|
134
|
+
if (args.version || command === '--version' || command === '-v') {
|
|
135
|
+
console.log(readPackageVersion())
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!command || command === '--help' || command === '-h') {
|
|
140
|
+
printHelp()
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (command === 'config' && args._[1] === 'path') {
|
|
145
|
+
console.log(CONFIG_PATH)
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (command === 'config' && args._[1] === 'show') {
|
|
150
|
+
const config = readConfig()
|
|
151
|
+
console.log(JSON.stringify({ ...config, apiKey: `${config.apiKey.slice(0, 18)}...` }, null, 2))
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (command === 'execute') {
|
|
156
|
+
await execute(args)
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
throw new Error(`未知命令:${command}`)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
main().catch((error) => {
|
|
164
|
+
console.error(error.message)
|
|
165
|
+
process.exit(1)
|
|
166
|
+
})
|