@hangox/mg-cli 1.0.8 → 1.0.9
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/bin/mg-cli.js +0 -0
- package/dist/cli.js +516 -22
- package/dist/cli.js.map +1 -1
- package/dist/daemon-runner.js +267 -8
- package/dist/daemon-runner.js.map +1 -1
- package/dist/{index-DmySkKst.d.ts → index-cEKly9mt.d.ts} +98 -6
- package/dist/index.d.ts +3 -3
- package/dist/index.js +278 -8
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +267 -8
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -41,6 +41,7 @@ var ErrorNames = {
|
|
|
41
41
|
["E015" /* SERVER_START_FAILED */]: "SERVER_START_FAILED",
|
|
42
42
|
["E016" /* SERVER_ALREADY_RUNNING */]: "SERVER_ALREADY_RUNNING",
|
|
43
43
|
["E017" /* CONNECTION_LOST */]: "CONNECTION_LOST",
|
|
44
|
+
["E018" /* NO_EXTENSION_CONNECTED */]: "NO_EXTENSION_CONNECTED",
|
|
44
45
|
["E099" /* UNKNOWN_ERROR */]: "UNKNOWN_ERROR"
|
|
45
46
|
};
|
|
46
47
|
var ErrorMessages = {
|
|
@@ -61,6 +62,7 @@ var ErrorMessages = {
|
|
|
61
62
|
["E015" /* SERVER_START_FAILED */]: "\u81EA\u52A8\u542F\u52A8 Server \u5931\u8D25",
|
|
62
63
|
["E016" /* SERVER_ALREADY_RUNNING */]: "Server \u5DF2\u5728\u8FD0\u884C\u4E2D",
|
|
63
64
|
["E017" /* CONNECTION_LOST */]: "\u8FDE\u63A5\u65AD\u5F00",
|
|
65
|
+
["E018" /* NO_EXTENSION_CONNECTED */]: "\u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin",
|
|
64
66
|
["E099" /* UNKNOWN_ERROR */]: "\u672A\u77E5\u9519\u8BEF"
|
|
65
67
|
};
|
|
66
68
|
var MGError = class extends Error {
|
|
@@ -210,6 +212,12 @@ var ConnectionManager = class {
|
|
|
210
212
|
providers = /* @__PURE__ */ new Map();
|
|
211
213
|
/** Consumer 连接 */
|
|
212
214
|
consumers = /* @__PURE__ */ new Map();
|
|
215
|
+
/** Chrome 扩展连接(按扩展 ID 索引) */
|
|
216
|
+
chromeExtensions = /* @__PURE__ */ new Map();
|
|
217
|
+
/** 扩展序号映射(扩展 ID → 序号) */
|
|
218
|
+
extensionIndexMap = /* @__PURE__ */ new Map();
|
|
219
|
+
/** 下一个可用的扩展序号 */
|
|
220
|
+
nextExtensionIndex = 1;
|
|
213
221
|
/** 所有连接(按 ID 索引) */
|
|
214
222
|
allConnections = /* @__PURE__ */ new Map();
|
|
215
223
|
/** 心跳检查定时器 */
|
|
@@ -304,6 +312,16 @@ var ConnectionManager = class {
|
|
|
304
312
|
} else if (connectionInfo.type === "consumer" /* CONSUMER */) {
|
|
305
313
|
this.consumers.delete(connectionId);
|
|
306
314
|
this.logger.info(`Consumer \u65AD\u5F00: ${connectionId}`);
|
|
315
|
+
} else if (connectionInfo.type === "chrome_extension" /* CHROME_EXTENSION */) {
|
|
316
|
+
for (const [extensionId, extWs] of this.chromeExtensions) {
|
|
317
|
+
if (extWs.connectionId === connectionId) {
|
|
318
|
+
const index = this.extensionIndexMap.get(extensionId);
|
|
319
|
+
this.chromeExtensions.delete(extensionId);
|
|
320
|
+
this.extensionIndexMap.delete(extensionId);
|
|
321
|
+
this.logger.info(`Chrome \u6269\u5C55\u65AD\u5F00: ${extensionId} (\u5E8F\u53F7: #${index})`);
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
307
325
|
}
|
|
308
326
|
}
|
|
309
327
|
/**
|
|
@@ -357,6 +375,7 @@ var ConnectionManager = class {
|
|
|
357
375
|
return {
|
|
358
376
|
providers: providerCount,
|
|
359
377
|
consumers: this.consumers.size,
|
|
378
|
+
extensions: this.chromeExtensions.size,
|
|
360
379
|
total: this.allConnections.size
|
|
361
380
|
};
|
|
362
381
|
}
|
|
@@ -366,6 +385,48 @@ var ConnectionManager = class {
|
|
|
366
385
|
getConnectedPageUrls() {
|
|
367
386
|
return Array.from(this.providers.keys());
|
|
368
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* 添加 Chrome 扩展连接
|
|
390
|
+
*/
|
|
391
|
+
addChromeExtension(ws, extensionId) {
|
|
392
|
+
const managedWs = this.addConnection(ws, "chrome_extension" /* CHROME_EXTENSION */);
|
|
393
|
+
const index = this.nextExtensionIndex++;
|
|
394
|
+
this.extensionIndexMap.set(extensionId, index);
|
|
395
|
+
this.chromeExtensions.set(extensionId, managedWs);
|
|
396
|
+
this.logger.info(`Chrome \u6269\u5C55\u8FDE\u63A5: ${extensionId} (\u5206\u914D\u5E8F\u53F7: #${index})`);
|
|
397
|
+
return managedWs;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* 根据序号查找扩展
|
|
401
|
+
*/
|
|
402
|
+
findExtensionByIndex(index) {
|
|
403
|
+
for (const [extensionId, extIndex] of this.extensionIndexMap) {
|
|
404
|
+
if (extIndex === index) {
|
|
405
|
+
return this.chromeExtensions.get(extensionId);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return void 0;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 获取第一个扩展
|
|
412
|
+
*/
|
|
413
|
+
getFirstExtension() {
|
|
414
|
+
return this.chromeExtensions.values().next().value;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* 获取所有扩展信息
|
|
418
|
+
*/
|
|
419
|
+
getAllExtensions() {
|
|
420
|
+
const result = [];
|
|
421
|
+
for (const [extensionId, ws] of this.chromeExtensions) {
|
|
422
|
+
const index = this.extensionIndexMap.get(extensionId);
|
|
423
|
+
if (index !== void 0) {
|
|
424
|
+
result.push({ index, extensionId, ws });
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
result.sort((a, b) => a.index - b.index);
|
|
428
|
+
return result;
|
|
429
|
+
}
|
|
369
430
|
/**
|
|
370
431
|
* 关闭所有连接
|
|
371
432
|
*/
|
|
@@ -377,6 +438,8 @@ var ConnectionManager = class {
|
|
|
377
438
|
}
|
|
378
439
|
this.providers.clear();
|
|
379
440
|
this.consumers.clear();
|
|
441
|
+
this.chromeExtensions.clear();
|
|
442
|
+
this.extensionIndexMap.clear();
|
|
380
443
|
this.allConnections.clear();
|
|
381
444
|
}
|
|
382
445
|
};
|
|
@@ -494,6 +557,24 @@ var RequestHandler = class {
|
|
|
494
557
|
this.logger.error(`\u53D1\u9001\u9519\u8BEF\u54CD\u5E94\u5931\u8D25: ${requestId}`, err);
|
|
495
558
|
}
|
|
496
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* 注册待处理请求(供外部使用,如 OPEN_PAGE)
|
|
562
|
+
* @param requestId 请求 ID
|
|
563
|
+
* @param consumer 发起请求的 Consumer
|
|
564
|
+
* @param sendCallback 发送请求的回调函数
|
|
565
|
+
*/
|
|
566
|
+
registerPendingRequest(requestId, consumer, sendCallback) {
|
|
567
|
+
const timer = setTimeout(() => {
|
|
568
|
+
this.handleTimeout(requestId);
|
|
569
|
+
}, REQUEST_TIMEOUT);
|
|
570
|
+
this.pendingRequests.set(requestId, {
|
|
571
|
+
id: requestId,
|
|
572
|
+
consumer,
|
|
573
|
+
timer,
|
|
574
|
+
timestamp: Date.now()
|
|
575
|
+
});
|
|
576
|
+
sendCallback();
|
|
577
|
+
}
|
|
497
578
|
/**
|
|
498
579
|
* 清理特定连接的所有待处理请求
|
|
499
580
|
*/
|
|
@@ -666,12 +747,22 @@ var MGServer = class {
|
|
|
666
747
|
*/
|
|
667
748
|
handleRegister(ws, message) {
|
|
668
749
|
const { connectionType, pageUrl, pageId } = message.data;
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
750
|
+
const extensionId = message.data.extensionId;
|
|
751
|
+
let managedWs;
|
|
752
|
+
let extensionIndex;
|
|
753
|
+
if (connectionType === "chrome_extension" /* CHROME_EXTENSION */ && extensionId) {
|
|
754
|
+
managedWs = this.connectionManager.addChromeExtension(ws, extensionId);
|
|
755
|
+
const exts = this.connectionManager.getAllExtensions();
|
|
756
|
+
const ext = exts.find((e) => e.extensionId === extensionId);
|
|
757
|
+
extensionIndex = ext?.index;
|
|
758
|
+
} else {
|
|
759
|
+
managedWs = this.connectionManager.addConnection(
|
|
760
|
+
ws,
|
|
761
|
+
connectionType,
|
|
762
|
+
pageUrl,
|
|
763
|
+
pageId
|
|
764
|
+
);
|
|
765
|
+
}
|
|
675
766
|
const ack = {
|
|
676
767
|
id: message.id || "",
|
|
677
768
|
type: "register_ack" /* REGISTER_ACK */,
|
|
@@ -679,7 +770,8 @@ var MGServer = class {
|
|
|
679
770
|
data: {
|
|
680
771
|
connectionId: managedWs.connectionId,
|
|
681
772
|
pageUrl,
|
|
682
|
-
serverVersion: getVersion()
|
|
773
|
+
serverVersion: getVersion(),
|
|
774
|
+
...extensionIndex !== void 0 && { extensionIndex }
|
|
683
775
|
}
|
|
684
776
|
};
|
|
685
777
|
ws.send(JSON.stringify(ack));
|
|
@@ -696,6 +788,15 @@ var MGServer = class {
|
|
|
696
788
|
case "get_server_status" /* GET_SERVER_STATUS */:
|
|
697
789
|
this.handleGetServerStatus(ws, message);
|
|
698
790
|
break;
|
|
791
|
+
case "list_extensions" /* LIST_EXTENSIONS */:
|
|
792
|
+
this.handleListExtensions(ws, message);
|
|
793
|
+
break;
|
|
794
|
+
case "open_page" /* OPEN_PAGE */:
|
|
795
|
+
this.handleOpenPage(ws, message);
|
|
796
|
+
break;
|
|
797
|
+
case "navigate_to_node" /* NAVIGATE_TO_NODE */:
|
|
798
|
+
this.handleNavigateToNode(ws, message);
|
|
799
|
+
break;
|
|
699
800
|
case "response" /* RESPONSE */:
|
|
700
801
|
case "error" /* ERROR */:
|
|
701
802
|
this.requestHandler.handleResponse(message);
|
|
@@ -728,6 +829,13 @@ var MGServer = class {
|
|
|
728
829
|
connectedAt: info.connectedAt.toISOString(),
|
|
729
830
|
lastActiveAt: info.lastActiveAt.toISOString()
|
|
730
831
|
}));
|
|
832
|
+
const extensions = this.connectionManager.getAllExtensions();
|
|
833
|
+
const connectedExtensions = extensions.map((ext) => ({
|
|
834
|
+
index: ext.index,
|
|
835
|
+
extensionId: ext.extensionId,
|
|
836
|
+
connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
|
|
837
|
+
lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
|
|
838
|
+
}));
|
|
731
839
|
const uptimeMs = this.startedAt ? Date.now() - this.startedAt.getTime() : 0;
|
|
732
840
|
const statusData = {
|
|
733
841
|
running: this.isRunning,
|
|
@@ -737,7 +845,8 @@ var MGServer = class {
|
|
|
737
845
|
uptime: formatDuration(uptimeMs),
|
|
738
846
|
version: getVersion(),
|
|
739
847
|
stats,
|
|
740
|
-
connectedPages
|
|
848
|
+
connectedPages,
|
|
849
|
+
connectedExtensions
|
|
741
850
|
};
|
|
742
851
|
const response = {
|
|
743
852
|
id: message.id || "",
|
|
@@ -748,6 +857,156 @@ var MGServer = class {
|
|
|
748
857
|
ws.send(JSON.stringify(response));
|
|
749
858
|
this.logger.info("\u8FD4\u56DE Server \u72B6\u6001\u4FE1\u606F");
|
|
750
859
|
}
|
|
860
|
+
/**
|
|
861
|
+
* 处理扩展列表查询
|
|
862
|
+
*/
|
|
863
|
+
handleListExtensions(ws, message) {
|
|
864
|
+
const extensions = this.connectionManager.getAllExtensions();
|
|
865
|
+
const extensionList = extensions.map((ext) => ({
|
|
866
|
+
index: ext.index,
|
|
867
|
+
extensionId: ext.extensionId,
|
|
868
|
+
connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
|
|
869
|
+
lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
|
|
870
|
+
}));
|
|
871
|
+
const response = {
|
|
872
|
+
id: message.id || "",
|
|
873
|
+
type: "response" /* RESPONSE */,
|
|
874
|
+
success: true,
|
|
875
|
+
data: {
|
|
876
|
+
extensions: extensionList,
|
|
877
|
+
totalCount: extensionList.length
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
ws.send(JSON.stringify(response));
|
|
881
|
+
this.logger.info(`\u8FD4\u56DE\u6269\u5C55\u5217\u8868\uFF0C\u5171 ${extensionList.length} \u4E2A\u6269\u5C55`);
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* 处理打开页面请求
|
|
885
|
+
*/
|
|
886
|
+
handleOpenPage(ws, message) {
|
|
887
|
+
const params = message.params;
|
|
888
|
+
const requestId = message.id || "";
|
|
889
|
+
if (!params?.url) {
|
|
890
|
+
const errorResponse = {
|
|
891
|
+
id: requestId,
|
|
892
|
+
type: "error" /* ERROR */,
|
|
893
|
+
success: false,
|
|
894
|
+
error: {
|
|
895
|
+
code: "E011" /* INVALID_PARAMS */,
|
|
896
|
+
name: "INVALID_PARAMS",
|
|
897
|
+
message: "\u7F3A\u5C11 url \u53C2\u6570"
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
ws.send(JSON.stringify(errorResponse));
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
const targetIndex = params.extensionIndex || 1;
|
|
904
|
+
const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
|
|
905
|
+
if (!targetExtension) {
|
|
906
|
+
const errorResponse = {
|
|
907
|
+
id: requestId,
|
|
908
|
+
type: "error" /* ERROR */,
|
|
909
|
+
success: false,
|
|
910
|
+
error: {
|
|
911
|
+
code: "E018" /* NO_EXTENSION_CONNECTED */,
|
|
912
|
+
name: "NO_EXTENSION_CONNECTED",
|
|
913
|
+
message: targetIndex === 1 ? "\u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin" : `\u672A\u627E\u5230\u5E8F\u53F7\u4E3A #${targetIndex} \u7684\u6269\u5C55\u5B9E\u4F8B`
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
ws.send(JSON.stringify(errorResponse));
|
|
917
|
+
this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const forwardMessage = {
|
|
921
|
+
id: requestId,
|
|
922
|
+
type: "open_page" /* OPEN_PAGE */,
|
|
923
|
+
params: { url: params.url }
|
|
924
|
+
};
|
|
925
|
+
this.requestHandler.registerPendingRequest(requestId, ws, () => {
|
|
926
|
+
try {
|
|
927
|
+
targetExtension.send(JSON.stringify(forwardMessage));
|
|
928
|
+
this.logger.info(`\u8F6C\u53D1 OPEN_PAGE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.url}`);
|
|
929
|
+
} catch (error) {
|
|
930
|
+
this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
|
|
931
|
+
const errorResponse = {
|
|
932
|
+
id: requestId,
|
|
933
|
+
type: "error" /* ERROR */,
|
|
934
|
+
success: false,
|
|
935
|
+
error: {
|
|
936
|
+
code: "E001" /* CONNECTION_FAILED */,
|
|
937
|
+
name: "CONNECTION_FAILED",
|
|
938
|
+
message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
ws.send(JSON.stringify(errorResponse));
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* 处理节点导航请求
|
|
947
|
+
*/
|
|
948
|
+
handleNavigateToNode(ws, message) {
|
|
949
|
+
const params = message.params;
|
|
950
|
+
const requestId = message.id || "";
|
|
951
|
+
if (!params?.pageUrl || !params?.nodeId) {
|
|
952
|
+
const errorResponse = {
|
|
953
|
+
id: requestId,
|
|
954
|
+
type: "error" /* ERROR */,
|
|
955
|
+
success: false,
|
|
956
|
+
error: {
|
|
957
|
+
code: "E011" /* INVALID_PARAMS */,
|
|
958
|
+
name: "INVALID_PARAMS",
|
|
959
|
+
message: "\u7F3A\u5C11 pageUrl \u6216 nodeId \u53C2\u6570"
|
|
960
|
+
}
|
|
961
|
+
};
|
|
962
|
+
ws.send(JSON.stringify(errorResponse));
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const targetIndex = params.extensionIndex || 1;
|
|
966
|
+
const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
|
|
967
|
+
if (!targetExtension) {
|
|
968
|
+
const errorResponse = {
|
|
969
|
+
id: requestId,
|
|
970
|
+
type: "error" /* ERROR */,
|
|
971
|
+
success: false,
|
|
972
|
+
error: {
|
|
973
|
+
code: "E018" /* NO_EXTENSION_CONNECTED */,
|
|
974
|
+
name: "NO_EXTENSION_CONNECTED",
|
|
975
|
+
message: targetIndex === 1 ? "\u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin" : `\u672A\u627E\u5230\u5E8F\u53F7\u4E3A #${targetIndex} \u7684\u6269\u5C55\u5B9E\u4F8B`
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
ws.send(JSON.stringify(errorResponse));
|
|
979
|
+
this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const forwardMessage = {
|
|
983
|
+
id: requestId,
|
|
984
|
+
type: "navigate_to_node" /* NAVIGATE_TO_NODE */,
|
|
985
|
+
params: {
|
|
986
|
+
pageUrl: params.pageUrl,
|
|
987
|
+
nodeId: params.nodeId
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
this.requestHandler.registerPendingRequest(requestId, ws, () => {
|
|
991
|
+
try {
|
|
992
|
+
targetExtension.send(JSON.stringify(forwardMessage));
|
|
993
|
+
this.logger.info(`\u8F6C\u53D1 NAVIGATE_TO_NODE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.pageUrl} -> ${params.nodeId}`);
|
|
994
|
+
} catch (error) {
|
|
995
|
+
this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
|
|
996
|
+
const errorResponse = {
|
|
997
|
+
id: requestId,
|
|
998
|
+
type: "error" /* ERROR */,
|
|
999
|
+
success: false,
|
|
1000
|
+
error: {
|
|
1001
|
+
code: "E001" /* CONNECTION_FAILED */,
|
|
1002
|
+
name: "CONNECTION_FAILED",
|
|
1003
|
+
message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
1006
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1007
|
+
}
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
751
1010
|
/**
|
|
752
1011
|
* 停止服务器
|
|
753
1012
|
*/
|