nginx-proxy-manager-cli 0.2.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/AGENTS.md +34 -0
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +19 -0
- package/dist/client.js +111 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +406 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.js +113 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.js +36 -0
- package/dist/json.js.map +1 -0
- package/dist/output.d.ts +4 -0
- package/dist/output.js +28 -0
- package/dist/output.js.map +1 -0
- package/dist/safe.d.ts +3 -0
- package/dist/safe.js +28 -0
- package/dist/safe.js.map +1 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +79 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## 开发约定
|
|
4
|
+
|
|
5
|
+
- 遵守KISS。
|
|
6
|
+
- 写操作必须默认确认,自动化场景使用 `--yes`。
|
|
7
|
+
- 所有可运行命令都要有 `--json` 参数保证机器可读。
|
|
8
|
+
|
|
9
|
+
## 开发流程
|
|
10
|
+
|
|
11
|
+
使用TDD开发,开发完创建至少一个 Subagent 做 Review ,Review 要做压力测试和对抗测试。
|
|
12
|
+
|
|
13
|
+
流程:
|
|
14
|
+
1. 写失败测试。
|
|
15
|
+
2. 写最小模型。
|
|
16
|
+
3. Subagent Review and fix loop。
|
|
17
|
+
4. 完成需求功能。
|
|
18
|
+
5. Subagent Review and fix loop。
|
|
19
|
+
|
|
20
|
+
## 操作边界
|
|
21
|
+
|
|
22
|
+
- 不要执行真实环境写操作。
|
|
23
|
+
- 连接真实环境时优先运行只读命令。
|
|
24
|
+
- 不要读取或修改用户真实 HOME 配置,除非用户明确要求。
|
|
25
|
+
|
|
26
|
+
## 安全
|
|
27
|
+
|
|
28
|
+
- 不打印 JWT、密码或 token。
|
|
29
|
+
- 不把真实账号、密码或 token 写入仓库。
|
|
30
|
+
- 文档和测试只能使用占位值。
|
|
31
|
+
|
|
32
|
+
## 发布边界
|
|
33
|
+
|
|
34
|
+
- 不要执行真实 commit、tag、push 或 publish,除非用户明确要求。
|
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aturan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# nginx-proxy-manager-cli
|
|
2
|
+
|
|
3
|
+
用于在命令行管理 Nginx Proxy Manager。
|
|
4
|
+
|
|
5
|
+
命令入口:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
nginx-proxy-manager
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add -g nginx-proxy-manager-cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 快速开始
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
nginx-proxy-manager profile add prod \
|
|
21
|
+
--base_url https://proxy.example.com \
|
|
22
|
+
--username admin@example.com \
|
|
23
|
+
--password "$PASSWORD" \
|
|
24
|
+
--default
|
|
25
|
+
|
|
26
|
+
nginx-proxy-manager health
|
|
27
|
+
nginx-proxy-manager proxy-hosts list
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
写操作默认需要确认。脚本或自动化环境中使用 `--yes`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
nginx-proxy-manager --yes proxy-hosts create \
|
|
34
|
+
--domain_names app.example.com \
|
|
35
|
+
--forward_scheme http \
|
|
36
|
+
--forward_host app \
|
|
37
|
+
--forward_port 8080
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
复杂请求体使用 `--body-json` 或 `--from-file`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
nginx-proxy-manager --yes proxy-hosts update 1 \
|
|
44
|
+
--body-json '{"enabled":true}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 配置
|
|
48
|
+
|
|
49
|
+
默认配置路径:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
$HOME/.nginx-xproxy-manager.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
配置路径优先级:
|
|
56
|
+
|
|
57
|
+
1. `--config PATH`
|
|
58
|
+
2. `NGINX_PROXY_MANAGER_CONFIG`
|
|
59
|
+
3. 默认配置路径
|
|
60
|
+
|
|
61
|
+
示例:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
nginx-proxy-manager --config ./npm-config.json proxy-hosts list
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Profile
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
nginx-proxy-manager profile add
|
|
71
|
+
nginx-proxy-manager profile add prod --base_url https://proxy.example.com --username admin --password "$PASSWORD" --default
|
|
72
|
+
nginx-proxy-manager profile list
|
|
73
|
+
nginx-proxy-manager profile show prod
|
|
74
|
+
nginx-proxy-manager profile use prod
|
|
75
|
+
nginx-proxy-manager --yes profile remove prod
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 命令
|
|
79
|
+
|
|
80
|
+
认证与健康检查:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
nginx-proxy-manager auth token
|
|
84
|
+
nginx-proxy-manager health
|
|
85
|
+
nginx-proxy-manager schema
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Certificates:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
nginx-proxy-manager certificates list
|
|
92
|
+
nginx-proxy-manager certificates get 1
|
|
93
|
+
nginx-proxy-manager --yes certificates create --body-json '{"provider":"letsencrypt","domain_names":["example.com"]}'
|
|
94
|
+
nginx-proxy-manager --yes certificates delete 1
|
|
95
|
+
nginx-proxy-manager --yes certificates renew 1
|
|
96
|
+
nginx-proxy-manager certificates download 1 --output cert.zip
|
|
97
|
+
nginx-proxy-manager --yes certificates upload --from-file certificate-upload.json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Proxy hosts:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
nginx-proxy-manager proxy-hosts list
|
|
104
|
+
nginx-proxy-manager proxy-hosts get 1
|
|
105
|
+
nginx-proxy-manager --yes proxy-hosts create --domain_names app.example.com --forward_scheme http --forward_host app --forward_port 8080
|
|
106
|
+
nginx-proxy-manager --yes proxy-hosts update 1 --body-json '{"enabled":true}'
|
|
107
|
+
nginx-proxy-manager --yes proxy-hosts delete 1
|
|
108
|
+
nginx-proxy-manager --yes proxy-hosts enable 1
|
|
109
|
+
nginx-proxy-manager --yes proxy-hosts disable 1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Redirection hosts:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
nginx-proxy-manager redirection-hosts list
|
|
116
|
+
nginx-proxy-manager redirection-hosts get 1
|
|
117
|
+
nginx-proxy-manager --yes redirection-hosts create --body-json '{"domain_names":["old.example.com"],"forward_domain_name":"new.example.com"}'
|
|
118
|
+
nginx-proxy-manager --yes redirection-hosts update 1 --from-file redirection-host.json
|
|
119
|
+
nginx-proxy-manager --yes redirection-hosts delete 1
|
|
120
|
+
nginx-proxy-manager --yes redirection-hosts enable 1
|
|
121
|
+
nginx-proxy-manager --yes redirection-hosts disable 1
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Streams:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
nginx-proxy-manager streams list
|
|
128
|
+
nginx-proxy-manager streams get 1
|
|
129
|
+
nginx-proxy-manager --yes streams create --body-json '{"incoming_port":2222,"forwarding_host":"ssh","forwarding_port":22}'
|
|
130
|
+
nginx-proxy-manager --yes streams update 1 --from-file stream.json
|
|
131
|
+
nginx-proxy-manager --yes streams delete 1
|
|
132
|
+
nginx-proxy-manager --yes streams enable 1
|
|
133
|
+
nginx-proxy-manager --yes streams disable 1
|
|
134
|
+
```
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createProgram } from "./commands.js";
|
|
3
|
+
export async function runCli(argv = process.argv) {
|
|
4
|
+
const program = createProgram({
|
|
5
|
+
env: process.env,
|
|
6
|
+
homeDir: process.env.HOME ?? "",
|
|
7
|
+
fetch,
|
|
8
|
+
stdin: process.stdin,
|
|
9
|
+
stdout: process.stdout,
|
|
10
|
+
stderr: process.stderr
|
|
11
|
+
});
|
|
12
|
+
await program.parseAsync(argv);
|
|
13
|
+
}
|
|
14
|
+
runCli().catch((error) => {
|
|
15
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
16
|
+
process.stderr.write(`${message}\n`);
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
});
|
|
19
|
+
//# 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":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAiB,OAAO,CAAC,IAAI;IACxD,MAAM,OAAO,GAAG,aAAa,CAAC;QAC5B,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;QAC/B,KAAK;QACL,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAChC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { JsonObject, JsonValue, Profile, RequestRecord } from "./types.js";
|
|
2
|
+
export type TokenCache = {
|
|
3
|
+
token: string;
|
|
4
|
+
expires: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class ApiClient {
|
|
7
|
+
private readonly profile;
|
|
8
|
+
private readonly fetchImpl;
|
|
9
|
+
private readonly onToken?;
|
|
10
|
+
constructor(profile: Profile, fetchImpl?: typeof fetch, onToken?: ((token: TokenCache) => Promise<void> | void) | undefined);
|
|
11
|
+
token(): Promise<string>;
|
|
12
|
+
request(record: RequestRecord): Promise<JsonValue>;
|
|
13
|
+
private url;
|
|
14
|
+
}
|
|
15
|
+
export declare function isTokenFresh(token: string | undefined, expiresAt: string | undefined): token is string;
|
|
16
|
+
export declare function assertOk(response: Response): Promise<void>;
|
|
17
|
+
export declare function resourcePath(resource: string, id?: string | number, action?: string): string;
|
|
18
|
+
export declare function coerceId(id: string): number | string;
|
|
19
|
+
export declare function dataToJsonObject(value: JsonValue): JsonObject;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { URL } from "node:url";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const tokenResponseSchema = z.union([
|
|
4
|
+
z.object({
|
|
5
|
+
token: z.string().min(1),
|
|
6
|
+
expires: z.string().min(1)
|
|
7
|
+
}),
|
|
8
|
+
z.object({
|
|
9
|
+
requires_2fa: z.literal(true),
|
|
10
|
+
challenge_token: z.string().min(1)
|
|
11
|
+
})
|
|
12
|
+
]);
|
|
13
|
+
export class ApiClient {
|
|
14
|
+
profile;
|
|
15
|
+
fetchImpl;
|
|
16
|
+
onToken;
|
|
17
|
+
constructor(profile, fetchImpl = fetch, onToken) {
|
|
18
|
+
this.profile = profile;
|
|
19
|
+
this.fetchImpl = fetchImpl;
|
|
20
|
+
this.onToken = onToken;
|
|
21
|
+
}
|
|
22
|
+
async token() {
|
|
23
|
+
if (isTokenFresh(this.profile.token, this.profile.token_expires_at)) {
|
|
24
|
+
return this.profile.token;
|
|
25
|
+
}
|
|
26
|
+
const response = await this.fetchImpl(this.url("/api/tokens"), {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: { "content-type": "application/json" },
|
|
29
|
+
body: JSON.stringify({
|
|
30
|
+
identity: this.profile.username,
|
|
31
|
+
secret: this.profile.password
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
await assertOk(response);
|
|
35
|
+
const data = tokenResponseSchema.parse(await response.json());
|
|
36
|
+
if ("requires_2fa" in data) {
|
|
37
|
+
throw new Error("当前 CLI 不支持 2FA,请使用未启用 2FA 的账号或专用账号");
|
|
38
|
+
}
|
|
39
|
+
this.profile.token = data.token;
|
|
40
|
+
this.profile.token_expires_at = data.expires;
|
|
41
|
+
await this.onToken?.({ token: data.token, expires: data.expires });
|
|
42
|
+
return data.token;
|
|
43
|
+
}
|
|
44
|
+
async request(record) {
|
|
45
|
+
const token = await this.token();
|
|
46
|
+
const headers = {
|
|
47
|
+
authorization: `Bearer ${token}`
|
|
48
|
+
};
|
|
49
|
+
let body;
|
|
50
|
+
if (record.body instanceof FormData) {
|
|
51
|
+
body = record.body;
|
|
52
|
+
}
|
|
53
|
+
else if (record.body !== undefined) {
|
|
54
|
+
headers["content-type"] = "application/json";
|
|
55
|
+
body = JSON.stringify(record.body);
|
|
56
|
+
}
|
|
57
|
+
const init = {
|
|
58
|
+
method: record.method,
|
|
59
|
+
headers
|
|
60
|
+
};
|
|
61
|
+
if (body !== undefined) {
|
|
62
|
+
init.body = body;
|
|
63
|
+
}
|
|
64
|
+
const response = await this.fetchImpl(this.url(record.path, record.query), init);
|
|
65
|
+
await assertOk(response);
|
|
66
|
+
if (response.status === 204)
|
|
67
|
+
return { ok: true };
|
|
68
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
69
|
+
if (contentType.includes("application/octet-stream")) {
|
|
70
|
+
return { data: await response.arrayBuffer() };
|
|
71
|
+
}
|
|
72
|
+
return (await response.json());
|
|
73
|
+
}
|
|
74
|
+
url(path, query) {
|
|
75
|
+
const base = this.profile.base_url.replace(/\/+$/, "");
|
|
76
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
77
|
+
const url = new URL(`${base}${normalizedPath}`);
|
|
78
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
79
|
+
url.searchParams.set(key, String(value));
|
|
80
|
+
}
|
|
81
|
+
return url.toString();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export function isTokenFresh(token, expiresAt) {
|
|
85
|
+
if (!token || !expiresAt)
|
|
86
|
+
return false;
|
|
87
|
+
const expiresTime = Date.parse(expiresAt);
|
|
88
|
+
if (!Number.isFinite(expiresTime))
|
|
89
|
+
return false;
|
|
90
|
+
return expiresTime > Date.now() + 30_000;
|
|
91
|
+
}
|
|
92
|
+
export async function assertOk(response) {
|
|
93
|
+
if (response.ok)
|
|
94
|
+
return;
|
|
95
|
+
const body = await response.text().catch(() => "");
|
|
96
|
+
throw new Error(`API 请求失败:${response.status} ${response.statusText}${body ? ` ${body}` : ""}`);
|
|
97
|
+
}
|
|
98
|
+
export function resourcePath(resource, id, action) {
|
|
99
|
+
const base = resource === "certificates" ? "/api/nginx/certificates" : `/api/nginx/${resource}`;
|
|
100
|
+
return [base, id, action].filter((part) => part !== undefined && part !== "").join("/");
|
|
101
|
+
}
|
|
102
|
+
export function coerceId(id) {
|
|
103
|
+
const numeric = Number(id);
|
|
104
|
+
return Number.isSafeInteger(numeric) && String(numeric) === id ? numeric : id;
|
|
105
|
+
}
|
|
106
|
+
export function dataToJsonObject(value) {
|
|
107
|
+
if (value && typeof value === "object" && !Array.isArray(value))
|
|
108
|
+
return value;
|
|
109
|
+
throw new Error("API 返回值不是 JSON object");
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { createWriteStream } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { confirm, input, password } from "@inquirer/prompts";
|
|
5
|
+
import { addProfile, getProfileName, readConfig, removeProfile, resolveConfigPath, selectProfile, useProfile, writeConfig } from "./config.js";
|
|
6
|
+
import { ApiClient, coerceId, dataToJsonObject, resourcePath } from "./client.js";
|
|
7
|
+
import { formatHuman, formatJson, formatProfileList } from "./output.js";
|
|
8
|
+
import { mergePayloads, parseJsonObject, readJsonObjectFile } from "./json.js";
|
|
9
|
+
const resourceNames = ["certificates", "proxy-hosts", "redirection-hosts", "streams"];
|
|
10
|
+
const writeActions = new Set(["create", "update", "delete", "enable", "disable", "renew", "upload"]);
|
|
11
|
+
const profileNamePattern = /^[A-Za-z0-9._-]+$/;
|
|
12
|
+
const requirePackage = createRequire(import.meta.url);
|
|
13
|
+
const packageInfo = requirePackage("../package.json");
|
|
14
|
+
export function createProgram(context) {
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name("nginx-proxy-manager")
|
|
18
|
+
.description("管理 Nginx Proxy Manager API 的命令行工具")
|
|
19
|
+
.version(packageInfo.version)
|
|
20
|
+
.option("--config <path>", "配置文件路径")
|
|
21
|
+
.option("--profile <name>", "要使用的 profile 名称")
|
|
22
|
+
.option("--json", "输出 JSON")
|
|
23
|
+
.option("--yes", "跳过写操作确认")
|
|
24
|
+
.configureOutput({
|
|
25
|
+
writeOut: (text) => write(context.stdout, text),
|
|
26
|
+
writeErr: (text) => write(context.stderr, text)
|
|
27
|
+
});
|
|
28
|
+
addProfileCommands(program, context);
|
|
29
|
+
addAuthCommands(program, context);
|
|
30
|
+
addHealthCommand(program, context);
|
|
31
|
+
for (const resource of resourceNames) {
|
|
32
|
+
addResourceCommands(program, context, resource);
|
|
33
|
+
}
|
|
34
|
+
return program;
|
|
35
|
+
}
|
|
36
|
+
function addProfileCommands(program, context) {
|
|
37
|
+
const profile = program.command("profile").description("管理本地 profile");
|
|
38
|
+
profile
|
|
39
|
+
.command("add [name]")
|
|
40
|
+
.description("新增或覆盖 profile")
|
|
41
|
+
.option("--base_url <url>", "base_url")
|
|
42
|
+
.option("--username <username>", "username")
|
|
43
|
+
.option("--password <password>", "password")
|
|
44
|
+
.option("--default", "设为默认 profile")
|
|
45
|
+
.action(async (name, options, command) => {
|
|
46
|
+
const global = getGlobal(command);
|
|
47
|
+
const path = getConfigPath(global, context);
|
|
48
|
+
const profileInput = await resolveProfileAddInput(name, options, context);
|
|
49
|
+
const newProfile = {
|
|
50
|
+
base_url: profileInput.base_url,
|
|
51
|
+
username: profileInput.username,
|
|
52
|
+
password: profileInput.password
|
|
53
|
+
};
|
|
54
|
+
await new ApiClient(newProfile, context.fetch).token();
|
|
55
|
+
const config = await addProfile(path, profileInput.name, newProfile, Boolean(options.default));
|
|
56
|
+
writeResult(context, global, {
|
|
57
|
+
ok: true,
|
|
58
|
+
config_path: path,
|
|
59
|
+
default_profile: config.default_profile ?? null,
|
|
60
|
+
profile: profileInput.name
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
profile
|
|
64
|
+
.command("list")
|
|
65
|
+
.description("列出 profile")
|
|
66
|
+
.action(async (_options, command) => {
|
|
67
|
+
const global = getGlobal(command);
|
|
68
|
+
const config = await readConfig(getConfigPath(global, context));
|
|
69
|
+
write(context.stdout, formatProfileList(config, Boolean(global.json)));
|
|
70
|
+
});
|
|
71
|
+
profile
|
|
72
|
+
.command("show [name]")
|
|
73
|
+
.description("显示 profile,password 会脱敏")
|
|
74
|
+
.action(async (name, _options, command) => {
|
|
75
|
+
const global = getGlobal(command);
|
|
76
|
+
const config = await readConfig(getConfigPath(global, context));
|
|
77
|
+
const profileName = getProfileName(config, name ?? stringOption(global.profile));
|
|
78
|
+
const profile = config.profiles[profileName];
|
|
79
|
+
writeResult(context, global, {
|
|
80
|
+
name: profileName,
|
|
81
|
+
default: config.default_profile === profileName,
|
|
82
|
+
base_url: profile?.base_url ?? "",
|
|
83
|
+
username: profile?.username ?? "",
|
|
84
|
+
credential: "[redacted]"
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
profile
|
|
88
|
+
.command("remove <name>")
|
|
89
|
+
.description("删除 profile")
|
|
90
|
+
.action(async (name, _options, command) => {
|
|
91
|
+
const global = getGlobal(command);
|
|
92
|
+
await confirmWrite(command, context);
|
|
93
|
+
const config = await removeProfile(getConfigPath(global, context), name);
|
|
94
|
+
writeResult(context, global, { ok: true, removed: name, default_profile: config.default_profile ?? null });
|
|
95
|
+
});
|
|
96
|
+
profile
|
|
97
|
+
.command("use <name>")
|
|
98
|
+
.description("切换默认 profile")
|
|
99
|
+
.action(async (name, _options, command) => {
|
|
100
|
+
const global = getGlobal(command);
|
|
101
|
+
const config = await useProfile(getConfigPath(global, context), name);
|
|
102
|
+
writeResult(context, global, { ok: true, default_profile: config.default_profile ?? null });
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async function resolveProfileAddInput(name, options, context) {
|
|
106
|
+
const currentName = stringOption(name);
|
|
107
|
+
const currentBaseUrl = stringOption(options.base_url);
|
|
108
|
+
const currentUsername = stringOption(options.username);
|
|
109
|
+
const currentPassword = stringOption(options.password);
|
|
110
|
+
if (currentName && currentBaseUrl && currentUsername && currentPassword) {
|
|
111
|
+
return validateProfileAddInput({
|
|
112
|
+
name: currentName,
|
|
113
|
+
base_url: currentBaseUrl,
|
|
114
|
+
username: currentUsername,
|
|
115
|
+
password: currentPassword
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const promptInput = context.stdin;
|
|
119
|
+
if (!promptInput?.isTTY) {
|
|
120
|
+
throw new Error("profile add requires name, --base_url, --username, and --password in non-interactive mode");
|
|
121
|
+
}
|
|
122
|
+
const promptContext = { input: promptInput, output: context.stderr };
|
|
123
|
+
const resolved = {
|
|
124
|
+
name: currentName ?? (await input({ message: "name", required: true, validate: validateProfileName }, promptContext)),
|
|
125
|
+
base_url: currentBaseUrl ??
|
|
126
|
+
(await input({ message: "base_url", required: true, validate: validateBaseUrl }, promptContext)),
|
|
127
|
+
username: currentUsername ?? (await input({ message: "username", required: true, validate: validateRequired("username") }, promptContext)),
|
|
128
|
+
password: currentPassword ??
|
|
129
|
+
(await password({
|
|
130
|
+
message: "password",
|
|
131
|
+
mask: "*",
|
|
132
|
+
validate: validateRequired("password")
|
|
133
|
+
}, promptContext))
|
|
134
|
+
};
|
|
135
|
+
return validateProfileAddInput(resolved);
|
|
136
|
+
}
|
|
137
|
+
function validateProfileAddInput(input) {
|
|
138
|
+
const checks = [
|
|
139
|
+
validateProfileName(input.name),
|
|
140
|
+
validateBaseUrl(input.base_url),
|
|
141
|
+
validateRequired("username")(input.username),
|
|
142
|
+
validateRequired("password")(input.password)
|
|
143
|
+
];
|
|
144
|
+
for (const result of checks) {
|
|
145
|
+
if (result !== true) {
|
|
146
|
+
throw new Error(result);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return input;
|
|
150
|
+
}
|
|
151
|
+
function validateProfileName(value) {
|
|
152
|
+
if (!value.trim())
|
|
153
|
+
return "profile name is required";
|
|
154
|
+
if (!profileNamePattern.test(value))
|
|
155
|
+
return "profile name may only contain letters, numbers, dots, underscores, and dashes";
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
function validateBaseUrl(value) {
|
|
159
|
+
try {
|
|
160
|
+
const url = new URL(value);
|
|
161
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
162
|
+
return "base_url must use http or https";
|
|
163
|
+
}
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return "base_url must be a valid URL";
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function validateRequired(field) {
|
|
171
|
+
return (value) => (value.trim().length > 0 ? true : `${field} is required`);
|
|
172
|
+
}
|
|
173
|
+
function addAuthCommands(program, context) {
|
|
174
|
+
const auth = program.command("auth").description("认证相关命令");
|
|
175
|
+
auth
|
|
176
|
+
.command("token")
|
|
177
|
+
.description("验证凭据并获取 token,但不会打印 JWT")
|
|
178
|
+
.action(async (_options, command) => {
|
|
179
|
+
const global = getGlobal(command);
|
|
180
|
+
const client = await getClient(command, context);
|
|
181
|
+
await client.token();
|
|
182
|
+
writeResult(context, global, { ok: true, token: "[redacted]" });
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function addHealthCommand(program, context) {
|
|
186
|
+
program
|
|
187
|
+
.command("health")
|
|
188
|
+
.description("读取 API schema 检查连通性")
|
|
189
|
+
.action(async (_options, command) => {
|
|
190
|
+
const global = getGlobal(command);
|
|
191
|
+
const client = await getClient(command, context);
|
|
192
|
+
const result = await client.request({ method: "GET", path: "/api/schema" });
|
|
193
|
+
writeResult(context, global, result);
|
|
194
|
+
});
|
|
195
|
+
program
|
|
196
|
+
.command("schema")
|
|
197
|
+
.description("读取 API schema")
|
|
198
|
+
.action(async (_options, command) => {
|
|
199
|
+
const global = getGlobal(command);
|
|
200
|
+
const client = await getClient(command, context);
|
|
201
|
+
const result = await client.request({ method: "GET", path: "/api/schema" });
|
|
202
|
+
writeResult(context, global, result);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function addResourceCommands(program, context, resource) {
|
|
206
|
+
const group = program.command(resource).description(`${resource} 资源命令`);
|
|
207
|
+
group
|
|
208
|
+
.command("list")
|
|
209
|
+
.description(`列出 ${resource}`)
|
|
210
|
+
.option("--query-json <json>", "查询参数 JSON object")
|
|
211
|
+
.action(async (options, command) => {
|
|
212
|
+
const global = getGlobal(command);
|
|
213
|
+
const client = await getClient(command, context);
|
|
214
|
+
const queryJson = stringOption(options.queryJson);
|
|
215
|
+
const query = queryJson ? parseJsonObject(queryJson, "--query-json") : undefined;
|
|
216
|
+
const result = await client.request({
|
|
217
|
+
method: "GET",
|
|
218
|
+
path: resourcePath(resource),
|
|
219
|
+
query: queryToRecord(query)
|
|
220
|
+
});
|
|
221
|
+
writeResult(context, global, result);
|
|
222
|
+
});
|
|
223
|
+
group
|
|
224
|
+
.command("get <id>")
|
|
225
|
+
.description(`读取 ${resource}`)
|
|
226
|
+
.action(async (id, _options, command) => {
|
|
227
|
+
const global = getGlobal(command);
|
|
228
|
+
const client = await getClient(command, context);
|
|
229
|
+
const result = await client.request({ method: "GET", path: resourcePath(resource, coerceId(id)) });
|
|
230
|
+
writeResult(context, global, result);
|
|
231
|
+
});
|
|
232
|
+
group
|
|
233
|
+
.command("create")
|
|
234
|
+
.description(`创建 ${resource}`)
|
|
235
|
+
.option("--body-json <json>", "请求体 JSON object")
|
|
236
|
+
.option("--from-file <path>", "从文件读取请求体 JSON object")
|
|
237
|
+
.allowUnknownOption(true)
|
|
238
|
+
.allowExcessArguments(true)
|
|
239
|
+
.action(async (options, command) => {
|
|
240
|
+
await writeResource(command, context, resource, "create", undefined, options, "POST");
|
|
241
|
+
});
|
|
242
|
+
group
|
|
243
|
+
.command("update <id>")
|
|
244
|
+
.description(`更新 ${resource}`)
|
|
245
|
+
.option("--body-json <json>", "请求体 JSON object")
|
|
246
|
+
.option("--from-file <path>", "从文件读取请求体 JSON object")
|
|
247
|
+
.allowUnknownOption(true)
|
|
248
|
+
.allowExcessArguments(true)
|
|
249
|
+
.action(async (id, options, command) => {
|
|
250
|
+
await writeResource(command, context, resource, "update", coerceId(id), options, "PUT");
|
|
251
|
+
});
|
|
252
|
+
group
|
|
253
|
+
.command("delete <id>")
|
|
254
|
+
.description(`删除 ${resource}`)
|
|
255
|
+
.action(async (id, _options, command) => {
|
|
256
|
+
await writeResource(command, context, resource, "delete", coerceId(id), undefined, "DELETE");
|
|
257
|
+
});
|
|
258
|
+
for (const action of ["enable", "disable"]) {
|
|
259
|
+
group
|
|
260
|
+
.command(`${action} <id>`)
|
|
261
|
+
.description(`${action} ${resource}`)
|
|
262
|
+
.action(async (id, _options, command) => {
|
|
263
|
+
await writeResource(command, context, resource, action, coerceId(id), undefined, "PUT", action);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
if (resource === "certificates") {
|
|
267
|
+
group
|
|
268
|
+
.command("renew <id>")
|
|
269
|
+
.description("续期 certificate")
|
|
270
|
+
.action(async (id, _options, command) => {
|
|
271
|
+
await writeResource(command, context, resource, "renew", coerceId(id), undefined, "POST", "renew");
|
|
272
|
+
});
|
|
273
|
+
group
|
|
274
|
+
.command("download <id>")
|
|
275
|
+
.description("下载 certificate")
|
|
276
|
+
.requiredOption("--output <path>", "输出文件路径")
|
|
277
|
+
.action(async (id, options, command) => {
|
|
278
|
+
const global = getGlobal(command);
|
|
279
|
+
const client = await getClient(command, context);
|
|
280
|
+
const result = await client.request({ method: "GET", path: resourcePath(resource, coerceId(id), "download") });
|
|
281
|
+
const object = dataToJsonObject(result);
|
|
282
|
+
const data = object.data;
|
|
283
|
+
if (!(data instanceof ArrayBuffer)) {
|
|
284
|
+
throw new Error("certificate download 未返回二进制内容");
|
|
285
|
+
}
|
|
286
|
+
await writeBinary(String(options.output), data);
|
|
287
|
+
writeResult(context, global, { ok: true, output: String(options.output) });
|
|
288
|
+
});
|
|
289
|
+
group
|
|
290
|
+
.command("upload")
|
|
291
|
+
.description("上传 certificate 元数据")
|
|
292
|
+
.option("--body-json <json>", "请求体 JSON object")
|
|
293
|
+
.option("--from-file <path>", "从文件读取请求体 JSON object")
|
|
294
|
+
.allowUnknownOption(true)
|
|
295
|
+
.allowExcessArguments(true)
|
|
296
|
+
.action(async (options, command) => {
|
|
297
|
+
await writeResource(command, context, resource, "upload", undefined, options, "POST", "upload");
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async function writeResource(command, context, resource, action, id, options, method, pathAction) {
|
|
302
|
+
if (writeActions.has(action))
|
|
303
|
+
await confirmWrite(command, context);
|
|
304
|
+
const global = getGlobal(command);
|
|
305
|
+
const client = await getClient(command, context);
|
|
306
|
+
const body = options ? await payloadFromOptions(options, command) : undefined;
|
|
307
|
+
const result = await client.request({
|
|
308
|
+
method,
|
|
309
|
+
path: resourcePath(resource, id, pathAction),
|
|
310
|
+
body
|
|
311
|
+
});
|
|
312
|
+
writeResult(context, global, result);
|
|
313
|
+
}
|
|
314
|
+
async function payloadFromOptions(options, command) {
|
|
315
|
+
const fromFilePath = stringOption(options.fromFile);
|
|
316
|
+
const bodyJsonRaw = stringOption(options.bodyJson);
|
|
317
|
+
const fromFile = fromFilePath ? await readJsonObjectFile(fromFilePath) : undefined;
|
|
318
|
+
const inlineJson = bodyJsonRaw ? parseJsonObject(bodyJsonRaw, "--body-json") : undefined;
|
|
319
|
+
const unknown = parseUnknownFieldOptions(command.args);
|
|
320
|
+
const payload = mergePayloads(fromFile, inlineJson, unknown);
|
|
321
|
+
if (Object.keys(payload).length === 0) {
|
|
322
|
+
throw new Error("写操作需要 --body-json、--from-file 或字段参数");
|
|
323
|
+
}
|
|
324
|
+
return payload;
|
|
325
|
+
}
|
|
326
|
+
export function parseUnknownFieldOptions(args) {
|
|
327
|
+
const payload = {};
|
|
328
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
329
|
+
const arg = args[index];
|
|
330
|
+
if (!arg?.startsWith("--"))
|
|
331
|
+
continue;
|
|
332
|
+
const key = arg.slice(2);
|
|
333
|
+
const values = [];
|
|
334
|
+
while (args[index + 1] && !args[index + 1]?.startsWith("--")) {
|
|
335
|
+
values.push(String(args[index + 1]));
|
|
336
|
+
index += 1;
|
|
337
|
+
}
|
|
338
|
+
payload[key] = values.length > 1 ? values : values[0] ?? true;
|
|
339
|
+
}
|
|
340
|
+
return payload;
|
|
341
|
+
}
|
|
342
|
+
async function getClient(command, context) {
|
|
343
|
+
const global = getGlobal(command);
|
|
344
|
+
const configPath = getConfigPath(global, context);
|
|
345
|
+
const config = await readConfig(configPath);
|
|
346
|
+
const profileName = getProfileName(config, stringOption(global.profile));
|
|
347
|
+
const profile = selectProfile(config, profileName);
|
|
348
|
+
return new ApiClient(profile, context.fetch, async ({ token, expires }) => {
|
|
349
|
+
profile.token = token;
|
|
350
|
+
profile.token_expires_at = expires;
|
|
351
|
+
await writeConfig(configPath, config);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
async function confirmWrite(command, context) {
|
|
355
|
+
const global = getGlobal(command);
|
|
356
|
+
if (global.yes)
|
|
357
|
+
return;
|
|
358
|
+
if (!context.stdin?.isTTY) {
|
|
359
|
+
throw new Error("写操作需要确认;在非交互环境请显式传入 --yes");
|
|
360
|
+
}
|
|
361
|
+
const accepted = await confirm({ message: "确认执行写操作?", default: false }, { input: context.stdin, output: context.stderr });
|
|
362
|
+
if (!accepted)
|
|
363
|
+
throw new Error("已取消写操作");
|
|
364
|
+
}
|
|
365
|
+
function getGlobal(command) {
|
|
366
|
+
let root = command;
|
|
367
|
+
while (root.parent)
|
|
368
|
+
root = root.parent;
|
|
369
|
+
return root.opts();
|
|
370
|
+
}
|
|
371
|
+
function getConfigPath(global, context) {
|
|
372
|
+
return resolveConfigPath({
|
|
373
|
+
explicitPath: stringOption(global.config),
|
|
374
|
+
env: context.env,
|
|
375
|
+
homeDir: context.homeDir
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
function writeResult(context, global, value) {
|
|
379
|
+
write(context.stdout, global.json ? formatJson(value) : formatHuman(value));
|
|
380
|
+
}
|
|
381
|
+
function write(stream, text) {
|
|
382
|
+
stream.write(text);
|
|
383
|
+
}
|
|
384
|
+
function stringOption(value) {
|
|
385
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
386
|
+
}
|
|
387
|
+
function queryToRecord(query) {
|
|
388
|
+
if (!query)
|
|
389
|
+
return undefined;
|
|
390
|
+
const output = {};
|
|
391
|
+
for (const [key, value] of Object.entries(query)) {
|
|
392
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
393
|
+
output[key] = value;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return output;
|
|
397
|
+
}
|
|
398
|
+
async function writeBinary(path, data) {
|
|
399
|
+
await new Promise((resolve, reject) => {
|
|
400
|
+
const stream = createWriteStream(path, { mode: 0o600 });
|
|
401
|
+
stream.on("error", reject);
|
|
402
|
+
stream.on("finish", resolve);
|
|
403
|
+
stream.end(Buffer.from(data));
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AppConfig, Profile } from "./types.js";
|
|
2
|
+
export declare const CONFIG_ENV = "NGINX_PROXY_MANAGER_CONFIG";
|
|
3
|
+
export declare const DEFAULT_CONFIG_BASENAME = ".nginx-xproxy-manager.json";
|
|
4
|
+
export type ConfigPathInput = {
|
|
5
|
+
explicitPath?: string | undefined;
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
homeDir?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function resolveConfigPath(input?: ConfigPathInput): string;
|
|
10
|
+
export declare function expandHome(path: string, homeDir: string): string;
|
|
11
|
+
export declare function pathExists(path: string): Promise<boolean>;
|
|
12
|
+
export declare function readConfig(path: string): Promise<AppConfig>;
|
|
13
|
+
export declare function writeConfig(path: string, config: AppConfig): Promise<void>;
|
|
14
|
+
export declare function addProfile(path: string, name: string, profile: Profile, makeDefault: boolean): Promise<AppConfig>;
|
|
15
|
+
export declare function removeProfile(path: string, name: string): Promise<AppConfig>;
|
|
16
|
+
export declare function useProfile(path: string, name: string): Promise<AppConfig>;
|
|
17
|
+
export declare function selectProfile(config: AppConfig, name?: string): Profile;
|
|
18
|
+
export declare function getProfileName(config: AppConfig, name?: string): string;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access, chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
export const CONFIG_ENV = "NGINX_PROXY_MANAGER_CONFIG";
|
|
6
|
+
export const DEFAULT_CONFIG_BASENAME = ".nginx-xproxy-manager.json";
|
|
7
|
+
const profileSchema = z.object({
|
|
8
|
+
base_url: z.string().url(),
|
|
9
|
+
username: z.string().min(1),
|
|
10
|
+
password: z.string().min(1),
|
|
11
|
+
token: z.string().min(1).optional(),
|
|
12
|
+
token_expires_at: z.string().min(1).optional()
|
|
13
|
+
});
|
|
14
|
+
const configSchema = z.object({
|
|
15
|
+
default_profile: z.string().min(1).optional(),
|
|
16
|
+
profiles: z.record(profileSchema).default({})
|
|
17
|
+
});
|
|
18
|
+
export function resolveConfigPath(input = {}) {
|
|
19
|
+
const env = input.env ?? process.env;
|
|
20
|
+
const homeDir = input.homeDir ?? process.env.HOME ?? "";
|
|
21
|
+
const chosen = input.explicitPath ?? env[CONFIG_ENV] ?? `${homeDir}/${DEFAULT_CONFIG_BASENAME}`;
|
|
22
|
+
return expandHome(chosen, homeDir);
|
|
23
|
+
}
|
|
24
|
+
export function expandHome(path, homeDir) {
|
|
25
|
+
if (path === "~")
|
|
26
|
+
return homeDir;
|
|
27
|
+
if (path.startsWith("~/"))
|
|
28
|
+
return resolve(homeDir, path.slice(2));
|
|
29
|
+
return resolve(path);
|
|
30
|
+
}
|
|
31
|
+
export async function pathExists(path) {
|
|
32
|
+
try {
|
|
33
|
+
await access(path, constants.F_OK);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function readConfig(path) {
|
|
41
|
+
if (!(await pathExists(path))) {
|
|
42
|
+
return { profiles: {} };
|
|
43
|
+
}
|
|
44
|
+
const raw = await readFile(path, "utf8");
|
|
45
|
+
const parsed = JSON.parse(raw);
|
|
46
|
+
return configSchema.parse(parsed);
|
|
47
|
+
}
|
|
48
|
+
export async function writeConfig(path, config) {
|
|
49
|
+
const normalized = configSchema.parse(config);
|
|
50
|
+
await mkdir(dirname(path), { recursive: true });
|
|
51
|
+
await writeFile(path, `${JSON.stringify(normalized, null, 2)}\n`, { mode: 0o600 });
|
|
52
|
+
try {
|
|
53
|
+
await chmod(path, 0o600);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// 某些文件系统不支持 chmod,写入模式已经尽量限制为 0600。
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function addProfile(path, name, profile, makeDefault) {
|
|
60
|
+
const config = await readConfig(path);
|
|
61
|
+
config.profiles[name] = profileSchema.parse(profile);
|
|
62
|
+
if (makeDefault || !config.default_profile) {
|
|
63
|
+
config.default_profile = name;
|
|
64
|
+
}
|
|
65
|
+
await writeConfig(path, config);
|
|
66
|
+
return config;
|
|
67
|
+
}
|
|
68
|
+
export async function removeProfile(path, name) {
|
|
69
|
+
const config = await readConfig(path);
|
|
70
|
+
if (!config.profiles[name]) {
|
|
71
|
+
throw new Error(`profile 不存在:${name}`);
|
|
72
|
+
}
|
|
73
|
+
delete config.profiles[name];
|
|
74
|
+
if (config.default_profile === name) {
|
|
75
|
+
const nextDefault = Object.keys(config.profiles)[0];
|
|
76
|
+
if (nextDefault) {
|
|
77
|
+
config.default_profile = nextDefault;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
delete config.default_profile;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
await writeConfig(path, config);
|
|
84
|
+
return config;
|
|
85
|
+
}
|
|
86
|
+
export async function useProfile(path, name) {
|
|
87
|
+
const config = await readConfig(path);
|
|
88
|
+
if (!config.profiles[name]) {
|
|
89
|
+
throw new Error(`profile 不存在:${name}`);
|
|
90
|
+
}
|
|
91
|
+
config.default_profile = name;
|
|
92
|
+
await writeConfig(path, config);
|
|
93
|
+
return config;
|
|
94
|
+
}
|
|
95
|
+
export function selectProfile(config, name) {
|
|
96
|
+
const profileName = name ?? config.default_profile;
|
|
97
|
+
if (!profileName) {
|
|
98
|
+
throw new Error("未配置默认 profile,请先运行 profile add 或使用 --profile");
|
|
99
|
+
}
|
|
100
|
+
const profile = config.profiles[profileName];
|
|
101
|
+
if (!profile) {
|
|
102
|
+
throw new Error(`profile 不存在:${profileName}`);
|
|
103
|
+
}
|
|
104
|
+
return profile;
|
|
105
|
+
}
|
|
106
|
+
export function getProfileName(config, name) {
|
|
107
|
+
const profileName = name ?? config.default_profile;
|
|
108
|
+
if (!profileName || !config.profiles[profileName]) {
|
|
109
|
+
throw new Error("未找到可用 profile");
|
|
110
|
+
}
|
|
111
|
+
return profileName;
|
|
112
|
+
}
|
|
113
|
+
//# 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/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createProgram, parseUnknownFieldOptions } from "./commands.js";
|
|
2
|
+
export { ApiClient, resourcePath } from "./client.js";
|
|
3
|
+
export { CONFIG_ENV, DEFAULT_CONFIG_BASENAME, readConfig, resolveConfigPath, writeConfig } from "./config.js";
|
|
4
|
+
export { formatHuman, formatJson } from "./output.js";
|
|
5
|
+
export { redactSecrets } from "./safe.js";
|
|
6
|
+
export type { AppConfig, JsonObject, JsonValue, Profile } from "./types.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createProgram, parseUnknownFieldOptions } from "./commands.js";
|
|
2
|
+
export { ApiClient, resourcePath } from "./client.js";
|
|
3
|
+
export { CONFIG_ENV, DEFAULT_CONFIG_BASENAME, readConfig, resolveConfigPath, writeConfig } from "./config.js";
|
|
4
|
+
export { formatHuman, formatJson } from "./output.js";
|
|
5
|
+
export { redactSecrets } from "./safe.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { JsonObject } from "./types.js";
|
|
2
|
+
export declare function parseJsonObject(raw: string, source?: string): JsonObject;
|
|
3
|
+
export declare function readJsonObjectFile(path: string): Promise<JsonObject>;
|
|
4
|
+
export declare function mergePayloads(...payloads: Array<JsonObject | undefined>): JsonObject;
|
package/dist/json.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const jsonValueSchema = z.lazy(() => z.union([
|
|
4
|
+
z.string(),
|
|
5
|
+
z.number(),
|
|
6
|
+
z.boolean(),
|
|
7
|
+
z.null(),
|
|
8
|
+
z.array(jsonValueSchema),
|
|
9
|
+
z.record(jsonValueSchema)
|
|
10
|
+
]));
|
|
11
|
+
const jsonObjectSchema = z.record(jsonValueSchema);
|
|
12
|
+
export function parseJsonObject(raw, source = "JSON") {
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(raw);
|
|
15
|
+
return jsonObjectSchema.parse(parsed);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
+
throw new Error(`${source} 不是合法 JSON object:${message}`, { cause: error });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function readJsonObjectFile(path) {
|
|
23
|
+
return parseJsonObject(await readFile(path, "utf8"), path);
|
|
24
|
+
}
|
|
25
|
+
export function mergePayloads(...payloads) {
|
|
26
|
+
const merged = {};
|
|
27
|
+
for (const payload of payloads) {
|
|
28
|
+
if (!payload)
|
|
29
|
+
continue;
|
|
30
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
31
|
+
merged[key] = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return merged;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=json.js.map
|
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,eAAe,GAAyB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CACxD,CAAC,CAAC,KAAK,CAAC;IACN,CAAC,CAAC,MAAM,EAAE;IACV,CAAC,CAAC,MAAM,EAAE;IACV,CAAC,CAAC,OAAO,EAAE;IACX,CAAC,CAAC,IAAI,EAAE;IACR,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;IACxB,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC;CAC1B,CAAC,CACH,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AAEnD,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,MAAM,GAAG,MAAM;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,OAAO,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,qBAAqB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAY;IACnD,OAAO,eAAe,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAG,QAAuC;IACtE,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/output.d.ts
ADDED
package/dist/output.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { assertSafeText, redactSecrets } from "./safe.js";
|
|
2
|
+
export function formatJson(value) {
|
|
3
|
+
const text = `${JSON.stringify(redactSecrets(value), null, 2)}\n`;
|
|
4
|
+
assertSafeText(text);
|
|
5
|
+
return text;
|
|
6
|
+
}
|
|
7
|
+
export function formatHuman(value) {
|
|
8
|
+
const safeValue = redactSecrets(value);
|
|
9
|
+
const text = typeof safeValue === "string" ? `${safeValue}\n` : `${JSON.stringify(safeValue, null, 2)}\n`;
|
|
10
|
+
assertSafeText(text);
|
|
11
|
+
return text;
|
|
12
|
+
}
|
|
13
|
+
export function formatProfileList(config, json) {
|
|
14
|
+
const profiles = Object.entries(config.profiles).map(([name, profile]) => ({
|
|
15
|
+
name,
|
|
16
|
+
default: config.default_profile === name,
|
|
17
|
+
base_url: profile.base_url,
|
|
18
|
+
username: profile.username
|
|
19
|
+
}));
|
|
20
|
+
if (json)
|
|
21
|
+
return formatJson(profiles);
|
|
22
|
+
if (profiles.length === 0)
|
|
23
|
+
return "未配置 profile\n";
|
|
24
|
+
return `${profiles
|
|
25
|
+
.map((profile) => `${profile.default ? "*" : " "} ${profile.name}\t${profile.base_url}\t${profile.username}`)
|
|
26
|
+
.join("\n")}\n`;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1D,MAAM,UAAU,UAAU,CAAC,KAAgB;IACzC,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAClE,cAAc,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAgB;IAC1C,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAC1G,cAAc,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,IAAa;IAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACzE,IAAI;QACJ,OAAO,EAAE,MAAM,CAAC,eAAe,KAAK,IAAI;QACxC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC,CAAC,CAAC;IACJ,IAAI,IAAI;QAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IAClD,OAAO,GAAG,QAAQ;SACf,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;SAC5G,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACpB,CAAC"}
|
package/dist/safe.d.ts
ADDED
package/dist/safe.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const secretKeys = new Set([
|
|
2
|
+
"authorization",
|
|
3
|
+
"jwt",
|
|
4
|
+
"password",
|
|
5
|
+
"secret",
|
|
6
|
+
"token",
|
|
7
|
+
"access_token",
|
|
8
|
+
"refresh_token"
|
|
9
|
+
]);
|
|
10
|
+
export function redactSecrets(value) {
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
return value.map((item) => redactSecrets(item));
|
|
13
|
+
}
|
|
14
|
+
if (value && typeof value === "object") {
|
|
15
|
+
const redacted = {};
|
|
16
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
17
|
+
redacted[key] = secretKeys.has(key.toLowerCase()) ? "[redacted]" : redactSecrets(nested);
|
|
18
|
+
}
|
|
19
|
+
return redacted;
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
export function assertSafeText(text) {
|
|
24
|
+
if (/eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/.test(text)) {
|
|
25
|
+
throw new Error("输出包含疑似 JWT,已阻止打印");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=safe.js.map
|
package/dist/safe.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe.js","sourceRoot":"","sources":["../src/safe.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,eAAe;IACf,KAAK;IACL,UAAU;IACV,QAAQ;IACR,OAAO;IACP,cAAc;IACd,eAAe;CAChB,CAAC,CAAC;AAEH,MAAM,UAAU,aAAa,CAAsB,KAAQ;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAM,CAAC;IACvD,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,QAAQ,GAA8B,EAAE,CAAC;QAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,QAAQ,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,QAAa,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,mDAAmD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
2
|
+
[key: string]: JsonValue;
|
|
3
|
+
};
|
|
4
|
+
export type JsonObject = {
|
|
5
|
+
[key: string]: JsonValue;
|
|
6
|
+
};
|
|
7
|
+
export interface Profile {
|
|
8
|
+
base_url: string;
|
|
9
|
+
username: string;
|
|
10
|
+
password: string;
|
|
11
|
+
token?: string | undefined;
|
|
12
|
+
token_expires_at?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
export interface AppConfig {
|
|
15
|
+
default_profile?: string | undefined;
|
|
16
|
+
profiles: Record<string, Profile>;
|
|
17
|
+
}
|
|
18
|
+
export interface RuntimeContext {
|
|
19
|
+
env: NodeJS.ProcessEnv;
|
|
20
|
+
homeDir: string;
|
|
21
|
+
fetch: typeof fetch;
|
|
22
|
+
stdin?: NodeJS.ReadStream;
|
|
23
|
+
stdout: NodeJS.WriteStream | NodeJS.WritableStream;
|
|
24
|
+
stderr: NodeJS.WriteStream | NodeJS.WritableStream;
|
|
25
|
+
}
|
|
26
|
+
export interface RequestRecord {
|
|
27
|
+
method: string;
|
|
28
|
+
path: string;
|
|
29
|
+
query?: Record<string, string | number | boolean> | undefined;
|
|
30
|
+
body?: JsonValue | FormData | undefined;
|
|
31
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nginx-proxy-manager-cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "用于管理 Nginx Proxy Manager API。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"packageManager": "pnpm@10.23.0",
|
|
7
|
+
"bin": {
|
|
8
|
+
"nginx-proxy-manager": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"AGENTS.md",
|
|
20
|
+
"CHANGELOG.md"
|
|
21
|
+
],
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+ssh://git@github.com/Aturan/nginx-proxy-manager-cli.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/Aturan/nginx-proxy-manager-cli/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/Aturan/nginx-proxy-manager-cli#readme",
|
|
31
|
+
"keywords": [
|
|
32
|
+
"nginx-proxy-manager",
|
|
33
|
+
"npm-cli",
|
|
34
|
+
"proxy-hosts",
|
|
35
|
+
"certificates",
|
|
36
|
+
"streams"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.11"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc -p tsconfig.build.json",
|
|
43
|
+
"clean": "rimraf dist coverage",
|
|
44
|
+
"dev": "pnpm build && node dist/cli.js",
|
|
45
|
+
"lint": "eslint .",
|
|
46
|
+
"lint:commit": "commitlint --from=HEAD~1 --to=HEAD",
|
|
47
|
+
"prepare": "husky",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"test": "vitest run tests/unit tests/integration",
|
|
50
|
+
"release": "node -e \"console.error('Use pnpm release:patch, pnpm release:minor, or pnpm release:major'); process.exit(1)\"",
|
|
51
|
+
"release:patch": "release-it patch --ci",
|
|
52
|
+
"release:minor": "release-it minor --ci",
|
|
53
|
+
"release:major": "release-it major --ci"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@inquirer/prompts": "^7.8.0",
|
|
57
|
+
"commander": "^14.0.0",
|
|
58
|
+
"undici": "^7.12.0",
|
|
59
|
+
"zod": "^3.25.76"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@commitlint/cli": "^21.2.0",
|
|
63
|
+
"@commitlint/config-conventional": "^21.2.0",
|
|
64
|
+
"@eslint/js": "^9.39.4",
|
|
65
|
+
"@release-it/conventional-changelog": "^11.0.1",
|
|
66
|
+
"@types/node": "^24.0.10",
|
|
67
|
+
"eslint": "^9.30.1",
|
|
68
|
+
"husky": "^9.1.7",
|
|
69
|
+
"release-it": "^18.1.2",
|
|
70
|
+
"rimraf": "^6.0.1",
|
|
71
|
+
"typescript": "^5.8.3",
|
|
72
|
+
"typescript-eslint": "^8.35.1",
|
|
73
|
+
"vitest": "^3.2.4"
|
|
74
|
+
},
|
|
75
|
+
"publishConfig": {
|
|
76
|
+
"access": "public",
|
|
77
|
+
"provenance": true
|
|
78
|
+
}
|
|
79
|
+
}
|