@goatlab/node-backend 0.2.5 → 0.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.
- package/README.md +146 -14
- package/dist/container/Container.d.ts +113 -25
- package/dist/container/Container.js +391 -168
- package/dist/container/Container.js.map +1 -1
- package/dist/container/examples/batch-operations.example.d.ts +1 -0
- package/dist/container/examples/batch-operations.example.js +165 -0
- package/dist/container/examples/batch-operations.example.js.map +1 -0
- package/dist/container/helpers.d.ts +8 -0
- package/dist/container/helpers.js +22 -0
- package/dist/container/helpers.js.map +1 -1
- package/dist/container/types.d.ts +60 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server/bootstraps/getExpressTrpcApp.d.ts +5 -1
- package/dist/server/bootstraps/getExpressTrpcApp.js +216 -12
- package/dist/server/bootstraps/getExpressTrpcApp.js.map +1 -1
- package/dist/server/middleware/memoryMonitor.example.d.ts +1 -0
- package/dist/server/middleware/memoryMonitor.example.js +109 -0
- package/dist/server/middleware/memoryMonitor.example.js.map +1 -0
- package/dist/server/middleware/memoryMonitor.middleware.d.ts +42 -0
- package/dist/server/middleware/memoryMonitor.middleware.js +134 -0
- package/dist/server/middleware/memoryMonitor.middleware.js.map +1 -0
- package/dist/server/middleware/productionError.middleware.d.ts +16 -0
- package/dist/server/middleware/productionError.middleware.js +94 -0
- package/dist/server/middleware/productionError.middleware.js.map +1 -0
- package/dist/server/middleware/security.middleware.d.ts +28 -0
- package/dist/server/middleware/security.middleware.js +151 -0
- package/dist/server/middleware/security.middleware.js.map +1 -0
- package/dist/server/services/secrets/examples/container-preload.example.d.ts +1 -0
- package/dist/server/services/secrets/examples/container-preload.example.js +148 -0
- package/dist/server/services/secrets/examples/container-preload.example.js.map +1 -0
- package/dist/server/services/secrets/index.d.ts +1 -0
- package/dist/server/services/secrets/index.js +6 -0
- package/dist/server/services/secrets/index.js.map +1 -0
- package/dist/server/services/secrets/secret.service.d.ts +48 -6
- package/dist/server/services/secrets/secret.service.js +280 -28
- package/dist/server/services/secrets/secret.service.js.map +1 -1
- package/dist/server/services/translations/translation.model.js +2 -1
- package/dist/server/services/translations/translation.model.js.map +1 -1
- package/dist/server/services/translations/translation.service.d.ts +8 -1
- package/dist/server/services/translations/translation.service.js +123 -13
- package/dist/server/services/translations/translation.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -1
|
@@ -11,6 +11,12 @@ const cors = require('cors');
|
|
|
11
11
|
const express = require("express");
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
13
|
const helmet = require('helmet');
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
const compression = require('compression');
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
|
+
const timeout = require('connect-timeout');
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
19
|
+
const responseTime = require('response-time');
|
|
14
20
|
const colors_1 = require("kleur/colors");
|
|
15
21
|
const trpc_to_openapi_1 = require("trpc-to-openapi");
|
|
16
22
|
const consts_1 = require("../consts");
|
|
@@ -19,6 +25,9 @@ const initOpenApiDocs_1 = require("../initOpenApiDocs");
|
|
|
19
25
|
const error_middleware_1 = require("../middleware/error.middleware");
|
|
20
26
|
const logs_middleware_1 = require("../middleware/logs.middleware");
|
|
21
27
|
const trpcError_middleware_1 = require("../middleware/trpcError.middleware");
|
|
28
|
+
const productionError_middleware_1 = require("../middleware/productionError.middleware");
|
|
29
|
+
const memoryMonitor_middleware_1 = require("../middleware/memoryMonitor.middleware");
|
|
30
|
+
const security_middleware_1 = require("../middleware/security.middleware");
|
|
22
31
|
// There is an issue returning the
|
|
23
32
|
// row count in Mysql (bigint) and parsing
|
|
24
33
|
// it back to JSON
|
|
@@ -30,23 +39,133 @@ const trpcError_middleware_1 = require("../middleware/trpcError.middleware");
|
|
|
30
39
|
function getExpressTrpcApp({ trpcRouter, port, expressResources, shouldInitOpenApiDocs, baseUrl = `http://localhost:${port}`, shouldEnableSentry, sentryService, logger = console, customHandlers }) {
|
|
31
40
|
logger.log(`Starting ${consts_1.pkg.name}`);
|
|
32
41
|
const app = express();
|
|
33
|
-
|
|
34
|
-
app.use(
|
|
35
|
-
|
|
42
|
+
// Performance: Enable compression with optimized settings
|
|
43
|
+
app.use(compression({
|
|
44
|
+
// Compression level: 6 provides a good balance between speed and compression ratio
|
|
45
|
+
level: 6,
|
|
46
|
+
// Skip compression for small responses (< 1KB)
|
|
47
|
+
threshold: 1024,
|
|
48
|
+
// Optimize compression buffer sizes for better performance
|
|
49
|
+
chunkSize: 16 * 1024, // 16KB chunks
|
|
50
|
+
memLevel: 8, // Memory usage level (1-9)
|
|
51
|
+
// Custom filter to handle various edge cases
|
|
52
|
+
filter: (req, res) => {
|
|
53
|
+
// Skip compression for already compressed content types
|
|
54
|
+
const contentType = res.getHeader('Content-Type');
|
|
55
|
+
const compressedTypes = [
|
|
56
|
+
'image/', 'audio/', 'video/', 'font/',
|
|
57
|
+
'application/pdf', 'application/zip',
|
|
58
|
+
'application/gzip', 'application/x-gzip',
|
|
59
|
+
'application/x-rar-compressed', 'application/x-7z-compressed',
|
|
60
|
+
'application/vnd.ms-fontobject', 'application/font-woff',
|
|
61
|
+
'application/font-woff2', 'application/x-font-ttf',
|
|
62
|
+
'application/x-font-truetype', 'application/x-font-opentype'
|
|
63
|
+
];
|
|
64
|
+
if (contentType && compressedTypes.some(type => contentType.includes(type))) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
// Skip compression for Server-Sent Events
|
|
68
|
+
if (contentType && contentType.includes('text/event-stream')) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Skip compression for WebSocket upgrade requests
|
|
72
|
+
if (req.headers.upgrade === 'websocket') {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
// Skip compression if Cache-Control contains no-transform directive
|
|
76
|
+
const cacheControl = req.headers['cache-control'] || res.getHeader('Cache-Control');
|
|
77
|
+
if (cacheControl?.includes('no-transform')) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
// Skip compression for HEAD requests
|
|
81
|
+
if (req.method === 'HEAD') {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// Skip compression if response already has Content-Encoding header
|
|
85
|
+
const encoding = res.getHeader('Content-Encoding');
|
|
86
|
+
if (encoding && encoding !== 'identity') {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
// Use the default compression filter for all other cases
|
|
90
|
+
return compression.filter(req, res);
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
// Performance: Add response time header
|
|
94
|
+
app.use(responseTime());
|
|
95
|
+
// Performance: Add memory monitoring middleware
|
|
96
|
+
const { middleware: memoryMiddleware, monitor: memoryMonitor } = (0, memoryMonitor_middleware_1.createMemoryMonitorMiddleware)({
|
|
97
|
+
logger,
|
|
98
|
+
warningThreshold: 90,
|
|
99
|
+
criticalThreshold: 95,
|
|
100
|
+
monitorInterval: 30000, // Check every 30 seconds
|
|
101
|
+
enableGarbageCollection: process.env.NODE_ENV === 'prod', // Only enable GC in production
|
|
102
|
+
addHeaders: process.env.NODE_ENV !== 'prod' // Add headers in non-production environments
|
|
103
|
+
});
|
|
104
|
+
app.use(memoryMiddleware);
|
|
105
|
+
// Security: Configure CORS with proper settings
|
|
106
|
+
app.use(cors((0, security_middleware_1.getCorsOptions)()));
|
|
107
|
+
// Security: Configure Helmet with enhanced settings
|
|
108
|
+
app.use(helmet((0, security_middleware_1.getHelmetOptions)()));
|
|
109
|
+
// Security: Additional security headers
|
|
110
|
+
app.use((0, security_middleware_1.additionalSecurityHeaders)());
|
|
111
|
+
// Security: Add request timeout (30 seconds default)
|
|
112
|
+
app.use(timeout(process.env.REQUEST_TIMEOUT || '30s'));
|
|
113
|
+
app.use((req, _res, next) => {
|
|
114
|
+
if (!req.timedout)
|
|
115
|
+
next();
|
|
116
|
+
});
|
|
117
|
+
// Security: Rate limiting - global
|
|
118
|
+
app.use((0, security_middleware_1.createRateLimiter)());
|
|
119
|
+
// Security: Stricter rate limiting for auth endpoints
|
|
120
|
+
app.use((req, res, next) => {
|
|
121
|
+
if (req.path.startsWith('/trpc/auth') || req.path.startsWith('/api/auth')) {
|
|
122
|
+
(0, security_middleware_1.createAuthRateLimiter)()(req, res, next);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
next();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
// Security: API rate limiting
|
|
129
|
+
app.use('/trpc/', (0, security_middleware_1.createApiRateLimiter)());
|
|
130
|
+
app.use('/api/', (0, security_middleware_1.createApiRateLimiter)());
|
|
131
|
+
// Enable ETags for better caching
|
|
132
|
+
app.set('etag', 'strong');
|
|
36
133
|
app.set('trust proxy', true);
|
|
37
134
|
if (shouldEnableSentry) {
|
|
38
135
|
Sentry.setupExpressErrorHandler(app);
|
|
39
136
|
}
|
|
40
|
-
|
|
41
|
-
|
|
137
|
+
// Configure body parsing with security limits
|
|
138
|
+
const jsonLimit = process.env.JSON_BODY_LIMIT || '100kb';
|
|
139
|
+
const urlEncodedLimit = process.env.URL_ENCODED_LIMIT || '100kb';
|
|
140
|
+
const rawLimit = process.env.RAW_BODY_LIMIT || '100kb';
|
|
141
|
+
app.use(express.json({
|
|
142
|
+
limit: jsonLimit,
|
|
143
|
+
type: ['application/json', 'text/plain'],
|
|
144
|
+
verify: (req, res, buf) => {
|
|
145
|
+
// Store raw body for webhook signature verification if needed
|
|
146
|
+
req.rawBody = buf.toString('utf8');
|
|
147
|
+
}
|
|
148
|
+
}));
|
|
149
|
+
app.use(express.urlencoded({ limit: urlEncodedLimit, extended: true }));
|
|
42
150
|
app.use(express.raw({
|
|
43
151
|
inflate: true,
|
|
44
|
-
limit:
|
|
152
|
+
limit: rawLimit
|
|
45
153
|
}));
|
|
154
|
+
// Add cache headers for static content
|
|
155
|
+
app.use((req, res, next) => {
|
|
156
|
+
if (req.url.match(/\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$/)) {
|
|
157
|
+
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
|
158
|
+
}
|
|
159
|
+
next();
|
|
160
|
+
});
|
|
46
161
|
app.use((req, resp, next) => (0, logs_middleware_1.expressRequestLogger)(req, resp, next, logger));
|
|
47
162
|
app.use((0, error_middleware_1.genericErrorMiddleware)({
|
|
48
163
|
sentryService: shouldEnableSentry ? sentryService : undefined
|
|
49
164
|
}));
|
|
165
|
+
// Add production error handler for sanitized error responses
|
|
166
|
+
if (process.env.NODE_ENV === 'prod') {
|
|
167
|
+
app.use((0, productionError_middleware_1.productionErrorHandler)());
|
|
168
|
+
}
|
|
50
169
|
customHandlers?.forEach(customHandler => {
|
|
51
170
|
app.use(customHandler);
|
|
52
171
|
});
|
|
@@ -82,20 +201,105 @@ function getExpressTrpcApp({ trpcRouter, port, expressResources, shouldInitOpenA
|
|
|
82
201
|
});
|
|
83
202
|
app.set('view engine', 'ejs');
|
|
84
203
|
app.set('views', [(0, path_1.join)(__dirname, './api/posts/views')]);
|
|
204
|
+
// Health check endpoints
|
|
205
|
+
app.get('/health', (req, res) => {
|
|
206
|
+
const memoryUsage = process.memoryUsage();
|
|
207
|
+
const lastMetrics = memoryMonitor.getLastMetrics();
|
|
208
|
+
res.json({
|
|
209
|
+
status: 'ok',
|
|
210
|
+
timestamp: new Date().toISOString(),
|
|
211
|
+
service: consts_1.pkg.name,
|
|
212
|
+
version: consts_1.pkg.version,
|
|
213
|
+
uptime: process.uptime(),
|
|
214
|
+
memory: {
|
|
215
|
+
used: js_utils_1.Units.humanByteSize(memoryUsage.heapUsed),
|
|
216
|
+
total: js_utils_1.Units.humanByteSize(memoryUsage.heapTotal),
|
|
217
|
+
percentage: lastMetrics ? lastMetrics.heapUsedPercentage.toFixed(1) + '%' : 'N/A',
|
|
218
|
+
rss: js_utils_1.Units.humanByteSize(memoryUsage.rss),
|
|
219
|
+
external: js_utils_1.Units.humanByteSize(memoryUsage.external),
|
|
220
|
+
monitoring: {
|
|
221
|
+
lastCheck: lastMetrics ? new Date(lastMetrics.timestamp).toISOString() : 'N/A',
|
|
222
|
+
warningThreshold: '90%',
|
|
223
|
+
criticalThreshold: '95%'
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
// Readiness check endpoint
|
|
229
|
+
app.get('/ready', async (req, res) => {
|
|
230
|
+
try {
|
|
231
|
+
// Add your readiness checks here
|
|
232
|
+
// For example: check database connection, external services, etc.
|
|
233
|
+
const checks = {
|
|
234
|
+
service: 'ready',
|
|
235
|
+
timestamp: new Date().toISOString()
|
|
236
|
+
};
|
|
237
|
+
res.json(checks);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
res.status(503).json({
|
|
241
|
+
status: 'not ready',
|
|
242
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
});
|
|
85
246
|
/**
|
|
86
|
-
* Start the app
|
|
247
|
+
* Start the app with graceful shutdown support
|
|
87
248
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
249
|
+
let server;
|
|
250
|
+
// Don't start server in test environment
|
|
251
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
252
|
+
if (process.env.K_SERVICE) {
|
|
253
|
+
server = app.listen(port, '0.0.0.0');
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
server = app.listen(port, '::');
|
|
257
|
+
}
|
|
90
258
|
}
|
|
91
|
-
|
|
92
|
-
|
|
259
|
+
// Graceful shutdown handler
|
|
260
|
+
const gracefulShutdown = () => {
|
|
261
|
+
logger.log('SIGTERM signal received: closing HTTP server');
|
|
262
|
+
// Stop memory monitoring
|
|
263
|
+
memoryMonitor.stopMonitoring();
|
|
264
|
+
if (server) {
|
|
265
|
+
server.close(() => {
|
|
266
|
+
logger.log('HTTP server closed');
|
|
267
|
+
// Perform cleanup tasks here
|
|
268
|
+
// Close database connections, message queues, etc.
|
|
269
|
+
process.exit(0);
|
|
270
|
+
});
|
|
271
|
+
// Force shutdown after 30 seconds
|
|
272
|
+
setTimeout(() => {
|
|
273
|
+
logger.error('Could not close connections in time, forcefully shutting down');
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}, 30000);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
// Only add process listeners if server was started (not in test env)
|
|
279
|
+
if (server) {
|
|
280
|
+
// Listen for termination signals
|
|
281
|
+
process.once('SIGTERM', gracefulShutdown);
|
|
282
|
+
process.once('SIGINT', gracefulShutdown);
|
|
283
|
+
// Handle uncaught errors
|
|
284
|
+
process.once('uncaughtException', (error) => {
|
|
285
|
+
logger.error('Uncaught Exception:', error);
|
|
286
|
+
if (shouldEnableSentry && sentryService) {
|
|
287
|
+
Sentry.captureException(error);
|
|
288
|
+
}
|
|
289
|
+
gracefulShutdown();
|
|
290
|
+
});
|
|
291
|
+
process.on('unhandledRejection', (reason, _promise) => {
|
|
292
|
+
logger.error('Unhandled Rejection at:', _promise, 'reason:', reason);
|
|
293
|
+
if (shouldEnableSentry && sentryService) {
|
|
294
|
+
Sentry.captureException(reason);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
93
297
|
}
|
|
94
298
|
const address = `http://localhost:${port}`;
|
|
95
299
|
const used = js_utils_1.Units.humanByteSize(process.memoryUsage().heapUsed);
|
|
96
300
|
console.log(`App Local Url:
|
|
97
301
|
${(0, colors_1.yellow)(address)}
|
|
98
302
|
in ${js_utils_1.Time.ms(process.uptime() * 1000)}, used ${used}`);
|
|
99
|
-
return app;
|
|
303
|
+
return { app, server };
|
|
100
304
|
}
|
|
101
305
|
//# sourceMappingURL=getExpressTrpcApp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getExpressTrpcApp.js","sourceRoot":"","sources":["../../../src/server/bootstraps/getExpressTrpcApp.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"getExpressTrpcApp.js","sourceRoot":"","sources":["../../../src/server/bootstraps/getExpressTrpcApp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// npx ts-node ./src/server/middleware/memoryMonitor.example.ts
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
/**
|
|
5
|
+
* Example demonstrating memory monitoring middleware capabilities
|
|
6
|
+
*
|
|
7
|
+
* This example shows:
|
|
8
|
+
* 1. How memory monitoring tracks heap usage
|
|
9
|
+
* 2. Warning and critical threshold alerts
|
|
10
|
+
* 3. Memory metrics in response headers
|
|
11
|
+
* 4. Automatic garbage collection triggers (when available)
|
|
12
|
+
*
|
|
13
|
+
* To run with garbage collection enabled:
|
|
14
|
+
* node --expose-gc -r ts-node/register ./src/server/middleware/memoryMonitor.example.ts
|
|
15
|
+
*/
|
|
16
|
+
const express_1 = require("express");
|
|
17
|
+
const memoryMonitor_middleware_1 = require("./memoryMonitor.middleware");
|
|
18
|
+
const app = (0, express_1.default)();
|
|
19
|
+
const port = 3001;
|
|
20
|
+
// Create memory monitor with aggressive thresholds for demo
|
|
21
|
+
const { middleware: memoryMiddleware, monitor } = (0, memoryMonitor_middleware_1.createMemoryMonitorMiddleware)({
|
|
22
|
+
warningThreshold: 70, // Warn at 70% heap usage
|
|
23
|
+
criticalThreshold: 85, // Critical at 85% heap usage
|
|
24
|
+
monitorInterval: 5000, // Check every 5 seconds
|
|
25
|
+
enableGarbageCollection: true,
|
|
26
|
+
addHeaders: true // Add memory info to response headers
|
|
27
|
+
});
|
|
28
|
+
app.use(memoryMiddleware);
|
|
29
|
+
// Endpoint to check current memory status
|
|
30
|
+
app.get('/memory-status', (req, res) => {
|
|
31
|
+
const metrics = monitor.getLastMetrics();
|
|
32
|
+
const memUsage = process.memoryUsage();
|
|
33
|
+
res.json({
|
|
34
|
+
current: {
|
|
35
|
+
heapUsedMB: (memUsage.heapUsed / (1024 * 1024)).toFixed(2),
|
|
36
|
+
heapTotalMB: (memUsage.heapTotal / (1024 * 1024)).toFixed(2),
|
|
37
|
+
heapUsedPercent: ((memUsage.heapUsed / memUsage.heapTotal) * 100).toFixed(1),
|
|
38
|
+
rssMB: (memUsage.rss / (1024 * 1024)).toFixed(2)
|
|
39
|
+
},
|
|
40
|
+
lastMonitored: metrics ? {
|
|
41
|
+
heapUsedMB: metrics.heapUsedMB.toFixed(2),
|
|
42
|
+
heapTotalMB: metrics.heapTotalMB.toFixed(2),
|
|
43
|
+
heapUsedPercent: metrics.heapUsedPercentage.toFixed(1),
|
|
44
|
+
timestamp: new Date(metrics.timestamp).toISOString()
|
|
45
|
+
} : null,
|
|
46
|
+
thresholds: {
|
|
47
|
+
warning: '70%',
|
|
48
|
+
critical: '85%'
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
// Endpoint to simulate memory leak (for testing)
|
|
53
|
+
let leakedData = [];
|
|
54
|
+
app.get('/leak-memory', (req, res) => {
|
|
55
|
+
// Allocate 10MB of memory
|
|
56
|
+
const size = 10 * 1024 * 1024;
|
|
57
|
+
const buffer = Buffer.alloc(size);
|
|
58
|
+
leakedData.push(buffer);
|
|
59
|
+
res.json({
|
|
60
|
+
message: 'Allocated 10MB',
|
|
61
|
+
totalLeaked: `${leakedData.length * 10}MB`,
|
|
62
|
+
currentHeapMB: (process.memoryUsage().heapUsed / (1024 * 1024)).toFixed(2)
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
// Endpoint to clear leaked memory
|
|
66
|
+
app.get('/clear-memory', (req, res) => {
|
|
67
|
+
const beforeMB = (process.memoryUsage().heapUsed / (1024 * 1024)).toFixed(2);
|
|
68
|
+
leakedData = [];
|
|
69
|
+
// Force garbage collection if available
|
|
70
|
+
if (global.gc) {
|
|
71
|
+
global.gc();
|
|
72
|
+
}
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
const afterMB = (process.memoryUsage().heapUsed / (1024 * 1024)).toFixed(2);
|
|
75
|
+
res.json({
|
|
76
|
+
message: 'Memory cleared',
|
|
77
|
+
beforeMB,
|
|
78
|
+
afterMB,
|
|
79
|
+
freedMB: (parseFloat(beforeMB) - parseFloat(afterMB)).toFixed(2)
|
|
80
|
+
});
|
|
81
|
+
}, 100);
|
|
82
|
+
});
|
|
83
|
+
// Health endpoint showing memory in response
|
|
84
|
+
app.get('/health', (req, res) => {
|
|
85
|
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
86
|
+
});
|
|
87
|
+
const server = app.listen(port, () => {
|
|
88
|
+
console.log(`Memory monitoring example server running at http://localhost:${port}`);
|
|
89
|
+
console.log('\nEndpoints:');
|
|
90
|
+
console.log(' GET /memory-status - Check current memory usage');
|
|
91
|
+
console.log(' GET /leak-memory - Simulate memory leak (allocates 10MB)');
|
|
92
|
+
console.log(' GET /clear-memory - Clear leaked memory');
|
|
93
|
+
console.log(' GET /health - Health check (see memory headers)');
|
|
94
|
+
console.log('\nMemory headers added to all responses:');
|
|
95
|
+
console.log(' X-Memory-Heap-Used-MB');
|
|
96
|
+
console.log(' X-Memory-Heap-Total-MB');
|
|
97
|
+
console.log(' X-Memory-Heap-Used-Percent');
|
|
98
|
+
console.log(' X-Memory-RSS-MB');
|
|
99
|
+
console.log('\nWatch the console for memory warnings/alerts!');
|
|
100
|
+
});
|
|
101
|
+
// Graceful shutdown
|
|
102
|
+
process.on('SIGTERM', () => {
|
|
103
|
+
monitor.stopMonitoring();
|
|
104
|
+
server.close(() => {
|
|
105
|
+
console.log('Server closed');
|
|
106
|
+
process.exit(0);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=memoryMonitor.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoryMonitor.example.js","sourceRoot":"","sources":["../../../src/server/middleware/memoryMonitor.example.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { CommonLogger } from '@goatlab/js-utils';
|
|
3
|
+
interface MemoryMonitorOptions {
|
|
4
|
+
logger?: CommonLogger;
|
|
5
|
+
warningThreshold?: number;
|
|
6
|
+
criticalThreshold?: number;
|
|
7
|
+
monitorInterval?: number;
|
|
8
|
+
enableGarbageCollection?: boolean;
|
|
9
|
+
addHeaders?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface MemoryMetrics {
|
|
12
|
+
heapUsedMB: number;
|
|
13
|
+
heapTotalMB: number;
|
|
14
|
+
heapUsedPercentage: number;
|
|
15
|
+
rssMB: number;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
}
|
|
18
|
+
declare class MemoryMonitor {
|
|
19
|
+
private logger;
|
|
20
|
+
private warningThreshold;
|
|
21
|
+
private criticalThreshold;
|
|
22
|
+
private monitorInterval;
|
|
23
|
+
private enableGarbageCollection;
|
|
24
|
+
private addHeaders;
|
|
25
|
+
private intervalTimer?;
|
|
26
|
+
private lastMetrics?;
|
|
27
|
+
private gcAvailable;
|
|
28
|
+
constructor(options?: MemoryMonitorOptions);
|
|
29
|
+
private getMemoryMetrics;
|
|
30
|
+
private formatMemoryMetrics;
|
|
31
|
+
private checkMemoryUsage;
|
|
32
|
+
startMonitoring(): void;
|
|
33
|
+
stopMonitoring(): void;
|
|
34
|
+
middleware(): (_req: Request, res: Response, next: NextFunction) => void;
|
|
35
|
+
getLastMetrics(): MemoryMetrics | undefined;
|
|
36
|
+
}
|
|
37
|
+
export declare function createMemoryMonitorMiddleware(options?: MemoryMonitorOptions): {
|
|
38
|
+
middleware: (req: Request, res: Response, next: NextFunction) => void;
|
|
39
|
+
monitor: MemoryMonitor;
|
|
40
|
+
};
|
|
41
|
+
export declare function memoryMonitorMiddleware(options?: MemoryMonitorOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// npx vitest run ./src/server/middleware/memoryMonitor.middleware.test.ts
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.createMemoryMonitorMiddleware = createMemoryMonitorMiddleware;
|
|
5
|
+
exports.memoryMonitorMiddleware = memoryMonitorMiddleware;
|
|
6
|
+
const colors_1 = require("kleur/colors");
|
|
7
|
+
class MemoryMonitor {
|
|
8
|
+
logger;
|
|
9
|
+
warningThreshold;
|
|
10
|
+
criticalThreshold;
|
|
11
|
+
monitorInterval;
|
|
12
|
+
enableGarbageCollection;
|
|
13
|
+
addHeaders;
|
|
14
|
+
intervalTimer;
|
|
15
|
+
lastMetrics;
|
|
16
|
+
gcAvailable;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.logger = options.logger || console;
|
|
19
|
+
this.warningThreshold = options.warningThreshold || 90;
|
|
20
|
+
this.criticalThreshold = options.criticalThreshold || 95;
|
|
21
|
+
this.monitorInterval = options.monitorInterval || 30000; // 30 seconds default
|
|
22
|
+
this.enableGarbageCollection = options.enableGarbageCollection !== false;
|
|
23
|
+
this.addHeaders = options.addHeaders !== false;
|
|
24
|
+
// Check if garbage collection is available
|
|
25
|
+
this.gcAvailable = typeof global.gc === 'function';
|
|
26
|
+
if (this.enableGarbageCollection && !this.gcAvailable) {
|
|
27
|
+
this.logger.warn('Garbage collection is not available. Run node with --expose-gc flag to enable.');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
getMemoryMetrics() {
|
|
31
|
+
const memUsage = process.memoryUsage();
|
|
32
|
+
const heapUsedMB = memUsage.heapUsed / (1024 * 1024);
|
|
33
|
+
const heapTotalMB = memUsage.heapTotal / (1024 * 1024);
|
|
34
|
+
const heapUsedPercentage = (memUsage.heapUsed / memUsage.heapTotal) * 100;
|
|
35
|
+
const rssMB = memUsage.rss / (1024 * 1024);
|
|
36
|
+
return {
|
|
37
|
+
heapUsedMB,
|
|
38
|
+
heapTotalMB,
|
|
39
|
+
heapUsedPercentage,
|
|
40
|
+
rssMB,
|
|
41
|
+
timestamp: Date.now()
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
formatMemoryMetrics(metrics) {
|
|
45
|
+
return `Heap: ${metrics.heapUsedMB.toFixed(2)}/${metrics.heapTotalMB.toFixed(2)}MB (${metrics.heapUsedPercentage.toFixed(1)}%) | RSS: ${metrics.rssMB.toFixed(2)}MB`;
|
|
46
|
+
}
|
|
47
|
+
checkMemoryUsage(metrics) {
|
|
48
|
+
const { heapUsedPercentage } = metrics;
|
|
49
|
+
if (heapUsedPercentage >= this.criticalThreshold) {
|
|
50
|
+
this.logger.error((0, colors_1.red)(`CRITICAL: Memory usage at ${heapUsedPercentage.toFixed(1)}% - ${this.formatMemoryMetrics(metrics)}`));
|
|
51
|
+
// Attempt garbage collection if available and enabled
|
|
52
|
+
if (this.enableGarbageCollection && this.gcAvailable) {
|
|
53
|
+
this.logger.warn('Triggering garbage collection due to critical memory usage');
|
|
54
|
+
global.gc();
|
|
55
|
+
// Log memory after GC
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
const afterGcMetrics = this.getMemoryMetrics();
|
|
58
|
+
this.logger.log(`Memory after GC: ${this.formatMemoryMetrics(afterGcMetrics)}`);
|
|
59
|
+
}, 100);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else if (heapUsedPercentage >= this.warningThreshold) {
|
|
63
|
+
this.logger.warn((0, colors_1.yellow)(`WARNING: Memory usage at ${heapUsedPercentage.toFixed(1)}% - ${this.formatMemoryMetrics(metrics)}`));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
startMonitoring() {
|
|
67
|
+
if (this.intervalTimer) {
|
|
68
|
+
return; // Already monitoring
|
|
69
|
+
}
|
|
70
|
+
// Initial check
|
|
71
|
+
const initialMetrics = this.getMemoryMetrics();
|
|
72
|
+
this.logger.log(`Memory monitoring started - ${this.formatMemoryMetrics(initialMetrics)}`);
|
|
73
|
+
this.intervalTimer = setInterval(() => {
|
|
74
|
+
const metrics = this.getMemoryMetrics();
|
|
75
|
+
this.lastMetrics = metrics;
|
|
76
|
+
this.checkMemoryUsage(metrics);
|
|
77
|
+
}, this.monitorInterval);
|
|
78
|
+
// Ensure timer doesn't prevent process from exiting
|
|
79
|
+
this.intervalTimer.unref();
|
|
80
|
+
}
|
|
81
|
+
stopMonitoring() {
|
|
82
|
+
if (this.intervalTimer) {
|
|
83
|
+
clearInterval(this.intervalTimer);
|
|
84
|
+
this.intervalTimer = undefined;
|
|
85
|
+
this.logger.log('Memory monitoring stopped');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
middleware() {
|
|
89
|
+
return (_req, res, next) => {
|
|
90
|
+
const metrics = this.getMemoryMetrics();
|
|
91
|
+
this.lastMetrics = metrics;
|
|
92
|
+
// Add memory metrics to response headers if enabled
|
|
93
|
+
if (this.addHeaders) {
|
|
94
|
+
res.setHeader('X-Memory-Heap-Used-MB', metrics.heapUsedMB.toFixed(2));
|
|
95
|
+
res.setHeader('X-Memory-Heap-Total-MB', metrics.heapTotalMB.toFixed(2));
|
|
96
|
+
res.setHeader('X-Memory-Heap-Used-Percent', metrics.heapUsedPercentage.toFixed(1));
|
|
97
|
+
res.setHeader('X-Memory-RSS-MB', metrics.rssMB.toFixed(2));
|
|
98
|
+
}
|
|
99
|
+
// Check memory usage on each request
|
|
100
|
+
this.checkMemoryUsage(metrics);
|
|
101
|
+
next();
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
getLastMetrics() {
|
|
105
|
+
return this.lastMetrics;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Track if we've already added process listeners
|
|
109
|
+
let processListenersAdded = false;
|
|
110
|
+
// Factory function to create memory monitor middleware
|
|
111
|
+
function createMemoryMonitorMiddleware(options) {
|
|
112
|
+
const monitor = new MemoryMonitor(options);
|
|
113
|
+
// Start background monitoring
|
|
114
|
+
monitor.startMonitoring();
|
|
115
|
+
// Handle graceful shutdown - only add listeners once globally
|
|
116
|
+
if (!processListenersAdded && process.env.NODE_ENV !== 'test') {
|
|
117
|
+
processListenersAdded = true;
|
|
118
|
+
const cleanup = () => {
|
|
119
|
+
monitor.stopMonitoring();
|
|
120
|
+
};
|
|
121
|
+
process.once('SIGTERM', cleanup);
|
|
122
|
+
process.once('SIGINT', cleanup);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
middleware: monitor.middleware(),
|
|
126
|
+
monitor
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Convenience middleware function for simple usage
|
|
130
|
+
function memoryMonitorMiddleware(options) {
|
|
131
|
+
const { middleware } = createMemoryMonitorMiddleware(options);
|
|
132
|
+
return middleware;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=memoryMonitor.middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoryMonitor.middleware.js","sourceRoot":"","sources":["../../../src/server/middleware/memoryMonitor.middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import type { HttpError, HttpErrorData } from '@goatlab/js-utils';
|
|
3
|
+
/**
|
|
4
|
+
* Sanitize error messages for production environment
|
|
5
|
+
* Prevents leaking sensitive information in error responses
|
|
6
|
+
*/
|
|
7
|
+
export declare function sanitizeErrorForProduction(error: HttpError<HttpErrorData>): HttpError<HttpErrorData>;
|
|
8
|
+
/**
|
|
9
|
+
* Production-ready error handler middleware
|
|
10
|
+
* Ensures no sensitive information is leaked in error responses
|
|
11
|
+
*/
|
|
12
|
+
export declare function productionErrorHandler(): (err: any, req: Request, res: Response, next: NextFunction) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Async error wrapper to catch errors in async route handlers
|
|
15
|
+
*/
|
|
16
|
+
export declare function asyncErrorHandler(fn: Function): (req: Request, res: Response, next: NextFunction) => void;
|