express-performance-toolkit 1.0.0 → 2.0.0

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.
Files changed (78) hide show
  1. package/README.md +119 -76
  2. package/dashboard-ui/README.md +73 -0
  3. package/dashboard-ui/eslint.config.js +23 -0
  4. package/dashboard-ui/index.html +13 -0
  5. package/dashboard-ui/package-lock.json +3382 -0
  6. package/dashboard-ui/package.json +32 -0
  7. package/dashboard-ui/src/App.css +184 -0
  8. package/dashboard-ui/src/App.tsx +182 -0
  9. package/dashboard-ui/src/components/BlockedModal.tsx +108 -0
  10. package/dashboard-ui/src/components/CachePanel.tsx +45 -0
  11. package/dashboard-ui/src/components/HealthCharts.tsx +142 -0
  12. package/dashboard-ui/src/components/InsightsPanel.tsx +49 -0
  13. package/dashboard-ui/src/components/KpiGrid.tsx +178 -0
  14. package/dashboard-ui/src/components/LiveLogs.tsx +76 -0
  15. package/dashboard-ui/src/components/Login.tsx +83 -0
  16. package/dashboard-ui/src/components/RoutesTable.tsx +110 -0
  17. package/dashboard-ui/src/hooks/useMetrics.ts +131 -0
  18. package/dashboard-ui/src/index.css +652 -0
  19. package/dashboard-ui/src/main.tsx +10 -0
  20. package/dashboard-ui/src/pages/InsightsPage.tsx +42 -0
  21. package/dashboard-ui/src/pages/LogsPage.tsx +26 -0
  22. package/dashboard-ui/src/pages/OverviewPage.tsx +32 -0
  23. package/dashboard-ui/src/pages/RoutesPage.tsx +26 -0
  24. package/dashboard-ui/src/utils/formatters.ts +27 -0
  25. package/dashboard-ui/tsconfig.app.json +28 -0
  26. package/dashboard-ui/tsconfig.json +7 -0
  27. package/dashboard-ui/tsconfig.node.json +26 -0
  28. package/dashboard-ui/vite.config.ts +12 -0
  29. package/dist/analyzer.d.ts +6 -0
  30. package/dist/analyzer.d.ts.map +1 -0
  31. package/dist/analyzer.js +70 -0
  32. package/dist/analyzer.js.map +1 -0
  33. package/dist/dashboard/dashboardRouter.d.ts +4 -4
  34. package/dist/dashboard/dashboardRouter.d.ts.map +1 -1
  35. package/dist/dashboard/dashboardRouter.js +67 -21
  36. package/dist/dashboard/dashboardRouter.js.map +1 -1
  37. package/dist/dashboard-ui/assets/index-CX-zE-Qy.css +1 -0
  38. package/dist/dashboard-ui/assets/index-Q9TGkd8n.js +41 -0
  39. package/dist/dashboard-ui/index.html +14 -0
  40. package/dist/index.d.ts +11 -10
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +35 -11
  43. package/dist/index.js.map +1 -1
  44. package/dist/logger.d.ts +3 -3
  45. package/dist/logger.d.ts.map +1 -1
  46. package/dist/logger.js +167 -9
  47. package/dist/logger.js.map +1 -1
  48. package/dist/queryHelper.d.ts.map +1 -1
  49. package/dist/queryHelper.js +1 -0
  50. package/dist/queryHelper.js.map +1 -1
  51. package/dist/rateLimit.d.ts +5 -0
  52. package/dist/rateLimit.d.ts.map +1 -0
  53. package/dist/rateLimit.js +67 -0
  54. package/dist/rateLimit.js.map +1 -0
  55. package/dist/store.d.ts +9 -2
  56. package/dist/store.d.ts.map +1 -1
  57. package/dist/store.js +147 -25
  58. package/dist/store.js.map +1 -1
  59. package/dist/types.d.ts +93 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/example/server.ts +68 -37
  62. package/package.json +9 -6
  63. package/src/analyzer.ts +78 -0
  64. package/src/dashboard/dashboardRouter.ts +88 -23
  65. package/src/index.ts +70 -30
  66. package/src/logger.ts +177 -13
  67. package/src/queryHelper.ts +2 -0
  68. package/src/rateLimit.ts +86 -0
  69. package/src/store.ts +136 -27
  70. package/src/types.ts +98 -0
  71. package/tests/analyzer.test.ts +108 -0
  72. package/tests/auth.test.ts +79 -0
  73. package/tests/bandwidth.test.ts +72 -0
  74. package/tests/integration.test.ts +51 -54
  75. package/tests/rateLimit.test.ts +57 -0
  76. package/tests/store.test.ts +37 -18
  77. package/tsconfig.json +1 -0
  78. package/src/dashboard/dashboard.html +0 -756
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Express Performance Toolkit</title>
8
+ <script type="module" crossorigin src="./assets/index-Q9TGkd8n.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-CX-zE-Qy.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Request, Response, NextFunction, Router } from 'express';
2
- import { MetricsStore } from './store';
3
- import { ToolkitOptions, Metrics, CacheMiddleware } from './types';
1
+ import { Request, Response, NextFunction, Router } from "express";
2
+ import { MetricsStore } from "./store";
3
+ import { ToolkitOptions, Metrics, CacheMiddleware } from "./types";
4
4
  export interface ToolkitInstance {
5
5
  /** The composed Express middleware */
6
6
  middleware: (req: Request, res: Response, next: NextFunction) => void;
@@ -35,11 +35,12 @@ export interface ToolkitInstance {
35
35
  * ```
36
36
  */
37
37
  export declare function performanceToolkit(options?: ToolkitOptions): ToolkitInstance;
38
- export { MetricsStore } from './store';
39
- export { LRUCache, createCacheMiddleware } from './cache';
40
- export { createCompressionMiddleware } from './compression';
41
- export { createLoggerMiddleware } from './logger';
42
- export { createQueryHelperMiddleware } from './queryHelper';
43
- export { createDashboardRouter } from './dashboard/dashboardRouter';
44
- export * from './types';
38
+ export { MetricsStore } from "./store";
39
+ export { LRUCache, createCacheMiddleware } from "./cache";
40
+ export { createCompressionMiddleware } from "./compression";
41
+ export { createLoggerMiddleware } from "./logger";
42
+ export { createQueryHelperMiddleware } from "./queryHelper";
43
+ export { createRateLimiter } from "./rateLimit";
44
+ export { createDashboardRouter } from "./dashboard/dashboardRouter";
45
+ export * from "./types";
45
46
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAMvC,OAAO,EACL,cAAc,EAMd,OAAO,EACP,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACtE,0EAA0E;IAC1E,eAAe,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,wBAAwB;IACxB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,6DAA6D;IAC7D,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,mCAAmC;IACnC,KAAK,EAAE,YAAY,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,cAAmB,GAAG,eAAe,CA+DhF;AAmBD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAOvC,OAAO,EACL,cAAc,EAOd,OAAO,EACP,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACtE,0EAA0E;IAC1E,eAAe,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,wBAAwB;IACxB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,6DAA6D;IAC7D,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,mCAAmC;IACnC,KAAK,EAAE,YAAY,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,cAAmB,GAC3B,eAAe,CAoGjB;AAiBD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -14,13 +14,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.createDashboardRouter = exports.createQueryHelperMiddleware = exports.createLoggerMiddleware = exports.createCompressionMiddleware = exports.createCacheMiddleware = exports.LRUCache = exports.MetricsStore = void 0;
17
+ exports.createDashboardRouter = exports.createRateLimiter = exports.createQueryHelperMiddleware = exports.createLoggerMiddleware = exports.createCompressionMiddleware = exports.createCacheMiddleware = exports.LRUCache = exports.MetricsStore = void 0;
18
18
  exports.performanceToolkit = performanceToolkit;
19
19
  const store_1 = require("./store");
20
20
  const cache_1 = require("./cache");
21
21
  const compression_1 = require("./compression");
22
22
  const logger_1 = require("./logger");
23
23
  const queryHelper_1 = require("./queryHelper");
24
+ const rateLimit_1 = require("./rateLimit");
24
25
  const dashboardRouter_1 = require("./dashboard/dashboardRouter");
25
26
  /**
26
27
  * ⚡ Express Performance Toolkit
@@ -45,31 +46,55 @@ function performanceToolkit(options = {}) {
45
46
  const store = new store_1.MetricsStore({ maxLogs: options.maxLogs || 1000 });
46
47
  const middlewares = [];
47
48
  let cacheMiddlewareInstance = null;
49
+ // ── Dashboard Config ─────────────────────────────────────
50
+ const dashboardConfig = normalizeOption(options.dashboard, {
51
+ enabled: true,
52
+ });
53
+ const dashboardExcludePath = dashboardConfig.path || "/__perf";
54
+ // ── Rate Limiter ─────────────────────────────────────────
55
+ const rateLimitConfig = normalizeOption(options.rateLimit, {
56
+ enabled: false,
57
+ });
58
+ if (rateLimitConfig.enabled !== false) {
59
+ // Automatically exclude dashboard from rate limiting to prevent UI lockouts
60
+ rateLimitConfig.exclude = [
61
+ ...(rateLimitConfig.exclude || []),
62
+ dashboardExcludePath,
63
+ ];
64
+ middlewares.push((0, rateLimit_1.createRateLimiter)(store, rateLimitConfig));
65
+ }
48
66
  // ── Compression ──────────────────────────────────────────
49
67
  const compressionConfig = normalizeOption(options.compression, { enabled: true });
50
68
  if (compressionConfig.enabled !== false) {
51
69
  middlewares.push((0, compression_1.createCompressionMiddleware)(compressionConfig));
52
70
  }
53
71
  // ── Query Helper ─────────────────────────────────────────
54
- const queryConfig = normalizeOption(options.queryHelper, { enabled: false });
72
+ const queryConfig = normalizeOption(options.queryHelper, {
73
+ enabled: false,
74
+ });
55
75
  if (queryConfig.enabled !== false) {
56
76
  middlewares.push((0, queryHelper_1.createQueryHelperMiddleware)(queryConfig));
57
77
  }
58
78
  // ── Logger (slow request detection) ──────────────────────
59
- const loggerConfig = normalizeOption(options.logSlowRequests, { enabled: true });
79
+ const loggerConfig = normalizeOption(options.logSlowRequests, {
80
+ enabled: true,
81
+ });
60
82
  if (loggerConfig.enabled !== false) {
61
83
  middlewares.push((0, logger_1.createLoggerMiddleware)(loggerConfig, store));
62
84
  }
63
85
  // ── Cache ────────────────────────────────────────────────
64
- const cacheConfig = normalizeOption(options.cache, { enabled: false });
86
+ const cacheConfig = normalizeOption(options.cache, {
87
+ enabled: false,
88
+ });
65
89
  if (cacheConfig.enabled !== false) {
66
90
  cacheMiddlewareInstance = (0, cache_1.createCacheMiddleware)(cacheConfig, store);
67
91
  middlewares.push(cacheMiddlewareInstance);
68
92
  }
69
93
  // ── Dashboard Router ─────────────────────────────────────
70
- const dashboardConfig = normalizeOption(options.dashboard, { enabled: true });
71
- const dashboardPath = dashboardConfig.path || '/__perf';
72
- const dashboardRouter = (0, dashboardRouter_1.createDashboardRouter)(store, dashboardConfig);
94
+ const dashboardRouter = (0, dashboardRouter_1.createDashboardRouter)(store, {
95
+ ...dashboardConfig,
96
+ path: "/", // Always serve at the root of the provided router
97
+ });
73
98
  // ── Composed Middleware ──────────────────────────────────
74
99
  function composedMiddleware(req, res, next) {
75
100
  let index = 0;
@@ -99,16 +124,13 @@ function performanceToolkit(options = {}) {
99
124
  }
100
125
  /**
101
126
  * Normalize a boolean | object option into a config object.
102
- * - `true` → defaults with enabled: true
103
- * - `false` → defaults with enabled: false
104
- * - object → merged with defaults
105
127
  */
106
128
  function normalizeOption(value, defaults) {
107
129
  if (value === true)
108
130
  return { ...defaults, enabled: true };
109
131
  if (value === false)
110
132
  return { ...defaults, enabled: false };
111
- if (typeof value === 'object')
133
+ if (typeof value === "object")
112
134
  return { ...defaults, ...value, enabled: true };
113
135
  return defaults;
114
136
  }
@@ -124,6 +146,8 @@ var logger_2 = require("./logger");
124
146
  Object.defineProperty(exports, "createLoggerMiddleware", { enumerable: true, get: function () { return logger_2.createLoggerMiddleware; } });
125
147
  var queryHelper_2 = require("./queryHelper");
126
148
  Object.defineProperty(exports, "createQueryHelperMiddleware", { enumerable: true, get: function () { return queryHelper_2.createQueryHelperMiddleware; } });
149
+ var rateLimit_2 = require("./rateLimit");
150
+ Object.defineProperty(exports, "createRateLimiter", { enumerable: true, get: function () { return rateLimit_2.createRateLimiter; } });
127
151
  var dashboardRouter_2 = require("./dashboard/dashboardRouter");
128
152
  Object.defineProperty(exports, "createDashboardRouter", { enumerable: true, get: function () { return dashboardRouter_2.createDashboardRouter; } });
129
153
  __exportStar(require("./types"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/logger.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Request, Response, NextFunction } from 'express';
2
- import { LoggerOptions } from './types';
3
- import { MetricsStore } from './store';
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { LoggerOptions } from "./types";
3
+ import { MetricsStore } from "./store";
4
4
  /**
5
5
  * Create request logging & slow API detection middleware.
6
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAY,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAcvC;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,YAAK,EAC3B,KAAK,EAAE,YAAY,GAClB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CA2D3D"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI1D,OAAO,EAAE,aAAa,EAAY,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA0GvC;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,YAAK,EAC3B,KAAK,EAAE,YAAY,GAClB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAiI3D"}
package/dist/logger.js CHANGED
@@ -1,33 +1,182 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.createLoggerMiddleware = createLoggerMiddleware;
7
40
  const on_finished_1 = __importDefault(require("on-finished"));
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
8
43
  /**
9
44
  * Default log formatter for console output.
10
45
  */
11
46
  function defaultFormatter(entry) {
12
- const slow = entry.slow ? ' 🔥 SLOW' : '';
13
- const cached = entry.cached ? ' [CACHED]' : '';
47
+ const slow = entry.slow ? " 🔥 SLOW" : "";
48
+ const cached = entry.cached ? " [CACHED]" : "";
14
49
  const status = entry.statusCode;
15
50
  const time = `${entry.responseTime}ms`;
16
51
  return `[perf] ${entry.method} ${entry.path} → ${status} ${time}${cached}${slow}`;
17
52
  }
53
+ /**
54
+ * Helper class for managing log file rotation and cleanup.
55
+ */
56
+ class LogRotator {
57
+ constructor(filePath, rotation, maxDays) {
58
+ this.currentStream = null;
59
+ this.currentDateStr = "";
60
+ this.basePath = path.resolve(process.cwd(), filePath);
61
+ this.logDir = path.dirname(this.basePath);
62
+ this.rotation = rotation;
63
+ this.maxDays = maxDays;
64
+ if (!fs.existsSync(this.logDir)) {
65
+ fs.mkdirSync(this.logDir, { recursive: true });
66
+ }
67
+ this.getStream(); // Initialize
68
+ }
69
+ getDateStr(date = new Date()) {
70
+ return date.toISOString().split("T")[0];
71
+ }
72
+ getRotatedPath(dateStr) {
73
+ if (!this.rotation)
74
+ return this.basePath;
75
+ const ext = path.extname(this.basePath);
76
+ const base = path.basename(this.basePath, ext);
77
+ return path.join(this.logDir, `${base}-${dateStr}${ext}`);
78
+ }
79
+ getStream() {
80
+ if (!this.rotation) {
81
+ if (!this.currentStream) {
82
+ this.currentStream = fs.createWriteStream(this.basePath, {
83
+ flags: "a",
84
+ });
85
+ }
86
+ return this.currentStream;
87
+ }
88
+ const todayStr = this.getDateStr();
89
+ if (this.currentDateStr !== todayStr) {
90
+ if (this.currentStream) {
91
+ this.currentStream.end();
92
+ }
93
+ this.currentDateStr = todayStr;
94
+ const newPath = this.getRotatedPath(todayStr);
95
+ this.currentStream = fs.createWriteStream(newPath, { flags: "a" });
96
+ // Run cleanup asynchronously in the background
97
+ this.cleanupOldLogs();
98
+ }
99
+ return this.currentStream;
100
+ }
101
+ cleanupOldLogs() {
102
+ if (!this.rotation || this.maxDays <= 0)
103
+ return;
104
+ fs.readdir(this.logDir, (err, files) => {
105
+ if (err)
106
+ return;
107
+ const ext = path.extname(this.basePath);
108
+ const base = path.basename(this.basePath, ext);
109
+ const prefix = `${base}-`;
110
+ const now = Date.now();
111
+ const maxAgeMs = this.maxDays * 24 * 60 * 60 * 1000;
112
+ files.forEach((file) => {
113
+ if (file.startsWith(prefix) && file.endsWith(ext)) {
114
+ const datePart = file.slice(prefix.length, -ext.length);
115
+ const fileDate = new Date(datePart).getTime();
116
+ if (!isNaN(fileDate) && now - fileDate > maxAgeMs) {
117
+ fs.unlink(path.join(this.logDir, file), (unlinkErr) => {
118
+ if (unlinkErr)
119
+ console.error(`[perf-toolkit] Failed to delete old log: ${file}`);
120
+ });
121
+ }
122
+ }
123
+ });
124
+ });
125
+ }
126
+ }
18
127
  /**
19
128
  * Create request logging & slow API detection middleware.
20
129
  */
21
130
  function createLoggerMiddleware(options = {}, store) {
22
- const { slowThreshold = 1000, console: logToConsole = true, formatter = defaultFormatter, } = options;
131
+ const { slowThreshold = 1000, console: logToConsole = true, file: logFilePath, rotation = false, maxDays = 7, formatter = defaultFormatter, } = options;
132
+ let rotator = null;
133
+ if (logFilePath) {
134
+ try {
135
+ rotator = new LogRotator(logFilePath, rotation, maxDays);
136
+ }
137
+ catch (err) {
138
+ console.error(`[perf-toolkit] Failed to initialize log rotator: ${err}`);
139
+ }
140
+ }
23
141
  return (req, res, next) => {
24
142
  const startTime = Date.now();
143
+ const reqPath = req.originalUrl || req.url;
144
+ // Ignore dashboard API paths
145
+ if (reqPath.includes("/api/metrics") ||
146
+ reqPath.includes("/api/reset") ||
147
+ reqPath.includes("/api/__perf")) {
148
+ return next();
149
+ }
150
+ // Byte counting logic
151
+ let bytesSent = 0;
152
+ const originalWrite = res.write;
153
+ const originalEnd = res.end;
154
+ res.write = function (chunk, encoding, _callback) {
155
+ if (chunk) {
156
+ bytesSent += Buffer.isBuffer(chunk)
157
+ ? chunk.length
158
+ : Buffer.byteLength(chunk, (typeof encoding === "string"
159
+ ? encoding
160
+ : "utf8"));
161
+ }
162
+ return originalWrite.apply(res, arguments);
163
+ };
164
+ res.end = function (chunk, encoding, _callback) {
165
+ if (chunk && typeof chunk !== "function") {
166
+ bytesSent += Buffer.isBuffer(chunk)
167
+ ? chunk.length
168
+ : Buffer.byteLength(chunk, (typeof encoding === "string"
169
+ ? encoding
170
+ : "utf8"));
171
+ }
172
+ return originalEnd.apply(res, arguments);
173
+ };
25
174
  // Attach perf data to request
26
175
  if (!req.perfToolkit) {
27
176
  req.perfToolkit = {
28
177
  startTime,
29
178
  queryCount: 0,
30
- trackQuery: (label) => {
179
+ trackQuery: () => {
31
180
  req.perfToolkit.queryCount++;
32
181
  },
33
182
  };
@@ -35,21 +184,25 @@ function createLoggerMiddleware(options = {}, store) {
35
184
  (0, on_finished_1.default)(res, (_err, finishedRes) => {
36
185
  const responseTime = Date.now() - startTime;
37
186
  const isSlow = responseTime >= slowThreshold;
187
+ // Extract route pattern if available (e.g. /users/:id)
188
+ const routePattern = req.route?.path;
38
189
  const entry = {
39
190
  method: req.method,
40
- path: req.originalUrl || req.url,
191
+ path: reqPath,
192
+ routePattern,
41
193
  statusCode: finishedRes.statusCode,
42
194
  responseTime,
43
195
  timestamp: Date.now(),
44
196
  slow: isSlow,
45
- cached: res.getHeader('X-Cache') === 'HIT',
197
+ cached: res.getHeader("X-Cache") === "HIT",
198
+ highQueries: req.perfToolkit?.highQueries || false,
46
199
  queryCount: req.perfToolkit?.queryCount,
47
- contentLength: parseInt(res.getHeader('content-length'), 10) || undefined,
48
- userAgent: req.get('user-agent'),
200
+ bytesSent,
201
+ userAgent: req.get("user-agent"),
49
202
  ip: req.ip,
50
203
  };
51
204
  // Record in store
52
- store.addLog(entry);
205
+ store.recordLog(entry);
53
206
  if (isSlow) {
54
207
  store.recordSlowRequest();
55
208
  }
@@ -63,6 +216,11 @@ function createLoggerMiddleware(options = {}, store) {
63
216
  console.log(message);
64
217
  }
65
218
  }
219
+ // File output
220
+ if (rotator) {
221
+ const logLine = JSON.stringify(entry) + "\n";
222
+ rotator.getStream().write(logLine);
223
+ }
66
224
  });
67
225
  next();
68
226
  };
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;;;AAoBA,wDA8DC;AAjFD,8DAAqC;AAIrC;;GAEG;AACH,SAAS,gBAAgB,CAAC,KAAe;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;IAChC,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,CAAC;IAEvC,OAAO,UAAU,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,MAAM,IAAI,IAAI,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,SAAgB,sBAAsB,CACpC,UAAyB,EAAE,EAC3B,KAAmB;IAEnB,MAAM,EACJ,aAAa,GAAG,IAAI,EACpB,OAAO,EAAE,YAAY,GAAG,IAAI,EAC5B,SAAS,GAAG,gBAAgB,GAC7B,GAAG,OAAO,CAAC;IAEZ,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;QAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,8BAA8B;QAC9B,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,WAAW,GAAG;gBAChB,SAAS;gBACT,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,CAAC,KAAc,EAAE,EAAE;oBAC7B,GAAG,CAAC,WAAY,CAAC,UAAU,EAAE,CAAC;gBAChC,CAAC;aACF,CAAC;QACJ,CAAC;QAED,IAAA,qBAAU,EAAC,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE;YACpC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC5C,MAAM,MAAM,GAAG,YAAY,IAAI,aAAa,CAAC;YAE7C,MAAM,KAAK,GAAa;gBACtB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG;gBAChC,UAAU,EAAE,WAAW,CAAC,UAAU;gBAClC,YAAY;gBACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,KAAK;gBAC1C,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,UAAU;gBACvC,aAAa,EAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAW,EAAE,EAAE,CAAC,IAAI,SAAS;gBACnF,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;gBAChC,EAAE,EAAE,GAAG,CAAC,EAAE;aACX,CAAC;YAEF,kBAAkB;YAClB,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,MAAM,EAAE,CAAC;gBACX,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,CAAC;YAED,iBAAiB;YACjB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;gBACjC,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"queryHelper.d.ts","sourceRoot":"","sources":["../src/queryHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kBAAuB,GAC/B,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAuC3D"}
1
+ {"version":3,"file":"queryHelper.d.ts","sourceRoot":"","sources":["../src/queryHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kBAAuB,GAC/B,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAyC3D"}
@@ -25,6 +25,7 @@ function createQueryHelperMiddleware(options = {}) {
25
25
  });
26
26
  // Warn if threshold exceeded
27
27
  if (req.perfToolkit.queryCount === threshold) {
28
+ req.perfToolkit.highQueries = true;
28
29
  console.warn(`[perf] ⚠️ N+1 Alert: ${req.method} ${req.originalUrl || req.url} ` +
29
30
  `has made ${threshold}+ queries. Consider optimizing with batch/join queries.`);
30
31
  console.warn(`[perf] Recent queries: ${queries
@@ -1 +1 @@
1
- {"version":3,"file":"queryHelper.js","sourceRoot":"","sources":["../src/queryHelper.ts"],"names":[],"mappings":";;AAOA,kEAyCC;AA7CD;;;GAGG;AACH,SAAgB,2BAA2B,CACzC,UAA8B,EAAE;IAEhC,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAEnC,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE;QAChE,MAAM,OAAO,GAA2C,EAAE,CAAC;QAE3D,kDAAkD;QAClD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,WAAW,GAAG;gBAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;aACrB,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,WAAW,CAAC,UAAU,GAAG,CAAC,KAAc,EAAQ,EAAE;YACpD,GAAG,CAAC,WAAY,CAAC,UAAU,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,KAAK,IAAI,SAAS,GAAG,CAAC,WAAY,CAAC,UAAU,EAAE;gBACtD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;YAEH,6BAA6B;YAC7B,IAAI,GAAG,CAAC,WAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC9C,OAAO,CAAC,IAAI,CACV,yBAAyB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG,GAAG;oBAClE,YAAY,SAAS,yDAAyD,CACjF,CAAC;gBACF,OAAO,CAAC,IAAI,CACV,4BAA4B,OAAO;qBAChC,KAAK,CAAC,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;qBACnB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"queryHelper.js","sourceRoot":"","sources":["../src/queryHelper.ts"],"names":[],"mappings":";;AAOA,kEA2CC;AA/CD;;;GAGG;AACH,SAAgB,2BAA2B,CACzC,UAA8B,EAAE;IAEhC,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAEnC,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE;QAChE,MAAM,OAAO,GAA2C,EAAE,CAAC;QAE3D,kDAAkD;QAClD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,WAAW,GAAG;gBAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;aACrB,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,WAAW,CAAC,UAAU,GAAG,CAAC,KAAc,EAAQ,EAAE;YACpD,GAAG,CAAC,WAAY,CAAC,UAAU,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,KAAK,IAAI,SAAS,GAAG,CAAC,WAAY,CAAC,UAAU,EAAE;gBACtD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;YAEH,6BAA6B;YAC7B,IAAI,GAAG,CAAC,WAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC9C,GAAG,CAAC,WAAY,CAAC,WAAW,GAAG,IAAI,CAAC;gBAEpC,OAAO,CAAC,IAAI,CACV,yBAAyB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG,GAAG;oBAClE,YAAY,SAAS,yDAAyD,CACjF,CAAC;gBACF,OAAO,CAAC,IAAI,CACV,4BAA4B,OAAO;qBAChC,KAAK,CAAC,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;qBACnB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { MetricsStore } from "./store";
3
+ import { RateLimitOptions } from "./types";
4
+ export declare function createRateLimiter(store: MetricsStore, options: RateLimitOptions | boolean | undefined): (req: Request, res: Response, next: NextFunction) => void;
5
+ //# sourceMappingURL=rateLimit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.d.ts","sourceRoot":"","sources":["../src/rateLimit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAO3C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,gBAAgB,GAAG,OAAO,GAAG,SAAS,SAIhC,OAAO,OAAO,QAAQ,QAAQ,YAAY,UAsE1D"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRateLimiter = createRateLimiter;
4
+ function createRateLimiter(store, options) {
5
+ const enabled = typeof options === "boolean" ? options : options?.enabled !== false;
6
+ if (!enabled) {
7
+ return (req, res, next) => next();
8
+ }
9
+ const opts = typeof options === "object" ? options : {};
10
+ const windowMs = opts.windowMs || 60000;
11
+ const max = opts.max || 100;
12
+ const statusCode = opts.statusCode || 429;
13
+ const message = opts.message || "Too many requests, please try again later.";
14
+ // In-memory store mapping IP addresses to tracking objects
15
+ const hits = new Map();
16
+ // Cleanup interval to prevent memory leaks from inactive IPs
17
+ setInterval(() => {
18
+ const now = Date.now();
19
+ for (const [ip, tracker] of hits.entries()) {
20
+ if (now > tracker.resetTime) {
21
+ hits.delete(ip);
22
+ }
23
+ }
24
+ }, windowMs).unref(); // .unref() ensures this interval doesn't keep the Node process alive
25
+ const exclude = opts.exclude || [];
26
+ return (req, res, next) => {
27
+ // Check exclusions
28
+ const path = req.path;
29
+ const isExcluded = exclude.some((pattern) => {
30
+ if (typeof pattern === "string")
31
+ return path.startsWith(pattern);
32
+ if (pattern instanceof RegExp)
33
+ return pattern.test(path);
34
+ return false;
35
+ });
36
+ if (isExcluded)
37
+ return next();
38
+ const ip = req.ip || req.connection.remoteAddress || "unknown";
39
+ const now = Date.now();
40
+ const routeKey = `${req.method} ${req.route ? req.route.path : req.path}`;
41
+ let tracker = hits.get(ip);
42
+ if (!tracker || now > tracker.resetTime) {
43
+ // Create new tracker or reset expired tracker
44
+ tracker = {
45
+ count: 1,
46
+ resetTime: now + windowMs,
47
+ };
48
+ hits.set(ip, tracker);
49
+ return next();
50
+ }
51
+ tracker.count++;
52
+ if (tracker.count > max) {
53
+ store.recordRateLimitHit(routeKey, ip, req.method, req.path);
54
+ res.setHeader("Retry-After", Math.ceil((tracker.resetTime - now) / 1000));
55
+ res.setHeader("X-RateLimit-Limit", max);
56
+ res.setHeader("X-RateLimit-Remaining", 0);
57
+ res.setHeader("X-RateLimit-Reset", Math.ceil(tracker.resetTime / 1000));
58
+ res.status(statusCode).send(message);
59
+ return;
60
+ }
61
+ res.setHeader("X-RateLimit-Limit", max);
62
+ res.setHeader("X-RateLimit-Remaining", max - tracker.count);
63
+ res.setHeader("X-RateLimit-Reset", Math.ceil(tracker.resetTime / 1000));
64
+ next();
65
+ };
66
+ }
67
+ //# sourceMappingURL=rateLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../src/rateLimit.ts"],"names":[],"mappings":"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"}
package/dist/store.d.ts CHANGED
@@ -1,21 +1,28 @@
1
- import { LogEntry, Metrics } from './types';
1
+ import { LogEntry, Metrics } from "./types";
2
2
  /**
3
3
  * In-memory metrics store — shared state between all middleware components.
4
4
  * Uses a ring buffer for request logs and counters for aggregate stats.
5
5
  */
6
6
  export declare class MetricsStore {
7
7
  private maxLogs;
8
+ private maxRoutes;
8
9
  private logs;
10
+ private blockedEvents;
11
+ private histogram;
9
12
  private stats;
10
13
  constructor(options?: {
11
14
  maxLogs?: number;
12
15
  });
13
16
  /** Add a request log entry to the ring buffer. */
14
- addLog(entry: LogEntry): void;
17
+ recordLog(log: LogEntry): void;
18
+ private createNewRouteStats;
19
+ private updateRouteStats;
15
20
  recordSlowRequest(): void;
21
+ recordRateLimitHit(routeKey: string, ip: string, method: string, path: string): void;
16
22
  recordCacheHit(): void;
17
23
  recordCacheMiss(): void;
18
24
  setCacheSize(size: number): void;
25
+ private calculateCacheHitRate;
19
26
  /** Get all metrics data for the dashboard. */
20
27
  getMetrics(): Metrics;
21
28
  /** Reset all metrics. */
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAc,MAAM,SAAS,CAAC;AAExD;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,KAAK,CAUX;gBAEU,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;IAgB9C,kDAAkD;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAsC7B,iBAAiB,IAAI,IAAI;IAIzB,cAAc,IAAI,IAAI;IAItB,eAAe,IAAI,IAAI;IAIvB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC,8CAA8C;IAC9C,UAAU,IAAI,OAAO;IA2BrB,yBAAyB;IACzB,KAAK,IAAI,IAAI;CAYd"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAA4B,MAAM,SAAS,CAAC;AAKtE;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,KAAK,CAaX;gBAEU,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;IAqB9C,kDAAkD;IAClD,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAwC9B,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,gBAAgB;IAkBxB,iBAAiB,IAAI,IAAI;IAIzB,kBAAkB,CAChB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,IAAI;IAyBP,cAAc,IAAI,IAAI;IAItB,eAAe,IAAI,IAAI;IAIvB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC,OAAO,CAAC,qBAAqB;IAO7B,8CAA8C;IAC9C,UAAU,IAAI,OAAO;IA8CrB,yBAAyB;IACzB,KAAK,IAAI,IAAI;CAkBd"}