@hangox/mg-cli 1.0.7 → 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 +518 -35
- 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-DUQN5gSR.d.ts → index-cEKly9mt.d.ts} +98 -6
- package/dist/index.d.ts +53 -4
- package/dist/index.js +527 -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/daemon-runner.js
CHANGED
|
@@ -122,6 +122,7 @@ var ErrorNames = {
|
|
|
122
122
|
["E015" /* SERVER_START_FAILED */]: "SERVER_START_FAILED",
|
|
123
123
|
["E016" /* SERVER_ALREADY_RUNNING */]: "SERVER_ALREADY_RUNNING",
|
|
124
124
|
["E017" /* CONNECTION_LOST */]: "CONNECTION_LOST",
|
|
125
|
+
["E018" /* NO_EXTENSION_CONNECTED */]: "NO_EXTENSION_CONNECTED",
|
|
125
126
|
["E099" /* UNKNOWN_ERROR */]: "UNKNOWN_ERROR"
|
|
126
127
|
};
|
|
127
128
|
var ErrorMessages = {
|
|
@@ -142,6 +143,7 @@ var ErrorMessages = {
|
|
|
142
143
|
["E015" /* SERVER_START_FAILED */]: "\u81EA\u52A8\u542F\u52A8 Server \u5931\u8D25",
|
|
143
144
|
["E016" /* SERVER_ALREADY_RUNNING */]: "Server \u5DF2\u5728\u8FD0\u884C\u4E2D",
|
|
144
145
|
["E017" /* CONNECTION_LOST */]: "\u8FDE\u63A5\u65AD\u5F00",
|
|
146
|
+
["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",
|
|
145
147
|
["E099" /* UNKNOWN_ERROR */]: "\u672A\u77E5\u9519\u8BEF"
|
|
146
148
|
};
|
|
147
149
|
var MGError = class extends Error {
|
|
@@ -255,6 +257,12 @@ var ConnectionManager = class {
|
|
|
255
257
|
providers = /* @__PURE__ */ new Map();
|
|
256
258
|
/** Consumer 连接 */
|
|
257
259
|
consumers = /* @__PURE__ */ new Map();
|
|
260
|
+
/** Chrome 扩展连接(按扩展 ID 索引) */
|
|
261
|
+
chromeExtensions = /* @__PURE__ */ new Map();
|
|
262
|
+
/** 扩展序号映射(扩展 ID → 序号) */
|
|
263
|
+
extensionIndexMap = /* @__PURE__ */ new Map();
|
|
264
|
+
/** 下一个可用的扩展序号 */
|
|
265
|
+
nextExtensionIndex = 1;
|
|
258
266
|
/** 所有连接(按 ID 索引) */
|
|
259
267
|
allConnections = /* @__PURE__ */ new Map();
|
|
260
268
|
/** 心跳检查定时器 */
|
|
@@ -349,6 +357,16 @@ var ConnectionManager = class {
|
|
|
349
357
|
} else if (connectionInfo.type === "consumer" /* CONSUMER */) {
|
|
350
358
|
this.consumers.delete(connectionId);
|
|
351
359
|
this.logger.info(`Consumer \u65AD\u5F00: ${connectionId}`);
|
|
360
|
+
} else if (connectionInfo.type === "chrome_extension" /* CHROME_EXTENSION */) {
|
|
361
|
+
for (const [extensionId, extWs] of this.chromeExtensions) {
|
|
362
|
+
if (extWs.connectionId === connectionId) {
|
|
363
|
+
const index = this.extensionIndexMap.get(extensionId);
|
|
364
|
+
this.chromeExtensions.delete(extensionId);
|
|
365
|
+
this.extensionIndexMap.delete(extensionId);
|
|
366
|
+
this.logger.info(`Chrome \u6269\u5C55\u65AD\u5F00: ${extensionId} (\u5E8F\u53F7: #${index})`);
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
352
370
|
}
|
|
353
371
|
}
|
|
354
372
|
/**
|
|
@@ -402,6 +420,7 @@ var ConnectionManager = class {
|
|
|
402
420
|
return {
|
|
403
421
|
providers: providerCount,
|
|
404
422
|
consumers: this.consumers.size,
|
|
423
|
+
extensions: this.chromeExtensions.size,
|
|
405
424
|
total: this.allConnections.size
|
|
406
425
|
};
|
|
407
426
|
}
|
|
@@ -411,6 +430,48 @@ var ConnectionManager = class {
|
|
|
411
430
|
getConnectedPageUrls() {
|
|
412
431
|
return Array.from(this.providers.keys());
|
|
413
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* 添加 Chrome 扩展连接
|
|
435
|
+
*/
|
|
436
|
+
addChromeExtension(ws, extensionId) {
|
|
437
|
+
const managedWs = this.addConnection(ws, "chrome_extension" /* CHROME_EXTENSION */);
|
|
438
|
+
const index = this.nextExtensionIndex++;
|
|
439
|
+
this.extensionIndexMap.set(extensionId, index);
|
|
440
|
+
this.chromeExtensions.set(extensionId, managedWs);
|
|
441
|
+
this.logger.info(`Chrome \u6269\u5C55\u8FDE\u63A5: ${extensionId} (\u5206\u914D\u5E8F\u53F7: #${index})`);
|
|
442
|
+
return managedWs;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* 根据序号查找扩展
|
|
446
|
+
*/
|
|
447
|
+
findExtensionByIndex(index) {
|
|
448
|
+
for (const [extensionId, extIndex] of this.extensionIndexMap) {
|
|
449
|
+
if (extIndex === index) {
|
|
450
|
+
return this.chromeExtensions.get(extensionId);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return void 0;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* 获取第一个扩展
|
|
457
|
+
*/
|
|
458
|
+
getFirstExtension() {
|
|
459
|
+
return this.chromeExtensions.values().next().value;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* 获取所有扩展信息
|
|
463
|
+
*/
|
|
464
|
+
getAllExtensions() {
|
|
465
|
+
const result = [];
|
|
466
|
+
for (const [extensionId, ws] of this.chromeExtensions) {
|
|
467
|
+
const index = this.extensionIndexMap.get(extensionId);
|
|
468
|
+
if (index !== void 0) {
|
|
469
|
+
result.push({ index, extensionId, ws });
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
result.sort((a, b) => a.index - b.index);
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
414
475
|
/**
|
|
415
476
|
* 关闭所有连接
|
|
416
477
|
*/
|
|
@@ -422,6 +483,8 @@ var ConnectionManager = class {
|
|
|
422
483
|
}
|
|
423
484
|
this.providers.clear();
|
|
424
485
|
this.consumers.clear();
|
|
486
|
+
this.chromeExtensions.clear();
|
|
487
|
+
this.extensionIndexMap.clear();
|
|
425
488
|
this.allConnections.clear();
|
|
426
489
|
}
|
|
427
490
|
};
|
|
@@ -539,6 +602,24 @@ var RequestHandler = class {
|
|
|
539
602
|
this.logger.error(`\u53D1\u9001\u9519\u8BEF\u54CD\u5E94\u5931\u8D25: ${requestId}`, err);
|
|
540
603
|
}
|
|
541
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* 注册待处理请求(供外部使用,如 OPEN_PAGE)
|
|
607
|
+
* @param requestId 请求 ID
|
|
608
|
+
* @param consumer 发起请求的 Consumer
|
|
609
|
+
* @param sendCallback 发送请求的回调函数
|
|
610
|
+
*/
|
|
611
|
+
registerPendingRequest(requestId, consumer, sendCallback) {
|
|
612
|
+
const timer = setTimeout(() => {
|
|
613
|
+
this.handleTimeout(requestId);
|
|
614
|
+
}, REQUEST_TIMEOUT);
|
|
615
|
+
this.pendingRequests.set(requestId, {
|
|
616
|
+
id: requestId,
|
|
617
|
+
consumer,
|
|
618
|
+
timer,
|
|
619
|
+
timestamp: Date.now()
|
|
620
|
+
});
|
|
621
|
+
sendCallback();
|
|
622
|
+
}
|
|
542
623
|
/**
|
|
543
624
|
* 清理特定连接的所有待处理请求
|
|
544
625
|
*/
|
|
@@ -711,12 +792,22 @@ var MGServer = class {
|
|
|
711
792
|
*/
|
|
712
793
|
handleRegister(ws, message) {
|
|
713
794
|
const { connectionType, pageUrl, pageId } = message.data;
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
795
|
+
const extensionId = message.data.extensionId;
|
|
796
|
+
let managedWs;
|
|
797
|
+
let extensionIndex;
|
|
798
|
+
if (connectionType === "chrome_extension" /* CHROME_EXTENSION */ && extensionId) {
|
|
799
|
+
managedWs = this.connectionManager.addChromeExtension(ws, extensionId);
|
|
800
|
+
const exts = this.connectionManager.getAllExtensions();
|
|
801
|
+
const ext = exts.find((e) => e.extensionId === extensionId);
|
|
802
|
+
extensionIndex = ext?.index;
|
|
803
|
+
} else {
|
|
804
|
+
managedWs = this.connectionManager.addConnection(
|
|
805
|
+
ws,
|
|
806
|
+
connectionType,
|
|
807
|
+
pageUrl,
|
|
808
|
+
pageId
|
|
809
|
+
);
|
|
810
|
+
}
|
|
720
811
|
const ack = {
|
|
721
812
|
id: message.id || "",
|
|
722
813
|
type: "register_ack" /* REGISTER_ACK */,
|
|
@@ -724,7 +815,8 @@ var MGServer = class {
|
|
|
724
815
|
data: {
|
|
725
816
|
connectionId: managedWs.connectionId,
|
|
726
817
|
pageUrl,
|
|
727
|
-
serverVersion: getVersion()
|
|
818
|
+
serverVersion: getVersion(),
|
|
819
|
+
...extensionIndex !== void 0 && { extensionIndex }
|
|
728
820
|
}
|
|
729
821
|
};
|
|
730
822
|
ws.send(JSON.stringify(ack));
|
|
@@ -741,6 +833,15 @@ var MGServer = class {
|
|
|
741
833
|
case "get_server_status" /* GET_SERVER_STATUS */:
|
|
742
834
|
this.handleGetServerStatus(ws, message);
|
|
743
835
|
break;
|
|
836
|
+
case "list_extensions" /* LIST_EXTENSIONS */:
|
|
837
|
+
this.handleListExtensions(ws, message);
|
|
838
|
+
break;
|
|
839
|
+
case "open_page" /* OPEN_PAGE */:
|
|
840
|
+
this.handleOpenPage(ws, message);
|
|
841
|
+
break;
|
|
842
|
+
case "navigate_to_node" /* NAVIGATE_TO_NODE */:
|
|
843
|
+
this.handleNavigateToNode(ws, message);
|
|
844
|
+
break;
|
|
744
845
|
case "response" /* RESPONSE */:
|
|
745
846
|
case "error" /* ERROR */:
|
|
746
847
|
this.requestHandler.handleResponse(message);
|
|
@@ -773,6 +874,13 @@ var MGServer = class {
|
|
|
773
874
|
connectedAt: info.connectedAt.toISOString(),
|
|
774
875
|
lastActiveAt: info.lastActiveAt.toISOString()
|
|
775
876
|
}));
|
|
877
|
+
const extensions = this.connectionManager.getAllExtensions();
|
|
878
|
+
const connectedExtensions = extensions.map((ext) => ({
|
|
879
|
+
index: ext.index,
|
|
880
|
+
extensionId: ext.extensionId,
|
|
881
|
+
connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
|
|
882
|
+
lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
|
|
883
|
+
}));
|
|
776
884
|
const uptimeMs = this.startedAt ? Date.now() - this.startedAt.getTime() : 0;
|
|
777
885
|
const statusData = {
|
|
778
886
|
running: this.isRunning,
|
|
@@ -782,7 +890,8 @@ var MGServer = class {
|
|
|
782
890
|
uptime: formatDuration(uptimeMs),
|
|
783
891
|
version: getVersion(),
|
|
784
892
|
stats,
|
|
785
|
-
connectedPages
|
|
893
|
+
connectedPages,
|
|
894
|
+
connectedExtensions
|
|
786
895
|
};
|
|
787
896
|
const response = {
|
|
788
897
|
id: message.id || "",
|
|
@@ -793,6 +902,156 @@ var MGServer = class {
|
|
|
793
902
|
ws.send(JSON.stringify(response));
|
|
794
903
|
this.logger.info("\u8FD4\u56DE Server \u72B6\u6001\u4FE1\u606F");
|
|
795
904
|
}
|
|
905
|
+
/**
|
|
906
|
+
* 处理扩展列表查询
|
|
907
|
+
*/
|
|
908
|
+
handleListExtensions(ws, message) {
|
|
909
|
+
const extensions = this.connectionManager.getAllExtensions();
|
|
910
|
+
const extensionList = extensions.map((ext) => ({
|
|
911
|
+
index: ext.index,
|
|
912
|
+
extensionId: ext.extensionId,
|
|
913
|
+
connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
|
|
914
|
+
lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
|
|
915
|
+
}));
|
|
916
|
+
const response = {
|
|
917
|
+
id: message.id || "",
|
|
918
|
+
type: "response" /* RESPONSE */,
|
|
919
|
+
success: true,
|
|
920
|
+
data: {
|
|
921
|
+
extensions: extensionList,
|
|
922
|
+
totalCount: extensionList.length
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
ws.send(JSON.stringify(response));
|
|
926
|
+
this.logger.info(`\u8FD4\u56DE\u6269\u5C55\u5217\u8868\uFF0C\u5171 ${extensionList.length} \u4E2A\u6269\u5C55`);
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* 处理打开页面请求
|
|
930
|
+
*/
|
|
931
|
+
handleOpenPage(ws, message) {
|
|
932
|
+
const params = message.params;
|
|
933
|
+
const requestId = message.id || "";
|
|
934
|
+
if (!params?.url) {
|
|
935
|
+
const errorResponse = {
|
|
936
|
+
id: requestId,
|
|
937
|
+
type: "error" /* ERROR */,
|
|
938
|
+
success: false,
|
|
939
|
+
error: {
|
|
940
|
+
code: "E011" /* INVALID_PARAMS */,
|
|
941
|
+
name: "INVALID_PARAMS",
|
|
942
|
+
message: "\u7F3A\u5C11 url \u53C2\u6570"
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
ws.send(JSON.stringify(errorResponse));
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const targetIndex = params.extensionIndex || 1;
|
|
949
|
+
const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
|
|
950
|
+
if (!targetExtension) {
|
|
951
|
+
const errorResponse = {
|
|
952
|
+
id: requestId,
|
|
953
|
+
type: "error" /* ERROR */,
|
|
954
|
+
success: false,
|
|
955
|
+
error: {
|
|
956
|
+
code: "E018" /* NO_EXTENSION_CONNECTED */,
|
|
957
|
+
name: "NO_EXTENSION_CONNECTED",
|
|
958
|
+
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`
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
ws.send(JSON.stringify(errorResponse));
|
|
962
|
+
this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const forwardMessage = {
|
|
966
|
+
id: requestId,
|
|
967
|
+
type: "open_page" /* OPEN_PAGE */,
|
|
968
|
+
params: { url: params.url }
|
|
969
|
+
};
|
|
970
|
+
this.requestHandler.registerPendingRequest(requestId, ws, () => {
|
|
971
|
+
try {
|
|
972
|
+
targetExtension.send(JSON.stringify(forwardMessage));
|
|
973
|
+
this.logger.info(`\u8F6C\u53D1 OPEN_PAGE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.url}`);
|
|
974
|
+
} catch (error) {
|
|
975
|
+
this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
|
|
976
|
+
const errorResponse = {
|
|
977
|
+
id: requestId,
|
|
978
|
+
type: "error" /* ERROR */,
|
|
979
|
+
success: false,
|
|
980
|
+
error: {
|
|
981
|
+
code: "E001" /* CONNECTION_FAILED */,
|
|
982
|
+
name: "CONNECTION_FAILED",
|
|
983
|
+
message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
ws.send(JSON.stringify(errorResponse));
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* 处理节点导航请求
|
|
992
|
+
*/
|
|
993
|
+
handleNavigateToNode(ws, message) {
|
|
994
|
+
const params = message.params;
|
|
995
|
+
const requestId = message.id || "";
|
|
996
|
+
if (!params?.pageUrl || !params?.nodeId) {
|
|
997
|
+
const errorResponse = {
|
|
998
|
+
id: requestId,
|
|
999
|
+
type: "error" /* ERROR */,
|
|
1000
|
+
success: false,
|
|
1001
|
+
error: {
|
|
1002
|
+
code: "E011" /* INVALID_PARAMS */,
|
|
1003
|
+
name: "INVALID_PARAMS",
|
|
1004
|
+
message: "\u7F3A\u5C11 pageUrl \u6216 nodeId \u53C2\u6570"
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
const targetIndex = params.extensionIndex || 1;
|
|
1011
|
+
const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
|
|
1012
|
+
if (!targetExtension) {
|
|
1013
|
+
const errorResponse = {
|
|
1014
|
+
id: requestId,
|
|
1015
|
+
type: "error" /* ERROR */,
|
|
1016
|
+
success: false,
|
|
1017
|
+
error: {
|
|
1018
|
+
code: "E018" /* NO_EXTENSION_CONNECTED */,
|
|
1019
|
+
name: "NO_EXTENSION_CONNECTED",
|
|
1020
|
+
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`
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1023
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1024
|
+
this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const forwardMessage = {
|
|
1028
|
+
id: requestId,
|
|
1029
|
+
type: "navigate_to_node" /* NAVIGATE_TO_NODE */,
|
|
1030
|
+
params: {
|
|
1031
|
+
pageUrl: params.pageUrl,
|
|
1032
|
+
nodeId: params.nodeId
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
this.requestHandler.registerPendingRequest(requestId, ws, () => {
|
|
1036
|
+
try {
|
|
1037
|
+
targetExtension.send(JSON.stringify(forwardMessage));
|
|
1038
|
+
this.logger.info(`\u8F6C\u53D1 NAVIGATE_TO_NODE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.pageUrl} -> ${params.nodeId}`);
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
|
|
1041
|
+
const errorResponse = {
|
|
1042
|
+
id: requestId,
|
|
1043
|
+
type: "error" /* ERROR */,
|
|
1044
|
+
success: false,
|
|
1045
|
+
error: {
|
|
1046
|
+
code: "E001" /* CONNECTION_FAILED */,
|
|
1047
|
+
name: "CONNECTION_FAILED",
|
|
1048
|
+
message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
796
1055
|
/**
|
|
797
1056
|
* 停止服务器
|
|
798
1057
|
*/
|