@qs_cli/polaris-cli 0.0.0-stage → 0.2.3
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 +48 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +46 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +8 -0
- package/dist/client.js +63 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +144 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +111 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/env.d.ts +2 -0
- package/dist/commands/env.js +38 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/net.d.ts +2 -0
- package/dist/commands/net.js +152 -0
- package/dist/commands/net.js.map +1 -0
- package/dist/commands/user.d.ts +2 -0
- package/dist/commands/user.js +93 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/help.d.ts +2 -0
- package/dist/help.js +23 -0
- package/dist/help.js.map +1 -0
- package/dist/utils/curl.d.ts +1 -0
- package/dist/utils/curl.js +43 -0
- package/dist/utils/curl.js.map +1 -0
- package/dist/utils/format.d.ts +8 -0
- package/dist/utils/format.js +70 -0
- package/dist/utils/format.js.map +1 -0
- package/package.json +31 -4
package/README.md
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Polaris CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
观星台命令行查询工具,无需打开网页即可查询网络请求和用户账号信息。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
要求 Node.js 18 或更高版本。默认查询线上服务 `https://polaris.yfcenter.com`。
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @qs_cli/polaris-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
也可以在源码目录本地安装:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd polaris_cli
|
|
17
|
+
./install.sh
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
卸载:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
./uninstall.sh
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 快速开始
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
polaris env local # 切换到本地服务
|
|
30
|
+
polaris env online # 切换到线上服务
|
|
31
|
+
polaris login # 浏览器飞书授权
|
|
32
|
+
polaris whoami
|
|
33
|
+
polaris doctor
|
|
34
|
+
|
|
35
|
+
polaris net list --uid 123 --from '2026-11-10 00:00:00'
|
|
36
|
+
polaris net get 100 --curl
|
|
37
|
+
polaris user 123 --env qa
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
执行 `polaris help` 或 `polaris <command> --help` 查看完整参数和示例。
|
|
41
|
+
|
|
42
|
+
配置和不同环境的登录凭证保存在 `~/.polaris/config.json`,文件权限为 `0600`。
|
|
43
|
+
|
|
44
|
+
`polaris` 与 `polaris_cli` 是完全等价的命令入口,例如:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
polaris net list
|
|
48
|
+
polaris_cli net list
|
|
49
|
+
```
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command, CommanderError } from 'commander';
|
|
3
|
+
import { registerAuthCommands } from './commands/auth.js';
|
|
4
|
+
import { registerDoctorCommand } from './commands/doctor.js';
|
|
5
|
+
import { registerEnvCommand } from './commands/env.js';
|
|
6
|
+
import { registerNetCommand } from './commands/net.js';
|
|
7
|
+
import { registerUserCommand } from './commands/user.js';
|
|
8
|
+
import { configureHelp } from './help.js';
|
|
9
|
+
const VERSION = '0.2.3';
|
|
10
|
+
const program = new Command();
|
|
11
|
+
program
|
|
12
|
+
.name('polaris')
|
|
13
|
+
.description('观星台命令行查询工具')
|
|
14
|
+
.version(VERSION)
|
|
15
|
+
.option('--service-env <local|online>', '单次覆盖 Polaris 服务环境')
|
|
16
|
+
.option('--base <url>', '单次覆盖服务 Base URL')
|
|
17
|
+
.option('--json', '以 JSON 输出')
|
|
18
|
+
.helpCommand('help [command]', '显示命令帮助');
|
|
19
|
+
configureHelp(program);
|
|
20
|
+
registerAuthCommands(program);
|
|
21
|
+
registerEnvCommand(program);
|
|
22
|
+
registerDoctorCommand(program, VERSION);
|
|
23
|
+
registerNetCommand(program);
|
|
24
|
+
registerUserCommand(program);
|
|
25
|
+
program.exitOverride();
|
|
26
|
+
async function main() {
|
|
27
|
+
if (process.argv.length <= 2) {
|
|
28
|
+
program.outputHelp();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await program.parseAsync(process.argv);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error instanceof CommanderError) {
|
|
36
|
+
if (['commander.helpDisplayed', 'commander.version'].includes(error.code))
|
|
37
|
+
return;
|
|
38
|
+
process.exitCode = error.exitCode || 1;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
console.error(`错误: ${error instanceof Error ? error.message : String(error)}`);
|
|
42
|
+
process.exitCode = 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
await main();
|
|
46
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,OAAO,GAAG,OAAO,CAAA;AACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,YAAY,CAAC;KACzB,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,8BAA8B,EAAE,mBAAmB,CAAC;KAC3D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC;KACzC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC;KAC7B,WAAW,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAA;AAE1C,aAAa,CAAC,OAAO,CAAC,CAAA;AACtB,oBAAoB,CAAC,OAAO,CAAC,CAAA;AAC7B,kBAAkB,CAAC,OAAO,CAAC,CAAA;AAC3B,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACvC,kBAAkB,CAAC,OAAO,CAAC,CAAA;AAC3B,mBAAmB,CAAC,OAAO,CAAC,CAAA;AAE5B,OAAO,CAAC,YAAY,EAAE,CAAA;AAEtB,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,UAAU,EAAE,CAAA;QACpB,OAAM;IACR,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;YACpC,IAAI,CAAC,yBAAyB,EAAE,mBAAmB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,OAAM;YACjF,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC9E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACtB,CAAC;AACH,CAAC;AAED,MAAM,IAAI,EAAE,CAAA"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RequestContext } from './config.js';
|
|
2
|
+
export declare class ApiError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly body?: unknown | undefined;
|
|
5
|
+
constructor(message: string, status: number, body?: unknown | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare function apiRequest<T>(context: RequestContext, path: string, init?: RequestInit, timeoutMs?: number): Promise<T>;
|
|
8
|
+
export declare function queryPath(path: string, params: Record<string, unknown>): string;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
body;
|
|
4
|
+
constructor(message, status, body) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.body = body;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export async function apiRequest(context, path, init = {}, timeoutMs = 15_000) {
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
13
|
+
const headers = new Headers(init.headers);
|
|
14
|
+
headers.set('Accept', 'application/json');
|
|
15
|
+
if (context.token)
|
|
16
|
+
headers.set('Authorization', `Bearer ${context.token}`);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(`${context.baseUrl}${path}`, {
|
|
19
|
+
...init,
|
|
20
|
+
headers,
|
|
21
|
+
signal: controller.signal,
|
|
22
|
+
});
|
|
23
|
+
const text = await response.text();
|
|
24
|
+
let body;
|
|
25
|
+
try {
|
|
26
|
+
body = text ? JSON.parse(text) : undefined;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
body = text;
|
|
30
|
+
}
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const serverMessage = body && typeof body === 'object' && 'error' in body
|
|
33
|
+
? String(body.error)
|
|
34
|
+
: response.statusText;
|
|
35
|
+
const hint = response.status === 401 ? ';请先执行 polaris login' :
|
|
36
|
+
response.status === 403 ? ';当前账号权限不足' : '';
|
|
37
|
+
throw new ApiError(`请求失败 (${response.status}): ${serverMessage}${hint}`, response.status, body);
|
|
38
|
+
}
|
|
39
|
+
return body;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof ApiError)
|
|
43
|
+
throw error;
|
|
44
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
45
|
+
throw new Error(`请求超时: ${context.baseUrl}${path}`);
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`无法访问 ${context.baseUrl}: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function queryPath(path, params) {
|
|
54
|
+
const search = new URLSearchParams();
|
|
55
|
+
for (const [key, value] of Object.entries(params)) {
|
|
56
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
57
|
+
search.set(key, String(value));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const query = search.toString();
|
|
61
|
+
return query ? `${path}?${query}` : path;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,IAAc;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAA;QAHE,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAU;IAGhC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAuB,EACvB,IAAY,EACZ,OAAoB,EAAE,EACtB,SAAS,GAAG,MAAM;IAElB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAA;IAC7D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACzC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;IACzC,IAAI,OAAO,CAAC,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;IAE1E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YACxD,GAAG,IAAI;YACP,OAAO;YACP,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAClC,IAAI,IAAa,CAAA;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,IAAI,CAAA;QACb,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,aAAa,GACjB,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI;gBACjD,CAAC,CAAC,MAAM,CAAE,IAA2B,CAAC,KAAK,CAAC;gBAC5C,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAA;YACzB,MAAM,IAAI,GACR,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;gBACjD,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;YAC5C,MAAM,IAAI,QAAQ,CAAC,SAAS,QAAQ,CAAC,MAAM,MAAM,aAAa,GAAG,IAAI,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACjG,CAAC;QACD,OAAO,IAAS,CAAA;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,QAAQ;YAAE,MAAM,KAAK,CAAA;QAC1C,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC,CAAA;QACpD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,QAAQ,OAAO,CAAC,OAAO,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACvG,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,MAA+B;IACrE,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC1D,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAC/B,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { apiRequest } from '../client.js';
|
|
4
|
+
import { loadConfig, resolveContext, saveConfig, } from '../config.js';
|
|
5
|
+
import { printJson } from '../utils/format.js';
|
|
6
|
+
function tokenExpiresAt(token) {
|
|
7
|
+
if (!token)
|
|
8
|
+
return null;
|
|
9
|
+
try {
|
|
10
|
+
const body = token.split('.')[0];
|
|
11
|
+
const payload = JSON.parse(Buffer.from(body, 'base64url').toString('utf8'));
|
|
12
|
+
return payload.exp ? new Date(payload.exp * 1000).toISOString() : null;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function contextOf(command) {
|
|
19
|
+
return resolveContext(command.optsWithGlobals());
|
|
20
|
+
}
|
|
21
|
+
function openBrowser(url) {
|
|
22
|
+
const [command, args] = process.platform === 'darwin' ? ['open', [url]] :
|
|
23
|
+
process.platform === 'win32' ? ['cmd', ['/c', 'start', '', url]] :
|
|
24
|
+
['xdg-open', [url]];
|
|
25
|
+
try {
|
|
26
|
+
const child = spawn(command, args, { detached: true, stdio: 'ignore' });
|
|
27
|
+
child.on('error', () => undefined);
|
|
28
|
+
child.unref();
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function callbackPage(ok, message) {
|
|
36
|
+
const title = ok ? 'Polaris CLI 授权成功' : 'Polaris CLI 授权失败';
|
|
37
|
+
const safeMessage = message
|
|
38
|
+
.replaceAll('&', '&')
|
|
39
|
+
.replaceAll('<', '<')
|
|
40
|
+
.replaceAll('>', '>')
|
|
41
|
+
.replaceAll('"', '"')
|
|
42
|
+
.replaceAll("'", ''');
|
|
43
|
+
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><title>${title}</title></head>
|
|
44
|
+
<body style="font-family:-apple-system,sans-serif;padding:48px"><h2>${title}</h2><p>${safeMessage}</p>
|
|
45
|
+
<script>history.replaceState({}, document.title, location.pathname);</script></body></html>`;
|
|
46
|
+
}
|
|
47
|
+
async function login(command) {
|
|
48
|
+
const context = contextOf(command);
|
|
49
|
+
let server;
|
|
50
|
+
try {
|
|
51
|
+
const listener = await startLoginListener();
|
|
52
|
+
server = listener.server;
|
|
53
|
+
const loginUrl = `${context.baseUrl}/api/v1/auth/feishu/login?cli_port=${listener.port}`;
|
|
54
|
+
console.log(`正在打开浏览器完成 ${context.env} 环境的飞书登录…`);
|
|
55
|
+
console.log(`若浏览器未自动打开,请访问:\n${loginUrl}`);
|
|
56
|
+
openBrowser(loginUrl);
|
|
57
|
+
const token = await listener.token;
|
|
58
|
+
const config = loadConfig();
|
|
59
|
+
config.tokens[context.env] = { token, savedAt: new Date().toISOString() };
|
|
60
|
+
saveConfig(config);
|
|
61
|
+
const authenticated = { ...context, token };
|
|
62
|
+
const me = await apiRequest(authenticated, '/api/v1/auth/me');
|
|
63
|
+
console.log(`登录成功:${me.user?.name || me.user?.email || '未知用户'}(${me.user?.role || '-'})`);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
server?.close();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function startLoginListener() {
|
|
70
|
+
let resolveToken;
|
|
71
|
+
let rejectToken;
|
|
72
|
+
let settled = false;
|
|
73
|
+
const token = new Promise((resolve, reject) => {
|
|
74
|
+
resolveToken = resolve;
|
|
75
|
+
rejectToken = reject;
|
|
76
|
+
});
|
|
77
|
+
const server = createServer((request, response) => {
|
|
78
|
+
const url = new URL(request.url || '/', 'http://127.0.0.1');
|
|
79
|
+
if (url.pathname !== '/callback') {
|
|
80
|
+
response.writeHead(404).end('Not found');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const value = url.searchParams.get('token');
|
|
84
|
+
const callbackError = url.searchParams.get('error');
|
|
85
|
+
if (!value) {
|
|
86
|
+
response.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
87
|
+
response.end(callbackPage(false, callbackError || '没有收到登录凭证,请返回终端重试。'));
|
|
88
|
+
if (!settled) {
|
|
89
|
+
settled = true;
|
|
90
|
+
rejectToken(new Error(callbackError ? `飞书授权失败: ${callbackError}` : '登录回调缺少 token'));
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
95
|
+
response.end(callbackPage(true, '凭证已保存,可以关闭此页面并返回终端。'));
|
|
96
|
+
if (!settled) {
|
|
97
|
+
settled = true;
|
|
98
|
+
resolveToken(value);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
await new Promise((resolve, reject) => {
|
|
102
|
+
server.once('error', reject);
|
|
103
|
+
server.listen(0, '127.0.0.1', resolve);
|
|
104
|
+
});
|
|
105
|
+
const timer = setTimeout(() => {
|
|
106
|
+
if (!settled) {
|
|
107
|
+
settled = true;
|
|
108
|
+
rejectToken(new Error('登录等待超时(5 分钟)'));
|
|
109
|
+
}
|
|
110
|
+
}, 5 * 60_000);
|
|
111
|
+
token.finally(() => clearTimeout(timer)).catch(() => undefined);
|
|
112
|
+
return { port: server.address().port, server, token };
|
|
113
|
+
}
|
|
114
|
+
async function whoami(command) {
|
|
115
|
+
const context = contextOf(command);
|
|
116
|
+
const me = await apiRequest(context, '/api/v1/auth/me');
|
|
117
|
+
const expiresAt = tokenExpiresAt(context.token);
|
|
118
|
+
if (context.json) {
|
|
119
|
+
printJson({ ...me, token_expires_at: expiresAt });
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (!me.user) {
|
|
123
|
+
console.log('当前服务未启用登录认证。');
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log(`姓名: ${me.user.name || '-'}`);
|
|
127
|
+
console.log(`邮箱: ${me.user.email || '-'}`);
|
|
128
|
+
console.log(`角色: ${me.user.role}`);
|
|
129
|
+
console.log(`过期时间: ${expiresAt ? new Date(expiresAt).toLocaleString('zh-CN', { hour12: false }) : '-'}`);
|
|
130
|
+
console.log(`环境: ${context.env}`);
|
|
131
|
+
}
|
|
132
|
+
function logout(command) {
|
|
133
|
+
const context = contextOf(command);
|
|
134
|
+
const config = loadConfig();
|
|
135
|
+
delete config.tokens[context.env];
|
|
136
|
+
saveConfig(config);
|
|
137
|
+
console.log(`已清除 ${context.env} 的本地登录凭证。`);
|
|
138
|
+
}
|
|
139
|
+
export function registerAuthCommands(program) {
|
|
140
|
+
program.command('login').description('通过浏览器完成飞书登录').action((_options, command) => login(command));
|
|
141
|
+
program.command('logout').description('清除当前环境的登录凭证').action((_options, command) => logout(command));
|
|
142
|
+
program.command('whoami').description('显示当前登录账号与角色').action((_options, command) => whoami(command));
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { accessSync, constants } from 'node:fs';
|
|
2
|
+
import { arch, platform, release } from 'node:os';
|
|
3
|
+
import { apiRequest } from '../client.js';
|
|
4
|
+
import { CONFIG_PATH, ENV_URLS, loadConfig, resolveContext, } from '../config.js';
|
|
5
|
+
import { printJson, table } from '../utils/format.js';
|
|
6
|
+
async function probe(baseUrl) {
|
|
7
|
+
const started = performance.now();
|
|
8
|
+
try {
|
|
9
|
+
const response = await fetch(`${baseUrl}/healthz`, {
|
|
10
|
+
signal: AbortSignal.timeout(5_000),
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ok: response.ok,
|
|
14
|
+
status: response.status,
|
|
15
|
+
elapsedMs: Math.round(performance.now() - started),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
elapsedMs: Math.round(performance.now() - started),
|
|
22
|
+
error: error instanceof Error ? error.message : String(error),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function registerDoctorCommand(program, version) {
|
|
27
|
+
program
|
|
28
|
+
.command('doctor')
|
|
29
|
+
.description('检查 CLI、配置、服务连通性和登录权限')
|
|
30
|
+
.option('--json', '以 JSON 输出')
|
|
31
|
+
.addHelpText('after', `
|
|
32
|
+
示例:
|
|
33
|
+
polaris doctor
|
|
34
|
+
polaris doctor --json`)
|
|
35
|
+
.action(async (options, command) => {
|
|
36
|
+
const globals = command.optsWithGlobals();
|
|
37
|
+
const context = resolveContext({ ...globals, json: options.json ?? globals.json });
|
|
38
|
+
const config = loadConfig();
|
|
39
|
+
let configReadable = true;
|
|
40
|
+
try {
|
|
41
|
+
accessSync(CONFIG_PATH, constants.R_OK);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
configReadable = false;
|
|
45
|
+
}
|
|
46
|
+
const [local, online] = await Promise.all([
|
|
47
|
+
probe(ENV_URLS.local),
|
|
48
|
+
probe(ENV_URLS.online),
|
|
49
|
+
]);
|
|
50
|
+
let me = null;
|
|
51
|
+
let meError;
|
|
52
|
+
if (context.token) {
|
|
53
|
+
try {
|
|
54
|
+
me = await apiRequest(context, '/api/v1/auth/me', {}, 5_000);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
meError = error instanceof Error ? error.message : String(error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
let userEnvs = null;
|
|
61
|
+
if (context.token) {
|
|
62
|
+
try {
|
|
63
|
+
userEnvs = await apiRequest(context, '/api/v1/user-lookup/envs', {}, 5_000);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// 角色不足时 doctor 的登录检查仍然有效。
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const result = {
|
|
70
|
+
cli: {
|
|
71
|
+
version,
|
|
72
|
+
node: process.version,
|
|
73
|
+
os: `${platform()} ${release()}`,
|
|
74
|
+
arch: arch(),
|
|
75
|
+
executable: process.argv[1],
|
|
76
|
+
},
|
|
77
|
+
config: {
|
|
78
|
+
path: CONFIG_PATH,
|
|
79
|
+
exists: configReadable,
|
|
80
|
+
env: context.env,
|
|
81
|
+
baseUrl: context.baseUrl,
|
|
82
|
+
defaultUserEnv: config.defaultUserEnv,
|
|
83
|
+
},
|
|
84
|
+
connectivity: { local, online },
|
|
85
|
+
auth: {
|
|
86
|
+
hasToken: Boolean(context.token),
|
|
87
|
+
me,
|
|
88
|
+
error: meError,
|
|
89
|
+
},
|
|
90
|
+
userLookupEnvs: userEnvs,
|
|
91
|
+
};
|
|
92
|
+
if (context.json) {
|
|
93
|
+
printJson(result);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
console.log(table(['检查项', '结果'], [
|
|
97
|
+
['CLI 版本', version],
|
|
98
|
+
['Node.js', process.version],
|
|
99
|
+
['系统', `${platform()} ${arch()}`],
|
|
100
|
+
['命令路径', process.argv[1]],
|
|
101
|
+
['配置文件', `${CONFIG_PATH}${configReadable ? '' : '(尚未创建)'}`],
|
|
102
|
+
['当前环境', `${context.env} (${context.baseUrl})`],
|
|
103
|
+
['用户查询默认环境', config.defaultUserEnv],
|
|
104
|
+
['Local 连通性', local.ok ? `正常 HTTP ${local.status} / ${local.elapsedMs}ms` : `失败 / ${local.error || local.status}`],
|
|
105
|
+
['Online 连通性', online.ok ? `正常 HTTP ${online.status} / ${online.elapsedMs}ms` : `失败 / ${online.error || online.status}`],
|
|
106
|
+
['登录凭证', context.token ? (meError ? `无效:${meError}` : '有效') : '未登录,请执行 polaris login'],
|
|
107
|
+
['用户查询环境', userEnvs ? JSON.stringify(userEnvs) : '不可用或权限不足'],
|
|
108
|
+
], [24, 100]));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CONFIG_PATH, ENV_URLS, loadConfig, saveConfig } from '../config.js';
|
|
2
|
+
function useEnv(name) {
|
|
3
|
+
if (name !== 'local' && name !== 'online') {
|
|
4
|
+
throw new Error(`未知环境: ${name};可选值为 local 或 online`);
|
|
5
|
+
}
|
|
6
|
+
const config = loadConfig();
|
|
7
|
+
config.env = name;
|
|
8
|
+
saveConfig(config);
|
|
9
|
+
console.log(`已切换到 ${name}: ${ENV_URLS[name]}`);
|
|
10
|
+
}
|
|
11
|
+
export function registerEnvCommand(program) {
|
|
12
|
+
const env = program
|
|
13
|
+
.command('env [env]')
|
|
14
|
+
.description('查看或切换 Polaris 服务环境')
|
|
15
|
+
.addHelpText('after', `
|
|
16
|
+
示例:
|
|
17
|
+
polaris env
|
|
18
|
+
polaris env local
|
|
19
|
+
polaris env online
|
|
20
|
+
polaris env use local
|
|
21
|
+
polaris env use online`)
|
|
22
|
+
.action((name) => {
|
|
23
|
+
if (name) {
|
|
24
|
+
useEnv(name);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const config = loadConfig();
|
|
28
|
+
console.log(`当前环境: ${config.env}`);
|
|
29
|
+
console.log(`Base URL: ${ENV_URLS[config.env]}`);
|
|
30
|
+
console.log(`配置文件: ${CONFIG_PATH}`);
|
|
31
|
+
console.log('\n切换环境: polaris env local | polaris env online');
|
|
32
|
+
});
|
|
33
|
+
env
|
|
34
|
+
.command('use <env>')
|
|
35
|
+
.description('切换默认服务环境(local 或 online)')
|
|
36
|
+
.action(useEnv);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAwB,MAAM,cAAc,CAAA;AAElG,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,sBAAsB,CAAC,CAAA;IACtD,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,CAAC,GAAG,GAAG,IAAuB,CAAA;IACpC,UAAU,CAAC,MAAM,CAAC,CAAA;IAClB,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,MAAM,GAAG,GAAG,OAAO;SAChB,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,oBAAoB,CAAC;SACjC,WAAW,CAAC,OAAO,EAAE;;;;;;yBAMD,CAAC;SACrB,MAAM,CAAC,CAAC,IAAa,EAAE,EAAE;QACxB,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,CAAA;YACZ,OAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;QAC3B,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;QACrC,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACnD,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,EAAE,CAAC,CAAA;QACtC,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;IAEJ,GAAG;SACA,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,MAAM,CAAC,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { apiRequest, queryPath } from '../client.js';
|
|
2
|
+
import { resolveContext } from '../config.js';
|
|
3
|
+
import { generateCurl } from '../utils/curl.js';
|
|
4
|
+
import { formatDate, limitLines, prettyContent, printJson, table, } from '../utils/format.js';
|
|
5
|
+
function positiveInt(value, name, max) {
|
|
6
|
+
const parsed = Number(value);
|
|
7
|
+
if (!Number.isInteger(parsed) || parsed <= 0 || (max !== undefined && parsed > max)) {
|
|
8
|
+
throw new Error(`${name} 必须是 1${max ? `-${max}` : ' 以上'}的整数`);
|
|
9
|
+
}
|
|
10
|
+
return parsed;
|
|
11
|
+
}
|
|
12
|
+
async function listNet(options, command) {
|
|
13
|
+
const context = resolveContext(command.optsWithGlobals());
|
|
14
|
+
const page = positiveInt(options.page, '--page');
|
|
15
|
+
const size = positiveInt(options.size, '--size', 200);
|
|
16
|
+
if (options.success && !['true', 'false'].includes(options.success)) {
|
|
17
|
+
throw new Error('--success 只能是 true 或 false');
|
|
18
|
+
}
|
|
19
|
+
if (options.bizCode && options.bizCode !== 'nonzero' && !/^-?\d+$/.test(options.bizCode)) {
|
|
20
|
+
throw new Error('--biz-code 只能是整数或 nonzero');
|
|
21
|
+
}
|
|
22
|
+
const path = queryPath('/api/v1/net', {
|
|
23
|
+
id: options.id,
|
|
24
|
+
user_uid: options.uid,
|
|
25
|
+
device_id: options.device,
|
|
26
|
+
method: options.method?.toUpperCase(),
|
|
27
|
+
host: options.host,
|
|
28
|
+
keyword: options.keyword,
|
|
29
|
+
status_code: options.status,
|
|
30
|
+
success: options.success,
|
|
31
|
+
biz_code: options.bizCode,
|
|
32
|
+
min_duration: options.minDuration,
|
|
33
|
+
app_id: options.appId,
|
|
34
|
+
app_version: options.appVersion,
|
|
35
|
+
from: options.from,
|
|
36
|
+
to: options.to,
|
|
37
|
+
page,
|
|
38
|
+
size,
|
|
39
|
+
});
|
|
40
|
+
const result = await apiRequest(context, path);
|
|
41
|
+
if (context.json) {
|
|
42
|
+
printJson(result);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
console.log(`共 ${result.total} 条,第 ${result.page} 页,每页 ${result.size} 条`);
|
|
46
|
+
if (!result.items.length) {
|
|
47
|
+
console.log('没有匹配的网络请求。');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
console.log(table(['ID', '时间', '方法', '状态', '耗时', 'UID', 'Host', 'Path'], result.items.map((item) => [
|
|
51
|
+
item.id,
|
|
52
|
+
formatDate(item.client_time),
|
|
53
|
+
item.method,
|
|
54
|
+
item.status_code,
|
|
55
|
+
`${item.duration_ms ?? 0}ms`,
|
|
56
|
+
item.user_uid,
|
|
57
|
+
item.host,
|
|
58
|
+
item.path,
|
|
59
|
+
]), [10, 20, 8, 8, 10, 16, 28, 48]));
|
|
60
|
+
}
|
|
61
|
+
function section(title, content) {
|
|
62
|
+
console.log(`\n${title}\n${'─'.repeat(Math.max(8, title.length * 2))}`);
|
|
63
|
+
console.log(content);
|
|
64
|
+
}
|
|
65
|
+
async function getNet(idRaw, options, command) {
|
|
66
|
+
const id = positiveInt(idRaw, 'id');
|
|
67
|
+
const maxLines = positiveInt(options.maxLines, '--max-lines', 100_000);
|
|
68
|
+
const context = resolveContext(command.optsWithGlobals());
|
|
69
|
+
const item = await apiRequest(context, `/api/v1/net/${id}`);
|
|
70
|
+
if (context.json) {
|
|
71
|
+
printJson(item);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
section('概要', table(['方法', 'URL', '状态码', '耗时', '成功', '业务码'], [[item.method, item.url, item.status_code, `${item.duration_ms}ms`, item.success, item.biz_code]], [8, 80, 8, 10, 8, 10]));
|
|
75
|
+
if (item.error)
|
|
76
|
+
console.log(`错误: ${item.error}`);
|
|
77
|
+
section('基本信息', table(['字段', '值'], [
|
|
78
|
+
['Host', item.host],
|
|
79
|
+
['Path', item.path],
|
|
80
|
+
['平台', item.platform],
|
|
81
|
+
['App ID', item.app_id],
|
|
82
|
+
['App 版本', item.app_version],
|
|
83
|
+
['OS 版本', item.os_version],
|
|
84
|
+
['UID', item.user_uid],
|
|
85
|
+
['设备 ID', item.device_id],
|
|
86
|
+
['IP', item.ip],
|
|
87
|
+
['客户端时间', formatDate(item.client_time)],
|
|
88
|
+
['服务端时间', formatDate(item.server_time)],
|
|
89
|
+
], [16, 100]));
|
|
90
|
+
try {
|
|
91
|
+
const url = new URL(String(item.url));
|
|
92
|
+
const params = [...url.searchParams.entries()];
|
|
93
|
+
section('Query 参数', params.length
|
|
94
|
+
? table(['参数名', '参数值'], params, [30, 100])
|
|
95
|
+
: '(无 query 参数)');
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
section('Query 参数', '(URL 无法解析)');
|
|
99
|
+
}
|
|
100
|
+
section('请求头', prettyContent(item.request_headers));
|
|
101
|
+
section('请求体', prettyContent(item.request_body));
|
|
102
|
+
if (options.respHeaders || options.all) {
|
|
103
|
+
section('响应头', prettyContent(item.response_headers));
|
|
104
|
+
}
|
|
105
|
+
section('响应体', limitLines(prettyContent(item.response_body), maxLines));
|
|
106
|
+
if (options.curl || options.all) {
|
|
107
|
+
section('curl', generateCurl(item));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export function registerNetCommand(program) {
|
|
111
|
+
const net = program.command('net').description('查询网络请求');
|
|
112
|
+
net
|
|
113
|
+
.command('list')
|
|
114
|
+
.description('按多种条件查询网络请求列表')
|
|
115
|
+
.option('--id <number>', '按记录 ID 精确查询')
|
|
116
|
+
.option('--uid <string>', '按用户 UID 查询')
|
|
117
|
+
.option('--device <string>', '按设备 ID 查询')
|
|
118
|
+
.option('--method <method>', 'HTTP 方法')
|
|
119
|
+
.option('--host <string>', 'Host')
|
|
120
|
+
.option('--keyword <string>', 'URL/Path 关键词')
|
|
121
|
+
.option('--status <number>', 'HTTP 状态码')
|
|
122
|
+
.option('--success <true|false>', '是否成功')
|
|
123
|
+
.option('--biz-code <number|nonzero>', '业务码')
|
|
124
|
+
.option('--min-duration <ms>', '最小耗时(毫秒)')
|
|
125
|
+
.option('--app-id <string>', 'App ID')
|
|
126
|
+
.option('--app-version <string>', 'App 版本')
|
|
127
|
+
.option('--from <time>', '开始时间')
|
|
128
|
+
.option('--to <time>', '结束时间')
|
|
129
|
+
.option('--page <number>', '页码', '1')
|
|
130
|
+
.option('--size <number>', '每页条数,最大 200', '20')
|
|
131
|
+
.addHelpText('after', `
|
|
132
|
+
示例:
|
|
133
|
+
polaris net list --uid 123
|
|
134
|
+
polaris net list --method POST --status 500 --from "2026-11-10 00:00:00"
|
|
135
|
+
polaris net list --biz-code nonzero --min-duration 1000 --json`)
|
|
136
|
+
.action(listNet);
|
|
137
|
+
net
|
|
138
|
+
.command('get <id>')
|
|
139
|
+
.description('查看一条网络请求详情')
|
|
140
|
+
.option('--curl', '显示可执行 curl 命令')
|
|
141
|
+
.option('--resp-headers', '显示响应头')
|
|
142
|
+
.option('--all', '显示响应头和 curl')
|
|
143
|
+
.option('--max-lines <number>', '响应体最大行数', '80')
|
|
144
|
+
.addHelpText('after', `
|
|
145
|
+
示例:
|
|
146
|
+
polaris net get 100
|
|
147
|
+
polaris net get 100 --curl
|
|
148
|
+
polaris net get 100 --all --max-lines 200
|
|
149
|
+
polaris net get 100 --json`)
|
|
150
|
+
.action(getNet);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=net.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"net.js","sourceRoot":"","sources":["../../src/commands/net.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { apiRequest, queryPath } from '../client.js';
|
|
2
|
+
import { loadConfig, resolveContext } from '../config.js';
|
|
3
|
+
import { maskEmail, maskMobile, printJson, table } from '../utils/format.js';
|
|
4
|
+
function uidTypeName(value) {
|
|
5
|
+
if (value === 0)
|
|
6
|
+
return '普通';
|
|
7
|
+
if (value === 1)
|
|
8
|
+
return '特殊';
|
|
9
|
+
if (value === 2)
|
|
10
|
+
return '预留';
|
|
11
|
+
return String(value);
|
|
12
|
+
}
|
|
13
|
+
async function lookupUser(positionalUID, options, command) {
|
|
14
|
+
const context = resolveContext(command.optsWithGlobals());
|
|
15
|
+
const uid = options.uid || positionalUID;
|
|
16
|
+
const queryCount = [uid, options.email, options.mobile].filter(Boolean).length;
|
|
17
|
+
if (queryCount !== 1) {
|
|
18
|
+
throw new Error('请且仅请提供一种查询条件:UID、--email 或 --mobile');
|
|
19
|
+
}
|
|
20
|
+
if (uid && !/^[1-9]\d*$/.test(uid)) {
|
|
21
|
+
throw new Error('UID 必须是正整数');
|
|
22
|
+
}
|
|
23
|
+
if (options.nationCode && !options.mobile) {
|
|
24
|
+
throw new Error('--nation-code 只能与 --mobile 一起使用');
|
|
25
|
+
}
|
|
26
|
+
const env = options.env || loadConfig().defaultUserEnv;
|
|
27
|
+
if (!['dev', 'qa'].includes(env)) {
|
|
28
|
+
throw new Error('--env 只能是 dev 或 qa');
|
|
29
|
+
}
|
|
30
|
+
const path = queryPath('/api/v1/user-lookup', {
|
|
31
|
+
env,
|
|
32
|
+
uid,
|
|
33
|
+
email: options.email,
|
|
34
|
+
mobile: options.mobile,
|
|
35
|
+
nation_code: options.nationCode,
|
|
36
|
+
});
|
|
37
|
+
const result = await apiRequest(context, path);
|
|
38
|
+
const account = {
|
|
39
|
+
...result.account,
|
|
40
|
+
email: options.reveal ? result.account.email : maskEmail(result.account.email || ''),
|
|
41
|
+
mobile: options.reveal ? result.account.mobile : maskMobile(result.account.mobile || ''),
|
|
42
|
+
};
|
|
43
|
+
const output = { ...result, account };
|
|
44
|
+
if (context.json) {
|
|
45
|
+
printJson(output);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(table(['字段', '值'], [
|
|
49
|
+
['环境', result.env.toUpperCase()],
|
|
50
|
+
['UID', account.uid],
|
|
51
|
+
['账号类型', uidTypeName(account.uid_type)],
|
|
52
|
+
['昵称', account.nickname],
|
|
53
|
+
['区号', account.nation_code],
|
|
54
|
+
['手机号', account.mobile],
|
|
55
|
+
['邮箱', account.email],
|
|
56
|
+
['语言', account.language],
|
|
57
|
+
['头像', account.avatar],
|
|
58
|
+
], [16, 100]));
|
|
59
|
+
if (!options.reveal)
|
|
60
|
+
console.log('\n手机号和邮箱已脱敏;需要明文时添加 --reveal。');
|
|
61
|
+
}
|
|
62
|
+
export function registerUserCommand(program) {
|
|
63
|
+
const user = program
|
|
64
|
+
.command('user [uid]')
|
|
65
|
+
.description('在 Dev/QA 用户中心查询账号')
|
|
66
|
+
.option('--uid <uid>', '按 UID 查询(也可使用位置参数)')
|
|
67
|
+
.option('--env <dev|qa>', '用户中心环境(默认 qa)')
|
|
68
|
+
.option('--mobile <mobile>', '按手机号反查')
|
|
69
|
+
.option('--nation-code <code>', '手机号国家/地区码')
|
|
70
|
+
.option('--email <email>', '按邮箱反查')
|
|
71
|
+
.option('--reveal', '显示手机号和邮箱明文')
|
|
72
|
+
.addHelpText('after', `
|
|
73
|
+
示例:
|
|
74
|
+
polaris user 123 --env qa
|
|
75
|
+
polaris user --uid 123 --env dev
|
|
76
|
+
polaris user --mobile 91234567 --nation-code 852
|
|
77
|
+
polaris user --email user@example.com --reveal
|
|
78
|
+
polaris user envs`)
|
|
79
|
+
.action(lookupUser);
|
|
80
|
+
user
|
|
81
|
+
.command('envs')
|
|
82
|
+
.description('查看后端已配置的用户查询环境')
|
|
83
|
+
.action(async (_options, command) => {
|
|
84
|
+
const context = resolveContext(command.optsWithGlobals());
|
|
85
|
+
const result = await apiRequest(context, '/api/v1/user-lookup/envs');
|
|
86
|
+
if (context.json) {
|
|
87
|
+
printJson(result);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
console.log(table(['环境', '名称'], result.items.map((item) => [item.key, item.label]), [12, 40]));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/commands/user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAsB,MAAM,cAAc,CAAA;AAC7E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AA2B5E,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5B,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5B,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,aAAiC,EACjC,OAAoB,EACpB,OAAgB;IAEhB,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,eAAe,EAAmB,CAAC,CAAA;IAC1E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,aAAa,CAAA;IACxC,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAA;IAC9E,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IACD,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAA;IAC/B,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,cAAc,CAAA;IACtD,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,qBAAqB,EAAE;QAC5C,GAAG;QACH,GAAG;QACH,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,WAAW,EAAE,OAAO,CAAC,UAAU;KAChC,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAiB,OAAO,EAAE,IAAI,CAAC,CAAA;IAC9D,MAAM,OAAO,GAAG;QACd,GAAG,MAAM,CAAC,OAAO;QACjB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QACpF,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;KACzF,CAAA;IACD,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAA;IACrC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,CAAC,CAAA;QACjB,OAAM;IACR,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CACf,CAAC,IAAI,EAAE,GAAG,CAAC,EACX;QACE,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAChC,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC;QACpB,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC;QACxB,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC;QAC3B,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC;QACvB,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;QACrB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC;QACxB,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;KACvB,EACD,CAAC,EAAE,EAAE,GAAG,CAAC,CACV,CAAC,CAAA;IACF,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;AACnE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,mBAAmB,CAAC;SAChC,MAAM,CAAC,aAAa,EAAE,oBAAoB,CAAC;SAC3C,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAAC;SACzC,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC;SACrC,MAAM,CAAC,sBAAsB,EAAE,WAAW,CAAC;SAC3C,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC;SAClC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC;SAChC,WAAW,CAAC,OAAO,EAAE;;;;;;oBAMN,CAAC;SAChB,MAAM,CAAC,UAAU,CAAC,CAAA;IAErB,IAAI;SACD,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,gBAAgB,CAAC;SAC7B,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAgB,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,eAAe,EAAmB,CAAC,CAAA;QAC1E,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,OAAO,EACP,0BAA0B,CAC3B,CAAA;QACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,SAAS,CAAC,MAAM,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CACf,CAAC,IAAI,EAAE,IAAI,CAAC,EACZ,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAClD,CAAC,EAAE,EAAE,EAAE,CAAC,CACT,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACN,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type EnvironmentName = 'local' | 'online';
|
|
2
|
+
export interface StoredToken {
|
|
3
|
+
token: string;
|
|
4
|
+
savedAt: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PolarisConfig {
|
|
7
|
+
env: EnvironmentName;
|
|
8
|
+
defaultUserEnv: 'dev' | 'qa';
|
|
9
|
+
tokens: Partial<Record<EnvironmentName, StoredToken>>;
|
|
10
|
+
}
|
|
11
|
+
export interface GlobalOptions {
|
|
12
|
+
serviceEnv?: EnvironmentName;
|
|
13
|
+
base?: string;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface RequestContext {
|
|
17
|
+
env: EnvironmentName;
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
token?: string;
|
|
20
|
+
json: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const ENV_URLS: Record<EnvironmentName, string>;
|
|
23
|
+
export declare const CONFIG_PATH: string;
|
|
24
|
+
export declare function loadConfig(): PolarisConfig;
|
|
25
|
+
export declare function saveConfig(config: PolarisConfig): void;
|
|
26
|
+
export declare function normalizeBaseUrl(value: string): string;
|
|
27
|
+
export declare function resolveContext(options: GlobalOptions): RequestContext;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
export const ENV_URLS = {
|
|
5
|
+
local: 'http://127.0.0.1:8080',
|
|
6
|
+
online: 'https://polaris.yfcenter.com',
|
|
7
|
+
};
|
|
8
|
+
export const CONFIG_PATH = process.env.POLARIS_CONFIG || join(homedir(), '.polaris', 'config.json');
|
|
9
|
+
const DEFAULT_CONFIG = {
|
|
10
|
+
env: 'online',
|
|
11
|
+
defaultUserEnv: 'qa',
|
|
12
|
+
tokens: {},
|
|
13
|
+
};
|
|
14
|
+
export function loadConfig() {
|
|
15
|
+
try {
|
|
16
|
+
const parsed = JSON.parse(readFileSync(CONFIG_PATH, 'utf8'));
|
|
17
|
+
return {
|
|
18
|
+
env: parsed.env === 'local' || parsed.env === 'online' ? parsed.env : DEFAULT_CONFIG.env,
|
|
19
|
+
defaultUserEnv: parsed.defaultUserEnv === 'dev' ? 'dev' : 'qa',
|
|
20
|
+
tokens: parsed.tokens && typeof parsed.tokens === 'object' ? parsed.tokens : {},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return structuredClone(DEFAULT_CONFIG);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function saveConfig(config) {
|
|
28
|
+
const dir = dirname(CONFIG_PATH);
|
|
29
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
30
|
+
const temp = `${CONFIG_PATH}.${process.pid}.tmp`;
|
|
31
|
+
writeFileSync(temp, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
|
|
32
|
+
renameSync(temp, CONFIG_PATH);
|
|
33
|
+
chmodSync(CONFIG_PATH, 0o600);
|
|
34
|
+
}
|
|
35
|
+
export function normalizeBaseUrl(value) {
|
|
36
|
+
const url = new URL(value);
|
|
37
|
+
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
38
|
+
throw new Error('--base 只支持 http 或 https URL');
|
|
39
|
+
}
|
|
40
|
+
return url.toString().replace(/\/+$/, '');
|
|
41
|
+
}
|
|
42
|
+
export function resolveContext(options) {
|
|
43
|
+
const config = loadConfig();
|
|
44
|
+
const env = options.serviceEnv ?? config.env;
|
|
45
|
+
if (env !== 'local' && env !== 'online') {
|
|
46
|
+
throw new Error('--service-env 只能是 local 或 online');
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
env,
|
|
50
|
+
baseUrl: options.base ? normalizeBaseUrl(options.base) : ENV_URLS[env],
|
|
51
|
+
token: config.tokens[env]?.token,
|
|
52
|
+
json: Boolean(options.json),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/help.d.ts
ADDED
package/dist/help.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CONFIG_PATH, ENV_URLS, loadConfig } from './config.js';
|
|
2
|
+
export function configureHelp(program) {
|
|
3
|
+
const config = loadConfig();
|
|
4
|
+
const loggedIn = Boolean(config.tokens[config.env]?.token);
|
|
5
|
+
program
|
|
6
|
+
.showHelpAfterError('(执行 polaris help 查看完整帮助)')
|
|
7
|
+
.showSuggestionAfterError()
|
|
8
|
+
.addHelpText('beforeAll', 'Polaris CLI - 观星台命令行查询工具\n')
|
|
9
|
+
.addHelpText('afterAll', `
|
|
10
|
+
当前状态:
|
|
11
|
+
环境: ${config.env} (${ENV_URLS[config.env]})
|
|
12
|
+
登录: ${loggedIn ? '已保存凭证' : '未登录'}
|
|
13
|
+
配置: ${CONFIG_PATH}
|
|
14
|
+
|
|
15
|
+
常用示例:
|
|
16
|
+
polaris env online
|
|
17
|
+
polaris login
|
|
18
|
+
polaris net list --uid 123 --status 500
|
|
19
|
+
polaris net get 100 --curl
|
|
20
|
+
polaris user 123 --env qa
|
|
21
|
+
polaris doctor`);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=help.js.map
|
package/dist/help.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE/D,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAA;IAC1D,OAAO;SACJ,kBAAkB,CAAC,0BAA0B,CAAC;SAC9C,wBAAwB,EAAE;SAC1B,WAAW,CAAC,WAAW,EAAE,4BAA4B,CAAC;SACtD,WAAW,CAAC,UAAU,EAAE;;UAEnB,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC;UACnC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;UAC1B,WAAW;;;;;;;;iBAQJ,CAAC,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateCurl(request: Record<string, unknown>): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const MANAGED_HEADERS = new Set([
|
|
2
|
+
'content-length',
|
|
3
|
+
'host',
|
|
4
|
+
'connection',
|
|
5
|
+
'transfer-encoding',
|
|
6
|
+
'accept-encoding',
|
|
7
|
+
]);
|
|
8
|
+
function shellQuote(value) {
|
|
9
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
10
|
+
}
|
|
11
|
+
function parseHeaders(value) {
|
|
12
|
+
if (!value)
|
|
13
|
+
return {};
|
|
14
|
+
if (typeof value === 'object')
|
|
15
|
+
return value;
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(String(value));
|
|
18
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function generateCurl(request) {
|
|
25
|
+
const method = String(request.method || 'GET').toUpperCase();
|
|
26
|
+
const lines = [`curl --request ${method} ${shellQuote(request.url || '')}`];
|
|
27
|
+
for (const [key, rawValue] of Object.entries(parseHeaders(request.request_headers))) {
|
|
28
|
+
if (MANAGED_HEADERS.has(key.toLowerCase()))
|
|
29
|
+
continue;
|
|
30
|
+
const value = Array.isArray(rawValue)
|
|
31
|
+
? rawValue.join(', ')
|
|
32
|
+
: typeof rawValue === 'object' && rawValue !== null
|
|
33
|
+
? JSON.stringify(rawValue)
|
|
34
|
+
: String(rawValue ?? '');
|
|
35
|
+
lines.push(` --header ${shellQuote(`${key}: ${value}`)}`);
|
|
36
|
+
}
|
|
37
|
+
const body = request.request_body;
|
|
38
|
+
if (body !== null && body !== undefined && body !== '') {
|
|
39
|
+
lines.push(` --data-raw ${shellQuote(typeof body === 'string' ? body : JSON.stringify(body))}`);
|
|
40
|
+
}
|
|
41
|
+
return lines.join(' \\\n');
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=curl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curl.js","sourceRoot":"","sources":["../../src/utils/curl.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,gBAAgB;IAChB,MAAM;IACN,YAAY;IACZ,mBAAmB;IACnB,iBAAiB;CAClB,CAAC,CAAA;AAEF,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAA;AACpD,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAA;IACrB,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAgC,CAAA;IACtE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACxC,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAiC,CAAC,CAAC,CAAC,EAAE,CAAA;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgC;IAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;IAC5D,MAAM,KAAK,GAAG,CAAC,kBAAkB,MAAM,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3E,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QACpF,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAAE,SAAQ;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YACnC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;YACrB,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI;gBACjD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;gBAC1B,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;QAC5B,KAAK,CAAC,IAAI,CAAC,cAAc,UAAU,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAA;IACjC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,gBAAgB,UAAU,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAA;IAClG,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type TableValue = string | number | boolean | null | undefined;
|
|
2
|
+
export declare function table(headers: string[], rows: TableValue[][], maxWidths?: number[]): string;
|
|
3
|
+
export declare function printJson(value: unknown): void;
|
|
4
|
+
export declare function formatDate(value: unknown): string;
|
|
5
|
+
export declare function prettyContent(value: unknown): string;
|
|
6
|
+
export declare function limitLines(value: string, maxLines: number): string;
|
|
7
|
+
export declare function maskEmail(value: string): string;
|
|
8
|
+
export declare function maskMobile(value: string): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
function text(value) {
|
|
2
|
+
if (value === null || value === undefined || value === '')
|
|
3
|
+
return '-';
|
|
4
|
+
return String(value).replace(/\r?\n/g, ' ');
|
|
5
|
+
}
|
|
6
|
+
function clipped(value, width) {
|
|
7
|
+
if (value.length <= width)
|
|
8
|
+
return value;
|
|
9
|
+
return `${value.slice(0, Math.max(1, width - 1))}…`;
|
|
10
|
+
}
|
|
11
|
+
export function table(headers, rows, maxWidths = []) {
|
|
12
|
+
const normalized = rows.map((row) => row.map(text));
|
|
13
|
+
const widths = headers.map((header, index) => {
|
|
14
|
+
const contentWidth = Math.max(header.length, ...normalized.map((row) => row[index]?.length ?? 0));
|
|
15
|
+
return Math.min(contentWidth, maxWidths[index] ?? 40);
|
|
16
|
+
});
|
|
17
|
+
const line = (row) => row.map((value, index) => clipped(value ?? '', widths[index]).padEnd(widths[index])).join(' ').trimEnd();
|
|
18
|
+
const separator = widths.map((width) => '─'.repeat(width)).join(' ');
|
|
19
|
+
return [line(headers), separator, ...normalized.map(line)].join('\n');
|
|
20
|
+
}
|
|
21
|
+
export function printJson(value) {
|
|
22
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
23
|
+
}
|
|
24
|
+
export function formatDate(value) {
|
|
25
|
+
if (value === null || value === undefined || value === '')
|
|
26
|
+
return '-';
|
|
27
|
+
const date = typeof value === 'number' ? new Date(value) : new Date(String(value));
|
|
28
|
+
return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString('zh-CN', { hour12: false });
|
|
29
|
+
}
|
|
30
|
+
export function prettyContent(value) {
|
|
31
|
+
if (value === null || value === undefined || value === '')
|
|
32
|
+
return '(空)';
|
|
33
|
+
if (typeof value !== 'string')
|
|
34
|
+
return JSON.stringify(value, null, 2);
|
|
35
|
+
try {
|
|
36
|
+
return JSON.stringify(JSON.parse(value), null, 2);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function limitLines(value, maxLines) {
|
|
43
|
+
const lines = value.split(/\r?\n/);
|
|
44
|
+
if (lines.length <= maxLines)
|
|
45
|
+
return value;
|
|
46
|
+
return `${lines.slice(0, maxLines).join('\n')}\n…(已省略 ${lines.length - maxLines} 行,使用 --max-lines 调整)`;
|
|
47
|
+
}
|
|
48
|
+
export function maskEmail(value) {
|
|
49
|
+
if (!value)
|
|
50
|
+
return '';
|
|
51
|
+
const [name, domain] = value.split('@');
|
|
52
|
+
if (!domain)
|
|
53
|
+
return maskText(value);
|
|
54
|
+
const visible = name.length <= 2 ? name.slice(0, 1) : name.slice(0, 2);
|
|
55
|
+
return `${visible}${'*'.repeat(Math.max(2, name.length - visible.length))}@${domain}`;
|
|
56
|
+
}
|
|
57
|
+
export function maskMobile(value) {
|
|
58
|
+
const plain = value.trim();
|
|
59
|
+
if (!plain)
|
|
60
|
+
return '';
|
|
61
|
+
if (plain.length <= 5)
|
|
62
|
+
return maskText(plain);
|
|
63
|
+
return `${plain.slice(0, 3)}${'*'.repeat(plain.length - 5)}${plain.slice(-2)}`;
|
|
64
|
+
}
|
|
65
|
+
function maskText(value) {
|
|
66
|
+
if (value.length <= 1)
|
|
67
|
+
return '*';
|
|
68
|
+
return `${value[0]}${'*'.repeat(Math.max(2, value.length - 1))}`;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qs_cli/polaris-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "观星台命令行查询工具",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"polaris": "dist/cli.js",
|
|
8
|
+
"polaris_cli": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json && node -e \"require('fs').chmodSync('dist/cli.js',0o755)\"",
|
|
16
|
+
"start": "node dist/cli.js",
|
|
17
|
+
"check": "tsc -p tsconfig.json --noEmit"
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"registry": "https://registry.npmjs.org/",
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"commander": "^13.1.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^22.15.3",
|
|
31
|
+
"typescript": "^5.8.3"
|
|
32
|
+
}
|
|
33
|
+
}
|