ms-vite-plugin 1.0.2 → 1.0.3

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,367 @@
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, "hostIp", {
109
+ enumerable: true,
110
+ configurable: true,
111
+ writable: true,
112
+ value: detectHostIp()
113
+ });
114
+ Object.defineProperty(this, "port", {
115
+ enumerable: true,
116
+ configurable: true,
117
+ writable: true,
118
+ value: 31111
119
+ });
120
+ Object.defineProperty(this, "pending", {
121
+ enumerable: true,
122
+ configurable: true,
123
+ writable: true,
124
+ value: new Map()
125
+ });
126
+ }
127
+ /**
128
+ * 获取 WS 管理器单例
129
+ * @returns 返回单例实例
130
+ * @example
131
+ * const ws = WSManager.get()
132
+ */
133
+ static get() {
134
+ if (!this.instance) {
135
+ this.instance = new WSManager();
136
+ }
137
+ return this.instance;
138
+ }
139
+ /**
140
+ * 判断是否已有设备连接
141
+ * @returns 已连接返回 true,否则 false
142
+ * @example
143
+ * WSManager.isConnected()
144
+ */
145
+ static isConnected() {
146
+ return this.get().client !== null;
147
+ }
148
+ /**
149
+ * 静态请求入口
150
+ * @param type 请求类型
151
+ * @param message 请求参数
152
+ * @param timeoutMs 超时时间(毫秒)
153
+ * @returns 返回设备响应
154
+ * @example
155
+ * await WSManager.request("runtime_status", {}, 5000)
156
+ */
157
+ static request(type, message = {}, timeoutMs = 60000) {
158
+ return this.get().request(type, message, timeoutMs);
159
+ }
160
+ /**
161
+ * 获取监听地址
162
+ * @returns 返回 ws 地址
163
+ * @example
164
+ * ws.getAddress()
165
+ */
166
+ getAddress() {
167
+ return `ws://${this.hostIp}:${this.port}`;
168
+ }
169
+ /**
170
+ * 判断服务器是否已启动
171
+ * @returns 已启动返回 true,否则 false
172
+ * @example
173
+ * ws.isStarted()
174
+ */
175
+ isStarted() {
176
+ return this.wss !== null;
177
+ }
178
+ /**
179
+ * 启动 WS 服务
180
+ * @param port 指定端口,默认 31111
181
+ * @returns 启动完成后返回 Promise<void>
182
+ * @example
183
+ * await ws.start(31111)
184
+ */
185
+ async start(port = 31111) {
186
+ if (this.wss) {
187
+ console.log(`服务已开启,地址 ${this.getAddress()}`);
188
+ return;
189
+ }
190
+ this.port = port;
191
+ this.wss = new ws_1.WebSocketServer({ port: this.port, host: "0.0.0.0" });
192
+ this.wss.on("connection", (ws) => {
193
+ if (this.client) {
194
+ ws.send(JSON.stringify({ type: "reject", reason: "only-one-client" }));
195
+ ws.close(1013, "Only one client allowed");
196
+ return;
197
+ }
198
+ this.client = ws;
199
+ ws.on("close", () => {
200
+ if (this.client === ws) {
201
+ const socket = ws;
202
+ console.log(`设备已断开,设备IP: ${socket._socket?.remoteAddress || "unknown"}`);
203
+ this.stopStatusInterval();
204
+ this.client = null;
205
+ }
206
+ });
207
+ ws.on("message", (data) => {
208
+ let message = null;
209
+ try {
210
+ message = JSON.parse(data.toString());
211
+ }
212
+ catch {
213
+ return;
214
+ }
215
+ if (message.type === "log") {
216
+ console.log("[device-log]", JSON.stringify(message));
217
+ return;
218
+ }
219
+ const id = message.requestId;
220
+ if (id && this.pending.has(id)) {
221
+ const p = this.pending.get(id);
222
+ clearTimeout(p.timer);
223
+ this.pending.delete(id);
224
+ p.resolve(message);
225
+ }
226
+ });
227
+ const socket = ws;
228
+ console.log(`设备已连接,设备IP: ${socket._socket?.remoteAddress || "unknown"}`);
229
+ this.startStatusInterval();
230
+ });
231
+ await new Promise((resolve, reject) => {
232
+ this.wss.once("listening", () => {
233
+ console.log(`服务已开启,地址 ${this.getAddress()}`);
234
+ resolve();
235
+ });
236
+ this.wss.once("error", (err) => {
237
+ this.wss = null;
238
+ console.error(`服务启动失败: ${String(err)}`);
239
+ reject(err);
240
+ });
241
+ });
242
+ }
243
+ /**
244
+ * 等待设备连接
245
+ * @param timeoutMs 超时时间(毫秒)
246
+ * @returns 成功连接后返回 Promise<void>
247
+ * @example
248
+ * await ws.waitForClient(30000)
249
+ */
250
+ async waitForClient(timeoutMs = 30000) {
251
+ if (this.client) {
252
+ return;
253
+ }
254
+ await new Promise((resolve, reject) => {
255
+ const start = Date.now();
256
+ const timer = setInterval(() => {
257
+ if (this.client) {
258
+ clearInterval(timer);
259
+ resolve();
260
+ return;
261
+ }
262
+ if (Date.now() - start > timeoutMs) {
263
+ clearInterval(timer);
264
+ reject(new Error("等待设备连接超时"));
265
+ }
266
+ }, 200);
267
+ });
268
+ }
269
+ /**
270
+ * 发送请求并等待响应
271
+ * @param type 请求类型
272
+ * @param message 请求消息
273
+ * @param timeoutMs 超时时间(毫秒)
274
+ * @returns 返回设备响应
275
+ * @example
276
+ * await ws.request("files", {}, 60000)
277
+ */
278
+ async request(type, message = {}, timeoutMs = 5000) {
279
+ if (!this.client || this.client.readyState !== this.client.OPEN) {
280
+ throw new Error("no-client");
281
+ }
282
+ const id = (0, uuid_1.v4)();
283
+ const payload = JSON.stringify({ ...message, type, requestId: id });
284
+ return new Promise((resolve, reject) => {
285
+ const timer = setTimeout(() => {
286
+ this.pending.delete(id);
287
+ reject(new Error("timeout"));
288
+ }, timeoutMs);
289
+ this.pending.set(id, { resolve, reject, timer });
290
+ try {
291
+ this.client.send(payload);
292
+ }
293
+ catch (e) {
294
+ clearTimeout(timer);
295
+ this.pending.delete(id);
296
+ reject(e);
297
+ }
298
+ });
299
+ }
300
+ /**
301
+ * 停止 WS 服务
302
+ * @returns 停止完成后返回 Promise<void>
303
+ * @example
304
+ * await ws.stop()
305
+ */
306
+ async stop() {
307
+ if (!this.wss) {
308
+ return;
309
+ }
310
+ if (this.client) {
311
+ this.client.close(1000);
312
+ }
313
+ for (const [, p] of this.pending) {
314
+ clearTimeout(p.timer);
315
+ p.reject(new Error("server-stopped"));
316
+ }
317
+ this.pending.clear();
318
+ await new Promise((resolve) => this.wss.close(() => resolve()));
319
+ this.wss = null;
320
+ this.stopStatusInterval();
321
+ console.log("服务已停止");
322
+ }
323
+ /**
324
+ * 启动运行状态轮询
325
+ * @returns 无返回值
326
+ * @example
327
+ * ws.startStatusInterval()
328
+ */
329
+ startStatusInterval() {
330
+ this.stopStatusInterval();
331
+ this.checkInterval = setInterval(async () => {
332
+ try {
333
+ const data = await this.request("runtime_status");
334
+ if (data.success) {
335
+ const status = (data.data || {});
336
+ console.log(`[runtime] memory=${status.memory ?? "unknown"}, isRunning=${status.isRunning ?? "unknown"}`);
337
+ }
338
+ }
339
+ catch {
340
+ // ignore
341
+ }
342
+ }, 2000);
343
+ }
344
+ /**
345
+ * 停止运行状态轮询
346
+ * @returns 无返回值
347
+ * @example
348
+ * ws.stopStatusInterval()
349
+ */
350
+ stopStatusInterval() {
351
+ if (this.checkInterval) {
352
+ clearInterval(this.checkInterval);
353
+ this.checkInterval = null;
354
+ }
355
+ }
356
+ }
357
+ exports.WSManager = WSManager;
358
+ Object.defineProperty(WSManager, "instance", {
359
+ enumerable: true,
360
+ configurable: true,
361
+ writable: true,
362
+ value: null
363
+ });
364
+ /**
365
+ * 对齐原有命名导出
366
+ */
367
+ 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.3",
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
  }