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.
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WebSocketServerManager = exports.WSManager = void 0;
37
+ const os = __importStar(require("os"));
38
+ const uuid_1 = require("uuid");
39
+ const ws_1 = require("ws");
40
+ /**
41
+ * 选择当前机器最合适的局域网 IP
42
+ * @returns 返回可用的 IPv4 地址,兜底 127.0.0.1
43
+ * @example
44
+ * const ip = detectHostIp()
45
+ */
46
+ function detectHostIp() {
47
+ const nets = os.networkInterfaces();
48
+ const entries = [];
49
+ for (const name of Object.keys(nets)) {
50
+ for (const info of nets[name] || []) {
51
+ const i = info;
52
+ const addr = String(i.address || "");
53
+ const bad = /(awdl|utun|llw|bridge|vmnet|vbox|docker)/i.test(name);
54
+ const linkLocal = /^169\.254\./.test(addr);
55
+ if (i.family === "IPv4" && !i.internal && !bad && !linkLocal) {
56
+ entries.push({ name, addr });
57
+ }
58
+ }
59
+ }
60
+ const score = (e) => {
61
+ let s = 0;
62
+ if (process.platform === "darwin" && e.name === "en0") {
63
+ s += 60;
64
+ }
65
+ if (/(wi-?fi|wlan|wlp|wl)/i.test(e.name)) {
66
+ s += 50;
67
+ }
68
+ if (/^(en|eth)\d+$/i.test(e.name)) {
69
+ s += 40;
70
+ }
71
+ if (/^192\.168\./.test(e.addr)) {
72
+ s += 30;
73
+ }
74
+ else if (/^10\./.test(e.addr)) {
75
+ s += 25;
76
+ }
77
+ else if (/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(e.addr)) {
78
+ s += 20;
79
+ }
80
+ return s;
81
+ };
82
+ entries.sort((a, b) => score(b) - score(a));
83
+ return entries[0]?.addr ?? "127.0.0.1";
84
+ }
85
+ /**
86
+ * CLI 版 WebSocket 管理器
87
+ */
88
+ class WSManager {
89
+ constructor() {
90
+ Object.defineProperty(this, "wss", {
91
+ enumerable: true,
92
+ configurable: true,
93
+ writable: true,
94
+ value: null
95
+ });
96
+ Object.defineProperty(this, "client", {
97
+ enumerable: true,
98
+ configurable: true,
99
+ writable: true,
100
+ value: null
101
+ });
102
+ Object.defineProperty(this, "checkInterval", {
103
+ enumerable: true,
104
+ configurable: true,
105
+ writable: true,
106
+ value: null
107
+ });
108
+ Object.defineProperty(this, "connectedClientIp", {
109
+ enumerable: true,
110
+ configurable: true,
111
+ writable: true,
112
+ value: null
113
+ });
114
+ Object.defineProperty(this, "hostIp", {
115
+ enumerable: true,
116
+ configurable: true,
117
+ writable: true,
118
+ value: detectHostIp()
119
+ });
120
+ Object.defineProperty(this, "port", {
121
+ enumerable: true,
122
+ configurable: true,
123
+ writable: true,
124
+ value: 31111
125
+ });
126
+ Object.defineProperty(this, "pending", {
127
+ enumerable: true,
128
+ configurable: true,
129
+ writable: true,
130
+ value: new Map()
131
+ });
132
+ }
133
+ /**
134
+ * 获取 WS 管理器单例
135
+ * @returns 返回单例实例
136
+ * @example
137
+ * const ws = WSManager.get()
138
+ */
139
+ static get() {
140
+ if (!this.instance) {
141
+ this.instance = new WSManager();
142
+ }
143
+ return this.instance;
144
+ }
145
+ /**
146
+ * 判断是否已有设备连接
147
+ * @returns 已连接返回 true,否则 false
148
+ * @example
149
+ * WSManager.isConnected()
150
+ */
151
+ static isConnected() {
152
+ return this.get().client !== null;
153
+ }
154
+ /**
155
+ * 静态请求入口
156
+ * @param type 请求类型
157
+ * @param message 请求参数
158
+ * @param timeoutMs 超时时间(毫秒)
159
+ * @returns 返回设备响应
160
+ * @example
161
+ * await WSManager.request("runtime_status", {}, 5000)
162
+ */
163
+ static request(type, message = {}, timeoutMs = 60000) {
164
+ return this.get().request(type, message, timeoutMs);
165
+ }
166
+ /**
167
+ * 获取监听地址
168
+ * @returns 返回 ws 地址
169
+ * @example
170
+ * ws.getAddress()
171
+ */
172
+ getAddress() {
173
+ return `ws://${this.hostIp}:${this.port}`;
174
+ }
175
+ /**
176
+ * 判断服务器是否已启动
177
+ * @returns 已启动返回 true,否则 false
178
+ * @example
179
+ * ws.isStarted()
180
+ */
181
+ isStarted() {
182
+ return this.wss !== null;
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
+ }
202
+ /**
203
+ * 启动 WS 服务
204
+ * @param port 指定端口,默认 31111
205
+ * @returns 启动完成后返回 Promise<void>
206
+ * @example
207
+ * await ws.start(31111)
208
+ */
209
+ async start(port = 31111) {
210
+ if (this.wss) {
211
+ console.log(`服务已开启,地址 ${this.getAddress()}`);
212
+ return;
213
+ }
214
+ this.port = port;
215
+ this.wss = new ws_1.WebSocketServer({ port: this.port, host: "0.0.0.0" });
216
+ this.wss.on("connection", (ws) => {
217
+ if (this.client) {
218
+ ws.send(JSON.stringify({ type: "reject", reason: "only-one-client" }));
219
+ ws.close(1013, "Only one client allowed");
220
+ return;
221
+ }
222
+ this.client = ws;
223
+ const socket = ws;
224
+ this.connectedClientIp = socket._socket?.remoteAddress || null;
225
+ ws.on("close", () => {
226
+ if (this.client === ws) {
227
+ console.log(`设备已断开,设备IP: ${this.connectedClientIp || "unknown"}`);
228
+ this.stopStatusInterval();
229
+ this.client = null;
230
+ this.connectedClientIp = null;
231
+ }
232
+ });
233
+ ws.on("message", (data) => {
234
+ let message = null;
235
+ try {
236
+ message = JSON.parse(data.toString());
237
+ }
238
+ catch {
239
+ return;
240
+ }
241
+ if (message.type === "log") {
242
+ console.log("[device-log]", JSON.stringify(message));
243
+ return;
244
+ }
245
+ const id = message.requestId;
246
+ if (id && this.pending.has(id)) {
247
+ const p = this.pending.get(id);
248
+ clearTimeout(p.timer);
249
+ this.pending.delete(id);
250
+ p.resolve(message);
251
+ }
252
+ });
253
+ console.log(`设备已连接,设备IP: ${this.connectedClientIp || "unknown"}`);
254
+ this.startStatusInterval();
255
+ });
256
+ await new Promise((resolve, reject) => {
257
+ this.wss.once("listening", () => {
258
+ console.log(`服务已开启,地址 ${this.getAddress()}`);
259
+ resolve();
260
+ });
261
+ this.wss.once("error", (err) => {
262
+ this.wss = null;
263
+ console.error(`服务启动失败: ${String(err)}`);
264
+ reject(err);
265
+ });
266
+ });
267
+ }
268
+ /**
269
+ * 等待设备连接
270
+ * @param timeoutMs 超时时间(毫秒)
271
+ * @returns 成功连接后返回 Promise<void>
272
+ * @example
273
+ * await ws.waitForClient(30000)
274
+ */
275
+ async waitForClient(timeoutMs = 30000) {
276
+ if (this.client) {
277
+ return;
278
+ }
279
+ await new Promise((resolve, reject) => {
280
+ const start = Date.now();
281
+ const timer = setInterval(() => {
282
+ if (this.client) {
283
+ clearInterval(timer);
284
+ resolve();
285
+ return;
286
+ }
287
+ if (Date.now() - start > timeoutMs) {
288
+ clearInterval(timer);
289
+ reject(new Error("等待设备连接超时"));
290
+ }
291
+ }, 200);
292
+ });
293
+ }
294
+ /**
295
+ * 发送请求并等待响应
296
+ * @param type 请求类型
297
+ * @param message 请求消息
298
+ * @param timeoutMs 超时时间(毫秒)
299
+ * @returns 返回设备响应
300
+ * @example
301
+ * await ws.request("files", {}, 60000)
302
+ */
303
+ async request(type, message = {}, timeoutMs = 5000) {
304
+ if (!this.client || this.client.readyState !== this.client.OPEN) {
305
+ throw new Error("no-client");
306
+ }
307
+ const id = (0, uuid_1.v4)();
308
+ const payload = JSON.stringify({ ...message, type, requestId: id });
309
+ return new Promise((resolve, reject) => {
310
+ const timer = setTimeout(() => {
311
+ this.pending.delete(id);
312
+ reject(new Error("timeout"));
313
+ }, timeoutMs);
314
+ this.pending.set(id, { resolve, reject, timer });
315
+ try {
316
+ this.client.send(payload);
317
+ }
318
+ catch (e) {
319
+ clearTimeout(timer);
320
+ this.pending.delete(id);
321
+ reject(e);
322
+ }
323
+ });
324
+ }
325
+ /**
326
+ * 停止 WS 服务
327
+ * @returns 停止完成后返回 Promise<void>
328
+ * @example
329
+ * await ws.stop()
330
+ */
331
+ async stop() {
332
+ if (!this.wss) {
333
+ return;
334
+ }
335
+ if (this.client) {
336
+ this.client.close(1000);
337
+ }
338
+ for (const [, p] of this.pending) {
339
+ clearTimeout(p.timer);
340
+ p.reject(new Error("server-stopped"));
341
+ }
342
+ this.pending.clear();
343
+ await new Promise((resolve) => this.wss.close(() => resolve()));
344
+ this.wss = null;
345
+ this.stopStatusInterval();
346
+ console.log("服务已停止");
347
+ }
348
+ /**
349
+ * 启动运行状态轮询
350
+ * @returns 无返回值
351
+ * @example
352
+ * ws.startStatusInterval()
353
+ */
354
+ startStatusInterval() {
355
+ this.stopStatusInterval();
356
+ this.checkInterval = setInterval(async () => {
357
+ try {
358
+ const data = await this.request("runtime_status");
359
+ if (data.success) {
360
+ const status = (data.data || {});
361
+ console.log(`[runtime] memory=${status.memory ?? "unknown"}, isRunning=${status.isRunning ?? "unknown"}`);
362
+ }
363
+ }
364
+ catch {
365
+ // ignore
366
+ }
367
+ }, 2000);
368
+ }
369
+ /**
370
+ * 停止运行状态轮询
371
+ * @returns 无返回值
372
+ * @example
373
+ * ws.stopStatusInterval()
374
+ */
375
+ stopStatusInterval() {
376
+ if (this.checkInterval) {
377
+ clearInterval(this.checkInterval);
378
+ this.checkInterval = null;
379
+ }
380
+ }
381
+ }
382
+ exports.WSManager = WSManager;
383
+ Object.defineProperty(WSManager, "instance", {
384
+ enumerable: true,
385
+ configurable: true,
386
+ writable: true,
387
+ value: null
388
+ });
389
+ /**
390
+ * 对齐原有命名导出
391
+ */
392
+ exports.WebSocketServerManager = WSManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms-vite-plugin",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "type": "commonjs",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -19,16 +19,22 @@
19
19
  "prepublishOnly": "npm run build"
20
20
  },
21
21
  "dependencies": {
22
+ "archiver": "^7.0.1",
22
23
  "commander": "^14.0.3",
24
+ "crc": "^4.3.2",
23
25
  "fs-extra": "^11.3.4",
26
+ "uuid": "^14.0.0",
24
27
  "vite": "^8.0.9",
25
28
  "vite-plugin-bundle-obfuscator": "^1.11.0",
26
- "archiver": "^7.0.1"
29
+ "ws": "^8.20.0"
27
30
  },
28
31
  "devDependencies": {
32
+ "@types/archiver": "^7.0.0",
33
+ "@types/crc": "^4.0.0",
29
34
  "@types/fs-extra": "^11.0.4",
30
35
  "@types/node": "^25.6.0",
31
- "@types/archiver": "^7.0.0",
36
+ "@types/uuid": "^11.0.0",
37
+ "@types/ws": "^8.18.1",
32
38
  "typescript": "~6.0.3"
33
39
  }
34
40
  }