@naman_deep_singh/server-utils 1.3.0 → 1.4.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 (95) hide show
  1. package/README.md +19 -5
  2. package/dist/cjs/core/health.d.ts +5 -0
  3. package/dist/cjs/{periodic-health.d.ts → core/periodic-health.d.ts} +1 -1
  4. package/dist/{types → cjs/core}/server.d.ts +4 -4
  5. package/dist/cjs/{server.js → core/server.js} +40 -7
  6. package/dist/cjs/{shutdown.d.ts → core/shutdown.d.ts} +1 -1
  7. package/dist/cjs/index.d.ts +11 -11
  8. package/dist/cjs/index.js +10 -10
  9. package/dist/cjs/middleware/auth.middleware.d.ts +7 -0
  10. package/dist/cjs/middleware/auth.middleware.js +41 -0
  11. package/dist/cjs/middleware/cache.middleware.d.ts +2 -0
  12. package/dist/cjs/middleware/cache.middleware.js +56 -0
  13. package/dist/cjs/middleware/errorHandler.middleware.d.ts +2 -0
  14. package/dist/cjs/middleware/errorHandler.middleware.js +28 -0
  15. package/dist/cjs/middleware/index.d.ts +10 -0
  16. package/dist/cjs/middleware/index.js +40 -0
  17. package/dist/cjs/middleware/logging.middleware.d.ts +2 -0
  18. package/dist/cjs/middleware/logging.middleware.js +19 -0
  19. package/dist/cjs/middleware/plugins.middleware.d.ts +14 -0
  20. package/dist/cjs/middleware/plugins.middleware.js +58 -0
  21. package/dist/cjs/middleware/rateLimiter.middleware.d.ts +8 -0
  22. package/dist/cjs/middleware/rateLimiter.middleware.js +35 -0
  23. package/dist/cjs/middleware/requestId.middleware.d.ts +2 -0
  24. package/dist/cjs/middleware/requestId.middleware.js +12 -0
  25. package/dist/cjs/middleware/session.middleware.d.ts +2 -0
  26. package/dist/cjs/middleware/session.middleware.js +50 -0
  27. package/dist/cjs/middleware/validation.middleware.d.ts +11 -0
  28. package/dist/cjs/middleware/validation.middleware.js +66 -0
  29. package/dist/esm/core/health.d.ts +5 -0
  30. package/dist/esm/{periodic-health.d.ts → core/periodic-health.d.ts} +1 -1
  31. package/dist/esm/{server.d.ts → core/server.d.ts} +4 -4
  32. package/dist/esm/{server.js → core/server.js} +7 -7
  33. package/dist/esm/{shutdown.d.ts → core/shutdown.d.ts} +1 -1
  34. package/dist/esm/index.d.ts +11 -11
  35. package/dist/esm/index.js +10 -10
  36. package/dist/esm/middleware/auth.middleware.d.ts +7 -0
  37. package/dist/esm/middleware/auth.middleware.js +38 -0
  38. package/dist/esm/middleware/cache.middleware.d.ts +2 -0
  39. package/dist/esm/middleware/cache.middleware.js +53 -0
  40. package/dist/esm/middleware/errorHandler.middleware.d.ts +2 -0
  41. package/dist/esm/middleware/errorHandler.middleware.js +25 -0
  42. package/dist/esm/middleware/index.d.ts +10 -0
  43. package/dist/esm/middleware/index.js +20 -0
  44. package/dist/esm/middleware/logging.middleware.d.ts +2 -0
  45. package/dist/esm/middleware/logging.middleware.js +16 -0
  46. package/dist/esm/middleware/plugins.middleware.d.ts +14 -0
  47. package/dist/esm/middleware/plugins.middleware.js +47 -0
  48. package/dist/esm/middleware/rateLimiter.middleware.d.ts +8 -0
  49. package/dist/esm/middleware/rateLimiter.middleware.js +32 -0
  50. package/dist/esm/middleware/requestId.middleware.d.ts +2 -0
  51. package/dist/esm/middleware/requestId.middleware.js +9 -0
  52. package/dist/esm/middleware/session.middleware.d.ts +2 -0
  53. package/dist/esm/middleware/session.middleware.js +47 -0
  54. package/dist/esm/middleware/validation.middleware.d.ts +11 -0
  55. package/dist/esm/middleware/validation.middleware.js +63 -0
  56. package/dist/types/core/health.d.ts +5 -0
  57. package/dist/types/{periodic-health.d.ts → core/periodic-health.d.ts} +1 -1
  58. package/dist/{cjs → types/core}/server.d.ts +4 -4
  59. package/dist/types/{shutdown.d.ts → core/shutdown.d.ts} +1 -1
  60. package/dist/types/index.d.ts +11 -11
  61. package/dist/types/middleware/auth.middleware.d.ts +7 -0
  62. package/dist/types/middleware/cache.middleware.d.ts +2 -0
  63. package/dist/types/middleware/errorHandler.middleware.d.ts +2 -0
  64. package/dist/types/middleware/index.d.ts +10 -0
  65. package/dist/types/middleware/logging.middleware.d.ts +2 -0
  66. package/dist/types/middleware/plugins.middleware.d.ts +14 -0
  67. package/dist/types/middleware/rateLimiter.middleware.d.ts +8 -0
  68. package/dist/types/middleware/requestId.middleware.d.ts +2 -0
  69. package/dist/types/middleware/session.middleware.d.ts +2 -0
  70. package/dist/types/middleware/validation.middleware.d.ts +11 -0
  71. package/package.json +3 -1
  72. package/dist/cjs/health.d.ts +0 -5
  73. package/dist/cjs/middleware.d.ts +0 -39
  74. package/dist/cjs/middleware.js +0 -348
  75. package/dist/esm/health.d.ts +0 -5
  76. package/dist/esm/middleware.d.ts +0 -39
  77. package/dist/esm/middleware.js +0 -329
  78. package/dist/types/health.d.ts +0 -5
  79. package/dist/types/middleware.d.ts +0 -39
  80. /package/dist/cjs/{health.js → core/health.js} +0 -0
  81. /package/dist/cjs/{periodic-health.js → core/periodic-health.js} +0 -0
  82. /package/dist/cjs/{shutdown.js → core/shutdown.js} +0 -0
  83. /package/dist/cjs/{types.d.ts → types/index.d.ts} +0 -0
  84. /package/dist/cjs/{types.js → types/index.js} +0 -0
  85. /package/dist/cjs/{utils.d.ts → utils/utils.d.ts} +0 -0
  86. /package/dist/cjs/{utils.js → utils/utils.js} +0 -0
  87. /package/dist/esm/{health.js → core/health.js} +0 -0
  88. /package/dist/esm/{periodic-health.js → core/periodic-health.js} +0 -0
  89. /package/dist/esm/{shutdown.js → core/shutdown.js} +0 -0
  90. /package/dist/esm/{types.d.ts → types/index.d.ts} +0 -0
  91. /package/dist/esm/{types.js → types/index.js} +0 -0
  92. /package/dist/esm/{utils.d.ts → utils/utils.d.ts} +0 -0
  93. /package/dist/esm/{utils.js → utils/utils.js} +0 -0
  94. /package/dist/types/{types.d.ts → types/index.d.ts} +0 -0
  95. /package/dist/types/{utils.d.ts → utils/utils.d.ts} +0 -0
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSession = useSession;
4
+ // Session middleware helper (attaches sessionStore and helpers to req)
5
+ function useSession(cookieName) {
6
+ return async (req, res, next) => {
7
+ try {
8
+ const store = req.app.locals.sessionStore;
9
+ if (!store)
10
+ return next();
11
+ const name = cookieName || req.app.locals.sessionCookieName || 'sid';
12
+ let sid = req.cookies?.[name];
13
+ if (!sid) {
14
+ const cookieHeader = req.headers.cookie;
15
+ if (cookieHeader) {
16
+ const match = cookieHeader.split(';').map(s => s.trim()).find(s => s.startsWith(name + '='));
17
+ if (match)
18
+ sid = match.split('=')[1];
19
+ }
20
+ }
21
+ req.sessionId = sid;
22
+ req.sessionStore = store;
23
+ req.getSession = async () => {
24
+ if (!sid)
25
+ return null;
26
+ try {
27
+ return await store.get(sid);
28
+ }
29
+ catch (err) {
30
+ console.error(`[Session] Failed to get session "${sid}":`, err);
31
+ throw err;
32
+ }
33
+ };
34
+ req.createSession = async (id, data, ttl) => {
35
+ try {
36
+ return await store.create(id, data, ttl);
37
+ }
38
+ catch (err) {
39
+ console.error(`[Session] Failed to create session "${id}":`, err);
40
+ throw err;
41
+ }
42
+ };
43
+ next();
44
+ }
45
+ catch (err) {
46
+ console.error('[Session] Unexpected error in useSession middleware:', err);
47
+ next();
48
+ }
49
+ };
50
+ }
@@ -0,0 +1,11 @@
1
+ import { RequestHandler } from "node_modules/@types/express";
2
+ export interface ValidationRule {
3
+ field: string;
4
+ required?: boolean;
5
+ type?: 'string' | 'number' | 'email' | 'boolean';
6
+ minLength?: number;
7
+ maxLength?: number;
8
+ pattern?: RegExp;
9
+ custom?: (value: unknown) => boolean | string;
10
+ }
11
+ export declare function createValidationMiddleware(rules: ValidationRule[]): RequestHandler;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createValidationMiddleware = createValidationMiddleware;
4
+ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
5
+ function createValidationMiddleware(rules) {
6
+ return (req, res, next) => {
7
+ const errors = [];
8
+ for (const rule of rules) {
9
+ const value = req.body[rule.field];
10
+ if (rule.required && (value === undefined || value === null || value === '')) {
11
+ errors.push(`${rule.field} is required`);
12
+ continue;
13
+ }
14
+ if (value === undefined || value === null)
15
+ continue;
16
+ if (rule.type) {
17
+ switch (rule.type) {
18
+ case 'email':
19
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
20
+ if (!emailRegex.test(value)) {
21
+ errors.push(`${rule.field} must be a valid email`);
22
+ }
23
+ break;
24
+ case 'string':
25
+ if (typeof value !== 'string') {
26
+ errors.push(`${rule.field} must be a string`);
27
+ }
28
+ break;
29
+ case 'number':
30
+ if (typeof value !== 'number' && isNaN(Number(value))) {
31
+ errors.push(`${rule.field} must be a number`);
32
+ }
33
+ break;
34
+ case 'boolean':
35
+ if (typeof value !== 'boolean') {
36
+ errors.push(`${rule.field} must be a boolean`);
37
+ }
38
+ break;
39
+ }
40
+ }
41
+ if (rule.minLength && value.length < rule.minLength) {
42
+ errors.push(`${rule.field} must be at least ${rule.minLength} characters`);
43
+ }
44
+ if (rule.maxLength && value.length > rule.maxLength) {
45
+ errors.push(`${rule.field} must be no more than ${rule.maxLength} characters`);
46
+ }
47
+ if (rule.pattern && !rule.pattern.test(value)) {
48
+ errors.push(`${rule.field} format is invalid`);
49
+ }
50
+ if (rule.custom) {
51
+ const result = rule.custom(value);
52
+ if (result !== true) {
53
+ errors.push(typeof result === 'string' ? result : `${rule.field} is invalid`);
54
+ }
55
+ }
56
+ }
57
+ if (errors.length > 0) {
58
+ // Use ValidationError from errors-utils and let error middleware handle response
59
+ const validationError = new errors_utils_1.ValidationError('Validation failed', {
60
+ validationErrors: errors
61
+ });
62
+ return next(validationError);
63
+ }
64
+ next();
65
+ };
66
+ }
@@ -0,0 +1,5 @@
1
+ import { Application, RequestHandler } from 'express';
2
+ import { HealthCheckConfig, ServerPlugin } from '../types';
3
+ export declare function createHealthCheck(config?: HealthCheckConfig): RequestHandler;
4
+ export declare function withHealthCheck(path?: string, config?: HealthCheckConfig): ServerPlugin;
5
+ export declare function addHealthCheck(app: Application, path?: string, config?: HealthCheckConfig): void;
@@ -1,4 +1,4 @@
1
- import { PeriodicHealthCheckConfig } from './types';
1
+ import { PeriodicHealthCheckConfig } from '../types';
2
2
  export declare class PeriodicHealthMonitor {
3
3
  private intervals;
4
4
  private config;
@@ -1,6 +1,6 @@
1
- import express from 'express';
2
1
  import { Server } from 'http';
3
- import { ServerConfig, SocketIOConfig } from './types';
2
+ import { Application } from 'express';
3
+ import { ServerConfig, SocketIOConfig } from '../types';
4
4
  export interface GrpcService {
5
5
  service: Record<string, unknown>;
6
6
  implementation: Record<string, (...args: unknown[]) => unknown>;
@@ -26,7 +26,7 @@ export interface ServerInstanceConfig extends Required<Omit<ServerConfig, 'socke
26
26
  socketIO?: SocketIOConfig;
27
27
  }
28
28
  export interface ServerInstance {
29
- app: express.Application;
29
+ app: Application;
30
30
  server?: Server;
31
31
  config: ServerInstanceConfig;
32
32
  start(): Promise<ServerInstance>;
@@ -46,7 +46,7 @@ export interface ServerInfo {
46
46
  startTime: Date;
47
47
  }
48
48
  export declare class ExpressServer implements ServerInstance {
49
- app: express.Application;
49
+ app: Application;
50
50
  server?: Server;
51
51
  config: ServerInstanceConfig;
52
52
  cache?: import('@naman_deep_singh/cache').ICache<unknown>;
@@ -1,8 +1,8 @@
1
- import express from 'express';
2
- import { createGracefulShutdown } from './shutdown';
3
- import { PeriodicHealthMonitor } from './periodic-health';
4
- import crypto from 'crypto';
1
+ import express, { json, raw } from 'express';
5
2
  import { CacheFactory, SessionStore } from '@naman_deep_singh/cache';
3
+ import crypto from 'crypto';
4
+ import { PeriodicHealthMonitor } from './periodic-health';
5
+ import { createGracefulShutdown } from './shutdown';
6
6
  export class ExpressServer {
7
7
  constructor(name = 'Express Server', version = '1.0.0', config = {}) {
8
8
  this.status = 'stopped';
@@ -59,7 +59,7 @@ export class ExpressServer {
59
59
  }
60
60
  // Apply JSON parser if enabled
61
61
  if (this.config.json) {
62
- this.app.use(express.json());
62
+ this.app.use(json());
63
63
  }
64
64
  // Apply cookie parser if enabled
65
65
  if (this.config.cookieParser) {
@@ -162,7 +162,7 @@ export class ExpressServer {
162
162
  // attach session middleware globally so req.sessionStore is available
163
163
  try {
164
164
  // eslint-disable-next-line @typescript-eslint/no-var-requires
165
- const { useSession } = require('./middleware');
165
+ const { useSession } = require('../middleware/middleware');
166
166
  this.app.use(useSession(cookieName));
167
167
  console.log(`✅ [${serverName}] Session middleware enabled (cookie: ${cookieName}, TTL: ${ttl}s)`);
168
168
  }
@@ -306,7 +306,7 @@ export class ExpressServer {
306
306
  }
307
307
  }
308
308
  addWebhook(config) {
309
- this.app.post(config.path, express.raw({ type: 'application/json' }), async (req, res) => {
309
+ this.app.post(config.path, raw({ type: 'application/json' }), async (req, res) => {
310
310
  try {
311
311
  // Verify signature if secret provided
312
312
  if (config.secret) {
@@ -1,5 +1,5 @@
1
1
  import { Server } from 'http';
2
- import { GracefulShutdownConfig, ServerPlugin } from './types';
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
5
  export declare function startServerWithShutdown(app: import('express').Application, port: number, shutdownConfig?: GracefulShutdownConfig, serverName?: string, serverVersion?: string): Server;
@@ -1,19 +1,19 @@
1
- export { ExpressServer, createServer } from './server';
2
- export type { ServerInstance, ServerInfo, GrpcService, RpcMethod, WebhookConfig } from './server';
1
+ export { ExpressServer, createServer } from './core/server';
2
+ export type { ServerInstance, ServerInfo, GrpcService, RpcMethod, WebhookConfig } from './core/server';
3
3
  export { Request, Response, NextFunction, Router, Application } from 'express';
4
4
  export type { RequestHandler, ErrorRequestHandler } from 'express';
5
- export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
6
- export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
5
+ export { createHealthCheck, withHealthCheck, addHealthCheck } from './core/health';
6
+ export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
7
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
- export { getEnv, getEnvNumber, getEnvBoolean } from './utils';
9
- export { PeriodicHealthMonitor } from './periodic-health';
8
+ export { getEnv, getEnvNumber, getEnvBoolean } from './utils/utils';
9
+ export { PeriodicHealthMonitor } from './core/periodic-health';
10
10
  export type { ServerConfig, HealthCheckConfig, HealthCheck, GracefulShutdownConfig, ServerPlugin, SocketIOConfig, SocketInstance, PeriodicHealthCheckConfig, HealthCheckService } from './types';
11
- import { ExpressServer, createServer } from './server';
12
- import { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
13
- import { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
11
+ import { ExpressServer, createServer } from './core/server';
12
+ import { createHealthCheck, withHealthCheck, addHealthCheck } from './core/health';
13
+ import { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
14
14
  import { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth } from './middleware';
15
- import { getEnv, getEnvNumber, getEnvBoolean } from './utils';
16
- import { PeriodicHealthMonitor } from './periodic-health';
15
+ import { getEnv, getEnvNumber, getEnvBoolean } from './utils/utils';
16
+ import { PeriodicHealthMonitor } from './core/periodic-health';
17
17
  declare const ServerUtils: {
18
18
  createServer: typeof createServer;
19
19
  ExpressServer: typeof ExpressServer;
package/dist/esm/index.js CHANGED
@@ -1,24 +1,24 @@
1
1
  // Core server utilities
2
- export { ExpressServer, createServer } from './server';
2
+ export { ExpressServer, createServer } from './core/server';
3
3
  // Express re-exports (to avoid direct Express dependency in services)
4
4
  export { Router } from 'express';
5
5
  // Health check utilities
6
- export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
6
+ export { createHealthCheck, withHealthCheck, addHealthCheck } from './core/health';
7
7
  // Graceful shutdown utilities
8
- export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
8
+ export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
9
9
  // Middleware utilities
10
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
- export { getEnv, getEnvNumber, getEnvBoolean } from './utils';
12
+ export { getEnv, getEnvNumber, getEnvBoolean } from './utils/utils';
13
13
  // Periodic health monitoring
14
- export { PeriodicHealthMonitor } from './periodic-health';
14
+ export { PeriodicHealthMonitor } from './core/periodic-health';
15
15
  // Import all exports for default export
16
- import { ExpressServer, createServer } from './server';
17
- import { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
18
- import { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
16
+ import { ExpressServer, createServer } from './core/server';
17
+ import { createHealthCheck, withHealthCheck, addHealthCheck } from './core/health';
18
+ import { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
19
19
  import { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth } from './middleware';
20
- import { getEnv, getEnvNumber, getEnvBoolean } from './utils';
21
- import { PeriodicHealthMonitor } from './periodic-health';
20
+ import { getEnv, getEnvNumber, getEnvBoolean } from './utils/utils';
21
+ import { PeriodicHealthMonitor } from './core/periodic-health';
22
22
  // Default export for namespace usage
23
23
  const ServerUtils = {
24
24
  // Server creation
@@ -0,0 +1,7 @@
1
+ import { Request, RequestHandler } from "node_modules/@types/express";
2
+ export interface AuthConfig {
3
+ secret: string;
4
+ unauthorizedMessage?: string;
5
+ tokenExtractor?: (req: Request) => string | null;
6
+ }
7
+ export declare function createAuthMiddleware(config: AuthConfig): RequestHandler;
@@ -0,0 +1,38 @@
1
+ import { extractToken, safeVerifyToken } from "@naman_deep_singh/security";
2
+ import { UnauthorizedError } from "@naman_deep_singh/errors-utils";
3
+ export function createAuthMiddleware(config) {
4
+ const { secret, unauthorizedMessage = 'Unauthorized access', tokenExtractor = (req) => extractToken({
5
+ header: req.headers.authorization || undefined,
6
+ cookies: req.cookies,
7
+ query: req.query,
8
+ body: req.body
9
+ }) } = config;
10
+ return async (req, res, next) => {
11
+ try {
12
+ // Extract token from request
13
+ const token = tokenExtractor(req);
14
+ if (!token) {
15
+ const error = new UnauthorizedError(unauthorizedMessage, {
16
+ reason: 'No token provided'
17
+ });
18
+ return next(error);
19
+ }
20
+ // Use safe verify token from security package
21
+ const result = safeVerifyToken(token, secret);
22
+ if (!result.valid) {
23
+ const error = new UnauthorizedError(unauthorizedMessage, {
24
+ reason: 'Invalid or expired token',
25
+ originalError: result.error?.message
26
+ });
27
+ return next(error);
28
+ }
29
+ // Attach the verified payload as user
30
+ req.user = result.payload;
31
+ next();
32
+ }
33
+ catch (error) {
34
+ const unauthorizedError = new UnauthorizedError(unauthorizedMessage, error instanceof Error ? { originalError: error.message } : error);
35
+ return next(unauthorizedError);
36
+ }
37
+ };
38
+ }
@@ -0,0 +1,2 @@
1
+ import { RequestHandler } from "node_modules/@types/express";
2
+ export declare function cacheResponse(ttl?: number): RequestHandler;
@@ -0,0 +1,53 @@
1
+ // Cache response middleware (per-route opt-in)
2
+ export function cacheResponse(ttl) {
3
+ return async (req, res, next) => {
4
+ try {
5
+ if (req.method !== 'GET')
6
+ return next();
7
+ const cache = (req.cache ?? req.app.locals.cache);
8
+ const defaultTTL = req.app.locals.cacheDefaultTTL;
9
+ if (!cache || typeof cache.get !== 'function')
10
+ return next();
11
+ const key = `${req.originalUrl}`;
12
+ try {
13
+ const cached = await cache.get(key);
14
+ if (cached !== null && cached !== undefined) {
15
+ res.setHeader('X-Cache', 'HIT');
16
+ return res.json(cached);
17
+ }
18
+ }
19
+ catch (cacheErr) {
20
+ console.error(`[Cache] Failed to retrieve key "${key}":`, cacheErr);
21
+ // Continue without cache hit
22
+ }
23
+ const originalJson = res.json.bind(res);
24
+ res.json = (body) => {
25
+ try {
26
+ const expiry = ttl ?? defaultTTL;
27
+ if (expiry && cache && typeof cache.set === 'function') {
28
+ cache.set(key, body, expiry).catch((err) => {
29
+ console.error(`[Cache] Failed to set key "${key}" with TTL ${expiry}:`, err);
30
+ });
31
+ }
32
+ else if (cache) {
33
+ if (typeof cache.set === 'function') {
34
+ cache.set(key, body).catch((err) => {
35
+ console.error(`[Cache] Failed to set key "${key}":`, err);
36
+ });
37
+ }
38
+ }
39
+ }
40
+ catch (e) {
41
+ console.error(`[Cache] Error during cache.set operation:`, e);
42
+ }
43
+ res.setHeader('X-Cache', 'MISS');
44
+ return originalJson(body);
45
+ };
46
+ next();
47
+ }
48
+ catch (err) {
49
+ console.error('[Cache] Unexpected error in cacheResponse middleware:', err);
50
+ next();
51
+ }
52
+ };
53
+ }
@@ -0,0 +1,2 @@
1
+ import { ErrorRequestHandler } from "node_modules/@types/express";
2
+ export declare function createErrorHandler(): ErrorRequestHandler;
@@ -0,0 +1,25 @@
1
+ // Error handling middleware
2
+ export function createErrorHandler() {
3
+ return (err, req, res, next) => {
4
+ console.error('Error:', err);
5
+ if (res.headersSent) {
6
+ return next(err);
7
+ }
8
+ // Type guard for error objects
9
+ const errorObj = err;
10
+ const status = errorObj.status || errorObj.statusCode || 500;
11
+ const message = process.env.NODE_ENV === 'production'
12
+ ? 'Internal Server Error'
13
+ : errorObj.message || 'Unknown error';
14
+ res.status(status).json({
15
+ success: false,
16
+ message,
17
+ data: undefined,
18
+ error: {
19
+ message,
20
+ ...(process.env.NODE_ENV !== 'production' && { details: { stack: errorObj.stack } })
21
+ },
22
+ meta: null
23
+ });
24
+ };
25
+ }
@@ -0,0 +1,10 @@
1
+ export { AuthConfig, createAuthMiddleware } from './auth.middleware';
2
+ export { cacheResponse } from './cache.middleware';
3
+ export { createErrorHandler } from './errorHandler.middleware';
4
+ export { createLoggingMiddleware } from './logging.middleware';
5
+ export { RateLimitConfig, createRateLimitMiddleware } from './rateLimiter.middleware';
6
+ export { createRequestIdMiddleware } from './requestId.middleware';
7
+ export { useSession } from './session.middleware';
8
+ export { ValidationRule, createValidationMiddleware } from './validation.middleware';
9
+ export { withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth } from './plugins.middleware';
10
+ export { validateFields, rateLimit, requireAuth } from './plugins.middleware';
@@ -0,0 +1,20 @@
1
+ // Authentication Middleware
2
+ export { createAuthMiddleware } from './auth.middleware';
3
+ // Cache Middleware
4
+ export { cacheResponse } from './cache.middleware';
5
+ // Error Handler Middleware
6
+ export { createErrorHandler } from './errorHandler.middleware';
7
+ // Logging Middleware
8
+ export { createLoggingMiddleware } from './logging.middleware';
9
+ // Rate Limiter Middleware
10
+ export { createRateLimitMiddleware } from './rateLimiter.middleware';
11
+ // Request ID Middleware
12
+ export { createRequestIdMiddleware } from './requestId.middleware';
13
+ // Session Middleware
14
+ export { useSession } from './session.middleware';
15
+ // Validation Middleware
16
+ export { createValidationMiddleware } from './validation.middleware';
17
+ // Plugin middleware functions (for application-level middleware)
18
+ export { withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth } from './plugins.middleware';
19
+ // Convenience middleware functions (for route-level middleware)
20
+ export { validateFields, rateLimit, requireAuth } from './plugins.middleware';
@@ -0,0 +1,2 @@
1
+ import { RequestHandler } from "node_modules/@types/express";
2
+ export declare function createLoggingMiddleware(format?: 'simple' | 'detailed'): RequestHandler;
@@ -0,0 +1,16 @@
1
+ // Logging middleware
2
+ export function createLoggingMiddleware(format = 'simple') {
3
+ return (req, res, next) => {
4
+ const start = Date.now();
5
+ res.on('finish', () => {
6
+ const duration = Date.now() - start;
7
+ if (format === 'detailed') {
8
+ console.log(`${req.method} ${req.url} - ${res.statusCode} - ${duration}ms - ${req.ip}`);
9
+ }
10
+ else {
11
+ console.log(`${req.method} ${req.url} - ${res.statusCode}`);
12
+ }
13
+ });
14
+ next();
15
+ };
16
+ }
@@ -0,0 +1,14 @@
1
+ import { RequestHandler } from 'express';
2
+ import { ServerPlugin } from '../types';
3
+ import { ValidationRule } from './validation.middleware';
4
+ import { RateLimitConfig } from './rateLimiter.middleware';
5
+ import { AuthConfig } from './auth.middleware';
6
+ export declare function withLogging(format?: 'simple' | 'detailed'): ServerPlugin;
7
+ export declare function withErrorHandler(): ServerPlugin;
8
+ export declare function withRequestId(): ServerPlugin;
9
+ export declare function withValidation(rules: ValidationRule[]): ServerPlugin;
10
+ export declare function withRateLimit(config?: RateLimitConfig): ServerPlugin;
11
+ export declare function withAuth(config: AuthConfig): ServerPlugin;
12
+ export declare function validateFields(rules: ValidationRule[]): RequestHandler;
13
+ export declare function rateLimit(config?: RateLimitConfig): RequestHandler;
14
+ export declare function requireAuth(config: AuthConfig): RequestHandler;
@@ -0,0 +1,47 @@
1
+ import { createLoggingMiddleware } from './logging.middleware';
2
+ import { createErrorHandler } from './errorHandler.middleware';
3
+ import { createRequestIdMiddleware } from './requestId.middleware';
4
+ import { createValidationMiddleware } from './validation.middleware';
5
+ import { createRateLimitMiddleware } from './rateLimiter.middleware';
6
+ import { createAuthMiddleware } from './auth.middleware';
7
+ // Plugin versions
8
+ export function withLogging(format = 'simple') {
9
+ return (app) => {
10
+ app.use(createLoggingMiddleware(format));
11
+ };
12
+ }
13
+ export function withErrorHandler() {
14
+ return (app) => {
15
+ app.use(createErrorHandler());
16
+ };
17
+ }
18
+ export function withRequestId() {
19
+ return (app) => {
20
+ app.use(createRequestIdMiddleware());
21
+ };
22
+ }
23
+ export function withValidation(rules) {
24
+ return (app) => {
25
+ app.use(createValidationMiddleware(rules));
26
+ };
27
+ }
28
+ export function withRateLimit(config = {}) {
29
+ return (app) => {
30
+ app.use(createRateLimitMiddleware(config));
31
+ };
32
+ }
33
+ export function withAuth(config) {
34
+ return (app) => {
35
+ app.use(createAuthMiddleware(config));
36
+ };
37
+ }
38
+ // Convenience functions for route-specific middleware
39
+ export function validateFields(rules) {
40
+ return createValidationMiddleware(rules);
41
+ }
42
+ export function rateLimit(config = {}) {
43
+ return createRateLimitMiddleware(config);
44
+ }
45
+ export function requireAuth(config) {
46
+ return createAuthMiddleware(config);
47
+ }
@@ -0,0 +1,8 @@
1
+ import { Request, RequestHandler } from "node_modules/@types/express";
2
+ export interface RateLimitConfig {
3
+ windowMs?: number;
4
+ maxRequests?: number;
5
+ message?: string;
6
+ keyGenerator?: (req: Request) => string;
7
+ }
8
+ export declare function createRateLimitMiddleware(config?: RateLimitConfig): RequestHandler;
@@ -0,0 +1,32 @@
1
+ const rateLimitStore = new Map();
2
+ export function createRateLimitMiddleware(config = {}) {
3
+ const { windowMs = 15 * 60 * 1000, maxRequests = 100, message = 'Too many requests, please try again later', keyGenerator = (req) => req.ip || 'unknown' } = config;
4
+ return (req, res, next) => {
5
+ const key = keyGenerator(req);
6
+ const now = Date.now();
7
+ const record = rateLimitStore.get(key);
8
+ if (!record || now > record.resetTime) {
9
+ rateLimitStore.set(key, {
10
+ count: 1,
11
+ resetTime: now + windowMs
12
+ });
13
+ return next();
14
+ }
15
+ if (record.count >= maxRequests) {
16
+ return res.status(429).json({
17
+ success: false,
18
+ message,
19
+ data: undefined,
20
+ error: {
21
+ message,
22
+ details: {
23
+ retryAfter: Math.ceil((record.resetTime - now) / 1000)
24
+ }
25
+ },
26
+ meta: null
27
+ });
28
+ }
29
+ record.count++;
30
+ next();
31
+ };
32
+ }
@@ -0,0 +1,2 @@
1
+ import { RequestHandler } from "node_modules/@types/express";
2
+ export declare function createRequestIdMiddleware(): RequestHandler;
@@ -0,0 +1,9 @@
1
+ // Request ID middleware
2
+ export function createRequestIdMiddleware() {
3
+ return (req, res, next) => {
4
+ const requestId = Math.random().toString(36).substring(2, 15);
5
+ req.requestId = requestId;
6
+ res.setHeader('X-Request-ID', requestId);
7
+ next();
8
+ };
9
+ }
@@ -0,0 +1,2 @@
1
+ import { RequestHandler } from "node_modules/@types/express";
2
+ export declare function useSession(cookieName?: string): RequestHandler;