@heavybit/logger-ts 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.
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.morganStyleMiddleware = exports.errorLoggingMiddleware = exports.loggingMiddleware = exports.createLoggingMiddleware = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const logger_1 = require("../lib/logger");
6
+ const config_1 = require("../config");
7
+ const sanitize_1 = require("../utils/sanitize");
8
+ /**
9
+ * Filter sensitive data from request body
10
+ */
11
+ const filterSensitiveBody = (body) => {
12
+ return (0, sanitize_1.sanitizeData)(body);
13
+ };
14
+ /**
15
+ * Filter sensitive headers
16
+ */
17
+ const filterSensitiveHeaders = (headers) => {
18
+ return (0, sanitize_1.sanitizeHeaders)(headers);
19
+ };
20
+ /**
21
+ * Create the Express logging middleware with configuration options
22
+ *
23
+ * @param options - Middleware configuration options
24
+ * @returns Express middleware function
25
+ */
26
+ const createLoggingMiddleware = (options = {}) => {
27
+ const { skipEndpoints = [], logRequestBody = true, logResponseBody = false, requestIdGenerator = uuid_1.v4, additionalFields, } = options;
28
+ return (req, res, next) => {
29
+ const logger = (0, logger_1.getLogger)();
30
+ const config = (0, config_1.getConfig)();
31
+ // Get health check endpoint from config or options
32
+ const healthCheckEndpoint = config.healthCheckEndpoint || '/health';
33
+ const allSkipEndpoints = [...skipEndpoints, healthCheckEndpoint];
34
+ // Check if this endpoint should be skipped
35
+ if (allSkipEndpoints.some((endpoint) => req.path === endpoint || req.path.startsWith(endpoint))) {
36
+ return next();
37
+ }
38
+ // Generate unique request ID
39
+ const requestId = requestIdGenerator();
40
+ req.requestId = requestId;
41
+ // Store request body for logging
42
+ const requestBody = req.body;
43
+ // Capture start time
44
+ const startTime = Date.now();
45
+ req.startTime = startTime;
46
+ // Log incoming request
47
+ const logRequest = () => {
48
+ if (req.url && req.method) {
49
+ const logData = {
50
+ level: 'info',
51
+ message: 'Incoming request',
52
+ requestId,
53
+ method: req.method,
54
+ url: req.originalUrl,
55
+ timestamp: new Date().toISOString(),
56
+ };
57
+ // Add headers if not too large
58
+ const filteredHeaders = filterSensitiveHeaders(req.headers);
59
+ if (Object.keys(filteredHeaders).length <= 20) {
60
+ logData.headers = filteredHeaders;
61
+ }
62
+ // Add body if enabled
63
+ if (logRequestBody && requestBody && Object.keys(requestBody).length > 0) {
64
+ logData.body = filterSensitiveBody(requestBody);
65
+ }
66
+ // Add additional fields if provided
67
+ if (additionalFields) {
68
+ const extra = additionalFields(req);
69
+ Object.assign(logData, extra);
70
+ }
71
+ logger.info((0, logger_1.formatLogEntry)(logData));
72
+ }
73
+ };
74
+ // Log the incoming request
75
+ logRequest();
76
+ // Capture response body if enabled
77
+ let responseBody = '';
78
+ if (logResponseBody) {
79
+ const originalWrite = res.write.bind(res);
80
+ const originalEnd = res.end.bind(res);
81
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
+ res.write = function (chunk, ...args) {
83
+ if (chunk) {
84
+ responseBody += String(chunk);
85
+ }
86
+ return originalWrite(chunk, ...args);
87
+ };
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ res.end = function (chunk, ...args) {
90
+ if (chunk && typeof chunk !== 'function') {
91
+ responseBody += String(chunk);
92
+ }
93
+ return originalEnd(chunk, ...args);
94
+ };
95
+ }
96
+ // Event listener for when the response finishes
97
+ res.on('finish', () => {
98
+ const duration = Date.now() - startTime;
99
+ const logLevel = res.statusCode >= 400 ? 'error' : 'info';
100
+ const logData = {
101
+ level: logLevel,
102
+ message: 'Request completed',
103
+ requestId,
104
+ method: req.method,
105
+ url: req.originalUrl,
106
+ statusCode: res.statusCode,
107
+ responseTime: `${duration}ms`,
108
+ timestamp: new Date().toISOString(),
109
+ };
110
+ // Include request body for error responses
111
+ if (logLevel === 'error' && requestBody && Object.keys(requestBody).length > 0) {
112
+ logData.body = filterSensitiveBody(requestBody);
113
+ }
114
+ // Include response body if captured
115
+ if (logResponseBody && responseBody) {
116
+ try {
117
+ const parsedBody = JSON.parse(responseBody);
118
+ logData.body = {
119
+ ...(logData.body || {}),
120
+ response: (0, sanitize_1.sanitizeData)(parsedBody),
121
+ };
122
+ }
123
+ catch {
124
+ // Response is not JSON, skip
125
+ }
126
+ }
127
+ // Add additional fields
128
+ if (additionalFields) {
129
+ const extra = additionalFields(req);
130
+ Object.assign(logData, extra);
131
+ }
132
+ logger.log(logLevel, (0, logger_1.formatLogEntry)(logData));
133
+ });
134
+ // Event listener for response errors
135
+ res.on('error', (err) => {
136
+ const duration = Date.now() - startTime;
137
+ logger.error((0, logger_1.formatLogEntry)({
138
+ level: 'error',
139
+ message: 'Request failed',
140
+ requestId,
141
+ method: req.method,
142
+ url: req.originalUrl,
143
+ statusCode: res.statusCode,
144
+ responseTime: `${duration}ms`,
145
+ error: err.message,
146
+ body: filterSensitiveBody(requestBody),
147
+ timestamp: new Date().toISOString(),
148
+ }));
149
+ });
150
+ next();
151
+ };
152
+ };
153
+ exports.createLoggingMiddleware = createLoggingMiddleware;
154
+ /**
155
+ * Default logging middleware (uses default configuration)
156
+ */
157
+ exports.loggingMiddleware = (0, exports.createLoggingMiddleware)();
158
+ /**
159
+ * Error logging middleware for Express error handling
160
+ */
161
+ const errorLoggingMiddleware = (err, req, _res, next) => {
162
+ const logger = (0, logger_1.getLogger)();
163
+ const startTime = req.startTime || Date.now();
164
+ const duration = Date.now() - startTime;
165
+ logger.error((0, logger_1.formatLogEntry)({
166
+ level: 'error',
167
+ message: 'Unhandled error',
168
+ requestId: req.requestId,
169
+ method: req.method,
170
+ url: req.originalUrl,
171
+ statusCode: err.statusCode || err.status || 500,
172
+ responseTime: `${duration}ms`,
173
+ error: err.message,
174
+ body: (0, sanitize_1.sanitizeData)(req.body),
175
+ timestamp: new Date().toISOString(),
176
+ }));
177
+ // Pass to next error handler
178
+ next(err);
179
+ };
180
+ exports.errorLoggingMiddleware = errorLoggingMiddleware;
181
+ /**
182
+ * Morgan-style request logging format
183
+ * Returns a middleware that logs in a standardized format
184
+ */
185
+ const morganStyleMiddleware = (format = 'dev') => {
186
+ return (req, res, next) => {
187
+ const logger = (0, logger_1.getLogger)();
188
+ const startTime = Date.now();
189
+ const requestId = (0, uuid_1.v4)();
190
+ req.requestId = requestId;
191
+ res.on('finish', () => {
192
+ const duration = Date.now() - startTime;
193
+ let logMessage = '';
194
+ switch (format) {
195
+ case 'combined':
196
+ logMessage = `${req.ip} - - [${new Date().toISOString()}] "${req.method} ${req.originalUrl} HTTP/${req.httpVersion}" ${res.statusCode} - "${req.get('referer') || '-'}" "${req.get('user-agent') || '-'}"`;
197
+ break;
198
+ case 'common':
199
+ logMessage = `${req.ip} - - [${new Date().toISOString()}] "${req.method} ${req.originalUrl} HTTP/${req.httpVersion}" ${res.statusCode} -`;
200
+ break;
201
+ case 'dev':
202
+ logMessage = `${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms`;
203
+ break;
204
+ case 'short':
205
+ logMessage = `${req.ip} ${req.method} ${req.originalUrl} ${res.statusCode} - ${duration}ms`;
206
+ break;
207
+ case 'tiny':
208
+ logMessage = `${req.method} ${req.originalUrl} ${res.statusCode} - ${duration}ms`;
209
+ break;
210
+ }
211
+ const level = res.statusCode >= 400 ? 'error' : 'info';
212
+ logger.log(level, logMessage, {
213
+ requestId,
214
+ method: req.method,
215
+ url: req.originalUrl,
216
+ statusCode: res.statusCode,
217
+ responseTime: `${duration}ms`,
218
+ });
219
+ });
220
+ next();
221
+ };
222
+ };
223
+ exports.morganStyleMiddleware = morganStyleMiddleware;
224
+ exports.default = exports.loggingMiddleware;
225
+ //# sourceMappingURL=loggingMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loggingMiddleware.js","sourceRoot":"","sources":["../../src/middleware/loggingMiddleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import winston from 'winston';
3
+ /**
4
+ * Supported log levels
5
+ */
6
+ export type LogLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
7
+ /**
8
+ * Types of application classes for context-aware logging
9
+ */
10
+ export type ClassType = 'controllers' | 'services' | 'repositories' | 'utils' | 'middleware' | 'routes' | 'configuration' | 'validators' | 'eventListeners' | 'helpers' | 'jobs' | 'models' | 'transformers' | 'default' | 'unknown';
11
+ /**
12
+ * Log output targets
13
+ */
14
+ export type LogTarget = 'stdout' | 'file' | 'both';
15
+ /**
16
+ * Configuration for file-based logging
17
+ */
18
+ export interface FileLogConfig {
19
+ /** Directory for log files (default: 'logs') */
20
+ directory: string;
21
+ /** Maximum size of log file before rotation (default: '50m') */
22
+ maxSize: string;
23
+ /** Maximum retention period for log files (default: '30d') */
24
+ maxFiles: string;
25
+ /** Whether to compress archived logs (default: true) */
26
+ zippedArchive: boolean;
27
+ /** Date pattern for log file naming (default: 'YYYY-MM-DD') */
28
+ datePattern: string;
29
+ /** Log level for file output (default: 'info') */
30
+ level: LogLevel;
31
+ }
32
+ /**
33
+ * Configuration for console/stdout logging
34
+ */
35
+ export interface ConsoleLogConfig {
36
+ /** Whether to colorize console output (default: true in development) */
37
+ colorize: boolean;
38
+ /** Log level for console output (default: 'debug') */
39
+ level: LogLevel;
40
+ }
41
+ /**
42
+ * Main logger configuration
43
+ */
44
+ export interface LoggerConfig {
45
+ /** Where to output logs: 'stdout', 'file', or 'both' */
46
+ target: LogTarget;
47
+ /** Default log level if not specified by class type */
48
+ defaultLevel: LogLevel;
49
+ /** Console/stdout configuration */
50
+ console: ConsoleLogConfig;
51
+ /** File logging configuration */
52
+ file: FileLogConfig;
53
+ /** Log levels per class type */
54
+ classLevels: Partial<Record<ClassType, LogLevel>>;
55
+ /** Application name for log identification */
56
+ appName?: string;
57
+ /** Environment name (development, staging, production) */
58
+ environment?: string;
59
+ /** Custom sensitive fields to redact */
60
+ sensitiveFields?: string[];
61
+ /** Health check endpoint to skip logging */
62
+ healthCheckEndpoint?: string;
63
+ }
64
+ /**
65
+ * Base log entry structure
66
+ */
67
+ export interface BaseLogEntry {
68
+ level?: LogLevel;
69
+ message: string;
70
+ timestamp?: string;
71
+ [key: string]: unknown;
72
+ }
73
+ /**
74
+ * HTTP request log entry
75
+ */
76
+ export interface RequestLogEntry extends BaseLogEntry {
77
+ requestId?: string;
78
+ method?: string;
79
+ url?: string;
80
+ statusCode?: number;
81
+ responseTime?: string;
82
+ body?: Record<string, unknown>;
83
+ headers?: Record<string, unknown>;
84
+ error?: string | Error;
85
+ }
86
+ /**
87
+ * AOP context for method logging
88
+ */
89
+ export interface AOPContext {
90
+ methodName: string;
91
+ methodType: string;
92
+ classType: ClassType;
93
+ className: string;
94
+ startTime: number;
95
+ endTime?: number;
96
+ executionTime?: number;
97
+ url?: string;
98
+ method?: string;
99
+ body?: Record<string, unknown>;
100
+ result?: unknown;
101
+ responseBody?: unknown;
102
+ statusCode?: number;
103
+ message?: string;
104
+ error?: Error;
105
+ level?: LogLevel;
106
+ logType?: 'info' | 'error';
107
+ }
108
+ /**
109
+ * Advice type for AOP logging
110
+ */
111
+ export type AdviceType = 'before' | 'after' | 'around';
112
+ /**
113
+ * Advice phase during execution
114
+ */
115
+ export type AdvicePhase = 'before' | 'after' | 'error';
116
+ /**
117
+ * Advice function signature
118
+ */
119
+ export type AdviceFunction = (context: AOPContext, phase: AdvicePhase) => void;
120
+ /**
121
+ * Extended Express Request with logging properties
122
+ */
123
+ export interface LoggingRequest extends Request {
124
+ requestId?: string;
125
+ startTime?: number;
126
+ }
127
+ /**
128
+ * Middleware function type
129
+ */
130
+ export type LoggingMiddleware = (req: LoggingRequest, res: Response, next: NextFunction) => void;
131
+ /**
132
+ * Middleware configuration options
133
+ */
134
+ export interface MiddlewareOptions {
135
+ /** Endpoints to skip logging */
136
+ skipEndpoints?: string[];
137
+ /** Whether to log request body */
138
+ logRequestBody?: boolean;
139
+ /** Whether to log response body */
140
+ logResponseBody?: boolean;
141
+ /** Custom request ID generator */
142
+ requestIdGenerator?: () => string;
143
+ /** Additional fields to extract from request */
144
+ additionalFields?: (req: Request) => Record<string, unknown>;
145
+ }
146
+ /**
147
+ * Extended Winston logger with custom methods
148
+ */
149
+ export interface ExtendedLogger extends winston.Logger {
150
+ /** Log with request context */
151
+ logRequest(entry: RequestLogEntry): void;
152
+ /** Log with custom metadata */
153
+ logWithMeta(level: LogLevel, message: string, meta?: Record<string, unknown>): void;
154
+ /** Get the current configuration */
155
+ getConfig(): LoggerConfig;
156
+ }
157
+ /**
158
+ * Object with string keys and any values (for sanitization)
159
+ */
160
+ export type SanitizableObject = Record<string, unknown>;
161
+ /**
162
+ * Result of log formatting
163
+ */
164
+ export interface FormattedLogEntry {
165
+ level: LogLevel;
166
+ message: string;
167
+ requestId: string;
168
+ method: string;
169
+ methodName: string;
170
+ url: string;
171
+ statusCode: string;
172
+ responseTime: string;
173
+ timestamp: string;
174
+ body: Record<string, unknown>;
175
+ error: string;
176
+ }
177
+ /**
178
+ * Environment variable names used by the logger
179
+ */
180
+ export interface LoggerEnvVars {
181
+ LOG_TARGET: LogTarget;
182
+ LOG_TO_FILE: 'true' | 'false';
183
+ LOG_TO_CONSOLE: 'true' | 'false';
184
+ LOG_LEVEL: LogLevel;
185
+ LOG_DIR: string;
186
+ LOG_MAX_SIZE: string;
187
+ LOG_MAX_FILES: string;
188
+ LOG_DATE_PATTERN: string;
189
+ LOG_COLORIZE: 'true' | 'false';
190
+ LOG_LEVEL_CONTROLLERS: LogLevel;
191
+ LOG_LEVEL_SERVICES: LogLevel;
192
+ LOG_LEVEL_REPOSITORIES: LogLevel;
193
+ LOG_LEVEL_UTILS: LogLevel;
194
+ LOG_LEVEL_MIDDLEWARE: LogLevel;
195
+ LOG_LEVEL_ROUTES: LogLevel;
196
+ LOG_LEVEL_CONFIGURATION: LogLevel;
197
+ LOG_LEVEL_VALIDATORS: LogLevel;
198
+ LOG_LEVEL_EVENT_LISTENERS: LogLevel;
199
+ LOG_LEVEL_HELPERS: LogLevel;
200
+ LOG_LEVEL_JOBS: LogLevel;
201
+ LOG_LEVEL_MODELS: LogLevel;
202
+ LOG_LEVEL_TRANSFORMERS: LogLevel;
203
+ LOG_LEVEL_DEFAULT: LogLevel;
204
+ APP_NAME: string;
205
+ NODE_ENV: string;
206
+ HEALTHCHECK_ENDPOINT: string;
207
+ }
208
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { SanitizableObject } from '../types';
2
+ /**
3
+ * Recursively sanitize data by masking sensitive fields
4
+ *
5
+ * @param data - The data to sanitize
6
+ * @param sensitiveFields - Optional custom list of sensitive fields
7
+ * @param seen - Internal set to track circular references
8
+ * @returns Sanitized copy of the data
9
+ */
10
+ export declare const sanitizeData: <T extends SanitizableObject | unknown>(data: T, sensitiveFields?: string[], seen?: WeakSet<object>) => T;
11
+ /**
12
+ * Sanitize headers, specifically targeting authorization-type headers
13
+ */
14
+ export declare const sanitizeHeaders: (headers: Record<string, string | string[] | undefined>) => Record<string, string | string[] | undefined>;
15
+ /**
16
+ * Truncate large values to prevent log bloat
17
+ */
18
+ export declare const truncateValue: (value: unknown, maxLength?: number) => unknown;
19
+ /**
20
+ * Deep clone and sanitize for logging
21
+ */
22
+ export declare const prepareForLogging: <T extends SanitizableObject>(data: T, options?: {
23
+ sensitiveFields?: string[];
24
+ truncateLength?: number;
25
+ }) => T;
26
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAa7C;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,iBAAiB,GAAG,OAAO,EAChE,MAAM,CAAC,EACP,kBAAkB,MAAM,EAAE,EAC1B,OAAM,OAAO,CAAC,MAAM,CAAiB,KACpC,CA6CF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,KACrD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CA6B9C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,OAAO,EACd,YAAW,MAAa,KACvB,OAUF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,iBAAiB,EAC3D,MAAM,CAAC,EACP,UAAU;IACR,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,KACA,CAwBF,CAAC"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareForLogging = exports.truncateValue = exports.sanitizeHeaders = exports.sanitizeData = void 0;
4
+ const config_1 = require("../config");
5
+ /**
6
+ * Check if a key matches any sensitive field (case-insensitive)
7
+ */
8
+ const isSensitiveField = (key, sensitiveFields) => {
9
+ const lowerKey = key.toLowerCase();
10
+ return sensitiveFields.some((field) => field.toLowerCase() === lowerKey || lowerKey.includes(field.toLowerCase()));
11
+ };
12
+ /**
13
+ * Recursively sanitize data by masking sensitive fields
14
+ *
15
+ * @param data - The data to sanitize
16
+ * @param sensitiveFields - Optional custom list of sensitive fields
17
+ * @param seen - Internal set to track circular references
18
+ * @returns Sanitized copy of the data
19
+ */
20
+ const sanitizeData = (data, sensitiveFields, seen = new WeakSet()) => {
21
+ // Return primitives and null/undefined as-is
22
+ if (data === null || data === undefined) {
23
+ return data;
24
+ }
25
+ if (typeof data !== 'object') {
26
+ return data;
27
+ }
28
+ // Prevent circular references
29
+ if (seen.has(data)) {
30
+ return '[CIRCULAR REFERENCE]';
31
+ }
32
+ seen.add(data);
33
+ // Get sensitive fields from config or use provided/default
34
+ const fieldsToMask = sensitiveFields || (0, config_1.getConfig)()?.sensitiveFields || config_1.DEFAULT_SENSITIVE_FIELDS;
35
+ // Handle arrays
36
+ if (Array.isArray(data)) {
37
+ return data.map((item) => (0, exports.sanitizeData)(item, fieldsToMask, seen));
38
+ }
39
+ // Handle objects
40
+ const sanitized = {};
41
+ for (const [key, value] of Object.entries(data)) {
42
+ if (isSensitiveField(key, fieldsToMask)) {
43
+ // Mask sensitive string values
44
+ if (typeof value === 'string') {
45
+ sanitized[key] = '[REDACTED]';
46
+ }
47
+ else if (value !== null && value !== undefined) {
48
+ sanitized[key] = '[REDACTED]';
49
+ }
50
+ else {
51
+ sanitized[key] = value;
52
+ }
53
+ }
54
+ else if (typeof value === 'object' && value !== null) {
55
+ sanitized[key] = (0, exports.sanitizeData)(value, fieldsToMask, seen);
56
+ }
57
+ else {
58
+ sanitized[key] = value;
59
+ }
60
+ }
61
+ return sanitized;
62
+ };
63
+ exports.sanitizeData = sanitizeData;
64
+ /**
65
+ * Sanitize headers, specifically targeting authorization-type headers
66
+ */
67
+ const sanitizeHeaders = (headers) => {
68
+ const sensitiveHeaders = [
69
+ 'authorization',
70
+ 'x-api-key',
71
+ 'x-auth-token',
72
+ 'cookie',
73
+ 'set-cookie',
74
+ 'x-access-token',
75
+ 'x-refresh-token',
76
+ ];
77
+ const sanitized = { ...headers };
78
+ for (const header of sensitiveHeaders) {
79
+ if (sanitized[header]) {
80
+ sanitized[header] = '[REDACTED]';
81
+ }
82
+ // Also check lowercase and uppercase variants
83
+ const lowerHeader = header.toLowerCase();
84
+ const upperHeader = header.toUpperCase();
85
+ if (sanitized[lowerHeader]) {
86
+ sanitized[lowerHeader] = '[REDACTED]';
87
+ }
88
+ if (sanitized[upperHeader]) {
89
+ sanitized[upperHeader] = '[REDACTED]';
90
+ }
91
+ }
92
+ return sanitized;
93
+ };
94
+ exports.sanitizeHeaders = sanitizeHeaders;
95
+ /**
96
+ * Truncate large values to prevent log bloat
97
+ */
98
+ const truncateValue = (value, maxLength = 1000) => {
99
+ if (typeof value === 'string' && value.length > maxLength) {
100
+ return `${value.substring(0, maxLength)}... [TRUNCATED: ${value.length} chars]`;
101
+ }
102
+ if (Array.isArray(value) && value.length > 100) {
103
+ return [...value.slice(0, 100), `... [TRUNCATED: ${value.length} items]`];
104
+ }
105
+ return value;
106
+ };
107
+ exports.truncateValue = truncateValue;
108
+ /**
109
+ * Deep clone and sanitize for logging
110
+ */
111
+ const prepareForLogging = (data, options) => {
112
+ const sanitized = (0, exports.sanitizeData)(data, options?.sensitiveFields);
113
+ if (options?.truncateLength) {
114
+ const truncate = (obj) => {
115
+ if (typeof obj !== 'object' || obj === null) {
116
+ return (0, exports.truncateValue)(obj, options.truncateLength);
117
+ }
118
+ if (Array.isArray(obj)) {
119
+ return obj.map(truncate);
120
+ }
121
+ const result = {};
122
+ for (const [key, value] of Object.entries(obj)) {
123
+ result[key] = truncate(value);
124
+ }
125
+ return result;
126
+ };
127
+ return truncate(sanitized);
128
+ }
129
+ return sanitized;
130
+ };
131
+ exports.prepareForLogging = prepareForLogging;
132
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"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"}