mm_logger 0.0.0-stage → 1.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.
package/index.js ADDED
@@ -0,0 +1,27 @@
1
+ const Logger = require('./lib/logger');
2
+ const ConsoleLogger = require('./lib/console_logger');
3
+ const Admin = require('mm_corejs').Admin;
4
+
5
+ let admin = new Admin();
6
+ admin.setClass(Logger);
7
+
8
+ module.exports = {
9
+ LEVEL: require('./lib/level'),
10
+ Logger,
11
+ // 轻量控制台日志器(自 mm_corejs 迁移,类名避免与 Logger 冲突)
12
+ ConsoleLogger,
13
+ // 颜色工具(自 mm_corejs 迁移),结构与 mm_corejs.colors 保持一致
14
+ colors: require('./lib/colors'),
15
+ admin,
16
+ // 获取日志记录器实例(<模块>Admin 范式)
17
+ loggerAdmin(scope, config) {
18
+ if (!scope) {
19
+ scope = 'os';
20
+ }
21
+ return admin.get(scope, config);
22
+ },
23
+ // 兼容旧调用名
24
+ getLogger() {
25
+ return admin.get('os');
26
+ }
27
+ };
package/jest.config.js ADDED
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Jest 测试配置
5
+ */
6
+ module.exports = {
7
+ testEnvironment: 'node',
8
+ testMatch: ['<rootDir>/test/**/*.test.js'],
9
+ collectCoverageFrom: ['lib/colors.js', 'lib/console_logger.js'],
10
+ coverageThreshold: {
11
+ global: {
12
+ branches: 100,
13
+ functions: 100,
14
+ lines: 100,
15
+ statements: 100
16
+ }
17
+ }
18
+ };
package/lib/colors.js ADDED
@@ -0,0 +1,200 @@
1
+ // lib/colors.js
2
+ 'use strict';
3
+
4
+ const os = require('os');
5
+
6
+ /* =============================================================
7
+ * 1. ANSI 样式表
8
+ * 每项为 [开启码, 关闭码]
9
+ * 前景色关闭用 39,背景色关闭用 49,而不是 0(0 会清掉所有样式)
10
+ * =========================================================== */
11
+ const STYLES = {
12
+ reset: [0, 0],
13
+ bold: [1, 22],
14
+ dim: [2, 22],
15
+ italic: [3, 23],
16
+ underline: [4, 24],
17
+ blink: [5, 25],
18
+ inverse: [7, 27],
19
+ hidden: [8, 28],
20
+ strikethrough: [9, 29],
21
+
22
+ black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39],
23
+ blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39],
24
+ gray: [90, 39], grey: [90, 39],
25
+
26
+ redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39],
27
+ blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39],
28
+ whiteBright: [97, 39],
29
+
30
+ bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49],
31
+ bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49],
32
+ bgGray: [100, 49], bgGrey: [100, 49],
33
+ };
34
+
35
+ /* =============================================================
36
+ * 2. 环境检测
37
+ * =========================================================== */
38
+
39
+ // ---- Windows:判断当前终端是否支持 ANSI/VT ----
40
+ let _win_vt = null;
41
+
42
+ /**
43
+ * 判断当前终端是否支持 ANSI/VT
44
+ * @returns {boolean} 是否支持
45
+ */
46
+ function windowsSupportsVT() {
47
+ if (_win_vt !== null) return _win_vt;
48
+
49
+ // 明确支持 VT 的终端
50
+ if (process.env.WT_SESSION) return (_win_vt = true); // Windows Terminal
51
+ if (process.env.ConEmuANSI === 'ON') return (_win_vt = true); // ConEmu / Cmder
52
+ if (process.env.ANSICON) return (_win_vt = true); // ANSICON
53
+ if (process.env.TERM_PROGRAM === 'vscode') return (_win_vt = true); // VS Code 终端
54
+
55
+ // 系统版本:Windows 10 build 10586 (1511) 起原生支持 VT
56
+ try {
57
+ const parts = os.release().split('.').map(Number); // 如 "10.0.19045"
58
+ const major = parts[0] || 0;
59
+ const build = parts[2] || 0;
60
+ _win_vt = major >= 10 && build >= 10586;
61
+ } catch {
62
+ _win_vt = false;
63
+ }
64
+ return _win_vt;
65
+ }
66
+
67
+ // ---- 通用检测:对某个流是否应该上色 ----
68
+ /**
69
+ * 判断指定流是否应启用颜色
70
+ * @param {Object} stream 输出流(默认 process.stdout)
71
+ * @returns {boolean} 是否启用颜色
72
+ */
73
+ function supportsColor(stream) {
74
+ if (!stream) stream = process.stdout;
75
+
76
+ // NO_COLOR 标准:只要设置了该环境变量即禁用(即使值为空串)
77
+ if (process.env.NO_COLOR !== undefined) return false;
78
+
79
+ // FORCE_COLOR 优先级最高,方便 CI / 管道 / 测试场景
80
+ const fc = process.env.FORCE_COLOR;
81
+ if (fc !== undefined && fc !== '') {
82
+ return fc !== '0' && fc !== 'false';
83
+ }
84
+
85
+ // 非 TTY(重定向到文件、管道)——禁用,避免输出垃圾字符
86
+ if (!stream.isTTY) return false;
87
+
88
+ if (process.env.TERM === 'dumb') return false;
89
+
90
+ // 常见 CI 大多支持颜色
91
+ if (process.env.CI) {
92
+ return Boolean(
93
+ process.env.GITHUB_ACTIONS ||
94
+ process.env.GITLAB_CI ||
95
+ process.env.CIRCLECI ||
96
+ process.env.TRAVIS ||
97
+ process.env.BUILDKITE
98
+ );
99
+ }
100
+
101
+ // Windows 额外判断
102
+ if (process.platform === 'win32') return windowsSupportsVT();
103
+
104
+ // Linux / macOS / *nix:isTTY 为 true 就够了
105
+ return true;
106
+ }
107
+
108
+ /* =============================================================
109
+ * 3. 创建颜色工具
110
+ * =========================================================== */
111
+
112
+ /**
113
+ * 创建颜色工具集
114
+ * @param {boolean} enabled 是否启用颜色
115
+ * @returns {Object} 颜色工具对象
116
+ */
117
+ function createColors(enabled) {
118
+ const c = { enabled };
119
+
120
+ for (const [name, [open, close]] of Object.entries(STYLES)) {
121
+ c[name] = enabled
122
+ ? (s) => `\u001b[${open}m${s}\u001b[${close}m`
123
+ : (s) => String(s);
124
+ }
125
+
126
+ /**
127
+ * 生成 256 色前景着色器
128
+ * @param {number} code 颜色码
129
+ * @returns {Function} 着色函数
130
+ */
131
+ c.ansi256 = (code) =>
132
+ enabled
133
+ ? (s) => `\u001b[38;5;${code}m${s}\u001b[39m`
134
+ : (s) => String(s);
135
+
136
+ /**
137
+ * 生成真彩色前景着色器
138
+ * @param {number} r 红色分量
139
+ * @param {number} g 绿色分量
140
+ * @param {number} b 蓝色分量
141
+ * @returns {Function} 着色函数
142
+ */
143
+ c.rgb = (r, g, b) =>
144
+ enabled
145
+ ? (s) => `\u001b[38;2;${r};${g};${b}m${s}\u001b[39m`
146
+ : (s) => String(s);
147
+
148
+ /**
149
+ * 生成真彩色背景着色器
150
+ * @param {number} r 红色分量
151
+ * @param {number} g 绿色分量
152
+ * @param {number} b 蓝色分量
153
+ * @returns {Function} 着色函数
154
+ */
155
+ c.bgRgb = (r, g, b) =>
156
+ enabled
157
+ ? (s) => `\u001b[48;2;${r};${g};${b}m${s}\u001b[49m`
158
+ : (s) => String(s);
159
+
160
+ /**
161
+ * 生成组合样式着色器,如 c.style('bold red')('text')。
162
+ * 一次写入开启码、一次写入关闭码,避免嵌套重置导致串色。
163
+ * @param {string|Array<string>} names 样式名或样式名列表
164
+ * @returns {Function} 着色函数
165
+ */
166
+ c.style = (names) => {
167
+ if (!enabled) return (s) => String(s);
168
+ const list = Array.isArray(names) ? names : String(names).split(/\s+/);
169
+ const opens = [];
170
+ const closes = [];
171
+ for (const n of list) {
172
+ const s = STYLES[n];
173
+ if (s) {
174
+ opens.push(s[0]);
175
+ closes.unshift(s[1]); // 反序关闭
176
+ }
177
+ }
178
+ if (!opens.length) return (s) => String(s);
179
+ const open = `\u001b[${opens.join(';')}m`;
180
+ const close = `\u001b[${closes.join(';')}m`;
181
+ return (s) => `${open}${s}${close}`;
182
+ };
183
+
184
+ return c;
185
+ }
186
+
187
+ /* =============================================================
188
+ * 4. 导出
189
+ * =========================================================== */
190
+ module.exports = {
191
+ STYLES,
192
+ supportsColor,
193
+ windowsSupportsVT,
194
+ createColors,
195
+
196
+ // 便捷出口:默认对 stdout 检测
197
+ colors: createColors(supportsColor(process.stdout)),
198
+ // 快速创建一个针对任意流的着色器
199
+ forStream: (stream) => createColors(supportsColor(stream)),
200
+ };
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ // 轻量控制台日志器(自 mm_corejs/lib/logger.js 迁移)
4
+ // 依赖本目录内的 colors 工具,与 mm_logger 现有完整版 Logger 互不冲突。
5
+
6
+ const { colors: outColors, forStream } = require('./colors');
7
+
8
+ /**
9
+ * 标准错误着色器。
10
+ * error / warn 输出到 stderr,需按 stderr 的 TTY 能力单独检测,
11
+ * 否则重定向 stderr 时会残留 ANSI 转义序列。
12
+ */
13
+ const errColors = forStream(process.stderr);
14
+
15
+ /**
16
+ * 轻量控制台日志器
17
+ * @class ConsoleLogger
18
+ */
19
+ class ConsoleLogger {
20
+ /**
21
+ * 构造函数
22
+ */
23
+ constructor() {}
24
+
25
+ /**
26
+ * 信息日志
27
+ * @param {string} msg 日志消息
28
+ * @param {...*} args 日志参数列表
29
+ */
30
+ info(msg, ...args) {
31
+ console.info(outColors.blue(msg), ...args);
32
+ }
33
+
34
+ /**
35
+ * 调试日志
36
+ * @param {string} msg 日志消息
37
+ * @param {...*} args 日志参数列表
38
+ */
39
+ debug(msg, ...args) {
40
+ console.debug(outColors.white(msg), ...args);
41
+ }
42
+
43
+ /**
44
+ * 错误日志
45
+ * @param {string} msg 日志消息
46
+ * @param {...*} args 日志参数列表
47
+ */
48
+ error(msg, ...args) {
49
+ console.error(errColors.red(msg), ...args);
50
+ }
51
+
52
+ /**
53
+ * 成功日志
54
+ * @param {string} msg 日志消息
55
+ * @param {...*} args 日志参数列表
56
+ */
57
+ success(msg, ...args) {
58
+ console.log(outColors.green(msg), ...args);
59
+ }
60
+
61
+ /**
62
+ * 警告日志
63
+ * @param {string} msg 日志消息
64
+ * @param {...*} args 日志参数列表
65
+ */
66
+ warn(msg, ...args) {
67
+ console.warn(errColors.yellow(msg), ...args);
68
+ }
69
+ }
70
+
71
+ module.exports = ConsoleLogger;
package/lib/level.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 日志级别枚举
3
+ * @readonly
4
+ */
5
+ const LEVEL = {
6
+ debug: 10,
7
+ info: 20,
8
+ success: 25,
9
+ warn: 30,
10
+ error: 40,
11
+ fatal: 50
12
+ };
13
+
14
+ // 导出模块
15
+ module.exports = LEVEL;