@hangox/mg-cli 1.1.1 → 1.1.2

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 CHANGED
@@ -231,17 +231,22 @@ function parseMgpLink(link) {
231
231
  if (questionMarkIndex === -1) {
232
232
  return null;
233
233
  }
234
- const pageUrl = urlPart.slice(0, questionMarkIndex);
234
+ const basePath = urlPart.slice(0, questionMarkIndex);
235
235
  const queryString = urlPart.slice(questionMarkIndex + 1);
236
236
  const params = new URLSearchParams(queryString);
237
237
  const encodedNodeId = params.get("nodeId");
238
238
  const encodedPageId = params.get("pageId");
239
+ const mgPageId = params.get("page_id");
239
240
  if (!encodedNodeId && !encodedPageId) {
240
241
  return null;
241
242
  }
242
243
  if (encodedNodeId && encodedPageId) {
243
244
  return null;
244
245
  }
246
+ let pageUrl = basePath;
247
+ if (mgPageId) {
248
+ pageUrl = `${basePath}?page_id=${mgPageId}`;
249
+ }
245
250
  if (encodedNodeId) {
246
251
  const nodeId = decodeURIComponent(encodedNodeId);
247
252
  if (!/^(\d+:\d+)(\/\d+:\d+)*$/.test(nodeId)) {
@@ -256,10 +261,19 @@ function parseMgpLink(link) {
256
261
  return null;
257
262
  }
258
263
  }
264
+ const childNodeIdsRaw = params.get("childNodeIds");
265
+ let childNodeIds;
266
+ if (childNodeIdsRaw) {
267
+ childNodeIds = childNodeIdsRaw.split(",").map((id) => decodeURIComponent(id));
268
+ if (!childNodeIds.every((id) => /^(\d+:\d+)(\/\d+:\d+)*$/.test(id))) {
269
+ return null;
270
+ }
271
+ }
259
272
  return {
260
273
  pageUrl,
261
274
  nodeId,
262
- nodePath
275
+ nodePath,
276
+ childNodeIds
263
277
  };
264
278
  }
265
279
  if (encodedPageId) {
@@ -384,6 +398,8 @@ var NODE_DEFAULTS = {
384
398
  dashCap: "NONE",
385
399
  fillStyleId: "",
386
400
  strokeStyleId: "",
401
+ strokeFillStyleId: "",
402
+ strokeWidthStyleId: "",
387
403
  // Corner 属性
388
404
  cornerSmooth: 0,
389
405
  cornerRadius: 0,
@@ -391,6 +407,7 @@ var NODE_DEFAULTS = {
391
407
  topRightRadius: 0,
392
408
  bottomLeftRadius: 0,
393
409
  bottomRightRadius: 0,
410
+ cornerRadiusStyleId: "",
394
411
  // Layout 属性
395
412
  rotation: 0,
396
413
  flexGrow: 0,
@@ -406,9 +423,13 @@ var NODE_DEFAULTS = {
406
423
  paddingRight: 0,
407
424
  paddingBottom: 0,
408
425
  paddingLeft: 0,
426
+ paddingStyleId: "",
427
+ spacingStyleId: "",
409
428
  clipsContent: false,
410
429
  itemReverseZIndex: false,
411
430
  strokesIncludedInLayout: false,
431
+ overflowDirection: "NONE",
432
+ gridStyleId: "",
412
433
  // 其他属性
413
434
  componentPropertyReferences: null
414
435
  };
@@ -419,7 +440,8 @@ var EMPTY_ARRAY_FIELDS = [
419
440
  "strokeDashes",
420
441
  "exportSettings",
421
442
  "reactions",
422
- "attachedConnectors"
443
+ "attachedConnectors",
444
+ "layoutGrids"
423
445
  ];
424
446
  function isEmptyArray(value) {
425
447
  return Array.isArray(value) && value.length === 0;
@@ -1758,10 +1780,98 @@ var MGClient = class {
1758
1780
  }
1759
1781
  };
1760
1782
 
1783
+ // src/cli/analytics.ts
1784
+ import { PostHog } from "posthog-node";
1785
+ import { createHash } from "crypto";
1786
+ import { hostname, userInfo, platform, release } from "os";
1787
+ var POSTHOG_API_KEY = "phc_cSZZIxZOPhWOlsw92Wz8tmKQ5z8eQYsI3m9aM2Ujia9";
1788
+ var POSTHOG_HOST = "https://us.i.posthog.com";
1789
+ var posthogClient = null;
1790
+ var machineId = null;
1791
+ function isTelemetryDisabled() {
1792
+ 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";
1793
+ }
1794
+ function getMachineId() {
1795
+ if (machineId) {
1796
+ return machineId;
1797
+ }
1798
+ try {
1799
+ const hostName = hostname();
1800
+ const userName = userInfo().username;
1801
+ const raw = `${hostName}-${userName}-mg-cli`;
1802
+ machineId = createHash("sha256").update(raw).digest("hex").substring(0, 16);
1803
+ } catch {
1804
+ machineId = createHash("sha256").update(Math.random().toString()).digest("hex").substring(0, 16);
1805
+ }
1806
+ return machineId;
1807
+ }
1808
+ function getClient() {
1809
+ if (isTelemetryDisabled()) {
1810
+ return null;
1811
+ }
1812
+ if (!posthogClient) {
1813
+ posthogClient = new PostHog(POSTHOG_API_KEY, {
1814
+ host: POSTHOG_HOST,
1815
+ // CLI 工具使用立即刷新模式
1816
+ flushAt: 1,
1817
+ flushInterval: 0
1818
+ });
1819
+ }
1820
+ return posthogClient;
1821
+ }
1822
+ function trackCommand(properties) {
1823
+ const client = getClient();
1824
+ if (!client) {
1825
+ return;
1826
+ }
1827
+ try {
1828
+ client.capture({
1829
+ distinctId: getMachineId(),
1830
+ event: "cli_command",
1831
+ properties: {
1832
+ ...properties,
1833
+ version: getVersion(),
1834
+ os: platform(),
1835
+ os_release: release(),
1836
+ node_version: process.version
1837
+ }
1838
+ });
1839
+ } catch {
1840
+ }
1841
+ }
1842
+ function createCommandTracker(commandName) {
1843
+ const startTime = Date.now();
1844
+ return {
1845
+ /**
1846
+ * 记录命令成功
1847
+ */
1848
+ success() {
1849
+ trackCommand({
1850
+ command: commandName,
1851
+ success: true,
1852
+ duration_ms: Date.now() - startTime
1853
+ });
1854
+ },
1855
+ /**
1856
+ * 记录命令失败
1857
+ */
1858
+ failure(error) {
1859
+ trackCommand({
1860
+ command: commandName,
1861
+ success: false,
1862
+ duration_ms: Date.now() - startTime,
1863
+ error_code: error && "code" in error ? String(error.code) : void 0,
1864
+ error_message: error?.message
1865
+ });
1866
+ }
1867
+ };
1868
+ }
1869
+
1761
1870
  // src/cli/commands/server.ts
1762
1871
  function createServerCommand() {
1763
1872
  const serverCmd = new Command("server").description("Server \u7BA1\u7406\u547D\u4EE4");
1764
1873
  serverCmd.command("start").description("\u542F\u52A8 MG Server").option("--port <number>", "\u6307\u5B9A\u542F\u52A8\u7AEF\u53E3", (value) => parseInt(value, 10)).option("--foreground", "\u524D\u53F0\u6A21\u5F0F\u8FD0\u884C\uFF08\u4E0D\u4F5C\u4E3A\u5B88\u62A4\u8FDB\u7A0B\uFF09", false).action(async (options) => {
1874
+ const tracker = createCommandTracker("server_start");
1765
1875
  try {
1766
1876
  if (options.foreground) {
1767
1877
  await startServerForeground(options.port);
@@ -1773,12 +1883,15 @@ function createServerCommand() {
1773
1883
  console.log(`\u8FDB\u7A0B PID: ${info.pid}`);
1774
1884
  console.log(`\u8FD0\u884C\u6A21\u5F0F: \u5B88\u62A4\u8FDB\u7A0B`);
1775
1885
  }
1886
+ tracker.success();
1776
1887
  } catch (error) {
1777
1888
  console.error(`\u9519\u8BEF: ${error.message}`);
1889
+ tracker.failure(error);
1778
1890
  process.exit(1);
1779
1891
  }
1780
1892
  });
1781
1893
  serverCmd.command("stop").description("\u505C\u6B62 MG Server").action(() => {
1894
+ const tracker = createCommandTracker("server_stop");
1782
1895
  try {
1783
1896
  const { stopped, info } = stopServer();
1784
1897
  if (stopped && info) {
@@ -1800,12 +1913,15 @@ function createServerCommand() {
1800
1913
  } else {
1801
1914
  console.log("MG Server \u672A\u8FD0\u884C");
1802
1915
  }
1916
+ tracker.success();
1803
1917
  } catch (error) {
1804
1918
  console.error(`\u9519\u8BEF: ${error.message}`);
1919
+ tracker.failure(error);
1805
1920
  process.exit(1);
1806
1921
  }
1807
1922
  });
1808
1923
  serverCmd.command("restart").description("\u91CD\u542F MG Server").option("--port <number>", "\u91CD\u542F\u540E\u4F7F\u7528\u7684\u7AEF\u53E3", (value) => parseInt(value, 10)).action(async (options) => {
1924
+ const tracker = createCommandTracker("server_restart");
1809
1925
  try {
1810
1926
  const status = getServerStatus();
1811
1927
  if (status.running) {
@@ -1816,17 +1932,21 @@ function createServerCommand() {
1816
1932
  console.log(`\u7248\u672C: ${info.version}`);
1817
1933
  console.log(`\u76D1\u542C\u7AEF\u53E3: ${info.port}`);
1818
1934
  console.log(`\u65B0\u8FDB\u7A0B PID: ${info.pid}`);
1935
+ tracker.success();
1819
1936
  } catch (error) {
1820
1937
  console.error(`\u9519\u8BEF: ${error.message}`);
1938
+ tracker.failure(error);
1821
1939
  process.exit(1);
1822
1940
  }
1823
1941
  });
1824
1942
  serverCmd.command("status").description("\u67E5\u770B Server \u8FD0\u884C\u72B6\u6001").action(async () => {
1943
+ const tracker = createCommandTracker("server_status");
1825
1944
  try {
1826
1945
  const basicStatus = getServerStatus();
1827
1946
  if (!basicStatus.running) {
1828
1947
  console.log("MG Server \u72B6\u6001: \u672A\u8FD0\u884C \u2717");
1829
1948
  console.log("\u63D0\u793A: \u4F7F\u7528 'mg-cli server start' \u542F\u52A8 Server");
1949
+ tracker.success();
1830
1950
  return;
1831
1951
  }
1832
1952
  try {
@@ -1858,6 +1978,7 @@ function createServerCommand() {
1858
1978
  console.log(`\u63D0\u793A: \u8BF7\u5B89\u88C5 MG Plugin \u6D4F\u89C8\u5668\u6269\u5C55\u5E76\u5728 Chrome \u4E2D\u6253\u5F00 MasterGo \u9875\u9762`);
1859
1979
  console.log(` \u63D2\u4EF6\u5730\u5740: https://chromewebstore.google.com/detail/mg-plugin/ddhihanlpcdneicohnglnaliefnkaeja`);
1860
1980
  }
1981
+ tracker.success();
1861
1982
  } catch {
1862
1983
  console.log("MG Server \u72B6\u6001: \u8FD0\u884C\u4E2D \u2713");
1863
1984
  if (basicStatus.version) {
@@ -1869,9 +1990,11 @@ function createServerCommand() {
1869
1990
  console.log(`\u8FD0\u884C\u65F6\u957F: ${basicStatus.uptime}`);
1870
1991
  console.log(``);
1871
1992
  console.log(`\u6CE8\u610F: \u65E0\u6CD5\u83B7\u53D6\u8BE6\u7EC6\u8FDE\u63A5\u4FE1\u606F`);
1993
+ tracker.success();
1872
1994
  }
1873
1995
  } catch (error) {
1874
1996
  console.error(`\u9519\u8BEF: ${error.message}`);
1997
+ tracker.failure(error);
1875
1998
  process.exit(1);
1876
1999
  }
1877
2000
  });
@@ -1889,6 +2012,7 @@ function createGetNodeByIdCommand() {
1889
2012
  });
1890
2013
  }
1891
2014
  async function handleGetNodeById(options) {
2015
+ const tracker = createCommandTracker("get_node_by_id");
1892
2016
  const client = new MGClient({
1893
2017
  noAutoStart: options.noAutoStart,
1894
2018
  noRetry: options.noRetry
@@ -1922,8 +2046,10 @@ async function handleGetNodeById(options) {
1922
2046
  if (!options.raw) {
1923
2047
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1924
2048
  }
2049
+ tracker.success();
1925
2050
  } catch (error) {
1926
2051
  console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2052
+ tracker.failure(error instanceof Error ? error : void 0);
1927
2053
  process.exit(1);
1928
2054
  } finally {
1929
2055
  client.close();
@@ -1941,6 +2067,7 @@ function createGetNodeByLinkCommand() {
1941
2067
  });
1942
2068
  }
1943
2069
  async function handleGetNodeByLink(options) {
2070
+ const tracker = createCommandTracker("get_node_by_link");
1944
2071
  const parsed = parseMgpLink(options.link);
1945
2072
  if (!parsed) {
1946
2073
  console.error(`\u9519\u8BEF [${"E010" /* INVALID_LINK */}]: \u65E0\u6548\u7684 mgp:// \u94FE\u63A5\u683C\u5F0F`);
@@ -1948,10 +2075,12 @@ async function handleGetNodeByLink(options) {
1948
2075
  console.error(`\u671F\u671B\u683C\u5F0F:`);
1949
2076
  console.error(` \u8282\u70B9\u94FE\u63A5: mgp://[mastergo_page_url]?nodeId=[\u8282\u70B9ID]`);
1950
2077
  console.error(` \u9875\u9762\u94FE\u63A5: mgp://[mastergo_page_url]?pageId=[\u9875\u9762ID]`);
2078
+ tracker.failure({ code: "E010" /* INVALID_LINK */, message: "\u65E0\u6548\u7684 mgp:// \u94FE\u63A5\u683C\u5F0F" });
1951
2079
  process.exit(1);
1952
2080
  }
1953
- const { pageUrl, nodeId, pageId } = parsed;
2081
+ const { pageUrl, nodeId, pageId, childNodeIds } = parsed;
1954
2082
  const isPageLink = !!pageId;
2083
+ const isMultiSelect = childNodeIds && childNodeIds.length > 0;
1955
2084
  const client = new MGClient({
1956
2085
  noAutoStart: options.noAutoStart,
1957
2086
  noRetry: options.noRetry
@@ -1974,7 +2103,9 @@ async function handleGetNodeByLink(options) {
1974
2103
  const params = {
1975
2104
  nodeId,
1976
2105
  maxDepth: parseInt(options.maxDepth || "1", 10),
1977
- includeInvisible: options.includeInvisible || false
2106
+ includeInvisible: options.includeInvisible || false,
2107
+ // 多选模式:传递 childNodeIds 进行过滤
2108
+ ...isMultiSelect && { childNodeIds }
1978
2109
  };
1979
2110
  data = await client.requestWithRetry(
1980
2111
  "get_node_by_id" /* GET_NODE_BY_ID */,
@@ -1998,7 +2129,12 @@ async function handleGetNodeByLink(options) {
1998
2129
  console.log(`\u7C7B\u578B: \u9875\u9762`);
1999
2130
  } else {
2000
2131
  console.log(`\u8282\u70B9 ID: ${nodeId}`);
2001
- console.log(`\u7C7B\u578B: \u8282\u70B9`);
2132
+ if (isMultiSelect) {
2133
+ console.log(`\u7C7B\u578B: \u591A\u9009\u8282\u70B9 (\u516C\u5171\u7236\u5143\u7D20)`);
2134
+ console.log(`\u9009\u4E2D\u5B50\u8282\u70B9: ${childNodeIds.length} \u4E2A`);
2135
+ } else {
2136
+ console.log(`\u7C7B\u578B: \u8282\u70B9`);
2137
+ }
2002
2138
  }
2003
2139
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
2004
2140
  console.log(`\u904D\u5386\u6DF1\u5EA6: ${options.maxDepth || "1"}`);
@@ -2006,11 +2142,14 @@ async function handleGetNodeByLink(options) {
2006
2142
  if (!options.raw) {
2007
2143
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
2008
2144
  }
2145
+ tracker.success();
2009
2146
  } catch (error) {
2010
2147
  if (error instanceof MGError) {
2011
2148
  console.error(`\u9519\u8BEF [${error.code}]: ${error.message}`);
2149
+ tracker.failure(error);
2012
2150
  } else {
2013
2151
  console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2152
+ tracker.failure(error instanceof Error ? error : void 0);
2014
2153
  }
2015
2154
  process.exit(1);
2016
2155
  } finally {
@@ -2390,6 +2529,7 @@ async function handleGetNodeForSpace(options) {
2390
2529
  let pageUrl;
2391
2530
  let nodeId;
2392
2531
  let pageId;
2532
+ let childNodeIds;
2393
2533
  let isPageMode = false;
2394
2534
  if (options.link) {
2395
2535
  const parsed = parseMgpLink(options.link);
@@ -2400,6 +2540,7 @@ async function handleGetNodeForSpace(options) {
2400
2540
  process.exit(1);
2401
2541
  }
2402
2542
  pageUrl = parsed.pageUrl;
2543
+ childNodeIds = parsed.childNodeIds;
2403
2544
  if (parsed.pageId) {
2404
2545
  isPageMode = true;
2405
2546
  pageId = parsed.pageId;
@@ -2438,10 +2579,13 @@ async function handleGetNodeForSpace(options) {
2438
2579
  pageUrl
2439
2580
  );
2440
2581
  } else {
2582
+ const isMultiSelect = childNodeIds && childNodeIds.length > 0;
2441
2583
  const params = {
2442
2584
  nodeId,
2443
2585
  maxDepth,
2444
- includeInvisible
2586
+ includeInvisible,
2587
+ // 多选模式:传递 childNodeIds 进行过滤
2588
+ ...isMultiSelect && { childNodeIds }
2445
2589
  };
2446
2590
  data = await client.requestWithRetry(
2447
2591
  "get_node_by_id" /* GET_NODE_BY_ID */,
@@ -3014,8 +3158,9 @@ async function handleVisualize(options) {
3014
3158
  console.error(` \u9875\u9762\u94FE\u63A5: mgp://[mastergo_page_url]?pageId=[\u9875\u9762ID]`);
3015
3159
  process.exit(1);
3016
3160
  }
3017
- const { pageUrl, nodeId, pageId } = parsed;
3161
+ const { pageUrl, nodeId, pageId, childNodeIds } = parsed;
3018
3162
  const isPageLink = !!pageId;
3163
+ const isMultiSelect = childNodeIds && childNodeIds.length > 0;
3019
3164
  const client = new MGClient({
3020
3165
  noAutoStart: options.noAutoStart,
3021
3166
  noRetry: options.noRetry
@@ -3034,7 +3179,9 @@ async function handleVisualize(options) {
3034
3179
  const params = {
3035
3180
  nodeId,
3036
3181
  maxDepth: parseInt(options.maxDepth || "3", 10),
3037
- includeInvisible: false
3182
+ includeInvisible: false,
3183
+ // 多选模式:传递 childNodeIds 进行过滤
3184
+ ...isMultiSelect && { childNodeIds }
3038
3185
  };
3039
3186
  data = await client.requestWithRetry("get_node_by_id" /* GET_NODE_BY_ID */, params, pageUrl);
3040
3187
  }