ts-packages 1.0.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/package.json +18 -0
- package/packages/response-utils/README.md +110 -0
- package/packages/response-utils/package.json +22 -0
- package/packages/response-utils/src/index.ts +168 -0
- package/packages/response-utils/tsconfig.json +21 -0
- package/packages/security/README.md +116 -0
- package/packages/security/package.json +30 -0
- package/packages/security/src/index.ts +39 -0
- package/packages/security/tsconfig.json +21 -0
- package/packages/server-utils/README.md +281 -0
- package/packages/server-utils/package.json +27 -0
- package/packages/server-utils/src/health.ts +47 -0
- package/packages/server-utils/src/index.ts +113 -0
- package/packages/server-utils/src/middleware.ts +275 -0
- package/packages/server-utils/src/server.ts +320 -0
- package/packages/server-utils/src/shutdown.ts +60 -0
- package/packages/server-utils/src/types.ts +64 -0
- package/packages/server-utils/src/utils.ts +34 -0
- package/packages/server-utils/tsconfig.json +21 -0
- package/pnpm-workspace.yaml +2 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# @naman_deep_singh/server-utils
|
|
2
|
+
|
|
3
|
+
Extensible server utilities for Express.js microservices with multi-protocol support and TypeScript.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @naman_deep_singh/server-utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- ✅ **Multi-protocol support** - HTTP, gRPC, JSON-RPC, WebSockets, Webhooks
|
|
14
|
+
- ✅ **Express.js integration** with middleware collection
|
|
15
|
+
- ✅ **Graceful shutdown** handling
|
|
16
|
+
- ✅ **Health checks** with custom checks support
|
|
17
|
+
- ✅ **TypeScript support** with full type safety
|
|
18
|
+
- ✅ **Hybrid exports** - use named imports or namespace imports
|
|
19
|
+
- ✅ **Plugin architecture** for extensibility
|
|
20
|
+
- ✅ **Built-in middleware** - logging, validation, rate limiting, auth
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Named Imports
|
|
25
|
+
```typescript
|
|
26
|
+
import { createServer } from '@naman_deep_singh/server-utils';
|
|
27
|
+
|
|
28
|
+
const server = createServer('My API', '1.0.0', {
|
|
29
|
+
port: 3000,
|
|
30
|
+
cors: true,
|
|
31
|
+
helmet: true
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Add routes
|
|
35
|
+
server.app.get('/users', (req, res) => {
|
|
36
|
+
res.json({ users: [] });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Start server
|
|
40
|
+
await server.start();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Namespace Import
|
|
44
|
+
```typescript
|
|
45
|
+
import ServerUtils from '@naman_deep_singh/server-utils';
|
|
46
|
+
|
|
47
|
+
const server = ServerUtils.createServer('My API', '1.0.0');
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Multi-Protocol Support
|
|
51
|
+
|
|
52
|
+
### HTTP + Express Routes
|
|
53
|
+
```typescript
|
|
54
|
+
const server = createServer('Multi-Protocol Server', '1.0.0');
|
|
55
|
+
|
|
56
|
+
server.app.get('/api/users', (req, res) => {
|
|
57
|
+
res.json({ users: [] });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await server.start();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### gRPC Support
|
|
64
|
+
```typescript
|
|
65
|
+
// Add gRPC service (requires @grpc/grpc-js)
|
|
66
|
+
server.addGrpcService(userProto.UserService.service, {
|
|
67
|
+
getUser: (call, callback) => {
|
|
68
|
+
callback(null, { id: call.request.id, name: 'John' });
|
|
69
|
+
}
|
|
70
|
+
}, 50051); // Custom port
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### JSON-RPC Support
|
|
74
|
+
```typescript
|
|
75
|
+
// Add JSON-RPC methods (requires jayson)
|
|
76
|
+
server.addRpcMethods({
|
|
77
|
+
add: (params, callback) => {
|
|
78
|
+
callback(null, params[0] + params[1]);
|
|
79
|
+
},
|
|
80
|
+
getUser: (id, callback) => {
|
|
81
|
+
callback(null, { id, name: 'John' });
|
|
82
|
+
}
|
|
83
|
+
}, '/rpc'); // Custom path
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### WebSocket Support
|
|
87
|
+
```typescript
|
|
88
|
+
// Add Socket.IO (requires socket.io)
|
|
89
|
+
const io = server.addSocketIO({
|
|
90
|
+
cors: true,
|
|
91
|
+
onConnection: (socket) => {
|
|
92
|
+
console.log('Client connected:', socket.id);
|
|
93
|
+
|
|
94
|
+
socket.on('message', (data) => {
|
|
95
|
+
socket.broadcast.emit('message', data);
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
onDisconnection: (socket, reason) => {
|
|
99
|
+
console.log('Client disconnected:', socket.id, reason);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Webhook Support
|
|
105
|
+
```typescript
|
|
106
|
+
// Add secure webhooks
|
|
107
|
+
server.addWebhook({
|
|
108
|
+
path: '/webhooks/github',
|
|
109
|
+
secret: process.env.GITHUB_WEBHOOK_SECRET,
|
|
110
|
+
handler: async (payload, headers) => {
|
|
111
|
+
if (payload.action === 'opened') {
|
|
112
|
+
console.log('New PR opened:', payload.pull_request.title);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
server.addWebhook({
|
|
118
|
+
path: '/webhooks/stripe',
|
|
119
|
+
secret: process.env.STRIPE_WEBHOOK_SECRET,
|
|
120
|
+
handler: async (payload) => {
|
|
121
|
+
if (payload.type === 'payment_intent.succeeded') {
|
|
122
|
+
// Handle successful payment
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Built-in Middleware
|
|
129
|
+
|
|
130
|
+
### Logging Middleware
|
|
131
|
+
```typescript
|
|
132
|
+
import { createLoggingMiddleware, withLogging } from '@naman_deep_singh/server-utils';
|
|
133
|
+
|
|
134
|
+
// Direct usage
|
|
135
|
+
server.app.use(createLoggingMiddleware('detailed'));
|
|
136
|
+
|
|
137
|
+
// Plugin usage
|
|
138
|
+
const server = createServerWithPlugins('My API', '1.0.0', [
|
|
139
|
+
withLogging('detailed')
|
|
140
|
+
]);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Validation Middleware
|
|
144
|
+
```typescript
|
|
145
|
+
import { validateFields } from '@naman_deep_singh/server-utils';
|
|
146
|
+
|
|
147
|
+
server.app.post('/users', validateFields([
|
|
148
|
+
{ field: 'email', required: true, type: 'email' },
|
|
149
|
+
{ field: 'password', required: true, minLength: 8 },
|
|
150
|
+
{ field: 'age', type: 'number', custom: (value) => value >= 18 || 'Must be 18+' }
|
|
151
|
+
]), (req, res) => {
|
|
152
|
+
// Validation passed
|
|
153
|
+
res.json({ success: true });
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Rate Limiting
|
|
158
|
+
```typescript
|
|
159
|
+
import { rateLimit } from '@naman_deep_singh/server-utils';
|
|
160
|
+
|
|
161
|
+
server.app.use('/api', rateLimit({
|
|
162
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
163
|
+
maxRequests: 100,
|
|
164
|
+
message: 'Too many requests'
|
|
165
|
+
}));
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Authentication Middleware
|
|
169
|
+
```typescript
|
|
170
|
+
import { requireAuth } from '@naman_deep_singh/server-utils';
|
|
171
|
+
|
|
172
|
+
server.app.use('/protected', requireAuth({
|
|
173
|
+
tokenExtractor: (req) => req.headers.authorization?.substring(7),
|
|
174
|
+
tokenValidator: async (token) => {
|
|
175
|
+
// Verify JWT token
|
|
176
|
+
return jwt.verify(token, process.env.JWT_SECRET);
|
|
177
|
+
}
|
|
178
|
+
}));
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Health Checks
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { addHealthCheck } from '@naman_deep_singh/server-utils';
|
|
185
|
+
|
|
186
|
+
addHealthCheck(server.app, '/health', {
|
|
187
|
+
customChecks: [
|
|
188
|
+
{
|
|
189
|
+
name: 'database',
|
|
190
|
+
check: async () => {
|
|
191
|
+
// Check database connection
|
|
192
|
+
return await db.ping();
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: 'redis',
|
|
197
|
+
check: async () => {
|
|
198
|
+
return await redis.ping() === 'PONG';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Server Management
|
|
206
|
+
|
|
207
|
+
### Server Information
|
|
208
|
+
```typescript
|
|
209
|
+
const info = server.getInfo();
|
|
210
|
+
console.log(info);
|
|
211
|
+
// {
|
|
212
|
+
// name: 'My API',
|
|
213
|
+
// version: '1.0.0',
|
|
214
|
+
// port: 3000,
|
|
215
|
+
// uptime: 12345,
|
|
216
|
+
// status: 'running',
|
|
217
|
+
// startTime: Date
|
|
218
|
+
// }
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Graceful Shutdown
|
|
222
|
+
```typescript
|
|
223
|
+
const server = createServer('My API', '1.0.0', {
|
|
224
|
+
gracefulShutdown: true // Enabled by default
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// Handles SIGINT and SIGTERM
|
|
228
|
+
process.on('SIGINT', async () => {
|
|
229
|
+
await server.stop();
|
|
230
|
+
process.exit(0);
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Configuration Options
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
interface ServerConfig {
|
|
238
|
+
port?: number; // Default: 3000
|
|
239
|
+
cors?: boolean | CorsOptions; // Default: true
|
|
240
|
+
helmet?: boolean; // Default: true
|
|
241
|
+
json?: boolean; // Default: true
|
|
242
|
+
customMiddleware?: RequestHandler[];
|
|
243
|
+
healthCheck?: boolean | string; // Default: true
|
|
244
|
+
gracefulShutdown?: boolean; // Default: true
|
|
245
|
+
socketIO?: SocketIOConfig;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## API Reference
|
|
250
|
+
|
|
251
|
+
### Core Functions
|
|
252
|
+
- `createServer(name?, version?, config?)` - Create server instance
|
|
253
|
+
- `ExpressServer` - Server class for advanced usage
|
|
254
|
+
|
|
255
|
+
### Middleware Functions
|
|
256
|
+
- `createLoggingMiddleware(format?)` - Request logging
|
|
257
|
+
- `createErrorHandler()` - Error handling
|
|
258
|
+
- `createValidationMiddleware(rules)` - Input validation
|
|
259
|
+
- `createRateLimitMiddleware(config?)` - Rate limiting
|
|
260
|
+
- `createAuthMiddleware(config)` - Authentication
|
|
261
|
+
|
|
262
|
+
### Health & Monitoring
|
|
263
|
+
- `createHealthCheck(config?)` - Health check endpoint
|
|
264
|
+
- `addHealthCheck(app, path?, config?)` - Add health check to app
|
|
265
|
+
|
|
266
|
+
### Graceful Shutdown
|
|
267
|
+
- `createGracefulShutdown(server, config?)` - Setup graceful shutdown
|
|
268
|
+
- `startServerWithShutdown(app, port, config?)` - Start with shutdown handling
|
|
269
|
+
|
|
270
|
+
## Dependencies
|
|
271
|
+
|
|
272
|
+
### Required
|
|
273
|
+
- **express** - Web framework
|
|
274
|
+
- **cors** - CORS middleware
|
|
275
|
+
- **helmet** - Security middleware
|
|
276
|
+
- **cookie-parser** - Cookie parsing
|
|
277
|
+
|
|
278
|
+
### Optional (for specific features)
|
|
279
|
+
- **@grpc/grpc-js** - For gRPC support
|
|
280
|
+
- **jayson** - For JSON-RPC support
|
|
281
|
+
- **socket.io** - For WebSocket support
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@naman_deep_singh/server-utils",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Extensible server utilities for Express.js microservices with TypeScript",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"server",
|
|
12
|
+
"express",
|
|
13
|
+
"microservices",
|
|
14
|
+
"utils",
|
|
15
|
+
"typescript"
|
|
16
|
+
],
|
|
17
|
+
"author": "Naman Deep Singh",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"packageManager": "pnpm@10.20.0",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"express": "^4.21.1"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/express": "^4.17.21",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { HealthCheckConfig, HealthCheck, ServerPlugin } from './types';
|
|
3
|
+
|
|
4
|
+
export function createHealthCheck(config: HealthCheckConfig = {}): express.RequestHandler {
|
|
5
|
+
const { customChecks = [] } = config;
|
|
6
|
+
|
|
7
|
+
return async (req: express.Request, res: express.Response) => {
|
|
8
|
+
try {
|
|
9
|
+
const checks: Record<string, boolean> = {
|
|
10
|
+
server: true,
|
|
11
|
+
timestamp: Date.now() as any
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Run custom health checks
|
|
15
|
+
for (const check of customChecks) {
|
|
16
|
+
try {
|
|
17
|
+
checks[check.name] = await check.check();
|
|
18
|
+
} catch (error) {
|
|
19
|
+
checks[check.name] = false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const isHealthy = Object.values(checks).every(status => status === true || typeof status === 'number');
|
|
24
|
+
|
|
25
|
+
res.status(isHealthy ? 200 : 503).json({
|
|
26
|
+
status: isHealthy ? 'healthy' : 'unhealthy',
|
|
27
|
+
checks
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
res.status(503).json({
|
|
31
|
+
status: 'unhealthy',
|
|
32
|
+
error: 'Health check failed'
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function withHealthCheck(path: string = '/health', config: HealthCheckConfig = {}): ServerPlugin {
|
|
39
|
+
return (app: express.Application) => {
|
|
40
|
+
app.get(path, createHealthCheck(config));
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Convenience function for direct use
|
|
45
|
+
export function addHealthCheck(app: express.Application, path: string = '/health', config: HealthCheckConfig = {}): void {
|
|
46
|
+
app.get(path, createHealthCheck(config));
|
|
47
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Core server utilities
|
|
2
|
+
export { ExpressServer, createServer } from './server';
|
|
3
|
+
export type { ServerInstance, ServerInfo, GrpcService, RpcMethod, WebhookConfig } from './server';
|
|
4
|
+
|
|
5
|
+
// Health check utilities
|
|
6
|
+
export { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
|
|
7
|
+
|
|
8
|
+
// Graceful shutdown utilities
|
|
9
|
+
export { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
|
|
10
|
+
|
|
11
|
+
// Middleware utilities
|
|
12
|
+
export {
|
|
13
|
+
createLoggingMiddleware,
|
|
14
|
+
createErrorHandler,
|
|
15
|
+
createRequestIdMiddleware,
|
|
16
|
+
createValidationMiddleware,
|
|
17
|
+
createRateLimitMiddleware,
|
|
18
|
+
createAuthMiddleware,
|
|
19
|
+
withLogging,
|
|
20
|
+
withErrorHandler,
|
|
21
|
+
withRequestId,
|
|
22
|
+
withValidation,
|
|
23
|
+
withRateLimit,
|
|
24
|
+
withAuth,
|
|
25
|
+
validateFields,
|
|
26
|
+
rateLimit,
|
|
27
|
+
requireAuth,
|
|
28
|
+
type ValidationRule,
|
|
29
|
+
type RateLimitConfig,
|
|
30
|
+
type AuthConfig
|
|
31
|
+
} from './middleware';
|
|
32
|
+
|
|
33
|
+
// Utility functions
|
|
34
|
+
export {
|
|
35
|
+
getEnv,
|
|
36
|
+
getEnvNumber,
|
|
37
|
+
getEnvBoolean
|
|
38
|
+
} from './utils';
|
|
39
|
+
|
|
40
|
+
// Types
|
|
41
|
+
export type {
|
|
42
|
+
ServerConfig,
|
|
43
|
+
HealthCheckConfig,
|
|
44
|
+
HealthCheck,
|
|
45
|
+
GracefulShutdownConfig,
|
|
46
|
+
ServerPlugin,
|
|
47
|
+
SocketIOConfig,
|
|
48
|
+
SocketInstance
|
|
49
|
+
} from './types';
|
|
50
|
+
|
|
51
|
+
// Import all exports for default export
|
|
52
|
+
import { ExpressServer, createServer } from './server';
|
|
53
|
+
import { createHealthCheck, withHealthCheck, addHealthCheck } from './health';
|
|
54
|
+
import { createGracefulShutdown, withGracefulShutdown, startServerWithShutdown } from './shutdown';
|
|
55
|
+
import {
|
|
56
|
+
createLoggingMiddleware,
|
|
57
|
+
createErrorHandler,
|
|
58
|
+
createRequestIdMiddleware,
|
|
59
|
+
createValidationMiddleware,
|
|
60
|
+
createRateLimitMiddleware,
|
|
61
|
+
createAuthMiddleware,
|
|
62
|
+
withLogging,
|
|
63
|
+
withErrorHandler,
|
|
64
|
+
withRequestId,
|
|
65
|
+
withValidation,
|
|
66
|
+
withRateLimit,
|
|
67
|
+
withAuth,
|
|
68
|
+
validateFields,
|
|
69
|
+
rateLimit,
|
|
70
|
+
requireAuth
|
|
71
|
+
} from './middleware';
|
|
72
|
+
import { getEnv, getEnvNumber, getEnvBoolean } from './utils';
|
|
73
|
+
|
|
74
|
+
// Default export for namespace usage
|
|
75
|
+
const ServerUtils = {
|
|
76
|
+
// Server creation
|
|
77
|
+
createServer,
|
|
78
|
+
ExpressServer,
|
|
79
|
+
|
|
80
|
+
// Health checks
|
|
81
|
+
createHealthCheck,
|
|
82
|
+
withHealthCheck,
|
|
83
|
+
addHealthCheck,
|
|
84
|
+
|
|
85
|
+
// Graceful shutdown
|
|
86
|
+
createGracefulShutdown,
|
|
87
|
+
withGracefulShutdown,
|
|
88
|
+
startServerWithShutdown,
|
|
89
|
+
|
|
90
|
+
// Middleware
|
|
91
|
+
createLoggingMiddleware,
|
|
92
|
+
createErrorHandler,
|
|
93
|
+
createRequestIdMiddleware,
|
|
94
|
+
createValidationMiddleware,
|
|
95
|
+
createRateLimitMiddleware,
|
|
96
|
+
createAuthMiddleware,
|
|
97
|
+
withLogging,
|
|
98
|
+
withErrorHandler,
|
|
99
|
+
withRequestId,
|
|
100
|
+
withValidation,
|
|
101
|
+
withRateLimit,
|
|
102
|
+
withAuth,
|
|
103
|
+
validateFields,
|
|
104
|
+
rateLimit,
|
|
105
|
+
requireAuth,
|
|
106
|
+
|
|
107
|
+
// Utils
|
|
108
|
+
getEnv,
|
|
109
|
+
getEnvNumber,
|
|
110
|
+
getEnvBoolean
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default ServerUtils;
|