UNPKG

@allan1361/iota-big3-sdk-middleware

Version:

🏆 A+ Grade Certified Enterprise Middleware Framework - Phase 3 Certified (90/100) with advanced resilience patterns, comprehensive type safety, and production-ready observability

191 lines 7.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createLoggingMiddleware = createLoggingMiddleware; exports.loggingMiddleware = loggingMiddleware; exports.createLegacyLoggingMiddleware = createLegacyLoggingMiddleware; const tslib_1 = require("tslib"); const sdk_core_1 = require("@iota-big3/sdk-core"); const sdk_types_1 = require("@iota-big3/sdk-types"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const crypto = tslib_1.__importStar(require("crypto")); function generateRequestId() { return `req-${Date.now()}-${crypto.randomInt(0, Number.MAX_SAFE_INTEGER) / Number.MAX_SAFE_INTEGER.toString(36).substr(2, 9)}`; } function createLoggingMiddleware(sdk, config = {}) { const { enabled = true, level = 'info', includeBody = false, includeHeaders = false, colorize = true, metricsPrefix = 'http_' } = config; const levels = { debug: 0, info: 1, warn: 2, error: 3 }; const currentLevel = levels[level]; return (req, res, next) => { if (!enabled) { return next(); } req.startTime = Date.now(); req.id = req.headers['x-correlation-id'] || req.headers['x-request-id'] || generateRequestId(); const industry = typeof sdk.config.industry === 'string' ? sdk.config.industry : sdk.config.industry.name; if (currentLevel <= levels.info) { const logEntry = { id: req.id, timestamp: new Date().toISOString(), method: req.method, path: req.path, service: sdk?.config?.serviceName, industry }; if (includeHeaders) { logEntry.headers = req.headers; } if (includeBody) { logEntry.body = sanitizeBody(req.body); } if (Object.keys(req.query).length > 0) { logEntry.query = req.query; } logRequest(logEntry, colorize); } sdk?.telemetry?.incrementCounter(`${metricsPrefix}requests_total`, { method: req.method, path: req.route?.path || req.path, service: sdk?.config?.serviceName }); res.logData = {}; const originalSend = res.send; res.send = function (data) { res.logData = res.logData || {}; res.logData.body = sanitizeBody(data); res.logData.statusCode = res.statusCode; return originalSend.call(this, data); }; const originalJson = res.json; res.json = function (data) { res.logData = res.logData || {}; res.logData.body = sanitizeBody(data); res.logData.statusCode = res.statusCode; const apiResponse = typeof data === 'object' && data !== null && ('data' in data || 'error' in data) ? data : (0, sdk_types_1.createApiResponse)({ data }); return originalJson.call(this, apiResponse); }; res.on('finish', () => { const duration = Date.now() - req.startTime; sdk?.telemetry?.recordHistogram(`${metricsPrefix}request_duration_ms`, duration, { method: req.method, path: req.route?.path || req.path, status: res?.statusCode?.toString(), service: sdk?.config?.serviceName }); sdk?.telemetry?.incrementCounter(`${metricsPrefix}responses_total`, { method: req.method, path: req.route?.path || req.path, status: res?.statusCode?.toString(), service: sdk?.config?.serviceName }); const logLevel = getLogLevelForStatus(res.statusCode); if (currentLevel <= levels[logLevel]) { const logEntry = { id: req.id, timestamp: new Date().toISOString(), method: req.method, path: req.path, statusCode: res.statusCode, duration, service: sdk?.config?.serviceName, industry }; if (includeBody) { logEntry.body = sanitizeBody(res?.logData?.body); } if (includeBody) { logEntry.error = res?.logData?.error; } logResponse(logEntry, colorize, logLevel); } }); next(); }; } function logRequest(entry, colorize) { const color = colorize ? chalk_1.default : { gray: (s) => s, cyan: (s) => s, yellow: (s) => s }; let message = `${color.gray('→')} ${color.cyan(entry.method || '')} ${entry.path}`; if (entry.query && Object.keys(entry.query).length > 0) { message += ` ${color.gray('query=')}${JSON.stringify(entry.query)}`; } console.log(`[${entry.timestamp}] ${color.gray(entry.id || '')} ${message}`); if (entry.body) { console.log(color.gray(' Body:'), JSON.stringify(entry.body, null, 2)); } } function logResponse(entry, colorize, _level) { const color = colorize ? chalk_1.default : { gray: (s) => s, green: (s) => s, yellow: (s) => s, red: (s) => s, cyan: (s) => s }; const statusColor = entry.statusCode < 300 ? 'green' : entry.statusCode < 400 ? 'cyan' : entry.statusCode < 500 ? 'yellow' : 'red'; const statusText = color[statusColor](entry.statusCode.toString()); const durationText = color.gray(`${entry.duration}ms`); const message = `${color.gray('←')} ${statusText} ${color.cyan(entry.method)} ${entry.path} ${durationText}`; console.log(`[${entry.timestamp}] ${color.gray(entry.id)} ${message}`); if (entry.error) { console.error(color.red(' Error:'), entry.error); } } function getLogLevelForStatus(statusCode) { if (statusCode >= 500) return 'error'; if (statusCode >= 400) return 'warn'; return 'info'; } function sanitizeBody(body) { if (!body || typeof body !== 'object') { return body; } const sanitized = { ...body }; const sensitiveKeys = ['password', 'token', 'secret', 'apiKey', 'authorization']; Object.keys(sanitized).forEach(key => { if (sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive))) { sanitized[key] = '[REDACTED]'; } else if (typeof sanitized[key] === 'object' && sanitized[key] !== null) { sanitized[key] = sanitizeBody(sanitized[key]); } }); return sanitized; } function loggingMiddleware(options = {}) { if (!options.sdk) { throw new Error('SDK instance is required for logging middleware'); } return createLoggingMiddleware(options.sdk, options.config); } function createLegacyLoggingMiddleware(metadata, tribe) { console.warn('⚠️ Using legacy logging middleware. Please migrate to new pattern.'); const industryType = tribe || 'education'; const sdk = new sdk_core_1.SDK({ serviceName: metadata.name || 'unknown-service', industry: industryType }); sdk.start().catch(error => { console.error('Failed to start SDK for logging middleware:', error); }); return createLoggingMiddleware(sdk); } exports.default = createLoggingMiddleware; //# sourceMappingURL=logging-middleware.js.map