kempo-server 1.6.0 → 1.6.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/README.md CHANGED
@@ -221,8 +221,95 @@ This json file can have any of the following properties, any property not define
221
221
  - [routeFiles](#routefiles)
222
222
  - [noRescanPaths](#norescanpaths)
223
223
  - [maxRescanAttempts](#maxrescanattempts)
224
+ - [cache](#cache)
224
225
  - [middleware](#middleware)
225
226
 
227
+ ## Cache
228
+
229
+ Kempo Server includes an intelligent module caching system that dramatically improves performance by caching JavaScript route modules in memory. The cache combines multiple strategies:
230
+
231
+ - **LRU (Least Recently Used)** - Evicts oldest modules when cache fills
232
+ - **Time-based expiration** - Modules expire after configurable TTL
233
+ - **Memory monitoring** - Automatically clears cache if memory usage gets too high
234
+ - **File watching** - Instantly invalidates cache when files change (development)
235
+
236
+ ### Basic Cache Configuration
237
+
238
+ Enable caching in your `.config.json`:
239
+
240
+ ```json
241
+ {
242
+ "cache": {
243
+ "enabled": true,
244
+ "maxSize": 100,
245
+ "maxMemoryMB": 50,
246
+ "ttlMs": 300000,
247
+ "watchFiles": true
248
+ }
249
+ }
250
+ ```
251
+
252
+ ### Cache Options
253
+
254
+ - `enabled` (boolean) - Enable/disable caching (default: `true`)
255
+ - `maxSize` (number) - Maximum cached modules (default: `100`)
256
+ - `maxMemoryMB` (number) - Memory limit in MB (default: `50`)
257
+ - `ttlMs` (number) - Cache lifetime in milliseconds (default: `300000` - 5 minutes)
258
+ - `maxHeapUsagePercent` (number) - Clear cache when heap exceeds % (default: `70`)
259
+ - `memoryCheckInterval` (number) - Memory check frequency in ms (default: `30000`)
260
+ - `watchFiles` (boolean) - Auto-invalidate on file changes (default: `true`)
261
+ - `enableMemoryMonitoring` (boolean) - Enable memory monitoring (default: `true`)
262
+
263
+ ### Environment-Specific Configurations
264
+
265
+ Use different config files for different environments:
266
+
267
+ **Development (`dev.config.json`):**
268
+ ```json
269
+ {
270
+ "cache": {
271
+ "enabled": true,
272
+ "maxSize": 50,
273
+ "ttlMs": 300000,
274
+ "watchFiles": true
275
+ }
276
+ }
277
+ ```
278
+
279
+ **Production (`prod.config.json`):**
280
+ ```json
281
+ {
282
+ "cache": {
283
+ "enabled": true,
284
+ "maxSize": 1000,
285
+ "maxMemoryMB": 200,
286
+ "ttlMs": 3600000,
287
+ "watchFiles": false
288
+ }
289
+ }
290
+ ```
291
+
292
+ Run with specific config: `node src/index.js --config prod.config.json`
293
+
294
+ ### Cache Monitoring
295
+
296
+ Monitor cache performance at runtime:
297
+
298
+ - **View stats:** `GET /_admin/cache` - Returns detailed cache statistics
299
+ - **Clear cache:** `DELETE /_admin/cache` - Clears entire cache
300
+
301
+ Example response:
302
+ ```json
303
+ {
304
+ "cache": {
305
+ "size": 45,
306
+ "maxSize": 100,
307
+ "memoryUsageMB": 12.5,
308
+ "hitRate": 87
309
+ }
310
+ }
311
+ ```
312
+
226
313
  ## Middleware
227
314
 
228
315
  Kempo Server includes a powerful middleware system that allows you to add functionality like authentication, logging, CORS, compression, and more. Middleware runs before your route handlers and can modify requests, responses, or handle requests entirely.
@@ -511,6 +598,37 @@ The maximum number of times to attempt rescanning the file system when a file is
511
598
  }
512
599
  ```
513
600
 
601
+ ### cache
602
+
603
+ Configure the intelligent module caching system for improved performance:
604
+
605
+ ```json
606
+ {
607
+ "cache": {
608
+ "enabled": true,
609
+ "maxSize": 100,
610
+ "maxMemoryMB": 50,
611
+ "ttlMs": 300000,
612
+ "maxHeapUsagePercent": 70,
613
+ "memoryCheckInterval": 30000,
614
+ "watchFiles": true,
615
+ "enableMemoryMonitoring": true
616
+ }
617
+ }
618
+ ```
619
+
620
+ Cache options:
621
+ - `enabled` - Enable/disable caching (boolean, default: `true`)
622
+ - `maxSize` - Maximum cached modules (number, default: `100`)
623
+ - `maxMemoryMB` - Memory limit in MB (number, default: `50`)
624
+ - `ttlMs` - Cache lifetime in milliseconds (number, default: `300000`)
625
+ - `maxHeapUsagePercent` - Clear cache when heap exceeds % (number, default: `70`)
626
+ - `memoryCheckInterval` - Memory check frequency in ms (number, default: `30000`)
627
+ - `watchFiles` - Auto-invalidate on file changes (boolean, default: `true`)
628
+ - `enableMemoryMonitoring` - Enable memory monitoring (boolean, default: `true`)
629
+
630
+ Use different config files for different environments rather than nested objects.
631
+
514
632
  ## Features
515
633
 
516
634
  - **Zero Dependencies** - No external dependencies required
@@ -0,0 +1,24 @@
1
+ {
2
+ "_comment": "Development configuration with aggressive file watching and conservative memory usage",
3
+ "cache": {
4
+ "enabled": true,
5
+ "maxSize": 50,
6
+ "maxMemoryMB": 25,
7
+ "ttlMs": 300000,
8
+ "maxHeapUsagePercent": 65,
9
+ "memoryCheckInterval": 15000,
10
+ "watchFiles": true,
11
+ "enableMemoryMonitoring": true
12
+ },
13
+ "middleware": {
14
+ "cors": {
15
+ "enabled": true,
16
+ "origin": "*"
17
+ },
18
+ "logging": {
19
+ "enabled": true,
20
+ "includeUserAgent": true,
21
+ "includeResponseTime": true
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "_comment": "Low-memory configuration for resource-constrained environments",
3
+ "cache": {
4
+ "enabled": true,
5
+ "maxSize": 20,
6
+ "maxMemoryMB": 5,
7
+ "ttlMs": 120000,
8
+ "maxHeapUsagePercent": 60,
9
+ "memoryCheckInterval": 10000,
10
+ "watchFiles": true,
11
+ "enableMemoryMonitoring": true
12
+ },
13
+ "middleware": {
14
+ "compression": {
15
+ "enabled": true,
16
+ "threshold": 512
17
+ },
18
+ "logging": {
19
+ "enabled": true,
20
+ "includeResponseTime": false
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "_comment": "Cache disabled configuration for debugging or special environments",
3
+ "cache": {
4
+ "enabled": false
5
+ },
6
+ "middleware": {
7
+ "logging": {
8
+ "enabled": true,
9
+ "includeUserAgent": true,
10
+ "includeResponseTime": true
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "_comment": "Production configuration with large cache and disabled file watching",
3
+ "cache": {
4
+ "enabled": true,
5
+ "maxSize": 1000,
6
+ "maxMemoryMB": 200,
7
+ "ttlMs": 3600000,
8
+ "maxHeapUsagePercent": 85,
9
+ "memoryCheckInterval": 60000,
10
+ "watchFiles": false,
11
+ "enableMemoryMonitoring": true
12
+ },
13
+ "middleware": {
14
+ "cors": {
15
+ "enabled": true,
16
+ "origin": ["https://myapp.com", "https://www.myapp.com"],
17
+ "credentials": true
18
+ },
19
+ "compression": {
20
+ "enabled": true,
21
+ "threshold": 1024
22
+ },
23
+ "security": {
24
+ "enabled": true,
25
+ "headers": {
26
+ "X-Content-Type-Options": "nosniff",
27
+ "X-Frame-Options": "DENY",
28
+ "X-XSS-Protection": "1; mode=block",
29
+ "Strict-Transport-Security": "max-age=31536000; includeSubDomains"
30
+ }
31
+ },
32
+ "logging": {
33
+ "enabled": true,
34
+ "includeUserAgent": false,
35
+ "includeResponseTime": true
36
+ }
37
+ }
38
+ }
@@ -15,5 +15,15 @@
15
15
  "noRescanPaths": [
16
16
  "/vendor/"
17
17
  ],
18
- "maxRescanAttempts": 3
18
+ "maxRescanAttempts": 3,
19
+ "cache": {
20
+ "enabled": true,
21
+ "maxSize": 150,
22
+ "maxMemoryMB": 75,
23
+ "ttlMs": 600000,
24
+ "maxHeapUsagePercent": 75,
25
+ "memoryCheckInterval": 20000,
26
+ "watchFiles": true,
27
+ "enableMemoryMonitoring": true
28
+ }
19
29
  }
@@ -0,0 +1,28 @@
1
+ /*
2
+ Clear Cache Admin Endpoint
3
+ */
4
+
5
+ export default async (req, res) => {
6
+ // Find the router instance to access moduleCache
7
+ const moduleCache = req.moduleCache || req._kempoCache;
8
+
9
+ if (!moduleCache) {
10
+ res.writeHead(503, { 'Content-Type': 'application/json' });
11
+ res.end(JSON.stringify({
12
+ error: 'Cache not available',
13
+ message: 'Module cache is not enabled or accessible'
14
+ }));
15
+ return;
16
+ }
17
+
18
+ // Clear cache
19
+ const sizeBefore = moduleCache.cache.size;
20
+ moduleCache.clear();
21
+
22
+ res.writeHead(200, { 'Content-Type': 'application/json' });
23
+ res.end(JSON.stringify({
24
+ message: 'Cache cleared successfully',
25
+ entriesCleared: sizeBefore,
26
+ timestamp: new Date().toISOString()
27
+ }));
28
+ };
@@ -0,0 +1,53 @@
1
+ /*
2
+ Cache Administration Endpoint
3
+ GET /_admin/cache - Returns cache statistics as JSON
4
+ DELETE /_admin/cache - Clears the entire cache
5
+ */
6
+
7
+ export default async (req, res) => {
8
+ // Find the router instance to access moduleCache
9
+ // This is a bit of a hack - in practice you'd pass this through middleware
10
+ const moduleCache = req.moduleCache || req._kempoCache;
11
+
12
+ if (!moduleCache) {
13
+ res.writeHead(503, { 'Content-Type': 'application/json' });
14
+ res.end(JSON.stringify({
15
+ error: 'Cache not available',
16
+ message: 'Module cache is not enabled or accessible'
17
+ }));
18
+ return;
19
+ }
20
+
21
+ if (req.method === 'GET') {
22
+ // Return cache statistics
23
+ const stats = moduleCache.getStats();
24
+ const cachedFiles = moduleCache.getCachedFiles();
25
+
26
+ res.writeHead(200, { 'Content-Type': 'application/json' });
27
+ res.end(JSON.stringify({
28
+ ...stats,
29
+ cachedFiles: cachedFiles.map(file => ({
30
+ ...file,
31
+ ageSeconds: Math.round(file.age / 1000)
32
+ }))
33
+ }, null, 2));
34
+
35
+ } else if (req.method === 'DELETE') {
36
+ // Clear cache
37
+ const sizeBefore = moduleCache.cache.size;
38
+ moduleCache.clear();
39
+
40
+ res.writeHead(200, { 'Content-Type': 'application/json' });
41
+ res.end(JSON.stringify({
42
+ message: 'Cache cleared successfully',
43
+ entriesCleared: sizeBefore
44
+ }));
45
+
46
+ } else {
47
+ res.writeHead(405, { 'Content-Type': 'application/json' });
48
+ res.end(JSON.stringify({
49
+ error: 'Method not allowed',
50
+ allowed: ['GET', 'DELETE']
51
+ }));
52
+ }
53
+ };
@@ -0,0 +1,235 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" theme="auto">
3
+ <head>
4
+ <meta charset='utf-8'>
5
+ <meta http-equiv='X-UA-Compatible' content='IE=edge'>
6
+ <title>Caching - Kempo Server</title>
7
+ <meta name='viewport' content='width=device-width, initial-scale=1'>
8
+ <link rel="icon" type="image/png" sizes="48x48" href="./media/icon48.png">
9
+ <link rel="manifest" href="./manifest.json">
10
+ <link rel="stylesheet" href="./kempo.min.css" />
11
+ </head>
12
+ <body>
13
+ <main>
14
+ <a href="./" class="btn">Home</a>
15
+ <h1>Module Caching</h1>
16
+ <p>Kempo Server includes an intelligent module caching system that dramatically improves performance by caching JavaScript route modules in memory.</p>
17
+
18
+ <h2>How It Works</h2>
19
+ <p>The cache system combines multiple strategies to optimize performance while preventing memory issues:</p>
20
+ <ul>
21
+ <li><strong>LRU (Least Recently Used)</strong> - Evicts oldest modules when cache fills</li>
22
+ <li><strong>Time-based expiration</strong> - Modules expire after configurable TTL</li>
23
+ <li><strong>Memory monitoring</strong> - Automatically clears cache if memory usage gets too high</li>
24
+ <li><strong>File watching</strong> - Instantly invalidates cache when files change (development)</li>
25
+ </ul>
26
+
27
+ <h2>Basic Configuration</h2>
28
+ <p>Add a <code>cache</code> object to your <code>.config.json</code> file:</p>
29
+ <pre><code class="hljs json">{
30
+ <span class="hljs-attr">"cache"</span>: {
31
+ <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>,
32
+ <span class="hljs-attr">"maxSize"</span>: <span class="hljs-number">100</span>,
33
+ <span class="hljs-attr">"maxMemoryMB"</span>: <span class="hljs-number">50</span>,
34
+ <span class="hljs-attr">"ttlMs"</span>: <span class="hljs-number">300000</span>,
35
+ <span class="hljs-attr">"watchFiles"</span>: <span class="hljs-literal">true</span>
36
+ }
37
+ }</code></pre>
38
+
39
+ <h2>Configuration Options</h2>
40
+ <table>
41
+ <thead>
42
+ <tr>
43
+ <th>Option</th>
44
+ <th>Type</th>
45
+ <th>Default</th>
46
+ <th>Description</th>
47
+ </tr>
48
+ </thead>
49
+ <tbody>
50
+ <tr>
51
+ <td><code>enabled</code></td>
52
+ <td>boolean</td>
53
+ <td><code>true</code></td>
54
+ <td>Enable/disable the entire caching system</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>maxSize</code></td>
58
+ <td>number</td>
59
+ <td><code>100</code></td>
60
+ <td>Maximum number of modules to cache</td>
61
+ </tr>
62
+ <tr>
63
+ <td><code>maxMemoryMB</code></td>
64
+ <td>number</td>
65
+ <td><code>50</code></td>
66
+ <td>Memory limit for cache in megabytes</td>
67
+ </tr>
68
+ <tr>
69
+ <td><code>ttlMs</code></td>
70
+ <td>number</td>
71
+ <td><code>300000</code></td>
72
+ <td>Time to live in milliseconds (5 minutes)</td>
73
+ </tr>
74
+ <tr>
75
+ <td><code>maxHeapUsagePercent</code></td>
76
+ <td>number</td>
77
+ <td><code>70</code></td>
78
+ <td>Clear cache when heap usage exceeds this percentage</td>
79
+ </tr>
80
+ <tr>
81
+ <td><code>memoryCheckInterval</code></td>
82
+ <td>number</td>
83
+ <td><code>30000</code></td>
84
+ <td>How often to check memory usage (milliseconds)</td>
85
+ </tr>
86
+ <tr>
87
+ <td><code>watchFiles</code></td>
88
+ <td>boolean</td>
89
+ <td><code>true</code></td>
90
+ <td>Auto-invalidate cache when files change</td>
91
+ </tr>
92
+ <tr>
93
+ <td><code>enableMemoryMonitoring</code></td>
94
+ <td>boolean</td>
95
+ <td><code>true</code></td>
96
+ <td>Enable automatic memory monitoring</td>
97
+ </tr>
98
+ </tbody>
99
+ </table>
100
+
101
+ <h2>Environment-Specific Configuration</h2>
102
+ <p>Use separate configuration files for different environments instead of nested objects:</p>
103
+
104
+ <h3>Development Configuration</h3>
105
+ <p>Create <code>dev.config.json</code> with settings optimized for development:</p>
106
+ <pre><code class="hljs json">{
107
+ <span class="hljs-attr">"cache"</span>: {
108
+ <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>,
109
+ <span class="hljs-attr">"maxSize"</span>: <span class="hljs-number">50</span>,
110
+ <span class="hljs-attr">"maxMemoryMB"</span>: <span class="hljs-number">25</span>,
111
+ <span class="hljs-attr">"ttlMs"</span>: <span class="hljs-number">300000</span>,
112
+ <span class="hljs-attr">"watchFiles"</span>: <span class="hljs-literal">true</span>
113
+ }
114
+ }</code></pre>
115
+ <pre><code class="hljs bash">node src/index.js --config dev.config.json</code></pre>
116
+
117
+ <h3>Production Configuration</h3>
118
+ <p>Create <code>prod.config.json</code> with settings optimized for production:</p>
119
+ <pre><code class="hljs json">{
120
+ <span class="hljs-attr">"cache"</span>: {
121
+ <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>,
122
+ <span class="hljs-attr">"maxSize"</span>: <span class="hljs-number">1000</span>,
123
+ <span class="hljs-attr">"maxMemoryMB"</span>: <span class="hljs-number">200</span>,
124
+ <span class="hljs-attr">"ttlMs"</span>: <span class="hljs-number">3600000</span>,
125
+ <span class="hljs-attr">"watchFiles"</span>: <span class="hljs-literal">false</span>
126
+ }
127
+ }</code></pre>
128
+ <pre><code class="hljs bash">node src/index.js --config prod.config.json</code></pre>
129
+
130
+ <h2>Cache Monitoring</h2>
131
+ <p>Monitor cache performance and manage cached modules at runtime:</p>
132
+
133
+ <h3>View Cache Statistics</h3>
134
+ <pre><code class="hljs bash">curl http://localhost:3000/_admin/cache</code></pre>
135
+ <p>Returns detailed statistics including:</p>
136
+ <ul>
137
+ <li>Cache size and memory usage</li>
138
+ <li>Hit/miss rates</li>
139
+ <li>Node.js memory usage</li>
140
+ <li>List of cached files</li>
141
+ </ul>
142
+
143
+ <h3>Clear Cache</h3>
144
+ <pre><code class="hljs bash">curl -X DELETE http://localhost:3000/_admin/cache</code></pre>
145
+ <p>Immediately clears all cached modules.</p>
146
+
147
+ <h2>Performance Tuning</h2>
148
+
149
+ <h3>Memory Settings</h3>
150
+ <ul>
151
+ <li>Set <code>maxMemoryMB</code> to 10-20% of available server RAM</li>
152
+ <li>Use lower <code>maxHeapUsagePercent</code> (60-70%) for memory-constrained environments</li>
153
+ <li>Monitor actual usage with <code>/_admin/cache</code> endpoint</li>
154
+ </ul>
155
+
156
+ <h3>Cache Size</h3>
157
+ <ul>
158
+ <li>Start with <code>maxSize</code> = 10x your typical concurrent routes</li>
159
+ <li>Increase if you have many route files and sufficient memory</li>
160
+ <li>Decrease for microservices with few routes</li>
161
+ </ul>
162
+
163
+ <h3>TTL Settings</h3>
164
+ <ul>
165
+ <li><strong>Development:</strong> Short TTL (5-10 minutes) for quick iteration</li>
166
+ <li><strong>Production:</strong> Longer TTL (30-60 minutes) for stability</li>
167
+ <li><strong>High-change environments:</strong> Shorter TTL or rely on file watching</li>
168
+ </ul>
169
+
170
+ <h3>File Watching</h3>
171
+ <ul>
172
+ <li><strong>Enable</strong> (<code>watchFiles: true</code>) in development for instant invalidation</li>
173
+ <li><strong>Disable</strong> (<code>watchFiles: false</code>) in production to reduce overhead</li>
174
+ </ul>
175
+
176
+ <h2>Configuration Examples</h2>
177
+
178
+ <h3>Minimal Configuration</h3>
179
+ <p>Just enable caching with defaults:</p>
180
+ <pre><code class="hljs json">{
181
+ <span class="hljs-attr">"cache"</span>: {
182
+ <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>
183
+ }
184
+ }</code></pre>
185
+
186
+ <h3>High-Traffic Configuration</h3>
187
+ <p>For servers with lots of routes and traffic:</p>
188
+ <pre><code class="hljs json">{
189
+ <span class="hljs-attr">"cache"</span>: {
190
+ <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>,
191
+ <span class="hljs-attr">"maxSize"</span>: <span class="hljs-number">2000</span>,
192
+ <span class="hljs-attr">"maxMemoryMB"</span>: <span class="hljs-number">500</span>,
193
+ <span class="hljs-attr">"ttlMs"</span>: <span class="hljs-number">7200000</span>,
194
+ <span class="hljs-attr">"watchFiles"</span>: <span class="hljs-literal">false</span>
195
+ }
196
+ }</code></pre>
197
+
198
+ <h3>Memory-Constrained Configuration</h3>
199
+ <p>For servers with limited RAM:</p>
200
+ <pre><code class="hljs json">{
201
+ <span class="hljs-attr">"cache"</span>: {
202
+ <span class="hljs-attr">"enabled"</span>: <span class="hljs-literal">true</span>,
203
+ <span class="hljs-attr">"maxSize"</span>: <span class="hljs-number">25</span>,
204
+ <span class="hljs-attr">"maxMemoryMB"</span>: <span class="hljs-number">10</span>,
205
+ <span class="hljs-attr">"ttlMs"</span>: <span class="hljs-number">120000</span>,
206
+ <span class="hljs-attr">"maxHeapUsagePercent"</span>: <span class="hljs-number">60</span>
207
+ }
208
+ }</code></pre>
209
+
210
+ <h2>Troubleshooting</h2>
211
+
212
+ <h3>Cache Not Working</h3>
213
+ <ul>
214
+ <li>Verify <code>cache.enabled</code> is <code>true</code></li>
215
+ <li>Check file permissions for watching</li>
216
+ <li>Review server logs for cache statistics</li>
217
+ </ul>
218
+
219
+ <h3>Memory Issues</h3>
220
+ <ul>
221
+ <li>Reduce <code>maxMemoryMB</code> and <code>maxSize</code></li>
222
+ <li>Lower <code>maxHeapUsagePercent</code></li>
223
+ <li>Enable more aggressive memory monitoring</li>
224
+ </ul>
225
+
226
+ <h3>Performance Issues</h3>
227
+ <ul>
228
+ <li>Increase cache limits if you have available memory</li>
229
+ <li>Extend <code>ttlMs</code> for stable route files</li>
230
+ <li>Monitor hit rates with admin endpoints</li>
231
+ </ul>
232
+
233
+ </main>
234
+ </body>
235
+ </html>