@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
@@ -1,348 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLoggingMiddleware = createLoggingMiddleware;
4
- exports.createErrorHandler = createErrorHandler;
5
- exports.createRequestIdMiddleware = createRequestIdMiddleware;
6
- exports.createValidationMiddleware = createValidationMiddleware;
7
- exports.createRateLimitMiddleware = createRateLimitMiddleware;
8
- exports.createAuthMiddleware = createAuthMiddleware;
9
- exports.withLogging = withLogging;
10
- exports.withErrorHandler = withErrorHandler;
11
- exports.withRequestId = withRequestId;
12
- exports.withValidation = withValidation;
13
- exports.withRateLimit = withRateLimit;
14
- exports.withAuth = withAuth;
15
- exports.validateFields = validateFields;
16
- exports.rateLimit = rateLimit;
17
- exports.requireAuth = requireAuth;
18
- exports.cacheResponse = cacheResponse;
19
- exports.useSession = useSession;
20
- // Logging middleware
21
- function createLoggingMiddleware(format = 'simple') {
22
- return (req, res, next) => {
23
- const start = Date.now();
24
- res.on('finish', () => {
25
- const duration = Date.now() - start;
26
- if (format === 'detailed') {
27
- console.log(`${req.method} ${req.url} - ${res.statusCode} - ${duration}ms - ${req.ip}`);
28
- }
29
- else {
30
- console.log(`${req.method} ${req.url} - ${res.statusCode}`);
31
- }
32
- });
33
- next();
34
- };
35
- }
36
- // Error handling middleware
37
- function createErrorHandler() {
38
- return (err, req, res, next) => {
39
- console.error('Error:', err);
40
- if (res.headersSent) {
41
- return next(err);
42
- }
43
- // Type guard for error objects
44
- const errorObj = err;
45
- const status = errorObj.status || errorObj.statusCode || 500;
46
- const message = process.env.NODE_ENV === 'production'
47
- ? 'Internal Server Error'
48
- : errorObj.message || 'Unknown error';
49
- res.status(status).json({
50
- success: false,
51
- message,
52
- data: undefined,
53
- error: {
54
- message,
55
- ...(process.env.NODE_ENV !== 'production' && { details: { stack: errorObj.stack } })
56
- },
57
- meta: null
58
- });
59
- };
60
- }
61
- // Request ID middleware
62
- function createRequestIdMiddleware() {
63
- return (req, res, next) => {
64
- const requestId = Math.random().toString(36).substring(2, 15);
65
- req.requestId = requestId;
66
- res.setHeader('X-Request-ID', requestId);
67
- next();
68
- };
69
- }
70
- function createValidationMiddleware(rules) {
71
- return (req, res, next) => {
72
- const errors = [];
73
- for (const rule of rules) {
74
- const value = req.body[rule.field];
75
- if (rule.required && (value === undefined || value === null || value === '')) {
76
- errors.push(`${rule.field} is required`);
77
- continue;
78
- }
79
- if (value === undefined || value === null)
80
- continue;
81
- if (rule.type) {
82
- switch (rule.type) {
83
- case 'email':
84
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
85
- if (!emailRegex.test(value)) {
86
- errors.push(`${rule.field} must be a valid email`);
87
- }
88
- break;
89
- case 'string':
90
- if (typeof value !== 'string') {
91
- errors.push(`${rule.field} must be a string`);
92
- }
93
- break;
94
- case 'number':
95
- if (typeof value !== 'number' && isNaN(Number(value))) {
96
- errors.push(`${rule.field} must be a number`);
97
- }
98
- break;
99
- case 'boolean':
100
- if (typeof value !== 'boolean') {
101
- errors.push(`${rule.field} must be a boolean`);
102
- }
103
- break;
104
- }
105
- }
106
- if (rule.minLength && value.length < rule.minLength) {
107
- errors.push(`${rule.field} must be at least ${rule.minLength} characters`);
108
- }
109
- if (rule.maxLength && value.length > rule.maxLength) {
110
- errors.push(`${rule.field} must be no more than ${rule.maxLength} characters`);
111
- }
112
- if (rule.pattern && !rule.pattern.test(value)) {
113
- errors.push(`${rule.field} format is invalid`);
114
- }
115
- if (rule.custom) {
116
- const result = rule.custom(value);
117
- if (result !== true) {
118
- errors.push(typeof result === 'string' ? result : `${rule.field} is invalid`);
119
- }
120
- }
121
- }
122
- if (errors.length > 0) {
123
- return res.status(400).json({
124
- success: false,
125
- message: 'Validation failed',
126
- data: undefined,
127
- error: {
128
- message: 'Validation failed',
129
- details: errors
130
- },
131
- meta: null
132
- });
133
- }
134
- next();
135
- };
136
- }
137
- const rateLimitStore = new Map();
138
- function createRateLimitMiddleware(config = {}) {
139
- const { windowMs = 15 * 60 * 1000, maxRequests = 100, message = 'Too many requests, please try again later', keyGenerator = (req) => req.ip || 'unknown' } = config;
140
- return (req, res, next) => {
141
- const key = keyGenerator(req);
142
- const now = Date.now();
143
- const record = rateLimitStore.get(key);
144
- if (!record || now > record.resetTime) {
145
- rateLimitStore.set(key, {
146
- count: 1,
147
- resetTime: now + windowMs
148
- });
149
- return next();
150
- }
151
- if (record.count >= maxRequests) {
152
- return res.status(429).json({
153
- success: false,
154
- message,
155
- data: undefined,
156
- error: {
157
- message,
158
- details: {
159
- retryAfter: Math.ceil((record.resetTime - now) / 1000)
160
- }
161
- },
162
- meta: null
163
- });
164
- }
165
- record.count++;
166
- next();
167
- };
168
- }
169
- function createAuthMiddleware(config) {
170
- const { tokenExtractor = (req) => {
171
- const authHeader = req.headers.authorization;
172
- if (authHeader && authHeader.startsWith('Bearer ')) {
173
- return authHeader.substring(7);
174
- }
175
- return req.cookies?.token || null;
176
- }, tokenValidator = () => { throw new Error('Token validator not implemented'); }, unauthorizedMessage = 'Unauthorized access' } = config;
177
- return async (req, res, next) => {
178
- try {
179
- const token = tokenExtractor(req);
180
- if (!token) {
181
- return res.status(401).json({
182
- success: false,
183
- message: unauthorizedMessage,
184
- data: undefined,
185
- error: {
186
- message: unauthorizedMessage
187
- },
188
- meta: null
189
- });
190
- }
191
- const user = await tokenValidator(token);
192
- req.user = user;
193
- next();
194
- }
195
- catch (error) {
196
- return res.status(401).json({
197
- success: false,
198
- message: unauthorizedMessage,
199
- data: undefined,
200
- error: {
201
- message: unauthorizedMessage
202
- },
203
- meta: null
204
- });
205
- }
206
- };
207
- }
208
- // Plugin versions
209
- function withLogging(format = 'simple') {
210
- return (app) => {
211
- app.use(createLoggingMiddleware(format));
212
- };
213
- }
214
- function withErrorHandler() {
215
- return (app) => {
216
- app.use(createErrorHandler());
217
- };
218
- }
219
- function withRequestId() {
220
- return (app) => {
221
- app.use(createRequestIdMiddleware());
222
- };
223
- }
224
- function withValidation(rules) {
225
- return (app) => {
226
- app.use(createValidationMiddleware(rules));
227
- };
228
- }
229
- function withRateLimit(config = {}) {
230
- return (app) => {
231
- app.use(createRateLimitMiddleware(config));
232
- };
233
- }
234
- function withAuth(config) {
235
- return (app) => {
236
- app.use(createAuthMiddleware(config));
237
- };
238
- }
239
- // Convenience functions for route-specific middleware
240
- function validateFields(rules) {
241
- return createValidationMiddleware(rules);
242
- }
243
- function rateLimit(config = {}) {
244
- return createRateLimitMiddleware(config);
245
- }
246
- function requireAuth(config) {
247
- return createAuthMiddleware(config);
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
- }
@@ -1,5 +0,0 @@
1
- import express from 'express';
2
- import { HealthCheckConfig, ServerPlugin } from './types';
3
- export declare function createHealthCheck(config?: HealthCheckConfig): express.RequestHandler;
4
- export declare function withHealthCheck(path?: string, config?: HealthCheckConfig): ServerPlugin;
5
- export declare function addHealthCheck(app: express.Application, path?: string, config?: HealthCheckConfig): void;
@@ -1,39 +0,0 @@
1
- import express from 'express';
2
- import { ServerPlugin } from './types';
3
- export declare function createLoggingMiddleware(format?: 'simple' | 'detailed'): express.RequestHandler;
4
- export declare function createErrorHandler(): express.ErrorRequestHandler;
5
- export declare function createRequestIdMiddleware(): express.RequestHandler;
6
- export interface ValidationRule {
7
- field: string;
8
- required?: boolean;
9
- type?: 'string' | 'number' | 'email' | 'boolean';
10
- minLength?: number;
11
- maxLength?: number;
12
- pattern?: RegExp;
13
- custom?: (value: unknown) => boolean | string;
14
- }
15
- export declare function createValidationMiddleware(rules: ValidationRule[]): express.RequestHandler;
16
- export interface RateLimitConfig {
17
- windowMs?: number;
18
- maxRequests?: number;
19
- message?: string;
20
- keyGenerator?: (req: express.Request) => string;
21
- }
22
- export declare function createRateLimitMiddleware(config?: RateLimitConfig): express.RequestHandler;
23
- export interface AuthConfig {
24
- tokenExtractor?: (req: express.Request) => string | null;
25
- tokenValidator?: (token: string) => Promise<unknown> | unknown;
26
- unauthorizedMessage?: string;
27
- }
28
- export declare function createAuthMiddleware(config: AuthConfig): express.RequestHandler;
29
- export declare function withLogging(format?: 'simple' | 'detailed'): ServerPlugin;
30
- export declare function withErrorHandler(): ServerPlugin;
31
- export declare function withRequestId(): ServerPlugin;
32
- export declare function withValidation(rules: ValidationRule[]): ServerPlugin;
33
- export declare function withRateLimit(config?: RateLimitConfig): ServerPlugin;
34
- export declare function withAuth(config: AuthConfig): ServerPlugin;
35
- export declare function validateFields(rules: ValidationRule[]): express.RequestHandler;
36
- export declare function rateLimit(config?: RateLimitConfig): express.RequestHandler;
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;