ms-vite-plugin 1.0.2 → 1.0.4
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/dist/cli.js +297 -12
- package/dist/device.d.ts +32 -0
- package/dist/device.js +325 -0
- package/dist/project.d.ts +34 -0
- package/dist/project.js +474 -0
- package/dist/ws-manager.d.ts +125 -0
- package/dist/ws-manager.js +392 -0
- package/package.json +9 -3
package/dist/cli.js
CHANGED
|
@@ -35,13 +35,22 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const commander_1 = require("commander");
|
|
38
|
+
const os = __importStar(require("os"));
|
|
38
39
|
const path = __importStar(require("path"));
|
|
39
40
|
const build_1 = require("./build");
|
|
40
41
|
const fsExtra = __importStar(require("fs-extra"));
|
|
42
|
+
const project_1 = require("./project");
|
|
43
|
+
const ws_manager_1 = require("./ws-manager");
|
|
44
|
+
/**
|
|
45
|
+
* WS 状态持久化文件路径(用于跨进程查询 ws-status)
|
|
46
|
+
*/
|
|
47
|
+
const WS_PID_FILE = path.join(os.tmpdir(), "ms-cli-ws-server.json");
|
|
41
48
|
/**
|
|
42
49
|
* 检查工作目录是否为有效的 KuaiJS 项目
|
|
43
50
|
* @param workspacePath 工作目录路径
|
|
44
51
|
* @returns 是否为有效项目
|
|
52
|
+
* @example
|
|
53
|
+
* await isValidKuaiJSProject(process.cwd())
|
|
45
54
|
*/
|
|
46
55
|
async function isValidKuaiJSProject(workspacePath) {
|
|
47
56
|
try {
|
|
@@ -57,24 +66,36 @@ async function isValidKuaiJSProject(workspacePath) {
|
|
|
57
66
|
return false;
|
|
58
67
|
}
|
|
59
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* 统一校验项目目录合法性
|
|
71
|
+
* @param workspacePath 待校验的项目目录
|
|
72
|
+
* @returns 校验通过返回 Promise<void>
|
|
73
|
+
* @example
|
|
74
|
+
* await ensureValidKuaiJSProject("/Users/demo/project")
|
|
75
|
+
*/
|
|
76
|
+
async function ensureValidKuaiJSProject(workspacePath) {
|
|
77
|
+
if (await isValidKuaiJSProject(workspacePath)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
console.error("❌ 错误: 当前目录不是有效的 快点JS 项目");
|
|
81
|
+
console.error("请确保目录包含以下文件:");
|
|
82
|
+
console.error(" - package.json");
|
|
83
|
+
console.error(" - scripts/ 目录");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
60
86
|
/**
|
|
61
87
|
* 构建命令处理函数
|
|
62
88
|
* @param options 命令选项
|
|
89
|
+
* @returns 请求完成后退出
|
|
90
|
+
* @example
|
|
91
|
+
* ms build -d
|
|
63
92
|
*/
|
|
64
93
|
async function buildCommand(options) {
|
|
65
94
|
try {
|
|
66
|
-
const workspacePath =
|
|
67
|
-
? path.resolve(options.path)
|
|
68
|
-
: process.cwd();
|
|
95
|
+
const workspacePath = process.cwd();
|
|
69
96
|
const isDev = options.dev || false;
|
|
70
97
|
console.log(`🔍 检查项目目录: ${workspacePath}`);
|
|
71
|
-
|
|
72
|
-
console.error("❌ 错误: 当前目录不是有效的 快点JS 项目");
|
|
73
|
-
console.error("请确保目录包含以下文件:");
|
|
74
|
-
console.error(" - package.json");
|
|
75
|
-
console.error(" - scripts/ 目录");
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
98
|
+
await ensureValidKuaiJSProject(workspacePath);
|
|
78
99
|
console.log(`🚀 开始构建项目 (${isDev ? "开发模式" : "生产模式"})...`);
|
|
79
100
|
await (0, build_1.buildAll)(isDev, workspacePath);
|
|
80
101
|
console.log("✅ 构建完成!");
|
|
@@ -87,14 +108,278 @@ async function buildCommand(options) {
|
|
|
87
108
|
process.exit(1);
|
|
88
109
|
}
|
|
89
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* run 命令处理函数
|
|
113
|
+
* @param options 命令选项
|
|
114
|
+
* @returns 请求完成后退出
|
|
115
|
+
* @example
|
|
116
|
+
* ms run --ip 192.168.1.100 --port 9800
|
|
117
|
+
*/
|
|
118
|
+
async function runCommand(options) {
|
|
119
|
+
try {
|
|
120
|
+
const workspacePath = process.cwd();
|
|
121
|
+
await ensureValidKuaiJSProject(workspacePath);
|
|
122
|
+
await (0, project_1.runOnDevice)(options);
|
|
123
|
+
console.log("✅ 运行请求已发送");
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error("❌ 运行失败:", error instanceof Error ? error.message : error);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* runUI 命令处理函数
|
|
132
|
+
* @param options 命令选项
|
|
133
|
+
* @returns 请求完成后退出
|
|
134
|
+
* @example
|
|
135
|
+
* ms run-ui --ip 192.168.1.100 --port 9800
|
|
136
|
+
*/
|
|
137
|
+
async function runUICommand(options) {
|
|
138
|
+
try {
|
|
139
|
+
const workspacePath = process.cwd();
|
|
140
|
+
await ensureValidKuaiJSProject(workspacePath);
|
|
141
|
+
await (0, project_1.runUIOnDevice)(options);
|
|
142
|
+
console.log("✅ UI 预览请求已发送");
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error("❌ UI 预览失败:", error instanceof Error ? error.message : error);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* stop 命令处理函数
|
|
151
|
+
* @param options 命令选项
|
|
152
|
+
* @returns 请求完成后退出
|
|
153
|
+
* @example
|
|
154
|
+
* ms stop --ip 192.168.1.100 --port 9800
|
|
155
|
+
*/
|
|
156
|
+
async function stopCommand(options) {
|
|
157
|
+
try {
|
|
158
|
+
const workspacePath = process.cwd();
|
|
159
|
+
await ensureValidKuaiJSProject(workspacePath);
|
|
160
|
+
await (0, project_1.stopOnDevice)(options);
|
|
161
|
+
console.log("✅ 停止请求已发送");
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.error("❌ 停止失败:", error instanceof Error ? error.message : error);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* ws-start 命令处理函数
|
|
170
|
+
* @param options 命令选项
|
|
171
|
+
* @returns 常驻直到收到退出信号
|
|
172
|
+
* @example
|
|
173
|
+
* ms ws-start --ws-port 31111
|
|
174
|
+
*/
|
|
175
|
+
async function wsStartCommand(options) {
|
|
176
|
+
try {
|
|
177
|
+
await ensureValidKuaiJSProject(process.cwd());
|
|
178
|
+
const wsPortText = (options.wsPort ?? "31111").trim();
|
|
179
|
+
const wsPort = Number.parseInt(wsPortText, 10);
|
|
180
|
+
if (!Number.isInteger(wsPort) || wsPort < 1 || wsPort > 65535) {
|
|
181
|
+
throw new Error(`无效 ws 端口: ${wsPortText}`);
|
|
182
|
+
}
|
|
183
|
+
const ws = ws_manager_1.WSManager.get();
|
|
184
|
+
await ws.start(wsPort);
|
|
185
|
+
/**
|
|
186
|
+
* 写入 WS 运行状态到临时文件,供 ws-status 命令跨进程读取
|
|
187
|
+
*/
|
|
188
|
+
const writeStatus = async () => {
|
|
189
|
+
const payload = {
|
|
190
|
+
pid: process.pid,
|
|
191
|
+
port: wsPort,
|
|
192
|
+
address: ws.getAddress(),
|
|
193
|
+
startedAt: Date.now(),
|
|
194
|
+
connected: ws.isClientConnected(),
|
|
195
|
+
clientIp: ws.getConnectedClientIp(),
|
|
196
|
+
};
|
|
197
|
+
await fsExtra.writeJSON(WS_PID_FILE, payload);
|
|
198
|
+
};
|
|
199
|
+
await writeStatus();
|
|
200
|
+
const statusTimer = setInterval(() => {
|
|
201
|
+
writeStatus().catch(() => {
|
|
202
|
+
// ignore periodic write errors
|
|
203
|
+
});
|
|
204
|
+
}, 1000);
|
|
205
|
+
await fsExtra.writeJSON(WS_PID_FILE, {
|
|
206
|
+
pid: process.pid,
|
|
207
|
+
port: wsPort,
|
|
208
|
+
address: ws.getAddress(),
|
|
209
|
+
startedAt: Date.now(),
|
|
210
|
+
connected: ws.isClientConnected(),
|
|
211
|
+
clientIp: ws.getConnectedClientIp(),
|
|
212
|
+
});
|
|
213
|
+
console.log("按 Ctrl+C 停止 WS 服务");
|
|
214
|
+
await new Promise((resolve) => {
|
|
215
|
+
const shutdown = async () => {
|
|
216
|
+
process.off("SIGINT", shutdown);
|
|
217
|
+
process.off("SIGTERM", shutdown);
|
|
218
|
+
clearInterval(statusTimer);
|
|
219
|
+
await ws.stop();
|
|
220
|
+
await fsExtra.remove(WS_PID_FILE);
|
|
221
|
+
resolve();
|
|
222
|
+
};
|
|
223
|
+
process.on("SIGINT", shutdown);
|
|
224
|
+
process.on("SIGTERM", shutdown);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
console.error("❌ WS 服务启动失败:", error instanceof Error ? error.message : error);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* ws-stop 命令处理函数
|
|
234
|
+
* @returns 请求完成后退出
|
|
235
|
+
* @example
|
|
236
|
+
* ms ws-stop
|
|
237
|
+
*/
|
|
238
|
+
async function wsStopCommand() {
|
|
239
|
+
try {
|
|
240
|
+
await ensureValidKuaiJSProject(process.cwd());
|
|
241
|
+
if (!(await fsExtra.pathExists(WS_PID_FILE))) {
|
|
242
|
+
console.log("WS 服务未运行");
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const info = await fsExtra.readJSON(WS_PID_FILE);
|
|
246
|
+
const pid = Number(info.pid);
|
|
247
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
248
|
+
await fsExtra.remove(WS_PID_FILE);
|
|
249
|
+
throw new Error("WS PID 文件损坏");
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
process.kill(pid, "SIGTERM");
|
|
253
|
+
console.log(`✅ 已发送停止信号到 WS 进程: ${pid}`);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
console.log("WS 进程不存在,清理 PID 文件");
|
|
257
|
+
}
|
|
258
|
+
await fsExtra.remove(WS_PID_FILE);
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
console.error("❌ WS 服务停止失败:", error instanceof Error ? error.message : error);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* ws-status 命令处理函数
|
|
267
|
+
* @returns 请求完成后退出
|
|
268
|
+
* @example
|
|
269
|
+
* ms ws-status
|
|
270
|
+
*/
|
|
271
|
+
async function wsStatusCommand() {
|
|
272
|
+
await ensureValidKuaiJSProject(process.cwd());
|
|
273
|
+
if (!(await fsExtra.pathExists(WS_PID_FILE))) {
|
|
274
|
+
console.log("服务状态: stopped");
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const info = await fsExtra.readJSON(WS_PID_FILE);
|
|
278
|
+
const pid = Number(info.pid);
|
|
279
|
+
const address = String(info.address || "unknown");
|
|
280
|
+
const connected = Boolean(info.connected);
|
|
281
|
+
const clientIp = info.clientIp === null || info.clientIp === undefined
|
|
282
|
+
? null
|
|
283
|
+
: String(info.clientIp);
|
|
284
|
+
let running = false;
|
|
285
|
+
try {
|
|
286
|
+
process.kill(pid, 0);
|
|
287
|
+
running = true;
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
running = false;
|
|
291
|
+
}
|
|
292
|
+
if (!running) {
|
|
293
|
+
await fsExtra.remove(WS_PID_FILE);
|
|
294
|
+
console.log("服务状态: stopped");
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
console.log(`服务状态: running (pid=${pid})`);
|
|
298
|
+
console.log(`WS 地址: ${address}`);
|
|
299
|
+
console.log(`连接状态: ${connected ? "connected" : "disconnected"}`);
|
|
300
|
+
if (connected) {
|
|
301
|
+
console.log(`设备IP: ${clientIp || "unknown"}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* 生成顶层 help 的详细命令参数说明
|
|
306
|
+
* @returns 返回格式化后的帮助文本
|
|
307
|
+
* @example
|
|
308
|
+
* renderDetailedCommandHelp()
|
|
309
|
+
*/
|
|
310
|
+
function renderDetailedCommandHelp() {
|
|
311
|
+
const lines = [];
|
|
312
|
+
lines.push("");
|
|
313
|
+
lines.push("详细命令参数:");
|
|
314
|
+
const commands = commander_1.program.commands.filter((cmd) => cmd.name() !== "help");
|
|
315
|
+
for (const cmd of commands) {
|
|
316
|
+
lines.push(` ${cmd.name()}:`);
|
|
317
|
+
if (cmd.options.length === 0) {
|
|
318
|
+
lines.push(" (无额外参数)");
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
for (const opt of cmd.options) {
|
|
322
|
+
const desc = opt.description ? ` ${opt.description}` : "";
|
|
323
|
+
lines.push(` ${opt.flags}${desc}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
lines.push("");
|
|
327
|
+
return lines.join("\n");
|
|
328
|
+
}
|
|
90
329
|
// 配置 CLI 程序
|
|
91
|
-
commander_1.program.name("ms-cli").description("快点JS 构建工具").version("
|
|
330
|
+
commander_1.program.name("ms-cli").description("快点JS 构建工具").version("1.0.4");
|
|
331
|
+
commander_1.program.addHelpText("after", renderDetailedCommandHelp);
|
|
92
332
|
// 构建命令
|
|
93
333
|
commander_1.program
|
|
94
334
|
.command("build")
|
|
95
335
|
.description("构建 快点JS 项目")
|
|
96
336
|
.option("-d, --dev", "开发模式构建 (包含 source map)")
|
|
97
|
-
.option("-p, --path <path>", "指定项目路径")
|
|
98
337
|
.action(buildCommand);
|
|
338
|
+
// 运行命令
|
|
339
|
+
commander_1.program
|
|
340
|
+
.command("run")
|
|
341
|
+
.description("在设备上运行项目")
|
|
342
|
+
.option("-i, --ip <ip>", "设备 IP 地址(transport=http 时必填)")
|
|
343
|
+
.option("--port <port>", "设备端口 (默认: 9800)", "9800")
|
|
344
|
+
.option("-t, --transport <transport>", "传输方式: http|ws", "http")
|
|
345
|
+
.option("--ws-port <wsPort>", "WS 服务端口 (默认: 31111)", "31111")
|
|
346
|
+
.option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
|
|
347
|
+
.action(runCommand);
|
|
348
|
+
// UI 预览命令
|
|
349
|
+
commander_1.program
|
|
350
|
+
.command("run-ui")
|
|
351
|
+
.description("在设备上预览 UI")
|
|
352
|
+
.option("-i, --ip <ip>", "设备 IP 地址(transport=http 时必填)")
|
|
353
|
+
.option("--port <port>", "设备端口 (默认: 9800)", "9800")
|
|
354
|
+
.option("-t, --transport <transport>", "传输方式: http|ws", "http")
|
|
355
|
+
.option("--ws-port <wsPort>", "WS 服务端口 (默认: 31111)", "31111")
|
|
356
|
+
.option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
|
|
357
|
+
.action(runUICommand);
|
|
358
|
+
// 停止命令
|
|
359
|
+
commander_1.program
|
|
360
|
+
.command("stop")
|
|
361
|
+
.description("停止设备上的项目")
|
|
362
|
+
.option("-i, --ip <ip>", "设备 IP 地址(transport=http 时必填)")
|
|
363
|
+
.option("--port <port>", "设备端口 (默认: 9800)", "9800")
|
|
364
|
+
.option("-t, --transport <transport>", "传输方式: http|ws", "http")
|
|
365
|
+
.option("--ws-port <wsPort>", "WS 服务端口 (默认: 31111)", "31111")
|
|
366
|
+
.option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
|
|
367
|
+
.action(stopCommand);
|
|
368
|
+
// WS 服务启动命令
|
|
369
|
+
commander_1.program
|
|
370
|
+
.command("ws-start")
|
|
371
|
+
.description("启动 CLI 内置 WS 服务")
|
|
372
|
+
.option("--ws-port <wsPort>", "WS 服务端口 (默认: 31111)", "31111")
|
|
373
|
+
.action(wsStartCommand);
|
|
374
|
+
// WS 服务停止命令
|
|
375
|
+
commander_1.program
|
|
376
|
+
.command("ws-stop")
|
|
377
|
+
.description("停止 CLI 内置 WS 服务")
|
|
378
|
+
.action(wsStopCommand);
|
|
379
|
+
// WS 服务状态命令
|
|
380
|
+
commander_1.program
|
|
381
|
+
.command("ws-status")
|
|
382
|
+
.description("查看 CLI 内置 WS 服务状态")
|
|
383
|
+
.action(wsStatusCommand);
|
|
99
384
|
// 解析命令行参数
|
|
100
385
|
commander_1.program.parse();
|
package/dist/device.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设备命令选项
|
|
3
|
+
*/
|
|
4
|
+
export interface DeviceCliOptions {
|
|
5
|
+
ip: string;
|
|
6
|
+
port?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 在设备上运行项目(先同步后运行)
|
|
11
|
+
* @param options 命令选项
|
|
12
|
+
* @returns 执行完成后返回 Promise<void>
|
|
13
|
+
* @example
|
|
14
|
+
* await runOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
|
|
15
|
+
*/
|
|
16
|
+
export declare function runOnDevice(options: DeviceCliOptions): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* 在设备上预览 UI(先同步后调用 runUI)
|
|
19
|
+
* @param options 命令选项
|
|
20
|
+
* @returns 执行完成后返回 Promise<void>
|
|
21
|
+
* @example
|
|
22
|
+
* await runUIOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
|
|
23
|
+
*/
|
|
24
|
+
export declare function runUIOnDevice(options: DeviceCliOptions): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* 停止设备上的项目
|
|
27
|
+
* @param options 命令选项
|
|
28
|
+
* @returns 执行完成后返回 Promise<void>
|
|
29
|
+
* @example
|
|
30
|
+
* await stopOnDevice({ ip: "192.168.1.10", port: "9800" })
|
|
31
|
+
*/
|
|
32
|
+
export declare function stopOnDevice(options: DeviceCliOptions): Promise<void>;
|