@wax0629/pi-manager 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/package.json +1 -1
- package/src/cli.mjs +86 -20
- package/web/dist/assets/index-BFfa1pbc.js +9 -0
- package/web/dist/assets/index-rnKFOIEj.css +2 -0
- package/web/dist/index.html +16 -3
- package/web/dist/assets/index-CW8mUwad.js +0 -9
- package/web/dist/assets/index-Dnr7dLeF.css +0 -2
package/README.md
CHANGED
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -4,7 +4,9 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const CLI_MESSAGES = {
|
|
8
|
+
zh: {
|
|
9
|
+
help: `Pi Manager — 本地控制面
|
|
8
10
|
|
|
9
11
|
用法:
|
|
10
12
|
pi-manager [选项]
|
|
@@ -16,9 +18,65 @@ const HELP = `Pi Manager — 本地控制面
|
|
|
16
18
|
-h, --help 显示帮助
|
|
17
19
|
|
|
18
20
|
缺 web/dist 时先运行: npm --prefix web run build
|
|
19
|
-
|
|
21
|
+
`,
|
|
22
|
+
unknownArg: "未知参数: {token}",
|
|
23
|
+
needValue: "{flag} 需要一个值",
|
|
24
|
+
invalidPort: "无效端口: {value}",
|
|
25
|
+
missingDist: "缺少 web/dist/index.html。先运行: npm --prefix web run build",
|
|
26
|
+
alreadyRunning: "Pi Manager 已在运行: {url}",
|
|
27
|
+
startFailed: "Pi Manager 启动失败: {error}",
|
|
28
|
+
cannotOpen: "无法打开浏览器: {error}",
|
|
29
|
+
openManual: "请手动打开 {url}"
|
|
30
|
+
},
|
|
31
|
+
en: {
|
|
32
|
+
help: `Pi Manager — local control plane
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
pi-manager [options]
|
|
36
|
+
|
|
37
|
+
Options:
|
|
38
|
+
--host <address> listen address (default 127.0.0.1, or PI_MANAGER_HOST)
|
|
39
|
+
--port <port> listen port (default 8670, or PI_MANAGER_PORT)
|
|
40
|
+
--no-open do not open a browser
|
|
41
|
+
-h, --help show help
|
|
42
|
+
|
|
43
|
+
If web/dist is missing, run: npm --prefix web run build
|
|
44
|
+
`,
|
|
45
|
+
unknownArg: "Unknown argument: {token}",
|
|
46
|
+
needValue: "{flag} requires a value",
|
|
47
|
+
invalidPort: "Invalid port: {value}",
|
|
48
|
+
missingDist: "Missing web/dist/index.html. Run: npm --prefix web run build",
|
|
49
|
+
alreadyRunning: "Pi Manager is already running at {url}",
|
|
50
|
+
startFailed: "Pi Manager failed to start: {error}",
|
|
51
|
+
cannotOpen: "Could not open the browser: {error}",
|
|
52
|
+
openManual: "Open {url} manually"
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export function cliLocale(env = process.env) {
|
|
57
|
+
const explicit = String(env.PI_MANAGER_LANG || "").trim().toLowerCase();
|
|
58
|
+
if (explicit === "zh" || explicit.startsWith("zh")) return "zh";
|
|
59
|
+
if (explicit === "en" || explicit.startsWith("en")) return "en";
|
|
60
|
+
const lang = String(env.LANG || env.LC_ALL || env.LC_MESSAGES || "").toLowerCase();
|
|
61
|
+
return lang.startsWith("zh") ? "zh" : "en";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function formatCliMessage(template, params) {
|
|
65
|
+
if (!params) return template;
|
|
66
|
+
return template.replace(/\{(\w+)\}/g, (match, name) => (
|
|
67
|
+
Object.prototype.hasOwnProperty.call(params, name) ? String(params[name]) : match
|
|
68
|
+
));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function cliMessage(key, params, env = process.env) {
|
|
72
|
+
const locale = cliLocale(env);
|
|
73
|
+
const table = CLI_MESSAGES[locale] || CLI_MESSAGES.en;
|
|
74
|
+
return formatCliMessage(table[key] || CLI_MESSAGES.en[key] || key, params);
|
|
75
|
+
}
|
|
20
76
|
|
|
21
|
-
|
|
77
|
+
const HELP = CLI_MESSAGES.en.help;
|
|
78
|
+
|
|
79
|
+
export function parseCliArgs(argv, env = process.env) {
|
|
22
80
|
const args = { host: undefined, port: undefined, open: true, help: false };
|
|
23
81
|
for (let i = 0; i < argv.length; i += 1) {
|
|
24
82
|
const token = argv[i];
|
|
@@ -31,7 +89,7 @@ export function parseCliArgs(argv) {
|
|
|
31
89
|
continue;
|
|
32
90
|
}
|
|
33
91
|
if (token === "--host") {
|
|
34
|
-
args.host = requireValue(argv, ++i, "--host");
|
|
92
|
+
args.host = requireValue(argv, ++i, "--host", env);
|
|
35
93
|
continue;
|
|
36
94
|
}
|
|
37
95
|
if (token.startsWith("--host=")) {
|
|
@@ -39,28 +97,28 @@ export function parseCliArgs(argv) {
|
|
|
39
97
|
continue;
|
|
40
98
|
}
|
|
41
99
|
if (token === "--port" || token === "-p") {
|
|
42
|
-
args.port = parsePort(requireValue(argv, ++i, token));
|
|
100
|
+
args.port = parsePort(requireValue(argv, ++i, token, env), env);
|
|
43
101
|
continue;
|
|
44
102
|
}
|
|
45
103
|
if (token.startsWith("--port=")) {
|
|
46
|
-
args.port = parsePort(token.slice("--port=".length));
|
|
104
|
+
args.port = parsePort(token.slice("--port=".length), env);
|
|
47
105
|
continue;
|
|
48
106
|
}
|
|
49
|
-
throw new Error(
|
|
107
|
+
throw new Error(cliMessage("unknownArg", { token }, env));
|
|
50
108
|
}
|
|
51
109
|
return args;
|
|
52
110
|
}
|
|
53
111
|
|
|
54
|
-
function requireValue(argv, index, flag) {
|
|
112
|
+
function requireValue(argv, index, flag, env = process.env) {
|
|
55
113
|
const value = argv[index];
|
|
56
|
-
if (!value || value.startsWith("-")) throw new Error(
|
|
114
|
+
if (!value || value.startsWith("-")) throw new Error(cliMessage("needValue", { flag }, env));
|
|
57
115
|
return value;
|
|
58
116
|
}
|
|
59
117
|
|
|
60
|
-
function parsePort(value) {
|
|
118
|
+
function parsePort(value, env = process.env) {
|
|
61
119
|
const port = Number(value);
|
|
62
120
|
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
63
|
-
throw new Error(
|
|
121
|
+
throw new Error(cliMessage("invalidPort", { value }, env));
|
|
64
122
|
}
|
|
65
123
|
return port;
|
|
66
124
|
}
|
|
@@ -97,7 +155,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
97
155
|
return 1;
|
|
98
156
|
}
|
|
99
157
|
if (args.help) {
|
|
100
|
-
process.stdout.write(
|
|
158
|
+
process.stdout.write(cliMessage("help"));
|
|
101
159
|
return 0;
|
|
102
160
|
}
|
|
103
161
|
if (args.host) process.env.PI_MANAGER_HOST = args.host;
|
|
@@ -105,7 +163,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
105
163
|
|
|
106
164
|
const { startManagerServer, publicDir, store } = await import("./server.mjs");
|
|
107
165
|
if (!hasWebUi(publicDir)) {
|
|
108
|
-
console.error("
|
|
166
|
+
console.error(cliMessage("missingDist"));
|
|
109
167
|
process.exitCode = 1;
|
|
110
168
|
return 1;
|
|
111
169
|
}
|
|
@@ -122,9 +180,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
122
180
|
console.log(`Pi gateway: http://${gateway.host}:${gateway.port}/v1`);
|
|
123
181
|
} catch (error) {
|
|
124
182
|
if (error && error.code === "EADDRINUSE") {
|
|
125
|
-
console.log(
|
|
183
|
+
console.log(cliMessage("alreadyRunning", { url }));
|
|
126
184
|
} else {
|
|
127
|
-
console.error(
|
|
185
|
+
console.error(cliMessage("startFailed", { error: error instanceof Error ? error.message : String(error) }));
|
|
128
186
|
process.exitCode = 1;
|
|
129
187
|
return 1;
|
|
130
188
|
}
|
|
@@ -134,8 +192,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
134
192
|
try {
|
|
135
193
|
await openBrowser(url);
|
|
136
194
|
} catch (error) {
|
|
137
|
-
console.error(
|
|
138
|
-
console.error(
|
|
195
|
+
console.error(cliMessage("cannotOpen", { error: error instanceof Error ? error.message : String(error) }));
|
|
196
|
+
console.error(cliMessage("openManual", { url }));
|
|
139
197
|
}
|
|
140
198
|
}
|
|
141
199
|
|
|
@@ -144,12 +202,20 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
144
202
|
return 0;
|
|
145
203
|
}
|
|
146
204
|
|
|
147
|
-
|
|
148
|
-
if (
|
|
205
|
+
export function isCliEntrypoint(argv1 = process.argv[1], moduleUrl = import.meta.url) {
|
|
206
|
+
if (!argv1) return false;
|
|
207
|
+
try {
|
|
208
|
+
return fs.realpathSync(argv1) === fs.realpathSync(fileURLToPath(moduleUrl));
|
|
209
|
+
} catch {
|
|
210
|
+
return path.resolve(argv1) === fileURLToPath(moduleUrl);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (isCliEntrypoint()) {
|
|
149
215
|
main().catch((error) => {
|
|
150
216
|
console.error(error instanceof Error ? error.message : String(error));
|
|
151
217
|
process.exitCode = 1;
|
|
152
218
|
});
|
|
153
219
|
}
|
|
154
220
|
|
|
155
|
-
export { main, HELP };
|
|
221
|
+
export { main, HELP, CLI_MESSAGES };
|