@done-coding/output-node 0.1.0-alpha.0 → 0.1.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/README.md +251 -299
- package/es/index.mjs +203 -275
- package/package.json +6 -3
- package/types/index.d.ts +8 -49
package/README.md
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
# @done-coding/output-node
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@done-coding/output-node)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://codecov.io/gh/done-coding/output-node)
|
|
6
|
+
|
|
3
7
|
Node.js 环境下的同构输出工具包,基于 @done-coding/output-core 核心包构建,提供控制台输出和日志文件输出功能。
|
|
4
8
|
|
|
5
|
-
##
|
|
9
|
+
## 功能特性
|
|
6
10
|
|
|
7
11
|
- 🎨 **丰富的控制台输出** - 支持多种输出类型和颜色配置
|
|
8
12
|
- 📝 **专业的日志文件输出** - 基于 pino 的高性能日志记录
|
|
9
13
|
- 🔄 **混合类型接口** - 支持函数调用和属性链式调用两种方式
|
|
10
14
|
- 🛡️ **临终落盘保护** - 使用 signal-exit 库实现非侵入式进程退出监听
|
|
11
|
-
- 🚨
|
|
12
|
-
- ⚡ **高性能** -
|
|
15
|
+
- 🚨 **框架兼容** - 与 NestJS 等现代框架的关闭钩子完美兼容
|
|
16
|
+
- ⚡ **高性能** - 异步日志写入,可配置缓冲区大小
|
|
13
17
|
- 🔧 **完整的错误处理** - 输入验证、配置验证、文件权限检查
|
|
14
|
-
- 📦
|
|
15
|
-
-
|
|
18
|
+
- 📦 **完整类型支持** - 100% TypeScript 类型定义和类型推导
|
|
19
|
+
- 🔇 **动态静默控制** - 支持运行时动态控制输出静默,基于类型的条件静默
|
|
20
|
+
- 🎯 **智能切换同步** - 支持控制台和日志文件之间的智能切换和同步
|
|
16
21
|
- 📋 **TABLE 类型特殊处理** - 智能表格数据展示和 JSON 序列化
|
|
17
|
-
- 🔧 **常量集中管理** - 所有配置参数的默认值统一管理
|
|
18
22
|
|
|
19
|
-
##
|
|
23
|
+
## 快速开始
|
|
24
|
+
|
|
25
|
+
### 安装
|
|
20
26
|
|
|
21
27
|
```bash
|
|
22
28
|
npm install @done-coding/output-node
|
|
@@ -26,247 +32,228 @@ yarn add @done-coding/output-node
|
|
|
26
32
|
pnpm add @done-coding/output-node
|
|
27
33
|
```
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
### 控制台输出
|
|
35
|
+
### 最小可用示例
|
|
32
36
|
|
|
33
37
|
```typescript
|
|
34
38
|
import {
|
|
35
39
|
createOutputConsole,
|
|
36
|
-
OutputConsoleTypeEnum,
|
|
37
|
-
} from "@done-coding/output-node";
|
|
38
|
-
|
|
39
|
-
// 创建控制台输出实例
|
|
40
|
-
const outputConsole = createOutputConsole({
|
|
41
|
-
enableColor: true, // 启用颜色输出
|
|
42
|
-
silent: false, // 非静默模式
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// 函数调用方式
|
|
46
|
-
outputConsole(OutputConsoleTypeEnum.INFO, "这是一条信息");
|
|
47
|
-
outputConsole(OutputConsoleTypeEnum.SUCCESS, "操作成功!");
|
|
48
|
-
outputConsole(OutputConsoleTypeEnum.ERROR, "发生错误");
|
|
49
|
-
|
|
50
|
-
// 属性链式调用方式(推荐)
|
|
51
|
-
outputConsole.info("这是一条信息");
|
|
52
|
-
outputConsole.success("操作成功!");
|
|
53
|
-
outputConsole.error("发生错误");
|
|
54
|
-
outputConsole.warn("这是一个警告");
|
|
55
|
-
outputConsole.debug("调试信息");
|
|
56
|
-
outputConsole.stage("当前步骤");
|
|
57
|
-
outputConsole.skip("跳过此步骤");
|
|
58
|
-
|
|
59
|
-
// TABLE 类型特殊处理
|
|
60
|
-
outputConsole.table({
|
|
61
|
-
name: "张三",
|
|
62
|
-
age: 25,
|
|
63
|
-
city: "北京",
|
|
64
|
-
});
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 日志文件输出
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import {
|
|
71
40
|
createOutputLogFile,
|
|
72
|
-
OutputLogFileTypeEnum,
|
|
73
41
|
} from "@done-coding/output-node";
|
|
74
42
|
|
|
75
|
-
//
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
silent: false, // 非静默模式
|
|
80
|
-
sync: false, // 异步写入(推荐)
|
|
81
|
-
bufferSize: 4096, // 缓冲区大小
|
|
82
|
-
});
|
|
43
|
+
// 创建控制台输出
|
|
44
|
+
const output = createOutputConsole();
|
|
45
|
+
output.info("Hello World");
|
|
46
|
+
output.success("操作成功");
|
|
83
47
|
|
|
84
|
-
//
|
|
85
|
-
logger(
|
|
86
|
-
logger(OutputLogFileTypeEnum.ERROR, "数据库连接失败");
|
|
87
|
-
|
|
88
|
-
// 属性链式调用方式(推荐)
|
|
48
|
+
// 创建日志文件输出
|
|
49
|
+
const logger = createOutputLogFile({ logFilePath: "app.log" });
|
|
89
50
|
logger.info("应用启动");
|
|
90
|
-
logger.
|
|
91
|
-
logger.error("数据库连接失败");
|
|
92
|
-
logger.debug("调试信息");
|
|
93
|
-
logger.trace("详细跟踪信息");
|
|
94
|
-
logger.fatal("致命错误,应用即将退出");
|
|
51
|
+
logger.error("发生错误");
|
|
95
52
|
```
|
|
96
53
|
|
|
97
|
-
|
|
54
|
+
## 架构设计
|
|
98
55
|
|
|
99
|
-
|
|
100
|
-
import { outputLogFile } from "@done-coding/output-node";
|
|
56
|
+
### 分层架构
|
|
101
57
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
});
|
|
58
|
+
```
|
|
59
|
+
┌─────────────────────────────────────┐
|
|
60
|
+
│ Node.js 适配包层 │
|
|
61
|
+
│ (@done-coding/output-node) │
|
|
62
|
+
├─────────────────────────────────────┤
|
|
63
|
+
│ 核心包层 │
|
|
64
|
+
│ (@done-coding/output-core) │
|
|
65
|
+
├─────────────────────────────────────┤
|
|
66
|
+
│ 驱动实现层 │
|
|
67
|
+
│ (console.log, pino, chalk, etc.) │
|
|
68
|
+
└─────────────────────────────────────┘
|
|
114
69
|
```
|
|
115
70
|
|
|
116
|
-
###
|
|
71
|
+
### 设计原则
|
|
117
72
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
73
|
+
1. **自动化驱动** - 自动创建和管理输出驱动实现
|
|
74
|
+
2. **零配置** - 提供合理的默认配置,开箱即用
|
|
75
|
+
3. **高性能** - 异步日志写入,可配置缓冲区
|
|
76
|
+
4. **安全可靠** - 完整的错误处理和防御性编程
|
|
77
|
+
5. **框架兼容** - 与现代框架(NestJS、Express 等)完美兼容
|
|
78
|
+
6. **极简 API** - 最少化的配置参数,易于使用
|
|
124
79
|
|
|
125
|
-
|
|
126
|
-
const fileLogger = createOutputLogFile({ logFilePath: "error.log" });
|
|
80
|
+
### 内置实现
|
|
127
81
|
|
|
128
|
-
|
|
129
|
-
const outputConsole = createOutputConsole({
|
|
130
|
-
enableColor: true,
|
|
131
|
-
// 错误级别切换到日志文件(不在控制台显示)
|
|
132
|
-
isSwitchLogFile: (type) => type === OutputConsoleTypeEnum.ERROR,
|
|
133
|
-
// 警告级别同步到日志文件(控制台和文件都显示)
|
|
134
|
-
isSyncToLogFile: (type) => type === OutputConsoleTypeEnum.WARN,
|
|
135
|
-
// 指定日志文件输出函数
|
|
136
|
-
outputFileFn: fileLogger,
|
|
137
|
-
});
|
|
82
|
+
#### 控制台输出驱动
|
|
138
83
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
84
|
+
- **基础实现**: `console.log` + `chalk` 颜色支持
|
|
85
|
+
- **颜色配置**: 支持自定义颜色映射和禁用颜色
|
|
86
|
+
- **TABLE 类型**: 自动调用 `console.table` 进行表格展示
|
|
87
|
+
- **错误处理**: 颜色格式化失败时自动降级到无颜色输出
|
|
88
|
+
|
|
89
|
+
#### 日志文件输出驱动
|
|
90
|
+
|
|
91
|
+
- **基础实现**: `pino` + `sonic-boom` 高性能日志写入
|
|
92
|
+
- **缓冲机制**: 可配置缓冲区大小,支持同步/异步写入
|
|
93
|
+
- **临终保护**: 使用 `signal-exit` 实现非侵入式进程退出监听
|
|
94
|
+
- **内置控制台**: 自动提供 `outputConsoleFn`,基于 pino 输出到控制台
|
|
143
95
|
|
|
144
96
|
## API 文档
|
|
145
97
|
|
|
146
|
-
### createOutputConsole
|
|
98
|
+
### createOutputConsole
|
|
147
99
|
|
|
148
100
|
创建控制台输出实例。
|
|
149
101
|
|
|
150
|
-
|
|
102
|
+
**签名:**
|
|
151
103
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
- `isSyncToLogFile?: (type: OutputConsoleTypeEnum) => boolean` - 同步到日志文件的条件函数
|
|
158
|
-
- `outputFileFn?: OutputLogFile` - 日志文件输出函数
|
|
104
|
+
```typescript
|
|
105
|
+
function createOutputConsole(
|
|
106
|
+
options?: CreateOutputConsoleOptions,
|
|
107
|
+
): OutputConsole;
|
|
108
|
+
```
|
|
159
109
|
|
|
160
|
-
|
|
110
|
+
**参数:**
|
|
161
111
|
|
|
162
|
-
|
|
112
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
113
|
+
| ----------------------- | ------------------------------------- | ------ | -------------------- |
|
|
114
|
+
| options.isSilent | (type) => boolean | - | 动态静默控制函数 |
|
|
115
|
+
| options.enableColor | boolean | true | 是否启用颜色输出 |
|
|
116
|
+
| options.colorMap | Record<OutputConsoleTypeEnum, string> | - | 自定义颜色映射 |
|
|
117
|
+
| options.isSwitchLogFile | (type) => boolean | - | 切换到日志文件的条件 |
|
|
118
|
+
| options.isSyncToLogFile | (type) => boolean | - | 同步到日志文件的条件 |
|
|
119
|
+
| options.outputFileFn | OutputConsoleRaw | - | 日志文件输出函数 |
|
|
163
120
|
|
|
164
|
-
|
|
165
|
-
- 属性调用:`output.info(...messages)`、`output.error(...messages)` 等
|
|
121
|
+
**返回值:** OutputConsole 混合类型实例
|
|
166
122
|
|
|
167
|
-
|
|
123
|
+
**示例:**
|
|
168
124
|
|
|
169
|
-
|
|
125
|
+
```typescript
|
|
126
|
+
const output = createOutputConsole({
|
|
127
|
+
enableColor: true,
|
|
128
|
+
isSilent: (type) =>
|
|
129
|
+
type === OutputConsoleTypeEnum.DEBUG && !process.env.DEBUG,
|
|
130
|
+
});
|
|
170
131
|
|
|
171
|
-
|
|
132
|
+
output.info("信息");
|
|
133
|
+
output.success("成功");
|
|
134
|
+
output.error("错误");
|
|
135
|
+
```
|
|
172
136
|
|
|
173
|
-
|
|
174
|
-
- `silent?: boolean` - 是否静默模式,默认 `false`
|
|
175
|
-
- `logFilePath?: string` - 日志文件路径,默认自动生成
|
|
176
|
-
- `prettyPrint?: boolean` - 是否启用美化输出,默认 `false`
|
|
177
|
-
- `sync?: boolean` - 是否同步写入,默认 `false`
|
|
178
|
-
- `bufferSize?: number` - 缓冲区大小,默认 `4096`
|
|
137
|
+
### createOutputLogFile
|
|
179
138
|
|
|
180
|
-
|
|
139
|
+
创建日志文件输出实例。
|
|
181
140
|
|
|
182
|
-
|
|
141
|
+
**签名:**
|
|
183
142
|
|
|
184
|
-
|
|
185
|
-
|
|
143
|
+
```typescript
|
|
144
|
+
function createOutputLogFile(
|
|
145
|
+
options: CreateOutputLogFileOptions,
|
|
146
|
+
): OutputLogFile;
|
|
147
|
+
```
|
|
186
148
|
|
|
187
|
-
|
|
149
|
+
**参数:**
|
|
188
150
|
|
|
189
|
-
|
|
151
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
152
|
+
| ----------------------- | ----------------- | ------ | -------------------- |
|
|
153
|
+
| options.logFilePath | string | - | 日志文件路径(必传) |
|
|
154
|
+
| options.isSilent | (type) => boolean | - | 动态静默控制函数 |
|
|
155
|
+
| options.sync | boolean | false | 是否同步写入 |
|
|
156
|
+
| options.bufferSize | number | 4096 | 缓冲区大小(字节) |
|
|
157
|
+
| options.isSwitchConsole | (type) => boolean | - | 切换到控制台的条件 |
|
|
190
158
|
|
|
191
|
-
|
|
159
|
+
**返回值:** OutputLogFile 混合类型实例
|
|
192
160
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
161
|
+
**示例:**
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const logger = createOutputLogFile({
|
|
165
|
+
logFilePath: "app.log",
|
|
166
|
+
sync: false,
|
|
167
|
+
bufferSize: 8192,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
logger.info("应用启动");
|
|
171
|
+
logger.error("数据库连接失败");
|
|
172
|
+
```
|
|
199
173
|
|
|
200
174
|
### 输出类型枚举
|
|
201
175
|
|
|
202
176
|
#### OutputConsoleTypeEnum
|
|
203
177
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
WARN = 37, // 警告
|
|
215
|
-
ERROR = 38, // 错误
|
|
216
|
-
}
|
|
217
|
-
```
|
|
178
|
+
| 值 | 名称 | 说明 |
|
|
179
|
+
| --- | ------- | -------- |
|
|
180
|
+
| 31 | DEBUG | 调试信息 |
|
|
181
|
+
| 32 | SKIP | 跳过 |
|
|
182
|
+
| 33 | INFO | 提示信息 |
|
|
183
|
+
| 34 | TABLE | 表格 |
|
|
184
|
+
| 35 | STAGE | 步骤 |
|
|
185
|
+
| 36 | SUCCESS | 成功 |
|
|
186
|
+
| 37 | WARN | 警告 |
|
|
187
|
+
| 38 | ERROR | 错误 |
|
|
218
188
|
|
|
219
189
|
#### OutputLogFileTypeEnum
|
|
220
190
|
|
|
221
|
-
|
|
191
|
+
| 值 | 名称 | 说明 |
|
|
192
|
+
| --- | ----- | ------------ |
|
|
193
|
+
| 10 | TRACE | 跟踪级别 |
|
|
194
|
+
| 20 | DEBUG | 调试级别 |
|
|
195
|
+
| 30 | INFO | 信息级别 |
|
|
196
|
+
| 40 | WARN | 警告级别 |
|
|
197
|
+
| 50 | ERROR | 错误级别 |
|
|
198
|
+
| 60 | FATAL | 致命错误级别 |
|
|
222
199
|
|
|
223
|
-
|
|
224
|
-
enum OutputLogFileTypeEnum {
|
|
225
|
-
TRACE = 10, // 跟踪级别
|
|
226
|
-
DEBUG = 20, // 调试级别
|
|
227
|
-
INFO = 30, // 信息级别
|
|
228
|
-
WARN = 40, // 警告级别
|
|
229
|
-
ERROR = 50, // 错误级别
|
|
230
|
-
FATAL = 60, // 致命错误级别
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
## 高级功能
|
|
200
|
+
## 进阶使用
|
|
235
201
|
|
|
236
|
-
###
|
|
237
|
-
|
|
238
|
-
Node.js 包使用 signal-exit 库实现非侵入式临终落盘保护机制,确保进程退出时日志数据不丢失:
|
|
202
|
+
### 动态静默控制
|
|
239
203
|
|
|
240
204
|
```typescript
|
|
241
|
-
import {
|
|
205
|
+
import {
|
|
206
|
+
createOutputConsole,
|
|
207
|
+
OutputConsoleTypeEnum,
|
|
208
|
+
} from "@done-coding/output-node";
|
|
242
209
|
|
|
243
|
-
|
|
244
|
-
|
|
210
|
+
const output = createOutputConsole({
|
|
211
|
+
// 动态控制静默:只在调试模式下显示 DEBUG 信息
|
|
212
|
+
isSilent: (type) => {
|
|
213
|
+
if (type === OutputConsoleTypeEnum.DEBUG) {
|
|
214
|
+
return !process.env.DEBUG;
|
|
215
|
+
}
|
|
216
|
+
// 生产环境下静默所有 SKIP 类型
|
|
217
|
+
if (type === OutputConsoleTypeEnum.SKIP) {
|
|
218
|
+
return process.env.NODE_ENV === "production";
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
},
|
|
222
|
+
});
|
|
245
223
|
|
|
246
|
-
|
|
247
|
-
//
|
|
248
|
-
//
|
|
224
|
+
output.debug("调试信息"); // 只在 DEBUG=true 时显示
|
|
225
|
+
output.skip("跳过信息"); // 生产环境下不显示
|
|
226
|
+
output.info("普通信息"); // 总是显示
|
|
249
227
|
```
|
|
250
228
|
|
|
251
|
-
###
|
|
252
|
-
|
|
253
|
-
包含完整的错误处理机制:
|
|
229
|
+
### 切换和同步逻辑
|
|
254
230
|
|
|
255
231
|
```typescript
|
|
256
232
|
import {
|
|
257
233
|
createOutputConsole,
|
|
258
|
-
|
|
234
|
+
createOutputLogFile,
|
|
235
|
+
OutputConsoleTypeEnum,
|
|
259
236
|
} from "@done-coding/output-node";
|
|
260
237
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
238
|
+
// 创建日志文件输出
|
|
239
|
+
const fileLogger = createOutputLogFile({ logFilePath: "error.log" });
|
|
240
|
+
|
|
241
|
+
// 创建带有切换和同步逻辑的控制台输出
|
|
242
|
+
const output = createOutputConsole({
|
|
243
|
+
enableColor: true,
|
|
244
|
+
// 错误级别切换到日志文件(不在控制台显示)
|
|
245
|
+
isSwitchLogFile: (type) => type === OutputConsoleTypeEnum.ERROR,
|
|
246
|
+
// 警告级别同步到日志文件(控制台和文件都显示)
|
|
247
|
+
isSyncToLogFile: (type) => type === OutputConsoleTypeEnum.WARN,
|
|
248
|
+
outputFileFn: (type, ...messages) => {
|
|
249
|
+
// 将控制台类型映射到日志文件类型并输出
|
|
250
|
+
fileLogger(type, ...messages);
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
output.info("普通信息"); // 只在控制台显示
|
|
255
|
+
output.warn("警告信息"); // 控制台和文件都显示
|
|
256
|
+
output.error("错误信息"); // 只在文件中记录
|
|
270
257
|
```
|
|
271
258
|
|
|
272
259
|
### 自定义颜色配置
|
|
@@ -277,7 +264,7 @@ import {
|
|
|
277
264
|
OutputConsoleTypeEnum,
|
|
278
265
|
} from "@done-coding/output-node";
|
|
279
266
|
|
|
280
|
-
const
|
|
267
|
+
const output = createOutputConsole({
|
|
281
268
|
enableColor: true,
|
|
282
269
|
colorMap: {
|
|
283
270
|
[OutputConsoleTypeEnum.INFO]: "blue",
|
|
@@ -291,161 +278,126 @@ const outputConsole = createOutputConsole({
|
|
|
291
278
|
### 缓冲区配置
|
|
292
279
|
|
|
293
280
|
```typescript
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// 自定义缓冲区大小
|
|
281
|
+
// 异步写入模式(推荐用于生产环境)
|
|
297
282
|
const logger = createOutputLogFile({
|
|
298
|
-
|
|
283
|
+
logFilePath: "app.log",
|
|
299
284
|
sync: false, // 异步写入
|
|
285
|
+
bufferSize: 8192, // 8KB 缓冲区
|
|
300
286
|
});
|
|
301
287
|
|
|
302
288
|
// 同步写入模式(性能较低但数据安全性更高)
|
|
303
289
|
const syncLogger = createOutputLogFile({
|
|
290
|
+
logFilePath: "critical.log",
|
|
304
291
|
sync: true, // 同步写入
|
|
305
292
|
bufferSize: 1024, // 较小的缓冲区
|
|
306
293
|
});
|
|
307
294
|
```
|
|
308
295
|
|
|
309
|
-
###
|
|
296
|
+
### TABLE 类型处理
|
|
310
297
|
|
|
311
298
|
```typescript
|
|
312
|
-
|
|
313
|
-
generateDefaultNodeLogFileName,
|
|
314
|
-
getConsoleTypeName,
|
|
315
|
-
getLogFileTypeName,
|
|
316
|
-
} from "@done-coding/output-node";
|
|
299
|
+
const output = createOutputConsole();
|
|
317
300
|
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
|
|
301
|
+
// 数组表格
|
|
302
|
+
output.table([
|
|
303
|
+
{ name: "张三", age: 25, city: "北京" },
|
|
304
|
+
{ name: "李四", age: 30, city: "上海" },
|
|
305
|
+
]);
|
|
321
306
|
|
|
322
|
-
//
|
|
323
|
-
|
|
324
|
-
|
|
307
|
+
// 对象表格
|
|
308
|
+
output.table({
|
|
309
|
+
total: 100,
|
|
310
|
+
success: 95,
|
|
311
|
+
failed: 5,
|
|
312
|
+
});
|
|
325
313
|
```
|
|
326
314
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
### 1. 使用属性调用方式
|
|
315
|
+
### 临终落盘保护
|
|
330
316
|
|
|
331
317
|
```typescript
|
|
332
|
-
|
|
333
|
-
outputConsole.info("用户登录成功");
|
|
334
|
-
outputConsole.error("数据库连接失败");
|
|
318
|
+
import { createOutputLogFile } from "@done-coding/output-node";
|
|
335
319
|
|
|
336
|
-
//
|
|
337
|
-
|
|
320
|
+
// 创建日志实例会自动注册 signal-exit 监听器
|
|
321
|
+
const logger = createOutputLogFile({ logFilePath: "app.log" });
|
|
322
|
+
|
|
323
|
+
logger.info("应用启动");
|
|
324
|
+
|
|
325
|
+
// 当收到 SIGINT 或 SIGTERM 信号时,会自动刷新日志缓冲区
|
|
326
|
+
// 与 NestJS 等现代框架的关闭钩子完美兼容
|
|
338
327
|
```
|
|
339
328
|
|
|
340
|
-
|
|
329
|
+
## 开发与测试
|
|
341
330
|
|
|
342
|
-
|
|
343
|
-
// 开发环境
|
|
344
|
-
const devLogger = createOutputLogFile({
|
|
345
|
-
prettyPrint: true, // 美化输出便于调试
|
|
346
|
-
logFilePath: "dev.log",
|
|
347
|
-
outputToConsole: true, // 同时输出到控制台
|
|
348
|
-
});
|
|
331
|
+
### 测试覆盖率
|
|
349
332
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
bufferSize: 8192, // 较大缓冲区
|
|
356
|
-
});
|
|
357
|
-
```
|
|
333
|
+
- **语句覆盖率**: 99.35%
|
|
334
|
+
- **分支覆盖率**: 97.63%
|
|
335
|
+
- **函数覆盖率**: 97.5%
|
|
336
|
+
- **行覆盖率**: 99.35%
|
|
337
|
+
- **测试数量**: 181 个测试,全部通过
|
|
358
338
|
|
|
359
|
-
###
|
|
339
|
+
### 本地开发
|
|
360
340
|
|
|
361
|
-
```
|
|
362
|
-
|
|
341
|
+
```bash
|
|
342
|
+
# 克隆仓库
|
|
343
|
+
git clone https://github.com/done-coding/output-node.git
|
|
344
|
+
cd output-node
|
|
363
345
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
logFilePath: "/protected/app.log",
|
|
367
|
-
bufferSize: 4096,
|
|
368
|
-
});
|
|
369
|
-
} catch (error) {
|
|
370
|
-
// 降级到控制台输出
|
|
371
|
-
console.warn("日志文件创建失败,降级到控制台输出");
|
|
372
|
-
const fallbackLogger = createOutputLogFile({
|
|
373
|
-
outputToConsole: true,
|
|
374
|
-
prettyPrint: true,
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
```
|
|
346
|
+
# 安装依赖
|
|
347
|
+
pnpm install
|
|
378
348
|
|
|
379
|
-
|
|
349
|
+
# 开发模式
|
|
350
|
+
pnpm dev
|
|
380
351
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const outputConsole = createOutputConsole({
|
|
384
|
-
silent: process.env.NODE_ENV === "test",
|
|
385
|
-
});
|
|
352
|
+
# 运行测试
|
|
353
|
+
pnpm test
|
|
386
354
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
logFilePath: "batch.log",
|
|
390
|
-
prettyPrint: false, // 禁用美化以提高性能
|
|
391
|
-
sync: false, // 异步写入
|
|
392
|
-
bufferSize: 16384, // 更大的缓冲区
|
|
393
|
-
});
|
|
355
|
+
# 构建
|
|
356
|
+
pnpm build
|
|
394
357
|
```
|
|
395
358
|
|
|
396
|
-
###
|
|
359
|
+
### 贡献流程
|
|
397
360
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
]);
|
|
361
|
+
1. Fork 本仓库
|
|
362
|
+
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
|
|
363
|
+
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
|
364
|
+
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
|
365
|
+
5. 开启 Pull Request
|
|
404
366
|
|
|
405
|
-
|
|
406
|
-
outputConsole.table({
|
|
407
|
-
total: 100,
|
|
408
|
-
success: 95,
|
|
409
|
-
failed: 5,
|
|
410
|
-
});
|
|
367
|
+
## 常见问题
|
|
411
368
|
|
|
412
|
-
|
|
413
|
-
outputConsole.table("这不是表格数据");
|
|
414
|
-
```
|
|
369
|
+
**Q: 为什么 Node 包不需要传入 `outputImpl` 参数?**
|
|
415
370
|
|
|
416
|
-
|
|
371
|
+
A: Node 包自动提供了基于 `console.log + chalk` 和 `pino` 的输出实现,用户无需手动创建和传入 `outputImpl`。这是 Node 包相比 Core 包的主要优势。
|
|
417
372
|
|
|
418
|
-
|
|
419
|
-
- `chalk` - 控制台颜色输出
|
|
420
|
-
- `pino` - 高性能日志库
|
|
421
|
-
- `pino-pretty` - 日志美化输出
|
|
422
|
-
- `signal-exit` - 非侵入式进程退出监听
|
|
373
|
+
**Q: 如何在生产环境中优化日志性能?**
|
|
423
374
|
|
|
424
|
-
|
|
375
|
+
A: 使用异步写入模式(`sync: false`),适当增加缓冲区大小(如 8KB 或 16KB),并合理配置 `isSilent` 函数来过滤不必要的日志输出。
|
|
425
376
|
|
|
426
|
-
|
|
427
|
-
- **分支覆盖率**: 98.13%
|
|
428
|
-
- **函数覆盖率**: 97.29%
|
|
429
|
-
- **行覆盖率**: 99.51%
|
|
430
|
-
- **测试数量**: 182 个测试,全部通过
|
|
377
|
+
**Q: 如何在 NestJS 中使用?**
|
|
431
378
|
|
|
432
|
-
|
|
379
|
+
A: 可以在 NestJS 的 OnModuleInit 和 OnApplicationShutdown 钩子中使用,临终落盘保护会自动处理进程退出时的日志刷新。
|
|
433
380
|
|
|
434
|
-
|
|
381
|
+
**Q: 日志文件路径可以是相对路径吗?**
|
|
382
|
+
|
|
383
|
+
A: 可以,相对路径会相对于当前工作目录。建议使用绝对路径以避免歧义。
|
|
384
|
+
|
|
385
|
+
**Q: 如何禁用颜色输出?**
|
|
386
|
+
|
|
387
|
+
A: 设置 `enableColor: false` 即可。
|
|
388
|
+
|
|
389
|
+
**Q: 缓冲区大小应该设置多少?**
|
|
435
390
|
|
|
436
|
-
|
|
391
|
+
A: 默认 4KB 适合大多数场景。高频输出可以增加到 8KB 或 16KB,低频输出可以减少到 1KB。
|
|
437
392
|
|
|
438
|
-
|
|
393
|
+
**Q: 支持哪些 Node.js 版本?**
|
|
439
394
|
|
|
440
|
-
|
|
395
|
+
A: 支持 Node.js 14+,推荐使用 Node.js 16+。
|
|
441
396
|
|
|
442
|
-
|
|
397
|
+
**Q: 如何处理日志文件权限错误?**
|
|
443
398
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
- TABLE 类型特殊处理
|
|
450
|
-
- 常量集中管理
|
|
451
|
-
- 缓冲区大小配置和验证
|
|
399
|
+
A: 包会自动捕获权限错误并静默处理,日志会降级到内存缓冲。建议检查文件路径和目录权限。
|
|
400
|
+
|
|
401
|
+
## 许可证
|
|
402
|
+
|
|
403
|
+
MIT
|