express-performance-toolkit 1.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 (51) hide show
  1. package/README.md +217 -0
  2. package/dist/cache.d.ts +25 -0
  3. package/dist/cache.d.ts.map +1 -0
  4. package/dist/cache.js +182 -0
  5. package/dist/cache.js.map +1 -0
  6. package/dist/compression.d.ts +7 -0
  7. package/dist/compression.d.ts.map +1 -0
  8. package/dist/compression.js +26 -0
  9. package/dist/compression.js.map +1 -0
  10. package/dist/dashboard/dashboard.html +756 -0
  11. package/dist/dashboard/dashboardRouter.d.ts +9 -0
  12. package/dist/dashboard/dashboardRouter.d.ts.map +1 -0
  13. package/dist/dashboard/dashboardRouter.js +71 -0
  14. package/dist/dashboard/dashboardRouter.js.map +1 -0
  15. package/dist/index.d.ts +45 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +130 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/logger.d.ts +8 -0
  20. package/dist/logger.d.ts.map +1 -0
  21. package/dist/logger.js +70 -0
  22. package/dist/logger.js.map +1 -0
  23. package/dist/queryHelper.d.ts +8 -0
  24. package/dist/queryHelper.d.ts.map +1 -0
  25. package/dist/queryHelper.js +39 -0
  26. package/dist/queryHelper.js.map +1 -0
  27. package/dist/store.d.ts +24 -0
  28. package/dist/store.d.ts.map +1 -0
  29. package/dist/store.js +108 -0
  30. package/dist/store.js.map +1 -0
  31. package/dist/types.d.ts +135 -0
  32. package/dist/types.d.ts.map +1 -0
  33. package/dist/types.js +3 -0
  34. package/dist/types.js.map +1 -0
  35. package/example/server.ts +126 -0
  36. package/example/tsconfig.json +17 -0
  37. package/jest.config.js +10 -0
  38. package/package.json +57 -0
  39. package/src/cache.ts +228 -0
  40. package/src/compression.ts +25 -0
  41. package/src/dashboard/dashboard.html +756 -0
  42. package/src/dashboard/dashboardRouter.ts +45 -0
  43. package/src/index.ts +141 -0
  44. package/src/logger.ts +83 -0
  45. package/src/queryHelper.ts +49 -0
  46. package/src/store.ts +134 -0
  47. package/src/types.ts +155 -0
  48. package/tests/cache.test.ts +76 -0
  49. package/tests/integration.test.ts +124 -0
  50. package/tests/store.test.ts +103 -0
  51. package/tsconfig.json +21 -0
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # ⚡ Express Performance Toolkit
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**.
4
+
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
7
+
8
+ ---
9
+
10
+ ## ✨ Features
11
+
12
+ - 🚀 **Request Caching** — In-memory LRU cache with TTL (+ optional Redis adapter)
13
+ - 🗜️ **Response Compression** — Gzip/deflate with configurable thresholds
14
+ - 🔥 **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
+ - 🎯 **Fully Typed** — Written in TypeScript with complete type definitions
19
+
20
+ ---
21
+
22
+ ## 📦 Installation
23
+
24
+ ```bash
25
+ npm install express-performance-toolkit
26
+ ```
27
+
28
+ ---
29
+
30
+ ## 🚀 Quick Start
31
+
32
+ ```typescript
33
+ import express from 'express';
34
+ import { performanceToolkit } from 'express-performance-toolkit';
35
+
36
+ const app = express();
37
+
38
+ const toolkit = performanceToolkit({
39
+ cache: true,
40
+ logSlowRequests: true,
41
+ dashboard: true,
42
+ });
43
+
44
+ // Apply the composable middleware
45
+ app.use(toolkit.middleware);
46
+
47
+ // Mount the performance dashboard
48
+ app.use('/__perf', toolkit.dashboardRouter);
49
+
50
+ app.get('/api/users', (req, res) => {
51
+ res.json({ users: [{ id: 1, name: 'Alice' }] });
52
+ });
53
+
54
+ app.listen(3000, () => {
55
+ console.log('Server running on http://localhost:3000');
56
+ console.log('Dashboard at http://localhost:3000/__perf');
57
+ });
58
+ ```
59
+
60
+ ---
61
+
62
+ ## ⚙️ Configuration
63
+
64
+ ```typescript
65
+ const toolkit = performanceToolkit({
66
+ // Cache — boolean or CacheOptions
67
+ 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',
74
+ port: 6379,
75
+ },
76
+ },
77
+
78
+ // Compression — boolean or CompressionOptions
79
+ compression: {
80
+ threshold: 1024, // Min response size to compress (default: 1024 bytes)
81
+ level: 6, // Compression level 1-9 (default: 6)
82
+ },
83
+
84
+ // Logger / Slow Detection — boolean or LoggerOptions
85
+ 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`,
89
+ },
90
+
91
+ // Query Helper — boolean or QueryHelperOptions
92
+ queryHelper: {
93
+ threshold: 10, // Warn after this many queries/request (default: 10)
94
+ },
95
+
96
+ // Dashboard — boolean or DashboardOptions
97
+ dashboard: {
98
+ path: '/__perf', // Dashboard mount path (default: '/__perf')
99
+ },
100
+
101
+ maxLogs: 1000, // Max log entries in memory (default: 1000)
102
+ });
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 📊 Dashboard
108
+
109
+ Access the performance dashboard at `http://localhost:3000/__perf`:
110
+
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
116
+
117
+ ### Dashboard API
118
+
119
+ ```
120
+ GET /__perf → Dashboard HTML
121
+ GET /__perf/api/metrics → JSON metrics snapshot
122
+ POST /__perf/api/reset → Reset all metrics
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 🔍 Query Tracking
128
+
129
+ Track database queries per request to detect N+1 patterns:
130
+
131
+ ```typescript
132
+ app.get('/api/posts', async (req, res) => {
133
+ const posts = await db.getPosts();
134
+
135
+ for (const post of posts) {
136
+ req.perfToolkit?.trackQuery(`SELECT comments WHERE post_id=${post.id}`);
137
+ post.comments = await db.getComments(post.id);
138
+ }
139
+
140
+ res.json(posts);
141
+ });
142
+ // Console: ⚠️ N+1 Alert: GET /api/posts has made 10+ queries
143
+ ```
144
+
145
+ ---
146
+
147
+ ## 🏗️ Programmatic API
148
+
149
+ ```typescript
150
+ const toolkit = performanceToolkit({ cache: true });
151
+
152
+ // Access metrics programmatically
153
+ const metrics = toolkit.getMetrics();
154
+ console.log(metrics.totalRequests, metrics.avgResponseTime);
155
+
156
+ // Reset metrics
157
+ toolkit.resetMetrics();
158
+
159
+ // Manual cache control
160
+ toolkit.cache?.clear();
161
+ toolkit.cache?.delete('GET:/api/users');
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 🧪 Running Tests
167
+
168
+ ```bash
169
+ npm test
170
+ ```
171
+
172
+ ---
173
+
174
+ ## 🏃 Running the Example
175
+
176
+ ```bash
177
+ npx ts-node example/server.ts
178
+ ```
179
+
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
+ ---
186
+
187
+ ## 📁 Project Structure
188
+
189
+ ```
190
+ express-performance-toolkit/
191
+ ├── src/
192
+ │ ├── index.ts # Main entrypoint & performanceToolkit()
193
+ │ ├── 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
199
+ │ └── 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
206
+ ├── example/
207
+ │ └── server.ts # Example Express app
208
+ ├── package.json
209
+ ├── tsconfig.json
210
+ └── jest.config.js
211
+ ```
212
+
213
+ ---
214
+
215
+ ## 📄 License
216
+
217
+ MIT
@@ -0,0 +1,25 @@
1
+ import { CacheOptions, CacheEntry, CacheAdapter, CacheMiddleware } from "./types";
2
+ import { MetricsStore } from "./store";
3
+ /**
4
+ * In-memory LRU cache with TTL support.
5
+ */
6
+ export declare class LRUCache<T = CacheEntry> implements CacheAdapter<T> {
7
+ private maxSize;
8
+ private ttl;
9
+ private cache;
10
+ constructor(options?: {
11
+ maxSize?: number;
12
+ ttl?: number;
13
+ });
14
+ get(key: string): T | null;
15
+ set(key: string, value: T): void;
16
+ has(key: string): boolean;
17
+ delete(key: string): boolean;
18
+ clear(): void;
19
+ get size(): number;
20
+ }
21
+ /**
22
+ * Create cache middleware.
23
+ */
24
+ export declare function createCacheMiddleware(options?: CacheOptions, store?: MetricsStore): CacheMiddleware;
25
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EAEZ,eAAe,EAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;GAEG;AACH,qBAAa,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAgC;gBAEjC,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAO;IAM5D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAgB1B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAehC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AA6CD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,YAAiB,EAC1B,KAAK,CAAC,EAAE,YAAY,GACnB,eAAe,CA0GjB"}
package/dist/cache.js ADDED
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LRUCache = void 0;
4
+ exports.createCacheMiddleware = createCacheMiddleware;
5
+ /**
6
+ * In-memory LRU cache with TTL support.
7
+ */
8
+ class LRUCache {
9
+ constructor(options = {}) {
10
+ this.maxSize = options.maxSize || 100;
11
+ this.ttl = options.ttl || 60000;
12
+ this.cache = new Map();
13
+ }
14
+ get(key) {
15
+ const entry = this.cache.get(key);
16
+ if (!entry)
17
+ return null;
18
+ // Check TTL
19
+ if (Date.now() - entry.createdAt > this.ttl) {
20
+ this.cache.delete(key);
21
+ return null;
22
+ }
23
+ // Move to end (most recently used)
24
+ this.cache.delete(key);
25
+ this.cache.set(key, entry);
26
+ return entry.value;
27
+ }
28
+ set(key, value) {
29
+ // Remove oldest if at capacity
30
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
31
+ const firstKey = this.cache.keys().next().value;
32
+ if (firstKey !== undefined) {
33
+ this.cache.delete(firstKey);
34
+ }
35
+ }
36
+ this.cache.set(key, {
37
+ value,
38
+ createdAt: Date.now(),
39
+ });
40
+ }
41
+ has(key) {
42
+ return this.get(key) !== null;
43
+ }
44
+ delete(key) {
45
+ return this.cache.delete(key);
46
+ }
47
+ clear() {
48
+ this.cache.clear();
49
+ }
50
+ get size() {
51
+ return this.cache.size;
52
+ }
53
+ }
54
+ exports.LRUCache = LRUCache;
55
+ /**
56
+ * Create a Redis cache adapter (requires ioredis as peer dependency).
57
+ */
58
+ function createRedisAdapter(redisConfig) {
59
+ try {
60
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
61
+ const Redis = require("ioredis");
62
+ const client = new Redis(redisConfig);
63
+ const prefix = redisConfig.prefix || "ept:";
64
+ const ttl = redisConfig.ttl || 60;
65
+ return {
66
+ async get(key) {
67
+ const data = await client.get(`${prefix}${key}`);
68
+ return data ? JSON.parse(data) : null;
69
+ },
70
+ async set(key, value) {
71
+ await client.setex(`${prefix}${key}`, ttl, JSON.stringify(value));
72
+ },
73
+ async has(key) {
74
+ return (await client.exists(`${prefix}${key}`)) === 1;
75
+ },
76
+ async delete(key) {
77
+ await client.del(`${prefix}${key}`);
78
+ },
79
+ async clear() {
80
+ const keys = await client.keys(`${prefix}*`);
81
+ if (keys.length > 0)
82
+ await client.del(...keys);
83
+ },
84
+ get size() {
85
+ return -1; // Cannot easily get size from Redis
86
+ },
87
+ };
88
+ }
89
+ catch {
90
+ console.warn("[express-performance-toolkit] ioredis not installed. Falling back to in-memory cache.");
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Create cache middleware.
96
+ */
97
+ function createCacheMiddleware(options = {}, store) {
98
+ const { ttl = 60000, maxSize = 100, exclude = [], redis = null, methods = ["GET"], } = options;
99
+ let cacheAdapter;
100
+ if (redis) {
101
+ const redisAdapter = createRedisAdapter({
102
+ ...redis,
103
+ ttl: Math.ceil(ttl / 1000),
104
+ });
105
+ cacheAdapter = redisAdapter || new LRUCache({ maxSize, ttl });
106
+ }
107
+ else {
108
+ cacheAdapter = new LRUCache({ maxSize, ttl });
109
+ }
110
+ function shouldExclude(url) {
111
+ return exclude.some((pattern) => {
112
+ if (pattern instanceof RegExp)
113
+ return pattern.test(url);
114
+ return url.includes(pattern);
115
+ });
116
+ }
117
+ function getCacheKey(req) {
118
+ return `${req.method}:${req.originalUrl || req.url}`;
119
+ }
120
+ const handler = async (req, res, next) => {
121
+ // Only cache specified methods
122
+ if (!methods.includes(req.method)) {
123
+ return next();
124
+ }
125
+ // Check exclusion patterns
126
+ const url = req.originalUrl || req.url;
127
+ if (shouldExclude(url)) {
128
+ return next();
129
+ }
130
+ const key = getCacheKey(req);
131
+ try {
132
+ const cached = await cacheAdapter.get(key);
133
+ if (cached) {
134
+ if (store)
135
+ store.recordCacheHit();
136
+ const entry = cached;
137
+ res.set("X-Cache", "HIT");
138
+ res.set("Content-Type", entry.contentType || "application/json");
139
+ res.status(entry.statusCode || 200).send(entry.body);
140
+ return;
141
+ }
142
+ }
143
+ catch {
144
+ // Cache read failed — continue to handler
145
+ }
146
+ if (store)
147
+ store.recordCacheMiss();
148
+ res.set("X-Cache", "MISS");
149
+ // Intercept response to cache it
150
+ const originalSend = res.send.bind(res);
151
+ res.send = function (body) {
152
+ // Only cache successful responses
153
+ if (res.statusCode >= 200 && res.statusCode < 400) {
154
+ const entry = {
155
+ body: body,
156
+ statusCode: res.statusCode,
157
+ contentType: res.get("Content-Type"),
158
+ };
159
+ try {
160
+ cacheAdapter.set(key, entry);
161
+ if (store &&
162
+ typeof cacheAdapter.size === "number" &&
163
+ cacheAdapter.size >= 0) {
164
+ store.setCacheSize(cacheAdapter.size);
165
+ }
166
+ }
167
+ catch {
168
+ // Cache write failed — ignore
169
+ }
170
+ }
171
+ return originalSend(body);
172
+ };
173
+ next();
174
+ };
175
+ // Build the CacheMiddleware with attached control methods
176
+ const middleware = handler;
177
+ middleware.clear = () => cacheAdapter.clear();
178
+ middleware.delete = (key) => cacheAdapter.delete(key);
179
+ middleware.adapter = cacheAdapter;
180
+ return middleware;
181
+ }
182
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { CompressionOptions } from './types';
3
+ /**
4
+ * Create compression middleware with sensible defaults.
5
+ */
6
+ export declare function createCompressionMiddleware(options?: CompressionOptions): (req: Request, res: Response, next: NextFunction) => void;
7
+ //# sourceMappingURL=compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../src/compression.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kBAAuB,GAC/B,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAe3D"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createCompressionMiddleware = createCompressionMiddleware;
7
+ const compression_1 = __importDefault(require("compression"));
8
+ /**
9
+ * Create compression middleware with sensible defaults.
10
+ */
11
+ function createCompressionMiddleware(options = {}) {
12
+ const { threshold = 1024, level = 6 } = options;
13
+ return (0, compression_1.default)({
14
+ threshold,
15
+ level,
16
+ filter: (req, res) => {
17
+ // Don't compress if the client didn't request it
18
+ if (req.headers['x-no-compression']) {
19
+ return false;
20
+ }
21
+ // Use compression's default filter
22
+ return compression_1.default.filter(req, res);
23
+ },
24
+ });
25
+ }
26
+ //# sourceMappingURL=compression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.js","sourceRoot":"","sources":["../src/compression.ts"],"names":[],"mappings":";;;;;AAOA,kEAiBC;AAvBD,8DAAgD;AAGhD;;GAEG;AACH,SAAgB,2BAA2B,CACzC,UAA8B,EAAE;IAEhC,MAAM,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAEhD,OAAO,IAAA,qBAAqB,EAAC;QAC3B,SAAS;QACT,KAAK;QACL,MAAM,EAAE,CAAC,GAAY,EAAE,GAAa,EAAW,EAAE;YAC/C,iDAAiD;YACjD,IAAI,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACpC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,mCAAmC;YACnC,OAAO,qBAAqB,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAChD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}