rpc-express-toolkit 2.3.3 → 3.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.
package/src/logger.js CHANGED
@@ -1,153 +1,184 @@
1
- "use strict";
2
-
3
- /**
4
- * Simple structured logger for JSON-RPC operations
5
- */
6
- class Logger {
7
- constructor(options = {}) {
8
- this.level = options.level || 'info';
9
- this.enabled = options.enabled !== false;
10
- this.prefix = options.prefix || '[JSON-RPC]';
11
- this.customLogger = options.logger || null;
12
-
13
- this.levels = {
14
- error: 0,
15
- warn: 1,
16
- info: 2,
17
- debug: 3,
18
- trace: 4
19
- };
20
- }
21
-
22
- /**
23
- * Check if the given level should be logged
24
- * @param {string} level
25
- * @returns {boolean}
26
- */
27
- shouldLog(level) {
28
- return this.enabled && this.levels[level] <= this.levels[this.level];
29
- }
30
-
31
- /**
32
- * Format log message with metadata
33
- * @param {string} level
34
- * @param {string} message
35
- * @param {Object} meta
36
- * @returns {Object}
37
- */
38
- formatMessage(level, message, meta = {}) {
39
- return {
40
- timestamp: new Date().toISOString(),
41
- level: level.toUpperCase(),
42
- message,
43
- ...meta
44
- };
45
- }
46
-
47
- /**
48
- * Generic log method
49
- * @param {string} level
50
- * @param {string} message
51
- * @param {Object} meta
52
- */
53
- log(level, message, meta = {}) {
54
- if (!this.shouldLog(level)) return;
55
-
56
- const logData = this.formatMessage(level, message, meta);
57
-
58
- if (this.customLogger) {
59
- this.customLogger[level](logData);
60
- } else {
61
- const logMessage = `${this.prefix} ${logData.timestamp} [${logData.level}] ${message}`;
62
- const metaStr = Object.keys(meta).length > 0 ? ` | ${JSON.stringify(meta)}` : '';
63
- console[level === 'debug' || level === 'trace' ? 'log' : level](`${logMessage}${metaStr}`);
64
- }
65
- }
66
-
67
- error(message, meta) { this.log('error', message, meta); }
68
- warn(message, meta) { this.log('warn', message, meta); }
69
- info(message, meta) { this.log('info', message, meta); }
70
- debug(message, meta) { this.log('debug', message, meta); }
71
- trace(message, meta) { this.log('trace', message, meta); }
72
-
73
- /**
74
- * Log RPC call start
75
- * @param {string} method
76
- * @param {any} params
77
- * @param {string|number} id
78
- * @param {Object} req
79
- */
80
- rpcCall(method, params, id, req) {
81
- this.info('RPC call started', {
82
- method,
83
- id,
84
- params: this.sanitizeParams(params),
85
- userAgent: req.headers['user-agent'],
86
- ip: req.ip || req.connection?.remoteAddress
87
- });
88
- }
89
-
90
- /**
91
- * Log RPC call success
92
- * @param {string} method
93
- * @param {string|number} id
94
- * @param {number} duration
95
- * @param {any} result
96
- */
97
- rpcSuccess(method, id, duration, result) {
98
- this.info('RPC call completed', {
99
- method,
100
- id,
101
- duration: `${duration}ms`,
102
- resultType: typeof result,
103
- resultSize: result ? JSON.stringify(result).length : 0
104
- });
105
- }
106
-
107
- /**
108
- * Log RPC call error
109
- * @param {string} method
110
- * @param {string|number} id
111
- * @param {number} duration
112
- * @param {Error} error
113
- */
114
- rpcError(method, id, duration, error) {
115
- this.error('RPC call failed', {
116
- method,
117
- id,
118
- duration: `${duration}ms`,
119
- error: error.message,
120
- code: error.code,
121
- stack: error.stack
122
- });
123
- }
124
-
125
- /**
126
- * Sanitize parameters for logging (remove sensitive data)
127
- * @param {any} params
128
- * @returns {any}
129
- */
130
- sanitizeParams(params) {
131
- if (!params || typeof params !== 'object') return params;
132
-
133
- const sensitiveKeys = ['password', 'token', 'key', 'secret', 'auth', 'authorization'];
134
- const sanitized = Array.isArray(params) ? [...params] : { ...params };
135
-
136
- const sanitizeObj = (obj) => {
137
- if (typeof obj !== 'object' || obj === null) return obj;
138
-
139
- for (const [key, value] of Object.entries(obj)) {
140
- if (sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive))) {
141
- obj[key] = '[REDACTED]';
142
- } else if (typeof value === 'object') {
143
- sanitizeObj(value);
144
- }
145
- }
146
- return obj;
147
- };
148
-
149
- return sanitizeObj(sanitized);
150
- }
151
- }
152
-
153
- module.exports = Logger;
1
+ /**
2
+ * @file Logger Class
3
+ * @description A flexible logging system supporting multiple levels and custom formatting
4
+ */
5
+
6
+ /**
7
+ * Logger class for handling RPC logging
8
+ */
9
+ class Logger {
10
+ constructor(options = {}) {
11
+ this.level = options.level || 'info';
12
+ this.enabled = options.enabled !== false;
13
+ this.prefix = options.prefix || '[JSON-RPC]';
14
+ this.customLogger = options.logger || null;
15
+
16
+ this.levels = {
17
+ error: 0,
18
+ warn: 1,
19
+ info: 2,
20
+ debug: 3,
21
+ trace: 4,
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Check if the given level should be logged
27
+ * @param {string} level
28
+ * @returns {boolean}
29
+ */
30
+ shouldLog(level) {
31
+ return this.enabled && this.levels[level] <= this.levels[this.level];
32
+ }
33
+
34
+ /**
35
+ * Format log message with metadata
36
+ * @param {string} level
37
+ * @param {string} message
38
+ * @param {Object} meta
39
+ * @returns {Object}
40
+ */
41
+ formatMessage(level, message, meta = {}) {
42
+ return {
43
+ timestamp: new Date().toISOString(),
44
+ level: level.toUpperCase(),
45
+ message,
46
+ ...meta,
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Generic log method
52
+ * @param {string} level
53
+ * @param {string} message
54
+ * @param {Object} meta
55
+ */
56
+ log(level, message, meta = {}) {
57
+ if (!this.shouldLog(level)) return;
58
+
59
+ const logData = this.formatMessage(level, message, meta);
60
+
61
+ if (this.customLogger) {
62
+ this.customLogger[level](logData);
63
+ } else {
64
+ const logMessage = `${this.prefix} ${logData.timestamp} [${logData.level}] ${message}`;
65
+ const metaStr =
66
+ Object.keys(meta).length > 0 ? ` | ${JSON.stringify(meta)}` : '';
67
+ console[level === 'debug' || level === 'trace' ? 'log' : level](
68
+ `${logMessage}${metaStr}`
69
+ );
70
+ }
71
+ }
72
+
73
+ error(message, meta) {
74
+ this.log('error', message, meta);
75
+ }
76
+
77
+ warn(message, meta) {
78
+ this.log('warn', message, meta);
79
+ }
80
+
81
+ info(message, meta) {
82
+ this.log('info', message, meta);
83
+ }
84
+
85
+ debug(message, meta) {
86
+ this.log('debug', message, meta);
87
+ }
88
+
89
+ trace(message, meta) {
90
+ this.log('trace', message, meta);
91
+ }
92
+
93
+ /**
94
+ * Log RPC call start
95
+ * @param {string} method
96
+ * @param {any} params
97
+ * @param {string|number} id
98
+ * @param {Object} req
99
+ */
100
+ rpcCall(method, params, id, req) {
101
+ this.info('RPC call started', {
102
+ method,
103
+ id,
104
+ params: this.sanitizeParams(params),
105
+ userAgent: req.headers['user-agent'],
106
+ ip: req.ip || req.connection?.remoteAddress,
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Log RPC call success
112
+ * @param {string} method
113
+ * @param {string|number} id
114
+ * @param {number} duration
115
+ * @param {any} result
116
+ */
117
+ rpcSuccess(method, id, duration, result) {
118
+ this.info('RPC call completed', {
119
+ method,
120
+ id,
121
+ duration: `${duration}ms`,
122
+ resultType: typeof result,
123
+ resultSize: result ? JSON.stringify(result).length : 0,
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Log RPC call error
129
+ * @param {string} method
130
+ * @param {string|number} id
131
+ * @param {number} duration
132
+ * @param {Error} error
133
+ */
134
+ rpcError(method, id, duration, error) {
135
+ this.error('RPC call failed', {
136
+ method,
137
+ id,
138
+ duration: `${duration}ms`,
139
+ error: error.message,
140
+ code: error.code,
141
+ stack: error.stack,
142
+ });
143
+ }
144
+
145
+ /**
146
+ * Sanitize parameters for logging (remove sensitive data)
147
+ * @param {any} params
148
+ * @returns {any}
149
+ */
150
+ sanitizeParams(params) {
151
+ if (!params || typeof params !== 'object') return params;
152
+
153
+ const sensitiveKeys = [
154
+ 'password',
155
+ 'token',
156
+ 'key',
157
+ 'secret',
158
+ 'auth',
159
+ 'authorization',
160
+ ];
161
+ const sanitized = Array.isArray(params) ? [...params] : { ...params };
162
+
163
+ const sanitizeObj = (obj) => {
164
+ if (typeof obj !== 'object' || obj === null) return obj;
165
+
166
+ for (const [key, value] of Object.entries(obj)) {
167
+ if (
168
+ sensitiveKeys.some((sensitive) =>
169
+ key.toLowerCase().includes(sensitive)
170
+ )
171
+ ) {
172
+ obj[key] = '[REDACTED]';
173
+ } else if (typeof value === 'object') {
174
+ sanitizeObj(value);
175
+ }
176
+ }
177
+ return obj;
178
+ };
179
+
180
+ return sanitizeObj(sanitized);
181
+ }
182
+ }
183
+
184
+ module.exports = Logger;