{"_id":"@ai-partner-x/aiko-boot-starter-log","_rev":"4-908d0efc79824a94a42cd568420a7767","name":"@ai-partner-x/aiko-boot-starter-log","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.3":{"name":"@ai-partner-x/aiko-boot-starter-log","version":"0.1.3","keywords":["aiko-boot","logger","winston","logging"],"author":{"name":"AI Partner X"},"license":"MIT","_id":"@ai-partner-x/aiko-boot-starter-log@0.1.3","maintainers":[{"name":"moyin333","email":"158182907@qq.com"}],"dist":{"shasum":"4fe8b4501b30ecec668ceb37b84a1d42100f7485","tarball":"https://registry.npmjs.org/@ai-partner-x/aiko-boot-starter-log/-/aiko-boot-starter-log-0.1.3.tgz","fileCount":8,"integrity":"sha512-88bjm0alWqYjQFCzOrDOz/AUnY0x64MjwiljZK51fWb+N0lKl7scMnvm2KdXwGA9swxVkeKXxRTGrLEa5/ja3Q==","signatures":[{"sig":"MEQCIFf9bldk99tJ1eIXIw0mfoiGflsE7ni9chLoBZs0gotsAiBmVQenxZmesIxhHHcqnLEQez/QFRBxv5A3u7O4rHL0Zw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":375313},"main":"./dist/index.js","type":"module","_from":"file:ai-partner-x-aiko-boot-starter-log-0.1.3.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","clean":"rm -rf dist","test:ui":"vitest --ui","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"moyin333","email":"158182907@qq.com"},"_resolved":"/tmp/eada00ff29820e6020900d5f2adb8b1c/ai-partner-x-aiko-boot-starter-log-0.1.3.tgz","_integrity":"sha512-88bjm0alWqYjQFCzOrDOz/AUnY0x64MjwiljZK51fWb+N0lKl7scMnvm2KdXwGA9swxVkeKXxRTGrLEa5/ja3Q==","_npmVersion":"10.8.2","description":"Aiko Boot Starter - Log Component with Winston Integration","directories":{},"_nodeVersion":"20.20.1","dependencies":{"winston":"^3.11.0","reflect-metadata":"^0.2.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","@vitest/ui":"^2.0.0","typescript":"^5.3.0","@types/node":"^20.11.0","@vitest/coverage-v8":"^2.0.0"},"peerDependencies":{"typescript":">=5.0.0","@ai-partner-x/aiko-boot":"0.1.3"},"peerDependenciesMeta":{"@ai-partner-x/aiko-boot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/aiko-boot-starter-log_0.1.3_1773857066519_0.35407957371160204","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@ai-partner-x/aiko-boot-starter-log","version":"0.1.4","keywords":["aiko-boot","logger","winston","logging"],"author":{"name":"AI Partner X"},"license":"MIT","_id":"@ai-partner-x/aiko-boot-starter-log@0.1.4","maintainers":[{"name":"moyin333","email":"158182907@qq.com"}],"dist":{"shasum":"17d2e188746f5908b9936aa763e3fb69f595fd75","tarball":"https://registry.npmjs.org/@ai-partner-x/aiko-boot-starter-log/-/aiko-boot-starter-log-0.1.4.tgz","fileCount":8,"integrity":"sha512-52d+pn1T3npkagiy4S6L/AwIOCOhm+D7gay0wmRTcn7+2ncwjgrUpSgdh1iVt/Zh3vFbMgbrklJ1bj6AHG5icw==","signatures":[{"sig":"MEUCIQC0Gml3M/d3pjtpy3rkdUgfXYEgs0T7xHAd8gIfmP/4DQIgMsOXa8k291hd45hhIc4JtWfJb6//gJUGGN6lrkZ3BKE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":375313},"main":"./dist/index.js","type":"module","_from":"file:ai-partner-x-aiko-boot-starter-log-0.1.4.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","clean":"rm -rf dist","test:ui":"vitest --ui","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"moyin333","email":"158182907@qq.com"},"_resolved":"/tmp/125a1d015e7f4810c93735fd422f817f/ai-partner-x-aiko-boot-starter-log-0.1.4.tgz","_integrity":"sha512-52d+pn1T3npkagiy4S6L/AwIOCOhm+D7gay0wmRTcn7+2ncwjgrUpSgdh1iVt/Zh3vFbMgbrklJ1bj6AHG5icw==","_npmVersion":"10.8.2","description":"Aiko Boot Starter - Log Component with Winston Integration","directories":{},"_nodeVersion":"20.20.1","dependencies":{"winston":"^3.11.0","reflect-metadata":"^0.2.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","@vitest/ui":"^2.0.0","typescript":"^5.3.0","@types/node":"^20.11.0","@vitest/coverage-v8":"^2.0.0"},"peerDependencies":{"typescript":">=5.0.0","@ai-partner-x/aiko-boot":"0.1.4"},"peerDependenciesMeta":{"@ai-partner-x/aiko-boot":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/aiko-boot-starter-log_0.1.4_1773908277348_0.16117994593538154","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@ai-partner-x/aiko-boot-starter-log","version":"0.1.5","description":"Aiko Boot Starter - Log Component with Winston Integration","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"keywords":["aiko-boot","logger","winston","logging"],"author":{"name":"AI Partner X"},"license":"MIT","dependencies":{"winston":"^3.11.0","reflect-metadata":"^0.2.2"},"devDependencies":{"@types/node":"^20.11.0","tsup":"^8.0.0","typescript":"^5.3.0","vitest":"^2.0.0","@vitest/ui":"^2.0.0","@vitest/coverage-v8":"^2.0.0"},"peerDependencies":{"typescript":">=5.0.0","@ai-partner-x/aiko-boot":"0.1.5"},"peerDependenciesMeta":{"@ai-partner-x/aiko-boot":{"optional":true}},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"scripts":{"build":"tsup","dev":"tsup --watch","type-check":"tsc --noEmit","clean":"rm -rf dist","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","test:ui":"vitest --ui"},"_id":"@ai-partner-x/aiko-boot-starter-log@0.1.5","_integrity":"sha512-8GEgw1zVuLZCuVrVDNYQ4FMX02PhU5OWykN/G/LI66nXz3kvd9BA8/QjwIhKP2+DscIT0BYzWy1HJeOopTGn/w==","_resolved":"/tmp/b795692b0e3449430a7cb5955c4ffdbd/ai-partner-x-aiko-boot-starter-log-0.1.5.tgz","_from":"file:ai-partner-x-aiko-boot-starter-log-0.1.5.tgz","_nodeVersion":"20.20.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-8GEgw1zVuLZCuVrVDNYQ4FMX02PhU5OWykN/G/LI66nXz3kvd9BA8/QjwIhKP2+DscIT0BYzWy1HJeOopTGn/w==","shasum":"e85ec03bf3c5b25cfafb426ff32fa835408f570c","tarball":"https://registry.npmjs.org/@ai-partner-x/aiko-boot-starter-log/-/aiko-boot-starter-log-0.1.5.tgz","fileCount":8,"unpackedSize":375313,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIANYOakEMJCCKCX08ZQwEqy5Spjfb/qnVfBlxXx5SOz0AiEAgT+5LMn22pbwps5ZAhkbLqwFWrbfvI3ogFVX+/CdnXQ="}]},"_npmUser":{"name":"moyin333","email":"158182907@qq.com"},"directories":{},"maintainers":[{"name":"moyin333","email":"158182907@qq.com"},{"name":"liujin0528","email":"un0528@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aiko-boot-starter-log_0.1.5_1774102916821_0.08485405327591389"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-18T18:04:26.424Z","modified":"2026-03-21T14:21:57.092Z","0.1.3":"2026-03-18T18:04:26.753Z","0.1.4":"2026-03-19T08:17:57.537Z","0.1.5":"2026-03-21T14:21:56.959Z"},"author":{"name":"AI Partner X"},"license":"MIT","keywords":["aiko-boot","logger","winston","logging"],"description":"Aiko Boot Starter - Log Component with Winston Integration","maintainers":[{"name":"moyin333","email":"158182907@qq.com"},{"name":"liujin0528","email":"un0528@hotmail.com"}],"readme":"# @ai-partner-x/aiko-boot-starter-log\n\n基于 Winston 的简化日志组件，提供简洁易用的 API。\n\n## 目录结构\n\n```\npackages/aiko-boot-starter-log/\n├── src/\n│   ├── config.ts                   # 配置加载器\n│   ├── core/\n│   │   ├── facade.ts               # 外观层 API（快捷函数）\n│   │   └── logger.ts               # 核心日志类实现\n│   ├── decorators/\n│   │   ├── log.decorator.ts        # @Log 方法装饰器\n│   │   └── slf4j.decorator.ts      # @Slf4j 类装饰器\n│   ├── formatter.ts                # 格式化器\n│   ├── index.ts                    # 入口文件\n│   ├── loggerFactory.ts            # 日志工厂\n│   ├── metadata/\n│   │   └── metadata.ts             # 元数据管理\n│   ├── types.ts                    # 类型定义\n│   └── utils/\n│       └── decorator-utils.ts      # 装饰器工具函数\n├── __tests__/\n│   ├── auto-configuration.test.ts  # 自动配置测试\n│   ├── decorators.test.ts          # 装饰器集成测试\n│   ├── facade.test.ts              # 外观层 API 测试\n│   ├── formatter.test.ts           # 格式化器测试\n│   ├── integration.test.ts         # 集成测试\n│   ├── log-decorator.test.ts       # @Log 装饰器单元测试\n│   ├── logger.test.ts              # 核心 Logger 测试\n│   ├── loggerFactory.test.ts       # Logger 工厂测试\n│   ├── slf4j-decorator.test.ts     # @Slf4j 装饰器单元测试\n│   ├── types.test.ts               # 类型定义测试\n│   └── setup.ts                    # 测试环境设置\n├── examples/\n│   ├── basic-usage.ts              # 基础使用示例\n│   └── decorator-usage.ts          # 装饰器使用示例\n├── package.json\n├── tsconfig.json\n├── tsup.config.ts\n└── README.md\n```\n\n## 安装\n\n```bash\npnpm add @ai-partner-x/aiko-boot-starter-log\n# 或\nnpm install @ai-partner-x/aiko-boot-starter-log\n```\n\n### 装饰器支持依赖\n\n要使用装饰器功能，需要安装 `reflect-metadata`：\n\n```bash\npnpm add reflect-metadata\n# 或\nnpm install reflect-metadata\n```\n\n并在应用入口处导入：\n\n```typescript\nimport 'reflect-metadata';\n```\n\n## 快速开始\n\n```typescript\nimport { getLogger, defaultLogger } from '@ai-partner-x/aiko-boot-starter-log';\n\n// 使用默认 logger\ndefaultLogger.info('应用启动');\ndefaultLogger.debug('调试信息', { userId: 123 });\ndefaultLogger.error('发生错误', new Error('错误详情'));\n\n// 获取命名 logger\nconst logger = getLogger('my-app');\nlogger.info('Hello World');\n```\n\n## API 文档\n\n### 日志级别\n\n支持以下日志级别（从高到低）：\n\n| 级别 | 说明 |\n|------|------|\n| `error` | 错误信息 |\n| `warn` | 警告信息 |\n| `info` | 一般信息 |\n| `http` | HTTP 请求日志 |\n| `verbose` | 详细信息 |\n| `debug` | 调试信息 |\n| `silly` | 最详细的信息 |\n\n### 快捷函数\n\n#### 创建 Logger\n\n```typescript\nimport {\n  createConsoleLogger,\n  createFileLogger,\n  createCombinedLogger,\n  getLogger,\n} from '@ai-partner-x/aiko-boot-starter-log';\n\n// 创建控制台 logger\nconst consoleLogger = createConsoleLogger('app', 'debug');\n\n// 创建文件 logger\nconst fileLogger = createFileLogger('app', './logs/app.log', {\n  level: 'info',\n  maxSize: '10m',\n  maxFiles: 5,\n});\n\n// 创建组合 logger（控制台 + 文件）\nconst combinedLogger = createCombinedLogger('app', './logs/app.log', {\n  level: 'debug',\n});\n\n// 从工厂获取 logger\nconst logger = getLogger('my-module');\n```\n\n#### 初始化配置\n\n```typescript\nimport {\n  initLogging,\n  initFromEnv,\n  initFromFile,\n  autoInit,\n} from '@ai-partner-x/aiko-boot-starter-log';\n\n// 手动配置\ninitLogging({\n  level: 'debug',\n  format: 'pretty',\n  colorize: true,\n  transports: [\n    { type: 'console', level: 'debug', format: 'cli', colorize: true },\n    { type: 'file', filename: './logs/app.log', level: 'info' },\n  ],\n});\n\n// 从环境变量初始化\ninitFromEnv();\n\n// 从配置文件初始化\ninitFromFile('./log.config.json');\n\n// 自动加载（env > file > package.json > defaults）\nautoInit({ configFile: './log.config.json' });\n```\n\n### Formatter 格式化器\n\n```typescript\nimport { Formatter } from '@ai-partner-x/aiko-boot-starter-log';\n\n// 预定义格式\nFormatter.json();         // JSON 格式\nFormatter.simple();       // 简单文本格式\nFormatter.pretty();       // 美化格式\nFormatter.cli(true);      // 命令行格式（带颜色）\n\n// 环境预设\nFormatter.production();   // 生产环境格式\nFormatter.development();  // 开发环境格式\n\n// 自定义格式\nFormatter.custom({\n  timestamp: 'YYYY-MM-DD HH:mm:ss',\n  colorize: true,\n  custom: (info) => `[${info.level}] ${info.message}`,\n});\n```\n\n### ConfigLoader 配置加载器\n\n```typescript\nimport { ConfigLoader, loadConfig } from '@ai-partner-x/aiko-boot-starter-log';\n\n// 获取默认配置\nconst defaultConfig = ConfigLoader.getDefault();\n\n// 从环境变量加载\nconst envConfig = ConfigLoader.fromEnv();\n\n// 从文件加载\nconst fileConfig = ConfigLoader.fromFile('./log.config.json');\n\n// 自动加载（优先级: env > file > package.json > defaults）\nconst config = ConfigLoader.load({\n  configFile: './log.config.json',\n  env: true,\n});\n\n// 快捷函数\nconst config = loadConfig();\n```\n\n### 环境变量配置\n\n| 变量名 | 说明 | 示例 |\n|--------|------|------|\n| `LOG_LEVEL` | 日志级别 | `debug`, `info`, `warn` |\n| `LOG_FORMAT` | 输出格式 | `json`, `cli`, `pretty` |\n| `LOG_COLORIZE` | 启用颜色 | `true`, `false` |\n| `LOG_TIMESTAMP` | 显示时间戳 | `true`, `false` |\n| `LOG_FILE` | 日志文件路径 | `./logs/app.log` |\n| `LOG_CONSOLE` | 控制台输出 | `true`, `false` |\n\n### 传输配置\n\n#### 控制台传输\n\n```typescript\ninterface ConsoleTransportConfig {\n  type: 'console';\n  enabled?: boolean;\n  level?: LogLevel;\n  format?: 'json' | 'simple' | 'pretty' | 'cli';\n  colorize?: boolean;\n  timestamp?: boolean;\n}\n```\n\n#### 文件传输\n\n```typescript\ninterface FileTransportConfig {\n  type: 'file';\n  filename: string;\n  enabled?: boolean;\n  level?: LogLevel;\n  format?: 'json' | 'simple' | 'pretty' | 'cli';\n  maxSize?: string;  // e.g., '10m', '100k', '1g'\n  maxFiles?: number;\n  createDir?: boolean;\n}\n```\n\n#### 流传输\n\n```typescript\ninterface StreamTransportConfig {\n  type: 'stream';\n  stream: NodeJS.WritableStream;\n  enabled?: boolean;\n  level?: LogLevel;\n  format?: 'json' | 'simple' | 'pretty' | 'cli';\n}\n```\n\n### 子 Logger 和上下文\n\n```typescript\nconst logger = getLogger('app');\n\n// 创建子 logger\nconst childLogger = logger.child('module');\nchildLogger.info('来自子 logger 的消息');\n// 输出: [app:module] ...\n\n// 添加上下文\nconst contextLogger = logger.withContext({ requestId: 'req-123', userId: 456 });\ncontextLogger.info('带上下文的消息');\n// 输出包含: { requestId: 'req-123', userId: 456, ... }\n```\n\n### 错误日志\n\n```typescript\nconst logger = getLogger('app');\n\ntry {\n  throw new Error('Something went wrong');\n} catch (error) {\n  // 自动记录错误堆栈\n  logger.error('操作失败', error);\n\n  // 带额外上下文\n  logger.error('操作失败', error, { operation: 'database' });\n}\n```\n\n## 配置文件示例\n\n### log.config.json\n\n```json\n{\n  \"level\": \"info\",\n  \"format\": \"json\",\n  \"colorize\": false,\n  \"timestamp\": true,\n  \"defaultMeta\": {\n    \"service\": \"my-service\",\n    \"version\": \"1.0.0\"\n  },\n  \"transports\": [\n    {\n      \"type\": \"console\",\n      \"level\": \"debug\",\n      \"format\": \"cli\",\n      \"colorize\": true\n    },\n    {\n      \"type\": \"file\",\n      \"filename\": \"./logs/app.log\",\n      \"level\": \"info\",\n      \"maxSize\": \"10m\",\n      \"maxFiles\": 7\n    },\n    {\n      \"type\": \"file\",\n      \"filename\": \"./logs/error.log\",\n      \"level\": \"error\",\n      \"maxSize\": \"10m\",\n      \"maxFiles\": 30\n    }\n  ]\n}\n```\n\n### package.json 配置\n\n```json\n{\n  \"name\": \"my-app\",\n  \"log\": {\n    \"level\": \"info\",\n    \"format\": \"cli\",\n    \"colorize\": true\n  }\n}\n```\n\n## 装饰器支持 (v0.3.0+)\n\n从 v0.3.0 版本开始，组件提供了类似 Lombok 的装饰器支持，可以更简洁地使用日志功能。\n\n### 启用装饰器支持\n\n在应用入口处导入 `reflect-metadata`：\n\n```typescript\nimport 'reflect-metadata';\n```\n\n### @Slf4j 类装饰器\n\n自动为类注入日志记录器：\n\n```typescript\nimport { Slf4j } from '@ai-partner-x/aiko-boot-starter-log';\n\n@Slf4j()\nclass UserService {\n  getUser(id: string) {\n    this.logger.info(`Getting user ${id}`);\n    return { id, name: 'John Doe' };\n  }\n}\n\n// 使用自定义配置\n@Slf4j({ \n  name: 'OrderService',\n  level: 'debug',\n  factoryOptions: { level: 'debug' }\n})\nclass OrderService {\n  processOrder(orderId: string) {\n    this.logger.debug(`Processing order ${orderId}`);\n    return { orderId, status: 'processed' };\n  }\n}\n```\n\n### @Log 方法装饰器\n\n自动记录方法调用，支持同步和异步方法：\n\n```typescript\nimport { Log, LogInfo, LogDebug, LogError } from '@ai-partner-x/aiko-boot-starter-log';\n\n@Slf4j()\nclass ProductService {\n  \n  @Log()\n  async getProduct(id: string) {\n    // 自动记录方法调用\n    return { id, name: 'Product ' + id };\n  }\n  \n  @LogInfo('Searching products')\n  searchProducts(query: string) {\n    return [{ id: '1', name: query }];\n  }\n  \n  @LogDebug()\n  debugMethod() {\n    this.logger.debug('Debug information');\n    return 'debug';\n  }\n  \n  @LogError('Product creation failed')\n  createProduct(data: any) {\n    if (!data.name) {\n      throw new Error('Product name is required');\n    }\n    return { id: 'new', ...data };\n  }\n  \n  @Log({\n    level: 'info',\n    message: 'Processing order',\n    logArgs: true,\n    logResult: true,\n    logDuration: true\n  })\n  processOrder(orderId: string, items: any[]) {\n    return { orderId, status: 'processed' };\n  }\n}\n```\n\n### 装饰器选项\n\n#### @Slf4j 选项\n```typescript\ninterface Slf4jOptions {\n  name?: string;                    // 日志记录器名称（默认使用类名）\n  level?: string;                   // 日志级别\n  enabled?: boolean;                // 是否启用装饰器\n  factoryOptions?: Partial<LoggerFactoryOptions>; // 自定义日志工厂选项\n}\n```\n\n#### @Log 选项\n```typescript\ninterface LogOptions {\n  level?: 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';\n  message?: string;                 // 自定义日志消息模板\n  logArgs?: boolean;                // 是否记录方法参数（默认：true）\n  logResult?: boolean;              // 是否记录返回值（默认：true）\n  logDuration?: boolean;            // 是否记录执行时间（默认：true）\n  logError?: boolean;               // 是否记录错误（默认：true）\n  argsSerializer?: (args: any[]) => any;    // 参数序列化函数\n  resultSerializer?: (result: any) => any;  // 结果序列化函数\n  errorSerializer?: (error: Error) => any;  // 错误序列化函数\n  loggerName?: string;              // 自定义日志记录器名称（覆盖类级别的记录器）\n}\n```\n\n### 便捷装饰器\n\n- `@LogInfo(message?)` - 记录 info 级别日志\n- `@LogDebug(message?)` - 记录 debug 级别日志  \n- `@LogError(message?)` - 记录 error 级别日志\n\n### 元数据管理工具\n\n```typescript\nimport { LoggerMetadata, enableDecoratorSupport } from '@ai-partner-x/aiko-boot-starter-log';\n\n// 启用装饰器支持\nenableDecoratorSupport();\n\n// 检查类是否已应用 @Slf4j 装饰器\nconst isDecorated = LoggerMetadata.hasLogger(MyClass);\n\n// 获取类的日志记录器\nconst logger = LoggerMetadata.getLogger(MyClass);\n\n// 手动注入日志记录器\nLoggerMetadata.setLogger(MyClass, loggerInstance);\n```\n\n### 向后兼容性\n\n装饰器功能完全向后兼容，可以与传统的 API 混合使用：\n\n```typescript\nimport { getLogger } from '@ai-partner-x/aiko-boot-starter-log';\nimport { Slf4j } from '@ai-partner-x/aiko-boot-starter-log';\n\n// 传统方式\nclass TraditionalService {\n  private logger = getLogger('TraditionalService');\n  \n  doSomething() {\n    this.logger.info('传统方式');\n  }\n}\n\n// 装饰器方式\n@Slf4j({ name: 'ModernService' })\nclass ModernService {\n  doSomething() {\n    this.logger.info('装饰器方式');\n  }\n}\n\n// 两者可以共存\n```\n\n### 测试装饰器代码\n\n项目提供了完整的装饰器单元测试，可以作为编写测试的参考：\n\n```typescript\n// 测试 @Log 装饰器\nimport { describe, it, expect, vi } from 'vitest';\nimport { Log, Slf4j } from '@ai-partner-x/aiko-boot-starter-log';\nimport { LoggerMetadata } from '@ai-partner-x/aiko-boot-starter-log';\nimport { enableDecoratorSupport } from '@ai-partner-x/aiko-boot-starter-log';\n\nenableDecoratorSupport();\n\ndescribe('@Log 装饰器测试', () => {\n  beforeEach(() => {\n    // 模拟 logger\n    const mockLogger = {\n      info: vi.fn(),\n      error: vi.fn(),\n      debug: vi.fn(),\n    };\n    vi.spyOn(LoggerMetadata, 'getLogger').mockReturnValue(mockLogger as any);\n  });\n\n  it('应该记录方法调用', () => {\n    @Slf4j({ name: 'TestClass' })\n    class TestClass {\n      @Log()\n      testMethod(param: string) {\n        return `Hello ${param}`;\n      }\n    }\n\n    const instance = new TestClass();\n    const result = instance.testMethod('World');\n    \n    expect(result).toBe('Hello World');\n    // 验证日志被调用\n  });\n});\n```\n\n### 装饰器测试覆盖率\n\n项目的装饰器测试覆盖了以下关键场景：\n\n| 测试场景 | 覆盖文件 | 测试用例数 |\n|---------|---------|-----------|\n| @Log 装饰器基础功能 | `log-decorator.test.ts` | 20 |\n| @Slf4j 装饰器基础功能 | `slf4j-decorator.test.ts` | 15 |\n| 装饰器集成测试 | `decorators.test.ts` | 15+ |\n| 装饰器工具函数 | `decorators.test.ts` | 5+ |\n\n所有装饰器相关代码的测试覆盖率超过 85%，确保代码质量和稳定性。\n\n## 完整示例\n\n### 生产环境配置\n\n```typescript\nimport { Logger, Formatter } from '@ai-partner-x/aiko-boot-starter-log';\n\nconst logger = new Logger({\n  name: 'production-app',\n  level: 'info',\n  defaultMeta: {\n    service: 'api-server',\n    version: '1.0.0',\n    env: 'production',\n  },\n  transports: [\n    { type: 'console', level: 'info', format: 'json' },\n    { type: 'file', filename: './logs/app.log', level: 'info', maxSize: '50m', maxFiles: 30 },\n    { type: 'file', filename: './logs/error.log', level: 'error', maxSize: '50m', maxFiles: 30 },\n  ],\n});\n\nlogger.info('服务启动', { port: 3000 });\n```\n\n### 开发环境配置\n\n```typescript\nimport { autoInit, getLogger } from '@ai-partner-x/aiko-boot-starter-log';\n\n// 自动从环境变量加载配置\nautoInit();\n\nconst logger = getLogger('dev-app');\nlogger.debug('开发调试信息', { feature: 'new-feature' });\n```\n\n## 依赖管理\n\n### 运行时依赖\n- `winston@^3.11.0` - 日志功能核心库\n\n### 开发依赖\n- `typescript@^5.3.0` - TypeScript 编译器\n- `tsup@^8.0.0` - 构建工具\n- `vitest@^2.0.0` - 测试框架\n- `@types/node@^20.11.0` - Node.js 类型定义\n\n### 对等依赖（可选）\n- `@ai-partner-x/aiko-boot@workspace:*` - 与 Aiko Boot 框架集成\n\n## 最佳实践\n\n### 1. 日志级别选择\n- **生产环境**: `info` 或 `warn`\n- **开发环境**: `debug` 或 `verbose`\n- **测试环境**: `silly`（最详细）\n\n### 2. 输出格式\n- **控制台输出**: 使用 `cli` 或 `pretty` 格式，启用颜色\n- **文件输出**: 使用 `json` 格式，便于日志分析\n- **生产环境**: 使用 `json` 格式，包含完整时间戳\n\n### 3. 文件轮转\n```typescript\n// 合理的文件轮转配置\n{\n  type: 'file',\n  filename: './logs/app.log',\n  maxSize: '10m',    // 每个文件最大 10MB\n  maxFiles: 7,       // 保留最近 7 天的日志\n  level: 'info'\n}\n```\n\n### 4. 错误处理\n```typescript\n// 正确方式：传递 Error 对象\ntry {\n  // 业务逻辑\n} catch (error) {\n  logger.error('操作失败', error, { operation: 'database' });\n}\n\n// 避免：只传递字符串\nlogger.error('操作失败: ' + error.message); // ❌ 不推荐\n```\n\n### 5. 性能考虑\n- 避免在热路径中创建复杂的日志消息\n- 使用 `isDebugEnabled()` 等方法检查级别后再构建消息\n- 生产环境中关闭不必要的详细日志\n\n### 6. 安全考虑\n- 不要在日志中记录敏感信息（密码、令牌、个人信息等）\n- 使用环境变量控制日志级别\n- 定期审查和清理日志文件\n\n## 测试\n\n### 运行测试\n\n运行所有测试：\n```bash\nnpm test\n```\n\n运行特定测试文件：\n```bash\nnpm test -- log-decorator.test.ts\n```\n\n运行特定测试套件：\n```bash\nnpm test -- --run \"装饰器功能测试\"\n```\n\n生成测试覆盖率报告：\n```bash\nnpm run test:coverage\n```\n\n### 测试结构\n\n项目包含全面的单元测试，覆盖所有核心功能：\n\n```\n__tests__/\n├── auto-configuration.test.ts    # 自动配置测试\n├── decorators.test.ts            # 装饰器集成测试\n├── facade.test.ts               # 外观层 API 测试\n├── formatter.test.ts            # 格式化器测试\n├── integration.test.ts          # 集成测试\n├── log-decorator.test.ts        # @Log 装饰器单元测试（新增）\n├── logger.test.ts               # 核心 Logger 测试\n├── loggerFactory.test.ts        # Logger 工厂测试\n├── slf4j-decorator.test.ts      # @Slf4j 装饰器单元测试（新增）\n├── types.test.ts               # 类型定义测试\n└── setup.ts                    # 测试环境设置\n```\n\n### 装饰器单元测试\n\n#### @Log 装饰器测试 (`log-decorator.test.ts`)\n\n包含 20 个测试用例，覆盖以下功能：\n\n1. **基础功能测试**\n   - 同步方法装饰\n   - 异步方法装饰\n   - 方法参数记录\n   - 返回值记录\n   - 执行时间记录\n\n2. **错误处理测试**\n   - 同步方法错误记录\n   - 异步方法错误记录\n   - 错误日志禁用\n\n3. **自定义选项测试**\n   - 自定义日志级别\n   - 自定义消息模板\n   - 自定义序列化器\n   - 自定义 logger 名称\n\n4. **便捷装饰器测试**\n   - `@LogSimple` 装饰器\n   - `@LogInfo` 装饰器\n   - `@LogDebug` 装饰器\n   - `@LogError` 装饰器\n\n5. **边界情况测试**\n   - 没有 logger 的情况\n   - undefined 和 null 参数\n   - 函数参数处理\n   - 循环引用对象处理\n\n#### @Slf4j 装饰器测试 (`slf4j-decorator.test.ts`)\n\n包含 23 个测试用例，覆盖以下功能：\n\n1. **基础功能测试**\n   - 装饰器正确应用\n   - logger 属性注入\n   - 默认 logger 名称\n   - 自定义 logger 名称\n\n2. **选项配置测试**\n   - 装饰器禁用\n   - 自定义日志级别\n   - factoryOptions 配置\n\n3. **便捷装饰器测试**\n   - `@Slf4jSimple` 装饰器\n\n4. **工具函数测试**\n   - `isSlf4jDecorated` 函数\n\n5. **边界情况测试**\n   - 匿名类处理\n   - 没有名称的匿名类\n   - 匿名类作为函数返回值\n   - 匿名类继承场景\n   - 匿名类与箭头函数结合\n   - 匿名类多次装饰\n   - 匿名类禁用装饰器\n   - 继承场景\n   - 多次应用装饰器\n\n6. **集成测试**\n   - 与 `@Log` 装饰器协同工作\n   - 多个类使用不同 logger\n\n### 测试示例\n\n```typescript\n// log-decorator.test.ts 示例\ndescribe('@Log 装饰器单元测试', () => {\n  it('应该正确应用 @Log 装饰器到同步方法', () => {\n    @Slf4j({ name: 'TestClass' })\n    class TestClass {\n      @Log()\n      syncMethod(param: string) {\n        return `Hello ${param}`;\n      }\n    }\n\n    const instance = new TestClass();\n    const result = instance.syncMethod('World');\n    expect(result).toBe('Hello World');\n  });\n});\n\n// slf4j-decorator.test.ts 示例\ndescribe('@Slf4j 装饰器单元测试', () => {\n  it('应该正确应用 @Slf4j 装饰器', () => {\n    @Slf4j({ name: 'TestService' })\n    class TestService {\n      testMethod() {\n        return 'test';\n      }\n    }\n\n    expect(LoggerMetadata.hasLogger(TestService)).toBe(true);\n    expect(LoggerMetadata.getName(TestService)).toBe('TestService');\n  });\n});\n```\n\n### 匿名类边界情况测试\n\n`@Slf4j` 装饰器支持多种匿名类使用场景，测试覆盖了以下边界情况：\n\n#### 1. 基本匿名类测试\n```typescript\nit('应该处理匿名类', () => {\n  const AnonymousClass = class {\n    test() {\n      return 'test';\n    }\n  };\n  \n  // 应用装饰器\n  const DecoratedClass = Slf4j({ name: 'AnonymousLogger' })(AnonymousClass);\n  \n  expect(LoggerMetadata.hasLogger(DecoratedClass)).toBe(true);\n  expect(LoggerMetadata.getName(DecoratedClass)).toBe('AnonymousLogger');\n});\n```\n\n#### 2. 没有名称的匿名类\n```typescript\nit('应该处理没有名称的匿名类', () => {\n  // 完全匿名的类表达式\n  const AnonymousClass = class {};\n  \n  // 应用装饰器，不提供名称\n  const DecoratedClass = Slf4j()(AnonymousClass);\n  \n  expect(LoggerMetadata.hasLogger(DecoratedClass)).toBe(true);\n  // 匿名类的 name 属性通常是空字符串或 'class'\n  expect(LoggerMetadata.getName(DecoratedClass)).toBe('');\n});\n```\n\n#### 3. 匿名类作为函数返回值\n```typescript\nit('应该处理匿名类作为函数返回值', () => {\n  function createClass() {\n    return class {\n      method() {\n        return 'method';\n      }\n    };\n  }\n  \n  const AnonymousClass = createClass();\n  const DecoratedClass = Slf4j({ name: 'FunctionReturnClass' })(AnonymousClass);\n  \n  expect(LoggerMetadata.hasLogger(DecoratedClass)).toBe(true);\n  expect(LoggerMetadata.getName(DecoratedClass)).toBe('FunctionReturnClass');\n});\n```\n\n#### 4. 匿名类继承场景\n```typescript\nit('应该处理匿名类继承场景', () => {\n  // 匿名父类\n  const ParentClass = class {\n    parentMethod() {\n      return 'parent';\n    }\n  };\n  \n  // 应用装饰器到父类\n  const DecoratedParent = Slf4j({ name: 'ParentLogger' })(ParentClass);\n  \n  // 匿名子类继承匿名父类\n  const ChildClass = class extends DecoratedParent {\n    childMethod() {\n      return 'child';\n    }\n  };\n  \n  // 应用装饰器到子类\n  const DecoratedChild = Slf4j({ name: 'ChildLogger' })(ChildClass);\n  \n  const parent = new DecoratedParent();\n  const child = new DecoratedChild();\n  \n  expect(parent.logger?.name).toBe('ParentLogger');\n  expect(child.logger?.name).toBe('ChildLogger');\n});\n```\n\n#### 5. 匿名类与箭头函数结合\n```typescript\nit('应该处理匿名类与箭头函数结合', () => {\n  // 使用箭头函数创建匿名类\n  const createAnonymousClass = (name: string) => {\n    const cls = class {\n      constructor(public value: string) {}\n      \n      getValue() {\n        return this.value;\n      }\n    };\n    \n    // 动态应用装饰器\n    return Slf4j({ name })(cls);\n  };\n  \n  const DecoratedClassA = createAnonymousClass('ClassA');\n  const DecoratedClassB = createAnonymousClass('ClassB');\n  \n  const instanceA = new DecoratedClassA('valueA');\n  const instanceB = new DecoratedClassB('valueB');\n  \n  expect(instanceA.logger?.name).toBe('ClassA');\n  expect(instanceB.logger?.name).toBe('ClassB');\n});\n```\n\n#### 6. 匿名类多次装饰\n```typescript\nit('应该处理匿名类多次装饰的情况', () => {\n  const AnonymousClass = class {\n    test() {\n      return 'test';\n    }\n  };\n  \n  // 多次应用装饰器\n  const DecoratedOnce = Slf4j({ name: 'FirstLogger' })(AnonymousClass);\n  const DecoratedTwice = Slf4j({ name: 'SecondLogger' })(DecoratedOnce);\n  \n  expect(LoggerMetadata.getName(DecoratedTwice)).toBe('SecondLogger');\n});\n```\n\n#### 7. 匿名类禁用装饰器\n```typescript\nit('应该处理匿名类禁用装饰器的情况', () => {\n  const AnonymousClass = class {\n    test() {\n      return 'test';\n    }\n  };\n  \n  // 应用禁用状态的装饰器\n  const DecoratedClass = Slf4j({ enabled: false, name: 'DisabledLogger' })(AnonymousClass);\n  \n  expect(LoggerMetadata.hasLogger(DecoratedClass)).toBe(false);\n});\n```\n\n### 测试配置\n\n测试使用以下配置：\n\n- **测试框架**: Vitest v2.1.9\n- **模拟库**: Vitest 内置模拟功能\n- **断言库**: Vitest 内置 expect\n- **覆盖率工具**: @vitest/coverage-v8\n\n### 测试最佳实践\n\n1. **隔离测试环境**\n   - 每个测试用例使用独立的模拟\n   - 测试前后清理状态\n   - 避免测试间相互影响\n\n2. **模拟外部依赖**\n   - 使用 `vi.spyOn()` 模拟函数调用\n   - 使用 `vi.fn()` 创建模拟函数\n   - 模拟 `LoggerMetadata` 和 `getLogger`\n\n3. **装饰器支持**\n   - 测试文件开头调用 `enableDecoratorSupport()`\n   - 使用 `reflect-metadata` 支持装饰器语法\n   - 在 `beforeEach` 中定义装饰类\n\n4. **异步测试**\n   - 使用 `async/await` 处理异步方法\n   - 使用 `expect().rejects.toThrow()` 测试异步错误\n   - 合理设置超时时间\n\n5. **边界条件测试**\n   - 测试 null/undefined 参数\n   - 测试错误处理\n   - 测试性能边界情况\n   - 测试匿名类处理\n   - 测试继承和组合场景\n   - 测试装饰器多次应用\n# 日志级别判断逻辑验证\n\n## LOG_LEVELS 映射\n```typescript\nLOG_LEVELS = {\n  error: 0,   // 最高优先级\n  warn: 1,    // 次高优先级\n  info: 2,    // 中等优先级\n  http: 3,    // 较低优先级\n  verbose: 4, // 低优先级\n  debug: 5,   // 更低优先级\n  silly: 6    // 最低优先级\n}\n```\n\n## 判断逻辑\n`isLevelEnabled(level)` 使用以下逻辑：\n```typescript\nreturn LOG_LEVELS[level] <= LOG_LEVELS[this._level];\n```\n\n## 示例验证\n\n### 当前级别：info (2)\n- `isLevelEnabled('error')` = `0 <= 2` = `true` ✓\n- `isLevelEnabled('warn')` = `1 <= 2` = `true` ✓\n- `isLevelEnabled('info')` = `2 <= 2` = `true` ✓\n- `isLevelEnabled('http')` = `3 <= 2` = `false` ✓\n- `isLevelEnabled('debug')` = `5 <= 2` = `false` ✓\n\n## 常见问题\n\n### Q1: 为什么 winston 同时出现在 dependencies 和 devDependencies 中？\n**A**: 这是一个错误的配置。`winston` 是运行时必需的依赖，应该只出现在 `dependencies` 中。开发工具（如测试框架）应该在 `devDependencies` 中。已修复此问题。\n\n### Q2: 如何与 Aiko Boot 框架集成？\n**A**: 本库通过可选的 peerDependency `@ai-partner-x/aiko-boot` 与框架集成。如果安装了该框架，可以使用 `fromAikoBoot()` 方法自动加载配置。\n\n### Q3: 如何处理循环依赖？\n**A**: 使用工厂模式（LoggerFactory）管理 logger 实例，避免直接导入。通过 facade 函数（`getLogger()`, `defaultLogger`）访问 logger。\n\n### Q4: 为什么测试中直接调用 formatter.transform() 会失败？\n**A**: `transform()` 是 winston 的内部 API，不应该直接调用。测试应该验证格式化器的创建和使用，而不是直接调用内部方法。\n\n### Q5: 如何自定义日志格式？\n**A**: 使用 `Formatter.custom()` 方法，或创建自定义的 winston 格式器。参考 `formatter.ts` 中的实现。\n\n### Q6: 生产环境中应该使用什么日志级别？\n**A**: 建议使用 `info` 级别，记录重要业务事件和错误。避免在生产环境中使用 `debug` 或 `silly` 级别，以免影响性能。\n\n### Q7: 如何记录 Error 对象？\n**A**: 使用 `logger.error(message, error, metadata)` 格式。Error 的 `name`、`message` 和 `stack` 会自动包含在日志中。\n\n### Q8: 如何为装饰器编写单元测试？\n**A**: 参考项目中的 `log-decorator.test.ts` 和 `slf4j-decorator.test.ts` 文件。关键步骤包括：\n1. 导入 `enableDecoratorSupport()` 并调用\n2. 使用 `vi.spyOn()` 模拟 `LoggerMetadata.getLogger()`\n3. 在 `beforeEach` 中定义装饰类\n4. 测试装饰器的各种配置选项\n\n### Q9: 装饰器测试中如何模拟 logger？\n**A**: 创建 mock logger 对象，包含所有日志级别方法：\n```typescript\nconst mockLogger = {\n  name: 'TestLogger',\n  error: vi.fn(),\n  warn: vi.fn(),\n  info: vi.fn(),\n  debug: vi.fn(),\n  // ... 其他级别\n  isInfoEnabled: () => true,\n};\n```\n\n### Q10: 测试异步方法装饰器时需要注意什么？\n**A**: 使用 `async/await` 处理异步调用，并测试错误处理：\n```typescript\nit('应该记录异步方法抛出的错误', async () => {\n  @Slf4j({ name: 'TestClass' })\n  class TestClass {\n    @Log({ logError: true })\n    async asyncErrorMethod() {\n      throw new Error('Async error');\n    }\n  }\n\n  const instance = new TestClass();\n  await expect(instance.asyncErrorMethod()).rejects.toThrow('Async error');\n  expect(mockLogger.error).toHaveBeenCalled();\n});\n```\n\n## 贡献指南\n\n### 1. 代码规范\n- 使用 TypeScript 编写类型安全的代码\n- 遵循项目中的 ESLint 规则\n- 添加适当的类型定义和注释\n- 装饰器代码必须包含完整的类型定义\n\n### 2. 测试要求\n- 新功能必须包含单元测试\n- 修复 bug 时必须添加回归测试\n- 测试覆盖率不低于 80%\n- 装饰器测试必须覆盖所有配置选项\n\n#### 装饰器测试规范\n- 使用 Vitest 作为测试框架\n- 模拟 `LoggerMetadata` 和 `getLogger`\n- 测试同步和异步方法\n- 测试错误处理场景\n- 测试边界条件（null/undefined 参数等）\n- 测试匿名类处理\n- 测试继承和组合场景\n- 测试装饰器多次应用\n\n#### 测试文件命名\n- 装饰器测试文件：`[feature-name]-decorator.test.ts`\n- 集成测试文件：`[feature-name].test.ts`\n- 工具函数测试：`[util-name].test.ts`\n\n### 3. 依赖管理\n- 运行时依赖放在 `dependencies` 中\n- 开发工具放在 `devDependencies` 中\n- 可选集成放在 `peerDependencies` 中\n- 装饰器功能依赖 `reflect-metadata`\n\n### 4. 提交规范\n- 使用语义化提交消息\n- 提交前运行所有测试\n- 更新相关文档\n- 装饰器变更必须更新示例和测试\n\n### 5. 装饰器开发指南\n#### 添加新装饰器\n1. 在 `src/decorators/` 目录创建新文件\n2. 定义装饰器接口和实现\n3. 添加类型定义到 `src/types.ts`\n4. 创建单元测试文件\n5. 更新 `src/index.ts` 导出\n6. 添加使用示例\n\n#### 装饰器测试模板\n```typescript\nimport { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { NewDecorator } from '../src/decorators/new.decorator';\nimport { enableDecoratorSupport } from '../src/utils/decorator-utils';\n\nenableDecoratorSupport();\n\ndescribe('@NewDecorator 测试', () => {\n  beforeEach(() => {\n    vi.clearAllMocks();\n  });\n\n  afterEach(() => {\n    vi.restoreAllMocks();\n  });\n\n  it('应该正确应用装饰器', () => {\n    // 测试实现\n  });\n\n  it('应该支持配置选项', () => {\n    // 测试各种配置\n  });\n\n  it('应该处理边界情况', () => {\n    // 测试错误处理等\n  });\n});\n```\n\n### 6. 文档要求\n- 新功能必须更新 README.md\n- 装饰器必须提供完整的使用示例\n- API 文档必须包含类型定义\n- 测试文档说明如何运行和编写测试\n\n## 许可证\n\nMIT\n","readmeFilename":"README.md"}