@done-coding/output-node
v0.1.2
Published
node相关输出
Readme
@done-coding/output-node
Node.js 环境下的同构输出工具包,基于 @done-coding/output-core 核心包构建,提供控制台输出和日志文件输出功能。
功能特性
- 🎨 丰富的控制台输出 - 支持多种输出类型和颜色配置
- 📝 专业的日志文件输出 - 基于 pino 的高性能日志记录
- 🔄 混合类型接口 - 支持函数调用和属性链式调用两种方式
- 🛡️ 临终落盘保护 - 使用 signal-exit 库实现非侵入式进程退出监听
- 🚨 框架兼容 - 与 NestJS 等现代框架的关闭钩子完美兼容
- ⚡ 高性能 - 异步日志写入,可配置缓冲区大小
- 🔧 完整的错误处理 - 输入验证、配置验证、文件权限检查
- 📦 完整类型支持 - 100% TypeScript 类型定义和类型推导
- 🔇 动态静默控制 - 支持运行时动态控制输出静默,基于类型的条件静默
- 🎯 智能切换同步 - 支持控制台和日志文件之间的智能切换和同步
- 📋 TABLE 类型特殊处理 - 智能表格数据展示和 JSON 序列化
快速开始
安装
npm install @done-coding/output-node
# 或
yarn add @done-coding/output-node
# 或
pnpm add @done-coding/output-node最小可用示例
import {
createOutputConsole,
createOutputLogFile,
} from "@done-coding/output-node";
// 创建控制台输出
const output = createOutputConsole();
output.info("Hello World");
output.success("操作成功");
// 创建日志文件输出
const logger = createOutputLogFile({ logFilePath: "app.log" });
logger.info("应用启动");
logger.error("发生错误");架构设计
分层架构
┌─────────────────────────────────────┐
│ Node.js 适配包层 │
│ (@done-coding/output-node) │
├─────────────────────────────────────┤
│ 核心包层 │
│ (@done-coding/output-core) │
├─────────────────────────────────────┤
│ 驱动实现层 │
│ (console.log, pino, chalk, etc.) │
└─────────────────────────────────────┘设计原则
- 自动化驱动 - 自动创建和管理输出驱动实现
- 零配置 - 提供合理的默认配置,开箱即用
- 高性能 - 异步日志写入,可配置缓冲区
- 安全可靠 - 完整的错误处理和防御性编程
- 框架兼容 - 与现代框架(NestJS、Express 等)完美兼容
- 极简 API - 最少化的配置参数,易于使用
内置实现
控制台输出驱动
- 基础实现:
console.log+chalk颜色支持 - 颜色配置: 支持自定义颜色映射和禁用颜色
- TABLE 类型: 自动调用
console.table进行表格展示 - 错误处理: 颜色格式化失败时自动降级到无颜色输出
日志文件输出驱动
- 基础实现:
pino+sonic-boom高性能日志写入 - 缓冲机制: 可配置缓冲区大小,支持同步/异步写入
- 临终保护: 使用
signal-exit实现非侵入式进程退出监听 - 内置控制台: 自动提供
outputConsoleFn,基于 pino 输出到控制台
API 文档
createOutputConsole
创建控制台输出实例。
签名:
function createOutputConsole(
options?: CreateOutputConsoleOptions,
): OutputConsole;参数:
| 参数 | 类型 | 默认值 | 说明 | | ----------------------- | ------------------------------------- | ------ | -------------------- | | options.isSilent | (type) => boolean | - | 动态静默控制函数 | | options.enableColor | boolean | true | 是否启用颜色输出 | | options.colorMap | Record<OutputConsoleTypeEnum, string> | - | 自定义颜色映射 | | options.isSwitchLogFile | (type) => boolean | - | 切换到日志文件的条件 | | options.isSyncToLogFile | (type) => boolean | - | 同步到日志文件的条件 | | options.outputFileFn | OutputConsoleRaw | - | 日志文件输出函数 |
返回值: OutputConsole 混合类型实例
示例:
const output = createOutputConsole({
enableColor: true,
isSilent: (type) =>
type === OutputConsoleTypeEnum.DEBUG && !process.env.DEBUG,
});
output.info("信息");
output.success("成功");
output.error("错误");createOutputLogFile
创建日志文件输出实例。
签名:
function createOutputLogFile(
options: CreateOutputLogFileOptions,
): OutputLogFile;参数:
| 参数 | 类型 | 默认值 | 说明 | | ----------------------- | ----------------- | ------ | -------------------- | | options.logFilePath | string | - | 日志文件路径(必传) | | options.isSilent | (type) => boolean | - | 动态静默控制函数 | | options.sync | boolean | false | 是否同步写入 | | options.bufferSize | number | 4096 | 缓冲区大小(字节) | | options.isSwitchConsole | (type) => boolean | - | 切换到控制台的条件 |
返回值: OutputLogFile 混合类型实例
示例:
const logger = createOutputLogFile({
logFilePath: "app.log",
sync: false,
bufferSize: 8192,
});
logger.info("应用启动");
logger.error("数据库连接失败");输出类型枚举
OutputConsoleTypeEnum
| 值 | 名称 | 说明 | | --- | ------- | -------- | | 31 | DEBUG | 调试信息 | | 32 | SKIP | 跳过 | | 33 | INFO | 提示信息 | | 34 | TABLE | 表格 | | 35 | STAGE | 步骤 | | 36 | SUCCESS | 成功 | | 37 | WARN | 警告 | | 38 | ERROR | 错误 |
OutputLogFileTypeEnum
| 值 | 名称 | 说明 | | --- | ----- | ------------ | | 10 | TRACE | 跟踪级别 | | 20 | DEBUG | 调试级别 | | 30 | INFO | 信息级别 | | 40 | WARN | 警告级别 | | 50 | ERROR | 错误级别 | | 60 | FATAL | 致命错误级别 |
进阶使用
动态静默控制
import {
createOutputConsole,
OutputConsoleTypeEnum,
} from "@done-coding/output-node";
const output = createOutputConsole({
// 动态控制静默:只在调试模式下显示 DEBUG 信息
isSilent: (type) => {
if (type === OutputConsoleTypeEnum.DEBUG) {
return !process.env.DEBUG;
}
// 生产环境下静默所有 SKIP 类型
if (type === OutputConsoleTypeEnum.SKIP) {
return process.env.NODE_ENV === "production";
}
return false;
},
});
output.debug("调试信息"); // 只在 DEBUG=true 时显示
output.skip("跳过信息"); // 生产环境下不显示
output.info("普通信息"); // 总是显示切换和同步逻辑
import {
createOutputConsole,
createOutputLogFile,
OutputConsoleTypeEnum,
} from "@done-coding/output-node";
// 创建日志文件输出
const fileLogger = createOutputLogFile({ logFilePath: "error.log" });
// 创建带有切换和同步逻辑的控制台输出
const output = createOutputConsole({
enableColor: true,
// 错误级别切换到日志文件(不在控制台显示)
isSwitchLogFile: (type) => type === OutputConsoleTypeEnum.ERROR,
// 警告级别同步到日志文件(控制台和文件都显示)
isSyncToLogFile: (type) => type === OutputConsoleTypeEnum.WARN,
outputFileFn: (type, ...messages) => {
// 将控制台类型映射到日志文件类型并输出
fileLogger(type, ...messages);
},
});
output.info("普通信息"); // 只在控制台显示
output.warn("警告信息"); // 控制台和文件都显示
output.error("错误信息"); // 只在文件中记录自定义颜色配置
import {
createOutputConsole,
OutputConsoleTypeEnum,
} from "@done-coding/output-node";
const output = createOutputConsole({
enableColor: true,
colorMap: {
[OutputConsoleTypeEnum.INFO]: "blue",
[OutputConsoleTypeEnum.SUCCESS]: "greenBright",
[OutputConsoleTypeEnum.ERROR]: "redBright",
[OutputConsoleTypeEnum.WARN]: "yellow",
},
});缓冲区配置
// 异步写入模式(推荐用于生产环境)
const logger = createOutputLogFile({
logFilePath: "app.log",
sync: false, // 异步写入
bufferSize: 8192, // 8KB 缓冲区
});
// 同步写入模式(性能较低但数据安全性更高)
const syncLogger = createOutputLogFile({
logFilePath: "critical.log",
sync: true, // 同步写入
bufferSize: 1024, // 较小的缓冲区
});TABLE 类型处理
const output = createOutputConsole();
// 数组表格
output.table([
{ name: "张三", age: 25, city: "北京" },
{ name: "李四", age: 30, city: "上海" },
]);
// 对象表格
output.table({
total: 100,
success: 95,
failed: 5,
});临终落盘保护
import { createOutputLogFile } from "@done-coding/output-node";
// 创建日志实例会自动注册 signal-exit 监听器
const logger = createOutputLogFile({ logFilePath: "app.log" });
logger.info("应用启动");
// 当收到 SIGINT 或 SIGTERM 信号时,会自动刷新日志缓冲区
// 与 NestJS 等现代框架的关闭钩子完美兼容开发与测试
测试覆盖率
- 语句覆盖率: 99.35%
- 分支覆盖率: 97.63%
- 函数覆盖率: 97.5%
- 行覆盖率: 99.35%
- 测试数量: 181 个测试,全部通过
本地开发
# 克隆仓库
git clone https://github.com/done-coding/output-node.git
cd output-node
# 安装依赖
pnpm install
# 开发模式
pnpm dev
# 运行测试
pnpm test
# 构建
pnpm build贡献流程
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 开启 Pull Request
常见问题
Q: 为什么 Node 包不需要传入 outputImpl 参数?
A: Node 包自动提供了基于 console.log + chalk 和 pino 的输出实现,用户无需手动创建和传入 outputImpl。这是 Node 包相比 Core 包的主要优势。
Q: 如何在生产环境中优化日志性能?
A: 使用异步写入模式(sync: false),适当增加缓冲区大小(如 8KB 或 16KB),并合理配置 isSilent 函数来过滤不必要的日志输出。
Q: 如何在 NestJS 中使用?
A: 可以在 NestJS 的 OnModuleInit 和 OnApplicationShutdown 钩子中使用,临终落盘保护会自动处理进程退出时的日志刷新。
Q: 日志文件路径可以是相对路径吗?
A: 可以,相对路径会相对于当前工作目录。建议使用绝对路径以避免歧义。
Q: 如何禁用颜色输出?
A: 设置 enableColor: false 即可。
Q: 缓冲区大小应该设置多少?
A: 默认 4KB 适合大多数场景。高频输出可以增加到 8KB 或 16KB,低频输出可以减少到 1KB。
Q: 支持哪些 Node.js 版本?
A: 支持 Node.js 14+,推荐使用 Node.js 16+。
Q: 如何处理日志文件权限错误?
A: 包会自动捕获权限错误并静默处理,日志会降级到内存缓冲。建议检查文件路径和目录权限。
许可证
MIT
