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 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 = options.path
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
- if (!(await isValidKuaiJSProject(workspacePath))) {
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("0.0.7");
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();
@@ -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>;