@naman_deep_singh/server-utils 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/core/health.d.ts +2 -2
- package/dist/cjs/core/health.js +4 -4
- package/dist/cjs/core/periodic-health.d.ts +1 -1
- package/dist/cjs/core/periodic-health.js +4 -4
- package/dist/cjs/core/server.d.ts +6 -5
- package/dist/cjs/core/server.js +34 -22
- package/dist/cjs/core/shutdown.d.ts +2 -2
- package/dist/cjs/core/shutdown.js +2 -1
- package/dist/cjs/index.d.ts +11 -11
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/middleware/auth.middleware.d.ts +1 -1
- package/dist/cjs/middleware/auth.middleware.js +5 -5
- package/dist/cjs/middleware/cache.middleware.d.ts +1 -1
- package/dist/cjs/middleware/cache.middleware.js +2 -0
- package/dist/cjs/middleware/errorHandler.middleware.d.ts +1 -1
- package/dist/cjs/middleware/errorHandler.middleware.js +4 -2
- package/dist/cjs/middleware/index.d.ts +4 -4
- package/dist/cjs/middleware/logging.middleware.d.ts +1 -1
- package/dist/cjs/middleware/plugins.middleware.d.ts +5 -5
- package/dist/cjs/middleware/plugins.middleware.js +3 -3
- package/dist/cjs/middleware/rateLimiter.middleware.d.ts +1 -1
- package/dist/cjs/middleware/rateLimiter.middleware.js +5 -5
- package/dist/cjs/middleware/requestId.middleware.d.ts +1 -1
- package/dist/cjs/middleware/session.middleware.d.ts +1 -1
- package/dist/cjs/middleware/session.middleware.js +4 -1
- package/dist/cjs/middleware/validation.middleware.d.ts +1 -1
- package/dist/cjs/middleware/validation.middleware.js +3 -2
- package/dist/cjs/types/index.d.ts +1 -1
- package/dist/cjs/utils/utils.js +2 -2
- package/dist/esm/core/health.d.ts +2 -2
- package/dist/esm/core/health.js +4 -4
- package/dist/esm/core/periodic-health.d.ts +1 -1
- package/dist/esm/core/periodic-health.js +4 -4
- package/dist/esm/core/server.d.ts +6 -5
- package/dist/esm/core/server.js +33 -21
- package/dist/esm/core/shutdown.d.ts +2 -2
- package/dist/esm/core/shutdown.js +2 -1
- package/dist/esm/index.d.ts +11 -11
- package/dist/esm/index.js +9 -9
- package/dist/esm/middleware/auth.middleware.d.ts +1 -1
- package/dist/esm/middleware/auth.middleware.js +6 -6
- package/dist/esm/middleware/cache.middleware.d.ts +1 -1
- package/dist/esm/middleware/cache.middleware.js +2 -0
- package/dist/esm/middleware/errorHandler.middleware.d.ts +1 -1
- package/dist/esm/middleware/errorHandler.middleware.js +4 -2
- package/dist/esm/middleware/index.d.ts +4 -4
- package/dist/esm/middleware/index.js +4 -4
- package/dist/esm/middleware/logging.middleware.d.ts +1 -1
- package/dist/esm/middleware/plugins.middleware.d.ts +5 -5
- package/dist/esm/middleware/plugins.middleware.js +3 -3
- package/dist/esm/middleware/rateLimiter.middleware.d.ts +1 -1
- package/dist/esm/middleware/rateLimiter.middleware.js +5 -5
- package/dist/esm/middleware/requestId.middleware.d.ts +1 -1
- package/dist/esm/middleware/session.middleware.d.ts +1 -1
- package/dist/esm/middleware/session.middleware.js +4 -1
- package/dist/esm/middleware/validation.middleware.d.ts +1 -1
- package/dist/esm/middleware/validation.middleware.js +4 -3
- package/dist/esm/types/index.d.ts +1 -1
- package/dist/esm/utils/utils.js +2 -2
- package/dist/types/core/health.d.ts +2 -2
- package/dist/types/core/periodic-health.d.ts +1 -1
- package/dist/types/core/server.d.ts +6 -5
- package/dist/types/core/shutdown.d.ts +2 -2
- package/dist/types/index.d.ts +11 -11
- package/dist/types/middleware/auth.middleware.d.ts +1 -1
- package/dist/types/middleware/cache.middleware.d.ts +1 -1
- package/dist/types/middleware/errorHandler.middleware.d.ts +1 -1
- package/dist/types/middleware/index.d.ts +4 -4
- package/dist/types/middleware/logging.middleware.d.ts +1 -1
- package/dist/types/middleware/plugins.middleware.d.ts +5 -5
- package/dist/types/middleware/rateLimiter.middleware.d.ts +1 -1
- package/dist/types/middleware/requestId.middleware.d.ts +1 -1
- package/dist/types/middleware/session.middleware.d.ts +1 -1
- package/dist/types/middleware/validation.middleware.d.ts +1 -1
- package/dist/types/types/index.d.ts +1 -1
- package/package.json +4 -4
package/dist/esm/core/health.js
CHANGED
|
@@ -4,7 +4,7 @@ export function createHealthCheck(config = {}) {
|
|
|
4
4
|
try {
|
|
5
5
|
const checks = {
|
|
6
6
|
server: true,
|
|
7
|
-
timestamp: Date.now()
|
|
7
|
+
timestamp: Date.now(),
|
|
8
8
|
};
|
|
9
9
|
// Run custom health checks
|
|
10
10
|
for (const check of customChecks) {
|
|
@@ -15,16 +15,16 @@ export function createHealthCheck(config = {}) {
|
|
|
15
15
|
checks[check.name] = false;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
const isHealthy = Object.values(checks).every(status => status === true || typeof status === 'number');
|
|
18
|
+
const isHealthy = Object.values(checks).every((status) => status === true || typeof status === 'number');
|
|
19
19
|
res.status(isHealthy ? 200 : 503).json({
|
|
20
20
|
status: isHealthy ? 'healthy' : 'unhealthy',
|
|
21
|
-
checks
|
|
21
|
+
checks,
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
catch (error) {
|
|
25
25
|
res.status(503).json({
|
|
26
26
|
status: 'unhealthy',
|
|
27
|
-
error: 'Health check failed'
|
|
27
|
+
error: 'Health check failed',
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
};
|
|
@@ -9,7 +9,7 @@ export class PeriodicHealthMonitor {
|
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
const interval = this.config.interval || 30000;
|
|
12
|
-
this.config.services.forEach(service => {
|
|
12
|
+
this.config.services.forEach((service) => {
|
|
13
13
|
const intervalId = setInterval(async () => {
|
|
14
14
|
await this.checkServiceHealth(service);
|
|
15
15
|
}, interval);
|
|
@@ -18,7 +18,7 @@ export class PeriodicHealthMonitor {
|
|
|
18
18
|
console.log(`📊 ${this.serviceName}: Periodic health monitoring enabled (${interval}ms interval) for ${this.config.services.length} service(s)`);
|
|
19
19
|
}
|
|
20
20
|
stop() {
|
|
21
|
-
this.intervals.forEach(interval => clearInterval(interval));
|
|
21
|
+
this.intervals.forEach((interval) => clearInterval(interval));
|
|
22
22
|
this.intervals = [];
|
|
23
23
|
console.log(`🛑 ${this.serviceName}: Periodic health monitoring stopped`);
|
|
24
24
|
}
|
|
@@ -31,8 +31,8 @@ export class PeriodicHealthMonitor {
|
|
|
31
31
|
method: 'GET',
|
|
32
32
|
signal: controller.signal,
|
|
33
33
|
headers: {
|
|
34
|
-
'User-Agent': `${this.serviceName}-health-monitor
|
|
35
|
-
}
|
|
34
|
+
'User-Agent': `${this.serviceName}-health-monitor`,
|
|
35
|
+
},
|
|
36
36
|
});
|
|
37
37
|
clearTimeout(timeoutId);
|
|
38
38
|
if (response.ok) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { ICache, SessionStore } from '@naman_deep_singh/cache';
|
|
2
|
+
import type { Server } from 'http';
|
|
3
|
+
import type { Application } from 'express';
|
|
4
|
+
import type { ServerConfig, SocketIOConfig } from '../types';
|
|
4
5
|
export interface GrpcService {
|
|
5
6
|
service: Record<string, unknown>;
|
|
6
7
|
implementation: Record<string, (...args: unknown[]) => unknown>;
|
|
@@ -49,8 +50,8 @@ export declare class ExpressServer implements ServerInstance {
|
|
|
49
50
|
app: Application;
|
|
50
51
|
server?: Server;
|
|
51
52
|
config: ServerInstanceConfig;
|
|
52
|
-
cache?:
|
|
53
|
-
sessionStore?:
|
|
53
|
+
cache?: ICache<unknown>;
|
|
54
|
+
sessionStore?: SessionStore | undefined;
|
|
54
55
|
private status;
|
|
55
56
|
private grpcServices;
|
|
56
57
|
private grpcServer?;
|
package/dist/esm/core/server.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import express, { json, raw } from 'express';
|
|
2
|
-
import { CacheFactory, SessionStore } from '@naman_deep_singh/cache';
|
|
3
1
|
import crypto from 'crypto';
|
|
2
|
+
import { CacheFactory, SessionStore } from '@naman_deep_singh/cache';
|
|
3
|
+
import express, { json, raw } from 'express';
|
|
4
4
|
import { PeriodicHealthMonitor } from './periodic-health';
|
|
5
5
|
import { createGracefulShutdown } from './shutdown';
|
|
6
|
+
import { useSession } from '../middleware';
|
|
6
7
|
export class ExpressServer {
|
|
7
8
|
constructor(name = 'Express Server', version = '1.0.0', config = {}) {
|
|
8
9
|
this.status = 'stopped';
|
|
@@ -24,7 +25,7 @@ export class ExpressServer {
|
|
|
24
25
|
socketIO: config.socketIO,
|
|
25
26
|
periodicHealthCheck: config.periodicHealthCheck || { enabled: false },
|
|
26
27
|
cache: config.cache || { enabled: false },
|
|
27
|
-
session: config.session || { enabled: false }
|
|
28
|
+
session: config.session || { enabled: false },
|
|
28
29
|
};
|
|
29
30
|
// Initialize locals for cache/session
|
|
30
31
|
this.app.locals.cache = undefined;
|
|
@@ -72,21 +73,24 @@ export class ExpressServer {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
// Apply custom middleware
|
|
75
|
-
if (this.config.customMiddleware &&
|
|
76
|
-
this.config.customMiddleware.
|
|
76
|
+
if (this.config.customMiddleware &&
|
|
77
|
+
this.config.customMiddleware.length > 0) {
|
|
78
|
+
this.config.customMiddleware.forEach((middleware) => {
|
|
77
79
|
this.app.use(middleware);
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
82
|
// Add health check if enabled
|
|
81
83
|
if (this.config.healthCheck) {
|
|
82
|
-
const healthPath = typeof this.config.healthCheck === 'string'
|
|
84
|
+
const healthPath = typeof this.config.healthCheck === 'string'
|
|
85
|
+
? this.config.healthCheck
|
|
86
|
+
: '/health';
|
|
83
87
|
this.app.get(healthPath, async (req, res) => {
|
|
84
88
|
const base = {
|
|
85
89
|
status: 'healthy',
|
|
86
90
|
service: this.config.name,
|
|
87
91
|
version: this.config.version,
|
|
88
92
|
uptime: Date.now() - this.config.startTime.getTime(),
|
|
89
|
-
timestamp: new Date().toISOString()
|
|
93
|
+
timestamp: new Date().toISOString(),
|
|
90
94
|
};
|
|
91
95
|
// If cache is enabled, include its health
|
|
92
96
|
const cache = req.app.locals.cache;
|
|
@@ -95,7 +99,12 @@ export class ExpressServer {
|
|
|
95
99
|
base.cache = await cache.isAlive();
|
|
96
100
|
}
|
|
97
101
|
catch (e) {
|
|
98
|
-
base.cache = {
|
|
102
|
+
base.cache = {
|
|
103
|
+
isAlive: false,
|
|
104
|
+
adapter: 'unknown',
|
|
105
|
+
timestamp: new Date(),
|
|
106
|
+
error: e.message,
|
|
107
|
+
};
|
|
99
108
|
}
|
|
100
109
|
}
|
|
101
110
|
res.status(200).json(base);
|
|
@@ -114,7 +123,11 @@ export class ExpressServer {
|
|
|
114
123
|
}
|
|
115
124
|
console.log(`🔄 [${serverName}] Initializing cache adapter: ${config.cache.adapter || 'memory'}...`);
|
|
116
125
|
// Use createWithFallback to prefer primary and fall back to memory when configured
|
|
117
|
-
const cfg = {
|
|
126
|
+
const cfg = {
|
|
127
|
+
...(cacheConfig || {}),
|
|
128
|
+
ttl: cacheConfig?.ttl ??
|
|
129
|
+
config.cache?.defaultTTL,
|
|
130
|
+
};
|
|
118
131
|
const cache = await CacheFactory.createWithFallback(cfg);
|
|
119
132
|
this.app.locals.cache = cache;
|
|
120
133
|
this.cache = cache;
|
|
@@ -124,7 +137,7 @@ export class ExpressServer {
|
|
|
124
137
|
req.cache = cache;
|
|
125
138
|
next();
|
|
126
139
|
});
|
|
127
|
-
console.log(`✅ [${serverName}] Cache initialized successfully (adapter: ${
|
|
140
|
+
console.log(`✅ [${serverName}] Cache initialized successfully (adapter: ${cacheConfig.adapter || 'memory'})`);
|
|
128
141
|
}
|
|
129
142
|
catch (err) {
|
|
130
143
|
console.error(`❌ [${serverName}] Failed to initialize cache (fallback to memory if enabled):`, err instanceof Error ? err.message : err);
|
|
@@ -133,7 +146,8 @@ export class ExpressServer {
|
|
|
133
146
|
}
|
|
134
147
|
// Initialize session if enabled
|
|
135
148
|
if (config.session && config.session.enabled) {
|
|
136
|
-
const cookieName = config.session.cookieName ||
|
|
149
|
+
const cookieName = config.session.cookieName ||
|
|
150
|
+
`${serverName.replace(/\s+/g, '_').toLowerCase()}.sid`;
|
|
137
151
|
const ttl = config.session.ttl ?? 3600;
|
|
138
152
|
let cache = this.app.locals.cache;
|
|
139
153
|
if (!cache) {
|
|
@@ -161,8 +175,6 @@ export class ExpressServer {
|
|
|
161
175
|
this.sessionStore = store;
|
|
162
176
|
// attach session middleware globally so req.sessionStore is available
|
|
163
177
|
try {
|
|
164
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
165
|
-
const { useSession } = require('../middleware/middleware');
|
|
166
178
|
this.app.use(useSession(cookieName));
|
|
167
179
|
console.log(`✅ [${serverName}] Session middleware enabled (cookie: ${cookieName}, TTL: ${ttl}s)`);
|
|
168
180
|
}
|
|
@@ -217,7 +229,7 @@ export class ExpressServer {
|
|
|
217
229
|
catch (e) {
|
|
218
230
|
// SessionStore may not have close; ignore
|
|
219
231
|
}
|
|
220
|
-
}
|
|
232
|
+
},
|
|
221
233
|
});
|
|
222
234
|
}
|
|
223
235
|
// Start periodic health monitoring after server is running
|
|
@@ -267,7 +279,7 @@ export class ExpressServer {
|
|
|
267
279
|
port: this.config.port,
|
|
268
280
|
uptime: Date.now() - this.config.startTime.getTime(),
|
|
269
281
|
status: this.status,
|
|
270
|
-
startTime: this.config.startTime
|
|
282
|
+
startTime: this.config.startTime,
|
|
271
283
|
};
|
|
272
284
|
}
|
|
273
285
|
addGrpcService(service, implementation, port = 50051) {
|
|
@@ -275,7 +287,6 @@ export class ExpressServer {
|
|
|
275
287
|
// Lazy load gRPC to avoid dependency issues
|
|
276
288
|
if (!this.grpcServer) {
|
|
277
289
|
try {
|
|
278
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
279
290
|
const grpc = require('@grpc/grpc-js');
|
|
280
291
|
this.grpcServer = new grpc.Server();
|
|
281
292
|
// Add all services
|
|
@@ -295,7 +306,6 @@ export class ExpressServer {
|
|
|
295
306
|
addRpcMethods(methods, path = '/rpc') {
|
|
296
307
|
Object.assign(this.rpcMethods, methods);
|
|
297
308
|
try {
|
|
298
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
299
309
|
const jayson = require('jayson');
|
|
300
310
|
const rpcServer = jayson.server(this.rpcMethods);
|
|
301
311
|
this.app.use(path, rpcServer.middleware());
|
|
@@ -310,13 +320,16 @@ export class ExpressServer {
|
|
|
310
320
|
try {
|
|
311
321
|
// Verify signature if secret provided
|
|
312
322
|
if (config.secret) {
|
|
313
|
-
const signature = req.headers['x-hub-signature-256'] ||
|
|
323
|
+
const signature = req.headers['x-hub-signature-256'] ||
|
|
324
|
+
req.headers['x-signature-256'];
|
|
314
325
|
if (signature) {
|
|
315
326
|
const expectedSignature = crypto
|
|
316
327
|
.createHmac('sha256', config.secret)
|
|
317
328
|
.update(req.body)
|
|
318
329
|
.digest('hex');
|
|
319
|
-
const providedSignature = Array.isArray(signature)
|
|
330
|
+
const providedSignature = Array.isArray(signature)
|
|
331
|
+
? signature[0]
|
|
332
|
+
: signature;
|
|
320
333
|
if (!providedSignature.includes(expectedSignature)) {
|
|
321
334
|
return res.status(401).json({ error: 'Invalid signature' });
|
|
322
335
|
}
|
|
@@ -340,7 +353,6 @@ export class ExpressServer {
|
|
|
340
353
|
throw new Error(`${this.config.name}: Server must be started before adding Socket.IO`);
|
|
341
354
|
}
|
|
342
355
|
try {
|
|
343
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
344
356
|
const { Server } = require('socket.io');
|
|
345
357
|
// Configure CORS
|
|
346
358
|
const corsConfig = config.cors === true
|
|
@@ -349,7 +361,7 @@ export class ExpressServer {
|
|
|
349
361
|
// Create Socket.IO server
|
|
350
362
|
const io = new Server(this.server, {
|
|
351
363
|
cors: config.cors ? corsConfig : undefined,
|
|
352
|
-
path: config.path || '/socket.io'
|
|
364
|
+
path: config.path || '/socket.io',
|
|
353
365
|
});
|
|
354
366
|
// Store reference for cleanup
|
|
355
367
|
this.socketIO = io;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Server } from 'http';
|
|
2
|
-
import { GracefulShutdownConfig, ServerPlugin } from '../types';
|
|
1
|
+
import type { Server } from 'http';
|
|
2
|
+
import type { 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;
|
|
@@ -32,6 +32,7 @@ export function withGracefulShutdown(config = {}) {
|
|
|
32
32
|
return (app, serverConfig) => {
|
|
33
33
|
// This plugin needs to be applied after server.listen()
|
|
34
34
|
// Store config for later use
|
|
35
|
+
;
|
|
35
36
|
app.__gracefulShutdownConfig = config;
|
|
36
37
|
};
|
|
37
38
|
}
|
|
@@ -45,7 +46,7 @@ export function startServerWithShutdown(app, port, shutdownConfig = {}, serverNa
|
|
|
45
46
|
const enhancedConfig = {
|
|
46
47
|
...config,
|
|
47
48
|
serverName,
|
|
48
|
-
serverVersion
|
|
49
|
+
serverVersion,
|
|
49
50
|
};
|
|
50
51
|
createGracefulShutdown(server, enhancedConfig);
|
|
51
52
|
return server;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
export { ExpressServer, createServer } from './core/server';
|
|
2
|
-
export type { ServerInstance, ServerInfo, GrpcService, RpcMethod, WebhookConfig } 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 './core/health';
|
|
6
|
-
export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
|
|
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/utils';
|
|
5
|
+
export { createHealthCheck, withHealthCheck, addHealthCheck, } from './core/health';
|
|
6
|
+
export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown, } from './core/shutdown';
|
|
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/utils';
|
|
9
9
|
export { PeriodicHealthMonitor } from './core/periodic-health';
|
|
10
|
-
export type { ServerConfig, HealthCheckConfig, HealthCheck, GracefulShutdownConfig, ServerPlugin, SocketIOConfig, SocketInstance, PeriodicHealthCheckConfig, HealthCheckService } from './types';
|
|
11
|
-
import {
|
|
12
|
-
import { createHealthCheck, withHealthCheck, addHealthCheck } from './core/health';
|
|
13
|
-
import { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
|
|
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/utils';
|
|
10
|
+
export type { ServerConfig, HealthCheckConfig, HealthCheck, GracefulShutdownConfig, ServerPlugin, SocketIOConfig, SocketInstance, PeriodicHealthCheckConfig, HealthCheckService, } from './types';
|
|
11
|
+
import { addHealthCheck, createHealthCheck, withHealthCheck } from './core/health';
|
|
16
12
|
import { PeriodicHealthMonitor } from './core/periodic-health';
|
|
13
|
+
import { ExpressServer, createServer } from './core/server';
|
|
14
|
+
import { createGracefulShutdown, startServerWithShutdown, withGracefulShutdown } from './core/shutdown';
|
|
15
|
+
import { createAuthMiddleware, createErrorHandler, createLoggingMiddleware, createRateLimitMiddleware, createRequestIdMiddleware, createValidationMiddleware, rateLimit, requireAuth, validateFields, withAuth, withErrorHandler, withLogging, withRateLimit, withRequestId, withValidation } from './middleware';
|
|
16
|
+
import { getEnv, getEnvBoolean, getEnvNumber } from './utils/utils';
|
|
17
17
|
declare const ServerUtils: {
|
|
18
18
|
createServer: typeof createServer;
|
|
19
19
|
ExpressServer: typeof ExpressServer;
|
package/dist/esm/index.js
CHANGED
|
@@ -3,22 +3,22 @@ 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 './core/health';
|
|
6
|
+
export { createHealthCheck, withHealthCheck, addHealthCheck, } from './core/health';
|
|
7
7
|
// Graceful shutdown utilities
|
|
8
|
-
export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './core/shutdown';
|
|
8
|
+
export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown, } from './core/shutdown';
|
|
9
9
|
// Middleware utilities
|
|
10
|
-
export { createLoggingMiddleware, createErrorHandler, createRequestIdMiddleware, createValidationMiddleware, createRateLimitMiddleware, createAuthMiddleware, withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, validateFields, rateLimit, requireAuth, cacheResponse, useSession } 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
|
-
export { getEnv, getEnvNumber, getEnvBoolean } from './utils/utils';
|
|
12
|
+
export { getEnv, getEnvNumber, getEnvBoolean, } from './utils/utils';
|
|
13
13
|
// Periodic health monitoring
|
|
14
14
|
export { PeriodicHealthMonitor } from './core/periodic-health';
|
|
15
|
+
import { addHealthCheck, createHealthCheck, withHealthCheck, } from './core/health';
|
|
16
|
+
import { PeriodicHealthMonitor } from './core/periodic-health';
|
|
15
17
|
// Import all exports for default export
|
|
16
18
|
import { ExpressServer, createServer } from './core/server';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { getEnv, getEnvNumber, getEnvBoolean } from './utils/utils';
|
|
21
|
-
import { PeriodicHealthMonitor } from './core/periodic-health';
|
|
19
|
+
import { createGracefulShutdown, startServerWithShutdown, withGracefulShutdown, } from './core/shutdown';
|
|
20
|
+
import { createAuthMiddleware, createErrorHandler, createLoggingMiddleware, createRateLimitMiddleware, createRequestIdMiddleware, createValidationMiddleware, rateLimit, requireAuth, validateFields, withAuth, withErrorHandler, withLogging, withRateLimit, withRequestId, withValidation, } from './middleware';
|
|
21
|
+
import { getEnv, getEnvBoolean, getEnvNumber } from './utils/utils';
|
|
22
22
|
// Default export for namespace usage
|
|
23
23
|
const ServerUtils = {
|
|
24
24
|
// Server creation
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { UnauthorizedError } from '@naman_deep_singh/errors-utils';
|
|
2
|
+
import { extractToken, safeVerifyToken } from '@naman_deep_singh/security';
|
|
3
3
|
export function createAuthMiddleware(config) {
|
|
4
4
|
const { secret, unauthorizedMessage = 'Unauthorized access', tokenExtractor = (req) => extractToken({
|
|
5
5
|
header: req.headers.authorization || undefined,
|
|
6
6
|
cookies: req.cookies,
|
|
7
7
|
query: req.query,
|
|
8
|
-
body: req.body
|
|
9
|
-
}) } = config;
|
|
8
|
+
body: req.body,
|
|
9
|
+
}), } = config;
|
|
10
10
|
return async (req, res, next) => {
|
|
11
11
|
try {
|
|
12
12
|
// Extract token from request
|
|
13
13
|
const token = tokenExtractor(req);
|
|
14
14
|
if (!token) {
|
|
15
15
|
const error = new UnauthorizedError(unauthorizedMessage, {
|
|
16
|
-
reason: 'No token provided'
|
|
16
|
+
reason: 'No token provided',
|
|
17
17
|
});
|
|
18
18
|
return next(error);
|
|
19
19
|
}
|
|
@@ -22,7 +22,7 @@ export function createAuthMiddleware(config) {
|
|
|
22
22
|
if (!result.valid) {
|
|
23
23
|
const error = new UnauthorizedError(unauthorizedMessage, {
|
|
24
24
|
reason: 'Invalid or expired token',
|
|
25
|
-
originalError: result.error?.message
|
|
25
|
+
originalError: result.error?.message,
|
|
26
26
|
});
|
|
27
27
|
return next(error);
|
|
28
28
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RequestHandler } from
|
|
1
|
+
import type { RequestHandler } from 'node_modules/@types/express';
|
|
2
2
|
export declare function cacheResponse(ttl?: number): RequestHandler;
|
|
@@ -25,12 +25,14 @@ export function cacheResponse(ttl) {
|
|
|
25
25
|
try {
|
|
26
26
|
const expiry = ttl ?? defaultTTL;
|
|
27
27
|
if (expiry && cache && typeof cache.set === 'function') {
|
|
28
|
+
;
|
|
28
29
|
cache.set(key, body, expiry).catch((err) => {
|
|
29
30
|
console.error(`[Cache] Failed to set key "${key}" with TTL ${expiry}:`, err);
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
else if (cache) {
|
|
33
34
|
if (typeof cache.set === 'function') {
|
|
35
|
+
;
|
|
34
36
|
cache.set(key, body).catch((err) => {
|
|
35
37
|
console.error(`[Cache] Failed to set key "${key}":`, err);
|
|
36
38
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ErrorRequestHandler } from
|
|
1
|
+
import type { ErrorRequestHandler } from 'node_modules/@types/express';
|
|
2
2
|
export declare function createErrorHandler(): ErrorRequestHandler;
|
|
@@ -17,9 +17,11 @@ export function createErrorHandler() {
|
|
|
17
17
|
data: undefined,
|
|
18
18
|
error: {
|
|
19
19
|
message,
|
|
20
|
-
...(process.env.NODE_ENV !== 'production' && {
|
|
20
|
+
...(process.env.NODE_ENV !== 'production' && {
|
|
21
|
+
details: { stack: errorObj.stack },
|
|
22
|
+
}),
|
|
21
23
|
},
|
|
22
|
-
meta: null
|
|
24
|
+
meta: null,
|
|
23
25
|
});
|
|
24
26
|
};
|
|
25
27
|
}
|
|
@@ -2,9 +2,9 @@ export { AuthConfig, createAuthMiddleware } from './auth.middleware';
|
|
|
2
2
|
export { cacheResponse } from './cache.middleware';
|
|
3
3
|
export { createErrorHandler } from './errorHandler.middleware';
|
|
4
4
|
export { createLoggingMiddleware } from './logging.middleware';
|
|
5
|
-
export { RateLimitConfig, createRateLimitMiddleware } from './rateLimiter.middleware';
|
|
5
|
+
export { RateLimitConfig, createRateLimitMiddleware, } from './rateLimiter.middleware';
|
|
6
6
|
export { createRequestIdMiddleware } from './requestId.middleware';
|
|
7
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';
|
|
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';
|
|
@@ -7,14 +7,14 @@ export { createErrorHandler } from './errorHandler.middleware';
|
|
|
7
7
|
// Logging Middleware
|
|
8
8
|
export { createLoggingMiddleware } from './logging.middleware';
|
|
9
9
|
// Rate Limiter Middleware
|
|
10
|
-
export { createRateLimitMiddleware } from './rateLimiter.middleware';
|
|
10
|
+
export { createRateLimitMiddleware, } from './rateLimiter.middleware';
|
|
11
11
|
// Request ID Middleware
|
|
12
12
|
export { createRequestIdMiddleware } from './requestId.middleware';
|
|
13
13
|
// Session Middleware
|
|
14
14
|
export { useSession } from './session.middleware';
|
|
15
15
|
// Validation Middleware
|
|
16
|
-
export { createValidationMiddleware } from './validation.middleware';
|
|
16
|
+
export { createValidationMiddleware, } from './validation.middleware';
|
|
17
17
|
// Plugin middleware functions (for application-level middleware)
|
|
18
|
-
export { withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth } from './plugins.middleware';
|
|
18
|
+
export { withLogging, withErrorHandler, withRequestId, withValidation, withRateLimit, withAuth, } from './plugins.middleware';
|
|
19
19
|
// Convenience middleware functions (for route-level middleware)
|
|
20
|
-
export { validateFields, rateLimit, requireAuth } from './plugins.middleware';
|
|
20
|
+
export { validateFields, rateLimit, requireAuth, } from './plugins.middleware';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RequestHandler } from
|
|
1
|
+
import type { RequestHandler } from 'node_modules/@types/express';
|
|
2
2
|
export declare function createLoggingMiddleware(format?: 'simple' | 'detailed'): RequestHandler;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { RequestHandler } from 'express';
|
|
2
|
-
import { ServerPlugin } from '../types';
|
|
3
|
-
import {
|
|
4
|
-
import { RateLimitConfig } from './rateLimiter.middleware';
|
|
5
|
-
import {
|
|
1
|
+
import type { RequestHandler } from 'express';
|
|
2
|
+
import type { ServerPlugin } from '../types';
|
|
3
|
+
import type { AuthConfig } from './auth.middleware';
|
|
4
|
+
import type { RateLimitConfig } from './rateLimiter.middleware';
|
|
5
|
+
import type { ValidationRule } from './validation.middleware';
|
|
6
6
|
export declare function withLogging(format?: 'simple' | 'detailed'): ServerPlugin;
|
|
7
7
|
export declare function withErrorHandler(): ServerPlugin;
|
|
8
8
|
export declare function withRequestId(): ServerPlugin;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAuthMiddleware } from './auth.middleware';
|
|
2
2
|
import { createErrorHandler } from './errorHandler.middleware';
|
|
3
|
+
import { createLoggingMiddleware } from './logging.middleware';
|
|
4
|
+
import { createRateLimitMiddleware } from './rateLimiter.middleware';
|
|
3
5
|
import { createRequestIdMiddleware } from './requestId.middleware';
|
|
4
6
|
import { createValidationMiddleware } from './validation.middleware';
|
|
5
|
-
import { createRateLimitMiddleware } from './rateLimiter.middleware';
|
|
6
|
-
import { createAuthMiddleware } from './auth.middleware';
|
|
7
7
|
// Plugin versions
|
|
8
8
|
export function withLogging(format = 'simple') {
|
|
9
9
|
return (app) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const rateLimitStore = new Map();
|
|
2
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;
|
|
3
|
+
const { windowMs = 15 * 60 * 1000, maxRequests = 100, message = 'Too many requests, please try again later', keyGenerator = (req) => req.ip || 'unknown', } = config;
|
|
4
4
|
return (req, res, next) => {
|
|
5
5
|
const key = keyGenerator(req);
|
|
6
6
|
const now = Date.now();
|
|
@@ -8,7 +8,7 @@ export function createRateLimitMiddleware(config = {}) {
|
|
|
8
8
|
if (!record || now > record.resetTime) {
|
|
9
9
|
rateLimitStore.set(key, {
|
|
10
10
|
count: 1,
|
|
11
|
-
resetTime: now + windowMs
|
|
11
|
+
resetTime: now + windowMs,
|
|
12
12
|
});
|
|
13
13
|
return next();
|
|
14
14
|
}
|
|
@@ -20,10 +20,10 @@ export function createRateLimitMiddleware(config = {}) {
|
|
|
20
20
|
error: {
|
|
21
21
|
message,
|
|
22
22
|
details: {
|
|
23
|
-
retryAfter: Math.ceil((record.resetTime - now) / 1000)
|
|
24
|
-
}
|
|
23
|
+
retryAfter: Math.ceil((record.resetTime - now) / 1000),
|
|
24
|
+
},
|
|
25
25
|
},
|
|
26
|
-
meta: null
|
|
26
|
+
meta: null,
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
record.count++;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RequestHandler } from
|
|
1
|
+
import type { RequestHandler } from 'node_modules/@types/express';
|
|
2
2
|
export declare function createRequestIdMiddleware(): RequestHandler;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RequestHandler } from
|
|
1
|
+
import type { RequestHandler } from 'node_modules/@types/express';
|
|
2
2
|
export declare function useSession(cookieName?: string): RequestHandler;
|
|
@@ -10,7 +10,10 @@ export function useSession(cookieName) {
|
|
|
10
10
|
if (!sid) {
|
|
11
11
|
const cookieHeader = req.headers.cookie;
|
|
12
12
|
if (cookieHeader) {
|
|
13
|
-
const match = cookieHeader
|
|
13
|
+
const match = cookieHeader
|
|
14
|
+
.split(';')
|
|
15
|
+
.map((s) => s.trim())
|
|
16
|
+
.find((s) => s.startsWith(`${name}=`));
|
|
14
17
|
if (match)
|
|
15
18
|
sid = match.split('=')[1];
|
|
16
19
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { ValidationError } from
|
|
1
|
+
import { ValidationError } from '@naman_deep_singh/errors-utils';
|
|
2
2
|
export function createValidationMiddleware(rules) {
|
|
3
3
|
return (req, res, next) => {
|
|
4
4
|
const errors = [];
|
|
5
5
|
for (const rule of rules) {
|
|
6
6
|
const value = req.body[rule.field];
|
|
7
|
-
if (rule.required &&
|
|
7
|
+
if (rule.required &&
|
|
8
|
+
(value === undefined || value === null || value === '')) {
|
|
8
9
|
errors.push(`${rule.field} is required`);
|
|
9
10
|
continue;
|
|
10
11
|
}
|
|
@@ -54,7 +55,7 @@ export function createValidationMiddleware(rules) {
|
|
|
54
55
|
if (errors.length > 0) {
|
|
55
56
|
// Use ValidationError from errors-utils and let error middleware handle response
|
|
56
57
|
const validationError = new ValidationError('Validation failed', {
|
|
57
|
-
validationErrors: errors
|
|
58
|
+
validationErrors: errors,
|
|
58
59
|
});
|
|
59
60
|
return next(validationError);
|
|
60
61
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import express from 'express';
|
|
1
|
+
import type express from 'express';
|
|
2
2
|
export interface CorsOptions {
|
|
3
3
|
origin?: string | string[] | boolean | RegExp | ((origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => void);
|
|
4
4
|
methods?: string | string[];
|
package/dist/esm/utils/utils.js
CHANGED
|
@@ -31,8 +31,8 @@ export function getEnvBoolean(key, defaultValue) {
|
|
|
31
31
|
return defaultValue;
|
|
32
32
|
}
|
|
33
33
|
const normalized = value.toLowerCase();
|
|
34
|
-
if (normalized !==
|
|
34
|
+
if (normalized !== 'true' && normalized !== 'false') {
|
|
35
35
|
throw new Error(`Environment variable ${key} must be 'true' or 'false'`);
|
|
36
36
|
}
|
|
37
|
-
return normalized ===
|
|
37
|
+
return normalized === 'true';
|
|
38
38
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Application, RequestHandler } from 'express';
|
|
2
|
-
import { HealthCheckConfig, ServerPlugin } from '../types';
|
|
1
|
+
import type { Application, RequestHandler } from 'express';
|
|
2
|
+
import type { HealthCheckConfig, ServerPlugin } from '../types';
|
|
3
3
|
export declare function createHealthCheck(config?: HealthCheckConfig): RequestHandler;
|
|
4
4
|
export declare function withHealthCheck(path?: string, config?: HealthCheckConfig): ServerPlugin;
|
|
5
5
|
export declare function addHealthCheck(app: Application, path?: string, config?: HealthCheckConfig): void;
|