@hangox/mg-cli 1.0.5 → 1.0.7
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/dist/cli.js +252 -98
- package/dist/cli.js.map +1 -1
- package/dist/daemon-runner.js +58 -40
- package/dist/daemon-runner.js.map +1 -1
- package/dist/{index--AigFaD9.d.ts → index-DUQN5gSR.d.ts} +169 -11
- package/dist/index.d.ts +15 -5
- package/dist/index.js +103 -54
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +58 -40
- package/dist/server.js.map +1 -1
- package/package.json +4 -4
- package/VERSION +0 -1
|
@@ -3,12 +3,26 @@ import { WebSocket } from 'ws';
|
|
|
3
3
|
/**
|
|
4
4
|
* MG Plugin 常量定义
|
|
5
5
|
*/
|
|
6
|
-
/**
|
|
7
|
-
declare const
|
|
8
|
-
/**
|
|
9
|
-
declare const
|
|
10
|
-
/**
|
|
11
|
-
declare const
|
|
6
|
+
/** 是否为开发模式(通过环境变量 MG_DEV_MODE=true 设置) */
|
|
7
|
+
declare const IS_DEV_MODE: boolean;
|
|
8
|
+
/** 生产环境默认端口 */
|
|
9
|
+
declare const PROD_DEFAULT_PORT = 9527;
|
|
10
|
+
/** 生产环境端口范围:起始 */
|
|
11
|
+
declare const PROD_PORT_RANGE_START = 9527;
|
|
12
|
+
/** 生产环境端口范围:结束 */
|
|
13
|
+
declare const PROD_PORT_RANGE_END = 9536;
|
|
14
|
+
/** 开发环境默认端口 */
|
|
15
|
+
declare const DEV_DEFAULT_PORT = 19527;
|
|
16
|
+
/** 开发环境端口范围:起始 */
|
|
17
|
+
declare const DEV_PORT_RANGE_START = 19527;
|
|
18
|
+
/** 开发环境端口范围:结束 */
|
|
19
|
+
declare const DEV_PORT_RANGE_END = 19536;
|
|
20
|
+
/** 默认端口(根据运行模式自动选择) */
|
|
21
|
+
declare const DEFAULT_PORT: number;
|
|
22
|
+
/** 端口范围:起始(根据运行模式自动选择) */
|
|
23
|
+
declare const PORT_RANGE_START: number;
|
|
24
|
+
/** 端口范围:结束(根据运行模式自动选择) */
|
|
25
|
+
declare const PORT_RANGE_END: number;
|
|
12
26
|
/** 最大尝试端口数 */
|
|
13
27
|
declare const MAX_PORT_ATTEMPTS = 10;
|
|
14
28
|
/** 端口扫描超时(毫秒) */
|
|
@@ -47,6 +61,7 @@ declare enum MessageType {
|
|
|
47
61
|
REGISTER = "register",
|
|
48
62
|
REGISTER_ACK = "register_ack",
|
|
49
63
|
GET_NODE_BY_ID = "get_node_by_id",
|
|
64
|
+
GET_PAGE_BY_ID = "get_page_by_id",
|
|
50
65
|
GET_ALL_NODES = "get_all_nodes",
|
|
51
66
|
GET_SELECTION = "get_selection",
|
|
52
67
|
EXPORT_IMAGE = "export_image",
|
|
@@ -216,7 +231,139 @@ interface ConnectionInfo {
|
|
|
216
231
|
/** 最后活跃时间 */
|
|
217
232
|
lastActiveAt: Date;
|
|
218
233
|
}
|
|
219
|
-
/**
|
|
234
|
+
/**
|
|
235
|
+
* 节点信息
|
|
236
|
+
*
|
|
237
|
+
* 包含 MasterGo 节点的所有属性,根据节点类型不同,可用属性也不同。
|
|
238
|
+
*
|
|
239
|
+
* ## 通用属性 (所有节点)
|
|
240
|
+
* - `id`: 节点唯一标识
|
|
241
|
+
* - `name`: 节点名称
|
|
242
|
+
* - `type`: 节点类型 (FRAME, TEXT, RECTANGLE, ELLIPSE, POLYGON, STAR, LINE, PEN, COMPONENT, COMPONENT_SET, INSTANCE, GROUP, BOOLEAN_OPERATION, SLICE, CONNECTOR, SECTION)
|
|
243
|
+
* - `visible`: 是否可见
|
|
244
|
+
* - `isLocked`: 是否锁定
|
|
245
|
+
* - `slotInfo`: 插槽信息
|
|
246
|
+
* - `componentPropertyReferences`: 组件属性引用
|
|
247
|
+
* - `attachedConnectorIds`: 连接的连接线 ID 数组
|
|
248
|
+
*
|
|
249
|
+
* ## 布局属性 (LayoutMixin)
|
|
250
|
+
* - `x`, `y`: 坐标
|
|
251
|
+
* - `width`, `height`: 尺寸
|
|
252
|
+
* - `rotation`: 旋转角度
|
|
253
|
+
* - `absoluteTransform`: 绝对变换矩阵
|
|
254
|
+
* - `relativeTransform`: 相对变换矩阵
|
|
255
|
+
* - `absoluteRenderBounds`: 渲染边界(含阴影/外描边)
|
|
256
|
+
* - `absoluteBoundingBox`: 绝对边界框
|
|
257
|
+
* - `bound`: 边界
|
|
258
|
+
* - `minWidth`, `maxWidth`, `minHeight`, `maxHeight`: 尺寸约束
|
|
259
|
+
* - `constrainProportions`: 锁定宽高比
|
|
260
|
+
* - `layoutPositioning`: 布局定位方式 (AUTO | ABSOLUTE)
|
|
261
|
+
* - `alignSelf`: 交叉轴对齐 (STRETCH | INHERIT)
|
|
262
|
+
* - `flexGrow`: 弹性增长 (0 | 1)
|
|
263
|
+
* - `scaleFactor`: 缩放因子
|
|
264
|
+
*
|
|
265
|
+
* ## 混合属性 (BlendMixin)
|
|
266
|
+
* - `opacity`: 不透明度
|
|
267
|
+
* - `blendMode`: 混合模式
|
|
268
|
+
* - `isMask`: 是否蒙版
|
|
269
|
+
* - `isMaskOutline`: 轮廓蒙版
|
|
270
|
+
* - `isMaskVisible`: 蒙版可见
|
|
271
|
+
* - `effects`: 效果数组(阴影、模糊等)
|
|
272
|
+
* - `effectStyleId`: 效果样式 ID
|
|
273
|
+
*
|
|
274
|
+
* ## 几何属性 (GeometryMixin)
|
|
275
|
+
* - `fills`: 填充数组
|
|
276
|
+
* - `strokes`: 描边数组
|
|
277
|
+
* - `strokeWeight`: 描边粗细
|
|
278
|
+
* - `strokeAlign`: 描边对齐 (CENTER | INSIDE | OUTSIDE)
|
|
279
|
+
* - `strokeCap`: 端点装饰
|
|
280
|
+
* - `strokeJoin`: 拐角装饰
|
|
281
|
+
* - `strokeStyle`: 描边样式 (SOLID | DASH | CUSTOM)
|
|
282
|
+
* - `dashCap`: 虚线端点
|
|
283
|
+
* - `strokeDashes`: 虚线数组
|
|
284
|
+
* - `fillStyleId`: 填充样式 ID
|
|
285
|
+
* - `strokeFillStyleId`: 描边填充样式 ID
|
|
286
|
+
* - `strokeWidthStyleId`: 描边宽度样式 ID
|
|
287
|
+
* - `paddingStyleId`: 内边距样式 ID
|
|
288
|
+
* - `spacingStyleId`: 间距样式 ID
|
|
289
|
+
* - `cornerRadiusStyleId`: 圆角样式 ID
|
|
290
|
+
*
|
|
291
|
+
* ## 矩形描边属性 (RectangleStrokeWeightMixin)
|
|
292
|
+
* - `strokeTopWeight`, `strokeLeftWeight`, `strokeBottomWeight`, `strokeRightWeight`: 各边描边粗细
|
|
293
|
+
*
|
|
294
|
+
* ## 圆角属性 (CornerMixin)
|
|
295
|
+
* - `cornerSmooth`: 角平滑度
|
|
296
|
+
* - `cornerRadius`: 统一圆角
|
|
297
|
+
* - `topLeftRadius`, `topRightRadius`, `bottomLeftRadius`, `bottomRightRadius`: 各角圆角
|
|
298
|
+
*
|
|
299
|
+
* ## 约束属性 (ConstraintMixin)
|
|
300
|
+
* - `constraints`: 约束设置 { horizontal, vertical }
|
|
301
|
+
*
|
|
302
|
+
* ## 容器属性 (ContainerMixin)
|
|
303
|
+
* - `expanded`: 是否展开
|
|
304
|
+
*
|
|
305
|
+
* ## 自动布局属性 (FrameContainerMixin)
|
|
306
|
+
* - `flexMode`: 自动布局方向 (NONE | HORIZONTAL | VERTICAL)
|
|
307
|
+
* - `flexWrap`: 换行设置 (WRAP | NO_WRAP)
|
|
308
|
+
* - `itemSpacing`: 主轴间距
|
|
309
|
+
* - `crossAxisSpacing`: 交叉轴间距
|
|
310
|
+
* - `mainAxisAlignItems`: 主轴对齐
|
|
311
|
+
* - `crossAxisAlignItems`: 交叉轴对齐
|
|
312
|
+
* - `mainAxisSizingMode`: 主轴尺寸模式 (FIXED | AUTO)
|
|
313
|
+
* - `crossAxisSizingMode`: 交叉轴尺寸模式 (FIXED | AUTO)
|
|
314
|
+
* - `crossAxisAlignContent`: 多行对齐
|
|
315
|
+
* - `strokesIncludedInLayout`: 描边计入布局
|
|
316
|
+
* - `itemReverseZIndex`: 反转堆叠
|
|
317
|
+
* - `paddingTop`, `paddingRight`, `paddingBottom`, `paddingLeft`: 内边距
|
|
318
|
+
* - `clipsContent`: 裁剪内容
|
|
319
|
+
* - `layoutGrids`: 布局网格
|
|
320
|
+
* - `gridStyleId`: 网格样式 ID
|
|
321
|
+
* - `overflowDirection`: 溢出方向
|
|
322
|
+
*
|
|
323
|
+
* ## 原型交互属性 (ReactionMixin)
|
|
324
|
+
* - `reactions`: 原型交互数组
|
|
325
|
+
*
|
|
326
|
+
* ## 导出属性 (ExportMixin)
|
|
327
|
+
* - `exportSettings`: 导出设置数组
|
|
328
|
+
*
|
|
329
|
+
* ## TEXT 节点特有属性
|
|
330
|
+
* - `characters`: 文本内容
|
|
331
|
+
* - `hasMissingFont`: 缺失字体
|
|
332
|
+
* - `hyperlinks`: 超链接数组
|
|
333
|
+
* - `textAlignHorizontal`: 水平对齐
|
|
334
|
+
* - `textAlignVertical`: 垂直对齐
|
|
335
|
+
* - `textAutoResize`: 自动调整
|
|
336
|
+
* - `paragraphSpacing`: 段落间距
|
|
337
|
+
* - `textStyles`: 文本样式数组
|
|
338
|
+
* - `listStyles`: 列表样式数组
|
|
339
|
+
*
|
|
340
|
+
* ## COMPONENT/COMPONENT_SET 节点特有属性
|
|
341
|
+
* - `variantProperties`: 变体属性
|
|
342
|
+
* - `componentPropertyValues`: 组件属性值
|
|
343
|
+
* - `description`: 描述
|
|
344
|
+
* - `alias`: 别名
|
|
345
|
+
* - `documentationLinks`: 文档链接
|
|
346
|
+
* - `isExternal`: 是否团队库组件
|
|
347
|
+
* - `ukey`: 唯一键
|
|
348
|
+
* - `publishStatus`: 发布状态
|
|
349
|
+
*
|
|
350
|
+
* ## INSTANCE 节点特有属性
|
|
351
|
+
* - `componentProperties`: 组件属性
|
|
352
|
+
* - `exposedInstances`: 暴露的实例 ID 数组
|
|
353
|
+
* - `isExposedInstance`: 是否暴露的实例
|
|
354
|
+
* - `mainComponentId`: 主组件 ID
|
|
355
|
+
* - `mainComponentName`: 主组件名称
|
|
356
|
+
*
|
|
357
|
+
* ## 其他节点特有属性
|
|
358
|
+
* - ELLIPSE: `arcData`
|
|
359
|
+
* - POLYGON/STAR: `pointCount`
|
|
360
|
+
* - STAR: `innerRadius`
|
|
361
|
+
* - LINE: `leftStrokeCap`, `rightStrokeCap`
|
|
362
|
+
* - PEN: `penNetwork`, `penPaths`
|
|
363
|
+
* - BOOLEAN_OPERATION: `booleanOperation`
|
|
364
|
+
* - CONNECTOR: `connectorStart`, `connectorEnd`, `connectorStartStrokeCap`, `connectorEndStrokeCap`, `connectorText`
|
|
365
|
+
* - SLICE: `isPreserveRatio`
|
|
366
|
+
*/
|
|
220
367
|
interface NodeInfo {
|
|
221
368
|
/** 节点 ID */
|
|
222
369
|
id: string;
|
|
@@ -236,7 +383,7 @@ interface NodeInfo {
|
|
|
236
383
|
height?: number;
|
|
237
384
|
/** 子节点 */
|
|
238
385
|
children?: NodeInfo[];
|
|
239
|
-
/**
|
|
386
|
+
/** 其他属性(根据节点类型不同而不同) */
|
|
240
387
|
[key: string]: unknown;
|
|
241
388
|
}
|
|
242
389
|
/** 空间节点信息(仅包含位置和尺寸,用于 AI 理解空间布局) */
|
|
@@ -267,6 +414,17 @@ interface GetNodeParams {
|
|
|
267
414
|
/** 索引签名 */
|
|
268
415
|
[key: string]: unknown;
|
|
269
416
|
}
|
|
417
|
+
/** 获取页面参数 */
|
|
418
|
+
interface GetPageParams {
|
|
419
|
+
/** 页面 ID */
|
|
420
|
+
pageId: string;
|
|
421
|
+
/** 遍历深度 */
|
|
422
|
+
maxDepth?: number;
|
|
423
|
+
/** 是否包含不可见节点 */
|
|
424
|
+
includeInvisible?: boolean;
|
|
425
|
+
/** 索引签名 */
|
|
426
|
+
[key: string]: unknown;
|
|
427
|
+
}
|
|
270
428
|
/** 获取所有节点参数 */
|
|
271
429
|
interface GetAllNodesParams {
|
|
272
430
|
/** 遍历深度 */
|
|
@@ -518,7 +676,7 @@ interface ManagedWebSocket extends WebSocket {
|
|
|
518
676
|
*/
|
|
519
677
|
declare class ConnectionManager {
|
|
520
678
|
private logger;
|
|
521
|
-
/** Provider 连接(按页面 URL
|
|
679
|
+
/** Provider 连接(按页面 URL 索引,支持同 URL 多个连接) */
|
|
522
680
|
private providers;
|
|
523
681
|
/** Consumer 连接 */
|
|
524
682
|
private consumers;
|
|
@@ -552,7 +710,7 @@ declare class ConnectionManager {
|
|
|
552
710
|
*/
|
|
553
711
|
updateLastActive(ws: ManagedWebSocket): void;
|
|
554
712
|
/**
|
|
555
|
-
* 根据页面 URL 查找 Provider
|
|
713
|
+
* 根据页面 URL 查找 Provider(返回第一个可用的连接)
|
|
556
714
|
*/
|
|
557
715
|
findProviderByPageUrl(pageUrl: string): ManagedWebSocket | undefined;
|
|
558
716
|
/**
|
|
@@ -625,4 +783,4 @@ declare class RequestHandler {
|
|
|
625
783
|
cleanupAll(): void;
|
|
626
784
|
}
|
|
627
785
|
|
|
628
|
-
export { type
|
|
786
|
+
export { type ServerOptions as $, type PongMessage as A, type BaseMessage as B, CONFIG_DIR as C, DEV_DEFAULT_PORT as D, ErrorCode as E, type ConnectionInfo as F, type GetNodeParams as G, HEARTBEAT_INTERVAL as H, IS_DEV_MODE as I, type GetPageParams as J, type GetAllNodesParams as K, LOG_DIR as L, MAX_PORT_ATTEMPTS as M, type NodeInfo as N, type ExportImageParams as O, PROD_DEFAULT_PORT as P, type OutputFormatter as Q, REQUEST_TIMEOUT as R, type ServerInfo as S, type CliOptions as T, type RGBA as U, type MgPageInfo as V, type AllPagesInfo as W, type ConnectedPageInfo as X, type ServerStatusResponse as Y, MGServer as Z, createServer as _, type SpaceNodeInfo as a, ConnectionManager as a0, type ManagedWebSocket as a1, RequestHandler as a2, Logger as a3, createLogger as a4, LogLevel as a5, type LoggerOptions as a6, PROD_PORT_RANGE_START as b, PROD_PORT_RANGE_END as c, DEV_PORT_RANGE_START as d, DEV_PORT_RANGE_END as e, DEFAULT_PORT as f, PORT_RANGE_START as g, PORT_RANGE_END as h, PORT_SCAN_TIMEOUT as i, SERVER_INFO_FILE as j, SERVER_LOG_FILE as k, HEARTBEAT_TIMEOUT as l, SERVER_START_TIMEOUT as m, RETRY_INTERVALS as n, MAX_RETRY_COUNT as o, ConnectionType as p, MessageType as q, ErrorNames as r, ErrorMessages as s, MGError as t, createError as u, type RequestMessage as v, type ResponseMessage as w, type ErrorInfo as x, type RegisterMessage as y, type PingMessage as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ServerInfo, N as NodeInfo, a as SpaceNodeInfo } from './index
|
|
2
|
-
export {
|
|
1
|
+
import { S as ServerInfo, N as NodeInfo, a as SpaceNodeInfo } from './index-DUQN5gSR.js';
|
|
2
|
+
export { W as AllPagesInfo, B as BaseMessage, C as CONFIG_DIR, T as CliOptions, X as ConnectedPageInfo, F as ConnectionInfo, a0 as ConnectionManager, p as ConnectionType, f as DEFAULT_PORT, D as DEV_DEFAULT_PORT, e as DEV_PORT_RANGE_END, d as DEV_PORT_RANGE_START, E as ErrorCode, x as ErrorInfo, s as ErrorMessages, r as ErrorNames, O as ExportImageParams, K as GetAllNodesParams, G as GetNodeParams, J as GetPageParams, H as HEARTBEAT_INTERVAL, l as HEARTBEAT_TIMEOUT, I as IS_DEV_MODE, L as LOG_DIR, a5 as LogLevel, a3 as Logger, a6 as LoggerOptions, M as MAX_PORT_ATTEMPTS, o as MAX_RETRY_COUNT, t as MGError, Z as MGServer, a1 as ManagedWebSocket, q as MessageType, V as MgPageInfo, Q as OutputFormatter, h as PORT_RANGE_END, g as PORT_RANGE_START, i as PORT_SCAN_TIMEOUT, P as PROD_DEFAULT_PORT, c as PROD_PORT_RANGE_END, b as PROD_PORT_RANGE_START, z as PingMessage, A as PongMessage, R as REQUEST_TIMEOUT, n as RETRY_INTERVALS, U as RGBA, y as RegisterMessage, a2 as RequestHandler, v as RequestMessage, w as ResponseMessage, j as SERVER_INFO_FILE, k as SERVER_LOG_FILE, m as SERVER_START_TIMEOUT, $ as ServerOptions, Y as ServerStatusResponse, u as createError, a4 as createLogger, _ as createServer } from './index-DUQN5gSR.js';
|
|
3
3
|
import 'ws';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -56,15 +56,18 @@ declare function isDesignPageUrl(url: string): boolean;
|
|
|
56
56
|
/**
|
|
57
57
|
* 解析 mgp:// 链接
|
|
58
58
|
*
|
|
59
|
-
* 支持的格式 (queryParams 格式,nodeId 需要 URL 编码):
|
|
59
|
+
* 支持的格式 (queryParams 格式,nodeId/pageId 需要 URL 编码):
|
|
60
60
|
* - mgp://mastergo.netease.com/file/174135798361888?nodeId=123%3A456 (单个节点)
|
|
61
61
|
* - mgp://mastergo.netease.com/file/174135798361888?nodeId=0%3A8633&nodePath=314%3A13190%2F0%3A8633 (带父节点路径)
|
|
62
|
+
* - mgp://mastergo.netease.com/file/174135798361888?pageId=0%3A1 (页面链接)
|
|
62
63
|
*
|
|
63
64
|
* 输出: { pageUrl: 'mastergo.netease.com/file/174135798361888', nodeId: '0:8633', nodePath: ['314:13190', '0:8633'] }
|
|
65
|
+
* 或 { pageUrl: 'mastergo.netease.com/file/174135798361888', pageId: '0:1' }
|
|
64
66
|
*/
|
|
65
67
|
declare function parseMgpLink(link: string): {
|
|
66
68
|
pageUrl: string;
|
|
67
|
-
nodeId
|
|
69
|
+
nodeId?: string;
|
|
70
|
+
pageId?: string;
|
|
68
71
|
nodePath?: string[];
|
|
69
72
|
} | null;
|
|
70
73
|
/**
|
|
@@ -75,6 +78,13 @@ declare function parseMgpLink(link: string): {
|
|
|
75
78
|
* @param nodePath 可选的父节点路径(会被 URL 编码)
|
|
76
79
|
*/
|
|
77
80
|
declare function generateMgpLink(pageUrl: string, nodeId: string, nodePath?: string[]): string;
|
|
81
|
+
/**
|
|
82
|
+
* 生成 mgp:// 页面链接
|
|
83
|
+
*
|
|
84
|
+
* @param pageUrl 页面 URL(会被标准化)
|
|
85
|
+
* @param pageId 页面 ID(会被 URL 编码)
|
|
86
|
+
*/
|
|
87
|
+
declare function generatePageLink(pageUrl: string, pageId: string): string;
|
|
78
88
|
/**
|
|
79
89
|
* 格式化文件大小
|
|
80
90
|
*/
|
|
@@ -153,4 +163,4 @@ declare function trimNodeDefaults<T extends Record<string, unknown>>(node: T): T
|
|
|
153
163
|
*/
|
|
154
164
|
declare function extractSpaceInfo(node: NodeInfo): SpaceNodeInfo;
|
|
155
165
|
|
|
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 };
|
|
166
|
+
export { NODE_DEFAULTS, NodeInfo, ServerInfo, SpaceNodeInfo, deleteServerInfo, ensureConfigDir, ensureDir, ensureOutputDir, extractFileId, extractFileIdFromMgpLink, extractFileIdFromUrl, extractSpaceInfo, formatDuration, formatFileSize, formatLogTime, generateId, generateMgpLink, generatePageLink, getCurrentISOTime, isDesignPageUrl, isProcessRunning, killProcess, normalizePageUrl, parseMgpLink, readServerInfo, resolveOutputPath, roundToOneDecimal, trimNodeDefaults, writeServerInfo };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// src/shared/constants.ts
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { join } from "path";
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
4
|
+
var IS_DEV_MODE = process.env.MG_DEV_MODE === "true";
|
|
5
|
+
var PROD_DEFAULT_PORT = 9527;
|
|
6
|
+
var PROD_PORT_RANGE_START = 9527;
|
|
7
|
+
var PROD_PORT_RANGE_END = 9536;
|
|
8
|
+
var DEV_DEFAULT_PORT = 19527;
|
|
9
|
+
var DEV_PORT_RANGE_START = 19527;
|
|
10
|
+
var DEV_PORT_RANGE_END = 19536;
|
|
11
|
+
var DEFAULT_PORT = IS_DEV_MODE ? DEV_DEFAULT_PORT : PROD_DEFAULT_PORT;
|
|
12
|
+
var PORT_RANGE_START = IS_DEV_MODE ? DEV_PORT_RANGE_START : PROD_PORT_RANGE_START;
|
|
13
|
+
var PORT_RANGE_END = IS_DEV_MODE ? DEV_PORT_RANGE_END : PROD_PORT_RANGE_END;
|
|
7
14
|
var MAX_PORT_ATTEMPTS = 10;
|
|
8
15
|
var PORT_SCAN_TIMEOUT = 500;
|
|
9
16
|
var CONFIG_DIR = join(homedir(), ".mg-plugin");
|
|
@@ -27,6 +34,7 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
27
34
|
MessageType2["REGISTER"] = "register";
|
|
28
35
|
MessageType2["REGISTER_ACK"] = "register_ack";
|
|
29
36
|
MessageType2["GET_NODE_BY_ID"] = "get_node_by_id";
|
|
37
|
+
MessageType2["GET_PAGE_BY_ID"] = "get_page_by_id";
|
|
30
38
|
MessageType2["GET_ALL_NODES"] = "get_all_nodes";
|
|
31
39
|
MessageType2["GET_SELECTION"] = "get_selection";
|
|
32
40
|
MessageType2["EXPORT_IMAGE"] = "export_image";
|
|
@@ -83,7 +91,7 @@ var ErrorNames = {
|
|
|
83
91
|
var ErrorMessages = {
|
|
84
92
|
["E001" /* CONNECTION_FAILED */]: "\u65E0\u6CD5\u8FDE\u63A5\u5230 MG Server",
|
|
85
93
|
["E002" /* CONNECTION_TIMEOUT */]: "\u8FDE\u63A5\u8D85\u65F6",
|
|
86
|
-
["E003" /* NO_PAGE_CONNECTED */]: "\u6CA1\u6709 MasterGo \u9875\u9762\u8FDE\u63A5\u5230 Server",
|
|
94
|
+
["E003" /* NO_PAGE_CONNECTED */]: "\u6CA1\u6709 MasterGo \u9875\u9762\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u5B89\u88C5 MG Plugin \u6D4F\u89C8\u5668\u6269\u5C55: https://chromewebstore.google.com/detail/mg-plugin/ddhihanlpcdneicohnglnaliefnkaeja",
|
|
87
95
|
["E004" /* PAGE_NOT_FOUND */]: "\u672A\u627E\u5230\u5339\u914D\u7684\u9875\u9762",
|
|
88
96
|
["E005" /* NODE_NOT_FOUND */]: "\u8282\u70B9\u4E0D\u5B58\u5728",
|
|
89
97
|
["E006" /* NO_SELECTION */]: "\u6CA1\u6709\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9",
|
|
@@ -218,27 +226,44 @@ function parseMgpLink(link) {
|
|
|
218
226
|
const queryString = urlPart.slice(questionMarkIndex + 1);
|
|
219
227
|
const params = new URLSearchParams(queryString);
|
|
220
228
|
const encodedNodeId = params.get("nodeId");
|
|
221
|
-
|
|
229
|
+
const encodedPageId = params.get("pageId");
|
|
230
|
+
if (!encodedNodeId && !encodedPageId) {
|
|
222
231
|
return null;
|
|
223
232
|
}
|
|
224
|
-
|
|
225
|
-
if (!/^(\d+:\d+)(\/\d+:\d+)*$/.test(nodeId)) {
|
|
233
|
+
if (encodedNodeId && encodedPageId) {
|
|
226
234
|
return null;
|
|
227
235
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const decodedNodePath = decodeURIComponent(encodedNodePath);
|
|
232
|
-
nodePath = decodedNodePath.split("/").filter(Boolean);
|
|
233
|
-
if (!nodePath.every((segment) => /^\d+:\d+$/.test(segment))) {
|
|
236
|
+
if (encodedNodeId) {
|
|
237
|
+
const nodeId = decodeURIComponent(encodedNodeId);
|
|
238
|
+
if (!/^(\d+:\d+)(\/\d+:\d+)*$/.test(nodeId)) {
|
|
234
239
|
return null;
|
|
235
240
|
}
|
|
241
|
+
const encodedNodePath = params.get("nodePath");
|
|
242
|
+
let nodePath;
|
|
243
|
+
if (encodedNodePath) {
|
|
244
|
+
const decodedNodePath = decodeURIComponent(encodedNodePath);
|
|
245
|
+
nodePath = decodedNodePath.split("/").filter(Boolean);
|
|
246
|
+
if (!nodePath.every((segment) => /^\d+:\d+$/.test(segment))) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
pageUrl,
|
|
252
|
+
nodeId,
|
|
253
|
+
nodePath
|
|
254
|
+
};
|
|
236
255
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
256
|
+
if (encodedPageId) {
|
|
257
|
+
const pageId = decodeURIComponent(encodedPageId);
|
|
258
|
+
if (!/^\d+:\d+$/.test(pageId)) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
pageUrl,
|
|
263
|
+
pageId
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
242
267
|
} catch {
|
|
243
268
|
return null;
|
|
244
269
|
}
|
|
@@ -253,6 +278,11 @@ function generateMgpLink(pageUrl, nodeId, nodePath) {
|
|
|
253
278
|
}
|
|
254
279
|
return link;
|
|
255
280
|
}
|
|
281
|
+
function generatePageLink(pageUrl, pageId) {
|
|
282
|
+
const normalizedUrl = normalizePageUrl(pageUrl);
|
|
283
|
+
const encodedPageId = encodeURIComponent(pageId);
|
|
284
|
+
return `mgp://${normalizedUrl}?pageId=${encodedPageId}`;
|
|
285
|
+
}
|
|
256
286
|
function formatFileSize(bytes) {
|
|
257
287
|
if (bytes < 1024) {
|
|
258
288
|
return `${bytes} \u5B57\u8282`;
|
|
@@ -550,7 +580,7 @@ function createLogger(options) {
|
|
|
550
580
|
// src/server/connection-manager.ts
|
|
551
581
|
var ConnectionManager = class {
|
|
552
582
|
logger;
|
|
553
|
-
/** Provider 连接(按页面 URL
|
|
583
|
+
/** Provider 连接(按页面 URL 索引,支持同 URL 多个连接) */
|
|
554
584
|
providers = /* @__PURE__ */ new Map();
|
|
555
585
|
/** Consumer 连接 */
|
|
556
586
|
consumers = /* @__PURE__ */ new Map();
|
|
@@ -586,7 +616,8 @@ var ConnectionManager = class {
|
|
|
586
616
|
*/
|
|
587
617
|
checkHeartbeats() {
|
|
588
618
|
const now = Date.now();
|
|
589
|
-
|
|
619
|
+
const entries = Array.from(this.allConnections.entries());
|
|
620
|
+
for (const [id, ws] of entries) {
|
|
590
621
|
const lastActive = ws.connectionInfo.lastActiveAt.getTime();
|
|
591
622
|
const elapsed = now - lastActive;
|
|
592
623
|
if (elapsed > HEARTBEAT_TIMEOUT) {
|
|
@@ -616,14 +647,10 @@ var ConnectionManager = class {
|
|
|
616
647
|
managedWs.isAlive = true;
|
|
617
648
|
this.allConnections.set(connectionId, managedWs);
|
|
618
649
|
if (type === "provider" /* PROVIDER */ && pageUrl) {
|
|
619
|
-
const existing = this.providers.get(pageUrl);
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
existing.close();
|
|
624
|
-
}
|
|
625
|
-
this.providers.set(pageUrl, managedWs);
|
|
626
|
-
this.logger.info(`Provider \u8FDE\u63A5: ${pageUrl}`);
|
|
650
|
+
const existing = this.providers.get(pageUrl) || [];
|
|
651
|
+
existing.push(managedWs);
|
|
652
|
+
this.providers.set(pageUrl, existing);
|
|
653
|
+
this.logger.info(`Provider \u8FDE\u63A5: ${pageUrl} (\u5F53\u524D\u8BE5\u9875\u9762\u8FDE\u63A5\u6570: ${existing.length})`);
|
|
627
654
|
} else if (type === "consumer" /* CONSUMER */) {
|
|
628
655
|
this.consumers.set(connectionId, managedWs);
|
|
629
656
|
this.logger.info(`Consumer \u8FDE\u63A5: ${connectionId}`);
|
|
@@ -637,8 +664,17 @@ var ConnectionManager = class {
|
|
|
637
664
|
const { connectionId, connectionInfo } = ws;
|
|
638
665
|
this.allConnections.delete(connectionId);
|
|
639
666
|
if (connectionInfo.type === "provider" /* PROVIDER */ && connectionInfo.pageUrl) {
|
|
640
|
-
this.providers.
|
|
641
|
-
|
|
667
|
+
const connections = this.providers.get(connectionInfo.pageUrl);
|
|
668
|
+
if (connections) {
|
|
669
|
+
const index = connections.findIndex((c) => c.connectionId === connectionId);
|
|
670
|
+
if (index !== -1) {
|
|
671
|
+
connections.splice(index, 1);
|
|
672
|
+
if (connections.length === 0) {
|
|
673
|
+
this.providers.delete(connectionInfo.pageUrl);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
this.logger.info(`Provider \u65AD\u5F00: ${connectionInfo.pageUrl} (\u8FDE\u63A5ID: ${connectionId})`);
|
|
642
678
|
} else if (connectionInfo.type === "consumer" /* CONSUMER */) {
|
|
643
679
|
this.consumers.delete(connectionId);
|
|
644
680
|
this.logger.info(`Consumer \u65AD\u5F00: ${connectionId}`);
|
|
@@ -652,31 +688,48 @@ var ConnectionManager = class {
|
|
|
652
688
|
ws.isAlive = true;
|
|
653
689
|
}
|
|
654
690
|
/**
|
|
655
|
-
* 根据页面 URL 查找 Provider
|
|
691
|
+
* 根据页面 URL 查找 Provider(返回第一个可用的连接)
|
|
656
692
|
*/
|
|
657
693
|
findProviderByPageUrl(pageUrl) {
|
|
658
|
-
|
|
694
|
+
const connections = this.providers.get(pageUrl);
|
|
695
|
+
return connections?.[0];
|
|
659
696
|
}
|
|
660
697
|
/**
|
|
661
698
|
* 获取第一个可用的 Provider
|
|
662
699
|
*/
|
|
663
700
|
getFirstProvider() {
|
|
664
|
-
const
|
|
665
|
-
const
|
|
666
|
-
|
|
701
|
+
const allConnections = Array.from(this.providers.values());
|
|
702
|
+
for (const connections of allConnections) {
|
|
703
|
+
if (connections.length > 0) {
|
|
704
|
+
return connections[0];
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return void 0;
|
|
667
708
|
}
|
|
668
709
|
/**
|
|
669
710
|
* 获取所有 Provider 信息
|
|
670
711
|
*/
|
|
671
712
|
getAllProviders() {
|
|
672
|
-
|
|
713
|
+
const result = [];
|
|
714
|
+
const allConnections = Array.from(this.providers.values());
|
|
715
|
+
for (const connections of allConnections) {
|
|
716
|
+
for (const ws of connections) {
|
|
717
|
+
result.push(ws.connectionInfo);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return result;
|
|
673
721
|
}
|
|
674
722
|
/**
|
|
675
723
|
* 获取连接统计
|
|
676
724
|
*/
|
|
677
725
|
getStats() {
|
|
726
|
+
let providerCount = 0;
|
|
727
|
+
const allConnections = Array.from(this.providers.values());
|
|
728
|
+
for (const connections of allConnections) {
|
|
729
|
+
providerCount += connections.length;
|
|
730
|
+
}
|
|
678
731
|
return {
|
|
679
|
-
providers:
|
|
732
|
+
providers: providerCount,
|
|
680
733
|
consumers: this.consumers.size,
|
|
681
734
|
total: this.allConnections.size
|
|
682
735
|
};
|
|
@@ -692,7 +745,8 @@ var ConnectionManager = class {
|
|
|
692
745
|
*/
|
|
693
746
|
closeAll() {
|
|
694
747
|
this.stopHeartbeatCheck();
|
|
695
|
-
|
|
748
|
+
const allWs = Array.from(this.allConnections.values());
|
|
749
|
+
for (const ws of allWs) {
|
|
696
750
|
ws.close();
|
|
697
751
|
}
|
|
698
752
|
this.providers.clear();
|
|
@@ -728,7 +782,7 @@ var RequestHandler = class {
|
|
|
728
782
|
} else {
|
|
729
783
|
provider = this.connectionManager.getFirstProvider();
|
|
730
784
|
if (!provider) {
|
|
731
|
-
this.sendError(consumer, requestId, "E003" /* NO_PAGE_CONNECTED */, "
|
|
785
|
+
this.sendError(consumer, requestId, "E003" /* NO_PAGE_CONNECTED */, ErrorMessages["E003" /* NO_PAGE_CONNECTED */]);
|
|
732
786
|
return;
|
|
733
787
|
}
|
|
734
788
|
}
|
|
@@ -846,24 +900,11 @@ function getVersion() {
|
|
|
846
900
|
try {
|
|
847
901
|
const currentFile = fileURLToPath(import.meta.url);
|
|
848
902
|
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
903
|
const packageJsonPaths = [
|
|
865
904
|
join2(currentDir, "..", "package.json"),
|
|
905
|
+
// dist/xxx.js -> ../package.json
|
|
866
906
|
join2(currentDir, "..", "..", "package.json")
|
|
907
|
+
// src/shared/version.ts -> ../../package.json
|
|
867
908
|
];
|
|
868
909
|
for (const packageJsonPath of packageJsonPaths) {
|
|
869
910
|
if (existsSync3(packageJsonPath)) {
|
|
@@ -1132,11 +1173,15 @@ export {
|
|
|
1132
1173
|
ConnectionManager,
|
|
1133
1174
|
ConnectionType,
|
|
1134
1175
|
DEFAULT_PORT,
|
|
1176
|
+
DEV_DEFAULT_PORT,
|
|
1177
|
+
DEV_PORT_RANGE_END,
|
|
1178
|
+
DEV_PORT_RANGE_START,
|
|
1135
1179
|
ErrorCode,
|
|
1136
1180
|
ErrorMessages,
|
|
1137
1181
|
ErrorNames,
|
|
1138
1182
|
HEARTBEAT_INTERVAL,
|
|
1139
1183
|
HEARTBEAT_TIMEOUT,
|
|
1184
|
+
IS_DEV_MODE,
|
|
1140
1185
|
LOG_DIR,
|
|
1141
1186
|
LogLevel,
|
|
1142
1187
|
Logger,
|
|
@@ -1149,6 +1194,9 @@ export {
|
|
|
1149
1194
|
PORT_RANGE_END,
|
|
1150
1195
|
PORT_RANGE_START,
|
|
1151
1196
|
PORT_SCAN_TIMEOUT,
|
|
1197
|
+
PROD_DEFAULT_PORT,
|
|
1198
|
+
PROD_PORT_RANGE_END,
|
|
1199
|
+
PROD_PORT_RANGE_START,
|
|
1152
1200
|
REQUEST_TIMEOUT,
|
|
1153
1201
|
RETRY_INTERVALS,
|
|
1154
1202
|
RequestHandler,
|
|
@@ -1171,6 +1219,7 @@ export {
|
|
|
1171
1219
|
formatLogTime,
|
|
1172
1220
|
generateId,
|
|
1173
1221
|
generateMgpLink,
|
|
1222
|
+
generatePageLink,
|
|
1174
1223
|
getCurrentISOTime,
|
|
1175
1224
|
isDesignPageUrl,
|
|
1176
1225
|
isProcessRunning,
|