unnbound-logger-sdk 3.0.0 → 3.0.1

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,475 @@
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.UnnboundLogger = exports.logger = void 0;
7
+ /**
8
+ * Core logger implementation
9
+ */
10
+ const pino_1 = __importDefault(require("pino"));
11
+ const logger_utils_1 = require("./utils/logger-utils");
12
+ const uuid_1 = require("uuid");
13
+ const trace_context_1 = require("./utils/trace-context");
14
+ const axios_1 = require("axios");
15
+ const http_status_messages_1 = require("./utils/http-status-messages");
16
+ const storage_1 = require("./storage");
17
+ exports.logger = (0, pino_1.default)({
18
+ level: process.env.LOG_LEVEL ?? 'info',
19
+ base: {
20
+ environment: process.env.ENVIRONMENT,
21
+ workflowId: process.env.UNNBOUND_WORKFLOW_ID,
22
+ workflowUrl: process.env.UNNBOUND_WORKFLOW_URL,
23
+ serviceId: process.env.UNNBOUND_SERVICE_ID,
24
+ deploymentId: process.env.UNNBOUND_DEPLOYMENT_ID,
25
+ },
26
+ mixin: () => {
27
+ console.log('storage', storage_1.storage.getStore());
28
+ return storage_1.storage.getStore() ?? {};
29
+ },
30
+ serializers: {
31
+ req: pino_1.default.stdSerializers.req,
32
+ res: pino_1.default.stdSerializers.res,
33
+ err: pino_1.default.stdSerializers.err,
34
+ },
35
+ // Let CloudWatch handle timestamps
36
+ timestamp: false,
37
+ // Change message field from 'msg' to 'messages'
38
+ messageKey: 'messages',
39
+ formatters: {
40
+ level: (level) => ({ level }),
41
+ },
42
+ });
43
+ /**
44
+ * UnnboundLogger provides typed, structured logging using Pino
45
+ */
46
+ class UnnboundLogger {
47
+ /**
48
+ * Creates a new UnnboundLogger instance
49
+ * @param options - Configuration options for the logger
50
+ */
51
+ constructor(options = {}) {
52
+ // Trace middleware
53
+ this.traceMiddleware = (req, res, next) => {
54
+ // Check if the route should be ignored
55
+ if (this.shouldIgnorePath(req.path, this.ignoreTraceRoutes)) {
56
+ return next();
57
+ }
58
+ const traceId = req.header(this.traceHeaderKey) || (0, uuid_1.v4)();
59
+ res.setHeader(this.traceHeaderKey, traceId);
60
+ trace_context_1.traceContext.run(traceId, () => {
61
+ // Log the incoming request
62
+ const reqLog = this.httpRequest(req, { traceId });
63
+ // Capture response body for logging
64
+ const originalSend = res.send;
65
+ res.send = function (body) {
66
+ res.locals.body = body;
67
+ return originalSend.call(this, body);
68
+ };
69
+ // Log the response when it finishes
70
+ res.on('finish', () => {
71
+ this.httpResponse(res, req, { requestId: reqLog.requestId, traceId });
72
+ });
73
+ next();
74
+ });
75
+ };
76
+ // Axios trace middleware
77
+ this.axiosTraceMiddleware = {
78
+ onFulfilled: (config) => {
79
+ // Check if the URL should be ignored
80
+ if (config.url && this.shouldIgnorePath(config.url, this.ignoreAxiosTraceRoutes)) {
81
+ return config;
82
+ }
83
+ const traceId = trace_context_1.traceContext.getTraceId();
84
+ if (traceId) {
85
+ const headers = new axios_1.AxiosHeaders(config.headers);
86
+ headers.set(this.traceHeaderKey, traceId);
87
+ config.headers = headers;
88
+ }
89
+ // Store request start time and generate requestId for duration calculation and correlation
90
+ const startTime = Date.now();
91
+ const requestId = (0, uuid_1.v4)();
92
+ config.metadata = { startTime, requestId };
93
+ // Log the outgoing request using proper httpRequest method
94
+ const mockReq = {
95
+ method: config.method?.toUpperCase() || 'UNKNOWN',
96
+ url: `${config.baseURL || ''}${config.url}`,
97
+ originalUrl: `${config.baseURL || ''}${config.url}`,
98
+ headers: config.headers || {},
99
+ body: (0, logger_utils_1.safeJsonParse)(config.data),
100
+ ip: 'outgoing', // Mark as outgoing request
101
+ protocol: 'https', // Default for outgoing
102
+ secure: true,
103
+ get: () => undefined, // Mock get method for constructFullUrl
104
+ };
105
+ this.httpRequest(mockReq, {
106
+ traceId,
107
+ requestId,
108
+ startTime,
109
+ });
110
+ return config;
111
+ },
112
+ onRejected: (error) => {
113
+ return Promise.reject(error);
114
+ },
115
+ };
116
+ // Axios response interceptor (should be used separately)
117
+ this.axiosResponseInterceptor = {
118
+ onFulfilled: (response) => {
119
+ // Check if the URL should be ignored
120
+ const url = `${response.config?.baseURL || ''}${response.config?.url}`;
121
+ if (url && this.shouldIgnorePath(url, this.ignoreAxiosTraceRoutes)) {
122
+ return response;
123
+ }
124
+ // Calculate duration
125
+ const startTime = response.config.metadata?.startTime || Date.now();
126
+ const requestId = response.config.metadata?.requestId;
127
+ const duration = Date.now() - startTime;
128
+ // Log the successful response using proper httpResponse method
129
+ const mockReq = {
130
+ method: response.config.method?.toUpperCase() || 'UNKNOWN',
131
+ url: `${response.config.baseURL || ''}${response.config.url}`,
132
+ originalUrl: `${response.config.baseURL || ''}${response.config.url}`,
133
+ ip: 'outgoing', // Mark as outgoing request
134
+ protocol: 'https', // Default for outgoing
135
+ secure: true,
136
+ get: () => undefined, // Mock get method for constructFullUrl
137
+ };
138
+ const mockRes = {
139
+ statusCode: response.status,
140
+ locals: {
141
+ body: (0, logger_utils_1.safeJsonParse)(response.data),
142
+ startTime: startTime,
143
+ traceId: trace_context_1.traceContext.getTraceId(),
144
+ requestId: requestId,
145
+ },
146
+ getHeaders: () => response.headers || {},
147
+ };
148
+ this.httpResponse(mockRes, mockReq, {
149
+ requestId,
150
+ duration,
151
+ traceId: trace_context_1.traceContext.getTraceId(),
152
+ });
153
+ return response;
154
+ },
155
+ onRejected: (error) => {
156
+ // Check if the URL should be ignored
157
+ const url = `${error.config?.baseURL || ''}${error.config?.url}`;
158
+ if (url && this.shouldIgnorePath(url, this.ignoreAxiosTraceRoutes)) {
159
+ return Promise.reject(error);
160
+ }
161
+ // Calculate duration for error responses
162
+ const startTime = error.config?.metadata?.startTime || Date.now();
163
+ const requestId = error.config?.metadata?.requestId;
164
+ const duration = Date.now() - startTime;
165
+ // Log the error response using proper httpResponse method
166
+ if (error.response) {
167
+ const mockReq = {
168
+ method: error.config?.method?.toUpperCase() || 'UNKNOWN',
169
+ url: `${error.config?.baseURL || ''}${error.config?.url}`,
170
+ originalUrl: `${error.config?.baseURL || ''}${error.config?.url}`,
171
+ ip: 'outgoing', // Mark as outgoing request
172
+ protocol: 'https', // Default for outgoing
173
+ secure: true,
174
+ get: () => undefined, // Mock get method for constructFullUrl
175
+ };
176
+ const mockRes = {
177
+ statusCode: error.response.status,
178
+ locals: {
179
+ body: (0, logger_utils_1.safeJsonParse)(error.response.data),
180
+ startTime: startTime,
181
+ traceId: trace_context_1.traceContext.getTraceId(),
182
+ requestId: requestId,
183
+ },
184
+ getHeaders: () => error.response.headers || {},
185
+ };
186
+ this.httpResponse(mockRes, mockReq, {
187
+ requestId,
188
+ duration,
189
+ traceId: trace_context_1.traceContext.getTraceId(),
190
+ });
191
+ }
192
+ else {
193
+ // For network errors without response, log as general error
194
+ this.error('HTTP Request Failed', {
195
+ context: {
196
+ reason: 'No response received',
197
+ method: error.config?.method?.toUpperCase() || 'UNKNOWN',
198
+ url: `${error.config?.baseURL || ''}${error.config?.url}`,
199
+ },
200
+ error: error.message,
201
+ requestId,
202
+ traceId: trace_context_1.traceContext.getTraceId(),
203
+ });
204
+ }
205
+ return Promise.reject(error);
206
+ },
207
+ };
208
+ this.workflowId = process.env.UNNBOUND_WORKFLOW_ID || '';
209
+ this.workflowUrl = process.env.UNNBOUND_WORKFLOW_URL || '';
210
+ this.serviceId = process.env.UNNBOUND_SERVICE_ID || '';
211
+ this.deploymentId = process.env.UNNBOUND_DEPLOYMENT_ID || '';
212
+ this.traceHeaderKey = options.traceHeaderKey || 'unnbound-trace-id';
213
+ this.ignoreTraceRoutes = options.ignoreTraceRoutes || [];
214
+ this.ignoreAxiosTraceRoutes = options.ignoreAxiosTraceRoutes || [];
215
+ // Create Pino logger
216
+ this.logger = (0, pino_1.default)({
217
+ level: 'info',
218
+ base: {
219
+ // Disable all default base fields (pid, hostname) and add our own
220
+ workflowId: this.workflowId,
221
+ serviceId: this.serviceId,
222
+ deploymentId: this.deploymentId,
223
+ },
224
+ // Let CloudWatch handle timestamps
225
+ timestamp: false,
226
+ // Change message field from 'msg' to 'messages'
227
+ messageKey: 'messages',
228
+ formatters: {
229
+ level: (level) => ({ level }),
230
+ },
231
+ });
232
+ }
233
+ /**
234
+ * Checks if a path matches any of the ignore patterns
235
+ * @param path - The path to check
236
+ * @param patterns - Array of glob patterns to match against
237
+ * @returns boolean indicating if the path should be ignored
238
+ */
239
+ shouldIgnorePath(path, patterns) {
240
+ return patterns.some((pattern) => {
241
+ // Convert glob pattern to regex
242
+ const regexPattern = pattern
243
+ .replace(/\./g, '\\.') // Escape dots
244
+ .replace(/\*/g, '.*') // Convert * to .*
245
+ .replace(/\?/g, '.'); // Convert ? to .
246
+ const regex = new RegExp(`^${regexPattern}$`);
247
+ return regex.test(path);
248
+ });
249
+ }
250
+ /**
251
+ * Logs a general message
252
+ * @param level - Log level
253
+ * @param message - Log message
254
+ * @param options - Additional logging options
255
+ */
256
+ log(level, message, options = {}) {
257
+ const logId = (0, uuid_1.v4)();
258
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
259
+ const requestId = options.requestId || (0, uuid_1.v4)();
260
+ let logEntry;
261
+ const { traceId: optionTraceId, requestId: optionRequestId, level: optionLevel, ...restOptions } = options;
262
+ // If restOptions has any properties, we'll add them to data later
263
+ const hasRestOptions = Object.keys(restOptions).length > 0;
264
+ const baseEntry = {
265
+ logId,
266
+ type: 'general',
267
+ workflowId: this.workflowId,
268
+ serviceId: this.serviceId,
269
+ traceId,
270
+ requestId,
271
+ deploymentId: this.deploymentId,
272
+ };
273
+ if (message instanceof Error) {
274
+ logEntry = {
275
+ ...baseEntry,
276
+ message: message.name,
277
+ error: message,
278
+ ...(hasRestOptions && { data: restOptions }),
279
+ };
280
+ }
281
+ else if (typeof message === 'string') {
282
+ logEntry = {
283
+ ...baseEntry,
284
+ message,
285
+ ...(hasRestOptions && { data: restOptions }),
286
+ };
287
+ }
288
+ else {
289
+ // If message is an object, wrap it in a 'data' key
290
+ const messageObj = message;
291
+ logEntry = {
292
+ ...baseEntry,
293
+ message: 'Structured log data',
294
+ data: hasRestOptions ? { ...messageObj, ...restOptions } : messageObj,
295
+ };
296
+ }
297
+ // Separate the message from the log data and explicitly exclude any level field
298
+ const { message: logMessage, level: excludedLevel, ...logData } = logEntry;
299
+ this.logger[level](logData, logMessage);
300
+ return logEntry;
301
+ }
302
+ /**
303
+ * Logs an error message
304
+ * @param message - Error message or object
305
+ * @param options - Additional logging options
306
+ */
307
+ error(message, options = {}) {
308
+ return this.log('error', message, options);
309
+ }
310
+ /**
311
+ * Logs a warning message
312
+ * @param message - Warning message
313
+ * @param options - Additional logging options
314
+ */
315
+ warn(message, options = {}) {
316
+ return this.log('warn', message, options);
317
+ }
318
+ /**
319
+ * Logs an info message
320
+ * @param message - Info message
321
+ * @param options - Additional logging options
322
+ */
323
+ info(message, options = {}) {
324
+ return this.log('info', message, options);
325
+ }
326
+ /**
327
+ * Logs a debug message
328
+ * @param message - Debug message
329
+ * @param options - Additional logging options
330
+ */
331
+ debug(message, options = {}) {
332
+ return this.log('debug', message, options);
333
+ }
334
+ /**
335
+ * Constructs the full URL from request information
336
+ * @param req - Express request object
337
+ * @returns Full URL string
338
+ */
339
+ constructFullUrl(req) {
340
+ // If the URL is already absolute, return it directly
341
+ const reqUrl = req.originalUrl || req.url;
342
+ if (reqUrl?.startsWith('http://') || reqUrl?.startsWith('https://')) {
343
+ return reqUrl;
344
+ }
345
+ // Check if we have a workflow URL configured (preferred method)
346
+ if (this.workflowUrl) {
347
+ // Use workflow URL as the base URL
348
+ return `${this.workflowUrl.replace(/\/$/, '')}${reqUrl}`;
349
+ }
350
+ // Fallback to constructing from request info for incoming requests
351
+ const protocol = req.protocol || (req.secure ? 'https' : 'http');
352
+ const host = req.get('host') || req.get('x-forwarded-host') || 'localhost';
353
+ return `${protocol}://${host}${reqUrl}`;
354
+ }
355
+ /**
356
+ * Logs an HTTP request
357
+ * @param req - Express request object
358
+ * @param options - Additional logging options
359
+ * @returns The request ID for correlating with the response
360
+ */
361
+ httpRequest(req, options = {}) {
362
+ const logId = (0, uuid_1.v4)();
363
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
364
+ const requestId = options.requestId || (0, uuid_1.v4)();
365
+ const startTime = options.startTime || Date.now();
366
+ // Store request metadata in res.locals for later use
367
+ if (req.res) {
368
+ req.res.locals.requestId = requestId;
369
+ req.res.locals.startTime = startTime;
370
+ req.res.locals.traceId = traceId;
371
+ req.res.locals.workflowId = this.workflowId;
372
+ req.res.locals.workflowUrl = this.workflowUrl;
373
+ req.res.locals.serviceId = this.serviceId;
374
+ }
375
+ const logEntry = {
376
+ logId,
377
+ type: 'httpRequest',
378
+ message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
379
+ workflowId: this.workflowId,
380
+ serviceId: this.serviceId,
381
+ traceId,
382
+ requestId,
383
+ deploymentId: this.deploymentId,
384
+ duration: 0, // Will be updated in response
385
+ httpRequest: {
386
+ url: this.constructFullUrl(req),
387
+ method: req.method,
388
+ headers: (0, logger_utils_1.filterHeaders)(req.headers),
389
+ ip: (0, logger_utils_1.normalizeIp)(req.ip),
390
+ body: (0, logger_utils_1.safeJsonParse)(req.body),
391
+ },
392
+ };
393
+ const { message: logMessage, ...logData } = logEntry;
394
+ this.logger[options.level || 'info'](logData, logMessage);
395
+ return logEntry;
396
+ }
397
+ /**
398
+ * Logs an HTTP response
399
+ * @param res - Express response object
400
+ * @param req - Express request object
401
+ * @param options - Additional logging options
402
+ */
403
+ httpResponse(res, req, options = {}) {
404
+ const logId = (0, uuid_1.v4)();
405
+ const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
406
+ const startTime = res.locals.startTime || options.startTime || Date.now();
407
+ const workflowId = res.locals.workflowId || this.workflowId;
408
+ const serviceId = res.locals.serviceId || this.serviceId;
409
+ const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
410
+ const duration = options.duration || Date.now() - startTime;
411
+ // Determine log level based on status code
412
+ let level = options.level || 'info';
413
+ if (!options.level) {
414
+ if (res.statusCode >= 400) {
415
+ level = 'error';
416
+ }
417
+ else {
418
+ level = 'info';
419
+ }
420
+ }
421
+ const logEntry = {
422
+ logId,
423
+ type: 'httpResponse',
424
+ message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
425
+ workflowId: workflowId || '',
426
+ serviceId: serviceId || '',
427
+ traceId,
428
+ requestId,
429
+ deploymentId: this.deploymentId,
430
+ duration,
431
+ httpResponse: {
432
+ url: this.constructFullUrl(req),
433
+ method: req.method,
434
+ headers: (0, logger_utils_1.filterHeaders)(res.getHeaders()),
435
+ ip: (0, logger_utils_1.normalizeIp)(req.ip),
436
+ status: res.statusCode,
437
+ body: (0, logger_utils_1.safeJsonParse)(res.locals.body),
438
+ },
439
+ };
440
+ const { message: logMessage, ...logData } = logEntry;
441
+ this.logger[level](logData, logMessage);
442
+ return logEntry;
443
+ }
444
+ /**
445
+ * Logs a database query transaction
446
+ * @param query - Database query details
447
+ * @param options - Additional logging options
448
+ */
449
+ dbQueryTransaction(query, options = {}) {
450
+ const logId = (0, uuid_1.v4)();
451
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
452
+ const requestId = options.requestId || (0, uuid_1.v4)();
453
+ const duration = options.duration || (options.startTime ? Date.now() - options.startTime : 0);
454
+ const level = query.status === 'success' ? 'info' : 'error';
455
+ const logEntry = {
456
+ logId,
457
+ type: 'dbQueryTransaction',
458
+ message: `DB Query ${query.status} - ${query.vendor}`,
459
+ workflowId: this.workflowId,
460
+ serviceId: this.serviceId,
461
+ traceId,
462
+ requestId,
463
+ deploymentId: this.deploymentId,
464
+ duration,
465
+ db: query,
466
+ };
467
+ const { message: logMessage, ...logData } = logEntry;
468
+ this.logger[level](logData, logMessage);
469
+ return logEntry;
470
+ }
471
+ }
472
+ exports.UnnboundLogger = UnnboundLogger;
473
+ process.on('uncaughtException', (err, origin) => {
474
+ exports.logger.error({ err, origin }, `Uncaught exception.`);
475
+ });
@@ -0,0 +1,9 @@
1
+ interface HttpStatus {
2
+ message: string;
3
+ description: string;
4
+ }
5
+ export declare const httpStatusDetails: {
6
+ [key: number]: HttpStatus;
7
+ };
8
+ export declare function getStatusMessage(statusCode: number): string;
9
+ export {};
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.httpStatusDetails = void 0;
4
+ exports.getStatusMessage = getStatusMessage;
5
+ exports.httpStatusDetails = {
6
+ 100: {
7
+ message: 'Continue',
8
+ description: 'The server has received the request headers, and the client should proceed to send the request body',
9
+ },
10
+ 101: {
11
+ message: 'Switching Protocols',
12
+ description: 'The requester has asked the server to switch protocols',
13
+ },
14
+ 103: {
15
+ message: 'Early Hints',
16
+ description: 'Used with the Link header to allow the browser to start preloading resources while the server prepares a response',
17
+ },
18
+ 200: { message: 'OK', description: 'The request is OK' },
19
+ 201: {
20
+ message: 'Created',
21
+ description: 'The request has been fulfilled, and a new resource is created',
22
+ },
23
+ 202: {
24
+ message: 'Accepted',
25
+ description: 'The request has been accepted for processing, but the processing has not been completed',
26
+ },
27
+ 203: {
28
+ message: 'Non-Authoritative Information',
29
+ description: 'The request has been successfully processed, but is returning information that may be from another source',
30
+ },
31
+ 204: {
32
+ message: 'No Content',
33
+ description: 'The request has been successfully processed, but is not returning any content',
34
+ },
35
+ 205: {
36
+ message: 'Reset Content',
37
+ description: 'The request has been successfully processed, but is not returning any content, and requires that the requester reset the document view',
38
+ },
39
+ 206: {
40
+ message: 'Partial Content',
41
+ description: 'The server is delivering only part of the resource due to a range header sent by the client',
42
+ },
43
+ 300: {
44
+ message: 'Multiple Choices',
45
+ description: 'A link list. The user can select a link and go to that location. Maximum five addresses',
46
+ },
47
+ 301: { message: 'Moved Permanently', description: 'The requested page has moved to a new URL' },
48
+ 302: { message: 'Found', description: 'The requested page has moved temporarily to a new URL' },
49
+ 303: {
50
+ message: 'See Other',
51
+ description: 'The requested page can be found under a different URL',
52
+ },
53
+ 304: {
54
+ message: 'Not Modified',
55
+ description: 'Indicates the requested page has not been modified since last requested',
56
+ },
57
+ 307: {
58
+ message: 'Temporary Redirect',
59
+ description: 'The requested page has moved temporarily to a new URL',
60
+ },
61
+ 308: {
62
+ message: 'Permanent Redirect',
63
+ description: 'The requested page has moved permanently to a new URL',
64
+ },
65
+ 400: { message: 'Bad Request', description: 'The request cannot be fulfilled due to bad syntax' },
66
+ 401: {
67
+ message: 'Unauthorized',
68
+ description: 'The request was a legal request, but the server is refusing to respond to it. For use when authentication is possible but has failed or not yet been provided',
69
+ },
70
+ 402: { message: 'Payment Required', description: 'Reserved for future use' },
71
+ 403: {
72
+ message: 'Forbidden',
73
+ description: 'The request was a legal request, but the server is refusing to respond to it',
74
+ },
75
+ 404: {
76
+ message: 'Not Found',
77
+ description: 'The requested page could not be found but may be available again in the future',
78
+ },
79
+ 405: {
80
+ message: 'Method Not Allowed',
81
+ description: 'A request was made of a page using a request method not supported by that page',
82
+ },
83
+ 406: {
84
+ message: 'Not Acceptable',
85
+ description: 'The server can only generate a response that is not accepted by the client',
86
+ },
87
+ 407: {
88
+ message: 'Proxy Authentication Required',
89
+ description: 'The client must first authenticate itself with the proxy',
90
+ },
91
+ 408: { message: 'Request Timeout', description: 'The server timed out waiting for the request' },
92
+ 409: {
93
+ message: 'Conflict',
94
+ description: 'The request could not be completed because of a conflict in the request',
95
+ },
96
+ 410: { message: 'Gone', description: 'The requested page is no longer available' },
97
+ 411: {
98
+ message: 'Length Required',
99
+ description: 'The "Content-Length" is not defined. The server will not accept the request without it',
100
+ },
101
+ 412: {
102
+ message: 'Precondition Failed',
103
+ description: 'The precondition given in the request evaluated to false by the server',
104
+ },
105
+ 413: {
106
+ message: 'Request Too Large',
107
+ description: 'The server will not accept the request, because the request entity is too large',
108
+ },
109
+ 414: {
110
+ message: 'Request-URI Too Long',
111
+ description: 'The server will not accept the request, because the URI is too long. Occurs when you convert a POST request to a GET request with a long query information',
112
+ },
113
+ 415: {
114
+ message: 'Unsupported Media Type',
115
+ description: 'The server will not accept the request, because the media type is not supported',
116
+ },
117
+ 416: {
118
+ message: 'Range Not Satisfiable',
119
+ description: 'The client has asked for a portion of the file, but the server cannot supply that portion',
120
+ },
121
+ 417: {
122
+ message: 'Expectation Failed',
123
+ description: 'The server cannot meet the requirements of the Expect request-header field',
124
+ },
125
+ 500: {
126
+ message: 'Internal Server Error',
127
+ description: 'A generic error message, given when no more specific message is suitable',
128
+ },
129
+ 501: {
130
+ message: 'Not Implemented',
131
+ description: 'The server either does not recognize the request method, or it lacks the ability to fulfill the request',
132
+ },
133
+ 502: {
134
+ message: 'Bad Gateway',
135
+ description: 'The server was acting as a gateway or proxy and received an invalid response from the upstream server',
136
+ },
137
+ 503: {
138
+ message: 'Service Unavailable',
139
+ description: 'The server is currently unavailable (overloaded or down)',
140
+ },
141
+ 504: {
142
+ message: 'Gateway Timeout',
143
+ description: 'The server was acting as a gateway or proxy and did not receive a timely response from the upstream server',
144
+ },
145
+ 505: {
146
+ message: 'HTTP Version Not Supported',
147
+ description: 'The server does not support the HTTP protocol version used in the request',
148
+ },
149
+ 511: {
150
+ message: 'Network Authentication Required',
151
+ description: 'The client needs to authenticate to gain network access',
152
+ },
153
+ };
154
+ function getStatusMessage(statusCode) {
155
+ const status = exports.httpStatusDetails[statusCode];
156
+ if (status) {
157
+ return `${statusCode} ${status.message} - ${status.description}`;
158
+ }
159
+ return `${statusCode} Unknown Status`;
160
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Generates the current timestamp in ISO format
3
+ * @returns ISO timestamp string
4
+ */
5
+ export declare function generateTimestamp(): string;
6
+ /**
7
+ * Gets or creates a trace ID for a workflow
8
+ * @param workflowId - The workflow ID to get a trace ID for
9
+ * @returns A trace ID associated with the workflow
10
+ */
11
+ export declare function getTraceId(workflowId: string): string;
12
+ /**
13
+ * Clears a trace ID from the map
14
+ * @param workflowId - The workflow ID to clear
15
+ */
16
+ export declare function clearTraceId(workflowId: string): void;
17
+ /**
18
+ * Filters an object of headers, returning a new object with only the allowed headers.
19
+ * @param headers The original headers object.
20
+ * @returns A new object containing only the headers from the allow-list.
21
+ */
22
+ export declare function filterHeaders(headers?: Record<string, any>): Record<string, string>;
23
+ /**
24
+ * Safely parses JSON strings, returning the original data if parsing fails or if it's not a string.
25
+ * @param data The data to potentially parse as JSON.
26
+ * @returns Parsed JSON object or the original data.
27
+ */
28
+ export declare function safeJsonParse(data: any): any;
29
+ /**
30
+ * Normalizes IP addresses by removing IPv6 mapping prefix for IPv4 addresses.
31
+ * @param ip The IP address to normalize.
32
+ * @returns Normalized IP address string.
33
+ */
34
+ export declare function normalizeIp(ip: string | undefined): string | undefined;