@frontmcp/plugin-dashboard 1.8.6 → 1.8.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/esm/index.mjs CHANGED
@@ -432,7 +432,6 @@ import {
432
432
  import { MCP_ERROR_CODES, PublicMcpError } from "@frontmcp/sdk";
433
433
 
434
434
  // libs/utils/dist/esm/index.mjs
435
- import { createRequire as __frontmcpCreateRequire } from "module";
436
435
  import { z as z2 } from "@frontmcp/lazy-zod";
437
436
  var import_event_emitter = __toESM(require_node_event_emitter(), 1);
438
437
  import { z as z22 } from "@frontmcp/lazy-zod";
@@ -445,7 +444,8 @@ import { randomBytes as nobleRandomBytes } from "@noble/hashes/utils.js";
445
444
  import { gcm } from "@noble/ciphers/aes.js";
446
445
  import { analyzeForReDoS, REDOS_THRESHOLDS } from "@enclave-vm/ast";
447
446
  import { z as z3 } from "@frontmcp/lazy-zod";
448
- var require2 = __frontmcpCreateRequire(import.meta.url || "file:///");
447
+ var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : void 0;
448
+ var require2 = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || "file:///") : void 0;
449
449
  var __defProp2 = Object.defineProperty;
450
450
  var __getOwnPropNames2 = Object.getOwnPropertyNames;
451
451
  var __require2 = /* @__PURE__ */ ((x) => typeof require2 !== "undefined" ? require2 : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -2687,6 +2687,39 @@ var init_crypto = __esm({
2687
2687
  HKDF_SHA256_MAX_LENGTH = 255 * 32;
2688
2688
  }
2689
2689
  });
