Skip to content

Commit 334a30e

Browse files
committed
Version 1.1.2 - 12-21-2025
1 parent 90a3a45 commit 334a30e

File tree

4 files changed

+209
-124
lines changed

4 files changed

+209
-124
lines changed

index.cjs

Lines changed: 91 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,91 @@
1-
const winston = require('winston');
2-
3-
/**
4-
* Factory to create a Winston logger instance.
5-
* @param {Object} [options]
6-
* @param {string} [options.level] - Log level (default: process.env.LOG_LEVEL or 'info')
7-
* @param {Array} [options.transports] - Array of Winston transports (default: Console)
8-
* @returns {winston.Logger}
9-
*/
10-
const createLogger = ({
11-
level = process.env.LOG_LEVEL || 'info',
12-
transports = [new winston.transports.Console()]
13-
} = {}) => {
14-
const logger = winston.createLogger({
15-
level,
16-
format: winston.format.printf(({ level, message, ...meta }) => {
17-
let msg = `[${level.toUpperCase()}] ${message}`;
18-
const metaKeys = Object.keys(meta).filter(k => k !== 'level' && k !== 'message');
19-
if (metaKeys.length > 0) {
20-
// Custom replacer to handle BigInt and circular references
21-
const seen = new WeakSet();
22-
const replacer = (key, value) => {
23-
if (typeof value === 'bigint') return value.toString() + 'n';
24-
if (typeof value === 'object' && value !== null) {
25-
if (seen.has(value)) return '[Circular]';
26-
seen.add(value);
27-
}
28-
return value;
29-
};
30-
msg += ' ' + JSON.stringify(Object.fromEntries(metaKeys.map(k => [k, meta[k]])), replacer);
31-
}
32-
return msg;
33-
}),
34-
transports
35-
});
36-
37-
// Patch logger methods to support primitive/array as meta
38-
const levels = Object.keys(logger.levels || winston.config.npm.levels);
39-
levels.forEach((method) => {
40-
const orig = logger[method];
41-
logger[method] = function (msg, meta) {
42-
if (arguments.length === 2 && (typeof meta !== 'object' || meta === null || Array.isArray(meta))) {
43-
return orig.call(this, msg, { value: meta });
44-
}
45-
return orig.apply(this, arguments);
46-
};
47-
});
48-
return logger;
49-
};
50-
51-
const log = createLogger();
52-
module.exports = log;
53-
module.exports.createLogger = createLogger;
1+
const winston = require('winston');
2+
3+
/**
4+
* Factory to create a Winston logger instance.
5+
* @param {Object} [options]
6+
* @param {string} [options.level] - Log level (default: process.env.LOG_LEVEL or 'info')
7+
* @param {Array} [options.transports] - Array of Winston transports (default: Console)
8+
* @returns {winston.Logger}
9+
*/
10+
const createLogger = ({
11+
level = process.env.LOG_LEVEL || 'info',
12+
transports = [new winston.transports.Console()]
13+
} = {}) => {
14+
// Safe serializer: shallowly summarize objects without invoking toJSON/getters
15+
const safeSerialize = (obj) => {
16+
try {
17+
if (obj === null) return null;
18+
if (typeof obj !== 'object') return obj;
19+
const out = {};
20+
for (const k of Object.keys(obj)) {
21+
try {
22+
const v = obj[k];
23+
if (v === null) { out[k] = null; continue; }
24+
if (typeof v === 'object') {
25+
const info = { type: v && v.constructor && v.constructor.name ? v.constructor.name : 'Object' };
26+
try { if ('id' in v && (typeof v.id === 'string' || typeof v.id === 'number')) info.id = v.id; } catch (e) {}
27+
try { if ('name' in v && typeof v.name === 'string') info.name = v.name; } catch (e) {}
28+
out[k] = info;
29+
} else if (typeof v === 'function') {
30+
out[k] = `[Function: ${v.name || 'anonymous'}]`;
31+
} else {
32+
out[k] = v;
33+
}
34+
} catch (e) {
35+
out[k] = '[Unserializable]';
36+
}
37+
}
38+
return out;
39+
} catch (e) {
40+
try { return String(obj); } catch (ee) { return '[Unserializable]'; }
41+
}
42+
};
43+
44+
const logger = winston.createLogger({
45+
level,
46+
format: winston.format.printf(({ level, message, ...meta }) => {
47+
let msg = `[${level.toUpperCase()}] ${message}`;
48+
const metaKeys = Object.keys(meta).filter(k => k !== 'level' && k !== 'message');
49+
if (metaKeys.length > 0) {
50+
// Custom replacer to handle BigInt and circular references
51+
const seen = new WeakSet();
52+
const replacer = (key, value) => {
53+
if (typeof value === 'bigint') return value.toString() + 'n';
54+
if (typeof value === 'object' && value !== null) {
55+
if (seen.has(value)) return '[Circular]';
56+
seen.add(value);
57+
}
58+
return value;
59+
};
60+
const safeMeta = {};
61+
for (const k of metaKeys) {
62+
try { safeMeta[k] = safeSerialize(meta[k]); } catch (e) { safeMeta[k] = '[Unserializable]'; }
63+
}
64+
try {
65+
msg += ' ' + JSON.stringify(safeMeta, replacer);
66+
} catch (e) {
67+
try { msg += ' ' + String(safeMeta); } catch (ee) { msg += ' [Unserializable meta]'; }
68+
}
69+
}
70+
return msg;
71+
}),
72+
transports
73+
});
74+
75+
// Patch logger methods to support primitive/array as meta
76+
const levels = Object.keys(logger.levels || winston.config.npm.levels);
77+
levels.forEach((method) => {
78+
const orig = logger[method];
79+
logger[method] = function (msg, meta) {
80+
if (arguments.length === 2 && (typeof meta !== 'object' || meta === null || Array.isArray(meta))) {
81+
return orig.call(this, msg, { value: meta });
82+
}
83+
return orig.apply(this, arguments);
84+
};
85+
});
86+
return logger;
87+
};
88+
89+
const log = createLogger();
90+
module.exports = log;
91+
module.exports.createLogger = createLogger;

