@hangox/mg-cli 1.1.1 → 1.1.3
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 +243 -16
- package/dist/cli.js.map +1 -1
- package/dist/daemon-runner.js +79 -7
- package/dist/daemon-runner.js.map +1 -1
- package/dist/{index-cEKly9mt.d.ts → index-DorC5U6y.d.ts} +11 -0
- package/dist/index.d.ts +39 -6
- package/dist/index.js +142 -9
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +76 -4
- package/dist/server.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
45
45
|
MessageType2["OPEN_PAGE"] = "open_page";
|
|
46
46
|
MessageType2["NAVIGATE_TO_NODE"] = "navigate_to_node";
|
|
47
47
|
MessageType2["GET_SERVER_STATUS"] = "get_server_status";
|
|
48
|
+
MessageType2["TRACK_ANALYTICS"] = "track_analytics";
|
|
48
49
|
MessageType2["RESPONSE"] = "response";
|
|
49
50
|
MessageType2["ERROR"] = "error";
|
|
50
51
|
return MessageType2;
|
|
@@ -216,6 +217,32 @@ function normalizePageUrl(url) {
|
|
|
216
217
|
return url;
|
|
217
218
|
}
|
|
218
219
|
}
|
|
220
|
+
function normalizePageUrlWithPageId(url) {
|
|
221
|
+
try {
|
|
222
|
+
let urlObj;
|
|
223
|
+
if (!url.includes("://") && !url.startsWith("//")) {
|
|
224
|
+
urlObj = new URL(`https://${url}`);
|
|
225
|
+
} else {
|
|
226
|
+
urlObj = new URL(url);
|
|
227
|
+
}
|
|
228
|
+
const basePath = `${urlObj.host}${urlObj.pathname}`;
|
|
229
|
+
const pageId = urlObj.searchParams.get("page_id");
|
|
230
|
+
if (pageId) {
|
|
231
|
+
const decodedPageId = decodeURIComponent(pageId);
|
|
232
|
+
return `${basePath}?page_id=${decodedPageId}`;
|
|
233
|
+
}
|
|
234
|
+
return basePath;
|
|
235
|
+
} catch {
|
|
236
|
+
const withoutProtocol = url.replace(/^https?:\/\//, "").replace(/^\/\//, "");
|
|
237
|
+
const pageIdMatch = withoutProtocol.match(/[?&]page_id=([^&#]+)/);
|
|
238
|
+
const basePath = withoutProtocol.split("?")[0].split("#")[0];
|
|
239
|
+
if (pageIdMatch) {
|
|
240
|
+
const decodedPageId = decodeURIComponent(pageIdMatch[1]);
|
|
241
|
+
return `${basePath}?page_id=${decodedPageId}`;
|
|
242
|
+
}
|
|
243
|
+
return basePath;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
219
246
|
function isDesignPageUrl(url) {
|
|
220
247
|
return /\/file\/\d+/.test(url);
|
|
221
248
|
}
|
|
@@ -229,17 +256,22 @@ function parseMgpLink(link) {
|
|
|
229
256
|
if (questionMarkIndex === -1) {
|
|
230
257
|
return null;
|
|
231
258
|
}
|
|
232
|
-
const
|
|
259
|
+
const basePath = urlPart.slice(0, questionMarkIndex);
|
|
233
260
|
const queryString = urlPart.slice(questionMarkIndex + 1);
|
|
234
261
|
const params = new URLSearchParams(queryString);
|
|
235
262
|
const encodedNodeId = params.get("nodeId");
|
|
236
263
|
const encodedPageId = params.get("pageId");
|
|
264
|
+
const mgPageId = params.get("page_id");
|
|
237
265
|
if (!encodedNodeId && !encodedPageId) {
|
|
238
266
|
return null;
|
|
239
267
|
}
|
|
240
268
|
if (encodedNodeId && encodedPageId) {
|
|
241
269
|
return null;
|
|
242
270
|
}
|
|
271
|
+
let pageUrl = basePath;
|
|
272
|
+
if (mgPageId) {
|
|
273
|
+
pageUrl = `${basePath}?page_id=${mgPageId}`;
|
|
274
|
+
}
|
|
243
275
|
if (encodedNodeId) {
|
|
244
276
|
const nodeId = decodeURIComponent(encodedNodeId);
|
|
245
277
|
if (!/^(\d+:\d+)(\/\d+:\d+)*$/.test(nodeId)) {
|
|
@@ -254,10 +286,19 @@ function parseMgpLink(link) {
|
|
|
254
286
|
return null;
|
|
255
287
|
}
|
|
256
288
|
}
|
|
289
|
+
const childNodeIdsRaw = params.get("childNodeIds");
|
|
290
|
+
let childNodeIds;
|
|
291
|
+
if (childNodeIdsRaw) {
|
|
292
|
+
childNodeIds = childNodeIdsRaw.split(",").map((id) => decodeURIComponent(id));
|
|
293
|
+
if (!childNodeIds.every((id) => /^(\d+:\d+)(\/\d+:\d+)*$/.test(id))) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
257
297
|
return {
|
|
258
298
|
pageUrl,
|
|
259
299
|
nodeId,
|
|
260
|
-
nodePath
|
|
300
|
+
nodePath,
|
|
301
|
+
childNodeIds
|
|
261
302
|
};
|
|
262
303
|
}
|
|
263
304
|
if (encodedPageId) {
|
|
@@ -276,9 +317,10 @@ function parseMgpLink(link) {
|
|
|
276
317
|
}
|
|
277
318
|
}
|
|
278
319
|
function generateMgpLink(pageUrl, nodeId, nodePath) {
|
|
279
|
-
const normalizedUrl =
|
|
320
|
+
const normalizedUrl = normalizePageUrlWithPageId(pageUrl);
|
|
280
321
|
const encodedNodeId = encodeURIComponent(nodeId);
|
|
281
|
-
|
|
322
|
+
const separator = normalizedUrl.includes("?") ? "&" : "?";
|
|
323
|
+
let link = `mgp://${normalizedUrl}${separator}nodeId=${encodedNodeId}`;
|
|
282
324
|
if (nodePath && nodePath.length > 0) {
|
|
283
325
|
const encodedNodePath = encodeURIComponent(nodePath.join("/"));
|
|
284
326
|
link += `&nodePath=${encodedNodePath}`;
|
|
@@ -290,6 +332,15 @@ function generatePageLink(pageUrl, pageId) {
|
|
|
290
332
|
const encodedPageId = encodeURIComponent(pageId);
|
|
291
333
|
return `mgp://${normalizedUrl}?pageId=${encodedPageId}`;
|
|
292
334
|
}
|
|
335
|
+
function generateMultiNodeMgpLink(pageUrl, parentNodeId, childNodeIds) {
|
|
336
|
+
const normalizedUrl = normalizePageUrlWithPageId(pageUrl);
|
|
337
|
+
const encodedParentNodeId = encodeURIComponent(parentNodeId);
|
|
338
|
+
const separator = normalizedUrl.includes("?") ? "&" : "?";
|
|
339
|
+
let link = `mgp://${normalizedUrl}${separator}nodeId=${encodedParentNodeId}`;
|
|
340
|
+
const encodedChildIds = childNodeIds.map((id) => encodeURIComponent(id)).join(",");
|
|
341
|
+
link += `&childNodeIds=${encodedChildIds}`;
|
|
342
|
+
return link;
|
|
343
|
+
}
|
|
293
344
|
function formatFileSize(bytes) {
|
|
294
345
|
if (bytes < 1024) {
|
|
295
346
|
return `${bytes} \u5B57\u8282`;
|
|
@@ -408,6 +459,8 @@ var NODE_DEFAULTS = {
|
|
|
408
459
|
dashCap: "NONE",
|
|
409
460
|
fillStyleId: "",
|
|
410
461
|
strokeStyleId: "",
|
|
462
|
+
strokeFillStyleId: "",
|
|
463
|
+
strokeWidthStyleId: "",
|
|
411
464
|
// Corner 属性
|
|
412
465
|
cornerSmooth: 0,
|
|
413
466
|
cornerRadius: 0,
|
|
@@ -415,6 +468,7 @@ var NODE_DEFAULTS = {
|
|
|
415
468
|
topRightRadius: 0,
|
|
416
469
|
bottomLeftRadius: 0,
|
|
417
470
|
bottomRightRadius: 0,
|
|
471
|
+
cornerRadiusStyleId: "",
|
|
418
472
|
// Layout 属性
|
|
419
473
|
rotation: 0,
|
|
420
474
|
flexGrow: 0,
|
|
@@ -430,9 +484,13 @@ var NODE_DEFAULTS = {
|
|
|
430
484
|
paddingRight: 0,
|
|
431
485
|
paddingBottom: 0,
|
|
432
486
|
paddingLeft: 0,
|
|
487
|
+
paddingStyleId: "",
|
|
488
|
+
spacingStyleId: "",
|
|
433
489
|
clipsContent: false,
|
|
434
490
|
itemReverseZIndex: false,
|
|
435
491
|
strokesIncludedInLayout: false,
|
|
492
|
+
overflowDirection: "NONE",
|
|
493
|
+
gridStyleId: "",
|
|
436
494
|
// 其他属性
|
|
437
495
|
componentPropertyReferences: null
|
|
438
496
|
};
|
|
@@ -443,7 +501,8 @@ var EMPTY_ARRAY_FIELDS = [
|
|
|
443
501
|
"strokeDashes",
|
|
444
502
|
"exportSettings",
|
|
445
503
|
"reactions",
|
|
446
|
-
"attachedConnectors"
|
|
504
|
+
"attachedConnectors",
|
|
505
|
+
"layoutGrids"
|
|
447
506
|
];
|
|
448
507
|
function isEmptyArray(value) {
|
|
449
508
|
return Array.isArray(value) && value.length === 0;
|
|
@@ -607,8 +666,8 @@ var ConnectionManager = class {
|
|
|
607
666
|
allConnections = /* @__PURE__ */ new Map();
|
|
608
667
|
/** 心跳检查定时器 */
|
|
609
668
|
heartbeatTimer = null;
|
|
610
|
-
constructor(
|
|
611
|
-
this.logger =
|
|
669
|
+
constructor(logger2) {
|
|
670
|
+
this.logger = logger2;
|
|
612
671
|
}
|
|
613
672
|
/**
|
|
614
673
|
* 启动心跳检查
|
|
@@ -835,9 +894,9 @@ var RequestHandler = class {
|
|
|
835
894
|
connectionManager;
|
|
836
895
|
/** 待处理的请求 */
|
|
837
896
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
838
|
-
constructor(connectionManager,
|
|
897
|
+
constructor(connectionManager, logger2) {
|
|
839
898
|
this.connectionManager = connectionManager;
|
|
840
|
-
this.logger =
|
|
899
|
+
this.logger = logger2;
|
|
841
900
|
}
|
|
842
901
|
/**
|
|
843
902
|
* 处理 Consumer 请求
|
|
@@ -1022,6 +1081,60 @@ function isVersionMatch(version1, version2) {
|
|
|
1022
1081
|
return version1 === version2;
|
|
1023
1082
|
}
|
|
1024
1083
|
|
|
1084
|
+
// src/server/analytics.ts
|
|
1085
|
+
import { PostHog } from "posthog-node";
|
|
1086
|
+
var POSTHOG_API_KEY = "phc_cSZZIxZOPhWOlsw92Wz8tmKQ5z8eQYsI3m9aM2Ujia9";
|
|
1087
|
+
var POSTHOG_HOST = "https://us.i.posthog.com";
|
|
1088
|
+
var posthogClient = null;
|
|
1089
|
+
var logger = null;
|
|
1090
|
+
function isTelemetryDisabled() {
|
|
1091
|
+
return process.env.MG_TELEMETRY_DISABLED === "1" || process.env.MG_TELEMETRY_DISABLED === "true" || process.env.DO_NOT_TRACK === "1" || process.env.DO_NOT_TRACK === "true";
|
|
1092
|
+
}
|
|
1093
|
+
function initServerAnalytics(serverLogger) {
|
|
1094
|
+
logger = serverLogger;
|
|
1095
|
+
if (isTelemetryDisabled()) {
|
|
1096
|
+
logger.info("\u9065\u6D4B\u5DF2\u7981\u7528 (MG_TELEMETRY_DISABLED \u6216 DO_NOT_TRACK)");
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
if (!posthogClient) {
|
|
1100
|
+
posthogClient = new PostHog(POSTHOG_API_KEY, {
|
|
1101
|
+
host: POSTHOG_HOST,
|
|
1102
|
+
// Server 端使用批量模式,减少网络请求
|
|
1103
|
+
flushAt: 10,
|
|
1104
|
+
flushInterval: 3e4
|
|
1105
|
+
// 30 秒
|
|
1106
|
+
});
|
|
1107
|
+
logger.info("PostHog Analytics \u5DF2\u521D\u59CB\u5316");
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function trackEvent(eventData) {
|
|
1111
|
+
if (!posthogClient) {
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
posthogClient.capture({
|
|
1116
|
+
distinctId: eventData.distinctId,
|
|
1117
|
+
event: eventData.event,
|
|
1118
|
+
properties: eventData.properties
|
|
1119
|
+
});
|
|
1120
|
+
logger?.info(`\u7EDF\u8BA1\u4E8B\u4EF6\u5DF2\u8BB0\u5F55: ${eventData.event}`, eventData.properties);
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
logger?.error("\u7EDF\u8BA1\u4E8B\u4EF6\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
async function shutdownServerAnalytics() {
|
|
1126
|
+
if (posthogClient) {
|
|
1127
|
+
try {
|
|
1128
|
+
logger?.info("\u6B63\u5728\u53D1\u9001\u5269\u4F59\u7EDF\u8BA1\u4E8B\u4EF6...");
|
|
1129
|
+
await posthogClient.shutdown();
|
|
1130
|
+
logger?.info("PostHog Analytics \u5DF2\u5173\u95ED");
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
logger?.error("\u5173\u95ED PostHog \u5931\u8D25:", error);
|
|
1133
|
+
}
|
|
1134
|
+
posthogClient = null;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1025
1138
|
// src/server/websocket-server.ts
|
|
1026
1139
|
var MGServer = class {
|
|
1027
1140
|
wss = null;
|
|
@@ -1053,6 +1166,7 @@ var MGServer = class {
|
|
|
1053
1166
|
this.startedAt = /* @__PURE__ */ new Date();
|
|
1054
1167
|
this.logger.info(`Server \u542F\u52A8\u6210\u529F\uFF0C\u76D1\u542C\u7AEF\u53E3: ${port}`);
|
|
1055
1168
|
this.connectionManager.startHeartbeatCheck(HEARTBEAT_INTERVAL);
|
|
1169
|
+
initServerAnalytics(this.logger);
|
|
1056
1170
|
resolve2(port);
|
|
1057
1171
|
});
|
|
1058
1172
|
this.wss.on("error", (error) => {
|
|
@@ -1112,6 +1226,10 @@ var MGServer = class {
|
|
|
1112
1226
|
this.handleRegister(ws, message);
|
|
1113
1227
|
return;
|
|
1114
1228
|
}
|
|
1229
|
+
if (message.type === "track_analytics" /* TRACK_ANALYTICS */) {
|
|
1230
|
+
this.handleTrackAnalytics(message);
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1115
1233
|
const managedWs = ws;
|
|
1116
1234
|
if (!managedWs.connectionId) {
|
|
1117
1235
|
this.logger.warn("\u672A\u6CE8\u518C\u7684\u8FDE\u63A5\u53D1\u9001\u6D88\u606F\uFF0C\u5FFD\u7565");
|
|
@@ -1189,6 +1307,9 @@ var MGServer = class {
|
|
|
1189
1307
|
case "navigate_to_node" /* NAVIGATE_TO_NODE */:
|
|
1190
1308
|
this.handleNavigateToNode(ws, message);
|
|
1191
1309
|
break;
|
|
1310
|
+
case "track_analytics" /* TRACK_ANALYTICS */:
|
|
1311
|
+
this.handleTrackAnalytics(message);
|
|
1312
|
+
break;
|
|
1192
1313
|
case "response" /* RESPONSE */:
|
|
1193
1314
|
case "error" /* ERROR */:
|
|
1194
1315
|
this.requestHandler.handleResponse(message);
|
|
@@ -1334,6 +1455,15 @@ var MGServer = class {
|
|
|
1334
1455
|
}
|
|
1335
1456
|
});
|
|
1336
1457
|
}
|
|
1458
|
+
/**
|
|
1459
|
+
* 处理统计事件
|
|
1460
|
+
*/
|
|
1461
|
+
handleTrackAnalytics(message) {
|
|
1462
|
+
const eventData = message.data;
|
|
1463
|
+
if (eventData) {
|
|
1464
|
+
trackEvent(eventData);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1337
1467
|
/**
|
|
1338
1468
|
* 处理节点导航请求
|
|
1339
1469
|
*/
|
|
@@ -1407,6 +1537,7 @@ var MGServer = class {
|
|
|
1407
1537
|
return;
|
|
1408
1538
|
}
|
|
1409
1539
|
this.logger.info("\u6B63\u5728\u505C\u6B62 Server...");
|
|
1540
|
+
await shutdownServerAnalytics();
|
|
1410
1541
|
this.requestHandler.cleanupAll();
|
|
1411
1542
|
this.connectionManager.closeAll();
|
|
1412
1543
|
return new Promise((resolve2) => {
|
|
@@ -1738,12 +1869,14 @@ export {
|
|
|
1738
1869
|
formatLogTime,
|
|
1739
1870
|
generateId,
|
|
1740
1871
|
generateMgpLink,
|
|
1872
|
+
generateMultiNodeMgpLink,
|
|
1741
1873
|
generatePageLink,
|
|
1742
1874
|
getCurrentISOTime,
|
|
1743
1875
|
isDesignPageUrl,
|
|
1744
1876
|
isProcessRunning,
|
|
1745
1877
|
killProcess,
|
|
1746
1878
|
normalizePageUrl,
|
|
1879
|
+
normalizePageUrlWithPageId,
|
|
1747
1880
|
parseMgpLink,
|
|
1748
1881
|
readServerInfo,
|
|
1749
1882
|
resolveOutputPath,
|