@hangox/mg-cli 1.0.8 → 1.1.0
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 +1079 -127
- 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/cli.js
CHANGED
|
@@ -1,7 +1,139 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command13 } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/cli/version-check.ts
|
|
7
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
import { join as join2 } from "path";
|
|
10
|
+
import { execSync } from "child_process";
|
|
11
|
+
|
|
12
|
+
// src/shared/version.ts
|
|
13
|
+
import { readFileSync, existsSync } from "fs";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
import { dirname, join } from "path";
|
|
16
|
+
var cachedVersion = null;
|
|
17
|
+
function getVersion() {
|
|
18
|
+
if (cachedVersion !== null) {
|
|
19
|
+
return cachedVersion;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
23
|
+
const currentDir = dirname(currentFile);
|
|
24
|
+
const packageJsonPaths = [
|
|
25
|
+
join(currentDir, "..", "package.json"),
|
|
26
|
+
// dist/xxx.js -> ../package.json
|
|
27
|
+
join(currentDir, "..", "..", "package.json")
|
|
28
|
+
// src/shared/version.ts -> ../../package.json
|
|
29
|
+
];
|
|
30
|
+
for (const packageJsonPath of packageJsonPaths) {
|
|
31
|
+
if (existsSync(packageJsonPath)) {
|
|
32
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
33
|
+
if (packageJson.name === "@hangox/mg-cli") {
|
|
34
|
+
cachedVersion = packageJson.version || "0.0.0";
|
|
35
|
+
return cachedVersion;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
cachedVersion = "0.0.0";
|
|
40
|
+
return cachedVersion;
|
|
41
|
+
} catch {
|
|
42
|
+
cachedVersion = "0.0.0";
|
|
43
|
+
return cachedVersion;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
var DEV_VERSION = "9.9.9";
|
|
47
|
+
function isVersionMatch(version1, version2) {
|
|
48
|
+
if (version1 === DEV_VERSION || version2 === DEV_VERSION) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return version1 === version2;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/cli/version-check.ts
|
|
55
|
+
var CONFIG_DIR = join2(homedir(), ".config", "mg-cli");
|
|
56
|
+
var CHECK_FILE = join2(CONFIG_DIR, "last-version-check");
|
|
57
|
+
var CHECK_INTERVAL = 24 * 60 * 60 * 1e3;
|
|
58
|
+
function readCheckData() {
|
|
59
|
+
try {
|
|
60
|
+
if (!existsSync2(CHECK_FILE)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const content = readFileSync2(CHECK_FILE, "utf-8");
|
|
64
|
+
return JSON.parse(content);
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function writeCheckData(data) {
|
|
70
|
+
try {
|
|
71
|
+
if (!existsSync2(CONFIG_DIR)) {
|
|
72
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
writeFileSync(CHECK_FILE, JSON.stringify(data), "utf-8");
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function getRemoteVersion() {
|
|
79
|
+
try {
|
|
80
|
+
const result = execSync("npm view @hangox/mg-cli version", {
|
|
81
|
+
encoding: "utf-8",
|
|
82
|
+
timeout: 5e3,
|
|
83
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
84
|
+
});
|
|
85
|
+
return result.trim();
|
|
86
|
+
} catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function isNewerVersion(local, remote) {
|
|
91
|
+
const localParts = local.split(".").map(Number);
|
|
92
|
+
const remoteParts = remote.split(".").map(Number);
|
|
93
|
+
for (let i = 0; i < 3; i++) {
|
|
94
|
+
const l = localParts[i] || 0;
|
|
95
|
+
const r = remoteParts[i] || 0;
|
|
96
|
+
if (r > l) return true;
|
|
97
|
+
if (r < l) return false;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
function checkForUpdates() {
|
|
102
|
+
try {
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
const checkData = readCheckData();
|
|
105
|
+
if (checkData && now - checkData.timestamp < CHECK_INTERVAL) {
|
|
106
|
+
if (checkData.remoteVersion && isNewerVersion(getVersion(), checkData.remoteVersion)) {
|
|
107
|
+
printUpdateNotice(checkData.remoteVersion);
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const remoteVersion = getRemoteVersion();
|
|
112
|
+
if (remoteVersion) {
|
|
113
|
+
writeCheckData({
|
|
114
|
+
timestamp: now,
|
|
115
|
+
remoteVersion
|
|
116
|
+
});
|
|
117
|
+
if (isNewerVersion(getVersion(), remoteVersion)) {
|
|
118
|
+
printUpdateNotice(remoteVersion);
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
writeCheckData({
|
|
122
|
+
timestamp: now
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function printUpdateNotice(remoteVersion) {
|
|
129
|
+
const localVersion = getVersion();
|
|
130
|
+
console.log("");
|
|
131
|
+
console.log(`\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510`);
|
|
132
|
+
console.log(`\u2502 \u53D1\u73B0\u65B0\u7248\u672C ${remoteVersion}\uFF08\u5F53\u524D ${localVersion}\uFF09`);
|
|
133
|
+
console.log(`\u2502 \u8FD0\u884C npm install -g @hangox/mg-cli \u66F4\u65B0`);
|
|
134
|
+
console.log(`\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518`);
|
|
135
|
+
console.log("");
|
|
136
|
+
}
|
|
5
137
|
|
|
6
138
|
// src/cli/commands/server.ts
|
|
7
139
|
import { Command } from "commander";
|
|
@@ -9,15 +141,15 @@ import { Command } from "commander";
|
|
|
9
141
|
// src/server/daemon.ts
|
|
10
142
|
import { spawn } from "child_process";
|
|
11
143
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12
|
-
import { dirname as dirname4, join as
|
|
144
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
13
145
|
|
|
14
146
|
// src/shared/utils.ts
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
16
|
-
import { dirname, resolve, isAbsolute } from "path";
|
|
147
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync } from "fs";
|
|
148
|
+
import { dirname as dirname2, resolve, isAbsolute } from "path";
|
|
17
149
|
|
|
18
150
|
// src/shared/constants.ts
|
|
19
|
-
import { homedir } from "os";
|
|
20
|
-
import { join } from "path";
|
|
151
|
+
import { homedir as homedir2 } from "os";
|
|
152
|
+
import { join as join3 } from "path";
|
|
21
153
|
var IS_DEV_MODE = process.env.MG_DEV_MODE === "true";
|
|
22
154
|
var PROD_DEFAULT_PORT = 9527;
|
|
23
155
|
var PROD_PORT_RANGE_START = 9527;
|
|
@@ -29,10 +161,10 @@ var DEFAULT_PORT = IS_DEV_MODE ? DEV_DEFAULT_PORT : PROD_DEFAULT_PORT;
|
|
|
29
161
|
var PORT_RANGE_START = IS_DEV_MODE ? DEV_PORT_RANGE_START : PROD_PORT_RANGE_START;
|
|
30
162
|
var PORT_RANGE_END = IS_DEV_MODE ? DEV_PORT_RANGE_END : PROD_PORT_RANGE_END;
|
|
31
163
|
var PORT_SCAN_TIMEOUT = 500;
|
|
32
|
-
var
|
|
33
|
-
var SERVER_INFO_FILE =
|
|
34
|
-
var LOG_DIR =
|
|
35
|
-
var SERVER_LOG_FILE =
|
|
164
|
+
var CONFIG_DIR2 = join3(homedir2(), ".mg-plugin");
|
|
165
|
+
var SERVER_INFO_FILE = join3(CONFIG_DIR2, "server.json");
|
|
166
|
+
var LOG_DIR = join3(CONFIG_DIR2, "logs");
|
|
167
|
+
var SERVER_LOG_FILE = join3(LOG_DIR, "server.log");
|
|
36
168
|
var HEARTBEAT_INTERVAL = 3e4;
|
|
37
169
|
var HEARTBEAT_TIMEOUT = 9e4;
|
|
38
170
|
var REQUEST_TIMEOUT = 3e4;
|
|
@@ -42,20 +174,20 @@ var MAX_RETRY_COUNT = 3;
|
|
|
42
174
|
|
|
43
175
|
// src/shared/utils.ts
|
|
44
176
|
function ensureDir(dir) {
|
|
45
|
-
if (!
|
|
46
|
-
|
|
177
|
+
if (!existsSync3(dir)) {
|
|
178
|
+
mkdirSync2(dir, { recursive: true });
|
|
47
179
|
}
|
|
48
180
|
}
|
|
49
181
|
function ensureConfigDir() {
|
|
50
|
-
ensureDir(
|
|
182
|
+
ensureDir(CONFIG_DIR2);
|
|
51
183
|
ensureDir(LOG_DIR);
|
|
52
184
|
}
|
|
53
185
|
function readServerInfo() {
|
|
54
186
|
try {
|
|
55
|
-
if (!
|
|
187
|
+
if (!existsSync3(SERVER_INFO_FILE)) {
|
|
56
188
|
return null;
|
|
57
189
|
}
|
|
58
|
-
const content =
|
|
190
|
+
const content = readFileSync3(SERVER_INFO_FILE, "utf-8");
|
|
59
191
|
return JSON.parse(content);
|
|
60
192
|
} catch {
|
|
61
193
|
return null;
|
|
@@ -63,11 +195,11 @@ function readServerInfo() {
|
|
|
63
195
|
}
|
|
64
196
|
function writeServerInfo(info) {
|
|
65
197
|
ensureConfigDir();
|
|
66
|
-
|
|
198
|
+
writeFileSync2(SERVER_INFO_FILE, JSON.stringify(info, null, 2), "utf-8");
|
|
67
199
|
}
|
|
68
200
|
function deleteServerInfo() {
|
|
69
201
|
try {
|
|
70
|
-
if (
|
|
202
|
+
if (existsSync3(SERVER_INFO_FILE)) {
|
|
71
203
|
unlinkSync(SERVER_INFO_FILE);
|
|
72
204
|
}
|
|
73
205
|
} catch {
|
|
@@ -340,6 +472,12 @@ function extractSpaceInfo(node) {
|
|
|
340
472
|
width: roundToOneDecimal(typeof node.width === "number" ? node.width : 0),
|
|
341
473
|
height: roundToOneDecimal(typeof node.height === "number" ? node.height : 0)
|
|
342
474
|
};
|
|
475
|
+
if (typeof node.absoluteX === "number") {
|
|
476
|
+
result.absoluteX = roundToOneDecimal(node.absoluteX);
|
|
477
|
+
}
|
|
478
|
+
if (typeof node.absoluteY === "number") {
|
|
479
|
+
result.absoluteY = roundToOneDecimal(node.absoluteY);
|
|
480
|
+
}
|
|
343
481
|
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
344
482
|
result.children = node.children.map((child) => extractSpaceInfo(child));
|
|
345
483
|
}
|
|
@@ -365,6 +503,7 @@ var ErrorNames = {
|
|
|
365
503
|
["E015" /* SERVER_START_FAILED */]: "SERVER_START_FAILED",
|
|
366
504
|
["E016" /* SERVER_ALREADY_RUNNING */]: "SERVER_ALREADY_RUNNING",
|
|
367
505
|
["E017" /* CONNECTION_LOST */]: "CONNECTION_LOST",
|
|
506
|
+
["E018" /* NO_EXTENSION_CONNECTED */]: "NO_EXTENSION_CONNECTED",
|
|
368
507
|
["E099" /* UNKNOWN_ERROR */]: "UNKNOWN_ERROR"
|
|
369
508
|
};
|
|
370
509
|
var ErrorMessages = {
|
|
@@ -385,6 +524,7 @@ var ErrorMessages = {
|
|
|
385
524
|
["E015" /* SERVER_START_FAILED */]: "\u81EA\u52A8\u542F\u52A8 Server \u5931\u8D25",
|
|
386
525
|
["E016" /* SERVER_ALREADY_RUNNING */]: "Server \u5DF2\u5728\u8FD0\u884C\u4E2D",
|
|
387
526
|
["E017" /* CONNECTION_LOST */]: "\u8FDE\u63A5\u65AD\u5F00",
|
|
527
|
+
["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",
|
|
388
528
|
["E099" /* UNKNOWN_ERROR */]: "\u672A\u77E5\u9519\u8BEF"
|
|
389
529
|
};
|
|
390
530
|
var MGError = class extends Error {
|
|
@@ -420,8 +560,8 @@ var MGError = class extends Error {
|
|
|
420
560
|
import { WebSocketServer } from "ws";
|
|
421
561
|
|
|
422
562
|
// src/server/logger.ts
|
|
423
|
-
import { appendFileSync, existsSync as
|
|
424
|
-
import { dirname as
|
|
563
|
+
import { appendFileSync, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
564
|
+
import { dirname as dirname3 } from "path";
|
|
425
565
|
var levelPriority = {
|
|
426
566
|
["DEBUG" /* DEBUG */]: 0,
|
|
427
567
|
["INFO" /* INFO */]: 1,
|
|
@@ -438,9 +578,9 @@ var Logger = class {
|
|
|
438
578
|
minLevel: options.minLevel ?? "INFO" /* INFO */
|
|
439
579
|
};
|
|
440
580
|
if (this.options.file) {
|
|
441
|
-
const dir =
|
|
442
|
-
if (!
|
|
443
|
-
|
|
581
|
+
const dir = dirname3(this.options.filePath);
|
|
582
|
+
if (!existsSync4(dir)) {
|
|
583
|
+
mkdirSync3(dir, { recursive: true });
|
|
444
584
|
}
|
|
445
585
|
}
|
|
446
586
|
}
|
|
@@ -498,6 +638,12 @@ var ConnectionManager = class {
|
|
|
498
638
|
providers = /* @__PURE__ */ new Map();
|
|
499
639
|
/** Consumer 连接 */
|
|
500
640
|
consumers = /* @__PURE__ */ new Map();
|
|
641
|
+
/** Chrome 扩展连接(按扩展 ID 索引) */
|
|
642
|
+
chromeExtensions = /* @__PURE__ */ new Map();
|
|
643
|
+
/** 扩展序号映射(扩展 ID → 序号) */
|
|
644
|
+
extensionIndexMap = /* @__PURE__ */ new Map();
|
|
645
|
+
/** 下一个可用的扩展序号 */
|
|
646
|
+
nextExtensionIndex = 1;
|
|
501
647
|
/** 所有连接(按 ID 索引) */
|
|
502
648
|
allConnections = /* @__PURE__ */ new Map();
|
|
503
649
|
/** 心跳检查定时器 */
|
|
@@ -592,6 +738,16 @@ var ConnectionManager = class {
|
|
|
592
738
|
} else if (connectionInfo.type === "consumer" /* CONSUMER */) {
|
|
593
739
|
this.consumers.delete(connectionId);
|
|
594
740
|
this.logger.info(`Consumer \u65AD\u5F00: ${connectionId}`);
|
|
741
|
+
} else if (connectionInfo.type === "chrome_extension" /* CHROME_EXTENSION */) {
|
|
742
|
+
for (const [extensionId, extWs] of this.chromeExtensions) {
|
|
743
|
+
if (extWs.connectionId === connectionId) {
|
|
744
|
+
const index = this.extensionIndexMap.get(extensionId);
|
|
745
|
+
this.chromeExtensions.delete(extensionId);
|
|
746
|
+
this.extensionIndexMap.delete(extensionId);
|
|
747
|
+
this.logger.info(`Chrome \u6269\u5C55\u65AD\u5F00: ${extensionId} (\u5E8F\u53F7: #${index})`);
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
595
751
|
}
|
|
596
752
|
}
|
|
597
753
|
/**
|
|
@@ -645,6 +801,7 @@ var ConnectionManager = class {
|
|
|
645
801
|
return {
|
|
646
802
|
providers: providerCount,
|
|
647
803
|
consumers: this.consumers.size,
|
|
804
|
+
extensions: this.chromeExtensions.size,
|
|
648
805
|
total: this.allConnections.size
|
|
649
806
|
};
|
|
650
807
|
}
|
|
@@ -654,6 +811,48 @@ var ConnectionManager = class {
|
|
|
654
811
|
getConnectedPageUrls() {
|
|
655
812
|
return Array.from(this.providers.keys());
|
|
656
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* 添加 Chrome 扩展连接
|
|
816
|
+
*/
|
|
817
|
+
addChromeExtension(ws, extensionId) {
|
|
818
|
+
const managedWs = this.addConnection(ws, "chrome_extension" /* CHROME_EXTENSION */);
|
|
819
|
+
const index = this.nextExtensionIndex++;
|
|
820
|
+
this.extensionIndexMap.set(extensionId, index);
|
|
821
|
+
this.chromeExtensions.set(extensionId, managedWs);
|
|
822
|
+
this.logger.info(`Chrome \u6269\u5C55\u8FDE\u63A5: ${extensionId} (\u5206\u914D\u5E8F\u53F7: #${index})`);
|
|
823
|
+
return managedWs;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* 根据序号查找扩展
|
|
827
|
+
*/
|
|
828
|
+
findExtensionByIndex(index) {
|
|
829
|
+
for (const [extensionId, extIndex] of this.extensionIndexMap) {
|
|
830
|
+
if (extIndex === index) {
|
|
831
|
+
return this.chromeExtensions.get(extensionId);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return void 0;
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* 获取第一个扩展
|
|
838
|
+
*/
|
|
839
|
+
getFirstExtension() {
|
|
840
|
+
return this.chromeExtensions.values().next().value;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* 获取所有扩展信息
|
|
844
|
+
*/
|
|
845
|
+
getAllExtensions() {
|
|
846
|
+
const result = [];
|
|
847
|
+
for (const [extensionId, ws] of this.chromeExtensions) {
|
|
848
|
+
const index = this.extensionIndexMap.get(extensionId);
|
|
849
|
+
if (index !== void 0) {
|
|
850
|
+
result.push({ index, extensionId, ws });
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
result.sort((a, b) => a.index - b.index);
|
|
854
|
+
return result;
|
|
855
|
+
}
|
|
657
856
|
/**
|
|
658
857
|
* 关闭所有连接
|
|
659
858
|
*/
|
|
@@ -665,6 +864,8 @@ var ConnectionManager = class {
|
|
|
665
864
|
}
|
|
666
865
|
this.providers.clear();
|
|
667
866
|
this.consumers.clear();
|
|
867
|
+
this.chromeExtensions.clear();
|
|
868
|
+
this.extensionIndexMap.clear();
|
|
668
869
|
this.allConnections.clear();
|
|
669
870
|
}
|
|
670
871
|
};
|
|
@@ -782,6 +983,24 @@ var RequestHandler = class {
|
|
|
782
983
|
this.logger.error(`\u53D1\u9001\u9519\u8BEF\u54CD\u5E94\u5931\u8D25: ${requestId}`, err);
|
|
783
984
|
}
|
|
784
985
|
}
|
|
986
|
+
/**
|
|
987
|
+
* 注册待处理请求(供外部使用,如 OPEN_PAGE)
|
|
988
|
+
* @param requestId 请求 ID
|
|
989
|
+
* @param consumer 发起请求的 Consumer
|
|
990
|
+
* @param sendCallback 发送请求的回调函数
|
|
991
|
+
*/
|
|
992
|
+
registerPendingRequest(requestId, consumer, sendCallback) {
|
|
993
|
+
const timer = setTimeout(() => {
|
|
994
|
+
this.handleTimeout(requestId);
|
|
995
|
+
}, REQUEST_TIMEOUT);
|
|
996
|
+
this.pendingRequests.set(requestId, {
|
|
997
|
+
id: requestId,
|
|
998
|
+
consumer,
|
|
999
|
+
timer,
|
|
1000
|
+
timestamp: Date.now()
|
|
1001
|
+
});
|
|
1002
|
+
sendCallback();
|
|
1003
|
+
}
|
|
785
1004
|
/**
|
|
786
1005
|
* 清理特定连接的所有待处理请求
|
|
787
1006
|
*/
|
|
@@ -802,48 +1021,6 @@ var RequestHandler = class {
|
|
|
802
1021
|
}
|
|
803
1022
|
};
|
|
804
1023
|
|
|
805
|
-
// src/shared/version.ts
|
|
806
|
-
import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
|
|
807
|
-
import { fileURLToPath } from "url";
|
|
808
|
-
import { dirname as dirname3, join as join2 } from "path";
|
|
809
|
-
var cachedVersion = null;
|
|
810
|
-
function getVersion() {
|
|
811
|
-
if (cachedVersion !== null) {
|
|
812
|
-
return cachedVersion;
|
|
813
|
-
}
|
|
814
|
-
try {
|
|
815
|
-
const currentFile = fileURLToPath(import.meta.url);
|
|
816
|
-
const currentDir = dirname3(currentFile);
|
|
817
|
-
const packageJsonPaths = [
|
|
818
|
-
join2(currentDir, "..", "package.json"),
|
|
819
|
-
// dist/xxx.js -> ../package.json
|
|
820
|
-
join2(currentDir, "..", "..", "package.json")
|
|
821
|
-
// src/shared/version.ts -> ../../package.json
|
|
822
|
-
];
|
|
823
|
-
for (const packageJsonPath of packageJsonPaths) {
|
|
824
|
-
if (existsSync3(packageJsonPath)) {
|
|
825
|
-
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
826
|
-
if (packageJson.name === "@hangox/mg-cli") {
|
|
827
|
-
cachedVersion = packageJson.version || "0.0.0";
|
|
828
|
-
return cachedVersion;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
cachedVersion = "0.0.0";
|
|
833
|
-
return cachedVersion;
|
|
834
|
-
} catch {
|
|
835
|
-
cachedVersion = "0.0.0";
|
|
836
|
-
return cachedVersion;
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
var DEV_VERSION = "9.9.9";
|
|
840
|
-
function isVersionMatch(version1, version2) {
|
|
841
|
-
if (version1 === DEV_VERSION || version2 === DEV_VERSION) {
|
|
842
|
-
return true;
|
|
843
|
-
}
|
|
844
|
-
return version1 === version2;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
1024
|
// src/server/websocket-server.ts
|
|
848
1025
|
var MGServer = class {
|
|
849
1026
|
wss = null;
|
|
@@ -867,7 +1044,7 @@ var MGServer = class {
|
|
|
867
1044
|
throw new MGError("E016" /* SERVER_ALREADY_RUNNING */, "Server \u5DF2\u5728\u8FD0\u884C\u4E2D");
|
|
868
1045
|
}
|
|
869
1046
|
const port = await this.findAvailablePort();
|
|
870
|
-
return new Promise((
|
|
1047
|
+
return new Promise((resolve9, reject) => {
|
|
871
1048
|
this.wss = new WebSocketServer({ port });
|
|
872
1049
|
this.wss.on("listening", () => {
|
|
873
1050
|
this.port = port;
|
|
@@ -875,7 +1052,7 @@ var MGServer = class {
|
|
|
875
1052
|
this.startedAt = /* @__PURE__ */ new Date();
|
|
876
1053
|
this.logger.info(`Server \u542F\u52A8\u6210\u529F\uFF0C\u76D1\u542C\u7AEF\u53E3: ${port}`);
|
|
877
1054
|
this.connectionManager.startHeartbeatCheck(HEARTBEAT_INTERVAL);
|
|
878
|
-
|
|
1055
|
+
resolve9(port);
|
|
879
1056
|
});
|
|
880
1057
|
this.wss.on("error", (error) => {
|
|
881
1058
|
this.logger.error("Server \u9519\u8BEF:", error);
|
|
@@ -906,14 +1083,14 @@ var MGServer = class {
|
|
|
906
1083
|
* 检查端口是否可用
|
|
907
1084
|
*/
|
|
908
1085
|
isPortAvailable(port) {
|
|
909
|
-
return new Promise((
|
|
1086
|
+
return new Promise((resolve9) => {
|
|
910
1087
|
const testServer = new WebSocketServer({ port });
|
|
911
1088
|
testServer.on("listening", () => {
|
|
912
1089
|
testServer.close();
|
|
913
|
-
|
|
1090
|
+
resolve9(true);
|
|
914
1091
|
});
|
|
915
1092
|
testServer.on("error", () => {
|
|
916
|
-
|
|
1093
|
+
resolve9(false);
|
|
917
1094
|
});
|
|
918
1095
|
});
|
|
919
1096
|
}
|
|
@@ -961,12 +1138,22 @@ var MGServer = class {
|
|
|
961
1138
|
*/
|
|
962
1139
|
handleRegister(ws, message) {
|
|
963
1140
|
const { connectionType, pageUrl, pageId } = message.data;
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1141
|
+
const extensionId = message.data.extensionId;
|
|
1142
|
+
let managedWs;
|
|
1143
|
+
let extensionIndex;
|
|
1144
|
+
if (connectionType === "chrome_extension" /* CHROME_EXTENSION */ && extensionId) {
|
|
1145
|
+
managedWs = this.connectionManager.addChromeExtension(ws, extensionId);
|
|
1146
|
+
const exts = this.connectionManager.getAllExtensions();
|
|
1147
|
+
const ext = exts.find((e) => e.extensionId === extensionId);
|
|
1148
|
+
extensionIndex = ext?.index;
|
|
1149
|
+
} else {
|
|
1150
|
+
managedWs = this.connectionManager.addConnection(
|
|
1151
|
+
ws,
|
|
1152
|
+
connectionType,
|
|
1153
|
+
pageUrl,
|
|
1154
|
+
pageId
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
970
1157
|
const ack = {
|
|
971
1158
|
id: message.id || "",
|
|
972
1159
|
type: "register_ack" /* REGISTER_ACK */,
|
|
@@ -974,7 +1161,8 @@ var MGServer = class {
|
|
|
974
1161
|
data: {
|
|
975
1162
|
connectionId: managedWs.connectionId,
|
|
976
1163
|
pageUrl,
|
|
977
|
-
serverVersion: getVersion()
|
|
1164
|
+
serverVersion: getVersion(),
|
|
1165
|
+
...extensionIndex !== void 0 && { extensionIndex }
|
|
978
1166
|
}
|
|
979
1167
|
};
|
|
980
1168
|
ws.send(JSON.stringify(ack));
|
|
@@ -991,6 +1179,15 @@ var MGServer = class {
|
|
|
991
1179
|
case "get_server_status" /* GET_SERVER_STATUS */:
|
|
992
1180
|
this.handleGetServerStatus(ws, message);
|
|
993
1181
|
break;
|
|
1182
|
+
case "list_extensions" /* LIST_EXTENSIONS */:
|
|
1183
|
+
this.handleListExtensions(ws, message);
|
|
1184
|
+
break;
|
|
1185
|
+
case "open_page" /* OPEN_PAGE */:
|
|
1186
|
+
this.handleOpenPage(ws, message);
|
|
1187
|
+
break;
|
|
1188
|
+
case "navigate_to_node" /* NAVIGATE_TO_NODE */:
|
|
1189
|
+
this.handleNavigateToNode(ws, message);
|
|
1190
|
+
break;
|
|
994
1191
|
case "response" /* RESPONSE */:
|
|
995
1192
|
case "error" /* ERROR */:
|
|
996
1193
|
this.requestHandler.handleResponse(message);
|
|
@@ -1023,6 +1220,13 @@ var MGServer = class {
|
|
|
1023
1220
|
connectedAt: info.connectedAt.toISOString(),
|
|
1024
1221
|
lastActiveAt: info.lastActiveAt.toISOString()
|
|
1025
1222
|
}));
|
|
1223
|
+
const extensions = this.connectionManager.getAllExtensions();
|
|
1224
|
+
const connectedExtensions = extensions.map((ext) => ({
|
|
1225
|
+
index: ext.index,
|
|
1226
|
+
extensionId: ext.extensionId,
|
|
1227
|
+
connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
|
|
1228
|
+
lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
|
|
1229
|
+
}));
|
|
1026
1230
|
const uptimeMs = this.startedAt ? Date.now() - this.startedAt.getTime() : 0;
|
|
1027
1231
|
const statusData = {
|
|
1028
1232
|
running: this.isRunning,
|
|
@@ -1032,7 +1236,8 @@ var MGServer = class {
|
|
|
1032
1236
|
uptime: formatDuration(uptimeMs),
|
|
1033
1237
|
version: getVersion(),
|
|
1034
1238
|
stats,
|
|
1035
|
-
connectedPages
|
|
1239
|
+
connectedPages,
|
|
1240
|
+
connectedExtensions
|
|
1036
1241
|
};
|
|
1037
1242
|
const response = {
|
|
1038
1243
|
id: message.id || "",
|
|
@@ -1043,6 +1248,156 @@ var MGServer = class {
|
|
|
1043
1248
|
ws.send(JSON.stringify(response));
|
|
1044
1249
|
this.logger.info("\u8FD4\u56DE Server \u72B6\u6001\u4FE1\u606F");
|
|
1045
1250
|
}
|
|
1251
|
+
/**
|
|
1252
|
+
* 处理扩展列表查询
|
|
1253
|
+
*/
|
|
1254
|
+
handleListExtensions(ws, message) {
|
|
1255
|
+
const extensions = this.connectionManager.getAllExtensions();
|
|
1256
|
+
const extensionList = extensions.map((ext) => ({
|
|
1257
|
+
index: ext.index,
|
|
1258
|
+
extensionId: ext.extensionId,
|
|
1259
|
+
connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
|
|
1260
|
+
lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
|
|
1261
|
+
}));
|
|
1262
|
+
const response = {
|
|
1263
|
+
id: message.id || "",
|
|
1264
|
+
type: "response" /* RESPONSE */,
|
|
1265
|
+
success: true,
|
|
1266
|
+
data: {
|
|
1267
|
+
extensions: extensionList,
|
|
1268
|
+
totalCount: extensionList.length
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
ws.send(JSON.stringify(response));
|
|
1272
|
+
this.logger.info(`\u8FD4\u56DE\u6269\u5C55\u5217\u8868\uFF0C\u5171 ${extensionList.length} \u4E2A\u6269\u5C55`);
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* 处理打开页面请求
|
|
1276
|
+
*/
|
|
1277
|
+
handleOpenPage(ws, message) {
|
|
1278
|
+
const params = message.params;
|
|
1279
|
+
const requestId = message.id || "";
|
|
1280
|
+
if (!params?.url) {
|
|
1281
|
+
const errorResponse = {
|
|
1282
|
+
id: requestId,
|
|
1283
|
+
type: "error" /* ERROR */,
|
|
1284
|
+
success: false,
|
|
1285
|
+
error: {
|
|
1286
|
+
code: "E011" /* INVALID_PARAMS */,
|
|
1287
|
+
name: "INVALID_PARAMS",
|
|
1288
|
+
message: "\u7F3A\u5C11 url \u53C2\u6570"
|
|
1289
|
+
}
|
|
1290
|
+
};
|
|
1291
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
const targetIndex = params.extensionIndex || 1;
|
|
1295
|
+
const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
|
|
1296
|
+
if (!targetExtension) {
|
|
1297
|
+
const errorResponse = {
|
|
1298
|
+
id: requestId,
|
|
1299
|
+
type: "error" /* ERROR */,
|
|
1300
|
+
success: false,
|
|
1301
|
+
error: {
|
|
1302
|
+
code: "E018" /* NO_EXTENSION_CONNECTED */,
|
|
1303
|
+
name: "NO_EXTENSION_CONNECTED",
|
|
1304
|
+
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`
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1308
|
+
this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
const forwardMessage = {
|
|
1312
|
+
id: requestId,
|
|
1313
|
+
type: "open_page" /* OPEN_PAGE */,
|
|
1314
|
+
params: { url: params.url }
|
|
1315
|
+
};
|
|
1316
|
+
this.requestHandler.registerPendingRequest(requestId, ws, () => {
|
|
1317
|
+
try {
|
|
1318
|
+
targetExtension.send(JSON.stringify(forwardMessage));
|
|
1319
|
+
this.logger.info(`\u8F6C\u53D1 OPEN_PAGE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.url}`);
|
|
1320
|
+
} catch (error) {
|
|
1321
|
+
this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
|
|
1322
|
+
const errorResponse = {
|
|
1323
|
+
id: requestId,
|
|
1324
|
+
type: "error" /* ERROR */,
|
|
1325
|
+
success: false,
|
|
1326
|
+
error: {
|
|
1327
|
+
code: "E001" /* CONNECTION_FAILED */,
|
|
1328
|
+
name: "CONNECTION_FAILED",
|
|
1329
|
+
message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
/**
|
|
1337
|
+
* 处理节点导航请求
|
|
1338
|
+
*/
|
|
1339
|
+
handleNavigateToNode(ws, message) {
|
|
1340
|
+
const params = message.params;
|
|
1341
|
+
const requestId = message.id || "";
|
|
1342
|
+
if (!params?.pageUrl || !params?.nodeId) {
|
|
1343
|
+
const errorResponse = {
|
|
1344
|
+
id: requestId,
|
|
1345
|
+
type: "error" /* ERROR */,
|
|
1346
|
+
success: false,
|
|
1347
|
+
error: {
|
|
1348
|
+
code: "E011" /* INVALID_PARAMS */,
|
|
1349
|
+
name: "INVALID_PARAMS",
|
|
1350
|
+
message: "\u7F3A\u5C11 pageUrl \u6216 nodeId \u53C2\u6570"
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
const targetIndex = params.extensionIndex || 1;
|
|
1357
|
+
const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
|
|
1358
|
+
if (!targetExtension) {
|
|
1359
|
+
const errorResponse = {
|
|
1360
|
+
id: requestId,
|
|
1361
|
+
type: "error" /* ERROR */,
|
|
1362
|
+
success: false,
|
|
1363
|
+
error: {
|
|
1364
|
+
code: "E018" /* NO_EXTENSION_CONNECTED */,
|
|
1365
|
+
name: "NO_EXTENSION_CONNECTED",
|
|
1366
|
+
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`
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1370
|
+
this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
const forwardMessage = {
|
|
1374
|
+
id: requestId,
|
|
1375
|
+
type: "navigate_to_node" /* NAVIGATE_TO_NODE */,
|
|
1376
|
+
params: {
|
|
1377
|
+
pageUrl: params.pageUrl,
|
|
1378
|
+
nodeId: params.nodeId
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
this.requestHandler.registerPendingRequest(requestId, ws, () => {
|
|
1382
|
+
try {
|
|
1383
|
+
targetExtension.send(JSON.stringify(forwardMessage));
|
|
1384
|
+
this.logger.info(`\u8F6C\u53D1 NAVIGATE_TO_NODE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.pageUrl} -> ${params.nodeId}`);
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
|
|
1387
|
+
const errorResponse = {
|
|
1388
|
+
id: requestId,
|
|
1389
|
+
type: "error" /* ERROR */,
|
|
1390
|
+
success: false,
|
|
1391
|
+
error: {
|
|
1392
|
+
code: "E001" /* CONNECTION_FAILED */,
|
|
1393
|
+
name: "CONNECTION_FAILED",
|
|
1394
|
+
message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
|
|
1395
|
+
}
|
|
1396
|
+
};
|
|
1397
|
+
ws.send(JSON.stringify(errorResponse));
|
|
1398
|
+
}
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1046
1401
|
/**
|
|
1047
1402
|
* 停止服务器
|
|
1048
1403
|
*/
|
|
@@ -1053,12 +1408,12 @@ var MGServer = class {
|
|
|
1053
1408
|
this.logger.info("\u6B63\u5728\u505C\u6B62 Server...");
|
|
1054
1409
|
this.requestHandler.cleanupAll();
|
|
1055
1410
|
this.connectionManager.closeAll();
|
|
1056
|
-
return new Promise((
|
|
1411
|
+
return new Promise((resolve9) => {
|
|
1057
1412
|
this.wss.close(() => {
|
|
1058
1413
|
this.isRunning = false;
|
|
1059
1414
|
this.wss = null;
|
|
1060
1415
|
this.logger.info("Server \u5DF2\u505C\u6B62");
|
|
1061
|
-
|
|
1416
|
+
resolve9();
|
|
1062
1417
|
});
|
|
1063
1418
|
});
|
|
1064
1419
|
}
|
|
@@ -1159,7 +1514,7 @@ async function startServerDaemon(port) {
|
|
|
1159
1514
|
ensureConfigDir();
|
|
1160
1515
|
const currentFile = fileURLToPath2(import.meta.url);
|
|
1161
1516
|
const currentDir = dirname4(currentFile);
|
|
1162
|
-
const serverScript =
|
|
1517
|
+
const serverScript = join4(currentDir, "daemon-runner.js");
|
|
1163
1518
|
const args = ["--foreground"];
|
|
1164
1519
|
if (port) {
|
|
1165
1520
|
args.push("--port", String(port));
|
|
@@ -1175,7 +1530,7 @@ async function startServerDaemon(port) {
|
|
|
1175
1530
|
child.unref();
|
|
1176
1531
|
const startTime = Date.now();
|
|
1177
1532
|
while (Date.now() - startTime < SERVER_START_TIMEOUT) {
|
|
1178
|
-
await new Promise((
|
|
1533
|
+
await new Promise((resolve9) => setTimeout(resolve9, 200));
|
|
1179
1534
|
const { running: running2, info: info2 } = isServerRunning();
|
|
1180
1535
|
if (running2 && info2) {
|
|
1181
1536
|
return info2;
|
|
@@ -1196,7 +1551,7 @@ function stopServer() {
|
|
|
1196
1551
|
}
|
|
1197
1552
|
async function restartServer(port) {
|
|
1198
1553
|
const { info: oldInfo } = stopServer();
|
|
1199
|
-
await new Promise((
|
|
1554
|
+
await new Promise((resolve9) => setTimeout(resolve9, 500));
|
|
1200
1555
|
return startServerDaemon(port || oldInfo?.port);
|
|
1201
1556
|
}
|
|
1202
1557
|
function getServerStatus() {
|
|
@@ -1269,7 +1624,7 @@ var MGClient = class {
|
|
|
1269
1624
|
* 尝试连接指定端口
|
|
1270
1625
|
*/
|
|
1271
1626
|
tryConnect(port) {
|
|
1272
|
-
return new Promise((
|
|
1627
|
+
return new Promise((resolve9, reject) => {
|
|
1273
1628
|
const ws = new WebSocket2(`ws://localhost:${port}`);
|
|
1274
1629
|
const timer = setTimeout(() => {
|
|
1275
1630
|
ws.close();
|
|
@@ -1279,7 +1634,7 @@ var MGClient = class {
|
|
|
1279
1634
|
clearTimeout(timer);
|
|
1280
1635
|
this.ws = ws;
|
|
1281
1636
|
this.register();
|
|
1282
|
-
|
|
1637
|
+
resolve9();
|
|
1283
1638
|
});
|
|
1284
1639
|
ws.on("error", (error) => {
|
|
1285
1640
|
clearTimeout(timer);
|
|
@@ -1332,7 +1687,7 @@ var MGClient = class {
|
|
|
1332
1687
|
pageUrl,
|
|
1333
1688
|
timestamp: Date.now()
|
|
1334
1689
|
};
|
|
1335
|
-
return new Promise((
|
|
1690
|
+
return new Promise((resolve9, reject) => {
|
|
1336
1691
|
const timer = setTimeout(() => {
|
|
1337
1692
|
reject(new MGError("E012" /* REQUEST_TIMEOUT */, ErrorMessages["E012" /* REQUEST_TIMEOUT */]));
|
|
1338
1693
|
}, REQUEST_TIMEOUT);
|
|
@@ -1343,7 +1698,7 @@ var MGClient = class {
|
|
|
1343
1698
|
clearTimeout(timer);
|
|
1344
1699
|
this.ws?.off("message", messageHandler);
|
|
1345
1700
|
if (response.success) {
|
|
1346
|
-
|
|
1701
|
+
resolve9(response.data);
|
|
1347
1702
|
} else {
|
|
1348
1703
|
const error = response.error;
|
|
1349
1704
|
reject(
|
|
@@ -1525,11 +1880,11 @@ function createServerCommand() {
|
|
|
1525
1880
|
|
|
1526
1881
|
// src/cli/commands/get-node-by-id.ts
|
|
1527
1882
|
import { Command as Command2 } from "commander";
|
|
1528
|
-
import { writeFileSync as
|
|
1883
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
1529
1884
|
import { resolve as resolve2, dirname as dirname5 } from "path";
|
|
1530
|
-
import { mkdirSync as
|
|
1885
|
+
import { mkdirSync as mkdirSync4 } from "fs";
|
|
1531
1886
|
function createGetNodeByIdCommand() {
|
|
1532
|
-
return new Command2("get_node_by_id").description("\u6839\u636E\u8282\u70B9 ID \u83B7\u53D6\u8282\u70B9\u8BE6\u7EC6\u4FE1\u606F\u3002\u6570\u636E\u4FDD\u5B58\u5230\u6307\u5B9A JSON \u6587\u4EF6\uFF0C\u8FD4\u56DE\u6587\u4EF6\u8DEF\u5F84\u548C\u5927\u5C0F\u4FE1\u606F\u3002\u5982\u9700\u901A\u8FC7\u94FE\u63A5\u83B7\u53D6\uFF0C\u8BF7\u4F7F\u7528 get_node_by_link \u547D\u4EE4").requiredOption("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u53EF\u4ECE MasterGo \u6D6E\u7A97\u94FE\u63A5\u4E2D\u83B7\u53D6").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u589E\u52A0\u6DF1\u5EA6\u4F1A\u663E\u8457\u589E\u52A0\u6570\u636E\u91CF", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
1887
|
+
return new Command2("get_node_by_id").description("\u6839\u636E\u8282\u70B9 ID \u83B7\u53D6\u8282\u70B9\u8BE6\u7EC6\u4FE1\u606F\u3002\u6570\u636E\u4FDD\u5B58\u5230\u6307\u5B9A JSON \u6587\u4EF6\uFF0C\u8FD4\u56DE\u6587\u4EF6\u8DEF\u5F84\u548C\u5927\u5C0F\u4FE1\u606F\u3002\u5982\u9700\u901A\u8FC7\u94FE\u63A5\u83B7\u53D6\uFF0C\u8BF7\u4F7F\u7528 get_node_by_link \u547D\u4EE4").requiredOption("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u53EF\u4ECE MasterGo \u6D6E\u7A97\u94FE\u63A5\u4E2D\u83B7\u53D6").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u589E\u52A0\u6DF1\u5EA6\u4F1A\u663E\u8457\u589E\u52A0\u6570\u636E\u91CF", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
1533
1888
|
await handleGetNodeById(options);
|
|
1534
1889
|
});
|
|
1535
1890
|
}
|
|
@@ -1554,15 +1909,16 @@ async function handleGetNodeById(options) {
|
|
|
1554
1909
|
const outputData = options.raw ? data : trimNodeDefaults(data);
|
|
1555
1910
|
const outputPath = resolve2(options.output);
|
|
1556
1911
|
const outputDir = dirname5(outputPath);
|
|
1557
|
-
|
|
1558
|
-
const jsonContent = JSON.stringify(outputData, null, 2);
|
|
1559
|
-
|
|
1912
|
+
mkdirSync4(outputDir, { recursive: true });
|
|
1913
|
+
const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
|
|
1914
|
+
writeFileSync3(outputPath, jsonContent, "utf-8");
|
|
1560
1915
|
const size = jsonContent.length;
|
|
1561
1916
|
const sizeKB = (size / 1024).toFixed(2);
|
|
1562
1917
|
console.log(`\u6587\u4EF6\u8DEF\u5F84: ${outputPath}`);
|
|
1563
1918
|
console.log(`\u8282\u70B9 ID: ${options.nodeId}`);
|
|
1564
1919
|
console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
|
|
1565
1920
|
console.log(`\u8282\u70B9\u6DF1\u5EA6: ${params.maxDepth}`);
|
|
1921
|
+
console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
|
|
1566
1922
|
if (!options.raw) {
|
|
1567
1923
|
console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
|
|
1568
1924
|
}
|
|
@@ -1576,11 +1932,11 @@ async function handleGetNodeById(options) {
|
|
|
1576
1932
|
|
|
1577
1933
|
// src/cli/commands/get-node-by-link.ts
|
|
1578
1934
|
import { Command as Command3 } from "commander";
|
|
1579
|
-
import { writeFileSync as
|
|
1935
|
+
import { writeFileSync as writeFileSync4 } from "fs";
|
|
1580
1936
|
import { resolve as resolve3, dirname as dirname6 } from "path";
|
|
1581
|
-
import { mkdirSync as
|
|
1937
|
+
import { mkdirSync as mkdirSync5 } from "fs";
|
|
1582
1938
|
function createGetNodeByLinkCommand() {
|
|
1583
|
-
return new Command3("get_node_by_link").description("\u89E3\u6790 mgp:// \u534F\u8BAE\u94FE\u63A5\u5E76\u83B7\u53D6\u8282\u70B9/\u9875\u9762\u4FE1\u606F").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
1939
|
+
return new Command3("get_node_by_link").description("\u89E3\u6790 mgp:// \u534F\u8BAE\u94FE\u63A5\u5E76\u83B7\u53D6\u8282\u70B9/\u9875\u9762\u4FE1\u606F").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
1584
1940
|
await handleGetNodeByLink(options);
|
|
1585
1941
|
});
|
|
1586
1942
|
}
|
|
@@ -1629,9 +1985,9 @@ async function handleGetNodeByLink(options) {
|
|
|
1629
1985
|
const outputData = options.raw ? data : trimNodeDefaults(data);
|
|
1630
1986
|
const outputPath = resolve3(options.output);
|
|
1631
1987
|
const outputDir = dirname6(outputPath);
|
|
1632
|
-
|
|
1633
|
-
const jsonContent = JSON.stringify(outputData, null, 2);
|
|
1634
|
-
|
|
1988
|
+
mkdirSync5(outputDir, { recursive: true });
|
|
1989
|
+
const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
|
|
1990
|
+
writeFileSync4(outputPath, jsonContent, "utf-8");
|
|
1635
1991
|
const size = jsonContent.length;
|
|
1636
1992
|
const sizeKB = (size / 1024).toFixed(2);
|
|
1637
1993
|
console.log(`\u6587\u4EF6\u8DEF\u5F84: ${outputPath}`);
|
|
@@ -1646,6 +2002,7 @@ async function handleGetNodeByLink(options) {
|
|
|
1646
2002
|
}
|
|
1647
2003
|
console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
|
|
1648
2004
|
console.log(`\u904D\u5386\u6DF1\u5EA6: ${options.maxDepth || "1"}`);
|
|
2005
|
+
console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
|
|
1649
2006
|
if (!options.raw) {
|
|
1650
2007
|
console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
|
|
1651
2008
|
}
|
|
@@ -1663,11 +2020,11 @@ async function handleGetNodeByLink(options) {
|
|
|
1663
2020
|
|
|
1664
2021
|
// src/cli/commands/get-all-nodes.ts
|
|
1665
2022
|
import { Command as Command4 } from "commander";
|
|
1666
|
-
import { writeFileSync as
|
|
2023
|
+
import { writeFileSync as writeFileSync5 } from "fs";
|
|
1667
2024
|
import { resolve as resolve4, dirname as dirname7 } from "path";
|
|
1668
|
-
import { mkdirSync as
|
|
2025
|
+
import { mkdirSync as mkdirSync6 } from "fs";
|
|
1669
2026
|
function createGetAllNodesCommand() {
|
|
1670
|
-
return new Command4("get_all_nodes").description("\u83B7\u53D6\u5F53\u524D\u9875\u9762\u7684\u6240\u6709\u8282\u70B9\u6811\u3002\u8B66\u544A\uFF1A\u6DF1\u5EA6\u6BCF\u589E\u52A0 1\uFF0C\u6570\u636E\u91CF\u53EF\u80FD\u5448\u6307\u6570\u7EA7\u589E\u957F\u3002\u5EFA\u8BAE\u4ECE maxDepth=1 \u5F00\u59CB").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--maxDepth <number>", "\u6700\u5927\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u6DF1\u5EA6 2 \u53EF\u80FD\u4EA7\u751F 100KB-500KB\uFF0C\u6DF1\u5EA6 3 \u53EF\u80FD\u8D85\u8FC7 1MB", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2027
|
+
return new Command4("get_all_nodes").description("\u83B7\u53D6\u5F53\u524D\u9875\u9762\u7684\u6240\u6709\u8282\u70B9\u6811\u3002\u8B66\u544A\uFF1A\u6DF1\u5EA6\u6BCF\u589E\u52A0 1\uFF0C\u6570\u636E\u91CF\u53EF\u80FD\u5448\u6307\u6570\u7EA7\u589E\u957F\u3002\u5EFA\u8BAE\u4ECE maxDepth=1 \u5F00\u59CB").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--maxDepth <number>", "\u6700\u5927\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u6DF1\u5EA6 2 \u53EF\u80FD\u4EA7\u751F 100KB-500KB\uFF0C\u6DF1\u5EA6 3 \u53EF\u80FD\u8D85\u8FC7 1MB", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
1671
2028
|
await handleGetAllNodes(options);
|
|
1672
2029
|
});
|
|
1673
2030
|
}
|
|
@@ -1686,9 +2043,9 @@ async function handleGetAllNodes(options) {
|
|
|
1686
2043
|
const outputData = options.raw ? data : Array.isArray(data) ? data.map((node) => trimNodeDefaults(node)) : trimNodeDefaults(data);
|
|
1687
2044
|
const outputPath = resolve4(options.output);
|
|
1688
2045
|
const outputDir = dirname7(outputPath);
|
|
1689
|
-
|
|
1690
|
-
const jsonContent = JSON.stringify(outputData, null, 2);
|
|
1691
|
-
|
|
2046
|
+
mkdirSync6(outputDir, { recursive: true });
|
|
2047
|
+
const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
|
|
2048
|
+
writeFileSync5(outputPath, jsonContent, "utf-8");
|
|
1692
2049
|
const size = jsonContent.length;
|
|
1693
2050
|
const sizeKB = (size / 1024).toFixed(2);
|
|
1694
2051
|
const nodeCount = Array.isArray(data) ? data.length : 1;
|
|
@@ -1696,6 +2053,7 @@ async function handleGetAllNodes(options) {
|
|
|
1696
2053
|
console.log(`\u8282\u70B9\u6570\u91CF: ${nodeCount}`);
|
|
1697
2054
|
console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
|
|
1698
2055
|
console.log(`\u8282\u70B9\u6DF1\u5EA6: ${params.maxDepth}`);
|
|
2056
|
+
console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
|
|
1699
2057
|
if (!options.raw) {
|
|
1700
2058
|
console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
|
|
1701
2059
|
}
|
|
@@ -1709,9 +2067,9 @@ async function handleGetAllNodes(options) {
|
|
|
1709
2067
|
|
|
1710
2068
|
// src/cli/commands/export-image.ts
|
|
1711
2069
|
import { Command as Command5 } from "commander";
|
|
1712
|
-
import { writeFileSync as
|
|
2070
|
+
import { writeFileSync as writeFileSync6, unlinkSync as unlinkSync2 } from "fs";
|
|
1713
2071
|
import { resolve as resolve5, dirname as dirname8, extname, basename } from "path";
|
|
1714
|
-
import { mkdirSync as
|
|
2072
|
+
import { mkdirSync as mkdirSync7 } from "fs";
|
|
1715
2073
|
import { tmpdir } from "os";
|
|
1716
2074
|
import { vdConvert } from "vd-tool";
|
|
1717
2075
|
function createExportImageCommand() {
|
|
@@ -1801,23 +2159,23 @@ async function handleExportImage(options) {
|
|
|
1801
2159
|
console.log("\u8B66\u544A: \u672A\u6307\u5B9A --output\uFF0C\u6587\u4EF6\u5C06\u4FDD\u5B58\u5230\u4E34\u65F6\u76EE\u5F55\uFF0C\u53EF\u80FD\u4F1A\u88AB\u7CFB\u7EDF\u6E05\u7406");
|
|
1802
2160
|
}
|
|
1803
2161
|
const outputDir = dirname8(outputPath);
|
|
1804
|
-
|
|
2162
|
+
mkdirSync7(outputDir, { recursive: true });
|
|
1805
2163
|
const buffer = Buffer.from(response.data, "base64");
|
|
1806
2164
|
let finalPath = outputPath;
|
|
1807
2165
|
let finalSize = buffer.length;
|
|
1808
2166
|
if (isVectorFormat) {
|
|
1809
2167
|
const tempSvgPath = resolve5(tmpdir(), `temp_${Date.now()}.svg`);
|
|
1810
|
-
|
|
2168
|
+
writeFileSync6(tempSvgPath, buffer);
|
|
1811
2169
|
try {
|
|
1812
2170
|
const vectorOutputDir = dirname8(outputPath);
|
|
1813
2171
|
const convertedPath = await convertSvgToVector(tempSvgPath, vectorOutputDir);
|
|
1814
2172
|
const expectedOutputName = basename(tempSvgPath, ".svg") + ".xml";
|
|
1815
2173
|
const expectedOutputPath = resolve5(vectorOutputDir, expectedOutputName);
|
|
1816
2174
|
if (expectedOutputPath !== outputPath) {
|
|
1817
|
-
const { renameSync, existsSync:
|
|
1818
|
-
if (
|
|
2175
|
+
const { renameSync, existsSync: existsSync5 } = await import("fs");
|
|
2176
|
+
if (existsSync5(expectedOutputPath)) {
|
|
1819
2177
|
renameSync(expectedOutputPath, outputPath);
|
|
1820
|
-
} else if (
|
|
2178
|
+
} else if (existsSync5(convertedPath)) {
|
|
1821
2179
|
renameSync(convertedPath, outputPath);
|
|
1822
2180
|
}
|
|
1823
2181
|
}
|
|
@@ -1831,7 +2189,7 @@ async function handleExportImage(options) {
|
|
|
1831
2189
|
}
|
|
1832
2190
|
}
|
|
1833
2191
|
} else {
|
|
1834
|
-
|
|
2192
|
+
writeFileSync6(outputPath, buffer);
|
|
1835
2193
|
}
|
|
1836
2194
|
const sizeKB = (finalSize / 1024).toFixed(2);
|
|
1837
2195
|
console.log(`\u6587\u4EF6\u8DEF\u5F84: ${finalPath}`);
|
|
@@ -1895,7 +2253,7 @@ async function convertSvgToVector(svgPath, outputDir) {
|
|
|
1895
2253
|
// src/cli/commands/execute-code.ts
|
|
1896
2254
|
import { Command as Command6 } from "commander";
|
|
1897
2255
|
function createExecuteCodeCommand() {
|
|
1898
|
-
return new Command6("execute_code").description("\u5728 MasterGo \u9875\u9762\u6267\u884C\u81EA\u5B9A\u4E49 JavaScript \u4EE3\u7801\u3002\u901A\u8FC7 mg \u53D8\u91CF\u8BBF\u95EE MasterGo API\uFF0C\u7ED3\u679C\u4F1A\u88AB JSON \u5E8F\u5217\u5316\u8FD4\u56DE").argument("<code>", "\u8981\u6267\u884C\u7684\u4EE3\u7801\u3002\u53EF\u4F7F\u7528 mg \u53D8\u91CF\uFF0C\u5982 mg.currentPage.name\u3001mg.currentPage.selection").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF0C\u7528\u4E8E\u6307\u5B9A\u76EE\u6807\u9875\u9762\u3002\u4E0E --domain/--fileId \u4E8C\u9009\u4E00").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (code, options) => {
|
|
2256
|
+
return new Command6("execute_code").description("\u5728 MasterGo \u9875\u9762\u6267\u884C\u81EA\u5B9A\u4E49 JavaScript \u4EE3\u7801\u3002\u901A\u8FC7 mg \u53D8\u91CF\u8BBF\u95EE MasterGo API\uFF0C\u7ED3\u679C\u4F1A\u88AB JSON \u5E8F\u5217\u5316\u8FD4\u56DE").argument("<code>", "\u8981\u6267\u884C\u7684\u4EE3\u7801\u3002\u53EF\u4F7F\u7528 mg \u53D8\u91CF\uFF0C\u5982 mg.currentPage.name\u3001mg.currentPage.selection").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF0C\u7528\u4E8E\u6307\u5B9A\u76EE\u6807\u9875\u9762\u3002\u4E0E --domain/--fileId \u4E8C\u9009\u4E00").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (code, options) => {
|
|
1899
2257
|
await handleExecuteCode(code, options);
|
|
1900
2258
|
});
|
|
1901
2259
|
}
|
|
@@ -1928,7 +2286,7 @@ async function handleExecuteCode(code, options) {
|
|
|
1928
2286
|
if (result === null || result === void 0) {
|
|
1929
2287
|
console.log("\u6267\u884C\u5B8C\u6210\uFF08\u65E0\u8FD4\u56DE\u503C\uFF09");
|
|
1930
2288
|
} else if (typeof result === "object") {
|
|
1931
|
-
console.log(JSON.stringify(result, null, 2));
|
|
2289
|
+
console.log(JSON.stringify(result, null, options.pretty ? 2 : 0));
|
|
1932
2290
|
} else {
|
|
1933
2291
|
console.log(result);
|
|
1934
2292
|
}
|
|
@@ -1942,12 +2300,12 @@ async function handleExecuteCode(code, options) {
|
|
|
1942
2300
|
|
|
1943
2301
|
// src/cli/commands/get-all-pages.ts
|
|
1944
2302
|
import { Command as Command7 } from "commander";
|
|
1945
|
-
import { writeFileSync as
|
|
2303
|
+
import { writeFileSync as writeFileSync7 } from "fs";
|
|
1946
2304
|
import { resolve as resolve6, dirname as dirname9 } from "path";
|
|
1947
|
-
import { mkdirSync as
|
|
2305
|
+
import { mkdirSync as mkdirSync8 } from "fs";
|
|
1948
2306
|
import { tmpdir as tmpdir2 } from "os";
|
|
1949
2307
|
function createGetAllPagesCommand() {
|
|
1950
|
-
return new Command7("get_all_pages").description("\u83B7\u53D6 MasterGo \u6587\u6863\u7684\u6240\u6709\u9875\u9762\u4FE1\u606F\u3002\u4E0D\u6307\u5B9A --output \u65F6\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--link <url>", "\u9875\u9762\u94FE\u63A5\u3002\u652F\u6301\u5B8C\u6574 URL \u6216 mgp:// \u534F\u8BAE").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\u3002\u4ECE URL \u4E2D /file/ \u540E\u9762\u7684\u6570\u5B57").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u4E0D\u6307\u5B9A\u5219\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2308
|
+
return new Command7("get_all_pages").description("\u83B7\u53D6 MasterGo \u6587\u6863\u7684\u6240\u6709\u9875\u9762\u4FE1\u606F\u3002\u4E0D\u6307\u5B9A --output \u65F6\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--link <url>", "\u9875\u9762\u94FE\u63A5\u3002\u652F\u6301\u5B8C\u6574 URL \u6216 mgp:// \u534F\u8BAE").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\u3002\u4ECE URL \u4E2D /file/ \u540E\u9762\u7684\u6570\u5B57").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u4E0D\u6307\u5B9A\u5219\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
1951
2309
|
await handleGetAllPages(options);
|
|
1952
2310
|
});
|
|
1953
2311
|
}
|
|
@@ -1992,15 +2350,16 @@ async function handleGetAllPages(options) {
|
|
|
1992
2350
|
outputPath = resolve6(tmpdir2(), filename);
|
|
1993
2351
|
}
|
|
1994
2352
|
const outputDir = dirname9(outputPath);
|
|
1995
|
-
|
|
1996
|
-
const jsonContent = JSON.stringify(data, null, 2);
|
|
1997
|
-
|
|
2353
|
+
mkdirSync8(outputDir, { recursive: true });
|
|
2354
|
+
const jsonContent = JSON.stringify(data, null, options.pretty ? 2 : 0);
|
|
2355
|
+
writeFileSync7(outputPath, jsonContent, "utf-8");
|
|
1998
2356
|
const size = jsonContent.length;
|
|
1999
2357
|
const sizeKB = (size / 1024).toFixed(2);
|
|
2000
2358
|
console.log(`\u6587\u4EF6\u8DEF\u5F84: ${outputPath}`);
|
|
2001
2359
|
console.log(`\u6587\u6863\u540D\u79F0: ${data.documentName}`);
|
|
2002
2360
|
console.log(`\u9875\u9762\u6570\u91CF: ${data.totalCount}`);
|
|
2003
2361
|
console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
|
|
2362
|
+
console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
|
|
2004
2363
|
} catch (error) {
|
|
2005
2364
|
console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
|
|
2006
2365
|
process.exit(1);
|
|
@@ -2011,11 +2370,11 @@ async function handleGetAllPages(options) {
|
|
|
2011
2370
|
|
|
2012
2371
|
// src/cli/commands/get-node-for-space.ts
|
|
2013
2372
|
import { Command as Command8 } from "commander";
|
|
2014
|
-
import { writeFileSync as
|
|
2373
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
2015
2374
|
import { resolve as resolve7, dirname as dirname10 } from "path";
|
|
2016
|
-
import { mkdirSync as
|
|
2375
|
+
import { mkdirSync as mkdirSync9 } from "fs";
|
|
2017
2376
|
function createGetNodeForSpaceCommand() {
|
|
2018
|
-
return new Command8("get_node_for_space").description("\u83B7\u53D6\u8282\u70B9\u6216\u9875\u9762\u7684\u7A7A\u95F4\u4F4D\u7F6E\u4FE1\u606F\uFF08id\u3001name\u3001x\u3001y\u3001width\u3001height\uFF09\uFF0C\u7528\u4E8E AI \u7406\u89E3\u5143\u7D20\u5E03\u5C40\u3002\u9ED8\u8BA4\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\u3002\u652F\u6301 nodeId \u548C pageId \u94FE\u63A5").option("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u4E0E --link \u4E8C\u9009\u4E00").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09\u3002\u4E0E --nodeId \u4E8C\u9009\u4E00").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --nodeId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u548C --nodeId \u914D\u5408\u4F7F\u7528").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 99\uFF08\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\uFF09", "99").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2377
|
+
return new Command8("get_node_for_space").description("\u83B7\u53D6\u8282\u70B9\u6216\u9875\u9762\u7684\u7A7A\u95F4\u4F4D\u7F6E\u4FE1\u606F\uFF08id\u3001name\u3001x\u3001y\u3001width\u3001height\uFF09\uFF0C\u7528\u4E8E AI \u7406\u89E3\u5143\u7D20\u5E03\u5C40\u3002\u9ED8\u8BA4\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\u3002\u652F\u6301 nodeId \u548C pageId \u94FE\u63A5").option("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u4E0E --link \u4E8C\u9009\u4E00").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09\u3002\u4E0E --nodeId \u4E8C\u9009\u4E00").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --nodeId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u548C --nodeId \u914D\u5408\u4F7F\u7528").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 99\uFF08\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\uFF09", "99").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2019
2378
|
await handleGetNodeForSpace(options);
|
|
2020
2379
|
});
|
|
2021
2380
|
}
|
|
@@ -2093,9 +2452,9 @@ async function handleGetNodeForSpace(options) {
|
|
|
2093
2452
|
const spaceData = extractSpaceInfo(data);
|
|
2094
2453
|
const outputPath = resolve7(options.output);
|
|
2095
2454
|
const outputDir = dirname10(outputPath);
|
|
2096
|
-
|
|
2097
|
-
const jsonContent = JSON.stringify(spaceData, null, 2);
|
|
2098
|
-
|
|
2455
|
+
mkdirSync9(outputDir, { recursive: true });
|
|
2456
|
+
const jsonContent = JSON.stringify(spaceData, null, options.pretty ? 2 : 0);
|
|
2457
|
+
writeFileSync8(outputPath, jsonContent, "utf-8");
|
|
2099
2458
|
const size = jsonContent.length;
|
|
2100
2459
|
const sizeKB = (size / 1024).toFixed(2);
|
|
2101
2460
|
console.log(`\u6587\u4EF6\u8DEF\u5F84: ${outputPath}`);
|
|
@@ -2112,6 +2471,7 @@ async function handleGetNodeForSpace(options) {
|
|
|
2112
2471
|
}
|
|
2113
2472
|
console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
|
|
2114
2473
|
console.log(`\u8282\u70B9\u6DF1\u5EA6: ${maxDepth}`);
|
|
2474
|
+
console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
|
|
2115
2475
|
console.log(`\u6570\u636E\u6A21\u5F0F: \u7A7A\u95F4\u4FE1\u606F (\u4EC5 id, name, x, y, width, height)`);
|
|
2116
2476
|
} catch (error) {
|
|
2117
2477
|
if (error instanceof MGError) {
|
|
@@ -2125,8 +2485,595 @@ async function handleGetNodeForSpace(options) {
|
|
|
2125
2485
|
}
|
|
2126
2486
|
}
|
|
2127
2487
|
|
|
2488
|
+
// src/cli/commands/list-extensions.ts
|
|
2489
|
+
import { Command as Command9 } from "commander";
|
|
2490
|
+
function createListExtensionsCommand() {
|
|
2491
|
+
return new Command9("list_extensions").description("\u5217\u51FA\u6240\u6709\u5DF2\u8FDE\u63A5\u7684 Chrome \u6269\u5C55\u5B9E\u4F8B").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2492
|
+
await handleListExtensions(options);
|
|
2493
|
+
});
|
|
2494
|
+
}
|
|
2495
|
+
async function handleListExtensions(options) {
|
|
2496
|
+
const client = new MGClient({
|
|
2497
|
+
noAutoStart: options.noAutoStart,
|
|
2498
|
+
noRetry: options.noRetry
|
|
2499
|
+
});
|
|
2500
|
+
try {
|
|
2501
|
+
await client.connect();
|
|
2502
|
+
const data = await client.requestWithRetry("list_extensions" /* LIST_EXTENSIONS */, {});
|
|
2503
|
+
if (data.totalCount === 0) {
|
|
2504
|
+
console.log("\u5F53\u524D\u6CA1\u6709\u8FDE\u63A5\u7684\u6269\u5C55\u5B9E\u4F8B");
|
|
2505
|
+
console.log("\n\u8BF7\u786E\u4FDD:");
|
|
2506
|
+
console.log(" 1. \u6D4F\u89C8\u5668\u5DF2\u6253\u5F00");
|
|
2507
|
+
console.log(" 2. \u5DF2\u5B89\u88C5 MG Plugin \u6269\u5C55");
|
|
2508
|
+
console.log(" 3. \u6269\u5C55\u5DF2\u6210\u529F\u8FDE\u63A5\u5230 Server");
|
|
2509
|
+
} else {
|
|
2510
|
+
console.log(`\u627E\u5230 ${data.totalCount} \u4E2A\u6269\u5C55\u5B9E\u4F8B:
|
|
2511
|
+
`);
|
|
2512
|
+
for (const ext of data.extensions) {
|
|
2513
|
+
const connectedAt = new Date(ext.connectedAt);
|
|
2514
|
+
const lastActiveAt = new Date(ext.lastActiveAt);
|
|
2515
|
+
console.log(`\u6269\u5C55 #${ext.index}`);
|
|
2516
|
+
console.log(` Extension ID: ${ext.extensionId}`);
|
|
2517
|
+
console.log(` \u8FDE\u63A5\u65F6\u95F4: ${connectedAt.toLocaleString()}`);
|
|
2518
|
+
console.log(` \u6700\u540E\u6D3B\u8DC3: ${lastActiveAt.toLocaleString()}`);
|
|
2519
|
+
console.log("");
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
} catch (error) {
|
|
2523
|
+
console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
|
|
2524
|
+
process.exit(1);
|
|
2525
|
+
} finally {
|
|
2526
|
+
client.close();
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
// src/cli/commands/open-page.ts
|
|
2531
|
+
import { Command as Command10 } from "commander";
|
|
2532
|
+
function createOpenPageCommand() {
|
|
2533
|
+
return new Command10("open_page").description("\u901A\u8FC7 Chrome \u6269\u5C55\u6253\u5F00\u6307\u5B9A\u7684\u9875\u9762").requiredOption("--url <url>", "\u8981\u6253\u5F00\u7684\u9875\u9762 URL\uFF08\u5B8C\u6574 HTTPS URL\uFF09").option("--ext <index>", "\u6269\u5C55\u5B9E\u4F8B\u5E8F\u53F7\uFF081, 2, 3...\uFF09\uFF0C\u9ED8\u8BA4\u81EA\u52A8\u9009\u62E9\u7B2C\u4E00\u4E2A\u53EF\u7528\u6269\u5C55").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2534
|
+
await handleOpenPage(options);
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2537
|
+
async function handleOpenPage(options) {
|
|
2538
|
+
const client = new MGClient({
|
|
2539
|
+
noAutoStart: options.noAutoStart,
|
|
2540
|
+
noRetry: options.noRetry
|
|
2541
|
+
});
|
|
2542
|
+
try {
|
|
2543
|
+
if (!options.url.startsWith("https://") && !options.url.startsWith("http://")) {
|
|
2544
|
+
console.error("\u9519\u8BEF: URL \u5FC5\u987B\u4EE5 https:// \u6216 http:// \u5F00\u5934");
|
|
2545
|
+
console.error(`\u63D0\u4F9B\u7684 URL: ${options.url}`);
|
|
2546
|
+
process.exit(1);
|
|
2547
|
+
}
|
|
2548
|
+
await client.connect();
|
|
2549
|
+
let extensionIndex;
|
|
2550
|
+
if (typeof options.ext === "string") {
|
|
2551
|
+
extensionIndex = parseInt(options.ext, 10);
|
|
2552
|
+
} else if (typeof options.ext === "number") {
|
|
2553
|
+
extensionIndex = options.ext;
|
|
2554
|
+
} else {
|
|
2555
|
+
const extensionsData = await client.requestWithRetry("list_extensions" /* LIST_EXTENSIONS */, {});
|
|
2556
|
+
if (extensionsData.totalCount === 0) {
|
|
2557
|
+
console.error("\u9519\u8BEF: \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");
|
|
2558
|
+
console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
|
|
2559
|
+
console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
|
|
2560
|
+
console.error(" npx -y @hangox/mg-cli@latest list_extensions");
|
|
2561
|
+
console.error("");
|
|
2562
|
+
console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
|
|
2563
|
+
console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
|
|
2564
|
+
console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
|
|
2565
|
+
console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
|
|
2566
|
+
process.exit(1);
|
|
2567
|
+
}
|
|
2568
|
+
extensionIndex = extensionsData.extensions[0].index;
|
|
2569
|
+
console.log(`\u672A\u6307\u5B9A\u6269\u5C55\u5E8F\u53F7\uFF0C\u81EA\u52A8\u4F7F\u7528\u6269\u5C55 #${extensionIndex}`);
|
|
2570
|
+
}
|
|
2571
|
+
if (isNaN(extensionIndex) || extensionIndex < 1) {
|
|
2572
|
+
console.error("\u9519\u8BEF: \u6269\u5C55\u5E8F\u53F7\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570");
|
|
2573
|
+
console.error(`\u63D0\u4F9B\u7684\u5E8F\u53F7: ${options.ext}`);
|
|
2574
|
+
process.exit(1);
|
|
2575
|
+
}
|
|
2576
|
+
console.log(`\u6B63\u5728\u901A\u8FC7\u6269\u5C55 #${extensionIndex} \u6253\u5F00\u9875\u9762...`);
|
|
2577
|
+
console.log(`URL: ${options.url}`);
|
|
2578
|
+
const params = {
|
|
2579
|
+
url: options.url,
|
|
2580
|
+
extensionIndex
|
|
2581
|
+
};
|
|
2582
|
+
const data = await client.requestWithRetry(
|
|
2583
|
+
"open_page" /* OPEN_PAGE */,
|
|
2584
|
+
params
|
|
2585
|
+
);
|
|
2586
|
+
console.log(`
|
|
2587
|
+
\u2713 \u9875\u9762\u5DF2\u6253\u5F00`);
|
|
2588
|
+
console.log(`Tab ID: ${data.tabId}`);
|
|
2589
|
+
} catch (error) {
|
|
2590
|
+
console.error(`
|
|
2591
|
+
\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
|
|
2592
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2593
|
+
if (errorMsg.includes("NO_EXTENSION_CONNECTED") || errorMsg.includes("\u672A\u627E\u5230")) {
|
|
2594
|
+
console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
|
|
2595
|
+
console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
|
|
2596
|
+
console.error(" npx -y @hangox/mg-cli@latest list_extensions");
|
|
2597
|
+
console.error("");
|
|
2598
|
+
console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
|
|
2599
|
+
console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
|
|
2600
|
+
console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
|
|
2601
|
+
console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
|
|
2602
|
+
console.error("");
|
|
2603
|
+
console.error(" 3. \u67E5\u770B\u6269\u5C55\u5B89\u88C5\u6307\u5357:");
|
|
2604
|
+
console.error(" https://github.com/hangox/MasterGoPlugin#chrome-plugin");
|
|
2605
|
+
}
|
|
2606
|
+
process.exit(1);
|
|
2607
|
+
} finally {
|
|
2608
|
+
client.close();
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
// src/cli/commands/navigate-to-node.ts
|
|
2613
|
+
import { Command as Command11 } from "commander";
|
|
2614
|
+
function createNavigateToNodeCommand() {
|
|
2615
|
+
return new Command11("navigate_to_node").description("\u5BFC\u822A\u5230 mgp:// \u94FE\u63A5\u6307\u5B9A\u7684\u8282\u70B9\uFF08\u81EA\u52A8\u5207\u6362\u6216\u6253\u5F00\u9875\u9762\uFF09").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5").option("--ext <index>", "\u6269\u5C55\u5B9E\u4F8B\u5E8F\u53F7\uFF081, 2, 3...\uFF09\uFF0C\u9ED8\u8BA4\u81EA\u52A8\u9009\u62E9\u7B2C\u4E00\u4E2A\u53EF\u7528\u6269\u5C55").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
2616
|
+
await handleNavigateToNode(options);
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
async function handleNavigateToNode(options) {
|
|
2620
|
+
const parsed = parseMgpLink(options.link);
|
|
2621
|
+
if (!parsed) {
|
|
2622
|
+
console.error(`\u9519\u8BEF [${"E010" /* INVALID_LINK */}]: \u65E0\u6548\u7684 mgp:// \u94FE\u63A5\u683C\u5F0F`);
|
|
2623
|
+
console.error(`\u63D0\u4F9B\u7684\u94FE\u63A5: ${options.link}`);
|
|
2624
|
+
console.error(`\u671F\u671B\u683C\u5F0F: mgp://[mastergo_page_url]?nodeId=[\u8282\u70B9ID]`);
|
|
2625
|
+
process.exit(1);
|
|
2626
|
+
}
|
|
2627
|
+
const { pageUrl, nodeId } = parsed;
|
|
2628
|
+
if (!nodeId) {
|
|
2629
|
+
console.error(`\u9519\u8BEF [${"E010" /* INVALID_LINK */}]: \u94FE\u63A5\u5FC5\u987B\u5305\u542B nodeId \u53C2\u6570`);
|
|
2630
|
+
console.error(`\u63D0\u4F9B\u7684\u94FE\u63A5: ${options.link}`);
|
|
2631
|
+
console.error(`\u671F\u671B\u683C\u5F0F: mgp://[mastergo_page_url]?nodeId=[\u8282\u70B9ID]`);
|
|
2632
|
+
process.exit(1);
|
|
2633
|
+
}
|
|
2634
|
+
const client = new MGClient({
|
|
2635
|
+
noAutoStart: options.noAutoStart,
|
|
2636
|
+
noRetry: options.noRetry
|
|
2637
|
+
});
|
|
2638
|
+
try {
|
|
2639
|
+
await client.connect();
|
|
2640
|
+
let extensionIndex;
|
|
2641
|
+
if (typeof options.ext === "string") {
|
|
2642
|
+
extensionIndex = parseInt(options.ext, 10);
|
|
2643
|
+
} else if (typeof options.ext === "number") {
|
|
2644
|
+
extensionIndex = options.ext;
|
|
2645
|
+
} else {
|
|
2646
|
+
const extensionsData = await client.requestWithRetry("list_extensions" /* LIST_EXTENSIONS */, {});
|
|
2647
|
+
if (extensionsData.totalCount === 0) {
|
|
2648
|
+
console.error("\u9519\u8BEF: \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");
|
|
2649
|
+
console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
|
|
2650
|
+
console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
|
|
2651
|
+
console.error(" npx -y @hangox/mg-cli@latest list_extensions");
|
|
2652
|
+
console.error("");
|
|
2653
|
+
console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
|
|
2654
|
+
console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
|
|
2655
|
+
console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
|
|
2656
|
+
console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
|
|
2657
|
+
process.exit(1);
|
|
2658
|
+
}
|
|
2659
|
+
extensionIndex = extensionsData.extensions[0].index;
|
|
2660
|
+
console.log(`\u672A\u6307\u5B9A\u6269\u5C55\u5E8F\u53F7\uFF0C\u81EA\u52A8\u4F7F\u7528\u6269\u5C55 #${extensionIndex}`);
|
|
2661
|
+
}
|
|
2662
|
+
if (isNaN(extensionIndex) || extensionIndex < 1) {
|
|
2663
|
+
console.error("\u9519\u8BEF: \u6269\u5C55\u5E8F\u53F7\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570");
|
|
2664
|
+
console.error(`\u63D0\u4F9B\u7684\u5E8F\u53F7: ${options.ext}`);
|
|
2665
|
+
process.exit(1);
|
|
2666
|
+
}
|
|
2667
|
+
console.log(`\u6B63\u5728\u901A\u8FC7\u6269\u5C55 #${extensionIndex} \u5BFC\u822A\u5230\u8282\u70B9...`);
|
|
2668
|
+
console.log(`\u9875\u9762 URL: ${pageUrl}`);
|
|
2669
|
+
console.log(`\u8282\u70B9 ID: ${nodeId}`);
|
|
2670
|
+
const params = {
|
|
2671
|
+
pageUrl,
|
|
2672
|
+
nodeId,
|
|
2673
|
+
extensionIndex
|
|
2674
|
+
};
|
|
2675
|
+
const data = await client.requestWithRetry("navigate_to_node" /* NAVIGATE_TO_NODE */, params);
|
|
2676
|
+
console.log(`
|
|
2677
|
+
\u2713 \u5BFC\u822A\u6210\u529F`);
|
|
2678
|
+
console.log(`\u64CD\u4F5C: ${data.action === "switched" ? "\u5207\u6362\u5230\u5DF2\u6253\u5F00\u7684 Tab" : "\u6253\u5F00\u65B0 Tab"}`);
|
|
2679
|
+
console.log(`Tab ID: ${data.tabId}`);
|
|
2680
|
+
console.log(`URL: ${data.url}`);
|
|
2681
|
+
} catch (error) {
|
|
2682
|
+
if (error instanceof MGError) {
|
|
2683
|
+
console.error(`
|
|
2684
|
+
\u9519\u8BEF [${error.code}]: ${error.message}`);
|
|
2685
|
+
} else {
|
|
2686
|
+
console.error(`
|
|
2687
|
+
\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
|
|
2688
|
+
}
|
|
2689
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2690
|
+
if (errorMsg.includes("NO_EXTENSION_CONNECTED") || errorMsg.includes("\u672A\u627E\u5230")) {
|
|
2691
|
+
console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
|
|
2692
|
+
console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
|
|
2693
|
+
console.error(" npx -y @hangox/mg-cli@latest list_extensions");
|
|
2694
|
+
console.error("");
|
|
2695
|
+
console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
|
|
2696
|
+
console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
|
|
2697
|
+
console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
|
|
2698
|
+
console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
|
|
2699
|
+
console.error("");
|
|
2700
|
+
console.error(" 3. \u67E5\u770B\u6269\u5C55\u5B89\u88C5\u6307\u5357:");
|
|
2701
|
+
console.error(" https://github.com/hangox/MasterGoPlugin#chrome-plugin");
|
|
2702
|
+
}
|
|
2703
|
+
process.exit(1);
|
|
2704
|
+
} finally {
|
|
2705
|
+
client.close();
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
// src/cli/commands/visualize.ts
|
|
2710
|
+
import { Command as Command12 } from "commander";
|
|
2711
|
+
import { writeFileSync as writeFileSync9 } from "fs";
|
|
2712
|
+
import { resolve as resolve8, dirname as dirname11 } from "path";
|
|
2713
|
+
import { mkdirSync as mkdirSync10 } from "fs";
|
|
2714
|
+
|
|
2715
|
+
// src/shared/ascii-renderer.ts
|
|
2716
|
+
var defaultRenderOptions = {
|
|
2717
|
+
showId: true,
|
|
2718
|
+
showSize: true,
|
|
2719
|
+
showPadding: true,
|
|
2720
|
+
showRadius: true,
|
|
2721
|
+
showLayout: true,
|
|
2722
|
+
showGap: true,
|
|
2723
|
+
compact: true
|
|
2724
|
+
};
|
|
2725
|
+
function nodeToRenderNode(node) {
|
|
2726
|
+
const renderNode = {
|
|
2727
|
+
id: node.id,
|
|
2728
|
+
name: node.name,
|
|
2729
|
+
type: node.type,
|
|
2730
|
+
width: Math.round(node.width ?? 0),
|
|
2731
|
+
height: Math.round(node.height ?? 0),
|
|
2732
|
+
x: Math.round(node.x ?? 0),
|
|
2733
|
+
y: Math.round(node.y ?? 0)
|
|
2734
|
+
};
|
|
2735
|
+
const cornerRadius = node.cornerRadius;
|
|
2736
|
+
if (cornerRadius && cornerRadius > 0) {
|
|
2737
|
+
renderNode.cornerRadius = Math.round(cornerRadius);
|
|
2738
|
+
}
|
|
2739
|
+
const paddingTop = node.paddingTop;
|
|
2740
|
+
const paddingRight = node.paddingRight;
|
|
2741
|
+
const paddingBottom = node.paddingBottom;
|
|
2742
|
+
const paddingLeft = node.paddingLeft;
|
|
2743
|
+
if (paddingTop || paddingRight || paddingBottom || paddingLeft) {
|
|
2744
|
+
renderNode.padding = {
|
|
2745
|
+
top: Math.round(paddingTop ?? 0),
|
|
2746
|
+
right: Math.round(paddingRight ?? 0),
|
|
2747
|
+
bottom: Math.round(paddingBottom ?? 0),
|
|
2748
|
+
left: Math.round(paddingLeft ?? 0)
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
const flexMode = node.flexMode;
|
|
2752
|
+
if (flexMode === "HORIZONTAL") {
|
|
2753
|
+
renderNode.flexMode = "H";
|
|
2754
|
+
} else if (flexMode === "VERTICAL") {
|
|
2755
|
+
renderNode.flexMode = "V";
|
|
2756
|
+
} else {
|
|
2757
|
+
renderNode.flexMode = "none";
|
|
2758
|
+
}
|
|
2759
|
+
const itemSpacing = node.itemSpacing;
|
|
2760
|
+
if (itemSpacing && itemSpacing > 0) {
|
|
2761
|
+
renderNode.itemSpacing = Math.round(itemSpacing);
|
|
2762
|
+
}
|
|
2763
|
+
if (node.type === "TEXT") {
|
|
2764
|
+
const textStyles = node.textStyles;
|
|
2765
|
+
if (textStyles && textStyles.length > 0) {
|
|
2766
|
+
const firstStyle = textStyles[0];
|
|
2767
|
+
const fontFamily = firstStyle.textStyle?.fontName?.family;
|
|
2768
|
+
const fontSize = firstStyle.textStyle?.fontSize;
|
|
2769
|
+
if (fontFamily && fontSize) {
|
|
2770
|
+
renderNode.font = {
|
|
2771
|
+
family: fontFamily,
|
|
2772
|
+
size: Math.round(fontSize)
|
|
2773
|
+
};
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
if (node.children && node.children.length > 0) {
|
|
2778
|
+
renderNode.children = node.children.map(nodeToRenderNode);
|
|
2779
|
+
}
|
|
2780
|
+
return renderNode;
|
|
2781
|
+
}
|
|
2782
|
+
var CompactRenderer = class {
|
|
2783
|
+
options;
|
|
2784
|
+
treeChars = {
|
|
2785
|
+
branch: "\u251C\u2500 ",
|
|
2786
|
+
lastBranch: "\u2514\u2500 ",
|
|
2787
|
+
vertical: "\u2502 ",
|
|
2788
|
+
space: " "
|
|
2789
|
+
};
|
|
2790
|
+
gapChars = {
|
|
2791
|
+
vertical: "\u2195",
|
|
2792
|
+
horizontal: "\u2194"
|
|
2793
|
+
};
|
|
2794
|
+
constructor(options = {}) {
|
|
2795
|
+
this.options = { ...defaultRenderOptions, ...options, compact: true };
|
|
2796
|
+
}
|
|
2797
|
+
/**
|
|
2798
|
+
* 渲染节点为树形结构
|
|
2799
|
+
*/
|
|
2800
|
+
render(node) {
|
|
2801
|
+
const lines = [];
|
|
2802
|
+
lines.push(this.buildLine(node));
|
|
2803
|
+
if (node.children && node.children.length > 0) {
|
|
2804
|
+
this.renderChildren(node, "", lines);
|
|
2805
|
+
}
|
|
2806
|
+
return lines;
|
|
2807
|
+
}
|
|
2808
|
+
renderChildren(parent, prefix, lines) {
|
|
2809
|
+
if (!parent.children) return;
|
|
2810
|
+
const gapSymbol = parent.flexMode === "H" ? this.gapChars.horizontal : this.gapChars.vertical;
|
|
2811
|
+
parent.children.forEach((child, index) => {
|
|
2812
|
+
const isLastChild = index === parent.children.length - 1;
|
|
2813
|
+
const connector = isLastChild ? this.treeChars.lastBranch : this.treeChars.branch;
|
|
2814
|
+
lines.push(prefix + connector + this.buildLine(child));
|
|
2815
|
+
if (child.children && child.children.length > 0) {
|
|
2816
|
+
const childPrefix = prefix + (isLastChild ? this.treeChars.space : this.treeChars.vertical);
|
|
2817
|
+
this.renderChildren(child, childPrefix, lines);
|
|
2818
|
+
}
|
|
2819
|
+
if (this.options.showGap && parent.itemSpacing && parent.itemSpacing > 0 && index < parent.children.length - 1) {
|
|
2820
|
+
const gapLinePrefix = prefix + this.treeChars.vertical;
|
|
2821
|
+
lines.push(gapLinePrefix + ` ${gapSymbol} gap:${parent.itemSpacing}`);
|
|
2822
|
+
}
|
|
2823
|
+
});
|
|
2824
|
+
}
|
|
2825
|
+
buildLine(node) {
|
|
2826
|
+
const parts = [];
|
|
2827
|
+
let typeName = `${node.type} "${node.name}"`;
|
|
2828
|
+
if (this.options.showId) {
|
|
2829
|
+
typeName += ` [${node.id}]`;
|
|
2830
|
+
}
|
|
2831
|
+
parts.push(typeName);
|
|
2832
|
+
if (this.options.showSize) {
|
|
2833
|
+
parts.push(`${node.width}\xD7${node.height}`);
|
|
2834
|
+
}
|
|
2835
|
+
if (this.options.showRadius && node.cornerRadius) {
|
|
2836
|
+
parts.push(`r:${node.cornerRadius}`);
|
|
2837
|
+
}
|
|
2838
|
+
if (this.options.showPadding && node.padding) {
|
|
2839
|
+
const { top, right, bottom, left } = node.padding;
|
|
2840
|
+
if (top === right && right === bottom && bottom === left && top > 0) {
|
|
2841
|
+
parts.push(`p:${top}`);
|
|
2842
|
+
} else if (top > 0 || right > 0 || bottom > 0 || left > 0) {
|
|
2843
|
+
parts.push(`p:${top}/${right}/${bottom}/${left}`);
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
if (this.options.showLayout && node.flexMode && node.flexMode !== "none") {
|
|
2847
|
+
parts.push(`flex:${node.flexMode}`);
|
|
2848
|
+
}
|
|
2849
|
+
if (this.options.showGap && node.itemSpacing && node.itemSpacing > 0) {
|
|
2850
|
+
parts.push(`gap:${node.itemSpacing}`);
|
|
2851
|
+
}
|
|
2852
|
+
if (node.font) {
|
|
2853
|
+
parts.push(`font:${node.font.family}/${node.font.size}px`);
|
|
2854
|
+
}
|
|
2855
|
+
parts.push(`@(${node.x},${node.y})`);
|
|
2856
|
+
return parts.join(" ");
|
|
2857
|
+
}
|
|
2858
|
+
};
|
|
2859
|
+
var BoxRenderer = class {
|
|
2860
|
+
options;
|
|
2861
|
+
boxChars = {
|
|
2862
|
+
topLeft: "\u250C",
|
|
2863
|
+
topRight: "\u2510",
|
|
2864
|
+
bottomLeft: "\u2514",
|
|
2865
|
+
bottomRight: "\u2518",
|
|
2866
|
+
horizontal: "\u2500",
|
|
2867
|
+
vertical: "\u2502",
|
|
2868
|
+
teeRight: "\u251C",
|
|
2869
|
+
teeLeft: "\u2524"
|
|
2870
|
+
};
|
|
2871
|
+
gapChars = {
|
|
2872
|
+
vertical: "\u2195",
|
|
2873
|
+
horizontal: "\u2194"
|
|
2874
|
+
};
|
|
2875
|
+
/** 固定总宽度,确保右边框对齐 */
|
|
2876
|
+
totalWidth = 80;
|
|
2877
|
+
constructor(options = {}) {
|
|
2878
|
+
this.options = { ...defaultRenderOptions, ...options, compact: false };
|
|
2879
|
+
}
|
|
2880
|
+
/**
|
|
2881
|
+
* 渲染节点为框图
|
|
2882
|
+
*/
|
|
2883
|
+
render(node) {
|
|
2884
|
+
this.totalWidth = Math.max(80, this.calculateMaxWidth(node, 0));
|
|
2885
|
+
return this.renderNode(node, 0);
|
|
2886
|
+
}
|
|
2887
|
+
/**
|
|
2888
|
+
* 计算整棵树需要的最大宽度
|
|
2889
|
+
*/
|
|
2890
|
+
calculateMaxWidth(node, indent) {
|
|
2891
|
+
const indentWidth = indent * 4;
|
|
2892
|
+
const title = this.buildTitle(node);
|
|
2893
|
+
const props = this.buildPropsLine(node);
|
|
2894
|
+
const nodeWidth = Math.max(title.length + 6, props.length + 6) + indentWidth;
|
|
2895
|
+
let maxWidth = nodeWidth;
|
|
2896
|
+
if (node.children) {
|
|
2897
|
+
for (const child of node.children) {
|
|
2898
|
+
const childWidth = this.calculateMaxWidth(child, indent + 1);
|
|
2899
|
+
maxWidth = Math.max(maxWidth, childWidth);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
return maxWidth;
|
|
2903
|
+
}
|
|
2904
|
+
renderNode(node, indent) {
|
|
2905
|
+
const lines = [];
|
|
2906
|
+
const indentWidth = indent * 4;
|
|
2907
|
+
const contentWidth = this.totalWidth - indentWidth - 2;
|
|
2908
|
+
const indentStr = " ".repeat(indent);
|
|
2909
|
+
const title = this.buildTitle(node);
|
|
2910
|
+
const props = this.buildPropsLine(node);
|
|
2911
|
+
const titlePadding = contentWidth - title.length - 4;
|
|
2912
|
+
lines.push(
|
|
2913
|
+
indentStr + this.boxChars.topLeft + this.boxChars.horizontal + " " + title + " " + this.boxChars.horizontal.repeat(Math.max(0, titlePadding)) + this.boxChars.topRight
|
|
2914
|
+
);
|
|
2915
|
+
lines.push(
|
|
2916
|
+
indentStr + this.boxChars.vertical + " " + props.padEnd(contentWidth - 2) + this.boxChars.vertical
|
|
2917
|
+
);
|
|
2918
|
+
lines.push(
|
|
2919
|
+
indentStr + this.boxChars.teeRight + this.boxChars.horizontal.repeat(contentWidth) + this.boxChars.teeLeft
|
|
2920
|
+
);
|
|
2921
|
+
if (node.children && node.children.length > 0) {
|
|
2922
|
+
lines.push(
|
|
2923
|
+
indentStr + this.boxChars.vertical + " ".repeat(contentWidth) + this.boxChars.vertical
|
|
2924
|
+
);
|
|
2925
|
+
const gapSymbol = node.flexMode === "H" ? this.gapChars.horizontal : this.gapChars.vertical;
|
|
2926
|
+
node.children.forEach((child, index) => {
|
|
2927
|
+
const childLines = this.renderNode(child, indent + 1);
|
|
2928
|
+
for (const childLine of childLines) {
|
|
2929
|
+
const paddedLine = " " + childLine.padEnd(contentWidth - 2);
|
|
2930
|
+
lines.push(indentStr + this.boxChars.vertical + paddedLine + this.boxChars.vertical);
|
|
2931
|
+
}
|
|
2932
|
+
if (this.options.showGap && node.itemSpacing && node.itemSpacing > 0 && index < node.children.length - 1) {
|
|
2933
|
+
const gapText = `${gapSymbol} gap:${node.itemSpacing}`;
|
|
2934
|
+
const gapPadding = Math.floor((contentWidth - gapText.length) / 2);
|
|
2935
|
+
const gapLine = " ".repeat(gapPadding) + gapText;
|
|
2936
|
+
lines.push(
|
|
2937
|
+
indentStr + this.boxChars.vertical + gapLine.padEnd(contentWidth) + this.boxChars.vertical
|
|
2938
|
+
);
|
|
2939
|
+
} else {
|
|
2940
|
+
lines.push(
|
|
2941
|
+
indentStr + this.boxChars.vertical + " ".repeat(contentWidth) + this.boxChars.vertical
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
});
|
|
2945
|
+
}
|
|
2946
|
+
lines.push(
|
|
2947
|
+
indentStr + this.boxChars.bottomLeft + this.boxChars.horizontal.repeat(contentWidth) + this.boxChars.bottomRight
|
|
2948
|
+
);
|
|
2949
|
+
return lines;
|
|
2950
|
+
}
|
|
2951
|
+
buildTitle(node) {
|
|
2952
|
+
let title = `${node.type} "${node.name}"`;
|
|
2953
|
+
if (this.options.showId) {
|
|
2954
|
+
title += ` [${node.id}]`;
|
|
2955
|
+
}
|
|
2956
|
+
return title;
|
|
2957
|
+
}
|
|
2958
|
+
buildPropsLine(node) {
|
|
2959
|
+
const parts = [];
|
|
2960
|
+
if (this.options.showSize) {
|
|
2961
|
+
parts.push(`${node.width}\xD7${node.height}`);
|
|
2962
|
+
}
|
|
2963
|
+
if (this.options.showRadius && node.cornerRadius) {
|
|
2964
|
+
parts.push(`r:${node.cornerRadius}`);
|
|
2965
|
+
}
|
|
2966
|
+
if (this.options.showPadding && node.padding) {
|
|
2967
|
+
const { top, right, bottom, left } = node.padding;
|
|
2968
|
+
if (top === right && right === bottom && bottom === left && top > 0) {
|
|
2969
|
+
parts.push(`p:${top}`);
|
|
2970
|
+
} else if (top > 0 || right > 0 || bottom > 0 || left > 0) {
|
|
2971
|
+
parts.push(`p:${top}/${right}/${bottom}/${left}`);
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
if (this.options.showLayout && node.flexMode && node.flexMode !== "none") {
|
|
2975
|
+
parts.push(`flex:${node.flexMode}`);
|
|
2976
|
+
}
|
|
2977
|
+
if (this.options.showGap && node.itemSpacing && node.itemSpacing > 0) {
|
|
2978
|
+
parts.push(`gap:${node.itemSpacing}`);
|
|
2979
|
+
}
|
|
2980
|
+
if (node.font) {
|
|
2981
|
+
parts.push(`font:${node.font.family}/${node.font.size}px`);
|
|
2982
|
+
}
|
|
2983
|
+
parts.push(`pos:(${node.x},${node.y})`);
|
|
2984
|
+
return parts.join(" ");
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
function renderAscii(node, options = {}) {
|
|
2988
|
+
const renderNode = nodeToRenderNode(node);
|
|
2989
|
+
const mergedOptions = { ...defaultRenderOptions, ...options };
|
|
2990
|
+
let lines;
|
|
2991
|
+
if (mergedOptions.compact) {
|
|
2992
|
+
const renderer = new CompactRenderer(mergedOptions);
|
|
2993
|
+
lines = renderer.render(renderNode);
|
|
2994
|
+
} else {
|
|
2995
|
+
const renderer = new BoxRenderer(mergedOptions);
|
|
2996
|
+
lines = renderer.render(renderNode);
|
|
2997
|
+
}
|
|
2998
|
+
return lines.join("\n");
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
// src/cli/commands/visualize.ts
|
|
3002
|
+
function createVisualizeCommand() {
|
|
3003
|
+
return new Command12("visualize").description("\u5C06 MasterGo \u8BBE\u8BA1\u7A3F\u8282\u70B9\u6E32\u67D3\u4E3A ASCII \u793A\u610F\u56FE").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5").option("--output <path>", "\u8F93\u51FA\u6587\u4EF6\u8DEF\u5F84\uFF08\u4E0D\u6307\u5B9A\u5219\u8F93\u51FA\u5230\u7EC8\u7AEF\uFF09").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6", "3").option("--no-show-id", "\u9690\u85CF\u8282\u70B9 ID").option("--no-show-size", "\u9690\u85CF\u5C3A\u5BF8").option("--no-show-padding", "\u9690\u85CF padding").option("--no-show-radius", "\u9690\u85CF\u5706\u89D2").option("--no-show-layout", "\u9690\u85CF\u5E03\u5C40\u65B9\u5411").option("--no-show-gap", "\u9690\u85CF gap \u53EF\u89C6\u5316").option("--no-compact", "\u4F7F\u7528\u6846\u56FE\u6A21\u5F0F\uFF08\u4EBA\u7C7B\u9605\u8BFB\u4F18\u5316\uFF09").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
|
|
3004
|
+
await handleVisualize(options);
|
|
3005
|
+
});
|
|
3006
|
+
}
|
|
3007
|
+
async function handleVisualize(options) {
|
|
3008
|
+
const parsed = parseMgpLink(options.link);
|
|
3009
|
+
if (!parsed) {
|
|
3010
|
+
console.error(`\u9519\u8BEF [${"E010" /* INVALID_LINK */}]: \u65E0\u6548\u7684 mgp:// \u94FE\u63A5\u683C\u5F0F`);
|
|
3011
|
+
console.error(`\u63D0\u4F9B\u7684\u94FE\u63A5: ${options.link}`);
|
|
3012
|
+
console.error(`\u671F\u671B\u683C\u5F0F:`);
|
|
3013
|
+
console.error(` \u8282\u70B9\u94FE\u63A5: mgp://[mastergo_page_url]?nodeId=[\u8282\u70B9ID]`);
|
|
3014
|
+
console.error(` \u9875\u9762\u94FE\u63A5: mgp://[mastergo_page_url]?pageId=[\u9875\u9762ID]`);
|
|
3015
|
+
process.exit(1);
|
|
3016
|
+
}
|
|
3017
|
+
const { pageUrl, nodeId, pageId } = parsed;
|
|
3018
|
+
const isPageLink = !!pageId;
|
|
3019
|
+
const client = new MGClient({
|
|
3020
|
+
noAutoStart: options.noAutoStart,
|
|
3021
|
+
noRetry: options.noRetry
|
|
3022
|
+
});
|
|
3023
|
+
try {
|
|
3024
|
+
await client.connect();
|
|
3025
|
+
let data;
|
|
3026
|
+
if (isPageLink) {
|
|
3027
|
+
const params = {
|
|
3028
|
+
pageId,
|
|
3029
|
+
maxDepth: parseInt(options.maxDepth || "3", 10),
|
|
3030
|
+
includeInvisible: false
|
|
3031
|
+
};
|
|
3032
|
+
data = await client.requestWithRetry("get_page_by_id" /* GET_PAGE_BY_ID */, params, pageUrl);
|
|
3033
|
+
} else {
|
|
3034
|
+
const params = {
|
|
3035
|
+
nodeId,
|
|
3036
|
+
maxDepth: parseInt(options.maxDepth || "3", 10),
|
|
3037
|
+
includeInvisible: false
|
|
3038
|
+
};
|
|
3039
|
+
data = await client.requestWithRetry("get_node_by_id" /* GET_NODE_BY_ID */, params, pageUrl);
|
|
3040
|
+
}
|
|
3041
|
+
const renderOptions = {
|
|
3042
|
+
showId: options.showId !== false,
|
|
3043
|
+
showSize: options.showSize !== false,
|
|
3044
|
+
showPadding: options.showPadding !== false,
|
|
3045
|
+
showRadius: options.showRadius !== false,
|
|
3046
|
+
showLayout: options.showLayout !== false,
|
|
3047
|
+
showGap: options.showGap !== false,
|
|
3048
|
+
compact: options.compact !== false
|
|
3049
|
+
};
|
|
3050
|
+
const asciiOutput = renderAscii(data, renderOptions);
|
|
3051
|
+
if (options.output) {
|
|
3052
|
+
const outputPath = resolve8(options.output);
|
|
3053
|
+
const outputDir = dirname11(outputPath);
|
|
3054
|
+
mkdirSync10(outputDir, { recursive: true });
|
|
3055
|
+
writeFileSync9(outputPath, asciiOutput, "utf-8");
|
|
3056
|
+
console.log(`ASCII \u793A\u610F\u56FE\u5DF2\u4FDD\u5B58\u5230: ${outputPath}`);
|
|
3057
|
+
console.log(`Link: ${options.link}`);
|
|
3058
|
+
console.log(`\u6A21\u5F0F: ${options.compact ? "\u7D27\u51D1" : "\u6807\u51C6"}`);
|
|
3059
|
+
console.log(`\u904D\u5386\u6DF1\u5EA6: ${options.maxDepth || "3"}`);
|
|
3060
|
+
} else {
|
|
3061
|
+
console.log(asciiOutput);
|
|
3062
|
+
}
|
|
3063
|
+
} catch (error) {
|
|
3064
|
+
if (error instanceof MGError) {
|
|
3065
|
+
console.error(`\u9519\u8BEF [${error.code}]: ${error.message}`);
|
|
3066
|
+
} else {
|
|
3067
|
+
console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
|
|
3068
|
+
}
|
|
3069
|
+
process.exit(1);
|
|
3070
|
+
} finally {
|
|
3071
|
+
client.close();
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
|
|
2128
3075
|
// src/cli/index.ts
|
|
2129
|
-
var program = new
|
|
3076
|
+
var program = new Command13();
|
|
2130
3077
|
program.name("mg-cli").description("MasterGo CLI \u5DE5\u5177 - \u7528\u4E8E Claude Code \u4E0E MasterGo \u901A\u4FE1").version("1.0.0");
|
|
2131
3078
|
program.addCommand(createServerCommand());
|
|
2132
3079
|
program.addCommand(createGetNodeByIdCommand());
|
|
@@ -2136,5 +3083,10 @@ program.addCommand(createExportImageCommand());
|
|
|
2136
3083
|
program.addCommand(createExecuteCodeCommand());
|
|
2137
3084
|
program.addCommand(createGetAllPagesCommand());
|
|
2138
3085
|
program.addCommand(createGetNodeForSpaceCommand());
|
|
3086
|
+
program.addCommand(createListExtensionsCommand());
|
|
3087
|
+
program.addCommand(createOpenPageCommand());
|
|
3088
|
+
program.addCommand(createNavigateToNodeCommand());
|
|
3089
|
+
program.addCommand(createVisualizeCommand());
|
|
3090
|
+
checkForUpdates();
|
|
2139
3091
|
program.parse();
|
|
2140
3092
|
//# sourceMappingURL=cli.js.map
|