index.mjs

Lines changed: 100 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,100 @@
1-
import winston from 'winston';
2-
3-
/**
4-
* Factory to create a Winston logger instance.
5-
* @param {Object} [options]
6-
* @param {string} [options.level] - Log level (default: process.env.LOG_LEVEL or 'info')
7-
* @param {Array} [options.transports] - Array of Winston transports (default: Console)
8-
* @returns {winston.Logger}
9-
*/
10-
export const createLogger = ({
11-
level = process.env.LOG_LEVEL || 'info',
12-
transports = [new winston.transports.Console()]
13-
} = {}) => {
14-
const logger = winston.createLogger({
15-
level,
16-
format: winston.format.printf(({ level, message, ...meta }) => {
17-
let msg = `[${level.toUpperCase()}] ${message}`;
18-
const metaKeys = Object.keys(meta).filter(k => k !== 'level' && k !== 'message');
19-
if (metaKeys.length > 0) {
20-
// Custom replacer to handle BigInt and circular references
21-
const seen = new WeakSet();
22-
const replacer = (key, value) => {
23-
if (typeof value === 'bigint') return value.toString() + 'n';
24-
if (typeof value === 'object' && value !== null) {
25-
if (seen.has(value)) return '[Circular]';
26-
seen.add(value);
27-
}
28-
return value;
29-
};
30-
msg += ' ' + JSON.stringify(Object.fromEntries(metaKeys.map(k => [k, meta[k]])), replacer);
31-
}
32-
return msg;
33-
}),
34-
transports
35-
});
36-
37-
// Patch logger methods to support primitive/array as meta
38-
const levels = Object.keys(logger.levels || winston.config.npm.levels);
39-
levels.forEach((method) => {
40-
const orig = logger[method];
41-
logger[method] = function (msg, meta) {
42-
if (arguments.length === 2 && (typeof meta !== 'object' || meta === null || Array.isArray(meta))) {
43-
return orig.call(this, msg, { value: meta });
44-
}
45-
return orig.apply(this, arguments);
46-
};
47-
});
48-
return logger;
49-
};
50-
51-
const log = createLogger();
52-
export default log;
53-
export { log };
1+
import winston from 'winston';
2+
3+
/**
4+
* Factory to create a Winston logger instance.
5+
* @param {Object} [options]
6+
* @param {string} [options.level] - Log level (default: process.env.LOG_LEVEL or 'info')
7+
* @param {Array} [options.transports] - Array of Winston transports (default: Console)
8+
* @returns {winston.Logger}
9+
*/
10+
export const createLogger = ({
11+
level = process.env.LOG_LEVEL || 'info',
12+
transports = [new winston.transports.Console()]
13+
} = {}) => {
14+
// Safe serializer: shallowly summarize objects without invoking toJSON/getters
15+
const safeSerialize = (obj) => {
16+
try {
17+
if (obj === null) return null;
18+
if (typeof obj !== 'object') return obj;
19+
const out = {};
20+
for (const k of Object.keys(obj)) {
21+
try {
22+
const v = obj[k];
23+
if (v === null) { out[k] = null; continue; }
24+
if (typeof v === 'object') {
25+
const info = { type: v && v.constructor && v.constructor.name ? v.constructor.name : 'Object' };
26+
try { if ('id' in v && (typeof v.id === 'string' || typeof v.id === 'number')) info.id = v.id; } catch (e) {}
27+
try { if ('name' in v && typeof v.name === 'string') info.name = v.name; } catch (e) {}
28+
out[k] = info;
29+
} else if (typeof v === 'function') {
30+
out[k] = `[Function: ${v.name || 'anonymous'}]`;
31+
} else {
32+
out[k] = v;
33+
}
34+
} catch (e) {
35+
out[k] = '[Unserializable]';
36+
}
37+
}
38+
return out;
39+
} catch (e) {
40+
try { return String(obj); } catch (ee) { return '[Unserializable]'; }
41+
}
42+
};
43+
44+
const logger = winston.createLogger({
45+
level,
46+
format: winston.format.printf(({ level, message, ...meta }) => {
47+
let msg = `[${level.toUpperCase()}] ${message}`;
48+
const metaKeys = Object.keys(meta).filter(k => k !== 'level' && k !== 'message');
49+
if (metaKeys.length > 0) {
50+
// Custom replacer to handle BigInt and circular references
51+
const seen = new WeakSet();
52+
const replacer = (key, value) => {
53+
if (typeof value === 'bigint') return value.toString() + 'n';
54+
if (typeof value === 'object' && value !== null) {
55+
if (seen.has(value)) return '[Circular]';
56+
seen.add(value);
57+
}
58+
return value;
59+
};
60+
// Build a safe meta object to avoid invoking toJSON on library objects
61+
const safeMeta = {};
62+
for (const k of metaKeys) {
63+
try {
64+
safeMeta[k] = safeSerialize(meta[k]);
65+
} catch (e) {
66+
safeMeta[k] = '[Unserializable]';
67+
}
68+
}
69+
try {
70+
msg += ' ' + JSON.stringify(safeMeta, replacer);
71+
} catch (e) {
72+
try {
73+
msg += ' ' + String(safeMeta);
74+
} catch (ee) {
75+
msg += ' [Unserializable meta]';
76+
}
77+
}
78+
}
79+
return msg;
80+
}),
81+
transports
82+
});
83+
84+
// Patch logger methods to support primitive/array as meta
85+
const levels = Object.keys(logger.levels || winston.config.npm.levels);
86+
levels.forEach((method) => {
87+
const orig = logger[method];
88+
logger[method] = function (msg, meta) {
89+
if (arguments.length === 2 && (typeof meta !== 'object' || meta === null || Array.isArray(meta))) {
90+
return orig.call(this, msg, { value: meta });
91+
}
92+
return orig.apply(this, arguments);
93+
};
94+
});
95+
return logger;
96+
};
97+
98+
const log = createLogger();
99+
export default log;
100+
export { log };

package-lock.json

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@eliware/log",
33
"type": "module",
4-
"version": "1.1.1",
4+
"version": "1.1.2",
55
"description": "A Node.js logging library.",
66
"main": "index.cjs",
77
"module": "index.mjs",

0 commit comments

Comments
 (0)