@tumbaland/backend-core 1.16.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/.versionrc.json +7 -0
- package/README.md +179 -0
- package/__mocks__/uuid.js +8 -0
- package/dist/app/createBaseApp.d.ts +44 -0
- package/dist/app/createBaseApp.d.ts.map +1 -0
- package/dist/app/createBaseApp.js +54 -0
- package/dist/app/createBaseApp.js.map +1 -0
- package/dist/config/env.d.ts +8 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +17 -0
- package/dist/config/env.js.map +1 -0
- package/dist/database/connection.d.ts +3 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +49 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/errors/HttpError.d.ts +32 -0
- package/dist/errors/HttpError.d.ts.map +1 -0
- package/dist/errors/HttpError.js +61 -0
- package/dist/errors/HttpError.js.map +1 -0
- package/dist/health/healthController.d.ts +21 -0
- package/dist/health/healthController.d.ts.map +1 -0
- package/dist/health/healthController.js +56 -0
- package/dist/health/healthController.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +81 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/logger.d.ts +4 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +78 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/metrics/index.d.ts +17 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +99 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/middleware/authMiddleware.d.ts +9 -0
- package/dist/middleware/authMiddleware.d.ts.map +1 -0
- package/dist/middleware/authMiddleware.js +32 -0
- package/dist/middleware/authMiddleware.js.map +1 -0
- package/dist/middleware/corsMiddleware.d.ts +20 -0
- package/dist/middleware/corsMiddleware.d.ts.map +1 -0
- package/dist/middleware/corsMiddleware.js +33 -0
- package/dist/middleware/corsMiddleware.js.map +1 -0
- package/dist/middleware/errorHandler.d.ts +14 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +88 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/requestLogger.d.ts +16 -0
- package/dist/middleware/requestLogger.d.ts.map +1 -0
- package/dist/middleware/requestLogger.js +49 -0
- package/dist/middleware/requestLogger.js.map +1 -0
- package/dist/middleware/security.d.ts +26 -0
- package/dist/middleware/security.d.ts.map +1 -0
- package/dist/middleware/security.js +47 -0
- package/dist/middleware/security.js.map +1 -0
- package/dist/middleware/validate.d.ts +11 -0
- package/dist/middleware/validate.d.ts.map +1 -0
- package/dist/middleware/validate.js +24 -0
- package/dist/middleware/validate.js.map +1 -0
- package/dist/tracing/index.d.ts +13 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +89 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/types/auth.d.ts +32 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +3 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/utils/correlation.d.ts +11 -0
- package/dist/utils/correlation.d.ts.map +1 -0
- package/dist/utils/correlation.js +23 -0
- package/dist/utils/correlation.js.map +1 -0
- package/dist/utils/response.d.ts +24 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +35 -0
- package/dist/utils/response.js.map +1 -0
- package/jest.config.js +14 -0
- package/package.json +61 -0
- package/src/app/createBaseApp.test.ts +69 -0
- package/src/app/createBaseApp.ts +75 -0
- package/src/config/env.test.ts +28 -0
- package/src/config/env.ts +13 -0
- package/src/database/connection.test.ts +142 -0
- package/src/database/connection.ts +46 -0
- package/src/errors/HttpError.test.ts +38 -0
- package/src/errors/HttpError.ts +57 -0
- package/src/health/healthController.test.ts +91 -0
- package/src/health/healthController.ts +56 -0
- package/src/index.ts +60 -0
- package/src/logging/logger.test.ts +76 -0
- package/src/logging/logger.ts +103 -0
- package/src/metrics/index.test.ts +91 -0
- package/src/metrics/index.ts +110 -0
- package/src/middleware/authMiddleware.test.ts +104 -0
- package/src/middleware/authMiddleware.ts +29 -0
- package/src/middleware/corsMiddleware.test.ts +58 -0
- package/src/middleware/corsMiddleware.ts +36 -0
- package/src/middleware/errorHandler.test.ts +146 -0
- package/src/middleware/errorHandler.ts +98 -0
- package/src/middleware/requestLogger.test.ts +81 -0
- package/src/middleware/requestLogger.ts +47 -0
- package/src/middleware/security.test.ts +45 -0
- package/src/middleware/security.ts +43 -0
- package/src/middleware/validate.test.ts +60 -0
- package/src/middleware/validate.ts +23 -0
- package/src/tracing/index.test.ts +250 -0
- package/src/tracing/index.ts +97 -0
- package/src/types/auth.ts +33 -0
- package/src/utils/correlation.test.ts +47 -0
- package/src/utils/correlation.ts +22 -0
- package/src/utils/response.test.ts +64 -0
- package/src/utils/response.ts +60 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +20 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @tumbaland/backend-core - Core shared functionality for Tumbaland backend services
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.extractSpanContext = exports.injectHeaders = exports.setSpanTag = exports.logToSpan = exports.createChildSpan = exports.tracingMiddleware = exports.startSpan = exports.getTracer = exports.initTracer = exports.register = exports.businessMetrics = exports.databaseQueriesTotal = exports.databaseQueryDuration = exports.httpRequestsTotal = exports.httpRequestDuration = exports.metricsMiddleware = exports.sendError = exports.sendSuccess = exports.createApiResponse = exports.correlationMiddleware = exports.generateCorrelationId = exports.validate = exports.strictRateLimiter = exports.standardRateLimiter = exports.createRateLimiter = exports.securityHeaders = exports.simpleRequestLogger = exports.requestLoggerWithMetrics = exports.requestLogger = exports.errorHandler = exports.createCorsMiddleware = exports.authenticateToken = exports.TooManyRequestsError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.HttpError = exports.requireEnv = exports.disconnectDB = exports.connectDB = exports.metricsHandler = exports.healthLive = exports.healthCheck = exports.logger = exports.createBaseApp = void 0;
|
|
8
|
+
// App bootstrap
|
|
9
|
+
var createBaseApp_1 = require("./app/createBaseApp");
|
|
10
|
+
Object.defineProperty(exports, "createBaseApp", { enumerable: true, get: function () { return createBaseApp_1.createBaseApp; } });
|
|
11
|
+
// Logging
|
|
12
|
+
var logger_1 = require("./logging/logger");
|
|
13
|
+
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return __importDefault(logger_1).default; } });
|
|
14
|
+
// Health checks
|
|
15
|
+
var healthController_1 = require("./health/healthController");
|
|
16
|
+
Object.defineProperty(exports, "healthCheck", { enumerable: true, get: function () { return healthController_1.healthCheck; } });
|
|
17
|
+
Object.defineProperty(exports, "healthLive", { enumerable: true, get: function () { return healthController_1.healthLive; } });
|
|
18
|
+
Object.defineProperty(exports, "metricsHandler", { enumerable: true, get: function () { return healthController_1.metricsHandler; } });
|
|
19
|
+
// Database
|
|
20
|
+
var connection_1 = require("./database/connection");
|
|
21
|
+
Object.defineProperty(exports, "connectDB", { enumerable: true, get: function () { return connection_1.connectDB; } });
|
|
22
|
+
Object.defineProperty(exports, "disconnectDB", { enumerable: true, get: function () { return connection_1.disconnectDB; } });
|
|
23
|
+
// Config
|
|
24
|
+
var env_1 = require("./config/env");
|
|
25
|
+
Object.defineProperty(exports, "requireEnv", { enumerable: true, get: function () { return env_1.requireEnv; } });
|
|
26
|
+
// Errors
|
|
27
|
+
var HttpError_1 = require("./errors/HttpError");
|
|
28
|
+
Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return HttpError_1.HttpError; } });
|
|
29
|
+
Object.defineProperty(exports, "BadRequestError", { enumerable: true, get: function () { return HttpError_1.BadRequestError; } });
|
|
30
|
+
Object.defineProperty(exports, "UnauthorizedError", { enumerable: true, get: function () { return HttpError_1.UnauthorizedError; } });
|
|
31
|
+
Object.defineProperty(exports, "ForbiddenError", { enumerable: true, get: function () { return HttpError_1.ForbiddenError; } });
|
|
32
|
+
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return HttpError_1.NotFoundError; } });
|
|
33
|
+
Object.defineProperty(exports, "ConflictError", { enumerable: true, get: function () { return HttpError_1.ConflictError; } });
|
|
34
|
+
Object.defineProperty(exports, "TooManyRequestsError", { enumerable: true, get: function () { return HttpError_1.TooManyRequestsError; } });
|
|
35
|
+
// Middleware
|
|
36
|
+
var authMiddleware_1 = require("./middleware/authMiddleware");
|
|
37
|
+
Object.defineProperty(exports, "authenticateToken", { enumerable: true, get: function () { return authMiddleware_1.authenticateToken; } });
|
|
38
|
+
var corsMiddleware_1 = require("./middleware/corsMiddleware");
|
|
39
|
+
Object.defineProperty(exports, "createCorsMiddleware", { enumerable: true, get: function () { return corsMiddleware_1.createCorsMiddleware; } });
|
|
40
|
+
var errorHandler_1 = require("./middleware/errorHandler");
|
|
41
|
+
Object.defineProperty(exports, "errorHandler", { enumerable: true, get: function () { return errorHandler_1.errorHandler; } });
|
|
42
|
+
var requestLogger_1 = require("./middleware/requestLogger");
|
|
43
|
+
Object.defineProperty(exports, "requestLogger", { enumerable: true, get: function () { return requestLogger_1.requestLogger; } });
|
|
44
|
+
Object.defineProperty(exports, "requestLoggerWithMetrics", { enumerable: true, get: function () { return requestLogger_1.requestLoggerWithMetrics; } });
|
|
45
|
+
Object.defineProperty(exports, "simpleRequestLogger", { enumerable: true, get: function () { return requestLogger_1.simpleRequestLogger; } });
|
|
46
|
+
var security_1 = require("./middleware/security");
|
|
47
|
+
Object.defineProperty(exports, "securityHeaders", { enumerable: true, get: function () { return security_1.securityHeaders; } });
|
|
48
|
+
Object.defineProperty(exports, "createRateLimiter", { enumerable: true, get: function () { return security_1.createRateLimiter; } });
|
|
49
|
+
Object.defineProperty(exports, "standardRateLimiter", { enumerable: true, get: function () { return security_1.standardRateLimiter; } });
|
|
50
|
+
Object.defineProperty(exports, "strictRateLimiter", { enumerable: true, get: function () { return security_1.strictRateLimiter; } });
|
|
51
|
+
var validate_1 = require("./middleware/validate");
|
|
52
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_1.validate; } });
|
|
53
|
+
// Utils
|
|
54
|
+
var correlation_1 = require("./utils/correlation");
|
|
55
|
+
Object.defineProperty(exports, "generateCorrelationId", { enumerable: true, get: function () { return correlation_1.generateCorrelationId; } });
|
|
56
|
+
Object.defineProperty(exports, "correlationMiddleware", { enumerable: true, get: function () { return correlation_1.correlationMiddleware; } });
|
|
57
|
+
var response_1 = require("./utils/response");
|
|
58
|
+
Object.defineProperty(exports, "createApiResponse", { enumerable: true, get: function () { return response_1.createApiResponse; } });
|
|
59
|
+
Object.defineProperty(exports, "sendSuccess", { enumerable: true, get: function () { return response_1.sendSuccess; } });
|
|
60
|
+
Object.defineProperty(exports, "sendError", { enumerable: true, get: function () { return response_1.sendError; } });
|
|
61
|
+
// Metrics
|
|
62
|
+
var metrics_1 = require("./metrics");
|
|
63
|
+
Object.defineProperty(exports, "metricsMiddleware", { enumerable: true, get: function () { return metrics_1.metricsMiddleware; } });
|
|
64
|
+
Object.defineProperty(exports, "httpRequestDuration", { enumerable: true, get: function () { return metrics_1.httpRequestDuration; } });
|
|
65
|
+
Object.defineProperty(exports, "httpRequestsTotal", { enumerable: true, get: function () { return metrics_1.httpRequestsTotal; } });
|
|
66
|
+
Object.defineProperty(exports, "databaseQueryDuration", { enumerable: true, get: function () { return metrics_1.databaseQueryDuration; } });
|
|
67
|
+
Object.defineProperty(exports, "databaseQueriesTotal", { enumerable: true, get: function () { return metrics_1.databaseQueriesTotal; } });
|
|
68
|
+
Object.defineProperty(exports, "businessMetrics", { enumerable: true, get: function () { return metrics_1.businessMetrics; } });
|
|
69
|
+
Object.defineProperty(exports, "register", { enumerable: true, get: function () { return metrics_1.register; } });
|
|
70
|
+
// Tracing
|
|
71
|
+
var tracing_1 = require("./tracing");
|
|
72
|
+
Object.defineProperty(exports, "initTracer", { enumerable: true, get: function () { return tracing_1.initTracer; } });
|
|
73
|
+
Object.defineProperty(exports, "getTracer", { enumerable: true, get: function () { return tracing_1.getTracer; } });
|
|
74
|
+
Object.defineProperty(exports, "startSpan", { enumerable: true, get: function () { return tracing_1.startSpan; } });
|
|
75
|
+
Object.defineProperty(exports, "tracingMiddleware", { enumerable: true, get: function () { return tracing_1.tracingMiddleware; } });
|
|
76
|
+
Object.defineProperty(exports, "createChildSpan", { enumerable: true, get: function () { return tracing_1.createChildSpan; } });
|
|
77
|
+
Object.defineProperty(exports, "logToSpan", { enumerable: true, get: function () { return tracing_1.logToSpan; } });
|
|
78
|
+
Object.defineProperty(exports, "setSpanTag", { enumerable: true, get: function () { return tracing_1.setSpanTag; } });
|
|
79
|
+
Object.defineProperty(exports, "injectHeaders", { enumerable: true, get: function () { return tracing_1.injectHeaders; } });
|
|
80
|
+
Object.defineProperty(exports, "extractSpanContext", { enumerable: true, get: function () { return tracing_1.extractSpanContext; } });
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qFAAqF;;;;;;AAErF,gBAAgB;AAChB,qDAAoD;AAA3C,8GAAA,aAAa,OAAA;AAGtB,UAAU;AACV,2CAAqD;AAA5C,iHAAA,OAAO,OAAU;AAE1B,gBAAgB;AAChB,8DAAoF;AAA3E,+GAAA,WAAW,OAAA;AAAE,8GAAA,UAAU,OAAA;AAAE,kHAAA,cAAc,OAAA;AAEhD,WAAW;AACX,oDAAgE;AAAvD,uGAAA,SAAS,OAAA;AAAE,0GAAA,YAAY,OAAA;AAEhC,SAAS;AACT,oCAA0C;AAAjC,iGAAA,UAAU,OAAA;AAEnB,SAAS;AACT,gDAAuJ;AAA9I,sGAAA,SAAS,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,2GAAA,cAAc,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,iHAAA,oBAAoB,OAAA;AAE1H,aAAa;AACb,8DAAgE;AAAvD,mHAAA,iBAAiB,OAAA;AAC1B,8DAAmE;AAA1D,sHAAA,oBAAoB,OAAA;AAC7B,0DAAyD;AAAhD,4GAAA,YAAY,OAAA;AACrB,4DAA0G;AAAjG,8GAAA,aAAa,OAAA;AAAE,yHAAA,wBAAwB,OAAA;AAAE,oHAAA,mBAAmB,OAAA;AACrE,kDAAmH;AAA1G,2GAAA,eAAe,OAAA;AAAE,6GAAA,iBAAiB,OAAA;AAAE,+GAAA,mBAAmB,OAAA;AAAE,6GAAA,iBAAiB,OAAA;AACnF,kDAAiD;AAAxC,oGAAA,QAAQ,OAAA;AAKjB,QAAQ;AACR,mDAAmF;AAA1E,oHAAA,qBAAqB,OAAA;AAAE,oHAAA,qBAAqB,OAAA;AACrD,6CAA6E;AAApE,6GAAA,iBAAiB,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,qGAAA,SAAS,OAAA;AAGlD,UAAU;AACV,qCAQmB;AAPjB,4GAAA,iBAAiB,OAAA;AACjB,8GAAA,mBAAmB,OAAA;AACnB,4GAAA,iBAAiB,OAAA;AACjB,gHAAA,qBAAqB,OAAA;AACrB,+GAAA,oBAAoB,OAAA;AACpB,0GAAA,eAAe,OAAA;AACf,mGAAA,QAAQ,OAAA;AAGV,UAAU;AACV,qCAUmB;AATjB,qGAAA,UAAU,OAAA;AACV,oGAAA,SAAS,OAAA;AACT,oGAAA,SAAS,OAAA;AACT,4GAAA,iBAAiB,OAAA;AACjB,0GAAA,eAAe,OAAA;AACf,oGAAA,SAAS,OAAA;AACT,qGAAA,UAAU,OAAA;AACV,wGAAA,aAAa,OAAA;AACb,6GAAA,kBAAkB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logging/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AA8E9B,QAAA,MAAM,MAAM,gBAsBV,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const winston_1 = __importDefault(require("winston"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
// Define log levels
|
|
10
|
+
const levels = {
|
|
11
|
+
error: 0,
|
|
12
|
+
warn: 1,
|
|
13
|
+
info: 2,
|
|
14
|
+
http: 3,
|
|
15
|
+
debug: 4,
|
|
16
|
+
};
|
|
17
|
+
const level = () => {
|
|
18
|
+
const env = process.env.NODE_ENV || 'development';
|
|
19
|
+
const isDevelopment = env === 'development';
|
|
20
|
+
return isDevelopment ? 'debug' : 'info';
|
|
21
|
+
};
|
|
22
|
+
// Define colors for each level
|
|
23
|
+
const colors = {
|
|
24
|
+
error: 'red',
|
|
25
|
+
warn: 'yellow',
|
|
26
|
+
info: 'green',
|
|
27
|
+
http: 'magenta',
|
|
28
|
+
debug: 'white',
|
|
29
|
+
};
|
|
30
|
+
winston_1.default.addColors(colors);
|
|
31
|
+
// Define format for console (human-readable)
|
|
32
|
+
const consoleFormat = winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }), winston_1.default.format.colorize({ all: true }), winston_1.default.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`));
|
|
33
|
+
// Define JSON format for production (structured logging)
|
|
34
|
+
const jsonFormat = winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.json());
|
|
35
|
+
// Choose format based on environment
|
|
36
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
37
|
+
const logFormat = isProduction ? jsonFormat : consoleFormat;
|
|
38
|
+
// Define which transports the logger must use
|
|
39
|
+
const transports = [
|
|
40
|
+
// Console transport (goes to Docker stdout/stderr)
|
|
41
|
+
new winston_1.default.transports.Console({
|
|
42
|
+
format: logFormat,
|
|
43
|
+
level: level()
|
|
44
|
+
}),
|
|
45
|
+
];
|
|
46
|
+
// Add file transport only in development (optional)
|
|
47
|
+
if (!isProduction && process.env.LOG_TO_FILE === 'true') {
|
|
48
|
+
// Create logs directory if it doesn't exist
|
|
49
|
+
const logsDir = path_1.default.join(process.cwd(), 'logs');
|
|
50
|
+
if (!fs_1.default.existsSync(logsDir)) {
|
|
51
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
transports.push(new winston_1.default.transports.File({
|
|
54
|
+
filename: path_1.default.join(logsDir, 'app.log'),
|
|
55
|
+
format: jsonFormat,
|
|
56
|
+
level: 'debug'
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
// Create the logger instance
|
|
60
|
+
const logger = winston_1.default.createLogger({
|
|
61
|
+
level: level(),
|
|
62
|
+
levels,
|
|
63
|
+
format: logFormat,
|
|
64
|
+
transports,
|
|
65
|
+
// Handle exceptions and rejections
|
|
66
|
+
exceptionHandlers: [
|
|
67
|
+
new winston_1.default.transports.Console({
|
|
68
|
+
format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.simple())
|
|
69
|
+
})
|
|
70
|
+
],
|
|
71
|
+
rejectionHandlers: [
|
|
72
|
+
new winston_1.default.transports.Console({
|
|
73
|
+
format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.simple())
|
|
74
|
+
})
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
exports.default = logger;
|
|
78
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logging/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import promClient from 'prom-client';
|
|
2
|
+
declare const register: promClient.Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
3
|
+
export declare const httpRequestDuration: promClient.Histogram<"route" | "method" | "status_code">;
|
|
4
|
+
export declare const httpRequestsTotal: promClient.Counter<"route" | "method" | "status_code">;
|
|
5
|
+
export declare const activeConnections: promClient.Gauge<string>;
|
|
6
|
+
export declare const databaseQueryDuration: promClient.Histogram<"operation" | "collection">;
|
|
7
|
+
export declare const databaseQueriesTotal: promClient.Counter<"operation" | "collection" | "status">;
|
|
8
|
+
export declare const businessMetrics: {
|
|
9
|
+
albumsCreated: promClient.Counter<string>;
|
|
10
|
+
filesUploaded: promClient.Counter<"file_type">;
|
|
11
|
+
usersRegistered: promClient.Counter<string>;
|
|
12
|
+
paymentsProcessed: promClient.Counter<"method" | "status">;
|
|
13
|
+
};
|
|
14
|
+
export declare const metricsHandler: (req: any, res: any) => Promise<void>;
|
|
15
|
+
export declare const metricsMiddleware: (req: any, res: any, next: any) => void;
|
|
16
|
+
export { register };
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AAGrC,QAAA,MAAM,QAAQ,iEAA4B,CAAC;AAY3C,eAAO,MAAM,mBAAmB,0DAK9B,CAAC;AAEH,eAAO,MAAM,iBAAiB,wDAI5B,CAAC;AAEH,eAAO,MAAM,iBAAiB,0BAG5B,CAAC;AAEH,eAAO,MAAM,qBAAqB,kDAKhC,CAAC;AAEH,eAAO,MAAM,oBAAoB,2DAI/B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;CAsB3B,CAAC;AAGF,eAAO,MAAM,cAAc,GAAU,KAAK,GAAG,EAAE,KAAK,GAAG,kBAQtD,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,SAyB9D,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.register = exports.metricsMiddleware = exports.metricsHandler = exports.businessMetrics = exports.databaseQueriesTotal = exports.databaseQueryDuration = exports.activeConnections = exports.httpRequestsTotal = exports.httpRequestDuration = void 0;
|
|
7
|
+
const prom_client_1 = __importDefault(require("prom-client"));
|
|
8
|
+
// Create a Registry which registers the metrics
|
|
9
|
+
const register = new prom_client_1.default.Registry();
|
|
10
|
+
exports.register = register;
|
|
11
|
+
// Add a default label which is added to all metrics
|
|
12
|
+
register.setDefaultLabels({
|
|
13
|
+
app: process.env.SERVICE_NAME || 'unknown-service',
|
|
14
|
+
version: process.env.npm_package_version || '1.0.0'
|
|
15
|
+
});
|
|
16
|
+
// Enable the collection of default metrics
|
|
17
|
+
prom_client_1.default.collectDefaultMetrics({ register });
|
|
18
|
+
// Custom metrics
|
|
19
|
+
exports.httpRequestDuration = new prom_client_1.default.Histogram({
|
|
20
|
+
name: 'http_request_duration_seconds',
|
|
21
|
+
help: 'Duration of HTTP requests in seconds',
|
|
22
|
+
labelNames: ['method', 'route', 'status_code'],
|
|
23
|
+
buckets: [0.1, 0.5, 1, 2, 5, 10]
|
|
24
|
+
});
|
|
25
|
+
exports.httpRequestsTotal = new prom_client_1.default.Counter({
|
|
26
|
+
name: 'http_requests_total',
|
|
27
|
+
help: 'Total number of HTTP requests',
|
|
28
|
+
labelNames: ['method', 'route', 'status_code']
|
|
29
|
+
});
|
|
30
|
+
exports.activeConnections = new prom_client_1.default.Gauge({
|
|
31
|
+
name: 'active_connections',
|
|
32
|
+
help: 'Number of active connections'
|
|
33
|
+
});
|
|
34
|
+
exports.databaseQueryDuration = new prom_client_1.default.Histogram({
|
|
35
|
+
name: 'database_query_duration_seconds',
|
|
36
|
+
help: 'Duration of database queries in seconds',
|
|
37
|
+
labelNames: ['operation', 'collection'],
|
|
38
|
+
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5]
|
|
39
|
+
});
|
|
40
|
+
exports.databaseQueriesTotal = new prom_client_1.default.Counter({
|
|
41
|
+
name: 'database_queries_total',
|
|
42
|
+
help: 'Total number of database queries',
|
|
43
|
+
labelNames: ['operation', 'collection', 'status']
|
|
44
|
+
});
|
|
45
|
+
exports.businessMetrics = {
|
|
46
|
+
albumsCreated: new prom_client_1.default.Counter({
|
|
47
|
+
name: 'albums_created_total',
|
|
48
|
+
help: 'Total number of albums created'
|
|
49
|
+
}),
|
|
50
|
+
filesUploaded: new prom_client_1.default.Counter({
|
|
51
|
+
name: 'files_uploaded_total',
|
|
52
|
+
help: 'Total number of files uploaded',
|
|
53
|
+
labelNames: ['file_type']
|
|
54
|
+
}),
|
|
55
|
+
usersRegistered: new prom_client_1.default.Counter({
|
|
56
|
+
name: 'users_registered_total',
|
|
57
|
+
help: 'Total number of users registered'
|
|
58
|
+
}),
|
|
59
|
+
paymentsProcessed: new prom_client_1.default.Counter({
|
|
60
|
+
name: 'payments_processed_total',
|
|
61
|
+
help: 'Total number of payments processed',
|
|
62
|
+
labelNames: ['status', 'method']
|
|
63
|
+
})
|
|
64
|
+
};
|
|
65
|
+
// Metrics endpoint handler
|
|
66
|
+
const metricsHandler = async (req, res) => {
|
|
67
|
+
try {
|
|
68
|
+
res.set('Content-Type', register.contentType);
|
|
69
|
+
const metrics = await register.metrics();
|
|
70
|
+
res.end(metrics);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
res.status(500).end('Error generating metrics');
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
exports.metricsHandler = metricsHandler;
|
|
77
|
+
// Middleware to collect HTTP metrics
|
|
78
|
+
const metricsMiddleware = (req, res, next) => {
|
|
79
|
+
const start = Date.now();
|
|
80
|
+
const { method, url } = req;
|
|
81
|
+
// Increment active connections
|
|
82
|
+
exports.activeConnections.inc();
|
|
83
|
+
res.on('finish', () => {
|
|
84
|
+
const duration = (Date.now() - start) / 1000; // Convert to seconds
|
|
85
|
+
const { statusCode } = res;
|
|
86
|
+
// Record metrics
|
|
87
|
+
exports.httpRequestDuration
|
|
88
|
+
.labels(method, url, statusCode.toString())
|
|
89
|
+
.observe(duration);
|
|
90
|
+
exports.httpRequestsTotal
|
|
91
|
+
.labels(method, url, statusCode.toString())
|
|
92
|
+
.inc();
|
|
93
|
+
// Decrement active connections
|
|
94
|
+
exports.activeConnections.dec();
|
|
95
|
+
});
|
|
96
|
+
next();
|
|
97
|
+
};
|
|
98
|
+
exports.metricsMiddleware = metricsMiddleware;
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* JWT authentication middleware
|
|
4
|
+
* Verifies JWT token and attaches user info (and its embedded groups) to
|
|
5
|
+
* the request — typed via the global `Express.Request` augmentation in
|
|
6
|
+
* `../types/auth`, no `(req as any)` cast needed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function authenticateToken(req: Request, res: Response, next: NextFunction): void;
|
|
9
|
+
//# sourceMappingURL=authMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authMiddleware.d.ts","sourceRoot":"","sources":["../../src/middleware/authMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK1D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAiBvF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.authenticateToken = authenticateToken;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
const env_1 = require("../config/env");
|
|
9
|
+
/**
|
|
10
|
+
* JWT authentication middleware
|
|
11
|
+
* Verifies JWT token and attaches user info (and its embedded groups) to
|
|
12
|
+
* the request — typed via the global `Express.Request` augmentation in
|
|
13
|
+
* `../types/auth`, no `(req as any)` cast needed.
|
|
14
|
+
*/
|
|
15
|
+
function authenticateToken(req, res, next) {
|
|
16
|
+
try {
|
|
17
|
+
const JWT_SECRET = (0, env_1.requireEnv)('JWT_SECRET');
|
|
18
|
+
const token = req.cookies?.access_token || req.headers.authorization?.replace('Bearer ', '');
|
|
19
|
+
if (!token) {
|
|
20
|
+
res.status(401).json({ success: false, message: 'Access token required' });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const user = jsonwebtoken_1.default.verify(token, JWT_SECRET);
|
|
24
|
+
req.user = user;
|
|
25
|
+
req.userGroups = user.groups ?? [];
|
|
26
|
+
next();
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
res.status(401).json({ success: false, message: 'Invalid or expired token' });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=authMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authMiddleware.js","sourceRoot":"","sources":["../../src/middleware/authMiddleware.ts"],"names":[],"mappings":";;;;;AAWA,8CAiBC;AA3BD,gEAA+B;AAC/B,uCAA2C;AAG3C;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC/E,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAA,gBAAU,EAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,YAAY,IAAI,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAE7F,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAgB,CAAC;QAC1D,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAChB,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QACnC,IAAI,EAAE,CAAC;IACT,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import cors from 'cors';
|
|
2
|
+
export interface CorsMiddlewareOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Comma-separated origin whitelist. Defaults to process.env.CORS_ORIGIN,
|
|
5
|
+
* read per-request so it works regardless of dotenv.config() timing.
|
|
6
|
+
*/
|
|
7
|
+
origins?: string;
|
|
8
|
+
exposedHeaders?: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Shared CORS middleware with an explicit origin whitelist.
|
|
12
|
+
* Requests without an Origin header (server-to-server, curl, health checks)
|
|
13
|
+
* are always allowed; browser requests must match the whitelist.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createCorsMiddleware(options?: CorsMiddlewareOptions): (req: cors.CorsRequest, res: {
|
|
16
|
+
statusCode?: number | undefined;
|
|
17
|
+
setHeader(key: string, value: string): any;
|
|
18
|
+
end(): any;
|
|
19
|
+
}, next: (err?: any) => any) => void;
|
|
20
|
+
//# sourceMappingURL=corsMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corsMiddleware.d.ts","sourceRoot":"","sources":["../../src/middleware/corsMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B;cAmBiE,CAAC;;;aAAmH,CAAC,uBAD7P"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createCorsMiddleware = createCorsMiddleware;
|
|
7
|
+
const cors_1 = __importDefault(require("cors"));
|
|
8
|
+
const logger_1 = __importDefault(require("../logging/logger"));
|
|
9
|
+
/**
|
|
10
|
+
* Shared CORS middleware with an explicit origin whitelist.
|
|
11
|
+
* Requests without an Origin header (server-to-server, curl, health checks)
|
|
12
|
+
* are always allowed; browser requests must match the whitelist.
|
|
13
|
+
*/
|
|
14
|
+
function createCorsMiddleware(options = {}) {
|
|
15
|
+
return (0, cors_1.default)({
|
|
16
|
+
origin: (origin, callback) => {
|
|
17
|
+
const allowedOrigins = (options.origins ?? process.env.CORS_ORIGIN ?? '')
|
|
18
|
+
.split(',')
|
|
19
|
+
.map(o => o.trim())
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
if (!origin || allowedOrigins.includes(origin)) {
|
|
22
|
+
return callback(null, true);
|
|
23
|
+
}
|
|
24
|
+
logger_1.default.warn('Blocked CORS origin', { origin });
|
|
25
|
+
return callback(new Error('Not allowed by CORS: ' + origin));
|
|
26
|
+
},
|
|
27
|
+
credentials: true,
|
|
28
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
|
29
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-correlation-id', 'x-session-id'],
|
|
30
|
+
exposedHeaders: options.exposedHeaders
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=corsMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corsMiddleware.js","sourceRoot":"","sources":["../../src/middleware/corsMiddleware.ts"],"names":[],"mappings":";;;;;AAiBA,oDAkBC;AAnCD,gDAAwB;AACxB,+DAAuC;AAWvC;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,UAAiC,EAAE;IACtE,OAAO,IAAA,cAAI,EAAC;QACV,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YAC3B,MAAM,cAAc,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;iBACtE,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBAClB,MAAM,CAAC,OAAO,CAAC,CAAC;YACnB,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/C,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC9B,CAAC;YACD,gBAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC/C,OAAO,QAAQ,CAAC,IAAI,KAAK,CAAC,uBAAuB,GAAG,MAAM,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;QACpD,cAAc,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,cAAc,CAAC;QACzG,cAAc,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ErrorRequestHandler } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Global error handler middleware.
|
|
4
|
+
*
|
|
5
|
+
* Controllers throw a typed `HttpError` (BadRequestError, NotFoundError,
|
|
6
|
+
* ForbiddenError, ...) instead of hand-rolling try/catch + string-matching
|
|
7
|
+
* on `error.message` to pick a status code — Express 5 forwards rejected
|
|
8
|
+
* promises from async route handlers here automatically. Anything that
|
|
9
|
+
* isn't a recognized error type is treated as an unexpected bug: logged
|
|
10
|
+
* with its full stack and returned as a generic 500 (no message leak
|
|
11
|
+
* outside development), same as before this file knew about HttpError.
|
|
12
|
+
*/
|
|
13
|
+
export declare const errorHandler: ErrorRequestHandler;
|
|
14
|
+
//# sourceMappingURL=errorHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,mBAAmB,EAAE,MAAM,SAAS,CAAC;AA4B/E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,mBA0D1B,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.errorHandler = void 0;
|
|
7
|
+
const logger_1 = __importDefault(require("../logging/logger"));
|
|
8
|
+
const HttpError_1 = require("../errors/HttpError");
|
|
9
|
+
/**
|
|
10
|
+
* Recognizes error shapes that map to an obvious HTTP status without a
|
|
11
|
+
* controller having to catch and re-throw them: our own typed HttpError
|
|
12
|
+
* hierarchy, plus Mongoose's ValidationError (failed schema validation,
|
|
13
|
+
* e.g. a missing required field) and CastError (e.g. an invalid ObjectId
|
|
14
|
+
* string) — both of which are client mistakes, not server bugs, but throw
|
|
15
|
+
* as plain Mongoose error classes rather than anything of ours.
|
|
16
|
+
*/
|
|
17
|
+
function classifyError(error) {
|
|
18
|
+
if (error instanceof HttpError_1.HttpError) {
|
|
19
|
+
return { statusCode: error.statusCode, name: error.name, message: error.message };
|
|
20
|
+
}
|
|
21
|
+
if (error.name === 'ValidationError' || error.name === 'CastError') {
|
|
22
|
+
return { statusCode: 400, name: error.name, message: error.message };
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Global error handler middleware.
|
|
28
|
+
*
|
|
29
|
+
* Controllers throw a typed `HttpError` (BadRequestError, NotFoundError,
|
|
30
|
+
* ForbiddenError, ...) instead of hand-rolling try/catch + string-matching
|
|
31
|
+
* on `error.message` to pick a status code — Express 5 forwards rejected
|
|
32
|
+
* promises from async route handlers here automatically. Anything that
|
|
33
|
+
* isn't a recognized error type is treated as an unexpected bug: logged
|
|
34
|
+
* with its full stack and returned as a generic 500 (no message leak
|
|
35
|
+
* outside development), same as before this file knew about HttpError.
|
|
36
|
+
*/
|
|
37
|
+
const errorHandler = (error, req, res, _next) => {
|
|
38
|
+
const known = classifyError(error);
|
|
39
|
+
if (known) {
|
|
40
|
+
// Client errors (4xx) are routine, expected control flow — log without
|
|
41
|
+
// a stack trace at warn level, not as if the service were broken.
|
|
42
|
+
logger_1.default.warn('Request failed:', {
|
|
43
|
+
error: known.message,
|
|
44
|
+
statusCode: known.statusCode,
|
|
45
|
+
url: req.url,
|
|
46
|
+
method: req.method,
|
|
47
|
+
correlationId: req.correlationId
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
logger_1.default.error('Unhandled error:', {
|
|
52
|
+
error: error.message,
|
|
53
|
+
stack: error.stack,
|
|
54
|
+
url: req.url,
|
|
55
|
+
method: req.method,
|
|
56
|
+
ip: req.ip,
|
|
57
|
+
userAgent: req.get('User-Agent'),
|
|
58
|
+
correlationId: req.correlationId
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Add CORS headers to error responses
|
|
62
|
+
const origin = req.headers.origin;
|
|
63
|
+
if (origin && (origin.includes('localhost') || origin.includes('tumbaland.eu'))) {
|
|
64
|
+
res.header('Access-Control-Allow-Origin', origin);
|
|
65
|
+
res.header('Access-Control-Allow-Credentials', 'true');
|
|
66
|
+
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
67
|
+
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, x-correlation-id, x-session-id');
|
|
68
|
+
}
|
|
69
|
+
if (known) {
|
|
70
|
+
res.status(known.statusCode).json({
|
|
71
|
+
success: false,
|
|
72
|
+
error: known.name,
|
|
73
|
+
message: known.message
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Don't leak error details in production for unexpected errors
|
|
78
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
79
|
+
const errorMessage = isDevelopment ? error.message : 'Something went wrong';
|
|
80
|
+
res.status(500).json({
|
|
81
|
+
success: false,
|
|
82
|
+
error: 'Internal server error',
|
|
83
|
+
message: errorMessage,
|
|
84
|
+
...(isDevelopment && { stack: error.stack })
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
exports.errorHandler = errorHandler;
|
|
88
|
+
//# sourceMappingURL=errorHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Morgan middleware configured to use Winston logger
|
|
3
|
+
* Logs HTTP requests in structured format
|
|
4
|
+
*/
|
|
5
|
+
export declare const requestLogger: (req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse<import("node:http").IncomingMessage>, callback: (err?: Error) => void) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Combined middleware that includes both logging and metrics
|
|
8
|
+
* Use this instead of separate requestLogger and metricsMiddleware
|
|
9
|
+
*/
|
|
10
|
+
export declare const requestLoggerWithMetrics: ((req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse<import("node:http").IncomingMessage>, callback: (err?: Error) => void) => void)[];
|
|
11
|
+
/**
|
|
12
|
+
* Simple request logger for development
|
|
13
|
+
* Logs basic request info with correlation ID
|
|
14
|
+
*/
|
|
15
|
+
export declare const simpleRequestLogger: (req: any, res: any, next: any) => void;
|
|
16
|
+
//# sourceMappingURL=requestLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestLogger.d.ts","sourceRoot":"","sources":["../../src/middleware/requestLogger.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,eAAO,MAAM,aAAa,yIAFU,CAAC,yBAQnC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,0IAdD,CAAC,4BAcqC,CAAC;AAE3E;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,SAoBhE,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.simpleRequestLogger = exports.requestLoggerWithMetrics = exports.requestLogger = void 0;
|
|
7
|
+
const morgan_1 = __importDefault(require("morgan"));
|
|
8
|
+
const logger_1 = __importDefault(require("../logging/logger"));
|
|
9
|
+
const metrics_1 = require("../metrics");
|
|
10
|
+
/**
|
|
11
|
+
* Morgan middleware configured to use Winston logger
|
|
12
|
+
* Logs HTTP requests in structured format
|
|
13
|
+
*/
|
|
14
|
+
exports.requestLogger = (0, morgan_1.default)('combined', {
|
|
15
|
+
stream: {
|
|
16
|
+
write: (message) => {
|
|
17
|
+
logger_1.default.http(message.trim());
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Combined middleware that includes both logging and metrics
|
|
23
|
+
* Use this instead of separate requestLogger and metricsMiddleware
|
|
24
|
+
*/
|
|
25
|
+
exports.requestLoggerWithMetrics = [exports.requestLogger, metrics_1.metricsMiddleware];
|
|
26
|
+
/**
|
|
27
|
+
* Simple request logger for development
|
|
28
|
+
* Logs basic request info with correlation ID
|
|
29
|
+
*/
|
|
30
|
+
const simpleRequestLogger = (req, res, next) => {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
const correlationId = req.correlationId || 'unknown';
|
|
33
|
+
logger_1.default.info(`→ ${req.method} ${req.url}`, {
|
|
34
|
+
correlationId,
|
|
35
|
+
ip: req.ip,
|
|
36
|
+
userAgent: req.get('User-Agent')
|
|
37
|
+
});
|
|
38
|
+
res.on('finish', () => {
|
|
39
|
+
const duration = Date.now() - start;
|
|
40
|
+
logger_1.default.info(`← ${req.method} ${req.url} ${res.statusCode} ${duration}ms`, {
|
|
41
|
+
correlationId,
|
|
42
|
+
statusCode: res.statusCode,
|
|
43
|
+
duration
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
next();
|
|
47
|
+
};
|
|
48
|
+
exports.simpleRequestLogger = simpleRequestLogger;
|
|
49
|
+
//# sourceMappingURL=requestLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestLogger.js","sourceRoot":"","sources":["../../src/middleware/requestLogger.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,+DAAuC;AACvC,wCAA+C;AAE/C;;;GAGG;AACU,QAAA,aAAa,GAAG,IAAA,gBAAM,EAAC,UAAU,EAAE;IAC9C,MAAM,EAAE;QACN,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE;YACzB,gBAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;KACF;CACF,CAAC,CAAC;AAEH;;;GAGG;AACU,QAAA,wBAAwB,GAAG,CAAC,qBAAa,EAAE,2BAAiB,CAAC,CAAC;AAE3E;;;GAGG;AACI,MAAM,mBAAmB,GAAG,CAAC,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;IACnE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,IAAI,SAAS,CAAC;IAErD,gBAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,EAAE;QACxC,aAAa;QACb,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;KACjC,CAAC,CAAC;IAEH,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACpC,gBAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,IAAI,QAAQ,IAAI,EAAE;YACxE,aAAa;YACb,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,QAAQ;SACT,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,EAAE,CAAC;AACT,CAAC,CAAC;AApBW,QAAA,mBAAmB,uBAoB9B"}
|