@xiaou66/vite-plugin-vue-mcp-next 1.1.0 → 1.1.1

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/index.js CHANGED
@@ -57,6 +57,11 @@ var RESOLVED_VIRTUAL_SNAPDOM_LOADER_ID = `\0${VIRTUAL_SNAPDOM_LOADER_ID}`;
57
57
  var DEFAULT_MCP_CLIENT_SERVER_NAME = "vite-mcp-next";
58
58
  var LEGACY_MCP_CLIENT_SERVER_NAMES = ["vue-mcp-next"];
59
59
  var RUNTIME_PAGE_RECONNECTED_EVENT = "vite-plugin-vue-mcp-next:page-reconnected";
60
+ var RUNTIME_PAGE_CONNECTED_EVENT = "vite-plugin-vue-mcp-next:page-connected";
61
+ var RUNTIME_PAGE_DISCONNECTED_EVENT = "vite-plugin-vue-mcp-next:page-disconnected";
62
+ var RUNTIME_PAGE_HEARTBEAT_EVENT = "vite-plugin-vue-mcp-next:heartbeat";
63
+ var DEFAULT_RUNTIME_PAGE_HEARTBEAT_TIMEOUT_MS = 45e3;
64
+ var DEFAULT_RUNTIME_PAGE_HEARTBEAT_SCAN_INTERVAL_MS = 45e3;
60
65
  var DEFAULT_OPTIONS = {
61
66
  mcpPath: DEFAULT_MCP_PATH,
62
67
  host: "localhost",
@@ -2912,32 +2917,53 @@ function vueMcpNext(userOptions = {}) {
2912
2917
  () => createMcpServer(ctx, server),
2913
2918
  server
2914
2919
  );
2915
- server.ws.on(
2916
- "vite-plugin-vue-mcp-next:page-connected",
2917
- (payload) => {
2918
- if (isRuntimePageTarget(payload)) {
2919
- ctx.pages.upsert(payload);
2920
- void ctx.hooks.callHook(RUNTIME_PAGE_RECONNECTED_EVENT, payload);
2921
- void cdpLifecycle.connectPage(payload);
2920
+ const lastSeenAt = /* @__PURE__ */ new Map();
2921
+ const heartbeatTimer = setInterval(() => {
2922
+ const now = Date.now();
2923
+ for (const [pageId, seenAt] of lastSeenAt) {
2924
+ const target = ctx.pages.get(pageId);
2925
+ if (!target || target.source !== "runtime" || !target.connected) {
2926
+ lastSeenAt.delete(pageId);
2927
+ continue;
2922
2928
  }
2923
- }
2924
- );
2925
- server.ws.on(
2926
- "vite-plugin-vue-mcp-next:console-record",
2927
- (payload) => {
2928
- if (isConsoleRecord(payload)) {
2929
- ctx.consoleRecords.push(payload);
2929
+ if (now - seenAt >= DEFAULT_RUNTIME_PAGE_HEARTBEAT_TIMEOUT_MS) {
2930
+ ctx.pages.disconnect(pageId, now);
2931
+ lastSeenAt.delete(pageId);
2930
2932
  }
2931
2933
  }
2932
- );
2933
- server.ws.on(
2934
- "vite-plugin-vue-mcp-next:network-record",
2935
- (payload) => {
2936
- if (isNetworkRecord(payload)) {
2937
- ctx.networkRecords.push(payload);
2934
+ }, DEFAULT_RUNTIME_PAGE_HEARTBEAT_SCAN_INTERVAL_MS);
2935
+ server.ws.on(RUNTIME_PAGE_CONNECTED_EVENT, (payload) => {
2936
+ if (isRuntimePageTarget(payload)) {
2937
+ ctx.pages.upsert(payload);
2938
+ lastSeenAt.set(payload.pageId, Date.now());
2939
+ void ctx.hooks.callHook(RUNTIME_PAGE_RECONNECTED_EVENT, payload);
2940
+ void cdpLifecycle.connectPage(payload);
2941
+ }
2942
+ });
2943
+ server.ws.on(RUNTIME_PAGE_HEARTBEAT_EVENT, (payload) => {
2944
+ if (isRuntimeHeartbeatTarget(payload)) {
2945
+ const target = ctx.pages.get(payload.pageId);
2946
+ if (target?.source === "runtime" && target.connected) {
2947
+ lastSeenAt.set(payload.pageId, payload.timestamp);
2938
2948
  }
2939
2949
  }
2940
- );
2950
+ });
2951
+ server.ws.on(RUNTIME_PAGE_DISCONNECTED_EVENT, (payload) => {
2952
+ if (isRuntimeDisconnectTarget(payload)) {
2953
+ ctx.pages.disconnect(payload.pageId);
2954
+ lastSeenAt.delete(payload.pageId);
2955
+ }
2956
+ });
2957
+ server.ws.on("vite-plugin-vue-mcp-next:console-record", (payload) => {
2958
+ if (isConsoleRecord(payload)) {
2959
+ ctx.consoleRecords.push(payload);
2960
+ }
2961
+ });
2962
+ server.ws.on("vite-plugin-vue-mcp-next:network-record", (payload) => {
2963
+ if (isNetworkRecord(payload)) {
2964
+ ctx.networkRecords.push(payload);
2965
+ }
2966
+ });
2941
2967
  server.ws.on(
2942
2968
  "vite-plugin-vue-mcp-next:performance-record",
2943
2969
  (payload) => {
@@ -2967,6 +2993,7 @@ function vueMcpNext(userOptions = {}) {
2967
2993
  }, 300);
2968
2994
  }
2969
2995
  server.httpServer?.once("close", () => {
2996
+ clearInterval(heartbeatTimer);
2970
2997
  void cdpLifecycle.closeAll();
2971
2998
  });
2972
2999
  },
@@ -2991,6 +3018,20 @@ function isRuntimePageTarget(payload) {
2991
3018
  const target = payload;
2992
3019
  return target.source === "runtime" && typeof target.pageId === "string" && typeof target.url === "string" && typeof target.pathname === "string" && typeof target.connected === "boolean" && (target.runtimeClientId === void 0 || typeof target.runtimeClientId === "string");
2993
3020
  }
3021
+ function isRuntimeHeartbeatTarget(payload) {
3022
+ if (!payload || typeof payload !== "object") {
3023
+ return false;
3024
+ }
3025
+ const target = payload;
3026
+ return typeof target.pageId === "string" && typeof target.timestamp === "number";
3027
+ }
3028
+ function isRuntimeDisconnectTarget(payload) {
3029
+ if (!payload || typeof payload !== "object") {
3030
+ return false;
3031
+ }
3032
+ const target = payload;
3033
+ return typeof target.pageId === "string";
3034
+ }
2994
3035
  function isConsoleRecord(payload) {
2995
3036
  if (!payload || typeof payload !== "object") {
2996
3037
  return false;