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
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # ⚡ Express Performance Toolkit
2
2
 
3
- A powerful, all-in-one Express middleware that automatically optimizes your app with **request caching**, **response compression**, **slow API detection**, **query optimization helpers**, and a stunning **real-time performance dashboard**.
3
+ A powerful, all-in-one Express middleware that automatically optimizes your app with **request caching**, **response compression**, **smart rate limiting**, **bandwidth tracking**, **slow API detection**, **query optimization helpers**, and a stunning **real-time modular performance dashboard**.
4
4
 
5
+ [![npm version](https://img.shields.io/npm/v/express-performance-toolkit.svg?style=flat-square)](https://www.npmjs.com/package/express-performance-toolkit)
5
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
7
8
 
@@ -11,10 +12,14 @@ A powerful, all-in-one Express middleware that automatically optimizes your app
11
12
 
12
13
  - 🚀 **Request Caching** — In-memory LRU cache with TTL (+ optional Redis adapter)
13
14
  - 🗜️ **Response Compression** — Gzip/deflate with configurable thresholds
15
+ - 🛡️ **Smart Rate Limiting** — Protect your API with IP-based limits and blocked traffic tracking
16
+ - 📉 **Bandwidth Monitoring** — Real-time tracking of network egress and payload sizes
14
17
  - 🔥 **Slow API Detection** — Flag & log requests exceeding response time thresholds
15
- - 🔍 **Query Optimization** — N+1 query detection with `req.perfToolkit.trackQuery()`
16
- - 📊 **Real-time Dashboard** — Beautiful dark-themed dashboard at `/__perf`
17
- - 📝 **Structured Logging** — Per-request timing, status codes, cache status
18
+ - 🔍 **Insights** — Automatic detection of N+1 queries, slow routes, and caching opportunities
19
+ - 📊 **Modular Dashboard** — Multi-page real-time dashboard at `/__perf` (Overview, Routes, Insights, Logs)
20
+ - 🔐 **Secure by Default** — Built-in dashboard authentication with session protection
21
+ - 🧠 **Memory Efficient** — Automatic path normalization and route capping to prevent memory leaks in production
22
+ - 📝 **Structured Logging** — Per-request timing, status codes, cache status, and optional file-based logging with rotation
18
23
  - 🎯 **Fully Typed** — Written in TypeScript with complete type definitions
19
24
 
20
25
  ---
@@ -30,106 +35,139 @@ npm install express-performance-toolkit
30
35
  ## 🚀 Quick Start
31
36
 
32
37
  ```typescript
33
- import express from 'express';
34
- import { performanceToolkit } from 'express-performance-toolkit';
38
+ import express from "express";
39
+ import { performanceToolkit } from "express-performance-toolkit";
35
40
 
36
41
  const app = express();
37
42
 
38
43
  const toolkit = performanceToolkit({
39
44
  cache: true,
40
45
  logSlowRequests: true,
41
- dashboard: true,
46
+ dashboard: {
47
+ enabled: true,
48
+ auth: {
49
+ username: "admin",
50
+ password: "your-password", // Change this!
51
+ secret: "your-session-secret", // Change this!
52
+ },
53
+ },
54
+ rateLimit: {
55
+ enabled: true,
56
+ windowMs: 60000,
57
+ max: 100,
58
+ },
42
59
  });
43
60
 
44
61
  // Apply the composable middleware
45
62
  app.use(toolkit.middleware);
46
63
 
47
64
  // Mount the performance dashboard
48
- app.use('/__perf', toolkit.dashboardRouter);
65
+ app.use("/__perf", toolkit.dashboardRouter);
49
66
 
50
- app.get('/api/users', (req, res) => {
51
- res.json({ users: [{ id: 1, name: 'Alice' }] });
67
+ app.get("/api/users", (req, res) => {
68
+ res.json({ users: [{ id: 1, name: "Alice" }] });
52
69
  });
53
70
 
54
71
  app.listen(3000, () => {
55
- console.log('Server running on http://localhost:3000');
56
- console.log('Dashboard at http://localhost:3000/__perf');
72
+ console.log("Server running on http://localhost:3000");
73
+ console.log("Dashboard at http://localhost:3000/__perf");
57
74
  });
58
75
  ```
59
76
 
60
77
  ---
61
78
 
62
- ## ⚙️ Configuration
79
+ ## ⚙️ Configuration Properties
80
+
81
+ | Option | Type | Default | Description |
82
+ | :---------------- | :------------------------------ | :------ | :---------------------------------- |
83
+ | `cache` | `boolean \| CacheOptions` | `true` | LRU caching configuration. |
84
+ | `compression` | `boolean \| CompressionOptions` | `true` | Response compression settings. |
85
+ | `logSlowRequests` | `boolean \| LoggerOptions` | `true` | Slow request detection & logging. |
86
+ | `rateLimit` | `boolean \| RateLimitOptions` | `false` | Smart IP-based rate limiting. |
87
+ | `queryHelper` | `boolean \| QueryHelperOptions` | `true` | N+1 query detection helper. |
88
+ | `dashboard` | `boolean \| DashboardOptions` | `true` | Real-time modular dashboard & auth. |
89
+ | `maxLogs` | `number` | `1000` | Max log entries to keep in memory. |
90
+
91
+ ### Advanced Usage Examples
92
+
93
+ #### Caching with Redis
63
94
 
64
95
  ```typescript
65
96
  const toolkit = performanceToolkit({
66
97
  // Cache — boolean or CacheOptions
67
98
  cache: {
68
- ttl: 60000, // Cache TTL in ms (default: 60000)
69
- maxSize: 100, // Max LRU entries (default: 100)
70
- methods: ['GET'], // HTTP methods to cache (default: ['GET'])
71
- exclude: ['/health', /^\/admin/], // URL patterns to skip
72
- redis: { // Optional Redis adapter (requires ioredis)
73
- host: 'localhost',
99
+ ttl: 60000, // Cache TTL in ms (default: 60000)
100
+ maxSize: 100, // Max LRU entries (default: 100)
101
+ methods: ["GET"], // HTTP methods to cache (default: ['GET'])
102
+ exclude: ["/health", /^\/admin/], // URL patterns to skip
103
+ redis: {
104
+ // Optional Redis adapter (requires ioredis)
105
+ host: "localhost",
74
106
  port: 6379,
75
107
  },
76
108
  },
77
109
 
78
110
  // Compression — boolean or CompressionOptions
79
111
  compression: {
80
- threshold: 1024, // Min response size to compress (default: 1024 bytes)
81
- level: 6, // Compression level 1-9 (default: 6)
112
+ threshold: 1024, // Min response size to compress (default: 1024 bytes)
113
+ level: 6, // Compression level 1-9 (default: 6)
82
114
  },
83
115
 
84
116
  // Logger / Slow Detection — boolean or LoggerOptions
85
117
  logSlowRequests: {
86
- slowThreshold: 1000, // Flag requests slower than this (default: 1000ms)
87
- console: true, // Log to console (default: true)
88
- formatter: (entry) => `${entry.method} ${entry.path} ${entry.responseTime}ms`,
118
+ slowThreshold: 1000, // Flag requests slower than this (default: 1000ms)
119
+ console: true, // Log to console (default: true)
120
+ file: "logs/perf.log", // Optional: Log all requests to a file (JSON Lines format)
121
+ rotation: true, // Optional: Daily log rotation (e.g. perf-2023-10-27.log)
122
+ maxDays: 7, // Optional: Auto-delete logs older than this (requires rotation)
123
+ formatter: (entry) =>
124
+ `${entry.method} ${entry.path} ${entry.responseTime}ms`,
89
125
  },
90
126
 
91
127
  // Query Helper — boolean or QueryHelperOptions
92
128
  queryHelper: {
93
- threshold: 10, // Warn after this many queries/request (default: 10)
129
+ threshold: 10, // Warn after this many queries/request (default: 10)
94
130
  },
95
131
 
96
132
  // Dashboard — boolean or DashboardOptions
97
133
  dashboard: {
98
- path: '/__perf', // Dashboard mount path (default: '/__perf')
134
+ path: "/__perf", // Dashboard mount path (default: '/__perf')
135
+ auth: {
136
+ username: "admin",
137
+ password: "your-password", // Change this!
138
+ secret: "your-session-secret", // Change this!
139
+ },
99
140
  },
100
141
 
101
- maxLogs: 1000, // Max log entries in memory (default: 1000)
142
+ maxLogs: 1000, // Max log entries in memory (default: 1000)
102
143
  });
103
144
  ```
104
145
 
105
146
  ---
106
147
 
107
- ## 📊 Dashboard
148
+ ## 📊 Performance Dashboard
108
149
 
109
- Access the performance dashboard at `http://localhost:3000/__perf`:
150
+ Access the performance dashboard at `http://localhost:3000/__perf` (Protected with `admin`/`perf-toolkit` by default).
110
151
 
111
- - **Real-time stats** Total requests, avg response time, slow request count
112
- - **Cache performance** — Hit/miss ratio donut chart
113
- - **Status code breakdown** — Visual bar chart
114
- - **Slowest routes** — Table of routes sorted by average response time
115
- - **Request log** — Filterable log with timing, cache status, and 🔥 slow flags
152
+ The dashboard is now modular and divided into four key views:
116
153
 
117
- ### Dashboard API
154
+ - **🏠 Overview**: Real-time KPI grid, Event Loop lag, Heap Memory usage, and Cache efficiency.
155
+ - **🛣️ Routes**: Per-endpoint breakdown of latency, call counts, and payload sizes.
156
+ - **💡 Insights**: Smart recommendations for caching, N+1 query fixing, and heavy payload optimization.
157
+ - **📋 Logs**: A live stream of request logs with 🔥 slow markers and cache status.
118
158
 
119
- ```
120
- GET /__perf → Dashboard HTML
121
- GET /__perf/api/metrics → JSON metrics snapshot
122
- POST /__perf/api/reset → Reset all metrics
123
- ```
159
+ ### Memory Optimization
160
+
161
+ The toolkit automatically **normalizes paths** (e.g., grouping `/users/1` and `/users/2` under `/users/:id`) and **caps unique routes** (max 200) to prevent memory leaks in production environments with heavy dynamic traffic.
124
162
 
125
163
  ---
126
164
 
127
- ## 🔍 Query Tracking
165
+ ## 🔍 Smart Insights & Query Tracking
128
166
 
129
167
  Track database queries per request to detect N+1 patterns:
130
168
 
131
169
  ```typescript
132
- app.get('/api/posts', async (req, res) => {
170
+ app.get("/api/posts", async (req, res) => {
133
171
  const posts = await db.getPosts();
134
172
 
135
173
  for (const post of posts) {
@@ -139,49 +177,42 @@ app.get('/api/posts', async (req, res) => {
139
177
 
140
178
  res.json(posts);
141
179
  });
142
- // Console: ⚠️ N+1 Alert: GET /api/posts has made 10+ queries
180
+ // Dashboard will now show an "N+1 Query Detected" alert for this route!
143
181
  ```
144
182
 
145
183
  ---
146
184
 
147
185
  ## 🏗️ Programmatic API
148
186
 
187
+ You can access the toolkit state programmatically:
188
+
149
189
  ```typescript
150
190
  const toolkit = performanceToolkit({ cache: true });
151
191
 
152
- // Access metrics programmatically
192
+ // Access metrics snapshot
153
193
  const metrics = toolkit.getMetrics();
154
194
  console.log(metrics.totalRequests, metrics.avgResponseTime);
155
195
 
156
- // Reset metrics
157
- toolkit.resetMetrics();
158
-
159
196
  // Manual cache control
160
197
  toolkit.cache?.clear();
161
- toolkit.cache?.delete('GET:/api/users');
198
+ toolkit.cache?.delete("GET /api/users");
199
+
200
+ // Reset metrics
201
+ toolkit.resetMetrics();
162
202
  ```
163
203
 
164
204
  ---
165
205
 
166
- ## 🧪 Running Tests
206
+ ## 🧪 Testing & Development
167
207
 
168
208
  ```bash
209
+ # Run unit & integration tests
169
210
  npm test
170
- ```
171
-
172
- ---
173
-
174
- ## 🏃 Running the Example
175
211
 
176
- ```bash
177
- npx ts-node example/server.ts
212
+ # Run the example server
213
+ npm run example
178
214
  ```
179
215
 
180
- Then visit:
181
- - `http://localhost:3000/api/users` — fast, cached response
182
- - `http://localhost:3000/api/slow` — triggers slow request alert
183
- - `http://localhost:3000/__perf` — performance dashboard
184
-
185
216
  ---
186
217
 
187
218
  ## 📁 Project Structure
@@ -189,29 +220,41 @@ Then visit:
189
220
  ```
190
221
  express-performance-toolkit/
191
222
  ├── src/
192
- │ ├── index.ts # Main entrypoint & performanceToolkit()
223
+ │ ├── index.ts # Entrypoint & performanceToolkit()
193
224
  │ ├── types.ts # TypeScript interfaces
194
- │ ├── store.ts # Metrics store (ring buffer + counters)
195
- │ ├── cache.ts # LRU cache + Redis adapter
196
- │ ├── compression.ts # Compression middleware wrapper
197
- │ ├── logger.ts # Request timing & slow detection
198
- │ ├── queryHelper.ts # N+1 query detection
225
+ │ ├── store.ts # Metrics store (Capped routes & ring buffer)
226
+ │ ├── cache.ts # Cache middleware + adapters
227
+ │ ├── logger.ts # Path normalization & request timing
228
+ │ ├── rateLimit.ts # Smart IP-based rate limiter
229
+ │ ├── analyzer.ts # Insights engine
199
230
  │ └── dashboard/
200
- ├── dashboardRouter.ts # Dashboard Express router
201
- │ └── dashboard.html # Dashboard UI
202
- ├── tests/
203
- │ ├── cache.test.ts
204
- │ ├── store.test.ts
205
- │ └── integration.test.ts
231
+ └── dashboardRouter.ts # Web UI backend & auth
232
+ ├── dashboard-ui/ # React dashboard source
206
233
  ├── example/
207
- │ └── server.ts # Example Express app
234
+ │ └── server.ts # Comprehensive demo server
208
235
  ├── package.json
209
- ├── tsconfig.json
210
- └── jest.config.js
236
+ └── tsconfig.json
211
237
  ```
212
238
 
213
239
  ---
214
240
 
241
+ ## 🤝 Contributing
242
+
243
+ We love open source! This package is public and open for anyone to use and improve. If you have ideas for new features, performance optimizations, or bug fixes, we highly encourage you to contribute!
244
+
245
+ **How to contribute:**
246
+
247
+ 1. Fork the repository
248
+ 2. Create a new branch (`git checkout -b feature/amazing-feature`)
249
+ 3. Make your changes and add tests if applicable
250
+ 4. Commit your changes (`git commit -m 'Add amazing feature'`)
251
+ 5. Push to the branch (`git push origin feature/amazing-feature`)
252
+ 6. Open a Pull Request!
253
+
254
+ Every contribution helps make this toolkit better for the community. Let's build something awesome together! 🚀
255
+
256
+ ---
257
+
215
258
  ## 📄 License
216
259
 
217
260
  MIT
@@ -0,0 +1,73 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
+
14
+ ## Expanding the ESLint configuration
15
+
16
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
17
+
18
+ ```js
19
+ export default defineConfig([
20
+ globalIgnores(['dist']),
21
+ {
22
+ files: ['**/*.{ts,tsx}'],
23
+ extends: [
24
+ // Other configs...
25
+
26
+ // Remove tseslint.configs.recommended and replace with this
27
+ tseslint.configs.recommendedTypeChecked,
28
+ // Alternatively, use this for stricter rules
29
+ tseslint.configs.strictTypeChecked,
30
+ // Optionally, add this for stylistic rules
31
+ tseslint.configs.stylisticTypeChecked,
32
+
33
+ // Other configs...
34
+ ],
35
+ languageOptions: {
36
+ parserOptions: {
37
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
+ tsconfigRootDir: import.meta.dirname,
39
+ },
40
+ // other options...
41
+ },
42
+ },
43
+ ])
44
+ ```
45
+
46
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
+
48
+ ```js
49
+ // eslint.config.js
50
+ import reactX from 'eslint-plugin-react-x'
51
+ import reactDom from 'eslint-plugin-react-dom'
52
+
53
+ export default defineConfig([
54
+ globalIgnores(['dist']),
55
+ {
56
+ files: ['**/*.{ts,tsx}'],
57
+ extends: [
58
+ // Other configs...
59
+ // Enable lint rules for React
60
+ reactX.configs['recommended-typescript'],
61
+ // Enable lint rules for React DOM
62
+ reactDom.configs.recommended,
63
+ ],
64
+ languageOptions: {
65
+ parserOptions: {
66
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
+ tsconfigRootDir: import.meta.dirname,
68
+ },
69
+ // other options...
70
+ },
71
+ },
72
+ ])
73
+ ```
@@ -0,0 +1,23 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+ import { defineConfig, globalIgnores } from 'eslint/config'
7
+
8
+ export default defineConfig([
9
+ globalIgnores(['dist']),
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ extends: [
13
+ js.configs.recommended,
14
+ tseslint.configs.recommended,
15
+ reactHooks.configs.flat.recommended,
16
+ reactRefresh.configs.vite,
17
+ ],
18
+ languageOptions: {
19
+ ecmaVersion: 2020,
20
+ globals: globals.browser,
21
+ },
22
+ },
23
+ ])
@@ -0,0 +1,13 @@
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
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>