ms-vite-plugin 1.0.3 → 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
@@ -41,11 +41,16 @@ const build_1 = require("./build");
41
41
  const fsExtra = __importStar(require("fs-extra"));
42
42
  const project_1 = require("./project");
43
43
  const ws_manager_1 = require("./ws-manager");
44
+ /**
45
+ * WS 状态持久化文件路径(用于跨进程查询 ws-status)
46
+ */
44
47
  const WS_PID_FILE = path.join(os.tmpdir(), "ms-cli-ws-server.json");
45
48
  /**
46
49
  * 检查工作目录是否为有效的 KuaiJS 项目
47
50
  * @param workspacePath 工作目录路径
48
51
  * @returns 是否为有效项目
52
+ * @example
53
+ * await isValidKuaiJSProject(process.cwd())
49
54
  */
50
55
  async function isValidKuaiJSProject(workspacePath) {
51
56
  try {
@@ -61,24 +66,36 @@ async function isValidKuaiJSProject(workspacePath) {
61
66
  return false;
62
67
  }
63
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
+ }
64
86
  /**
65
87
  * 构建命令处理函数
66
88
  * @param options 命令选项
89
+ * @returns 请求完成后退出
90
+ * @example
91
+ * ms build -d
67
92
  */
68
93
  async function buildCommand(options) {
69
94
  try {
70
- const workspacePath = options.path
71
- ? path.resolve(options.path)
72
- : process.cwd();
95
+ const workspacePath = process.cwd();
73
96
  const isDev = options.dev || false;
74
97
  console.log(`🔍 检查项目目录: ${workspacePath}`);
75
- if (!(await isValidKuaiJSProject(workspacePath))) {
76
- console.error("❌ 错误: 当前目录不是有效的 快点JS 项目");
77
- console.error("请确保目录包含以下文件:");
78
- console.error(" - package.json");
79
- console.error(" - scripts/ 目录");
80
- process.exit(1);
81
- }
98
+ await ensureValidKuaiJSProject(workspacePath);
82
99
  console.log(`🚀 开始构建项目 (${isDev ? "开发模式" : "生产模式"})...`);
83
100
  await (0, build_1.buildAll)(isDev, workspacePath);
84
101
  console.log("✅ 构建完成!");
@@ -96,10 +113,12 @@ async function buildCommand(options) {
96
113
  * @param options 命令选项
97
114
  * @returns 请求完成后退出
98
115
  * @example
99
- * ms run --ip 192.168.1.100 --port 9800 --path ./
116
+ * ms run --ip 192.168.1.100 --port 9800
100
117
  */
101
118
  async function runCommand(options) {
102
119
  try {
120
+ const workspacePath = process.cwd();
121
+ await ensureValidKuaiJSProject(workspacePath);
103
122
  await (0, project_1.runOnDevice)(options);
104
123
  console.log("✅ 运行请求已发送");
105
124
  }
@@ -113,10 +132,12 @@ async function runCommand(options) {
113
132
  * @param options 命令选项
114
133
  * @returns 请求完成后退出
115
134
  * @example
116
- * ms run-ui --ip 192.168.1.100 --port 9800 --path ./
135
+ * ms run-ui --ip 192.168.1.100 --port 9800
117
136
  */
118
137
  async function runUICommand(options) {
119
138
  try {
139
+ const workspacePath = process.cwd();
140
+ await ensureValidKuaiJSProject(workspacePath);
120
141
  await (0, project_1.runUIOnDevice)(options);
121
142
  console.log("✅ UI 预览请求已发送");
122
143
  }
@@ -134,6 +155,8 @@ async function runUICommand(options) {
134
155
  */
135
156
  async function stopCommand(options) {
136
157
  try {
158
+ const workspacePath = process.cwd();
159
+ await ensureValidKuaiJSProject(workspacePath);
137
160
  await (0, project_1.stopOnDevice)(options);
138
161
  console.log("✅ 停止请求已发送");
139
162
  }
@@ -151,6 +174,7 @@ async function stopCommand(options) {
151
174
  */
152
175
  async function wsStartCommand(options) {
153
176
  try {
177
+ await ensureValidKuaiJSProject(process.cwd());
154
178
  const wsPortText = (options.wsPort ?? "31111").trim();
155
179
  const wsPort = Number.parseInt(wsPortText, 10);
156
180
  if (!Number.isInteger(wsPort) || wsPort < 1 || wsPort > 65535) {
@@ -158,17 +182,40 @@ async function wsStartCommand(options) {
158
182
  }
159
183
  const ws = ws_manager_1.WSManager.get();
160
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);
161
205
  await fsExtra.writeJSON(WS_PID_FILE, {
162
206
  pid: process.pid,
163
207
  port: wsPort,
164
208
  address: ws.getAddress(),
165
209
  startedAt: Date.now(),
210
+ connected: ws.isClientConnected(),
211
+ clientIp: ws.getConnectedClientIp(),
166
212
  });
167
213
  console.log("按 Ctrl+C 停止 WS 服务");
168
214
  await new Promise((resolve) => {
169
215
  const shutdown = async () => {
170
216
  process.off("SIGINT", shutdown);
171
217
  process.off("SIGTERM", shutdown);
218
+ clearInterval(statusTimer);
172
219
  await ws.stop();
173
220
  await fsExtra.remove(WS_PID_FILE);
174
221
  resolve();
@@ -190,6 +237,7 @@ async function wsStartCommand(options) {
190
237
  */
191
238
  async function wsStopCommand() {
192
239
  try {
240
+ await ensureValidKuaiJSProject(process.cwd());
193
241
  if (!(await fsExtra.pathExists(WS_PID_FILE))) {
194
242
  console.log("WS 服务未运行");
195
243
  return;
@@ -221,6 +269,7 @@ async function wsStopCommand() {
221
269
  * ms ws-status
222
270
  */
223
271
  async function wsStatusCommand() {
272
+ await ensureValidKuaiJSProject(process.cwd());
224
273
  if (!(await fsExtra.pathExists(WS_PID_FILE))) {
225
274
  console.log("服务状态: stopped");
226
275
  return;
@@ -228,6 +277,10 @@ async function wsStatusCommand() {
228
277
  const info = await fsExtra.readJSON(WS_PID_FILE);
229
278
  const pid = Number(info.pid);
230
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);
231
284
  let running = false;
232
285
  try {
233
286
  process.kill(pid, 0);
@@ -243,15 +296,44 @@ async function wsStatusCommand() {
243
296
  }
244
297
  console.log(`服务状态: running (pid=${pid})`);
245
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");
246
328
  }
247
329
  // 配置 CLI 程序
248
- 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);
249
332
  // 构建命令
250
333
  commander_1.program
251
334
  .command("build")
252
335
  .description("构建 快点JS 项目")
253
336
  .option("-d, --dev", "开发模式构建 (包含 source map)")
254
- .option("-p, --path <path>", "指定项目路径")
255
337
  .action(buildCommand);
256
338
  // 运行命令
257
339
  commander_1.program
@@ -262,7 +344,6 @@ commander_1.program
262
344
  .option("-t, --transport <transport>", "传输方式: http|ws", "http")
263
345
  .option("--ws-port <wsPort>", "WS 服务端口 (默认: 31111)", "31111")
264
346
  .option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
265
- .option("-p, --path <path>", "指定项目路径")
266
347
  .action(runCommand);
267
348
  // UI 预览命令
268
349
  commander_1.program
@@ -273,7 +354,6 @@ commander_1.program
273
354
  .option("-t, --transport <transport>", "传输方式: http|ws", "http")
274
355
  .option("--ws-port <wsPort>", "WS 服务端口 (默认: 31111)", "31111")
275
356
  .option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
276
- .option("-p, --path <path>", "指定项目路径")
277
357
  .action(runUICommand);
278
358
  // 停止命令
279
359
  commander_1.program
package/dist/project.d.ts CHANGED
@@ -4,7 +4,6 @@
4
4
  export interface DeviceCliOptions {
5
5
  ip?: string;
6
6
  port?: string;
7
- path?: string;
8
7
  transport?: string;
9
8
  wsPort?: string;
10
9
  wsWaitMs?: string;
package/dist/project.js CHANGED
@@ -403,9 +403,7 @@ async function ensureWsReady(options) {
403
403
  * await runOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
404
404
  */
405
405
  async function runOnDevice(options) {
406
- const workspacePath = options.path
407
- ? path.resolve(options.path)
408
- : process.cwd();
406
+ const workspacePath = process.cwd();
409
407
  const transport = parseTransport(options);
410
408
  console.log(`🔧 开始构建项目: ${workspacePath}`);
411
409
  await runDevBuild(workspacePath);
@@ -433,9 +431,7 @@ async function runOnDevice(options) {
433
431
  * await runUIOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
434
432
  */
435
433
  async function runUIOnDevice(options) {
436
- const workspacePath = options.path
437
- ? path.resolve(options.path)
438
- : process.cwd();
434
+ const workspacePath = process.cwd();
439
435
  const transport = parseTransport(options);
440
436
  console.log(`🔧 开始构建项目: ${workspacePath}`);
441
437
  await runDevBuild(workspacePath);
@@ -15,6 +15,7 @@ export declare class WSManager {
15
15
  private wss;
16
16
  private client;
17
17
  private checkInterval;
18
+ private connectedClientIp;
18
19
  private readonly hostIp;
19
20
  private port;
20
21
  private pending;
@@ -56,6 +57,20 @@ export declare class WSManager {
56
57
  * ws.isStarted()
57
58
  */
58
59
  isStarted(): boolean;
60
+ /**
61
+ * 获取设备连接状态
62
+ * @returns 已连接返回 true,否则 false
63
+ * @example
64
+ * ws.isClientConnected()
65
+ */
66
+ isClientConnected(): boolean;
67
+ /**
68
+ * 获取当前连接设备 IP
69
+ * @returns 返回设备 IP,未连接时返回 null
70
+ * @example
71
+ * ws.getConnectedClientIp()
72
+ */
73
+ getConnectedClientIp(): string | null;
59
74
  /**
60
75
  * 启动 WS 服务
61
76
  * @param port 指定端口,默认 31111
@@ -105,6 +105,12 @@ class WSManager {
105
105
  writable: true,
106
106
  value: null
107
107
  });
108
+ Object.defineProperty(this, "connectedClientIp", {
109
+ enumerable: true,
110
+ configurable: true,
111
+ writable: true,
112
+ value: null
113
+ });
108
114
  Object.defineProperty(this, "hostIp", {
109
115
  enumerable: true,
110
116
  configurable: true,
@@ -175,6 +181,24 @@ class WSManager {
175
181
  isStarted() {
176
182
  return this.wss !== null;
177
183
  }
184
+ /**
185
+ * 获取设备连接状态
186
+ * @returns 已连接返回 true,否则 false
187
+ * @example
188
+ * ws.isClientConnected()
189
+ */
190
+ isClientConnected() {
191
+ return this.client !== null;
192
+ }
193
+ /**
194
+ * 获取当前连接设备 IP
195
+ * @returns 返回设备 IP,未连接时返回 null
196
+ * @example
197
+ * ws.getConnectedClientIp()
198
+ */
199
+ getConnectedClientIp() {
200
+ return this.connectedClientIp;
201
+ }
178
202
  /**
179
203
  * 启动 WS 服务
180
204
  * @param port 指定端口,默认 31111
@@ -196,12 +220,14 @@ class WSManager {
196
220
  return;
197
221
  }
198
222
  this.client = ws;
223
+ const socket = ws;
224
+ this.connectedClientIp = socket._socket?.remoteAddress || null;
199
225
  ws.on("close", () => {
200
226
  if (this.client === ws) {
201
- const socket = ws;
202
- console.log(`设备已断开,设备IP: ${socket._socket?.remoteAddress || "unknown"}`);
227
+ console.log(`设备已断开,设备IP: ${this.connectedClientIp || "unknown"}`);
203
228
  this.stopStatusInterval();
204
229
  this.client = null;
230
+ this.connectedClientIp = null;
205
231
  }
206
232
  });
207
233
  ws.on("message", (data) => {
@@ -224,8 +250,7 @@ class WSManager {
224
250
  p.resolve(message);
225
251
  }
226
252
  });
227
- const socket = ws;
228
- console.log(`设备已连接,设备IP: ${socket._socket?.remoteAddress || "unknown"}`);
253
+ console.log(`设备已连接,设备IP: ${this.connectedClientIp || "unknown"}`);
229
254
  this.startStatusInterval();
230
255
  });
231
256
  await new Promise((resolve, reject) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms-vite-plugin",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "type": "commonjs",
5
5
  "license": "MIT",
6
6
  "publishConfig": {