@naman_deep_singh/server-utils 1.1.0 → 1.3.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.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @naman_deep_singh/server-utils
2
2
 
3
- **Version:** 1.1.0
3
+ **Version:** 1.3.0 (with integrated cache & session support)
4
4
 
5
- Extensible server utilities for Express.js microservices with multi-protocol support and TypeScript.
5
+ Extensible server utilities for Express.js microservices with multi-protocol support, integrated caching, session management, and TypeScript.
6
6
 
7
7
  ## Installation
8
8
 
@@ -13,17 +13,19 @@ npm install @naman_deep_singh/server-utils
13
13
  ## Features
14
14
 
15
15
  - ✅ **Multi-protocol support** - HTTP, gRPC, JSON-RPC, WebSockets, Webhooks
16
+ - ✅ **Integrated caching** - Redis, Memcache, in-memory with automatic fallback
17
+ - ✅ **Session management** - Distributed session store with configurable TTL
16
18
  - ✅ **Express.js integration** with middleware collection
17
- - ✅ **Graceful shutdown** handling
18
- - ✅ **Health checks** with custom checks support
19
+ - ✅ **Graceful shutdown** handling with cache/session cleanup
20
+ - ✅ **Health checks** with custom checks and cache health integration
19
21
  - ✅ **TypeScript support** with full type safety
20
- - ✅ **Hybrid exports** - use named imports or namespace imports
21
- - ✅ **Plugin architecture** for extensibility
22
- - ✅ **Built-in middleware** - logging, validation, rate limiting, auth
22
+
23
+ - ✅ **Built-in middleware** - logging, validation, rate limiting, auth, caching, sessions
24
+
23
25
 
24
26
  ## Quick Start
25
27
 
26
- ### Named Imports
28
+ ### Basic Usage
27
29
  ```typescript
28
30
  import { createServer } from '@naman_deep_singh/server-utils';
29
31
 
@@ -42,13 +44,6 @@ server.app.get('/users', (req, res) => {
42
44
  await server.start();
43
45
  ```
44
46
 
45
- ### Namespace Import
46
- ```typescript
47
- import ServerUtils from '@naman_deep_singh/server-utils';
48
-
49
- const server = ServerUtils.createServer('My API', '1.0.0');
50
- ```
51
-
52
47
  ## Multi-Protocol Support
53
48
 
54
49
  ### HTTP + Express Routes
