@idlebox/logger 0.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/LICENSE +21 -0
- package/config/rig.json +5 -0
- package/lib/common/colors.d.ts +13 -0
- package/lib/common/colors.d.ts.map +1 -0
- package/lib/common/colors.js +33 -0
- package/lib/common/colors.js.map +1 -0
- package/lib/common/create.d.ts +4 -0
- package/lib/common/create.d.ts.map +1 -0
- package/lib/common/create.js +93 -0
- package/lib/common/create.js.map +1 -0
- package/lib/common/debug-fn.d.ts +13 -0
- package/lib/common/debug-fn.d.ts.map +1 -0
- package/lib/common/debug-fn.js +141 -0
- package/lib/common/debug-fn.js.map +1 -0
- package/lib/common/debug.commands.d.ts +13 -0
- package/lib/common/debug.commands.d.ts.map +1 -0
- package/lib/common/debug.commands.js +129 -0
- package/lib/common/debug.commands.js.map +1 -0
- package/lib/common/helpers.d.ts +56 -0
- package/lib/common/helpers.d.ts.map +1 -0
- package/lib/common/helpers.js +173 -0
- package/lib/common/helpers.js.map +1 -0
- package/lib/common/logger.create.d.ts +9 -0
- package/lib/common/logger.create.d.ts.map +1 -0
- package/lib/common/logger.create.js +27 -0
- package/lib/common/logger.create.js.map +1 -0
- package/lib/common/logger.global.d.ts +10 -0
- package/lib/common/logger.global.d.ts.map +1 -0
- package/lib/common/logger.global.js +28 -0
- package/lib/common/logger.global.js.map +1 -0
- package/lib/common/printer.d.ts +2 -0
- package/lib/common/printer.d.ts.map +1 -0
- package/lib/common/printer.js +2 -0
- package/lib/common/printer.js.map +1 -0
- package/lib/common/types.d.ts +32 -0
- package/lib/common/types.d.ts.map +1 -0
- package/lib/common/types.js +12 -0
- package/lib/common/types.js.map +1 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +9 -0
- package/lib/index.js.map +1 -0
- package/lib/printers/file.d.ts +2 -0
- package/lib/printers/file.d.ts.map +1 -0
- package/lib/printers/file.js +27 -0
- package/lib/printers/file.js.map +1 -0
- package/lib/test/01-simple.test.d.ts +2 -0
- package/lib/test/01-simple.test.d.ts.map +1 -0
- package/lib/test/01-simple.test.js +33 -0
- package/lib/test/01-simple.test.js.map +1 -0
- package/lib/test/02-debug.test.d.ts +2 -0
- package/lib/test/02-debug.test.d.ts.map +1 -0
- package/lib/test/02-debug.test.js +9 -0
- package/lib/test/02-debug.test.js.map +1 -0
- package/lib/test/03-file.test.d.ts +2 -0
- package/lib/test/03-file.test.d.ts.map +1 -0
- package/lib/test/03-file.test.js +34 -0
- package/lib/test/03-file.test.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +35 -0
- package/src/common/colors.ts +33 -0
- package/src/common/create.ts +116 -0
- package/src/common/debug-fn.ts +171 -0
- package/src/common/debug.commands.ts +132 -0
- package/src/common/helpers.ts +184 -0
- package/src/common/logger.create.ts +35 -0
- package/src/common/logger.global.ts +31 -0
- package/src/common/printer.ts +0 -0
- package/src/common/types.ts +39 -0
- package/src/index.ts +23 -0
- package/src/printers/file.ts +29 -0
- package/src/test/01-simple.test.ts +44 -0
- package/src/test/02-debug.test.ts +11 -0
- package/src/test/03-file.test.ts +46 -0
- package/src/tsconfig.json +10 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import { formatWithOptions, inspect } from 'node:util';
|
|
3
|
+
|
|
4
|
+
const STRING_MAX_LENGTH = 128;
|
|
5
|
+
|
|
6
|
+
function color_error(message: string, color: boolean) {
|
|
7
|
+
if (color) {
|
|
8
|
+
return `\x1B[38;5;9m<inspect**${message}**>\x1B[39m`;
|
|
9
|
+
} else {
|
|
10
|
+
return `<inspect**${message}**>`;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function options(color: boolean) {
|
|
15
|
+
return {
|
|
16
|
+
depth: 5,
|
|
17
|
+
compact: true,
|
|
18
|
+
colors: color,
|
|
19
|
+
maxArrayLength: 3,
|
|
20
|
+
maxStringLength: STRING_MAX_LENGTH,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function nodeFormat(message: string, object: readonly unknown[], color: boolean): string {
|
|
25
|
+
return formatWithOptions(options(color), message, ...object);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function nodeInspect(object: unknown, color: boolean): string {
|
|
29
|
+
return inspect(object, options(color));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isSyncIterable(obj: unknown): obj is Iterable<unknown> {
|
|
33
|
+
return typeof obj === 'object' && obj !== null && Symbol.iterator in obj;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const debug_commands = {
|
|
37
|
+
inspect(object: unknown, color: boolean) {
|
|
38
|
+
return inspect(object, options(color));
|
|
39
|
+
},
|
|
40
|
+
stripe(s: unknown, color: boolean) {
|
|
41
|
+
if (typeof s !== 'string') {
|
|
42
|
+
return color_error(`can not stripe ${typeof s}`, color);
|
|
43
|
+
}
|
|
44
|
+
if (s.length > 100) {
|
|
45
|
+
if (color) {
|
|
46
|
+
return `\x1B[38;5;10m"${s.slice(0, STRING_MAX_LENGTH - 3)}..."\x1B[39m`;
|
|
47
|
+
} else {
|
|
48
|
+
return `"${s.slice(0, STRING_MAX_LENGTH - 3)}..."`;
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
return s;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
list(items: unknown, color: boolean) {
|
|
55
|
+
if (!isSyncIterable(items)) {
|
|
56
|
+
return color_error(`list<> need iterable value, not ${typeof items}(${items?.constructor?.name})`, color);
|
|
57
|
+
}
|
|
58
|
+
const postfix = color ? '\x1B[0m' : '';
|
|
59
|
+
let index = 0;
|
|
60
|
+
const lines: string[] = [];
|
|
61
|
+
const prefix = color ? '\x1B[2m' : '';
|
|
62
|
+
for (const item of items) {
|
|
63
|
+
if (Array.isArray(item)) {
|
|
64
|
+
if (item.length === 2) {
|
|
65
|
+
const [key, value] = item;
|
|
66
|
+
if (typeof key === 'number') {
|
|
67
|
+
lines.push(` - ${prefix}${item}${postfix}`);
|
|
68
|
+
} else {
|
|
69
|
+
lines.push(` * ${prefix}${key}: ${value.toString()}${postfix}`);
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
return color_error(`list<> item ${index} is array with length ${item.length}, expected 2`, color);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
lines.push(` - ${prefix}${item}${postfix}`);
|
|
76
|
+
}
|
|
77
|
+
index++;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (lines.length === 0) {
|
|
81
|
+
const prefix = color ? '\x1B[3;2m' : '';
|
|
82
|
+
return ':\n' + prefix + ' - <list is empty>' + postfix;
|
|
83
|
+
}
|
|
84
|
+
return ':\n' + lines.join('\n');
|
|
85
|
+
},
|
|
86
|
+
commandline(cmds: unknown, color: boolean) {
|
|
87
|
+
if (Array.isArray(cmds)) {
|
|
88
|
+
const prefix = color ? '\x1B[2m' : '';
|
|
89
|
+
const postfix = color ? '\x1B[0m' : '';
|
|
90
|
+
return prefix + cmds.map((s) => JSON.stringify(s)).join(' ') + postfix;
|
|
91
|
+
} else if (typeof cmds === 'string') {
|
|
92
|
+
const prefix = color ? '\x1B[2;3m' : '';
|
|
93
|
+
const postfix = color ? '\x1B[0m' : '';
|
|
94
|
+
return prefix + cmds + postfix;
|
|
95
|
+
} else {
|
|
96
|
+
return color_error(`commandline<> need string or array, not ${typeof cmds}`, color);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
long(s: unknown, color: boolean) {
|
|
100
|
+
if (typeof s !== 'string') {
|
|
101
|
+
if (Array.isArray(s)) {
|
|
102
|
+
s = `[${s.join(', ')}]`;
|
|
103
|
+
} else {
|
|
104
|
+
return color_error(`long<> need string, not ${typeof s}(${s?.constructor?.name})`, color);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (color) {
|
|
108
|
+
return `\x1B[3m${s}\x1B[23m`;
|
|
109
|
+
} else {
|
|
110
|
+
return s;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
relative(s: unknown, color: boolean) {
|
|
114
|
+
if (typeof s !== 'string') {
|
|
115
|
+
return color_error(`relative<> need string, not ${typeof s}(${s?.constructor?.name})`, color);
|
|
116
|
+
}
|
|
117
|
+
return relative(process.cwd(), s);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
type DebugCommands = Record<string, (arg: unknown, color: boolean) => string>;
|
|
121
|
+
|
|
122
|
+
export function call_debug_command(
|
|
123
|
+
command: keyof typeof debug_commands | string,
|
|
124
|
+
arg: unknown,
|
|
125
|
+
color: boolean,
|
|
126
|
+
): string {
|
|
127
|
+
const fn = (debug_commands as DebugCommands)[command];
|
|
128
|
+
if (!fn) {
|
|
129
|
+
return color_error(`unknown command ${command}`, color);
|
|
130
|
+
}
|
|
131
|
+
return fn(arg, color);
|
|
132
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
import { terminal } from './logger.global.js';
|
|
4
|
+
import { EnableLogLevel } from './types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 判断 字符串是否为“真值”
|
|
8
|
+
* * 1 / 0
|
|
9
|
+
* * true / false
|
|
10
|
+
* * on / off
|
|
11
|
+
* * yes / no
|
|
12
|
+
* * enabled / disabled
|
|
13
|
+
*
|
|
14
|
+
* 其他内容会导致一个警告,并返回 false
|
|
15
|
+
*/
|
|
16
|
+
export function is_string_truthy(value: string | undefined) {
|
|
17
|
+
if (!value) return false;
|
|
18
|
+
|
|
19
|
+
value = value.toLowerCase();
|
|
20
|
+
if (value === '1' || value === 'true' || value === 'on' || value === 'yes' || value === 'enabled') {
|
|
21
|
+
return true;
|
|
22
|
+
} else if (value === '0' || value === 'false' || value === 'off' || value === 'no' || value === 'disabled') {
|
|
23
|
+
return false;
|
|
24
|
+
} else {
|
|
25
|
+
terminal.warn`invalid boolean string: ${value}, assuming false.`;
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface IWritableStream extends NodeJS.WritableStream {
|
|
31
|
+
colorEnabled?: boolean;
|
|
32
|
+
isTTY?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function _colorEnabled(stream: IWritableStream): boolean {
|
|
36
|
+
const colorArg = process.argv.find((e) => e.startsWith('--color=') || e === '--color' || e === '-c');
|
|
37
|
+
const noColorArg = process.argv.includes('--no-color');
|
|
38
|
+
|
|
39
|
+
// 命令行顶级优先
|
|
40
|
+
if (colorArg) return true;
|
|
41
|
+
if (noColorArg) return false;
|
|
42
|
+
|
|
43
|
+
// 环境变量
|
|
44
|
+
if (process.env.NO_COLOR || process.env.NODE_DISABLE_COLORS === '1') {
|
|
45
|
+
/**
|
|
46
|
+
* https://force-color.org/
|
|
47
|
+
* https://nodejs.org/docs/latest/api/cli.html#node_disable_colors1
|
|
48
|
+
*/
|
|
49
|
+
return false;
|
|
50
|
+
} else if (process.env.FORCE_COLOR) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 检测其他可能
|
|
55
|
+
if (stream.isTTY) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// TODO
|
|
60
|
+
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function detectColorEnable(stream: IWritableStream = process.stderr): boolean {
|
|
65
|
+
if (stream.colorEnabled === undefined) {
|
|
66
|
+
stream.colorEnabled = _colorEnabled(stream);
|
|
67
|
+
}
|
|
68
|
+
return stream.colorEnabled;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function escapeRegExp(str: string) {
|
|
72
|
+
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param tag tag to match, e.g. "app:db:insert"
|
|
78
|
+
* @returns a RegExp, eg. /(^|\s)(\\*|app:\\*|app:db:\\*|app:db:insert)($|\s)/
|
|
79
|
+
*/
|
|
80
|
+
export function compile_match_regex(tag: string, invert = false): RegExp {
|
|
81
|
+
const parts = tag.split(':');
|
|
82
|
+
parts.pop();
|
|
83
|
+
|
|
84
|
+
let regs = ['\\*'];
|
|
85
|
+
|
|
86
|
+
let comb = [];
|
|
87
|
+
for (const part of parts) {
|
|
88
|
+
comb.push(part);
|
|
89
|
+
regs.push(`${escapeRegExp(comb.join(':'))}:\\*`);
|
|
90
|
+
}
|
|
91
|
+
regs.push(escapeRegExp(tag));
|
|
92
|
+
return new RegExp(`(?:^|,)(${invert ? '-' : ''})(${regs.join('|')})(?:$|,)`, 'i');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 从字符串中匹配指定的tag是否启用,不完全模拟 debug 模块的功能,不处理反义匹配(需用match_disabled)
|
|
97
|
+
* @param tag 类似 "app:db:insert" 的tag
|
|
98
|
+
* @param env 环境变量内容,默认 process.env.DEBUG
|
|
99
|
+
* @returns 冒号数量
|
|
100
|
+
*/
|
|
101
|
+
export function match_enabled(tag: string, env = process.env.DEBUG || ''): number {
|
|
102
|
+
const tagReg = compile_match_regex(tag);
|
|
103
|
+
const m = tagReg.exec(env);
|
|
104
|
+
if (!m) return 0;
|
|
105
|
+
return m[0].split(':').length;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 从字符串中匹配指定的tag是否禁用,不完全模拟 debug 模块的功能,tag前面不要加-
|
|
110
|
+
* @param tag 类似 "app:db:insert" 的tag
|
|
111
|
+
* @param env 环境变量内容,默认 process.env.DEBUG
|
|
112
|
+
* @returns 冒号数量 - 1
|
|
113
|
+
*/
|
|
114
|
+
export function match_disabled(tag: string, env = process.env.DEBUG || ''): number {
|
|
115
|
+
const tagReg = compile_match_regex(tag, true);
|
|
116
|
+
const m = tagReg.exec(env);
|
|
117
|
+
if (!m) return -1;
|
|
118
|
+
return m[0].split(':').length - 1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 调用debug模块的debug.enabled方法
|
|
123
|
+
*/
|
|
124
|
+
export function debug_enabled(tag: string) {
|
|
125
|
+
return debug(tag).enabled;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 当指定tag开启时,应该输出它的什么级别
|
|
130
|
+
* tag关闭时始终默认error
|
|
131
|
+
*
|
|
132
|
+
* 只有新创建的受此影响,且不影响root-logger,也不影响.extend
|
|
133
|
+
*/
|
|
134
|
+
export let defaultLogLevel = (() => {
|
|
135
|
+
if (process.argv.includes('--verbose')) {
|
|
136
|
+
// 参数中含有 --verbose 时,设置默认日志级别
|
|
137
|
+
return EnableLogLevel.verbose;
|
|
138
|
+
} else {
|
|
139
|
+
// 参数中含有 --debug 或 -d 时,设置默认日志级别
|
|
140
|
+
const dbgCnt = process.argv.filter((e) => e === '--debug' || e === '-d').length;
|
|
141
|
+
if (dbgCnt > 1) {
|
|
142
|
+
return EnableLogLevel.verbose;
|
|
143
|
+
} else if (dbgCnt === 1) {
|
|
144
|
+
return EnableLogLevel.debug;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// DEBUG=xxx,verbose,xxx
|
|
149
|
+
// biome-ignore lint/performance/useTopLevelRegex:
|
|
150
|
+
const has_debug_verbose = /(?<=^|,)(verbose|debug)(?=$|,)/;
|
|
151
|
+
const setted = has_debug_verbose.exec(process.env.DEBUG || '');
|
|
152
|
+
if (setted) {
|
|
153
|
+
if (setted[0] === 'verbose') {
|
|
154
|
+
return EnableLogLevel.verbose;
|
|
155
|
+
} else {
|
|
156
|
+
return EnableLogLevel.debug;
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
// 直接通过 DEBUG_LEVEL 设置
|
|
160
|
+
switch (process.env.DEBUG_LEVEL || '') {
|
|
161
|
+
case '':
|
|
162
|
+
return EnableLogLevel.log;
|
|
163
|
+
case 'verbose':
|
|
164
|
+
return EnableLogLevel.verbose;
|
|
165
|
+
case 'debug':
|
|
166
|
+
return EnableLogLevel.debug;
|
|
167
|
+
case 'info':
|
|
168
|
+
return EnableLogLevel.info;
|
|
169
|
+
case 'warn':
|
|
170
|
+
return EnableLogLevel.warn;
|
|
171
|
+
default:
|
|
172
|
+
console.error('Invalid DEBUG_LEVEL: %s, using verbose.', process.env.DEBUG_LEVEL);
|
|
173
|
+
return EnableLogLevel.verbose;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
})();
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 手动设置默认日志级别
|
|
180
|
+
* root-logger 和 已经创建的 不受此影响
|
|
181
|
+
*/
|
|
182
|
+
export function set_default_log_level(level: EnableLogLevel) {
|
|
183
|
+
defaultLogLevel = level;
|
|
184
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { PassThrough } from 'node:stream';
|
|
3
|
+
import { create } from './create.js';
|
|
4
|
+
import { debug_enabled, defaultLogLevel } from './helpers.js';
|
|
5
|
+
import { terminal } from './logger.global.js';
|
|
6
|
+
import { EnableLogLevel, type IMyLogger } from './types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 创建一个新的logger实例
|
|
10
|
+
* @param color_enabled 默认自动
|
|
11
|
+
* @param pipeTo 默认是 process.stderr
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export function createLogger(
|
|
15
|
+
tag: string,
|
|
16
|
+
color_enabled: boolean | undefined = undefined,
|
|
17
|
+
pipeTo: undefined | NodeJS.WritableStream = process.stderr,
|
|
18
|
+
): IMyLogger {
|
|
19
|
+
const stream = new PassThrough();
|
|
20
|
+
if (pipeTo) {
|
|
21
|
+
Object.assign(stream, { isTTY: (pipeTo as any).isTTY });
|
|
22
|
+
stream.pipe(pipeTo);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let level = EnableLogLevel.error;
|
|
26
|
+
if (debug_enabled(tag)) {
|
|
27
|
+
level = defaultLogLevel;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const logger = create(tag, color_enabled, stream, level);
|
|
31
|
+
|
|
32
|
+
(terminal || logger).verbose`logger "${tag}" created, level = ${EnableLogLevel[level]}`;
|
|
33
|
+
|
|
34
|
+
return logger;
|
|
35
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { PassThrough } from 'node:stream';
|
|
3
|
+
import { create } from './create.js';
|
|
4
|
+
import { EnableLogLevel, type IMyLogger } from './types.js';
|
|
5
|
+
|
|
6
|
+
const stream = new PassThrough();
|
|
7
|
+
stream.pipe(process.stderr);
|
|
8
|
+
Object.assign(stream, { isTTY: process.stderr.isTTY });
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 作为logger导出,必须在程序入口调用过 createGlobalLogger() 才能使用
|
|
12
|
+
*/
|
|
13
|
+
export let terminal: IMyLogger;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 创建root-logger,随后logger变量可用
|
|
17
|
+
*/
|
|
18
|
+
export function createGlobalLogger(tag: string, defaultLevel: EnableLogLevel = EnableLogLevel.auto): void {
|
|
19
|
+
if (terminal) throw new Error('global logger already created');
|
|
20
|
+
|
|
21
|
+
terminal = create(tag, undefined, stream);
|
|
22
|
+
|
|
23
|
+
terminal.enable(defaultLevel || EnableLogLevel.log);
|
|
24
|
+
|
|
25
|
+
if (terminal.verbose.isEnabled) {
|
|
26
|
+
terminal.verbose`verbose is enabled`;
|
|
27
|
+
} else {
|
|
28
|
+
terminal.debug`debug is enabled`;
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type IMyDebug<T = void> = (message: TemplateStringsArray | string, ...args: readonly any[]) => T;
|
|
2
|
+
|
|
3
|
+
export interface IMyDebugWithControl extends IMyDebug {
|
|
4
|
+
enable(): void;
|
|
5
|
+
disable(): void;
|
|
6
|
+
readonly isEnabled: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export enum EnableLogLevel {
|
|
10
|
+
auto,
|
|
11
|
+
fatal,
|
|
12
|
+
error,
|
|
13
|
+
warn,
|
|
14
|
+
info,
|
|
15
|
+
log,
|
|
16
|
+
debug,
|
|
17
|
+
verbose,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type IMyLogger = {
|
|
21
|
+
fatal: IMyDebug<never>;
|
|
22
|
+
|
|
23
|
+
error: IMyDebug;
|
|
24
|
+
success: IMyDebugWithControl;
|
|
25
|
+
|
|
26
|
+
warn: IMyDebugWithControl;
|
|
27
|
+
info: IMyDebugWithControl;
|
|
28
|
+
log: IMyDebugWithControl;
|
|
29
|
+
debug: IMyDebugWithControl;
|
|
30
|
+
verbose: IMyDebugWithControl;
|
|
31
|
+
|
|
32
|
+
extend: (tag: string) => IMyLogger;
|
|
33
|
+
stream: NodeJS.ReadableStream;
|
|
34
|
+
|
|
35
|
+
enable(newMaxLevel: EnableLogLevel): void;
|
|
36
|
+
|
|
37
|
+
readonly tag: string;
|
|
38
|
+
readonly colorEnabled: boolean;
|
|
39
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { LogLevel, logTagColor } from './common/colors.js';
|
|
2
|
+
export { all_logger_names } from './common/create.js';
|
|
3
|
+
export { createDebug } from './common/debug-fn.js';
|
|
4
|
+
export {
|
|
5
|
+
detectColorEnable as color_enabled,
|
|
6
|
+
debug_enabled,
|
|
7
|
+
is_string_truthy,
|
|
8
|
+
match_disabled,
|
|
9
|
+
match_enabled,
|
|
10
|
+
set_default_log_level,
|
|
11
|
+
} from './common/helpers.js';
|
|
12
|
+
export { createLogger } from './common/logger.create.js';
|
|
13
|
+
export {
|
|
14
|
+
createGlobalLogger as createRootLogger,
|
|
15
|
+
terminal as logger,
|
|
16
|
+
} from './common/logger.global.js';
|
|
17
|
+
export {
|
|
18
|
+
EnableLogLevel,
|
|
19
|
+
type IMyDebug,
|
|
20
|
+
type IMyDebugWithControl,
|
|
21
|
+
type IMyLogger,
|
|
22
|
+
} from './common/types.js';
|
|
23
|
+
export { createLogFile } from './printers/file.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createWriteStream } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { Transform, type TransformCallback } from 'node:stream';
|
|
4
|
+
|
|
5
|
+
export function createLogFile(filePath: string): NodeJS.WritableStream {
|
|
6
|
+
const file = resolve(process.cwd(), filePath);
|
|
7
|
+
console.log(`Creating log file: ${file}`);
|
|
8
|
+
const target = createWriteStream(file, { autoClose: true, encoding: 'utf-8', flush: true });
|
|
9
|
+
target.on('error', (err) => {
|
|
10
|
+
console.error(`Error writing to log file ${file}:`, err);
|
|
11
|
+
});
|
|
12
|
+
target.on('open', (fd) => {
|
|
13
|
+
console.error(`log file ${file}:`, fd);
|
|
14
|
+
});
|
|
15
|
+
target.on('close', () => {
|
|
16
|
+
console.error(`log file ${file}: close`);
|
|
17
|
+
});
|
|
18
|
+
const filter = new ColorRemoveStream();
|
|
19
|
+
filter.pipe(target, { end: true });
|
|
20
|
+
|
|
21
|
+
return filter;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class ColorRemoveStream extends Transform {
|
|
25
|
+
override _transform(chunk: Buffer, _encoding: string, callback: TransformCallback): void {
|
|
26
|
+
const cleaned = chunk.toString().replace(/\x1B\[[0-9;]*m/g, '');
|
|
27
|
+
callback(null, cleaned);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createGlobalLogger } from '../common/logger.global.js';
|
|
2
|
+
import { logger } from '../index.js';
|
|
3
|
+
|
|
4
|
+
createGlobalLogger('wow');
|
|
5
|
+
|
|
6
|
+
const l = 'such';
|
|
7
|
+
const o = { hello: 'world' };
|
|
8
|
+
|
|
9
|
+
logger.error`wow, ${l} doge! ${o}!`;
|
|
10
|
+
logger.error('wow, such %s! %o?', l, o);
|
|
11
|
+
console.log('----------------');
|
|
12
|
+
|
|
13
|
+
logger.warn`wow, ${l} doge! ${o}!`;
|
|
14
|
+
logger.warn('wow, such %s! %o?', l, o);
|
|
15
|
+
console.log('----------------');
|
|
16
|
+
|
|
17
|
+
logger.info`wow, ${l} doge! ${o}!`;
|
|
18
|
+
logger.info('wow, such %s! %o?', l, o);
|
|
19
|
+
console.log('----------------');
|
|
20
|
+
|
|
21
|
+
logger.log`wow, ${l} doge! ${o}!`;
|
|
22
|
+
logger.log('wow, such %s! %o?', l, o);
|
|
23
|
+
console.log('----------------');
|
|
24
|
+
|
|
25
|
+
logger.success`wow, ${l} doge! ${o}!`;
|
|
26
|
+
logger.success('wow, such %s! %o?', l, o);
|
|
27
|
+
console.log('----------------');
|
|
28
|
+
|
|
29
|
+
logger.debug`wow, ${l} doge! ${o}!`;
|
|
30
|
+
logger.debug('wow, such %s! %o?', l, o);
|
|
31
|
+
console.log('----------------');
|
|
32
|
+
|
|
33
|
+
logger.verbose`wow, ${l} doge! ${o}!`;
|
|
34
|
+
logger.verbose('wow, such %s! %o?', l, o);
|
|
35
|
+
console.log('----------------');
|
|
36
|
+
|
|
37
|
+
logger.fatal`wow, ${l} doge! ${o}!`;
|
|
38
|
+
logger.fatal('wow, such %s! %o?', l, o);
|
|
39
|
+
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
console.log('----------------');
|
|
42
|
+
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
logger.error`this not happen`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createGlobalLogger } from '../common/logger.global.js';
|
|
2
|
+
import { logger } from '../index.js';
|
|
3
|
+
|
|
4
|
+
createGlobalLogger('wow');
|
|
5
|
+
|
|
6
|
+
const l = 'such';
|
|
7
|
+
const o = { hello: 'world' };
|
|
8
|
+
|
|
9
|
+
logger.debug`wow, ${l} doge! ${o}!`;
|
|
10
|
+
console.log('----------------');
|
|
11
|
+
logger.debug('wow, such %s! %o?', l, o);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createGlobalLogger } from '../common/logger.global.js';
|
|
2
|
+
import { createLogFile, logger } from '../index.js';
|
|
3
|
+
|
|
4
|
+
createGlobalLogger('wow');
|
|
5
|
+
|
|
6
|
+
logger.stream.pipe(createLogFile('test.log'));
|
|
7
|
+
|
|
8
|
+
const l = 'such';
|
|
9
|
+
const o = { hello: 'world' };
|
|
10
|
+
|
|
11
|
+
logger.error`wow, ${l} doge! ${o}!`;
|
|
12
|
+
logger.error('wow, such %s! %o?', l, o);
|
|
13
|
+
console.log('----------------');
|
|
14
|
+
|
|
15
|
+
logger.warn`wow, ${l} doge! ${o}!`;
|
|
16
|
+
logger.warn('wow, such %s! %o?', l, o);
|
|
17
|
+
console.log('----------------');
|
|
18
|
+
|
|
19
|
+
logger.info`wow, ${l} doge! ${o}!`;
|
|
20
|
+
logger.info('wow, such %s! %o?', l, o);
|
|
21
|
+
console.log('----------------');
|
|
22
|
+
|
|
23
|
+
logger.log`wow, ${l} doge! ${o}!`;
|
|
24
|
+
logger.log('wow, such %s! %o?', l, o);
|
|
25
|
+
console.log('----------------');
|
|
26
|
+
|
|
27
|
+
logger.success`wow, ${l} doge! ${o}!`;
|
|
28
|
+
logger.success('wow, such %s! %o?', l, o);
|
|
29
|
+
console.log('----------------');
|
|
30
|
+
|
|
31
|
+
logger.debug`wow, ${l} doge! ${o}!`;
|
|
32
|
+
logger.debug('wow, such %s! %o?', l, o);
|
|
33
|
+
console.log('----------------');
|
|
34
|
+
|
|
35
|
+
logger.verbose`wow, ${l} doge! ${o}!`;
|
|
36
|
+
logger.verbose('wow, such %s! %o?', l, o);
|
|
37
|
+
console.log('----------------');
|
|
38
|
+
|
|
39
|
+
logger.fatal`wow, ${l} doge! ${o}!`;
|
|
40
|
+
logger.fatal('wow, such %s! %o?', l, o);
|
|
41
|
+
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
console.log('----------------');
|
|
44
|
+
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
logger.error`this not happen`;
|