@hangox/mg-cli 1.0.2 → 1.0.5
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/VERSION +1 -0
- package/dist/cli.js +551 -134
- package/dist/cli.js.map +1 -1
- package/dist/daemon-runner.js +106 -4
- package/dist/daemon-runner.js.map +1 -1
- package/dist/{index-DNrszrq9.d.ts → index--AigFaD9.d.ts} +61 -1
- package/dist/index.d.ts +30 -3
- package/dist/index.js +237 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +104 -5
- package/dist/server.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ServerInfo } from './index
|
|
2
|
-
export {
|
|
1
|
+
import { S as ServerInfo, N as NodeInfo, a as SpaceNodeInfo } from './index--AigFaD9.js';
|
|
2
|
+
export { F as AllPagesInfo, B as BaseMessage, C as CONFIG_DIR, y as CliOptions, I as ConnectedPageInfo, v as ConnectionInfo, U as ConnectionManager, j as ConnectionType, D as DEFAULT_PORT, E as ErrorCode, r as ErrorInfo, m as ErrorMessages, l as ErrorNames, x as ExportImageParams, w as GetAllNodesParams, G as GetNodeParams, H as HEARTBEAT_INTERVAL, f as HEARTBEAT_TIMEOUT, L as LOG_DIR, Z as LogLevel, X as Logger, _ as LoggerOptions, M as MAX_PORT_ATTEMPTS, i as MAX_RETRY_COUNT, n as MGError, K as MGServer, V as ManagedWebSocket, k as MessageType, A as MgPageInfo, O as OutputFormatter, b as PORT_RANGE_END, P as PORT_RANGE_START, c as PORT_SCAN_TIMEOUT, t as PingMessage, u as PongMessage, R as REQUEST_TIMEOUT, h as RETRY_INTERVALS, z as RGBA, s as RegisterMessage, W as RequestHandler, p as RequestMessage, q as ResponseMessage, d as SERVER_INFO_FILE, e as SERVER_LOG_FILE, g as SERVER_START_TIMEOUT, T as ServerOptions, J as ServerStatusResponse, o as createError, Y as createLogger, Q as createServer } from './index--AigFaD9.js';
|
|
3
3
|
import 'ws';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -125,5 +125,32 @@ declare function extractFileIdFromMgpLink(link: string): string | null;
|
|
|
125
125
|
* @returns fileId 或 null
|
|
126
126
|
*/
|
|
127
127
|
declare function extractFileId(input: string): string | null;
|
|
128
|
+
/**
|
|
129
|
+
* 四舍五入到一位小数
|
|
130
|
+
* 25.666667938232422 -> 25.7
|
|
131
|
+
*/
|
|
132
|
+
declare function roundToOneDecimal(value: number): number;
|
|
133
|
+
/**
|
|
134
|
+
* MasterGo 节点属性默认值
|
|
135
|
+
* 基于官方文档定义,当值等于默认值时可以省略以减少 JSON 体积
|
|
136
|
+
*/
|
|
137
|
+
declare const NODE_DEFAULTS: Record<string, unknown>;
|
|
138
|
+
/**
|
|
139
|
+
* 精简节点数据,移除等于默认值的字段
|
|
140
|
+
* 递归处理 children 数组
|
|
141
|
+
*
|
|
142
|
+
* @param node 原始节点数据
|
|
143
|
+
* @returns 精简后的节点数据
|
|
144
|
+
*/
|
|
145
|
+
declare function trimNodeDefaults<T extends Record<string, unknown>>(node: T): T;
|
|
146
|
+
/**
|
|
147
|
+
* 提取节点的空间信息
|
|
148
|
+
* 只保留 id、name、x、y、width、height 和 children 字段
|
|
149
|
+
* 用于让 AI 以最少的字段理解节点的空间布局关系
|
|
150
|
+
*
|
|
151
|
+
* @param node 原始节点数据
|
|
152
|
+
* @returns 精简的空间节点信息
|
|
153
|
+
*/
|
|
154
|
+
declare function extractSpaceInfo(node: NodeInfo): SpaceNodeInfo;
|
|
128
155
|
|
|
129
|
-
export { ServerInfo, deleteServerInfo, ensureConfigDir, ensureDir, ensureOutputDir, extractFileId, extractFileIdFromMgpLink, extractFileIdFromUrl, formatDuration, formatFileSize, formatLogTime, generateId, generateMgpLink, getCurrentISOTime, isDesignPageUrl, isProcessRunning, killProcess, normalizePageUrl, parseMgpLink, readServerInfo, resolveOutputPath, writeServerInfo };
|
|
156
|
+
export { NODE_DEFAULTS, NodeInfo, ServerInfo, SpaceNodeInfo, deleteServerInfo, ensureConfigDir, ensureDir, ensureOutputDir, extractFileId, extractFileIdFromMgpLink, extractFileIdFromUrl, extractSpaceInfo, formatDuration, formatFileSize, formatLogTime, generateId, generateMgpLink, getCurrentISOTime, isDesignPageUrl, isProcessRunning, killProcess, normalizePageUrl, parseMgpLink, readServerInfo, resolveOutputPath, roundToOneDecimal, trimNodeDefaults, writeServerInfo };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
32
32
|
MessageType2["EXPORT_IMAGE"] = "export_image";
|
|
33
33
|
MessageType2["EXECUTE_CODE"] = "execute_code";
|
|
34
34
|
MessageType2["GET_ALL_PAGES"] = "get_all_pages";
|
|
35
|
+
MessageType2["GET_SERVER_STATUS"] = "get_server_status";
|
|
35
36
|
MessageType2["RESPONSE"] = "response";
|
|
36
37
|
MessageType2["ERROR"] = "error";
|
|
37
38
|
return MessageType2;
|
|
@@ -317,6 +318,152 @@ function extractFileId(input) {
|
|
|
317
318
|
}
|
|
318
319
|
return extractFileIdFromUrl(trimmed);
|
|
319
320
|
}
|
|
321
|
+
var NUMERIC_FIELDS = [
|
|
322
|
+
"x",
|
|
323
|
+
"y",
|
|
324
|
+
"width",
|
|
325
|
+
"height",
|
|
326
|
+
"rotation",
|
|
327
|
+
"opacity",
|
|
328
|
+
"cornerRadius",
|
|
329
|
+
"topLeftRadius",
|
|
330
|
+
"topRightRadius",
|
|
331
|
+
"bottomLeftRadius",
|
|
332
|
+
"bottomRightRadius",
|
|
333
|
+
"strokeWeight",
|
|
334
|
+
"strokeTopWeight",
|
|
335
|
+
"strokeLeftWeight",
|
|
336
|
+
"strokeBottomWeight",
|
|
337
|
+
"strokeRightWeight",
|
|
338
|
+
"paddingTop",
|
|
339
|
+
"paddingRight",
|
|
340
|
+
"paddingBottom",
|
|
341
|
+
"paddingLeft",
|
|
342
|
+
"itemSpacing",
|
|
343
|
+
"crossAxisSpacing",
|
|
344
|
+
"flexGrow"
|
|
345
|
+
];
|
|
346
|
+
function roundToOneDecimal(value) {
|
|
347
|
+
return Math.round(value * 10) / 10;
|
|
348
|
+
}
|
|
349
|
+
var NODE_DEFAULTS = {
|
|
350
|
+
// Scene Node 属性
|
|
351
|
+
visible: true,
|
|
352
|
+
isVisible: true,
|
|
353
|
+
isLocked: false,
|
|
354
|
+
// Blend 属性
|
|
355
|
+
opacity: 1,
|
|
356
|
+
blendMode: "NORMAL",
|
|
357
|
+
isMask: false,
|
|
358
|
+
isMaskOutline: false,
|
|
359
|
+
isMaskVisible: false,
|
|
360
|
+
effectStyleId: "",
|
|
361
|
+
// Geometry 属性
|
|
362
|
+
strokeStyle: "SOLID",
|
|
363
|
+
strokeWeight: 0,
|
|
364
|
+
strokeTopWeight: 0,
|
|
365
|
+
strokeLeftWeight: 0,
|
|
366
|
+
strokeBottomWeight: 0,
|
|
367
|
+
strokeRightWeight: 0,
|
|
368
|
+
strokeAlign: "CENTER",
|
|
369
|
+
strokeCap: "NONE",
|
|
370
|
+
strokeJoin: "MITER",
|
|
371
|
+
dashCap: "NONE",
|
|
372
|
+
fillStyleId: "",
|
|
373
|
+
strokeStyleId: "",
|
|
374
|
+
// Corner 属性
|
|
375
|
+
cornerSmooth: 0,
|
|
376
|
+
cornerRadius: 0,
|
|
377
|
+
topLeftRadius: 0,
|
|
378
|
+
topRightRadius: 0,
|
|
379
|
+
bottomLeftRadius: 0,
|
|
380
|
+
bottomRightRadius: 0,
|
|
381
|
+
// Layout 属性
|
|
382
|
+
rotation: 0,
|
|
383
|
+
flexGrow: 0,
|
|
384
|
+
alignSelf: "INHERIT",
|
|
385
|
+
layoutPositioning: "AUTO",
|
|
386
|
+
constrainProportions: false,
|
|
387
|
+
// 容器专属属性 (FrameNode)
|
|
388
|
+
flexMode: "NONE",
|
|
389
|
+
flexWrap: "NO_WRAP",
|
|
390
|
+
itemSpacing: 0,
|
|
391
|
+
crossAxisSpacing: 0,
|
|
392
|
+
paddingTop: 0,
|
|
393
|
+
paddingRight: 0,
|
|
394
|
+
paddingBottom: 0,
|
|
395
|
+
paddingLeft: 0,
|
|
396
|
+
clipsContent: false,
|
|
397
|
+
itemReverseZIndex: false,
|
|
398
|
+
strokesIncludedInLayout: false,
|
|
399
|
+
// 其他属性
|
|
400
|
+
componentPropertyReferences: null
|
|
401
|
+
};
|
|
402
|
+
var EMPTY_ARRAY_FIELDS = [
|
|
403
|
+
"fills",
|
|
404
|
+
"strokes",
|
|
405
|
+
"effects",
|
|
406
|
+
"strokeDashes",
|
|
407
|
+
"exportSettings",
|
|
408
|
+
"reactions",
|
|
409
|
+
"attachedConnectors"
|
|
410
|
+
];
|
|
411
|
+
function isEmptyArray(value) {
|
|
412
|
+
return Array.isArray(value) && value.length === 0;
|
|
413
|
+
}
|
|
414
|
+
function isEqual(a, b) {
|
|
415
|
+
if (a === b) return true;
|
|
416
|
+
if (a === null || b === null) return a === b;
|
|
417
|
+
if (typeof a !== typeof b) return false;
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
function trimNodeDefaults(node) {
|
|
421
|
+
const result = {};
|
|
422
|
+
for (const [key, value] of Object.entries(node)) {
|
|
423
|
+
if (key === "children" && Array.isArray(value)) {
|
|
424
|
+
const trimmedChildren = value.map(
|
|
425
|
+
(child) => typeof child === "object" && child !== null ? trimNodeDefaults(child) : child
|
|
426
|
+
);
|
|
427
|
+
if (trimmedChildren.length > 0) {
|
|
428
|
+
result[key] = trimmedChildren;
|
|
429
|
+
}
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (EMPTY_ARRAY_FIELDS.includes(key) && isEmptyArray(value)) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
if (NUMERIC_FIELDS.includes(key) && typeof value === "number") {
|
|
436
|
+
const roundedValue = roundToOneDecimal(value);
|
|
437
|
+
if (key in NODE_DEFAULTS && isEqual(roundedValue, NODE_DEFAULTS[key])) {
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
result[key] = roundedValue;
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
if (key in NODE_DEFAULTS) {
|
|
444
|
+
const defaultValue = NODE_DEFAULTS[key];
|
|
445
|
+
if (isEqual(value, defaultValue)) {
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
result[key] = value;
|
|
450
|
+
}
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
function extractSpaceInfo(node) {
|
|
454
|
+
const result = {
|
|
455
|
+
id: node.id,
|
|
456
|
+
name: node.name,
|
|
457
|
+
x: roundToOneDecimal(typeof node.x === "number" ? node.x : 0),
|
|
458
|
+
y: roundToOneDecimal(typeof node.y === "number" ? node.y : 0),
|
|
459
|
+
width: roundToOneDecimal(typeof node.width === "number" ? node.width : 0),
|
|
460
|
+
height: roundToOneDecimal(typeof node.height === "number" ? node.height : 0)
|
|
461
|
+
};
|
|
462
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
463
|
+
result.children = node.children.map((child) => extractSpaceInfo(child));
|
|
464
|
+
}
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
320
467
|
|
|
321
468
|
// src/server/websocket-server.ts
|
|
322
469
|
import { WebSocketServer } from "ws";
|
|
@@ -687,6 +834,54 @@ var RequestHandler = class {
|
|
|
687
834
|
}
|
|
688
835
|
};
|
|
689
836
|
|
|
837
|
+
// src/shared/version.ts
|
|
838
|
+
import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
|
|
839
|
+
import { fileURLToPath } from "url";
|
|
840
|
+
import { dirname as dirname3, join as join2 } from "path";
|
|
841
|
+
var cachedVersion = null;
|
|
842
|
+
function getVersion() {
|
|
843
|
+
if (cachedVersion !== null) {
|
|
844
|
+
return cachedVersion;
|
|
845
|
+
}
|
|
846
|
+
try {
|
|
847
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
848
|
+
const currentDir = dirname3(currentFile);
|
|
849
|
+
const versionFilePaths = [
|
|
850
|
+
join2(currentDir, "..", "VERSION"),
|
|
851
|
+
// dist/xxx.js -> ../VERSION
|
|
852
|
+
join2(currentDir, "..", "..", "VERSION")
|
|
853
|
+
// src/shared/version.ts -> ../../VERSION
|
|
854
|
+
];
|
|
855
|
+
for (const versionFilePath of versionFilePaths) {
|
|
856
|
+
if (existsSync3(versionFilePath)) {
|
|
857
|
+
const version = readFileSync2(versionFilePath, "utf-8").trim();
|
|
858
|
+
if (version) {
|
|
859
|
+
cachedVersion = version;
|
|
860
|
+
return cachedVersion;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
const packageJsonPaths = [
|
|
865
|
+
join2(currentDir, "..", "package.json"),
|
|
866
|
+
join2(currentDir, "..", "..", "package.json")
|
|
867
|
+
];
|
|
868
|
+
for (const packageJsonPath of packageJsonPaths) {
|
|
869
|
+
if (existsSync3(packageJsonPath)) {
|
|
870
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
871
|
+
if (packageJson.name === "@hangox/mg-cli") {
|
|
872
|
+
cachedVersion = packageJson.version || "0.0.0";
|
|
873
|
+
return cachedVersion;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
cachedVersion = "0.0.0";
|
|
878
|
+
return cachedVersion;
|
|
879
|
+
} catch {
|
|
880
|
+
cachedVersion = "0.0.0";
|
|
881
|
+
return cachedVersion;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
690
885
|
// src/server/websocket-server.ts
|
|
691
886
|
var MGServer = class {
|
|
692
887
|
wss = null;
|
|
@@ -695,6 +890,7 @@ var MGServer = class {
|
|
|
695
890
|
requestHandler;
|
|
696
891
|
port;
|
|
697
892
|
isRunning = false;
|
|
893
|
+
startedAt = null;
|
|
698
894
|
constructor(options = {}) {
|
|
699
895
|
this.port = options.port || DEFAULT_PORT;
|
|
700
896
|
this.logger = options.logger || createLogger();
|
|
@@ -714,6 +910,7 @@ var MGServer = class {
|
|
|
714
910
|
this.wss.on("listening", () => {
|
|
715
911
|
this.port = port;
|
|
716
912
|
this.isRunning = true;
|
|
913
|
+
this.startedAt = /* @__PURE__ */ new Date();
|
|
717
914
|
this.logger.info(`Server \u542F\u52A8\u6210\u529F\uFF0C\u76D1\u542C\u7AEF\u53E3: ${port}`);
|
|
718
915
|
this.connectionManager.startHeartbeatCheck(HEARTBEAT_INTERVAL);
|
|
719
916
|
resolve2(port);
|
|
@@ -814,7 +1011,8 @@ var MGServer = class {
|
|
|
814
1011
|
success: true,
|
|
815
1012
|
data: {
|
|
816
1013
|
connectionId: managedWs.connectionId,
|
|
817
|
-
pageUrl
|
|
1014
|
+
pageUrl,
|
|
1015
|
+
serverVersion: getVersion()
|
|
818
1016
|
}
|
|
819
1017
|
};
|
|
820
1018
|
ws.send(JSON.stringify(ack));
|
|
@@ -828,6 +1026,9 @@ var MGServer = class {
|
|
|
828
1026
|
case "ping" /* PING */:
|
|
829
1027
|
this.handlePing(ws, message);
|
|
830
1028
|
break;
|
|
1029
|
+
case "get_server_status" /* GET_SERVER_STATUS */:
|
|
1030
|
+
this.handleGetServerStatus(ws, message);
|
|
1031
|
+
break;
|
|
831
1032
|
case "response" /* RESPONSE */:
|
|
832
1033
|
case "error" /* ERROR */:
|
|
833
1034
|
this.requestHandler.handleResponse(message);
|
|
@@ -849,6 +1050,37 @@ var MGServer = class {
|
|
|
849
1050
|
};
|
|
850
1051
|
ws.send(JSON.stringify(pong));
|
|
851
1052
|
}
|
|
1053
|
+
/**
|
|
1054
|
+
* 处理 Server 状态查询
|
|
1055
|
+
*/
|
|
1056
|
+
handleGetServerStatus(ws, message) {
|
|
1057
|
+
const providers = this.connectionManager.getAllProviders();
|
|
1058
|
+
const stats = this.connectionManager.getStats();
|
|
1059
|
+
const connectedPages = providers.map((info) => ({
|
|
1060
|
+
pageUrl: info.pageUrl || "",
|
|
1061
|
+
connectedAt: info.connectedAt.toISOString(),
|
|
1062
|
+
lastActiveAt: info.lastActiveAt.toISOString()
|
|
1063
|
+
}));
|
|
1064
|
+
const uptimeMs = this.startedAt ? Date.now() - this.startedAt.getTime() : 0;
|
|
1065
|
+
const statusData = {
|
|
1066
|
+
running: this.isRunning,
|
|
1067
|
+
port: this.port,
|
|
1068
|
+
pid: process.pid,
|
|
1069
|
+
startedAt: this.startedAt?.toISOString() || "",
|
|
1070
|
+
uptime: formatDuration(uptimeMs),
|
|
1071
|
+
version: getVersion(),
|
|
1072
|
+
stats,
|
|
1073
|
+
connectedPages
|
|
1074
|
+
};
|
|
1075
|
+
const response = {
|
|
1076
|
+
id: message.id || "",
|
|
1077
|
+
type: "response" /* RESPONSE */,
|
|
1078
|
+
success: true,
|
|
1079
|
+
data: statusData
|
|
1080
|
+
};
|
|
1081
|
+
ws.send(JSON.stringify(response));
|
|
1082
|
+
this.logger.info("\u8FD4\u56DE Server \u72B6\u6001\u4FE1\u606F");
|
|
1083
|
+
}
|
|
852
1084
|
/**
|
|
853
1085
|
* 停止服务器
|
|
854
1086
|
*/
|
|
@@ -913,6 +1145,7 @@ export {
|
|
|
913
1145
|
MGError,
|
|
914
1146
|
MGServer,
|
|
915
1147
|
MessageType,
|
|
1148
|
+
NODE_DEFAULTS,
|
|
916
1149
|
PORT_RANGE_END,
|
|
917
1150
|
PORT_RANGE_START,
|
|
918
1151
|
PORT_SCAN_TIMEOUT,
|
|
@@ -932,6 +1165,7 @@ export {
|
|
|
932
1165
|
extractFileId,
|
|
933
1166
|
extractFileIdFromMgpLink,
|
|
934
1167
|
extractFileIdFromUrl,
|
|
1168
|
+
extractSpaceInfo,
|
|
935
1169
|
formatDuration,
|
|
936
1170
|
formatFileSize,
|
|
937
1171
|
formatLogTime,
|
|
@@ -945,6 +1179,8 @@ export {
|
|
|
945
1179
|
parseMgpLink,
|
|
946
1180
|
readServerInfo,
|
|
947
1181
|
resolveOutputPath,
|
|
1182
|
+
roundToOneDecimal,
|
|
1183
|
+
trimNodeDefaults,
|
|
948
1184
|
writeServerInfo
|
|
949
1185
|
};
|
|
950
1186
|
//# sourceMappingURL=index.js.map
|