@@ -129,17 +124,13 @@ server.addWebhook({
129
124
 
130
125
  ## Built-in Middleware
131
126
 
127
+
132
128
  ### Logging Middleware
133
129
  ```typescript
134
- import { createLoggingMiddleware, withLogging } from '@naman_deep_singh/server-utils';
130
+ import { createLoggingMiddleware } from '@naman_deep_singh/server-utils';
135
131
 
136
132
  // Direct usage
137
133
  server.app.use(createLoggingMiddleware('detailed'));
138
-
139
- // Plugin usage
140
- const server = createServerWithPlugins('My API', '1.0.0', [
141
- withLogging('detailed')
142
- ]);
143
134
  ```
144
135
 
145
136
  ### Validation Middleware
@@ -182,52 +173,16 @@ server.app.use('/protected', requireAuth({
182
173
 
183
174
  ## Health Checks
184
175
 
176
+
185
177
  ### Basic Health Check
186
178
  ```typescript
187
- import { addHealthCheck, createHealthCheck, withHealthCheck } from '@naman_deep_singh/server-utils';
179
+ import { createHealthCheck } from '@naman_deep_singh/server-utils';
188
180
 
189
- // Method 1: Direct addition
190
- addHealthCheck(server.app, '/health');
181
+ // The health check is automatically enabled when healthCheck is not false
182
+ // Health endpoint is available at /health by default
191
183
 
192
- // Method 2: As middleware
184
+ // If you need to customize or disable it:
193
185
  server.app.get('/health', createHealthCheck());
194
-
195
- // Method 3: As plugin
196
- const server = createServerWithPlugins('My API', '1.0.0', [
197
- withHealthCheck('/health')
198
- ]);
199
- ```
200
-
201
- ### Advanced Health Checks
202
- ```typescript
203
- addHealthCheck(server.app, '/health', {
204
- customChecks: [
205
- {
206
- name: 'database',
207
- check: async () => {
208
- // Check database connection
209
- return await db.ping();
210
- }
211
- },
212
- {
213
- name: 'redis',
214
- check: async () => {
215
- return await redis.ping() === 'PONG';
216
- }
217
- }
218
- ]
219
- });
220
-
221
- // Response format:
222
- // {
223
- // "status": "healthy",
224
- // "checks": {
225
- // "server": true,
226
- // "timestamp": 1640995200000,
227
- // "database": true,
228
- // "redis": false
229
- // }
230
- // }
231
186
  ```
232
187
 
233
188
  ## Server Management
@@ -330,6 +285,12 @@ import { Request, Response, NextFunction, Router, Application } from '@naman_dee
330
285
  import type { RequestHandler, ErrorRequestHandler } from '@naman_deep_singh/server-utils';
331
286
 
332
287
  // No need to install Express separately in your services
288
+
289
+ ## TypeScript Notes
290
+
291
+ - This package includes TypeScript augmentations for Express `Request` and `Application` that expose runtime helpers used by the middleware (for example `req.cache`, `req.sessionStore`, `req.getSession`, and `req.createSession`). Installing and importing `@naman_deep_singh/server-utils` in your project will surface these types automatically.
292
+ - Middleware that attaches runtime props uses `unknown` internally and runtime guards — prefer the provided helpers rather than casting `req` to `any`.
293
+
333
294
  ```
334
295
 
335
296
  ## API Reference
@@ -418,4 +379,252 @@ server.app.get('/users', (req, res) => {
418
379
  const responder = (res as any).responder();
419
380
  return responder.okAndSend({ users: [] });
420
381
  });
382
+ ```
383
+
384
+ ## Cache & Session Integration
385
+
386
+ Built-in support for distributed caching and session management (disabled by default).
387
+
388
+ ### Enable Redis Cache
389
+
390
+ ```typescript
391
+ const server = createServer('My API', '1.0.0', {
392
+ port: 3000,
393
+ cache: {
394
+ enabled: true,
395
+ adapter: 'redis',
396
+ options: {
397
+ host: 'localhost',
398
+ port: 6379,
399
+ password: 'your_password'
400
+ },
401
+ defaultTTL: 3600 // seconds
402
+ }
403
+ });
404
+
405
+ // Access cache in routes
406
+ server.app.get('/user/:id', async (req, res) => {
407
+ const key = `user:${req.params.id}`;
408
+ const cached = await (req as any).cache.get(key);
409
+ if (cached) return res.json(cached);
410
+
411
+ // Fetch from DB, then cache
412
+ const user = { id: req.params.id, name: 'John' };
413
+ await (req as any).cache.set(key, user, 3600);
414
+ return res.json(user);
415
+ });
416
+ ```
417
+
418
+ ### Enable Redis Cluster Cache
419
+
420
+ ```typescript
421
+ const server = createServer('My API', '1.0.0', {
422
+ port: 3000,
423
+ cache: {
424
+ enabled: true,
425
+ adapter: 'redis',
426
+ options: {
427
+ cluster: [
428
+ { host: 'redis-node-1', port: 6379 },
429
+ { host: 'redis-node-2', port: 6379 },
430
+ { host: 'redis-node-3', port: 6379 }
431
+ ]
432
+ }
433
+ }
434
+ });
435
+ ```
436
+
437
+ ### Enable Memcache
438
+
439
+ ```typescript
440
+ const server = createServer('My API', '1.0.0', {
441
+ port: 3000,
442
+ cache: {
443
+ enabled: true,
444
+ adapter: 'memcache',
445
+ options: {
446
+ servers: ['localhost:11211', 'localhost:11212']
447
+ }
448
+ }
449
+ });
450
+ ```
451
+
452
+ ### Enable Sessions
453
+
454
+ ```typescript
455
+ const server = createServer('My API', '1.0.0', {
456
+ port: 3000,
457
+ cache: {
458
+ enabled: true,
459
+ adapter: 'redis',
460
+ options: { host: 'localhost', port: 6379 }
461
+ },
462
+ session: {
463
+ enabled: true,
464
+ cookieName: 'my_app.sid', // Defaults to {servername}.sid
465
+ ttl: 3600, // 1 hour
466
+ cookieOptions: {
467
+ httpOnly: true,
468
+ secure: true, // HTTPS only
469
+ sameSite: 'strict'
470
+ }
471
+ }
472
+ });
473
+
474
+ // Use sessions in routes
475
+ server.app.post('/login', async (req, res) => {
476
+ const sessionStore = (req.app as any).locals.sessionStore;
477
+ const sessionId = Math.random().toString(36).substring(7);
478
+
479
+ await sessionStore.create(sessionId, {
480
+ userId: 123,
481
+ username: 'john_doe',
482
+ loginTime: new Date()
483
+ });
484
+
485
+ res.cookie((req.app as any).locals.sessionCookieName, sessionId, {
486
+ httpOnly: true,
487
+ secure: true
488
+ });
489
+
490
+ return res.json({ message: 'Logged in' });
491
+ });
492
+
493
+ server.app.get('/profile', async (req, res) => {
494
+ const sessionId = (req as any).sessionId;
495
+ if (!sessionId) return res.status(401).json({ error: 'No session' });
496
+
497
+ const session = await (req as any).getSession();
498
+ if (!session) return res.status(401).json({ error: 'Session expired' });
499
+
500
+ return res.json({ user: session.username, loginTime: session.loginTime });
501
+ });
502
+ ```
503
+
504
+ ### Per-Route Response Caching
505
+
506
+ ```typescript
507
+ import { cacheResponse } from '@naman_deep_singh/server-utils';
508
+
509
+ // Cache GET response for 1 hour (3600 seconds)
510
+ server.app.get('/api/posts', cacheResponse(3600), (req, res) => {
511
+ // This endpoint's response is cached
512
+ res.json({ posts: [...] });
513
+ });
514
+
515
+ // Cache with default TTL from server config
516
+ server.app.get('/api/trending', cacheResponse(), (req, res) => {
517
+ res.json({ trending: [...] });
518
+ });
519
+ ```
520
+
521
+ ### Health Check with Cache Status
522
+
523
+ ```typescript
524
+ const server = createServer('My API', '1.0.0', {
525
+ healthCheck: '/health', // Automatic health endpoint
526
+ cache: { enabled: true, adapter: 'redis', ... }
527
+ });
528
+
529
+ // Health endpoint now includes cache status
530
+ // GET /health returns:
531
+ // {
532
+ // "status": "healthy",
533
+ // "service": "My API",
534
+ // "version": "1.0.0",
535
+ // "uptime": 12345,
536
+ // "timestamp": "2025-12-12T...",
537
+ // "cache": {
538
+ // "isAlive": true,
539
+ // "adapter": "redis",
540
+ // "timestamp": "2025-12-12T..."
541
+ // }
542
+ // }
543
+ ```
544
+
545
+ ### Cache Configuration Options
546
+
547
+ All configuration is optional — cache and session are disabled by default:
548
+
549
+ ```typescript
550
+ interface CacheConfig {
551
+ enabled?: boolean; // Default: false
552
+ adapter?: 'redis' | 'memcache' | 'memory'; // Default: 'memory'
553
+ options?: {
554
+ // Redis single instance
555
+ host?: string; // Default: 'localhost'
556
+ port?: number; // Default: 6379
557
+ username?: string;
558
+ password?: string;
559
+ db?: number; // 0-15
560
+ tls?: boolean;
561
+
562
+ // Redis cluster
563
+ cluster?: Array<{ host: string; port: number }> | {
564
+ nodes: Array<{ host: string; port: number }>;
565
+ options?: { maxRedirections?: number; ... };
566
+ };
567
+
568
+ // Memcache
569
+ servers?: string | string[]; // e.g., 'localhost:11211'
570
+
571
+ namespace?: string; // Key prefix
572
+ ttl?: number; // Default TTL in seconds
573
+ };
574
+ defaultTTL?: number; // Fallback TTL for routes
575
+ }
576
+
577
+ interface SessionConfig {
578
+ enabled?: boolean; // Default: false
579
+ cookieName?: string; // Default: {servername}.sid
580
+ ttl?: number; // Default: 3600 (1 hour)
581
+ cookieOptions?: {
582
+ path?: string;
583
+ httpOnly?: boolean; // Default: true
584
+ secure?: boolean; // HTTPS only
585
+ sameSite?: 'lax' | 'strict' | 'none';
586
+ };
587
+ }
588
+ ```
589
+
590
+ ### Graceful Shutdown
591
+
592
+ Cache and session stores are automatically closed on graceful shutdown:
593
+
594
+ ```typescript
595
+ const server = createServer('My API', '1.0.0', {
596
+ gracefulShutdown: true, // Enabled by default
597
+ cache: { enabled: true, adapter: 'redis', ... },
598
+ session: { enabled: true, ... }
599
+ });
600
+
601
+ // On SIGTERM/SIGINT, server will:
602
+ // 1. Stop accepting requests
603
+ // 2. Close cache connection (Redis/Memcache)
604
+ // 3. Close session store
605
+ // 4. Exit gracefully
606
+ ```
607
+
608
+ ## Feature Flags
609
+
610
+ All major features can be toggled independently:
611
+
612
+ ```typescript
613
+ const server = createServer('My API', '1.0.0', {
614
+ port: 3000,
615
+ cors: true, // Default: true
616
+ helmet: true, // Default: true
617
+ json: true, // Default: true
618
+ cookieParser: false, // Default: false
619
+ healthCheck: '/health', // Default: true
620
+ gracefulShutdown: true, // Default: true
621
+ cache: { enabled: false }, // Default: disabled
622
+ session: { enabled: false }, // Default: disabled
623
+ socketIO: { enabled: false }, // Default: disabled
624
+ periodicHealthCheck: { // Default: disabled
625
+ enabled: false,
626
+ interval: 30000,
627
+ services: [...]
628
+ }
629
+ });
421
630
  ```
@@ -4,7 +4,7 @@ export { Request, Response, NextFunction, Router, Application } from 'express';
4
4
  export type { RequestHandler, ErrorRequestHandler } from 'express';
5
5
  export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
6
6
  export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
7
- export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, type ValidationRule, type RateLimitConfig, type AuthConfig } from './middleware';
7
+ export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, cacheResponse, useSession, type ValidationRule, type RateLimitConfig, type AuthConfig } from './middleware';
8
8
  export { getEnv, getEnvNumber, getEnvBoolean } from './utils';
9
9
  export { PeriodicHealthMonitor } from './periodic-health';
10
10
  export type { ServerConfig, HealthCheckConfig, HealthCheck, GracefulShutdownConfig, ServerPlugin, SocketIOConfig, SocketInstance, PeriodicHealthCheckConfig, HealthCheckService } from './types';
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PeriodicHealthMonitor = exports.getEnvBoolean = exports.getEnvNumber = exports.getEnv = exports.requireAuth = exports.rateLimit = exports.validateFields = exports.withAuth = exports.withRateLimit = exports.withValidation = exports.withRequestId = exports.withErrorHandler = exports.withLogging = exports.createAuthMiddleware = exports.createRateLimitMiddleware = exports.createValidationMiddleware = exports.createRequestIdMiddleware = exports.createErrorHandler = exports.createLoggingMiddleware = exports.startServerWithShutdown = exports.withGracefulShutdown = exports.createGracefulShutdown = exports.addHealthCheck = exports.withHealthCheck = exports.createHealthCheck = exports.Router = exports.createServer = exports.ExpressServer = void 0;
3
+ exports.PeriodicHealthMonitor = exports.getEnvBoolean = exports.getEnvNumber = exports.getEnv = exports.useSession = exports.cacheResponse = exports.requireAuth = exports.rateLimit = exports.validateFields = exports.withAuth = exports.withRateLimit = exports.withValidation = exports.withRequestId = exports.withErrorHandler = exports.withLogging = exports.createAuthMiddleware = exports.createRateLimitMiddleware = exports.createValidationMiddleware = exports.createRequestIdMiddleware = exports.createErrorHandler = exports.createLoggingMiddleware = exports.startServerWithShutdown = exports.withGracefulShutdown = exports.createGracefulShutdown = exports.addHealthCheck = exports.withHealthCheck = exports.createHealthCheck = exports.Router = exports.createServer = exports.ExpressServer = void 0;
4
4
  // Core server utilities
5
5
  var server_1 = require("./server");
6
6
  Object.defineProperty(exports, "ExpressServer", { enumerable: true, get: function () { return server_1.ExpressServer; } });
@@ -35,6 +35,8 @@ Object.defineProperty(exports, "withAuth", { enumerable: true, get: function ()
35
35
  Object.defineProperty(exports, "validateFields", { enumerable: true, get: function () { return middleware_1.validateFields; } });
36
36
  Object.defineProperty(exports, "rateLimit", { enumerable: true, get: function () { return middleware_1.rateLimit; } });
37
37
  Object.defineProperty(exports, "requireAuth", { enumerable: true, get: function () { return middleware_1.requireAuth; } });
38
+ Object.defineProperty(exports, "cacheResponse", { enumerable: true, get: function () { return middleware_1.cacheResponse; } });
39
+ Object.defineProperty(exports, "useSession", { enumerable: true, get: function () { return middleware_1.useSession; } });
38
40
  // Utility functions
39
41
  var utils_1 = require("./utils");
40
42
  Object.defineProperty(exports, "getEnv", { enumerable: true, get: function () { return utils_1.getEnv; } });
@@ -35,3 +35,5 @@ export declare function withAuth(config: AuthConfig): ServerPlugin;
35
35
  export declare function validateFields(rules: ValidationRule[]): express.RequestHandler;
36
36
  export declare function rateLimit(config?: RateLimitConfig): express.RequestHandler;
37
37
  export declare function requireAuth(config: AuthConfig): express.RequestHandler;
38
+ export declare function cacheResponse(ttl?: number): express.RequestHandler;
39
+ export declare function useSession(cookieName?: string): express.RequestHandler;
@@ -15,6 +15,8 @@ exports.withAuth = withAuth;
15
15
  exports.validateFields = validateFields;
16
16
  exports.rateLimit = rateLimit;
17
17
  exports.requireAuth = requireAuth;
18
+ exports.cacheResponse = cacheResponse;
19
+ exports.useSession = useSession;
18
20
  // Logging middleware
19
21
  function createLoggingMiddleware(format = 'simple') {
20
22
  return (req, res, next) => {
@@ -244,3 +246,103 @@ function rateLimit(config = {}) {
244
246
  function requireAuth(config) {
245
247
  return createAuthMiddleware(config);
246
248
  }
249
+ // Cache response middleware (per-route opt-in)
250
+ function cacheResponse(ttl) {
251
+ return async (req, res, next) => {
252
+ try {
253
+ if (req.method !== 'GET')
254
+ return next();
255
+ const cache = (req.cache ?? req.app.locals.cache);
256
+ const defaultTTL = req.app.locals.cacheDefaultTTL;
257
+ if (!cache || typeof cache.get !== 'function')
258
+ return next();
259
+ const key = `${req.originalUrl}`;
260
+ try {
261
+ const cached = await cache.get(key);
262
+ if (cached !== null && cached !== undefined) {
263
+ res.setHeader('X-Cache', 'HIT');
264
+ return res.json(cached);
265
+ }
266
+ }
267
+ catch (cacheErr) {
268
+ console.error(`[Cache] Failed to retrieve key "${key}":`, cacheErr);
269
+ // Continue without cache hit
270
+ }
271
+ const originalJson = res.json.bind(res);
272
+ res.json = (body) => {
273
+ try {
274
+ const expiry = ttl ?? defaultTTL;
275
+ if (expiry && cache && typeof cache.set === 'function') {
276
+ cache.set(key, body, expiry).catch((err) => {
277
+ console.error(`[Cache] Failed to set key "${key}" with TTL ${expiry}:`, err);
278
+ });
279
+ }
280
+ else if (cache) {
281
+ if (typeof cache.set === 'function') {
282
+ cache.set(key, body).catch((err) => {
283
+ console.error(`[Cache] Failed to set key "${key}":`, err);
284
+ });
285
+ }
286
+ }
287
+ }
288
+ catch (e) {
289
+ console.error(`[Cache] Error during cache.set operation:`, e);
290
+ }
291
+ res.setHeader('X-Cache', 'MISS');
292
+ return originalJson(body);
293
+ };
294
+ next();
295
+ }
296
+ catch (err) {
297
+ console.error('[Cache] Unexpected error in cacheResponse middleware:', err);
298
+ next();
299
+ }
300
+ };
301
+ }
302
+ // Session middleware helper (attaches sessionStore and helpers to req)
303
+ function useSession(cookieName) {
304
+ return async (req, res, next) => {
305
+ try {
306
+ const store = req.app.locals.sessionStore;
307
+ if (!store)
308
+ return next();
309
+ const name = cookieName || req.app.locals.sessionCookieName || 'sid';
310
+ let sid = req.cookies?.[name];
311
+ if (!sid) {
312
+ const cookieHeader = req.headers.cookie;
313
+ if (cookieHeader) {
314
+ const match = cookieHeader.split(';').map(s => s.trim()).find(s => s.startsWith(name + '='));
315
+ if (match)
316
+ sid = match.split('=')[1];
317
+ }
318
+ }
319
+ req.sessionId = sid;
320
+ req.sessionStore = store;
321
+ req.getSession = async () => {
322
+ if (!sid)
323
+ return null;
324
+ try {
325
+ return await store.get(sid);
326
+ }
327
+ catch (err) {
328
+ console.error(`[Session] Failed to get session "${sid}":`, err);
329
+ throw err;
330
+ }
331
+ };
332
+ req.createSession = async (id, data, ttl) => {
333
+ try {
334
+ return await store.create(id, data, ttl);
335
+ }
336
+ catch (err) {
337
+ console.error(`[Session] Failed to create session "${id}":`, err);
338
+ throw err;
339
+ }
340
+ };
341
+ next();
342
+ }
343
+ catch (err) {
344
+ console.error('[Session] Unexpected error in useSession middleware:', err);
345
+ next();
346
+ }
347
+ };
348
+ }
@@ -49,6 +49,8 @@ export declare class ExpressServer implements ServerInstance {
49
49
  app: express.Application;
50
50
  server?: Server;
51
51
  config: ServerInstanceConfig;
52
+ cache?: import('@naman_deep_singh/cache').ICache<unknown>;
53
+ sessionStore?: import('@naman_deep_singh/cache').SessionStore | undefined;
52
54
  private status;
53
55
  private grpcServices;
54
56
  private grpcServer?;
@@ -57,6 +59,7 @@ export declare class ExpressServer implements ServerInstance {
57
59
  private healthMonitor?;
58
60
  constructor(name?: string, version?: string, config?: ServerConfig);
59
61
  private setupMiddleware;
62
+ private setupCacheAndSession;
60
63
  private setupPeriodicHealthMonitoring;
61
64
  start(): Promise<ServerInstance>;
62
65
  stop(): Promise<void>;
@@ -9,6 +9,7 @@ const express_1 = __importDefault(require("express"));
9
9
  const shutdown_1 = require("./shutdown");
10
10
  const periodic_health_1 = require("./periodic-health");
11
11
  const crypto_1 = __importDefault(require("crypto"));
12
+ const cache_1 = require("@naman_deep_singh/cache");
12
13
  class ExpressServer {
13
14
  constructor(name = 'Express Server', version = '1.0.0', config = {}) {
14
15
  this.status = 'stopped';
@@ -28,8 +29,14 @@ class ExpressServer {
28
29
  healthCheck: config.healthCheck ?? true,
29
30
  gracefulShutdown: config.gracefulShutdown ?? true,
30
31
  socketIO: config.socketIO,
31
- periodicHealthCheck: config.periodicHealthCheck || { enabled: false }
32
+ periodicHealthCheck: config.periodicHealthCheck || { enabled: false },
33
+ cache: config.cache || { enabled: false },
34
+ session: config.session || { enabled: false }
32
35
  };
36
+ // Initialize locals for cache/session
37
+ this.app.locals.cache = undefined;
38
+ this.app.locals.sessionStore = undefined;
39
+ this.app.locals.cacheDefaultTTL = config.cache?.defaultTTL;
33
40
  // Apply middleware based on configuration
34
41
  this.setupMiddleware();
35
42
  // Setup periodic health monitoring
@@ -80,17 +87,102 @@ class ExpressServer {
80
87
  // Add health check if enabled
81
88
  if (this.config.healthCheck) {
82
89
  const healthPath = typeof this.config.healthCheck === 'string' ? this.config.healthCheck : '/health';
83
- this.app.get(healthPath, (req, res) => {
84
- res.status(200).json({
90
+ this.app.get(healthPath, async (req, res) => {
91
+ const base = {
85
92
  status: 'healthy',
86
93
  service: this.config.name,
87
94
  version: this.config.version,
88
95
  uptime: Date.now() - this.config.startTime.getTime(),
89
96
  timestamp: new Date().toISOString()
90
- });
97
+ };
98
+ // If cache is enabled, include its health
99
+ const cache = req.app.locals.cache;
100
+ if (cache && typeof cache.isAlive === 'function') {
101
+ try {
102
+ base.cache = await cache.isAlive();
103
+ }
104
+ catch (e) {
105
+ base.cache = { isAlive: false, adapter: 'unknown', timestamp: new Date(), error: e.message };
106
+ }
107
+ }
108
+ res.status(200).json(base);
91
109
  });
92
110
  }
93
111
  }
112
+ async setupCacheAndSession(config, serverName) {
113
+ try {
114
+ // Initialize cache if enabled
115
+ if (config.cache && config.cache.enabled) {
116
+ try {
117
+ const provided = config.cache?.options;
118
+ let cacheConfig = provided && typeof provided === 'object' ? provided : undefined;
119
+ if (!cacheConfig) {
120
+ cacheConfig = { adapter: config.cache.adapter || 'memory' };
121
+ }
122
+ console.log(`🔄 [${serverName}] Initializing cache adapter: ${config.cache.adapter || 'memory'}...`);
123
+ // Use createWithFallback to prefer primary and fall back to memory when configured
124
+ const cfg = { ...(cacheConfig || {}), ttl: cacheConfig?.ttl ?? config.cache?.defaultTTL };
125
+ const cache = await cache_1.CacheFactory.createWithFallback(cfg);
126
+ this.app.locals.cache = cache;
127
+ this.cache = cache;
128
+ this.app.locals.cacheDefaultTTL = config.cache?.defaultTTL;
129
+ // attach per-request helper middleware
130
+ this.app.use((req, _res, next) => {
131
+ req.cache = cache;
132
+ next();
133
+ });
134
+ console.log(`✅ [${serverName}] Cache initialized successfully (adapter: ${(cacheConfig.adapter || 'memory')})`);
135
+ }
136
+ catch (err) {
137
+ console.error(`❌ [${serverName}] Failed to initialize cache (fallback to memory if enabled):`, err instanceof Error ? err.message : err);
138
+ // Cache initialization error is critical but we continue to allow graceful fallback
139
+ }
140
+ }
141
+ // Initialize session if enabled
142
+ if (config.session && config.session.enabled) {
143
+ const cookieName = config.session.cookieName || `${serverName.replace(/\s+/g, '_').toLowerCase()}.sid`;
144
+ const ttl = config.session.ttl ?? 3600;
145
+ let cache = this.app.locals.cache;
146
+ if (!cache) {
147
+ // fallback to in-memory cache for session store
148
+ try {
149
+ cache = cache_1.CacheFactory.create({ adapter: 'memory' });
150
+ this.app.locals.cache = cache;
151
+ this.cache = cache;
152
+ console.log(`📝 [${serverName}] Session store using in-memory cache`);
153
+ }
154
+ catch (e) {
155
+ console.error(`❌ [${serverName}] Failed to create in-memory cache for sessions:`, e instanceof Error ? e.message : e);
156
+ }
157
+ }
158
+ else {
159
+ console.log(`📝 [${serverName}] Session store initialized with configured cache adapter`);
160
+ }
161
+ if (!cache) {
162
+ console.error(`❌ [${serverName}] CRITICAL: Session enabled but no cache available to store sessions. Session functionality will be unavailable.`);
163
+ }
164
+ else {
165
+ const store = new cache_1.SessionStore(cache, { ttl });
166
+ this.app.locals.sessionStore = store;
167
+ this.app.locals.sessionCookieName = cookieName;
168
+ this.sessionStore = store;
169
+ // attach session middleware globally so req.sessionStore is available
170
+ try {
171
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
172
+ const { useSession } = require('./middleware');
173
+ this.app.use(useSession(cookieName));
174
+ console.log(`✅ [${serverName}] Session middleware enabled (cookie: ${cookieName}, TTL: ${ttl}s)`);
175
+ }
176
+ catch (err) {
177
+ console.error(`❌ [${serverName}] Session middleware not available:`, err instanceof Error ? err.message : err);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ catch (err) {
183
+ console.error(`❌ [${serverName}] Error during cache/session setup:`, err instanceof Error ? err.message : err);
184
+ }
185
+ }
94
186
  setupPeriodicHealthMonitoring() {
95
187
  if (this.config.periodicHealthCheck?.enabled) {
96
188
  this.healthMonitor = new periodic_health_1.PeriodicHealthMonitor(this.config.periodicHealthCheck, this.config.name);
@@ -98,6 +190,8 @@ class ExpressServer {
98
190
  }
99
191
  async start() {
100
192
  this.status = 'starting';
193
+ // Initialize cache and session before starting the server
194
+ await this.setupCacheAndSession(this.config, this.config.name);
101
195
  return new Promise((resolve, reject) => {
102
196
  try {
103
197
  this.server = this.app.listen(this.config.port, () => {
@@ -111,6 +205,25 @@ class ExpressServer {
111
205
  if (this.healthMonitor) {
112
206
  this.healthMonitor.stop();
113
207
  }
208
+ // Close cache and session store if present
209
+ try {
210
+ const cache = this.app.locals.cache;
211
+ if (cache && typeof cache.close === 'function') {
212
+ await cache.close();
213
+ }
214
+ }
215
+ catch (e) {
216
+ console.warn(`${this.config.name}: Error closing cache`, e);
217
+ }
218
+ try {
219
+ const store = this.app.locals.sessionStore;
220
+ if (store && typeof store.close === 'function') {
221
+ await store.close();
222
+ }
223
+ }
224
+ catch (e) {
225
+ // SessionStore may not have close; ignore
226
+ }
114
227
  }
115
228
  });
116
229
  }
@@ -2,4 +2,4 @@ import { Server } from 'http';
2
2
  import { GracefulShutdownConfig, ServerPlugin } from './types';
3
3
  export declare function createGracefulShutdown(server: Server, config?: GracefulShutdownConfig): void;
4
4
  export declare function withGracefulShutdown(config?: GracefulShutdownConfig): ServerPlugin;
5
- export declare function startServerWithShutdown(app: any, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
5
+ export declare function startServerWithShutdown(app: import('express').Application, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
@@ -22,6 +22,23 @@ export interface ServerConfig {
22
22
  periodicHealthCheck?: PeriodicHealthCheckConfig;
23
23
  name?: string;
24
24
  version?: string;
25
+ cache?: {
26
+ enabled?: boolean;
27
+ adapter?: 'redis' | 'memcache' | 'memory';
28
+ options?: unknown;
29
+ defaultTTL?: number;
30
+ };
31
+ session?: {
32
+ enabled?: boolean;
33
+ cookieName?: string;
34
+ ttl?: number;
35
+ cookieOptions?: {
36
+ path?: string;
37
+ httpOnly?: boolean;
38
+ secure?: boolean;
39
+ sameSite?: 'lax' | 'strict' | 'none';
40
+ };
41
+ };
25
42
  }
26
43
  export interface PeriodicHealthCheckConfig {
27
44
  enabled?: boolean;
@@ -4,7 +4,7 @@ export { Request, Response, NextFunction, Router, Application } from 'express';
4
4
  export type { RequestHandler, ErrorRequestHandler } from 'express';
5
5
  export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
6
6
  export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
7
- export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, type ValidationRule, type RateLimitConfig, type AuthConfig } from './middleware';
7
+ export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, cacheResponse, useSession, type ValidationRule, type RateLimitConfig, type AuthConfig } from './middleware';
8
8
  export { getEnv, getEnvNumber, getEnvBoolean } from './utils';
9
9
  export { PeriodicHealthMonitor } from './periodic-health';
10
10
  export type { ServerConfig, HealthCheckConfig, HealthCheck, GracefulShutdownConfig, ServerPlugin, SocketIOConfig, SocketInstance, PeriodicHealthCheckConfig, HealthCheckService } from './types';
package/dist/esm/index.js CHANGED
@@ -7,7 +7,7 @@ export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
7
7
  // Graceful shutdown utilities
8
8
  export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
9
9
  // Middleware utilities
10
- export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth } from './middleware';
10
+ export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, cacheResponse, useSession } from './middleware';
11
11
  // Utility functions
12
12
  export { getEnv, getEnvNumber, getEnvBoolean } from './utils';
13
13
  // Periodic health monitoring
@@ -35,3 +35,5 @@ export declare function withAuth(config: AuthConfig): ServerPlugin;
35
35
  export declare function validateFields(rules: ValidationRule[]): express.RequestHandler;
36
36
  export declare function rateLimit(config?: RateLimitConfig): express.RequestHandler;
37
37
  export declare function requireAuth(config: AuthConfig): express.RequestHandler;
38
+ export declare function cacheResponse(ttl?: number): express.RequestHandler;
39
+ export declare function useSession(cookieName?: string): express.RequestHandler;
@@ -227,3 +227,103 @@ export function rateLimit(config = {}) {
227
227
  export function requireAuth(config) {
228
228
  return createAuthMiddleware(config);
229
229
  }
230
+ // Cache response middleware (per-route opt-in)
231
+ export function cacheResponse(ttl) {
232
+ return async (req, res, next) => {
233
+ try {
234
+ if (req.method !== 'GET')
235
+ return next();
236
+ const cache = (req.cache ?? req.app.locals.cache);
237
+ const defaultTTL = req.app.locals.cacheDefaultTTL;
238
+ if (!cache || typeof cache.get !== 'function')
239
+ return next();
240
+ const key = `${req.originalUrl}`;
241
+ try {
242
+ const cached = await cache.get(key);
243
+ if (cached !== null && cached !== undefined) {
244
+ res.setHeader('X-Cache', 'HIT');
245
+ return res.json(cached);
246
+ }
247
+ }
248
+ catch (cacheErr) {
249
+ console.error(`[Cache] Failed to retrieve key "${key}":`, cacheErr);
250
+ // Continue without cache hit
251
+ }
252
+ const originalJson = res.json.bind(res);
253
+ res.json = (body) => {
254
+ try {
255
+ const expiry = ttl ?? defaultTTL;
256
+ if (expiry && cache && typeof cache.set === 'function') {
257
+ cache.set(key, body, expiry).catch((err) => {
258
+ console.error(`[Cache] Failed to set key "${key}" with TTL ${expiry}:`, err);
259
+ });
260
+ }
261
+ else if (cache) {
262
+ if (typeof cache.set === 'function') {
263
+ cache.set(key, body).catch((err) => {
264
+ console.error(`[Cache] Failed to set key "${key}":`, err);
265
+ });
266
+ }
267
+ }
268
+ }
269
+ catch (e) {
270
+ console.error(`[Cache] Error during cache.set operation:`, e);
271
+ }
272
+ res.setHeader('X-Cache', 'MISS');
273
+ return originalJson(body);
274
+ };
275
+ next();
276
+ }
277
+ catch (err) {
278
+ console.error('[Cache] Unexpected error in cacheResponse middleware:', err);
279
+ next();
280
+ }
281
+ };
282
+ }
283
+ // Session middleware helper (attaches sessionStore and helpers to req)
284
+ export function useSession(cookieName) {
285
+ return async (req, res, next) => {
286
+ try {
287
+ const store = req.app.locals.sessionStore;
288
+ if (!store)
289
+ return next();
290
+ const name = cookieName || req.app.locals.sessionCookieName || 'sid';
291
+ let sid = req.cookies?.[name];
292
+ if (!sid) {
293
+ const cookieHeader = req.headers.cookie;
294
+ if (cookieHeader) {
295
+ const match = cookieHeader.split(';').map(s => s.trim()).find(s => s.startsWith(name + '='));
296
+ if (match)
297
+ sid = match.split('=')[1];
298
+ }
299
+ }
300
+ req.sessionId = sid;
301
+ req.sessionStore = store;
302
+ req.getSession = async () => {
303
+ if (!sid)
304
+ return null;
305
+ try {
306
+ return await store.get(sid);
307
+ }
308
+ catch (err) {
309
+ console.error(`[Session] Failed to get session "${sid}":`, err);
310
+ throw err;
311
+ }
312
+ };
313
+ req.createSession = async (id, data, ttl) => {
314
+ try {
315
+ return await store.create(id, data, ttl);
316
+ }
317
+ catch (err) {
318
+ console.error(`[Session] Failed to create session "${id}":`, err);
319
+ throw err;
320
+ }
321
+ };
322
+ next();
323
+ }
324
+ catch (err) {
325
+ console.error('[Session] Unexpected error in useSession middleware:', err);
326
+ next();
327
+ }
328
+ };
329
+ }
@@ -49,6 +49,8 @@ export declare class ExpressServer implements ServerInstance {
49
49
  app: express.Application;
50
50
  server?: Server;
51
51
  config: ServerInstanceConfig;
52
+ cache?: import('@naman_deep_singh/cache').ICache<unknown>;
53
+ sessionStore?: import('@naman_deep_singh/cache').SessionStore | undefined;
52
54
  private status;
53
55
  private grpcServices;
54
56
  private grpcServer?;
@@ -57,6 +59,7 @@ export declare class ExpressServer implements ServerInstance {
57
59
  private healthMonitor?;
58
60
  constructor(name?: string, version?: string, config?: ServerConfig);
59
61
  private setupMiddleware;
62
+ private setupCacheAndSession;
60
63
  private setupPeriodicHealthMonitoring;
61
64
  start(): Promise<ServerInstance>;
62
65
  stop(): Promise<void>;
@@ -2,6 +2,7 @@ import express from 'express';
2
2
  import { createGracefulShutdown } from './shutdown';
3
3
  import { PeriodicHealthMonitor } from './periodic-health';
4
4
  import crypto from 'crypto';
5
+ import { CacheFactory, SessionStore } from '@naman_deep_singh/cache';
5
6
  export class ExpressServer {
6
7
  constructor(name = 'Express Server', version = '1.0.0', config = {}) {
7
8
  this.status = 'stopped';
@@ -21,8 +22,14 @@ export class ExpressServer {
21
22
  healthCheck: config.healthCheck ?? true,
22
23
  gracefulShutdown: config.gracefulShutdown ?? true,
23
24
  socketIO: config.socketIO,
24
- periodicHealthCheck: config.periodicHealthCheck || { enabled: false }
25
+ periodicHealthCheck: config.periodicHealthCheck || { enabled: false },
26
+ cache: config.cache || { enabled: false },
27
+ session: config.session || { enabled: false }
25
28
  };
29
+ // Initialize locals for cache/session
30
+ this.app.locals.cache = undefined;
31
+ this.app.locals.sessionStore = undefined;
32
+ this.app.locals.cacheDefaultTTL = config.cache?.defaultTTL;
26
33
  // Apply middleware based on configuration
27
34
  this.setupMiddleware();
28
35
  // Setup periodic health monitoring
@@ -73,17 +80,102 @@ export class ExpressServer {
73
80
  // Add health check if enabled
74
81
  if (this.config.healthCheck) {
75
82
  const healthPath = typeof this.config.healthCheck === 'string' ? this.config.healthCheck : '/health';
76
- this.app.get(healthPath, (req, res) => {
77
- res.status(200).json({
83
+ this.app.get(healthPath, async (req, res) => {
84
+ const base = {
78
85
  status: 'healthy',
79
86
  service: this.config.name,
80
87
  version: this.config.version,
81
88
  uptime: Date.now() - this.config.startTime.getTime(),
82
89
  timestamp: new Date().toISOString()
83
- });
90
+ };
91
+ // If cache is enabled, include its health
92
+ const cache = req.app.locals.cache;
93
+ if (cache && typeof cache.isAlive === 'function') {
94
+ try {
95
+ base.cache = await cache.isAlive();
96
+ }
97
+ catch (e) {
98
+ base.cache = { isAlive: false, adapter: 'unknown', timestamp: new Date(), error: e.message };
99
+ }
100
+ }
101
+ res.status(200).json(base);
84
102
  });
85
103
  }
86
104
  }
105
+ async setupCacheAndSession(config, serverName) {
106
+ try {
107
+ // Initialize cache if enabled
108
+ if (config.cache && config.cache.enabled) {
109
+ try {
110
+ const provided = config.cache?.options;
111
+ let cacheConfig = provided && typeof provided === 'object' ? provided : undefined;
112
+ if (!cacheConfig) {
113
+ cacheConfig = { adapter: config.cache.adapter || 'memory' };
114
+ }
115
+ console.log(`🔄 [${serverName}] Initializing cache adapter: ${config.cache.adapter || 'memory'}...`);
116
+ // Use createWithFallback to prefer primary and fall back to memory when configured
117
+ const cfg = { ...(cacheConfig || {}), ttl: cacheConfig?.ttl ?? config.cache?.defaultTTL };
118
+ const cache = await CacheFactory.createWithFallback(cfg);
119
+ this.app.locals.cache = cache;
120
+ this.cache = cache;
121
+ this.app.locals.cacheDefaultTTL = config.cache?.defaultTTL;
122
+ // attach per-request helper middleware
123
+ this.app.use((req, _res, next) => {
124
+ req.cache = cache;
125
+ next();
126
+ });
127
+ console.log(`✅ [${serverName}] Cache initialized successfully (adapter: ${(cacheConfig.adapter || 'memory')})`);
128
+ }
129
+ catch (err) {
130
+ console.error(`❌ [${serverName}] Failed to initialize cache (fallback to memory if enabled):`, err instanceof Error ? err.message : err);
131
+ // Cache initialization error is critical but we continue to allow graceful fallback
132
+ }
133
+ }
134
+ // Initialize session if enabled
135
+ if (config.session && config.session.enabled) {
136
+ const cookieName = config.session.cookieName || `${serverName.replace(/\s+/g, '_').toLowerCase()}.sid`;
137
+ const ttl = config.session.ttl ?? 3600;
138
+ let cache = this.app.locals.cache;
139
+ if (!cache) {
140
+ // fallback to in-memory cache for session store
141
+ try {
142
+ cache = CacheFactory.create({ adapter: 'memory' });
143
+ this.app.locals.cache = cache;
144
+ this.cache = cache;
145
+ console.log(`📝 [${serverName}] Session store using in-memory cache`);
146
+ }
147
+ catch (e) {
148
+ console.error(`❌ [${serverName}] Failed to create in-memory cache for sessions:`, e instanceof Error ? e.message : e);
149
+ }
150
+ }
151
+ else {
152
+ console.log(`📝 [${serverName}] Session store initialized with configured cache adapter`);
153
+ }
154
+ if (!cache) {
155
+ console.error(`❌ [${serverName}] CRITICAL: Session enabled but no cache available to store sessions. Session functionality will be unavailable.`);
156
+ }
157
+ else {
158
+ const store = new SessionStore(cache, { ttl });
159
+ this.app.locals.sessionStore = store;
160
+ this.app.locals.sessionCookieName = cookieName;
161
+ this.sessionStore = store;
162
+ // attach session middleware globally so req.sessionStore is available
163
+ try {
164
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
165
+ const { useSession } = require('./middleware');
166
+ this.app.use(useSession(cookieName));
167
+ console.log(`✅ [${serverName}] Session middleware enabled (cookie: ${cookieName}, TTL: ${ttl}s)`);
168
+ }
169
+ catch (err) {
170
+ console.error(`❌ [${serverName}] Session middleware not available:`, err instanceof Error ? err.message : err);
171
+ }
172
+ }
173
+ }
174
+ }
175
+ catch (err) {
176
+ console.error(`❌ [${serverName}] Error during cache/session setup:`, err instanceof Error ? err.message : err);
177
+ }
178
+ }
87
179
  setupPeriodicHealthMonitoring() {
88
180
  if (this.config.periodicHealthCheck?.enabled) {
89
181
  this.healthMonitor = new PeriodicHealthMonitor(this.config.periodicHealthCheck, this.config.name);
@@ -91,6 +183,8 @@ export class ExpressServer {
91
183
  }
92
184
  async start() {
93
185
  this.status = 'starting';
186
+ // Initialize cache and session before starting the server
187
+ await this.setupCacheAndSession(this.config, this.config.name);
94
188
  return new Promise((resolve, reject) => {
95
189
  try {
96
190
  this.server = this.app.listen(this.config.port, () => {
@@ -104,6 +198,25 @@ export class ExpressServer {
104
198
  if (this.healthMonitor) {
105
199
  this.healthMonitor.stop();
106
200
  }
201
+ // Close cache and session store if present
202
+ try {
203
+ const cache = this.app.locals.cache;
204
+ if (cache && typeof cache.close === 'function') {
205
+ await cache.close();
206
+ }
207
+ }
208
+ catch (e) {
209
+ console.warn(`${this.config.name}: Error closing cache`, e);
210
+ }
211
+ try {
212
+ const store = this.app.locals.sessionStore;
213
+ if (store && typeof store.close === 'function') {
214
+ await store.close();
215
+ }
216
+ }
217
+ catch (e) {
218
+ // SessionStore may not have close; ignore
219
+ }
107
220
  }
108
221
  });
109
222
  }
@@ -2,4 +2,4 @@ import { Server } from 'http';
2
2
  import { GracefulShutdownConfig, ServerPlugin } from './types';
3
3
  export declare function createGracefulShutdown(server: Server, config?: GracefulShutdownConfig): void;
4
4
  export declare function withGracefulShutdown(config?: GracefulShutdownConfig): ServerPlugin;
5
- export declare function startServerWithShutdown(app: any, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
5
+ export declare function startServerWithShutdown(app: import('express').Application, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
@@ -22,6 +22,23 @@ export interface ServerConfig {
22
22
  periodicHealthCheck?: PeriodicHealthCheckConfig;
23
23
  name?: string;
24
24
  version?: string;
25
+ cache?: {
26
+ enabled?: boolean;
27
+ adapter?: 'redis' | 'memcache' | 'memory';
28
+ options?: unknown;
29
+ defaultTTL?: number;
30
+ };
31
+ session?: {
32
+ enabled?: boolean;
33
+ cookieName?: string;
34
+ ttl?: number;
35
+ cookieOptions?: {
36
+ path?: string;
37
+ httpOnly?: boolean;
38
+ secure?: boolean;
39
+ sameSite?: 'lax' | 'strict' | 'none';
40
+ };
41
+ };
25
42
  }
26
43
  export interface PeriodicHealthCheckConfig {
27
44
  enabled?: boolean;
@@ -4,7 +4,7 @@ export { Request, Response, NextFunction, Router, Application } from 'express';
4
4
  export type { RequestHandler, ErrorRequestHandler } from 'express';
5
5
  export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
6
6
  export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
7
- export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, type ValidationRule, type RateLimitConfig, type AuthConfig } from './middleware';
7
+ export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, cacheResponse, useSession, type ValidationRule, type RateLimitConfig, type AuthConfig } from './middleware';
8
8
  export { getEnv, getEnvNumber, getEnvBoolean } from './utils';
9
9
  export { PeriodicHealthMonitor } from './periodic-health';
10
10
  export type { ServerConfig, HealthCheckConfig, HealthCheck, GracefulShutdownConfig, ServerPlugin, SocketIOConfig, SocketInstance, PeriodicHealthCheckConfig, HealthCheckService } from './types';
@@ -35,3 +35,5 @@ export declare function withAuth(config: AuthConfig): ServerPlugin;
35
35
  export declare function validateFields(rules: ValidationRule[]): express.RequestHandler;
36
36
  export declare function rateLimit(config?: RateLimitConfig): express.RequestHandler;
37
37
  export declare function requireAuth(config: AuthConfig): express.RequestHandler;
38
+ export declare function cacheResponse(ttl?: number): express.RequestHandler;
39
+ export declare function useSession(cookieName?: string): express.RequestHandler;
@@ -49,6 +49,8 @@ export declare class ExpressServer implements ServerInstance {
49
49
  app: express.Application;
50
50
  server?: Server;
51
51
  config: ServerInstanceConfig;
52
+ cache?: import('@naman_deep_singh/cache').ICache<unknown>;
53
+ sessionStore?: import('@naman_deep_singh/cache').SessionStore | undefined;
52
54
  private status;
53
55
  private grpcServices;
54
56
  private grpcServer?;
@@ -57,6 +59,7 @@ export declare class ExpressServer implements ServerInstance {
57
59
  private healthMonitor?;
58
60
  constructor(name?: string, version?: string, config?: ServerConfig);
59
61
  private setupMiddleware;
62
+ private setupCacheAndSession;
60
63
  private setupPeriodicHealthMonitoring;
61
64
  start(): Promise<ServerInstance>;
62
65
  stop(): Promise<void>;
@@ -2,4 +2,4 @@ import { Server } from 'http';
2
2
  import { GracefulShutdownConfig, ServerPlugin } from './types';
3
3
  export declare function createGracefulShutdown(server: Server, config?: GracefulShutdownConfig): void;
4
4
  export declare function withGracefulShutdown(config?: GracefulShutdownConfig): ServerPlugin;
5
- export declare function startServerWithShutdown(app: any, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
5
+ export declare function startServerWithShutdown(app: import('express').Application, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
@@ -22,6 +22,23 @@ export interface ServerConfig {
22
22
  periodicHealthCheck?: PeriodicHealthCheckConfig;
23
23
  name?: string;
24
24
  version?: string;
25
+ cache?: {
26
+ enabled?: boolean;
27
+ adapter?: 'redis' | 'memcache' | 'memory';
28
+ options?: unknown;
29
+ defaultTTL?: number;
30
+ };
31
+ session?: {
32
+ enabled?: boolean;
33
+ cookieName?: string;
34
+ ttl?: number;
35
+ cookieOptions?: {
36
+ path?: string;
37
+ httpOnly?: boolean;
38
+ secure?: boolean;
39
+ sameSite?: 'lax' | 'strict' | 'none';
40
+ };
41
+ };
25
42
  }
26
43
  export interface PeriodicHealthCheckConfig {
27
44
  enabled?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naman_deep_singh/server-utils",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Extensible server utilities for Express.js microservices with TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -27,16 +27,17 @@
27
27
  "author": "Naman Deep Singh",
28
28
  "license": "ISC",
29
29
  "dependencies": {
30
- "express": "^5.1.0",
31
- "cors": "^2.8.5",
32
- "helmet": "^8.1.0",
30
+ "@naman_deep_singh/cache": "^1.2.0",
31
+ "@types/express": "^5.0.5",
33
32
  "cookie-parser": "^1.4.6",
34
- "@types/express": "^5.0.5"
33
+ "cors": "^2.8.5",
34
+ "express": "^5.1.0",
35
+ "helmet": "^8.1.0"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@types/cors": "^2.8.19",
38
- "typescript": "^5.9.3",
39
- "rimraf": "^5.0.5"
39
+ "rimraf": "^5.0.5",
40
+ "typescript": "^5.9.3"
40
41
  },
41
42
  "scripts": {
42
43
  "build": "pnpm run build:types && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",