2690
+ function attachRedisErrorListener(client, options = {}) {
2691
+ const label = options.label ?? "redis";
2692
+ const intervalMs = options.intervalMs ?? DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;
2693
+ let lastLoggedAt = 0;
2694
+ let suppressed = 0;
2695
+ const listener = (error) => {
2696
+ const now = Date.now();
2697
+ if (lastLoggedAt !== 0 && now - lastLoggedAt < intervalMs) {
2698
+ suppressed++;
2699
+ return;
2700
+ }
2701
+ const extra = suppressed > 0 ? ` (${suppressed} similar error(s) suppressed)` : "";
2702
+ suppressed = 0;
2703
+ lastLoggedAt = now;
2704
+ const message = `[${label}] Redis connection error: ${error?.message ?? String(error)}${extra}`;
2705
+ if (options.logger) {
2706
+ options.logger.warn(message);
2707
+ } else {
2708
+ console.warn(message);
2709
+ }
2710
+ };
2711
+ client.on("error", listener);
2712
+ return () => {
2713
+ client.removeListener("error", listener);
2714
+ };
2715
+ }
2716
+ var DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;
2717
+ var init_redis_error_listener = __esm({
2718
+ "libs/utils/src/storage/redis-error-listener.ts"() {
2719
+ "use strict";
2720
+ DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS = 3e4;
2721
+ }
2722
+ });
2690
2723
  var init_utils = __esm({
2691
2724
  "libs/utils/src/storage/utils/index.ts"() {
2692
2725
  "use strict";
@@ -2695,7 +2728,8 @@ var init_utils = __esm({
2695
2728
  });
2696
2729
  var redis_exports = {};
2697
2730
  __export(redis_exports, {
2698
- RedisStorageAdapter: () => RedisStorageAdapter
2731
+ RedisStorageAdapter: () => RedisStorageAdapter,
2732
+ createRedisClient: () => createRedisClient
2699
2733
  });
2700
2734
  function getRedisClass() {
2701
2735
  try {
@@ -2713,11 +2747,26 @@ function getRedisClass() {
2713
2747
  });
2714
2748
  }
2715
2749
  }
2750
+ function createRedisClient(options) {
2751
+ const RedisClass = getRedisClass();
2752
+ const baseOptions = { lazyConnect: false, maxRetriesPerRequest: 3 };
2753
+ const client = options.url ? new RedisClass(options.url, baseOptions) : new RedisClass({
2754
+ ...baseOptions,
2755
+ host: options.host ?? "localhost",
2756
+ port: options.port ?? 6379,
2757
+ password: options.password,
2758
+ db: options.db ?? 0,
2759
+ tls: options.tls ? {} : void 0
2760
+ });
2761
+ attachRedisErrorListener(client, { label: options.label ?? "redis", logger: options.logger });
2762
+ return client;
2763
+ }
2716
2764
  var RedisStorageAdapter;
2717
2765
  var init_redis = __esm({
2718
2766
  "libs/utils/src/storage/adapters/redis.ts"() {
2719
2767
  "use strict";
2720
2768
  init_errors();
2769
+ init_redis_error_listener();
2721
2770
  init_utils();
2722
2771
  init_base();
2723
2772
  RedisStorageAdapter = class extends BaseStorageAdapter {
@@ -2726,6 +2775,7 @@ var init_redis = __esm({
2726
2775
  subscriber;
2727
2776
  options;
2728
2777
  ownsClient;
2778
+ detachErrorListener;
2729
2779
  connecting;
2730
2780
  keyPrefix;
2731
2781
  subscriptionHandlers = /* @__PURE__ */ new Map();
@@ -2782,7 +2832,10 @@ var init_redis = __esm({
2782
2832
  await client.ping();
2783
2833
  this.client = client;
2784
2834
  this.connected = true;
2785
- if (this.ownsClient) client.removeListener("error", recordSocketError);
2835
+ if (this.ownsClient) {
2836
+ client.removeListener("error", recordSocketError);
2837
+ this.detachErrorListener = attachRedisErrorListener(client, { label: "RedisStorage" });
2838
+ }
2786
2839
  } catch (e) {
2787
2840
  if (this.ownsClient && client) {
2788
2841
  try {
@@ -2803,6 +2856,8 @@ var init_redis = __esm({
2803
2856
  if (this.ownsClient && this.client) {
2804
2857
  await this.client.quit();
2805
2858
  }
2859
+ this.detachErrorListener?.();
2860
+ this.detachErrorListener = void 0;
2806
2861
  this.client = void 0;
2807
2862
  this.connected = false;
2808
2863
  this.subscriptionHandlers.clear();
@@ -3030,6 +3085,7 @@ var init_redis = __esm({
3030
3085
  } else {
3031
3086
  throw new StorageConfigError("redis", "Cannot create subscriber without url, config, or client");
3032
3087
  }
3088
+ attachRedisErrorListener(subscriber, { label: "RedisStorage:subscriber" });
3033
3089
  subscriber.on("message", (channel, message) => {
3034
3090
  const handlers = this.subscriptionHandlers.get(channel);
3035
3091
  if (handlers) {
@@ -3812,6 +3868,7 @@ var entryAvailabilitySchema = z3.object({
3812
3868
  }).strict();
3813
3869
  init_errors();
3814
3870
  init_memory();
3871
+ init_redis_error_listener();
3815
3872
  init_errors();
3816
3873
  init_crypto();
3817
3874
  init_errors();
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/plugin-dashboard",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "Dashboard plugin for FrontMCP - visual monitoring and introspection of MCP servers",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -47,12 +47,12 @@
47
47
  }
48
48
  },
49
49
  "dependencies": {
50
- "@frontmcp/sdk": "1.8.6"
50
+ "@frontmcp/sdk": "1.8.7"
51
51
  },
52
52
  "devDependencies": {
53
53
  "reflect-metadata": "^0.2.2"
54
54
  },
55
55
  "peerDependencies": {
56
- "@frontmcp/lazy-zod": "1.8.6"
56
+ "@frontmcp/lazy-zod": "1.8.7"
57
57
  }
58
58
  }
package/index.js CHANGED
@@ -443,7 +443,6 @@ var import_sdk7 = require("@frontmcp/sdk");
443
443
  var import_sdk2 = require("@frontmcp/sdk");
444
444
 
445
445
  // libs/utils/dist/esm/index.mjs
446
- var import_module = require("module");
447
446
  var import_lazy_zod2 = require("@frontmcp/lazy-zod");
448
447
  var import_lazy_zod3 = require("@frontmcp/lazy-zod");
449
448
  var import_event_emitter = __toESM(require_node_event_emitter(), 1);
@@ -457,7 +456,8 @@ var import_crypto_provider = __toESM(require_node(), 1);
457
456
  var import_ast = require("@enclave-vm/ast");
458
457
  var import_lazy_zod4 = require("@frontmcp/lazy-zod");
459
458
  var import_meta = {};
460
- var require2 = (0, import_module.createRequire)(import_meta.url || "file:///");
459
+ var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : void 0;
460
+ var require2 = __frontmcpModule ? __frontmcpModule.createRequire(import_meta.url || "file:///") : void 0;
461
461
  var __defProp2 = Object.defineProperty;
462
462
  var __getOwnPropNames2 = Object.getOwnPropertyNames;
463
463
  var __require = /* @__PURE__ */ ((x) => typeof require2 !== "undefined" ? require2 : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -2699,6 +2699,39 @@ var init_crypto = __esm({
2699
2699
  HKDF_SHA256_MAX_LENGTH = 255 * 32;
2700
2700
  }
2701
2701
  });
2702
+ function attachRedisErrorListener(client, options = {}) {
2703
+ const label = options.label ?? "redis";
2704
+ const intervalMs = options.intervalMs ?? DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;
2705
+ let lastLoggedAt = 0;
2706
+ let suppressed = 0;
2707
+ const listener = (error) => {
2708
+ const now = Date.now();
2709
+ if (lastLoggedAt !== 0 && now - lastLoggedAt < intervalMs) {
2710
+ suppressed++;
2711
+ return;
2712
+ }
2713
+ const extra = suppressed > 0 ? ` (${suppressed} similar error(s) suppressed)` : "";
2714
+ suppressed = 0;
2715
+ lastLoggedAt = now;
2716
+ const message = `[${label}] Redis connection error: ${error?.message ?? String(error)}${extra}`;
2717
+ if (options.logger) {
2718
+ options.logger.warn(message);
2719
+ } else {
2720
+ console.warn(message);
2721
+ }
2722
+ };
2723
+ client.on("error", listener);
2724
+ return () => {
2725
+ client.removeListener("error", listener);
2726
+ };
2727
+ }
2728
+ var DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;
2729
+ var init_redis_error_listener = __esm({
2730
+ "libs/utils/src/storage/redis-error-listener.ts"() {
2731
+ "use strict";
2732
+ DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS = 3e4;
2733
+ }
2734
+ });
2702
2735
  var init_utils = __esm({
2703
2736
  "libs/utils/src/storage/utils/index.ts"() {
2704
2737
  "use strict";
@@ -2707,7 +2740,8 @@ var init_utils = __esm({
2707
2740
  });
2708
2741
  var redis_exports = {};
2709
2742
  __export2(redis_exports, {
2710
- RedisStorageAdapter: () => RedisStorageAdapter
2743
+ RedisStorageAdapter: () => RedisStorageAdapter,
2744
+ createRedisClient: () => createRedisClient
2711
2745
  });
2712
2746
  function getRedisClass() {
2713
2747
  try {
@@ -2725,11 +2759,26 @@ function getRedisClass() {
2725
2759
  });
2726
2760
  }
2727
2761
  }
2762
+ function createRedisClient(options) {
2763
+ const RedisClass = getRedisClass();
2764
+ const baseOptions = { lazyConnect: false, maxRetriesPerRequest: 3 };
2765
+ const client = options.url ? new RedisClass(options.url, baseOptions) : new RedisClass({
2766
+ ...baseOptions,
2767
+ host: options.host ?? "localhost",
2768
+ port: options.port ?? 6379,
2769
+ password: options.password,
2770
+ db: options.db ?? 0,
2771
+ tls: options.tls ? {} : void 0
2772
+ });
2773
+ attachRedisErrorListener(client, { label: options.label ?? "redis", logger: options.logger });
2774
+ return client;
2775
+ }
2728
2776
  var RedisStorageAdapter;
2729
2777
  var init_redis = __esm({
2730
2778
  "libs/utils/src/storage/adapters/redis.ts"() {
2731
2779
  "use strict";
2732
2780
  init_errors();
2781
+ init_redis_error_listener();
2733
2782
  init_utils();
2734
2783
  init_base();
2735
2784
  RedisStorageAdapter = class extends BaseStorageAdapter {
@@ -2738,6 +2787,7 @@ var init_redis = __esm({
2738
2787
  subscriber;
2739
2788
  options;
2740
2789
  ownsClient;
2790
+ detachErrorListener;
2741
2791
  connecting;
2742
2792
  keyPrefix;
2743
2793
  subscriptionHandlers = /* @__PURE__ */ new Map();
@@ -2794,7 +2844,10 @@ var init_redis = __esm({
2794
2844
  await client.ping();
2795
2845
  this.client = client;
2796
2846
  this.connected = true;
2797
- if (this.ownsClient) client.removeListener("error", recordSocketError);
2847
+ if (this.ownsClient) {
2848
+ client.removeListener("error", recordSocketError);
2849
+ this.detachErrorListener = attachRedisErrorListener(client, { label: "RedisStorage" });
2850
+ }
2798
2851
  } catch (e) {
2799
2852
  if (this.ownsClient && client) {
2800
2853
  try {
@@ -2815,6 +2868,8 @@ var init_redis = __esm({
2815
2868
  if (this.ownsClient && this.client) {
2816
2869
  await this.client.quit();
2817
2870
  }
2871
+ this.detachErrorListener?.();
2872
+ this.detachErrorListener = void 0;
2818
2873
  this.client = void 0;
2819
2874
  this.connected = false;
2820
2875
  this.subscriptionHandlers.clear();
@@ -3042,6 +3097,7 @@ var init_redis = __esm({
3042
3097
  } else {
3043
3098
  throw new StorageConfigError("redis", "Cannot create subscriber without url, config, or client");
3044
3099
  }
3100
+ attachRedisErrorListener(subscriber, { label: "RedisStorage:subscriber" });
3045
3101
  subscriber.on("message", (channel, message) => {
3046
3102
  const handlers = this.subscriptionHandlers.get(channel);
3047
3103
  if (handlers) {
@@ -3824,6 +3880,7 @@ var entryAvailabilitySchema = import_lazy_zod4.z.object({
3824
3880
  }).strict();
3825
3881
  init_errors();
3826
3882
  init_memory();
3883
+ init_redis_error_listener();
3827
3884
  init_errors();
3828
3885
  init_crypto();
3829
3886
  init_errors();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/plugin-dashboard",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "Dashboard plugin for FrontMCP - visual monitoring and introspection of MCP servers",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -47,12 +47,12 @@
47
47
  }
48
48
  },
49
49
  "dependencies": {
50
- "@frontmcp/sdk": "1.8.6"
50
+ "@frontmcp/sdk": "1.8.7"
51
51
  },
52
52
  "devDependencies": {
53
53
  "reflect-metadata": "^0.2.2"
54
54
  },
55
55
  "peerDependencies": {
56
- "@frontmcp/lazy-zod": "1.8.6"
56
+ "@frontmcp/lazy-zod": "1.8.7"
57
57
  }
58
58
  }